diff --git a/BUILD.gn b/BUILD.gn index 588e9a15..163bd31 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1677,7 +1677,6 @@ "components/neterror/resources:closure_compile", "components/security_interstitials:closure_compile", "components/sync/driver/resources:closure_compile", - "components/ukm/debug:closure_compile", "mojo/public/tools/bindings/generators/js_templates/lite/test:closure_compile", "ui/webui/resources:closure_compile", ]
diff --git a/DEPS b/DEPS index 9689792c..bc8c7634 100644 --- a/DEPS +++ b/DEPS
@@ -359,7 +359,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': 'e639d04ea5b82c15f8eb25f1bc64b0db735bdb8a', + 'devtools_frontend_revision': 'c41a367319be563fa942a1cfa315de32b877388d', # 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. @@ -780,7 +780,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'c6d4682d323ed098f4a5265a1f264531f4a251f6', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '3a4ccf8e3c9a4422efe6b9af0c641e09b4afae2c', 'condition': 'checkout_ios', }, @@ -1145,7 +1145,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7ff520f0262b298e98ea29efefa5146b9fe5734d', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c5c48533cfdfe58302eb233f8d57e05aa559cd2a', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1542,7 +1542,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '6007fadd7cb1b558e89799b409d20529abb8c37f', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '9fcbb7415a3717c30e656811bc6509eee4d13040', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1815,7 +1815,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'J98AlfpF1UP6dn-WUiCIyYmt4jPVhKO20Ezm7AEeURQC', + 'version': 'eowIAxAh6WwOyfMECimDHmVKUYeuqIRwmt8gDLotcTUC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1837,7 +1837,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'OqbadMsBFiUCD5WGb0d6iYYxq_dQh7b2r6RztHuYCkgC', + 'version': 'Z4JT8aUmwfwFtY_0xMTBtD677pZSXpy2AOy-rqQApIMC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index b76b956..36e66f0 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -6014,3 +6014,56 @@ "Please use '#!/usr/bin/env python/2/3' as the shebang of %s" % file)) return result + + +def CheckBatchAnnotation(input_api, output_api): + """Checks that tests have either @Batch or @DoNotBatch annotation. If this + is not an instrumentation test, disregard.""" + + batch_annotation = input_api.re.compile(r'^\s*@Batch') + do_not_batch_annotation = input_api.re.compile(r'^\s*@DoNotBatch') + robolectric_test = input_api.re.compile(r'[rR]obolectric') + test_class_declaration = input_api.re.compile(r'^\s*public\sclass.*Test') + uiautomator_test = input_api.re.compile(r'[uU]i[aA]utomator') + + errors = [] + + def _FilterFile(affected_file): + return input_api.FilterSourceFile( + affected_file, + files_to_skip=input_api.DEFAULT_FILES_TO_SKIP, + files_to_check=[r'.*Test\.java$']) + + for f in input_api.AffectedSourceFiles(_FilterFile): + batch_matched = None + do_not_batch_matched = None + is_instrumentation_test = True + for line in f.NewContents(): + if robolectric_test.search(line) or uiautomator_test.search(line): + # Skip Robolectric and UiAutomator tests. + is_instrumentation_test = False + break + if not batch_matched: + batch_matched = batch_annotation.search(line) + if not do_not_batch_matched: + do_not_batch_matched = do_not_batch_annotation.search(line) + test_class_declaration_matched = test_class_declaration.search( + line) + if test_class_declaration_matched: + break + if (is_instrumentation_test and + not batch_matched and + not do_not_batch_matched): + errors.append(str(f.LocalPath())) + + results = [] + + if errors: + results.append( + output_api.PresubmitPromptWarning( + """ +Instrumentation tests should use either @Batch or @DoNotBatch. If tests are not +safe to run in batch, please use @DoNotBatch with reasons. +""", errors)) + + return results
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py index 9eb7349..12a7f3b 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py
@@ -4546,5 +4546,68 @@ for error in errors: self.assertRegex(error.message, r'DCHECK_IS_ON().+parentheses') +class CheckBatchAnnotation(unittest.TestCase): + """Test the CheckBatchAnnotation presubmit check.""" + + def testTruePositives(self): + """Examples of when there is no @Batch or @DoNotBatch is correctly flagged. +""" + mock_input = MockInputApi() + mock_input.files = [ + MockFile('path/OneTest.java', ['public class OneTest']), + MockFile('path/TwoTest.java', ['public class TwoTest']), + ] + errors = PRESUBMIT.CheckBatchAnnotation(mock_input, MockOutputApi()) + self.assertEqual(1, len(errors)) + self.assertEqual(2, len(errors[0].items)) + self.assertIn('OneTest.java', errors[0].items[0]) + self.assertIn('TwoTest.java', errors[0].items[1]) + + def testAnnotationsPresent(self): + """Examples of when there is @Batch or @DoNotBatch is correctly flagged.""" + mock_input = MockInputApi() + mock_input.files = [ + MockFile('path/OneTest.java', + ['@Batch(Batch.PER_CLASS)', 'public class One {']), + MockFile('path/TwoTest.java', + ['@DoNotBatch(reason = "dummy reasons.")', 'public class Two {' + ]), + MockFile('path/ThreeTest.java', + ['@Batch(Batch.PER_CLASS)', + 'public class Three extends BaseTestA {'], + ['@Batch(Batch.PER_CLASS)', + 'public class Three extends BaseTestB {']), + MockFile('path/FourTest.java', + ['@DoNotBatch(reason = "dummy reason 1")', + 'public class Four extends BaseTestA {'], + ['@DoNotBatch(reason = "dummy reason 2")', + 'public class Four extends BaseTestB {']), + MockFile('path/FiveTest.java', + ['import androidx.test.uiautomator.UiDevice;', + 'public class Five extends BaseTestA {'], + ['import androidx.test.uiautomator.UiDevice;', + 'public class Five extends BaseTestB {']), + MockFile('path/SixTest.java', + ['import org.chromium.base.test.BaseRobolectricTestRunner;', + 'public class Six extends BaseTestA {'], + ['import org.chromium.base.test.BaseRobolectricTestRunner;', + 'public class Six extends BaseTestB {']), + MockFile('path/SevenTest.java', + ['import org.robolectric.annotation.Config;', + 'public class Seven extends BaseTestA {'], + ['import org.robolectric.annotation.Config;', + 'public class Seven extends BaseTestB {']), + MockFile( + 'path/OtherClass.java', + ['public class OtherClass {'], + ), + MockFile('path/PRESUBMIT.py', + ['@Batch(Batch.PER_CLASS)', + '@DoNotBatch(reason = "dummy reason)']), + ] + errors = PRESUBMIT.CheckBatchAnnotation(mock_input, MockOutputApi()) + self.assertEqual(0, len(errors)) + + if __name__ == '__main__': unittest.main()
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index 9c2a946..078450c4 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -337,6 +337,8 @@ Flag.baseFeature(BlinkFeatures.EARLY_EXIT_ON_NOOP_CLASS_OR_STYLE_CHANGE, "Early exit when the style or class attribute of a DOM element is set to the" + " same value as before."), + Flag.baseFeature(BlinkFeatures.THREADED_PRELOAD_SCANNER, + "If enabled, the HTMLPreloadScanner will run on a worker thread."), // Add new commandline switches and features above. The final entry should have a // trailing comma for cleaner diffs. };
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentTest.java index bdc63b66..ea871b17 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentTest.java
@@ -15,12 +15,15 @@ import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withCount; +import android.content.Context; import android.content.Intent; +import android.support.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; 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; @@ -28,6 +31,7 @@ import org.chromium.android_webview.devui.ComponentsListFragment; import org.chromium.android_webview.devui.MainActivity; import org.chromium.android_webview.devui.R; +import org.chromium.android_webview.nonembedded_util.WebViewPackageHelper; import org.chromium.android_webview.services.ComponentsProviderPathUtil; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.base.ContextUtils; @@ -53,6 +57,13 @@ private static File sComponentsDownloadDir = new File(ComponentsProviderPathUtil.getComponentUpdateServiceDirectoryPath()); + @Before + public void setUp() { + Context context = InstrumentationRegistry.getTargetContext(); + WebViewPackageHelper.setCurrentWebViewPackageForTesting( + WebViewPackageHelper.getContextPackageInfo(context)); + } + @After public void tearDown() { if (sComponentsDownloadDir.exists()) {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentUpdateButtonTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentUpdateButtonTest.java index 48253fa..d3c5341 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentUpdateButtonTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/ComponentsListFragmentUpdateButtonTest.java
@@ -14,12 +14,15 @@ import static org.hamcrest.Matchers.anything; +import android.content.Context; import android.content.Intent; +import android.support.test.InstrumentationRegistry; 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; @@ -27,6 +30,7 @@ import org.chromium.android_webview.devui.ComponentsListFragment; import org.chromium.android_webview.devui.MainActivity; import org.chromium.android_webview.devui.R; +import org.chromium.android_webview.nonembedded_util.WebViewPackageHelper; import org.chromium.android_webview.services.ComponentsProviderPathUtil; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.android_webview.test.services.MockAwComponentUpdateService; @@ -51,6 +55,13 @@ private static File sComponentsDownloadDir = new File(ComponentsProviderPathUtil.getComponentUpdateServiceDirectoryPath()); + @Before + public void setUp() { + Context context = InstrumentationRegistry.getTargetContext(); + WebViewPackageHelper.setCurrentWebViewPackageForTesting( + WebViewPackageHelper.getContextPackageInfo(context)); + } + @After public void tearDown() { if (sComponentsDownloadDir.exists()) {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java index 8d79892..21ae1d6 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java
@@ -56,6 +56,7 @@ import org.hamcrest.TypeSafeMatcher; import org.junit.After; import org.junit.Assume; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -70,8 +71,8 @@ import org.chromium.android_webview.devui.MainActivity; import org.chromium.android_webview.devui.R; import org.chromium.android_webview.devui.WebViewPackageError; -import org.chromium.android_webview.nonembedded_util.WebViewPackageHelper; import org.chromium.android_webview.devui.util.CrashBugUrlFactory; +import org.chromium.android_webview.nonembedded_util.WebViewPackageHelper; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.base.Callback; import org.chromium.base.ContextUtils; @@ -106,6 +107,13 @@ @Rule public BaseActivityTestRule mRule = new BaseActivityTestRule<MainActivity>(MainActivity.class); + @Before + public void setUp() { + Context context = InstrumentationRegistry.getTargetContext(); + WebViewPackageHelper.setCurrentWebViewPackageForTesting( + WebViewPackageHelper.getContextPackageInfo(context)); + } + @After public void tearDown() { FileUtils.recursivelyDeleteFile(SystemWideCrashDirectories.getWebViewCrashDir(), null);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java index ae28995..0238c15a 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/DeveloperUiTest.java
@@ -48,12 +48,14 @@ import org.hamcrest.Matcher; import org.junit.After; import org.junit.Assume; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.android_webview.devui.MainActivity; import org.chromium.android_webview.devui.R; +import org.chromium.android_webview.nonembedded_util.WebViewPackageHelper; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.Feature; @@ -85,6 +87,13 @@ .respondWith(new ActivityResult(Activity.RESULT_OK, null)); } + @Before + public void setUp() { + Context context = InstrumentationRegistry.getTargetContext(); + WebViewPackageHelper.setCurrentWebViewPackageForTesting( + WebViewPackageHelper.getContextPackageInfo(context)); + } + @After public void tearDown() throws Exception { // Activity is launched, i.e the test is not skipped.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java index 338db25..8e6234f 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/FlagsFragmentTest.java
@@ -29,6 +29,7 @@ import static org.chromium.android_webview.test.devui.DeveloperUiTestUtils.withCount; +import android.content.Context; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.Drawable; @@ -63,6 +64,7 @@ import org.chromium.android_webview.devui.FlagsFragment; import org.chromium.android_webview.devui.MainActivity; import org.chromium.android_webview.devui.R; +import org.chromium.android_webview.nonembedded_util.WebViewPackageHelper; import org.chromium.android_webview.services.DeveloperUiService; import org.chromium.android_webview.test.AwJUnit4ClassRunner; import org.chromium.base.ContextUtils; @@ -109,6 +111,9 @@ FlagsFragment.setFlagListForTesting(sMockFlagList); DeveloperUiService.setFlagListForTesting(sMockFlagList); }); + Context context = InstrumentationRegistry.getTargetContext(); + WebViewPackageHelper.setCurrentWebViewPackageForTesting( + WebViewPackageHelper.getContextPackageInfo(context)); intent.putExtra(MainActivity.FRAGMENT_ID_INTENT_EXTRA, MainActivity.FRAGMENT_ID_FLAGS); mRule.launchActivity(intent); // Always close the soft keyboard when the activity is launched which is sometimes shown
diff --git a/ash/components/arc/session/arc_container_client_adapter.cc b/ash/components/arc/session/arc_container_client_adapter.cc index 1a038b74..bfaacce 100644 --- a/ash/components/arc/session/arc_container_client_adapter.cc +++ b/ash/components/arc/session/arc_container_client_adapter.cc
@@ -167,6 +167,7 @@ request.set_packages_cache_mode( ToLoginManagerPackageCacheMode(params.packages_cache_mode)); request.set_skip_gms_core_cache(params.skip_gms_core_cache); + request.set_skip_tts_cache(params.skip_tts_cache); request.set_is_demo_session(params.is_demo_session); request.set_demo_session_apps_path(params.demo_session_apps_path.value()); request.set_locale(params.locale);
diff --git a/ash/components/arc/session/arc_container_client_adapter_unittest.cc b/ash/components/arc/session/arc_container_client_adapter_unittest.cc index d7c4a5c..7f6ff379 100644 --- a/ash/components/arc/session/arc_container_client_adapter_unittest.cc +++ b/ash/components/arc/session/arc_container_client_adapter_unittest.cc
@@ -196,6 +196,26 @@ EXPECT_TRUE(request.enable_tts_caching()); } +TEST_F(ArcContainerClientAdapterTest, ConvertUpgradeParams_SkipTtsCacheSetup) { + UpgradeParams upgrade_params; + upgrade_params.skip_tts_cache = true; + client_adapter()->UpgradeArc(std::move(upgrade_params), + base::BindOnce(&OnMiniInstanceStarted)); + const auto& upgrade_request = + chromeos::FakeSessionManagerClient::Get()->last_upgrade_arc_request(); + EXPECT_TRUE(upgrade_request.skip_tts_cache()); +} + +TEST_F(ArcContainerClientAdapterTest, + ConvertUpgradeParams_EnableTtsCacheSetup) { + UpgradeParams upgrade_params; + client_adapter()->UpgradeArc(std::move(upgrade_params), + base::BindOnce(&OnMiniInstanceStarted)); + const auto& upgrade_request = + chromeos::FakeSessionManagerClient::Get()->last_upgrade_arc_request(); + EXPECT_FALSE(upgrade_request.skip_tts_cache()); +} + struct DalvikMemoryProfileTestParam { // Requested profile. StartParams::DalvikMemoryProfile profile;
diff --git a/ash/components/arc/session/arc_upgrade_params.cc b/ash/components/arc/session/arc_upgrade_params.cc index db9b3be..980dba98 100644 --- a/ash/components/arc/session/arc_upgrade_params.cc +++ b/ash/components/arc/session/arc_upgrade_params.cc
@@ -36,6 +36,8 @@ packages_cache_mode(GetPackagesCacheMode()), skip_gms_core_cache(base::CommandLine::ForCurrentProcess()->HasSwitch( ash::switches::kArcDisableGmsCoreCache)), + skip_tts_cache(base::CommandLine::ForCurrentProcess()->HasSwitch( + ash::switches::kArcDisableTtsCache)), enable_arc_nearby_share( base::FeatureList::IsEnabled(arc::kEnableArcNearbyShare)) {}
diff --git a/ash/components/arc/session/arc_upgrade_params.h b/ash/components/arc/session/arc_upgrade_params.h index 4dc07d9..191b4c6 100644 --- a/ash/components/arc/session/arc_upgrade_params.h +++ b/ash/components/arc/session/arc_upgrade_params.h
@@ -67,6 +67,10 @@ // The constructor automatically populates this from command-line. bool skip_gms_core_cache; + // Option to disable TTS cache. + // The constructor automatically populates this from command-line. + bool skip_tts_cache; + // The supervision transition state for this account. Indicates whether // child account should become regular, regular account should become child // or neither.
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc index 00c3413..f09f575c 100644 --- a/ash/components/arc/session/arc_vm_client_adapter.cc +++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -160,6 +160,8 @@ static_cast<int>(upgrade_params.management_transition)), base::StringPrintf("%s.serialno=%s", prefix.c_str(), serial_number.c_str()), + base::StringPrintf("%s.skip_tts_cache=%d", prefix.c_str(), + upgrade_params.skip_tts_cache), }; // Conditionally sets more properties based on |upgrade_params|. if (!upgrade_params.locale.empty()) {
diff --git a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc index a8d6a6e2..29d3b82 100644 --- a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc +++ b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -2544,5 +2544,22 @@ base::Contains(request.params(), "androidboot.arc.tts.caching=1")); } +TEST_F(ArcVmClientAdapterTest, ConvertUpgradeParams_SkipTtsCacheSetup) { + StartMiniArc(); + UpgradeParams upgrade_params = GetPopulatedUpgradeParams(); + upgrade_params.skip_tts_cache = true; + UpgradeArcWithParams(true, std::move(upgrade_params)); + EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(), + "ro.boot.skip_tts_cache=1")); +} + +TEST_F(ArcVmClientAdapterTest, ConvertUpgradeParams_EnableTtsCacheSetup) { + StartMiniArc(); + UpgradeParams upgrade_params = GetPopulatedUpgradeParams(); + UpgradeArcWithParams(true, std::move(upgrade_params)); + EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(), + "ro.boot.skip_tts_cache=0")); +} + } // namespace } // namespace arc
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc index def3c9a..a0df38c5 100644 --- a/ash/constants/ash_switches.cc +++ b/ash/constants/ash_switches.cc
@@ -101,6 +101,9 @@ // apps silently. Used in autotests to resolve racy conditions. const char kArcDisablePlayAutoInstall[] = "arc-disable-play-auto-install"; +// Used in autotest to disable TTS cache which is on by default. +const char kArcDisableTtsCache[] = "arc-disable-tts-cache"; + // Flag that disables ureadahead completely, including host and guest parts. // See also |kArcVmUreadaheadMode|. const char kArcDisableUreadahead[] = "arc-disable-ureadahead";
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h index ab02961..06f18bd 100644 --- a/ash/constants/ash_switches.h +++ b/ash/constants/ash_switches.h
@@ -40,6 +40,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kArcDisableMediaStoreMaintenance[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kArcDisablePlayAutoInstall[]; +COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kArcDisableTtsCache[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kArcDisableUreadahead[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kArcForceShowOptInUi[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kArcGeneratePlayAutoInstall[];
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc index d15778f..6b992ae 100644 --- a/ash/system/ime_menu/ime_menu_tray.cc +++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -279,10 +279,6 @@ // DetailedViewDelegate: void TransitionToMainView(bool restore_focus) override {} void CloseBubble() override {} - - gfx::Insets GetInsetsForDetailedView() const override { - return gfx::Insets(); - } }; explicit ImeMenuListView(std::unique_ptr<Delegate> delegate)
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc index 6c8ce9f..8dd8691 100644 --- a/ash/system/message_center/ash_notification_view.cc +++ b/ash/system/message_center/ash_notification_view.cc
@@ -112,9 +112,9 @@ constexpr int kTitleCharacterLimit = message_center::kNotificationWidth * message_center::kMaxTitleLines / message_center::kMinPixelsPerTitleCharacter; -constexpr int kTitleLabelSize = 14; +constexpr int kTitleLabelSize = 13; constexpr int kTimestampInCollapsedViewSize = 12; -constexpr int kMessageLabelSize = 13; +constexpr int kMessageLabelSize = 12; // The size for `icon_view_`, which is the icon within right content (between // title/message view and expand button). constexpr int kIconViewSize = 48;
diff --git a/ash/system/tray/detailed_view_delegate.cc b/ash/system/tray/detailed_view_delegate.cc index 47b1fd02..e6783b6 100644 --- a/ash/system/tray/detailed_view_delegate.cc +++ b/ash/system/tray/detailed_view_delegate.cc
@@ -104,10 +104,6 @@ return absl::nullopt; } -gfx::Insets DetailedViewDelegate::GetInsetsForDetailedView() const { - return kUnifiedDetailedViewPadding; -} - bool DetailedViewDelegate::IsOverflowIndicatorEnabled() const { return false; }
diff --git a/ash/system/tray/detailed_view_delegate.h b/ash/system/tray/detailed_view_delegate.h index ee1b663..7c4ed23 100644 --- a/ash/system/tray/detailed_view_delegate.h +++ b/ash/system/tray/detailed_view_delegate.h
@@ -51,9 +51,6 @@ // Get the background color of the detailed view. virtual absl::optional<SkColor> GetBackgroundColor(); - // Get the padding of the detailed view. - virtual gfx::Insets GetInsetsForDetailedView() const; - // Return true if overflow indicator of ScrollView is enabled. virtual bool IsOverflowIndicatorEnabled() const;
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h index 544b41e..90f271a1 100644 --- a/ash/system/tray/tray_constants.h +++ b/ash/system/tray/tray_constants.h
@@ -219,7 +219,6 @@ constexpr int kUnifiedTopShortcutButtonMinSpacing = 4; // Constants used in the detailed view in UnifiedSystemTray. -constexpr auto kUnifiedDetailedViewPadding = gfx::Insets::TLBR(0, 0, 8, 0); constexpr auto kUnifiedDetailedViewTitlePadding = gfx::Insets::TLBR(0, 0, 0, 16); constexpr int kUnifiedDetailedViewTitleRowHeight = 64;
diff --git a/ash/system/tray/tray_detailed_view.cc b/ash/system/tray/tray_detailed_view.cc index c1aa5bb..390bd87 100644 --- a/ash/system/tray/tray_detailed_view.cc +++ b/ash/system/tray/tray_detailed_view.cc
@@ -275,8 +275,7 @@ TrayDetailedView::TrayDetailedView(DetailedViewDelegate* delegate) : delegate_(delegate) { box_layout_ = SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical, - delegate->GetInsetsForDetailedView())); + views::BoxLayout::Orientation::kVertical)); SetBackground(views::CreateSolidBackground( delegate_->GetBackgroundColor().value_or(SK_ColorTRANSPARENT))); }
diff --git a/ash/webui/diagnostics_ui/backend/session_log_handler_unittest.cc b/ash/webui/diagnostics_ui/backend/session_log_handler_unittest.cc index 2f3c46b..ea8fa7b 100644 --- a/ash/webui/diagnostics_ui/backend/session_log_handler_unittest.cc +++ b/ash/webui/diagnostics_ui/backend/session_log_handler_unittest.cc
@@ -235,7 +235,8 @@ testing::NiceMock<ash::MockHoldingSpaceClient> holding_space_client_; }; -TEST_F(SessionLogHandlerTest, SaveSessionLog) { +// Flaky; see crbug.com/1336726 +TEST_F(SessionLogHandlerTest, DISABLED_SaveSessionLog) { base::RunLoop run_loop; // Populate routine log routine_log_->LogRoutineStarted(mojom::RoutineType::kCpuStress);
diff --git a/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom b/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom index 0c36070..c1faf303 100644 --- a/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom +++ b/ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom
@@ -113,6 +113,9 @@ // Whether or not to include the screenshot with this report. The screenshot // data should have been cached in C++ side. bool include_screenshot; + // Whether or not consent has been granted to Google for to contact user in + // reference to report. See (go/feedback-user-consent-faq). + bool contact_user_consent_granted; }; // Provides services needed by the feedback UI to display data and send reports.
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc index 46f4d083..13695c15 100644 --- a/ash/webui/os_feedback_ui/os_feedback_ui.cc +++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -41,6 +41,7 @@ void AddLocalizedStrings(content::WebUIDataSource* source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"backButtonLabel", IDS_FEEDBACK_TOOL_BACK_BUTTON_LABEL}, {"continueButtonLabel", IDS_FEEDBACK_TOOL_CONTINUE_BUTTON_LABEL}, {"descriptionHint", IDS_FEEDBACK_TOOL_DESCRIPTION_HINT}, {"descriptionLabel", IDS_FEEDBACK_TOOL_DESCRIPTION_LABEL}, @@ -60,6 +61,7 @@ {"confirmationTitleOnline", IDS_FEEDBACK_TOOL_PAGE_TITLE_AFTER_SENT}, {"diagnosticsAppLabel", IDS_FEEDBACK_TOOL_RESOURCES_DIAGNOSTICS_APP_LABEL}, + {"userConsentLabel", IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL}, }; source->AddLocalizedStrings(kLocalizedStrings);
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.html b/ash/webui/os_feedback_ui/resources/share_data_page.html index bd2191cc..6a8a431 100644 --- a/ash/webui/os_feedback_ui/resources/share_data_page.html +++ b/ash/webui/os_feedback_ui/resources/share_data_page.html
@@ -67,6 +67,9 @@ margin-bottom: 24px; } + .disabled-input-text { + color: var(--cros-text-color-disabled); + } </style> <div id="container"> <div id="header"> @@ -101,6 +104,12 @@ <option value="">Don't include email address</option> </select> </div> + <!-- User consent --> + <div id="userConsent" class="checkbox-field-container"> + <input id="userConsentCheckbox" type="checkbox" + aria-labelledby="userConsentLabel"> + <label id="userConsentLabel">[[i18n('userConsentLabel')]]</label> + </div> <!-- Diagnostic data --> <div id="shareDiagnosticData"> <h2 id="shareDiagnosticDataLabel">[[i18n('shareDiagnosticDataLabel')]]</h2> @@ -130,7 +139,7 @@ <div id="navButtons"> <cr-button id="buttonBack" class="cancel-button" on-click="handleBackButtonClicked_"> - Back + [[i18n('backButtonLabel')]] </cr-button> <cr-button id="buttonSend" class="action-button" on-click="handleSendButtonClicked_">
diff --git a/ash/webui/os_feedback_ui/resources/share_data_page.js b/ash/webui/os_feedback_ui/resources/share_data_page.js index 4b382e6..a24d875 100644 --- a/ash/webui/os_feedback_ui/resources/share_data_page.js +++ b/ash/webui/os_feedback_ui/resources/share_data_page.js
@@ -56,6 +56,15 @@ this.screenshotUrl; } + ready() { + super.ready(); + + // Set up event listener for email change to retarget |this| to be the + // ShareDataPageElement's context. + this.$.userEmailDropDown.addEventListener( + 'change', this.handleUserEmailDropDownChanged_.bind(this)); + } + /** * @return {boolean} * @protected @@ -72,6 +81,23 @@ return !!this.screenshotUrl; } + /** @protected */ + handleUserEmailDropDownChanged_() { + const email = this.$.userEmailDropDown.value; + const consentCheckbox = this.$.userConsentCheckbox; + + // Update UI and state of #userConsentCheckbox base on if report will be + // anonymous. + if (email === '') { + consentCheckbox.disabled = true; + consentCheckbox.checked = false; + this.$.userConsentLabel.classList.add('disabled-input-text'); + } else { + consentCheckbox.disabled = false; + this.$.userConsentLabel.classList.remove('disabled-input-text'); + } + } + /** * @param {!Event} e * @protected @@ -125,7 +151,9 @@ includeSystemLogsAndHistograms: this.getElement_('#sysInfoCheckbox').checked, includeScreenshot: this.getElement_('#screenshotCheckbox').checked && - !!this.getElement_('#screenshotImage').src + !!this.getElement_('#screenshotImage').src, + contactUserConsentGranted: + this.getElement_('#userConsentCheckbox').checked, }); report.attachedFile = @@ -136,6 +164,11 @@ report.feedbackContext.email = email; } + // Ensure consent granted is false when email not provided. + if (!email) { + report.contactUserConsentGranted = false; + } + if (this.getElement_('#pageUrlCheckbox').checked) { report.feedbackContext.pageUrl = { url: this.getElement_('#pageUrlText').value
diff --git a/ash/webui/personalization_app/resources/common/common_style.css b/ash/webui/personalization_app/resources/common/common_style.css index 4f922df..0a9b764 100644 --- a/ash/webui/personalization_app/resources/common/common_style.css +++ b/ash/webui/personalization_app/resources/common/common_style.css
@@ -109,7 +109,6 @@ .photo-images-container { background-color: var(--personalization-app-grid-item-background-color); - border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 12px; box-sizing: border-box; display: flex; @@ -182,6 +181,9 @@ animation-fill-mode: forwards; animation-name: resize; animation-timing-function: cubic-bezier(0.40, 0.00, 0.20, 1.00); +} + +.photo-inner-container[aria-selected='true'] .photo-images-border { border: 0; } @@ -233,13 +235,29 @@ } .preview-image-container { - border: 1px solid rgba(0, 0, 0, 0.08); border-radius: 12px; box-sizing: border-box; overflow: hidden; position: relative; } +/** + * Hover a border over the image container to avoid sub pixel rounding issues + * with chrome scaling images. + */ +.preview-image-border, +.photo-images-border { + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 12px; + bottom: 0; + box-sizing: border-box; + left: 0; + position: absolute; + right: 0; + top: 0; + z-index: 2; +} + .preview-image { height: 100%; object-fit: cover;
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html index a9aece8..416e32c 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html
@@ -173,6 +173,7 @@ <template is="dom-if" if="[[!loading_]]"> <template is="dom-if" if="[[!ambientModeEnabled_]]"> <div id="imageContainer" class="preview-image-container" aria-hidden="true"> + <div class="preview-image-border"></div> <img class="preview-image disabled" src="//personalization/common/slideshow.png"> </div> <div id="messageContainer"> @@ -190,6 +191,7 @@ Currently, we show blank containers --> <template is="dom-if" if="[[previewAlbums_]]"> <div id="imageContainer" class="preview-image-container"> + <div class="preview-image-border"></div> <template is="dom-if" if="[[clickable]]"> <img class="preview-image clickable" is="cr-auto-img" on-click="onClickPreviewImage_"
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html index 41ac52b8..2b2aa16 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html
@@ -119,7 +119,8 @@ } </style> <div id="container"> - <template is="dom-if" if="[[shouldShowMainSettings_(path)]]"> + <!-- restamp to avoid layout issues with iron-list resizing while hidden --> + <template is="dom-if" if="[[shouldShowMainSettings_(path)]]" restamp> <div id="mainSettings"> <template is="dom-if" if="[[loadingAmbientMode_(ambientModeEnabled_)]]"> <div id="toggleRowPlaceholder" class="ambient-toggle-row-container"> @@ -195,7 +196,8 @@ </template> </div> </template> - <template is="dom-if" if="[[shouldShowAlbums_(path)]]"> + <!-- restamp to avoid layout issues with iron-list resizing while hidden --> + <template is="dom-if" if="[[shouldShowAlbums_(path)]]" restamp> <div id="albumsSubpage"> <albums-subpage topic-source="[[getTopicSource_(queryParams)]]" albums="[[getAlbums_(albums_, queryParams)]]">
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.html index 376aa75..c6dc19a1 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.html
@@ -33,6 +33,7 @@ aria-selected$="[[getAriaSelected_(item, currentSelected_, pendingSelected_)]]" aria-label$="[[getAriaLabel_(item)]]"> <div class="photo-images-container"> + <div class="photo-images-border"></div> <img src="[[getImageData_(item, imageData_)]]" aria-hidden="true"> <iron-icon icon="personalization:checkmark"></iron-icon> </div>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html index 3754a36..79dee42 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html
@@ -91,6 +91,7 @@ <template is="dom-if" if="[[!isPolicyControlled_(image_)]]"> <div id="imageContainer" class="photo-images-container clickable" on-click="onClickWallpaper_" on-keypress="onClickWallpaper_"> + <div class="photo-images-border"></div> <img src$="[[getImageSrc_(image_)]]" alt$="[[getImageAltDescription_(image_)]]"> <div id="shelf"></div> @@ -98,6 +99,7 @@ </template> <template is="dom-if" if="[[isPolicyControlled_(image_)]]"> <div id="imageContainer" class="photo-images-container"> + <div class="photo-images-border"></div> <img src$="[[getImageSrc_(image_)]]" aria-description="$i18n{managedSetting}" alt$="[[getImageAltDescription_(image_)]]">
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.html index 7de93a3..cce9290a 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_selected_element.html
@@ -61,6 +61,7 @@ </template> <template is="dom-if" if="[[showImage_]]"> <div id="imageContainer" class="preview-image-container"> + <div class="preview-image-border"></div> <img class="preview-image" src$="[[getImageSrc_(image_)]]" aria-hidden="true"> </div> <h2 id="textContainer" class="preview-text-container" aria-live="polite" aria-label$="[[getAriaLabel_(image_, dailyRefreshState_)]]">
diff --git a/ash/webui/personalization_app/resources/untrusted/collections_grid.html b/ash/webui/personalization_app/resources/untrusted/collections_grid.html index cb061d5e2..07e86866 100644 --- a/ash/webui/personalization_app/resources/untrusted/collections_grid.html +++ b/ash/webui/personalization_app/resources/untrusted/collections_grid.html
@@ -161,6 +161,7 @@ aria-disabled="true" class="photo-inner-container photo-loading-failure"> <div class$="[[getClassForImagesContainer_(item)]]"> + <div class="photo-images-border"></div> <template is="dom-repeat" items="[[item.preview]]" as="preview"> <img is="cr-auto-img" auto-src="[[preview.url]]" aria-hidden="true" clear-src> @@ -185,6 +186,7 @@ on-click="onCollectionSelected_" on-keypress="onCollectionSelected_"> <div class$="[[getClassForImagesContainer_(item)]]"> + <div class="photo-images-border"></div> <img is="cr-auto-img" auto-src="[[getImageUrlForEmptyTile_(item)]]" aria-hidden="true" clear-src> </div> @@ -208,6 +210,7 @@ on-keypress="onCollectionSelected_" tabindex$="[[tabIndex]]"> <div class$="[[getClassForImagesContainer_(item)]]"> + <div class="photo-images-border"></div> <template is="dom-repeat" items="[[item.preview]]" as="preview"> <img is="cr-auto-img" auto-src="[[preview.url]]" class$="[[getClassForImg_(index, item)]]"
diff --git a/ash/webui/personalization_app/resources/untrusted/images_grid.html b/ash/webui/personalization_app/resources/untrusted/images_grid.html index 51308fe7..16fda71 100644 --- a/ash/webui/personalization_app/resources/untrusted/images_grid.html +++ b/ash/webui/personalization_app/resources/untrusted/images_grid.html
@@ -26,6 +26,7 @@ aria-selected$="[[getAriaSelected_(item, selectedAssetId_, pendingSelectedAssetId_)]]" aria-label$="[[getAriaLabel_(item)]]"> <div class="photo-images-container"> + <div class="photo-images-border"></div> <template is="dom-repeat" items="[[item.preview]]" as="preview"> <img is="cr-auto-img" class$="[[getClassForImg_(index, item)]]" auto-src="[[preview.url]]" aria-hidden="true" clear-src>
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc index c011e14..b632a47 100644 --- a/base/json/json_parser.cc +++ b/base/json/json_parser.cc
@@ -53,8 +53,6 @@ return JSONParser::kUnsupportedEncoding; case JSONParser::JSON_UNQUOTED_DICTIONARY_KEY: return JSONParser::kUnquotedDictionaryKey; - case JSONParser::JSON_TOO_LARGE: - return JSONParser::kInputTooLarge; case JSONParser::JSON_UNREPRESENTABLE_NUMBER: return JSONParser::kUnrepresentableNumber; case JSONParser::JSON_PARSE_ERROR_COUNT: @@ -109,7 +107,6 @@ "Unsupported encoding. JSON must be UTF-8."; const char JSONParser::kUnquotedDictionaryKey[] = "Dictionary keys must be quoted."; -const char JSONParser::kInputTooLarge[] = "Input string is too large (>2GB)."; const char JSONParser::kUnrepresentableNumber[] = "Number cannot be represented."; @@ -143,19 +140,12 @@ // index of the imaginary '\n' immediately before the start of the string: // 'A' is in column (0 - -1) = 1. line_number_ = 1; - index_last_line_ = -1; + index_last_line_ = static_cast<size_t>(-1); error_code_ = JSON_NO_ERROR; error_line_ = 0; error_column_ = 0; - // ICU and ReadUnicodeCharacter() use int32_t for lengths, so ensure - // that the index_ will not overflow when parsing. - if (!base::IsValueInRangeForNumericType<int32_t>(input.length())) { - ReportError(JSON_TOO_LARGE, -1); - return absl::nullopt; - } - // When the input JSON string starts with a UTF-8 Byte-Order-Mark, // advance the start position to avoid the ParseNextToken function mis- // treating a Unicode BOM as an invalid character and returning NULL. @@ -215,7 +205,7 @@ if (UNLIKELY(point == kUnicodeReplacementPoint)) { string_->append(kUnicodeReplacementString); } else { - WriteUnicodeCharacter(point, &*string_); + WriteUnicodeCharacter(static_cast<base_icu::UChar32>(point), &*string_); } } } @@ -264,7 +254,7 @@ } const char* JSONParser::pos() { - CHECK_LE(static_cast<size_t>(index_), input_.length()); + CHECK_LE(index_, input_.length()); return input_.data() + index_; } @@ -541,8 +531,7 @@ while (PeekChar()) { base_icu::UChar32 next_char = 0; - if (!ReadUnicodeCharacter(input_.data(), - static_cast<int32_t>(input_.length()), &index_, + if (!ReadUnicodeCharacter(input_.data(), input_.length(), &index_, &next_char) || !IsValidCodepoint(next_char)) { if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) { @@ -747,8 +736,8 @@ absl::optional<Value> JSONParser::ConsumeNumber() { const char* num_start = pos(); - const int start_index = index_; - int end_index = start_index; + const size_t start_index = index_; + size_t end_index = start_index; if (PeekChar() == '-') ConsumeChar(); @@ -787,7 +776,7 @@ // so save off where the parser should be on exit (see Consume invariant at // the top of the header), then make sure the next token is one which is // valid. - int exit_index = index_; + size_t exit_index = index_; switch (GetNextToken()) { case T_OBJECT_END:
diff --git a/base/json/json_parser.h b/base/json/json_parser.h index 6cdd1e08..aad1b3a 100644 --- a/base/json/json_parser.h +++ b/base/json/json_parser.h
@@ -54,7 +54,6 @@ JSON_UNEXPECTED_DATA_AFTER_ROOT, JSON_UNSUPPORTED_ENCODING, JSON_UNQUOTED_DICTIONARY_KEY, - JSON_TOO_LARGE, JSON_UNREPRESENTABLE_NUMBER, JSON_PARSE_ERROR_COUNT }; @@ -68,7 +67,6 @@ static const char kUnexpectedDataAfterRoot[]; static const char kUnsupportedEncoding[]; static const char kUnquotedDictionaryKey[]; - static const char kInputTooLarge[]; static const char kUnrepresentableNumber[]; explicit JSONParser(int options, size_t max_depth = kAbsoluteMaxDepth); @@ -253,7 +251,7 @@ StringPiece input_; // The index in the input stream to which the parser is wound. - int index_; + size_t index_; // The number of times the parser has recursed (current stack depth). size_t stack_depth_; @@ -262,7 +260,7 @@ int line_number_; // The last value of |index_| on the previous line. - int index_last_line_; + size_t index_last_line_; // Error information. JsonParseError error_code_;
diff --git a/base/json/string_escape.cc b/base/json/string_escape.cc index 4c1dbeb5..69362f7 100644 --- a/base/json/string_escape.cc +++ b/base/json/string_escape.cc
@@ -85,12 +85,8 @@ if (put_in_quotes) dest->push_back('"'); - // Casting is necessary because ICU uses int32_t. Try and do so safely. - CHECK_LE(str.length(), - static_cast<size_t>(std::numeric_limits<int32_t>::max())); - const int32_t length = static_cast<int32_t>(str.length()); - - for (int32_t i = 0; i < length; ++i) { + const size_t length = str.length(); + for (size_t i = 0; i < length; ++i) { base_icu::UChar32 code_point; if (!ReadUnicodeCharacter(str.data(), length, &i, &code_point) || code_point == CBU_SENTINEL) {
diff --git a/base/strings/escape.cc b/base/strings/escape.cc index e9b9afc..8c79bcd 100644 --- a/base/strings/escape.cc +++ b/base/strings/escape.cc
@@ -61,7 +61,7 @@ escaped.push_back(IntToHex(c >> 4)); escaped.push_back(IntToHex(c & 0xf)); } else { - escaped.push_back(c); + escaped.push_back(static_cast<char>(c)); } } return escaped; @@ -198,8 +198,8 @@ char most_sig_digit(escaped_text[index + 1]); char least_sig_digit(escaped_text[index + 2]); if (IsHexDigit(most_sig_digit) && IsHexDigit(least_sig_digit)) { - *value = - HexDigitToInt(most_sig_digit) * 16 + HexDigitToInt(least_sig_digit); + *value = static_cast<unsigned char>(HexDigitToInt(most_sig_digit) * 16 + + HexDigitToInt(least_sig_digit)); return true; } return false; @@ -236,7 +236,7 @@ } } - int32_t char_index = 0; + size_t char_index = 0; // Check if the unicode "character" that was just unescaped is valid. if (!ReadUnicodeCharacter(reinterpret_cast<char*>(bytes), num_bytes, &char_index, code_point_out)) { @@ -253,10 +253,11 @@ // This method takes a Unicode code point and returns true if it should be // unescaped, based on |rules|. -bool ShouldUnescapeCodePoint(UnescapeRule::Type rules, uint32_t code_point) { +bool ShouldUnescapeCodePoint(UnescapeRule::Type rules, + base_icu::UChar32 code_point) { // If this is an ASCII character, use the lookup table. - if (code_point < 0x80) { - return kUrlUnescape[code_point] || + if (code_point >= 0 && code_point < 0x80) { + return kUrlUnescape[static_cast<size_t>(code_point)] || // Allow some additional unescaping when flags are set. (code_point == ' ' && (rules & UnescapeRule::SPACES)) || // Allow any of the prohibited but non-control characters when doing @@ -418,7 +419,7 @@ // sequences. unsigned char non_utf8_byte; if (UnescapeUnsignedByteAtIndex(escaped_text, i, &non_utf8_byte)) { - result.push_back(non_utf8_byte); + result.push_back(static_cast<char>(non_utf8_byte)); if (adjustments) adjustments->push_back(OffsetAdjuster::Adjustment(i, 3, 1)); i += 3; @@ -569,7 +570,7 @@ // UnescapeUnsignedByteAtIndex does bounds checking, so this is always safe // to call. if (UnescapeUnsignedByteAtIndex(escaped_text, i, &byte)) { - unescaped_text[output_index++] = byte; + unescaped_text[output_index++] = static_cast<char>(byte); i += 3; continue; } @@ -595,7 +596,7 @@ unescaped_text->clear(); std::set<unsigned char> illegal_encoded_bytes; - for (char c = '\x00'; c < '\x20'; ++c) { + for (unsigned char c = '\x00'; c < '\x20'; ++c) { illegal_encoded_bytes.insert(c); } if (fail_on_path_separators) { @@ -632,7 +633,7 @@ std::u16string UnescapeForHTML(StringPiece16 input) { static const struct { const char* ampersand_code; - const char replacement; + const char16_t replacement; } kEscapeToChars[] = { {"<", '<'}, {">", '>'}, {"&", '&'}, {""", '"'}, {"'", '\''}, @@ -648,14 +649,15 @@ ++iter) { if (*iter == '&') { // Potential ampersand encode char. - size_t index = iter - text.begin(); + size_t index = static_cast<size_t>(iter - text.begin()); for (size_t i = 0; i < std::size(kEscapeToChars); i++) { if (ampersand_chars[i].empty()) { ampersand_chars[i] = ASCIIToUTF16(kEscapeToChars[i].ampersand_code); } if (text.find(ampersand_chars[i], index) == index) { - text.replace(iter, iter + ampersand_chars[i].length(), 1, - kEscapeToChars[i].replacement); + text.replace( + iter, iter + static_cast<ptrdiff_t>(ampersand_chars[i].length()), + 1, kEscapeToChars[i].replacement); break; } }
diff --git a/base/strings/escape.h b/base/strings/escape.h index 151993c..9eb6258 100644 --- a/base/strings/escape.h +++ b/base/strings/escape.h
@@ -74,41 +74,39 @@ // functions. typedef uint32_t Type; - enum { - // Don't unescape anything at all. - NONE = 0, + // Don't unescape anything at all. + static constexpr Type NONE = 0; - // Don't unescape anything special, but all normal unescaping will happen. - // This is a placeholder and can't be combined with other flags (since it's - // just the absence of them). All other unescape rules imply "normal" in - // addition to their special meaning. Things like escaped letters, digits, - // and most symbols will get unescaped with this mode. - NORMAL = 1 << 0, + // Don't unescape anything special, but all normal unescaping will happen. + // This is a placeholder and can't be combined with other flags (since it's + // just the absence of them). All other unescape rules imply "normal" in + // addition to their special meaning. Things like escaped letters, digits, + // and most symbols will get unescaped with this mode. + static constexpr Type NORMAL = 1 << 0; - // Convert %20 to spaces. In some places where we're showing URLs, we may - // want this. In places where the URL may be copied and pasted out, then - // you wouldn't want this since it might not be interpreted in one piece - // by other applications. Other UTF-8 spaces will not be unescaped. - SPACES = 1 << 1, + // Convert %20 to spaces. In some places where we're showing URLs, we may + // want this. In places where the URL may be copied and pasted out, then + // you wouldn't want this since it might not be interpreted in one piece + // by other applications. Other UTF-8 spaces will not be unescaped. + static constexpr Type SPACES = 1 << 1; - // Unescapes '/' and '\\'. If these characters were unescaped, the resulting - // URL won't be the same as the source one. Moreover, they are dangerous to - // unescape in strings that will be used as file paths or names. This value - // should only be used when slashes don't have special meaning, like data - // URLs. - PATH_SEPARATORS = 1 << 2, + // Unescapes '/' and '\\'. If these characters were unescaped, the resulting + // URL won't be the same as the source one. Moreover, they are dangerous to + // unescape in strings that will be used as file paths or names. This value + // should only be used when slashes don't have special meaning, like data + // URLs. + static constexpr Type PATH_SEPARATORS = 1 << 2; - // Unescapes various characters that will change the meaning of URLs, - // including '%', '+', '&', '#'. Does not unescape path separators. - // If these characters were unescaped, the resulting URL won't be the same - // as the source one. This flag is used when generating final output like - // filenames for URLs where we won't be interpreting as a URL and want to do - // as much unescaping as possible. - URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS = 1 << 3, + // Unescapes various characters that will change the meaning of URLs, + // including '%', '+', '&', '#'. Does not unescape path separators. + // If these characters were unescaped, the resulting URL won't be the same + // as the source one. This flag is used when generating final output like + // filenames for URLs where we won't be interpreting as a URL and want to do + // as much unescaping as possible. + static constexpr Type URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS = 1 << 3; - // URL queries use "+" for space. This flag controls that replacement. - REPLACE_PLUS_WITH_SPACE = 1 << 4, - }; + // URL queries use "+" for space. This flag controls that replacement. + static constexpr Type REPLACE_PLUS_WITH_SPACE = 1 << 4; }; // Unescapes |escaped_text| and returns the result.
diff --git a/base/strings/pattern.cc b/base/strings/pattern.cc index 613ddc28..9b01b2a3 100644 --- a/base/strings/pattern.cc +++ b/base/strings/pattern.cc
@@ -124,7 +124,7 @@ base_icu::UChar32 operator()(const char** p, const char* end) { base_icu::UChar32 c; int offset = 0; - CBU8_NEXT(*p, offset, end - *p, c); + CBU8_NEXT(reinterpret_cast<const uint8_t*>(*p), offset, end - *p, c); *p += offset; return c; }
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc index 12621c8..dbb0e3a4 100644 --- a/base/strings/safe_sprintf.cc +++ b/base/strings/safe_sprintf.cc
@@ -223,8 +223,13 @@ // if |pad| is ' '. // // Returns "false", if the |buffer_| overflowed at any time. - bool IToASCII(bool sign, bool upcase, int64_t i, int base, - char pad, size_t padding, const char* prefix); + bool IToASCII(bool sign, + bool upcase, + int64_t i, + size_t base, + char pad, + size_t padding, + const char* prefix); private: // Increments |count_| by |inc| unless this would cause |count_| to @@ -275,9 +280,13 @@ size_t count_; }; - -bool Buffer::IToASCII(bool sign, bool upcase, int64_t i, int base, - char pad, size_t padding, const char* prefix) { +bool Buffer::IToASCII(bool sign, + bool upcase, + int64_t i, + size_t base, + char pad, + size_t padding, + const char* prefix) { // Sanity check for parameters. None of these should ever fail, but see // above for the rationale why we can't call CHECK(). DEBUG_CHECK(base >= 2); @@ -295,7 +304,7 @@ // if (sign && i < 0) // prefix = "-"; // num = abs(i); - int minint = 0; + size_t minint = 0; uint64_t num; if (sign && i < 0) { prefix = "-"; @@ -335,7 +344,7 @@ } } else prefix = nullptr; - const size_t prefix_length = reverse_prefix - prefix; + const size_t prefix_length = static_cast<size_t>(reverse_prefix - prefix); // Loop until we have converted the entire number. Output at least one // character (i.e. '0'). @@ -384,7 +393,8 @@ } } else { started = true; - Out((upcase ? kUpCaseHexDigits : kDownCaseHexDigits)[num%base + minint]); + Out((upcase ? kUpCaseHexDigits + : kDownCaseHexDigits)[num % base + minint]); } minint = 0; @@ -457,13 +467,14 @@ // character from a space ' ' to a zero '0'. pad = ch == '0' ? '0' : ' '; for (;;) { + const size_t digit = static_cast<size_t>(ch - '0'); // The maximum allowed padding fills all the available address // space and leaves just enough space to insert the trailing NUL. const size_t max_padding = kSSizeMax - 1; - if (padding > max_padding/10 || - 10*padding > max_padding - (ch - '0')) { - DEBUG_CHECK(padding <= max_padding/10 && - 10*padding <= max_padding - (ch - '0')); + if (padding > max_padding / 10 || + 10 * padding > max_padding - digit) { + DEBUG_CHECK(padding <= max_padding / 10 && + 10 * padding <= max_padding - digit); // Integer overflow detected. Skip the rest of the width until // we find the format character, then do the normal error handling. padding_overflow: @@ -475,7 +486,7 @@ } goto fail_to_expand; } - padding = 10*padding + ch - '0'; + padding = 10 * padding + digit; if (padding > max_padding) { // This doesn't happen for "sane" values of kSSizeMax. But once // kSSizeMax gets smaller than about 10, our earlier range checks @@ -552,9 +563,9 @@ } else { // Pointer values require an actual pointer or a string. if (arg.type == Arg::POINTER) { - i = reinterpret_cast<uintptr_t>(arg.ptr); + i = reinterpret_cast<intptr_t>(arg.ptr); } else if (arg.type == Arg::STRING) { - i = reinterpret_cast<uintptr_t>(arg.str); + i = reinterpret_cast<intptr_t>(arg.str); } else if (arg.type == Arg::INT && arg.integer.width == sizeof(NULL) && arg.integer.i == 0) { // Allow C++'s version of NULL
diff --git a/base/strings/string_piece.cc b/base/strings/string_piece.cc index 95170da..28aabe4 100644 --- a/base/strings/string_piece.cc +++ b/base/strings/string_piece.cc
@@ -129,7 +129,7 @@ s.begin(), s.end()); if (found == self.end()) return BasicStringPiece<CharT>::npos; - return found - self.begin(); + return static_cast<size_t>(found - self.begin()); } size_t find_first_of(StringPiece16 self, StringPiece16 s, size_t pos) {
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc index 3bbc6e9..26a3b36 100644 --- a/base/strings/string_util.cc +++ b/base/strings/string_util.cc
@@ -174,7 +174,8 @@ while (char_index >= 0) { int32_t prev = char_index; base_icu::UChar32 code_point = 0; - CBU8_NEXT(data, char_index, truncation_length, code_point); + CBU8_NEXT(reinterpret_cast<const uint8_t*>(data), char_index, + truncation_length, code_point); if (!IsValidCharacter(code_point)) { char_index = prev - 1; } else { @@ -183,7 +184,7 @@ } if (char_index >= 0 ) - *output = input.substr(0, char_index); + *output = input.substr(0, static_cast<size_t>(char_index)); else output->clear(); }
diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc index bcace27..aee227c6 100644 --- a/base/strings/stringprintf.cc +++ b/base/strings/stringprintf.cc
@@ -65,14 +65,14 @@ int result = vsnprintfT(stack_buf, std::size(stack_buf), format, ap_copy); va_end(ap_copy); - if (result >= 0 && result < static_cast<int>(std::size(stack_buf))) { + if (result >= 0 && static_cast<size_t>(result) < std::size(stack_buf)) { // It fit. - dst->append(stack_buf, result); + dst->append(stack_buf, static_cast<size_t>(result)); return; } // Repeatedly increase buffer size until it fits. - int mem_length = std::size(stack_buf); + size_t mem_length = std::size(stack_buf); while (true) { if (result < 0) { #if BUILDFLAG(IS_WIN) @@ -88,7 +88,7 @@ #endif } else { // We need exactly "result + 1" characters. - mem_length = result + 1; + mem_length = static_cast<size_t>(result) + 1; } if (mem_length > 32 * 1024 * 1024) { @@ -107,9 +107,9 @@ result = vsnprintfT(&mem_buf[0], mem_length, format, ap_copy); va_end(ap_copy); - if ((result >= 0) && (result < mem_length)) { + if ((result >= 0) && (static_cast<size_t>(result) < mem_length)) { // It fit. - dst->append(&mem_buf[0], result); + dst->append(&mem_buf[0], static_cast<size_t>(result)); return; } }
diff --git a/base/strings/sys_string_conversions_win.cc b/base/strings/sys_string_conversions_win.cc index 356064f..340b25d 100644 --- a/base/strings/sys_string_conversions_win.cc +++ b/base/strings/sys_string_conversions_win.cc
@@ -42,7 +42,7 @@ return std::wstring(); std::wstring wide; - wide.resize(charcount); + wide.resize(static_cast<size_t>(charcount)); MultiByteToWideChar(code_page, 0, mb.data(), mb_length, &wide[0], charcount); return wide; @@ -61,7 +61,7 @@ return std::string(); std::string mb; - mb.resize(charcount); + mb.resize(static_cast<size_t>(charcount)); WideCharToMultiByte(code_page, 0, wide.data(), wide_length, &mb[0], charcount, NULL, NULL);
diff --git a/base/strings/utf_offset_string_conversions.cc b/base/strings/utf_offset_string_conversions.cc index f243e58..b4eb0e8f 100644 --- a/base/strings/utf_offset_string_conversions.cc +++ b/base/strings/utf_offset_string_conversions.cc
@@ -39,7 +39,8 @@ DCHECK(offset); if (*offset == std::u16string::npos) return; - int adjustment = 0; + size_t original_lengths = 0; + size_t output_lengths = 0; for (const auto& i : adjustments) { if (*offset <= i.original_offset) break; @@ -47,9 +48,10 @@ *offset = std::u16string::npos; return; } - adjustment += static_cast<int>(i.original_length - i.output_length); + original_lengths += i.original_length; + output_lengths += i.output_length; } - *offset -= adjustment; + *offset += output_lengths - original_lengths; if (*offset > limit) *offset = std::u16string::npos; @@ -70,17 +72,20 @@ size_t* offset) { if (*offset == std::u16string::npos) return; - int adjustment = 0; + size_t original_lengths = 0; + size_t output_lengths = 0; for (const auto& i : adjustments) { - if (*offset + adjustment <= i.original_offset) + if (*offset + original_lengths - output_lengths <= i.original_offset) break; - adjustment += static_cast<int>(i.original_length - i.output_length); - if ((*offset + adjustment) < (i.original_offset + i.original_length)) { + original_lengths += i.original_length; + output_lengths += i.output_length; + if ((*offset + original_lengths - output_lengths) < + (i.original_offset + i.original_length)) { *offset = std::u16string::npos; return; } } - *offset += adjustment; + *offset += original_lengths - output_lengths; } // static @@ -149,15 +154,15 @@ // <= // adjusted_iter->original_offset + shift + // adjusted_iter->original_length - // Modify the current |adjusted_iter| to include whatever collapsing // happened in |first_iter|, then advance to the next |first_adjustments| // because we dealt with the current one. - const int collapse = static_cast<int>(first_iter->original_length) - - static_cast<int>(first_iter->output_length); + // This function does not know how to deal with a string that expands and // then gets modified, only strings that collapse and then get modified. - DCHECK_GT(collapse, 0); + DCHECK_GT(first_iter->original_length, first_iter->output_length); + const size_t collapse = + first_iter->original_length - first_iter->output_length; adjusted_iter->original_length += collapse; currently_collapsing += collapse; ++first_iter; @@ -188,14 +193,12 @@ OffsetAdjuster::Adjustments* adjustments) { if (adjustments) adjustments->clear(); - // ICU requires 32-bit numbers. bool success = true; - int32_t src_len32 = static_cast<int32_t>(src_len); - for (int32_t i = 0; i < src_len32; i++) { + for (size_t i = 0; i < src_len; i++) { base_icu::UChar32 code_point; size_t original_i = i; size_t chars_written = 0; - if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) { + if (ReadUnicodeCharacter(src, src_len, &i, &code_point)) { chars_written = WriteUnicodeCharacter(code_point, output); } else { chars_written = WriteUnicodeCharacter(0xFFFD, output);
diff --git a/base/strings/utf_string_conversion_utils.cc b/base/strings/utf_string_conversion_utils.cc index c530637..4b900bd 100644 --- a/base/strings/utf_string_conversion_utils.cc +++ b/base/strings/utf_string_conversion_utils.cc
@@ -12,11 +12,12 @@ // ReadUnicodeCharacter -------------------------------------------------------- bool ReadUnicodeCharacter(const char* src, - int32_t src_len, - int32_t* char_index, + size_t src_len, + size_t* char_index, base_icu::UChar32* code_point_out) { base_icu::UChar32 code_point; - CBU8_NEXT(src, *char_index, src_len, code_point); + CBU8_NEXT(reinterpret_cast<const uint8_t*>(src), *char_index, src_len, + code_point); *code_point_out = code_point; // The ICU macro above moves to the next char, we want to point to the last @@ -28,13 +29,12 @@ } bool ReadUnicodeCharacter(const char16_t* src, - int32_t src_len, - int32_t* char_index, + size_t src_len, + size_t* char_index, base_icu::UChar32* code_point) { if (CBU16_IS_SURROGATE(src[*char_index])) { - if (!CBU16_IS_SURROGATE_LEAD(src[*char_index]) || - *char_index + 1 >= src_len || - !CBU16_IS_TRAIL(src[*char_index + 1])) { + if (!CBU16_IS_SURROGATE_LEAD(src[*char_index]) || !src_len || + *char_index >= src_len - 1 || !CBU16_IS_TRAIL(src[*char_index + 1])) { // Invalid surrogate pair. return false; } @@ -53,8 +53,8 @@ #if defined(WCHAR_T_IS_UTF32) bool ReadUnicodeCharacter(const wchar_t* src, - int32_t src_len, - int32_t* char_index, + size_t src_len, + size_t* char_index, base_icu::UChar32* code_point) { // Conversion is easy since the source is 32-bit. *code_point = src[*char_index]; @@ -66,20 +66,21 @@ // WriteUnicodeCharacter ------------------------------------------------------- -size_t WriteUnicodeCharacter(uint32_t code_point, std::string* output) { - if (code_point <= 0x7f) { +size_t WriteUnicodeCharacter(base_icu::UChar32 code_point, + std::string* output) { + if (code_point >= 0 && code_point <= 0x7f) { // Fast path the common case of one byte. output->push_back(static_cast<char>(code_point)); return 1; } - // CBU8_APPEND_UNSAFE can append up to 4 bytes. size_t char_offset = output->length(); size_t original_char_offset = char_offset; output->resize(char_offset + CBU8_MAX_LENGTH); - CBU8_APPEND_UNSAFE(&(*output)[0], char_offset, code_point); + CBU8_APPEND_UNSAFE(reinterpret_cast<uint8_t*>(output->data()), char_offset, + code_point); // CBU8_APPEND_UNSAFE will advance our pointer past the inserted character, so // it will represent the new length of the string. @@ -87,9 +88,10 @@ return char_offset - original_char_offset; } -size_t WriteUnicodeCharacter(uint32_t code_point, std::u16string* output) { +size_t WriteUnicodeCharacter(base_icu::UChar32 code_point, + std::u16string* output) { if (CBU16_LENGTH(code_point) == 1) { - // Thie code point is in the Basic Multilingual Plane (BMP). + // The code point is in the Basic Multilingual Plane (BMP). output->push_back(static_cast<char16_t>(code_point)); return 1; }
diff --git a/base/strings/utf_string_conversion_utils.h b/base/strings/utf_string_conversion_utils.h index 2ca9262..1f6bc0e 100644 --- a/base/strings/utf_string_conversion_utils.h +++ b/base/strings/utf_string_conversion_utils.h
@@ -49,21 +49,21 @@ // // Returns true on success. On false, |*code_point| will be invalid. BASE_EXPORT bool ReadUnicodeCharacter(const char* src, - int32_t src_len, - int32_t* char_index, + size_t src_len, + size_t* char_index, base_icu::UChar32* code_point_out); // Reads a UTF-16 character. The usage is the same as the 8-bit version above. BASE_EXPORT bool ReadUnicodeCharacter(const char16_t* src, - int32_t src_len, - int32_t* char_index, + size_t src_len, + size_t* char_index, base_icu::UChar32* code_point); #if defined(WCHAR_T_IS_UTF32) // Reads UTF-32 character. The usage is the same as the 8-bit version above. BASE_EXPORT bool ReadUnicodeCharacter(const wchar_t* src, - int32_t src_len, - int32_t* char_index, + size_t src_len, + size_t* char_index, base_icu::UChar32* code_point); #endif // defined(WCHAR_T_IS_UTF32) @@ -71,20 +71,21 @@ // Appends a UTF-8 character to the given 8-bit string. Returns the number of // bytes written. -BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point, +BASE_EXPORT size_t WriteUnicodeCharacter(base_icu::UChar32 code_point, std::string* output); // Appends the given code point as a UTF-16 character to the given 16-bit // string. Returns the number of 16-bit values written. -BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point, +BASE_EXPORT size_t WriteUnicodeCharacter(base_icu::UChar32 code_point, std::u16string* output); #if defined(WCHAR_T_IS_UTF32) // Appends the given UTF-32 character to the given 32-bit string. Returns the // number of 32-bit values written. -inline size_t WriteUnicodeCharacter(uint32_t code_point, std::wstring* output) { +inline size_t WriteUnicodeCharacter(base_icu::UChar32 code_point, + std::wstring* output) { // This is the easy case, just append the character. - output->push_back(code_point); + output->push_back(static_cast<wchar_t>(code_point)); return 1; } #endif // defined(WCHAR_T_IS_UTF32)
diff --git a/base/test/launcher/unit_test_launcher.cc b/base/test/launcher/unit_test_launcher.cc index 63d4600..ebb815c 100644 --- a/base/test/launcher/unit_test_launcher.cc +++ b/base/test/launcher/unit_test_launcher.cc
@@ -38,6 +38,10 @@ #include "base/files/file_descriptor_watcher_posix.h" #endif +#if BUILDFLAG(IS_WIN) +#include "base/debug/handle_hooks_win.h" +#endif + namespace base { namespace { @@ -166,6 +170,9 @@ force_single_process = true; } } +#if BUILDFLAG(IS_WIN) + base::debug::HandleHooks::PatchLoadedModules(); +#endif // BUILDFLAG(IS_WIN) if (CommandLine::ForCurrentProcess()->HasSwitch(kGTestHelpFlag) || CommandLine::ForCurrentProcess()->HasSwitch(kGTestListTestsFlag) ||
diff --git a/base/third_party/icu/icu_utf.h b/base/third_party/icu/icu_utf.h index 16792c4..6fa41010 100644 --- a/base/third_party/icu/icu_utf.h +++ b/base/third_party/icu/icu_utf.h
@@ -278,25 +278,27 @@ * @see U8_APPEND * @stable ICU 2.4 */ -#define CBU8_APPEND_UNSAFE(s, i, c) CBUPRV_BLOCK_MACRO_BEGIN { \ - uint32_t __uc=(c); \ - if(__uc<=0x7f) { \ - (s)[(i)++]=(uint8_t)__uc; \ - } else { \ - if(__uc<=0x7ff) { \ - (s)[(i)++]=(uint8_t)((__uc>>6)|0xc0); \ - } else { \ - if(__uc<=0xffff) { \ - (s)[(i)++]=(uint8_t)((__uc>>12)|0xe0); \ - } else { \ - (s)[(i)++]=(uint8_t)((__uc>>18)|0xf0); \ - (s)[(i)++]=(uint8_t)(((__uc>>12)&0x3f)|0x80); \ - } \ - (s)[(i)++]=(uint8_t)(((__uc>>6)&0x3f)|0x80); \ - } \ - (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \ - } \ -} CBUPRV_BLOCK_MACRO_END +#define CBU8_APPEND_UNSAFE(s, i, c) \ + CBUPRV_BLOCK_MACRO_BEGIN { \ + uint32_t __uc = (uint32_t)(c); \ + if (__uc <= 0x7f) { \ + (s)[(i)++] = (uint8_t)__uc; \ + } else { \ + if (__uc <= 0x7ff) { \ + (s)[(i)++] = (uint8_t)((__uc >> 6) | 0xc0); \ + } else { \ + if (__uc <= 0xffff) { \ + (s)[(i)++] = (uint8_t)((__uc >> 12) | 0xe0); \ + } else { \ + (s)[(i)++] = (uint8_t)((__uc >> 18) | 0xf0); \ + (s)[(i)++] = (uint8_t)(((__uc >> 12) & 0x3f) | 0x80); \ + } \ + (s)[(i)++] = (uint8_t)(((__uc >> 6) & 0x3f) | 0x80); \ + } \ + (s)[(i)++] = (uint8_t)((__uc & 0x3f) | 0x80); \ + } \ + } \ + CBUPRV_BLOCK_MACRO_END // source/common/unicode/utf16.h @@ -314,7 +316,7 @@ * @return TRUE or FALSE * @stable ICU 2.4 */ -#define CBU16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) +#define CBU16_IS_LEAD(c) (((uint32_t)(c)&0xfffffc00) == 0xd800) /** * Is this code unit a trail surrogate (U+dc00..U+dfff)? @@ -322,7 +324,7 @@ * @return TRUE or FALSE * @stable ICU 2.4 */ -#define CBU16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) +#define CBU16_IS_TRAIL(c) (((uint32_t)(c)&0xfffffc00) == 0xdc00) /** * Is this code unit a surrogate (U+d800..U+dfff)?
diff --git a/base/trace_event/memory_infra_background_allowlist.cc b/base/trace_event/memory_infra_background_allowlist.cc index 43b482d..b20ce7d1 100644 --- a/base/trace_event/memory_infra_background_allowlist.cc +++ b/base/trace_event/memory_infra_background_allowlist.cc
@@ -287,6 +287,7 @@ "sync/0x?/model_type/PASSWORD", "sync/0x?/model_type/PREFERENCE", "sync/0x?/model_type/PRINTER", + "sync/0x?/model_type/PRINTERS_AUTHORIZATION_SERVER", "sync/0x?/model_type/PRIORITY_PREFERENCE", "sync/0x?/model_type/READING_LIST", "sync/0x?/model_type/SEARCH_ENGINE",
diff --git a/base/win/scoped_handle_unittest.cc b/base/win/scoped_handle_unittest.cc index fa1a073..1663f2c 100644 --- a/base/win/scoped_handle_unittest.cc +++ b/base/win/scoped_handle_unittest.cc
@@ -11,7 +11,6 @@ #include "base/base_switches.h" #include "base/command_line.h" -#include "base/debug/handle_hooks_win.h" #include "base/files/file_path.h" #include "base/scoped_native_library.h" #include "base/test/multiprocess_test.h" @@ -19,7 +18,6 @@ #include "base/win/scoped_handle.h" #include "base/win/windows_version.h" #include "build/build_config.h" - #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" @@ -38,36 +36,8 @@ #endif // !defined(DEBUG) && defined(OFFICIAL_BUILD) } -} // namespace - -namespace testing { -extern "C" bool __declspec(dllexport) RunTest(); -} // namespace testing - -class ScopedHandleTest : public ::testing::Test, - public ::testing::WithParamInterface<bool> { - public: - ScopedHandleTest(const ScopedHandleTest&) = delete; - ScopedHandleTest& operator=(const ScopedHandleTest&) = delete; - - protected: - ScopedHandleTest() { - if (HooksEnabled()) { -#if defined(ARCH_CPU_32_BITS) - // EAT patch is only supported on 32-bit. - base::debug::HandleHooks::AddEATPatch(); -#endif - base::debug::HandleHooks::PatchLoadedModules(); - } - } - - static bool HooksEnabled() { return GetParam(); } - static bool DoDeathTestsWork() { - // Death tests don't seem to work on Windows 7 32-bit native with hooks - // enabled. - // TODO(crbug.com/1328022): Investigate why. - if (!HooksEnabled()) - return true; +// Death tests don't seem to work on Windows 7 32-bit native with hooks enabled. +bool DoDeathTestsWork() { #if defined(ARCH_CPU_32_BITS) const auto* os_info = base::win::OSInfo::GetInstance(); if (os_info->version() <= base::win::Version::WIN7 && @@ -76,12 +46,18 @@ } #endif // defined(ARCH_CPU_32_BITS) return true; - } -}; +} -using ScopedHandleDeathTest = ScopedHandleTest; +} // namespace -TEST_P(ScopedHandleTest, ScopedHandle) { +namespace testing { +extern "C" bool __declspec(dllexport) RunTest(); +} // namespace testing + +using ScopedHandleTest = ::testing::Test; +using ScopedHandleDeathTest = ::testing::Test; + +TEST_F(ScopedHandleTest, ScopedHandle) { // Any illegal error code will do. We just need to test that it is preserved // by ScopedHandle to avoid https://crbug.com/528394. const DWORD magic_error = 0x12345678; @@ -106,7 +82,10 @@ EXPECT_EQ(magic_error, ::GetLastError()); } -TEST_P(ScopedHandleDeathTest, HandleVerifierTrackedHasBeenClosed) { +TEST_F(ScopedHandleDeathTest, HandleVerifierTrackedHasBeenClosed) { + // This test is only valid if hooks are enabled. + if (!DoDeathTestsWork()) + return; HANDLE handle = ::CreateMutex(nullptr, false, nullptr); ASSERT_NE(HANDLE(nullptr), handle); using NtCloseFunc = decltype(&::NtClose); @@ -124,10 +103,8 @@ FailureMessage("CloseHandle failed")); } -TEST_P(ScopedHandleDeathTest, HandleVerifierCloseTrackedHandle) { +TEST_F(ScopedHandleDeathTest, HandleVerifierCloseTrackedHandle) { // This test is only valid if hooks are enabled. - if (!HooksEnabled()) - return; if (!DoDeathTestsWork()) return; @@ -152,7 +129,7 @@ FailureMessage("CloseHandleHook validation failure")); } -TEST_P(ScopedHandleDeathTest, HandleVerifierDoubleTracking) { +TEST_F(ScopedHandleDeathTest, HandleVerifierDoubleTracking) { if (!DoDeathTestsWork()) return; @@ -165,7 +142,7 @@ FailureMessage("Handle Already Tracked")); } -TEST_P(ScopedHandleDeathTest, HandleVerifierWrongOwner) { +TEST_F(ScopedHandleDeathTest, HandleVerifierWrongOwner) { if (!DoDeathTestsWork()) return; @@ -183,7 +160,7 @@ handle_holder.Close(); } -TEST_P(ScopedHandleDeathTest, HandleVerifierUntrackedHandle) { +TEST_F(ScopedHandleDeathTest, HandleVerifierUntrackedHandle) { if (!DoDeathTestsWork()) return; @@ -208,7 +185,7 @@ #define MAYBE_MultiProcess MultiProcess #endif -TEST_P(ScopedHandleTest, MAYBE_MultiProcess) { +TEST_F(ScopedHandleTest, MAYBE_MultiProcess) { // Initializing ICU in the child process causes a scoped handle to be created // before the test gets a chance to test the race condition, so disable ICU // for the child process here. @@ -240,18 +217,5 @@ return 0; } -INSTANTIATE_TEST_SUITE_P(HooksEnabled, - ScopedHandleTest, - ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(HooksDisabled, - ScopedHandleTest, - ::testing::Values(false)); -INSTANTIATE_TEST_SUITE_P(HooksEnabled, - ScopedHandleDeathTest, - ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(HooksDisabled, - ScopedHandleDeathTest, - ::testing::Values(false)); - } // namespace win } // namespace base
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index 7cb6451..839cb7d6 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -14,7 +14,6 @@ import os import pipes import re -import shlex import shutil import stat import subprocess @@ -281,26 +280,18 @@ has_stdout = print_stdout and stdout has_stderr = print_stderr and stderr - if has_stdout or has_stderr: + if fail_on_output and (has_stdout or has_stderr): + MSG = """\ +Command failed because it wrote to {}. +You can often set treat_warnings_as_errors=false to not treat output as \ +failure (useful when developing locally).""" if has_stdout and has_stderr: stream_string = 'stdout and stderr' elif has_stdout: stream_string = 'stdout' else: stream_string = 'stderr' - - if fail_on_output: - MSG = """ -Command failed because it wrote to {}. -You can often set treat_warnings_as_errors=false to not treat output as \ -failure (useful when developing locally).""" - raise CalledProcessError(cwd, args, MSG.format(stream_string)) - - MSG = """ -The above {} output was from: -{} -""" - sys.stderr.write(MSG.format(stream_string, shlex.join(args))) + raise CalledProcessError(cwd, args, MSG.format(stream_string)) return stdout
diff --git a/build/config/android/test/resource_overlay/BUILD.gn b/build/config/android/test/resource_overlay/BUILD.gn index 4a063d22..4cf18ef 100644 --- a/build/config/android/test/resource_overlay/BUILD.gn +++ b/build/config/android/test/resource_overlay/BUILD.gn
@@ -43,7 +43,7 @@ deps = [ ":root_tagged_dependency_resources" ] } -android_library("javatests") { +android_library("unit_device_javatests") { testonly = true sources = [ "java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java",
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc index ed3a8f5..d8a27e3 100644 --- a/cc/paint/paint_image.cc +++ b/cc/paint/paint_image.cc
@@ -71,6 +71,8 @@ return false; if (paint_worklet_input_ != other.paint_worklet_input_) return false; + // Do not check may_be_lcp_candidate_ as it should not affect any rendering + // operation, only metrics collection. return true; } @@ -397,6 +399,7 @@ << " animation_type_: " << static_cast<int>(animation_type_) << " completion_state_: " << static_cast<int>(completion_state_) << " is_multipart_: " << is_multipart_ + << " may_be_lcp_candidate_: " << may_be_lcp_candidate_ << " is YUV: " << IsYuv(SkYUVAPixmapInfo::SupportedDataTypes::All()); return str.str(); }
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index 32cbb7f..859f448 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h
@@ -264,6 +264,7 @@ CompletionState completion_state() const { return completion_state_; } bool is_multipart() const { return is_multipart_; } bool is_high_bit_depth() const { return is_high_bit_depth_; } + bool may_be_lcp_candidate() const { return may_be_lcp_candidate_; } int repetition_count() const { return repetition_count_; } bool ShouldAnimate() const; AnimationSequenceId reset_animation_sequence_id() const { @@ -389,6 +390,12 @@ // Whether this image has more than 8 bits per color channel. bool is_high_bit_depth_ = false; + // Whether this image may untimately be a candidate for Largest Contentful + // Paint. The final LCP contribution of an image is unknown until we present + // it, but this flag is intended for metrics on when we do not present the + // image when the system claims. + bool may_be_lcp_candidate_ = false; + // An incrementing sequence number maintained by the painter to indicate if // this animation should be reset in the compositor. Incrementing this number // will reset this animation in the compositor for the first frame which has a
diff --git a/cc/paint/paint_image_builder.h b/cc/paint/paint_image_builder.h index 008d0fa5..f75c3ff 100644 --- a/cc/paint/paint_image_builder.h +++ b/cc/paint/paint_image_builder.h
@@ -87,6 +87,10 @@ paint_image_.is_high_bit_depth_ = is_high_bit_depth; return std::move(*this); } + PaintImageBuilder&& set_may_be_lcp_candidate(bool may_be_lcp_candidate) { + paint_image_.may_be_lcp_candidate_ = may_be_lcp_candidate; + return std::move(*this); + } PaintImageBuilder&& set_repetition_count(int count) { paint_image_.repetition_count_ = count; return std::move(*this);
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 76bbece9..4e8eaad0 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -475,7 +475,7 @@ gfx::ScaleVector2d(overscroll_offset, 1.f / page_scale_factor()); ClipTree& clip_tree = property_trees()->clip_tree_mutable(); - ClipNode* clip_node = clip_tree.Node(overscroll_node_id_); + ClipNode* clip_node = clip_tree.Node(clip_tree.overscroll_node_id()); if (clip_node) { // Inflate the clip rect based on the overscroll direction. @@ -1265,7 +1265,8 @@ } ClipTree::ClipTree(PropertyTrees* property_trees) - : PropertyTree<ClipNode>(property_trees) {} + : PropertyTree<ClipNode>(property_trees), + overscroll_node_id_(kInvalidPropertyNodeId) {} void ClipTree::SetViewportClip(gfx::RectF viewport_rect) { if (size() < 2) @@ -1285,7 +1286,8 @@ #if DCHECK_IS_ON() bool ClipTree::operator==(const ClipTree& other) const { - return PropertyTree::operator==(other); + return PropertyTree::operator==(other) && + overscroll_node_id_ == other.overscroll_node_id(); } #endif
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 352c3b5..12ecb6e 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -333,6 +333,14 @@ void SetViewportClip(gfx::RectF viewport_rect); gfx::RectF ViewportClip() const; + + void set_overscroll_node_id(int id) { overscroll_node_id_ = id; } + int overscroll_node_id() const { return overscroll_node_id_; } + + private: + // Used to track the ClipNode that is corresponding to the overscroll + // TransformNode. + int overscroll_node_id_; }; class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
diff --git a/cc/trees/property_tree_unittest.cc b/cc/trees/property_tree_unittest.cc index 53b242c..b2ec896d 100644 --- a/cc/trees/property_tree_unittest.cc +++ b/cc/trees/property_tree_unittest.cc
@@ -203,18 +203,13 @@ PropertyTrees property_trees(synchronizer); ClipTree& clip_tree = property_trees.clip_tree_mutable(); - ClipNode root_clip; - root_clip.id = 1; - root_clip.parent_id = 0; - root_clip.clip = gfx::RectF(0, 0, 500, 500); - clip_tree.Insert(root_clip, 0); - const gfx::RectF clip_rect(0, 0, 100, 100); - ClipNode overscroll_clip; - overscroll_clip.id = 2; - overscroll_clip.parent_id = 1; - overscroll_clip.clip = clip_rect; - clip_tree.Insert(overscroll_clip, 1); + ClipNode clip_node; + clip_node.id = 1; + clip_node.parent_id = 0; + clip_node.clip = clip_rect; + clip_tree.Insert(clip_node, 0); + clip_tree.set_overscroll_node_id(clip_node.id); TransformTree& transform_tree = property_trees.transform_tree_mutable(); TransformNode contents_root; @@ -245,7 +240,8 @@ gfx::RectF expected_clip_rect(clip_rect); expected_clip_rect.set_height(clip_rect.height() + overscroll_offset.y()); - EXPECT_EQ(clip_tree.Node(overscroll_node.id)->clip, expected_clip_rect); + EXPECT_EQ(clip_tree.Node(clip_tree.overscroll_node_id())->clip, + expected_clip_rect); } TEST(PropertyTreeTest, TransformsWithFlattening) {
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 29493cb9..775733e 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1109,7 +1109,6 @@ "//components/commerce/core:proto_java", "//components/content_capture/android:java", "//components/content_settings/android:content_settings_enums_java", - "//components/crash/android:junit", "//components/digital_goods/mojom:mojom_java", "//components/dom_distiller/core/android:dom_distiller_core_java", "//components/embedder_support/android:content_view_java", @@ -1366,8 +1365,6 @@ "//components/security_state/core:security_state_enums_java", "//components/signin/public/android:java", "//components/signin/public/android:signin_java_test_support", - "//components/strictmode/android:javatests", - "//components/url_formatter/android:url_formatter_javatests", "//content/public/android:content_full_java", "//content/public/test/android:content_java_test_support", "//third_party/android_deps:espresso_java", @@ -1549,7 +1546,6 @@ "//components/autofill_assistant/android:public_java", "//components/background_task_scheduler:background_task_scheduler_java", "//components/background_task_scheduler:background_task_scheduler_task_ids_java", - "//components/background_task_scheduler/internal:background_task_scheduler_javatests", "//components/bookmarks/common/android:bookmarks_java", "//components/browser_ui/accessibility/android:java", "//components/browser_ui/bottomsheet/android:java", @@ -1578,7 +1574,6 @@ "//components/content_settings/android:content_settings_enums_java", "//components/content_settings/android:java", "//components/crash/android:java", - "//components/crash/android:javatests", "//components/digital_goods/mojom:mojom_java", "//components/dom_distiller/core/android:dom_distiller_core_java", "//components/dom_distiller/core/mojom:mojom_java", @@ -3149,19 +3144,21 @@ shared_libraries = [ ":libchromefortest" ] deps = [ ":chrome_unit_test_java", - "//build/config/android/test/resource_overlay:javatests", + "//build/config/android/test/resource_overlay:unit_device_javatests", "//chrome/android/features/tab_ui:unit_device_javatests", - "//chrome/browser/back_press/android:javatests", + "//chrome/browser/back_press/android:unit_device_javatests", "//chrome/browser/loading_modal/android:unit_device_javatests", - "//chrome/browser/partnercustomizations:javatests", + "//chrome/browser/partnercustomizations:unit_device_javatests", "//chrome/browser/ui/android/appmenu/internal:unit_device_javatests", "//chrome/browser/ui/messages/android:unit_device_javatests", - "//chrome/browser/user_education:javatests", - "//chrome/browser/video_tutorials/internal:javatests", + "//chrome/browser/user_education:unit_device_javatests", + "//chrome/browser/video_tutorials/internal:unit_device_javatests", "//components/browser_ui/widget/android:unit_device_javatests", "//components/embedder_support/android:embedder_support_javatests", "//components/paint_preview/player/android:javatests", - "//components/signin/public/android:javatests", + "//components/signin/public/android:unit_device_javatests", + "//components/strictmode/android:unit_device_javatests", + "//components/url_formatter/android:unit_device_javatests", ] data_deps = [
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index ca1ab4e..0d95e72 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -327,10 +327,8 @@ "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java", - "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java", - "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentBottomSheetTest.java", "javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentControllerTest.java",
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java index 13dda83..ae830628b0 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceBackButtonTest.java
@@ -6,9 +6,6 @@ import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.pressKey; -import static androidx.test.espresso.action.ViewActions.replaceText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withParent; @@ -17,7 +14,6 @@ import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.START_SURFACE_TEST_BASE_PARAMS; import static org.chromium.chrome.features.start_surface.StartSurfaceTestUtils.sClassParamsForStartSurfaceTest; -import static org.chromium.ui.test.util.ViewUtils.VIEW_GONE; import static org.chromium.ui.test.util.ViewUtils.onViewWaiting; import static org.chromium.ui.test.util.ViewUtils.waitForView; @@ -25,14 +21,11 @@ import android.support.test.InstrumentationRegistry; import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; import android.support.test.runner.lifecycle.Stage; -import android.view.KeyEvent; import android.view.View; import androidx.test.espresso.contrib.RecyclerViewActions; -import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; -import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; @@ -65,7 +58,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModel; -import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorTestingRobot; import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; @@ -290,198 +282,6 @@ @Test @MediumTest @Feature({"StartSurface"}) - @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) - // clang-format off - @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) - @DisableIf. - Build(sdk_is_less_than = Build.VERSION_CODES.N, message = "Flaky, see crbug.com/1246457") - public void testShow_SingleAsHomepage_BackButtonOnCarouselTabSwitcher() { - // clang-format on - if (!mImmediateReturn) { - StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); - } - - ChromeTabbedActivity cta = mActivityTestRule.getActivity(); - StartSurfaceTestUtils.waitForOverviewVisible( - mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); - StartSurfaceTestUtils.waitForTabModel(cta); - TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); - - onViewWaiting(withId(R.id.search_box_text)).perform(replaceText("about:blank")); - onView(withId(R.id.url_bar)).perform(pressKey(KeyEvent.KEYCODE_ENTER)); - LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.BROWSING); - TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); - - TabUiTestHelper.mergeAllNormalTabsToAGroup(cta); - StartSurfaceTestUtils.pressHomePageButton(cta); - LayoutTestUtils.waitForLayout(cta.getLayoutManager(), LayoutType.TAB_SWITCHER); - - StartSurfaceTestUtils.clickFirstTabInCarousel(); - onViewWaiting(allOf( - withId(org.chromium.chrome.tab_ui.R.id.dialog_container_view), isDisplayed())); - - StartSurfaceTestUtils.pressBack(mActivityTestRule); - waitForView(withId(org.chromium.chrome.tab_ui.R.id.dialog_container_view), VIEW_GONE); - onView(withId(R.id.primary_tasks_surface_view)).check(matches(isDisplayed())); - } - - @Test - @LargeTest - @Feature({"StartSurface"}) - @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) - @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) - public void testShow_SingleAsHomepage_BackButtonOnTabSwitcherWithDialogShowing() { - backButtonOnTabSwitcherWithDialogShowingImpl(); - } - - @Test - @LargeTest - @Feature({"StartSurface"}) - @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) - @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/show_last_active_tab_only/true"}) - public void testShow_SingleAsHomepageV2_BackButtonOnTabSwitcherWithDialogShowing() { - backButtonOnTabSwitcherWithDialogShowingImpl(); - } - - private void backButtonOnTabSwitcherWithDialogShowingImpl() { - if (!mImmediateReturn) { - StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); - } - - ChromeTabbedActivity cta = mActivityTestRule.getActivity(); - StartSurfaceTestUtils.waitForOverviewVisible( - mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); - StartSurfaceTestUtils.waitForTabModel(cta); - onViewWaiting(withId(R.id.logo)); - - // Launches the first site in mv tiles. - StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1); - - List<Tab> tabs = getTabsInCurrentTabModel(cta.getCurrentTabModel()); - TabSelectionEditorTestingRobot robot = new TabSelectionEditorTestingRobot(); - - if (isInstantReturn()) { - // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar - // omnibox. - return; - } - onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_button)); - TabUiTestHelper.enterTabSwitcher(cta); - - waitForView(withId(R.id.secondary_tasks_surface_view)); - StartSurfaceCoordinator startSurfaceCoordinator = - StartSurfaceTestUtils.getStartSurfaceFromUIThread(cta); - TestThreadUtils.runOnUiThreadBlocking( - () -> startSurfaceCoordinator.showTabSelectionEditorForTesting(tabs)); - robot.resultRobot.verifyTabSelectionEditorIsVisible() - .verifyToolbarActionButtonDisabled() - .verifyToolbarActionButtonWithResourceId( - org.chromium.chrome.tab_ui.R.string.tab_selection_editor_group) - .verifyToolbarSelectionTextWithResourceId( - org.chromium.chrome.tab_ui.R.string - .tab_selection_editor_toolbar_select_tabs) - .verifyAdapterHasItemCount(tabs.size()) - .verifyHasAtLeastNItemVisible(2); - - // Verifies that tapping the back button will close the TabSelectionEditor. - StartSurfaceTestUtils.pressBack(mActivityTestRule); - robot.resultRobot.verifyTabSelectionEditorIsHidden(); - onViewWaiting(withId(R.id.secondary_tasks_surface_view)); - - // Groups the two tabs. - TestThreadUtils.runOnUiThreadBlocking( - () -> startSurfaceCoordinator.showTabSelectionEditorForTesting(tabs)); - robot.resultRobot.verifyToolbarActionButtonWithResourceId( - org.chromium.chrome.tab_ui.R.string.tab_selection_editor_group); - robot.actionRobot.clickItemAtAdapterPosition(0) - .clickItemAtAdapterPosition(1) - .clickToolbarActionButton(); - robot.resultRobot.verifyTabSelectionEditorIsHidden(); - - // Opens the TabGridDialog by clicking the first group card. - onViewWaiting(Matchers.allOf(withParent(withId(R.id.tasks_surface_body)), - withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))) - .perform(RecyclerViewActions.actionOnItemAtPosition(0, click())); - CriteriaHelper.pollUiThread(() -> isTabGridDialogShown(cta)); - - // Verifies that the TabGridDialog is closed by tapping back button. - StartSurfaceTestUtils.pressBack(mActivityTestRule); - CriteriaHelper.pollUiThread(() -> isTabGridDialogHidden(cta)); - onViewWaiting(withId(R.id.secondary_tasks_surface_view)); - } - - @Test - @LargeTest - @Feature({"StartSurface"}) - @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) - @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) - public void testShow_SingleAsHomepage_BackButtonOnHomepageWithGroupTabsDialog() { - backButtonOnHomepageWithGroupTabsDialogImpl(); - } - - @Test - @LargeTest - @Feature({"StartSurface"}) - @EnableFeatures(ChromeFeatureList.TAB_GROUPS_ANDROID) - @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS + "/show_last_active_tab_only/true"}) - public void testShow_SingleAsHomepageV2_BackButtonOnHomepageWithGroupTabsDialog() { - backButtonOnHomepageWithGroupTabsDialogImpl(); - } - - private void backButtonOnHomepageWithGroupTabsDialogImpl() { - if (!mImmediateReturn) { - StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); - } - - ChromeTabbedActivity cta = mActivityTestRule.getActivity(); - StartSurfaceTestUtils.waitForOverviewVisible( - mLayoutChangedCallbackHelper, mCurrentlyActiveLayout); - StartSurfaceTestUtils.waitForTabModel(cta); - onViewWaiting(withId(R.id.logo)); - - // Launches the first site in MV tiles to create the second tab for grouping. - StartSurfaceTestUtils.launchFirstMVTile(cta, /* currentTabCount = */ 1); - - // When show_last_active_tab_only is enabled, we need to enter the tab switcher first to - // initialize the secondary task surface which shows the TabSelectionEditor dialog. - onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.tab_switcher_button)); - if (isInstantReturn()) { - // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar - // omnibox. - return; - } - TabUiTestHelper.enterTabSwitcher(cta); - waitForView(withId(R.id.secondary_tasks_surface_view)); - List<Tab> tabs = getTabsInCurrentTabModel(cta.getCurrentTabModel()); - TabSelectionEditorTestingRobot robot = new TabSelectionEditorTestingRobot(); - - // Enters the homepage, and shows the TabSelectionEditor dialog. - StartSurfaceTestUtils.pressHomePageButton(cta); - waitForView(withId(R.id.primary_tasks_surface_view)); - - StartSurfaceCoordinator startSurfaceCoordinator = - StartSurfaceTestUtils.getStartSurfaceFromUIThread(cta); - TestThreadUtils.runOnUiThreadBlocking( - () -> startSurfaceCoordinator.showTabSelectionEditorForTesting(tabs)); - robot.resultRobot.verifyTabSelectionEditorIsVisible() - .verifyToolbarActionButtonDisabled() - .verifyToolbarActionButtonWithResourceId( - org.chromium.chrome.tab_ui.R.string.tab_selection_editor_group) - .verifyToolbarSelectionTextWithResourceId( - org.chromium.chrome.tab_ui.R.string - .tab_selection_editor_toolbar_select_tabs) - .verifyAdapterHasItemCount(tabs.size()) - .verifyHasAtLeastNItemVisible(2); - - // Verifies that tapping the back button will close the TabSelectionEditor. - StartSurfaceTestUtils.pressBack(mActivityTestRule); - robot.resultRobot.verifyTabSelectionEditorIsHidden(); - onViewWaiting(withId(R.id.primary_tasks_surface_view)); - } - - @Test - @MediumTest - @Feature({"StartSurface"}) @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) public void testOpenRecentTabOnStartAndTapBackButtonReturnToStartSurface() throws ExecutionException {
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 2d516c7..d45021b 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -413,6 +413,7 @@ @MediumTest @Feature({"StartSurface"}) @CommandLineFlags.Add({START_SURFACE_TEST_BASE_PARAMS}) + @DisabledTest(message = "crbug.com/1170673 - NoInstant_NoReturn version is flaky") public void testSearchInSingleSurface() { if (!mImmediateReturn) { StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java index 532afe8337..4e97586 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -48,13 +48,11 @@ import android.content.res.Configuration; import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Build.VERSION_CODES; import android.support.test.InstrumentationRegistry; import android.view.View; -import android.widget.ImageView; import androidx.annotation.Nullable; import androidx.recyclerview.widget.GridLayoutManager; @@ -65,6 +63,7 @@ import androidx.test.espresso.ViewAssertion; import androidx.test.espresso.contrib.AccessibilityChecks; import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; import androidx.test.uiautomator.UiDevice; @@ -104,6 +103,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tab.TabStateExtractor; +import org.chromium.chrome.browser.tab.TabUtils; import org.chromium.chrome.browser.tabmodel.IncognitoTabHostUtils; import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel; @@ -111,6 +111,7 @@ import org.chromium.chrome.browser.tasks.pseudotab.PseudoTab; import org.chromium.chrome.browser.tasks.pseudotab.TabAttributeCache; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; +import org.chromium.chrome.browser.tasks.tab_management.TabGridThumbnailView; import org.chromium.chrome.browser.tasks.tab_management.TabProperties; import org.chromium.chrome.browser.tasks.tab_management.TabSelectionEditorTestingRobot; import org.chromium.chrome.browser.tasks.tab_management.TabSuggestionMessageService; @@ -1106,26 +1107,33 @@ } @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study"}) - @CommandLineFlags.Add({BASE_PARAMS}) + @LargeTest + // clang-format off + @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study", + ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID + "<Study"}) + @CommandLineFlags.Add({BASE_PARAMS + "/enable_launch_polish/true"}) @DisabledTest(message = "https://crbug.com/1122657") public void testThumbnailAspectRatio_default() { - prepareTabs(2, 0, mUrl); + // clang-format on + prepareTabs(2, 0, "about:blank"); enterTabSwitcher(mActivityTestRule.getActivity()); - onView(tabSwitcherViewMatcher()) - .check(ThumbnailAspectRatioAssertion.havingAspectRatio(1.0)); + onViewWaiting(tabSwitcherViewMatcher()) + .check(ThumbnailAspectRatioAssertion.havingAspectRatio( + TabUtils.getTabThumbnailAspectRatio(mActivityTestRule.getActivity()))); } @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study"}) - @CommandLineFlags.Add({BASE_PARAMS + "/thumbnail_aspect_ratio/0.75"}) + @LargeTest + // clang-format off + @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study", + ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID + "<Study"}) + @CommandLineFlags.Add({BASE_PARAMS + "/thumbnail_aspect_ratio/0.75/enable_launch_polish/true"}) @DisabledTest(message = "https://crbug.com/1122657") public void testThumbnailAspectRatio_point75() { - prepareTabs(2, 0, mUrl); + // clang-format on + prepareTabs(2, 0, "about:blank"); enterTabSwitcher(mActivityTestRule.getActivity()); - onView(tabSwitcherViewMatcher()) + onViewWaiting(tabSwitcherViewMatcher()) .check(ThumbnailAspectRatioAssertion.havingAspectRatio(0.75)); leaveGTSAndVerifyThumbnailsAreReleased(); @@ -1133,19 +1141,25 @@ mActivityTestRule.loadUrlInTab( NTP_URL, PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR, tab); enterTabSwitcher(mActivityTestRule.getActivity()); - onView(tabSwitcherViewMatcher()) + onViewWaiting(tabSwitcherViewMatcher()) .check(ThumbnailAspectRatioAssertion.havingAspectRatio(0.75)); } @Test - @MediumTest - @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study"}) - @CommandLineFlags.Add({BASE_PARAMS + "/thumbnail_aspect_ratio/2.0/allow_to_refetch/true"}) + @LargeTest + // clang-format off + @EnableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study", + ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID + "<Study"}) + @CommandLineFlags.Add({BASE_PARAMS + + "/thumbnail_aspect_ratio/2.0/allow_to_refetch/true/enable_launch_polish/true"}) @DisabledTest(message = "Flaky - https://crbug.com/1124041") public void testThumbnailAspectRatio_fromTwoToPoint75() throws Exception { - prepareTabs(2, 0, mUrl); + // clang-format on + prepareTabs(2, 0, "about:blank"); + // Select the first tab to ensure the second tab thumbnail is captured. + ChromeTabUtils.switchTabInCurrentTabModel(mActivityTestRule.getActivity(), 0); enterTabSwitcher(mActivityTestRule.getActivity()); - onView(tabSwitcherViewMatcher()) + onViewWaiting(tabSwitcherViewMatcher()) .check(ThumbnailAspectRatioAssertion.havingAspectRatio(2.0)); TabModel currentTabModel = mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel(); @@ -1158,7 +1172,7 @@ verifyAllThumbnailHasAspectRatio(0.75); enterTabSwitcher(mActivityTestRule.getActivity()); - onView(tabSwitcherViewMatcher()) + onViewWaiting(tabSwitcherViewMatcher()) .check(ThumbnailAspectRatioAssertion.havingAspectRatio(2.0)); TabUiTestHelper.finishActivity(mActivityTestRule.getActivity()); } @@ -1591,22 +1605,25 @@ RecyclerView recyclerView = (RecyclerView) view; RecyclerView.Adapter adapter = recyclerView.getAdapter(); + boolean hasAtLeastOneValidViewHolder = false; for (int i = 0; i < adapter.getItemCount(); i++) { RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(i); if (viewHolder != null) { + hasAtLeastOneValidViewHolder = true; ViewLookupCachingFrameLayout tabView = (ViewLookupCachingFrameLayout) viewHolder.itemView; - ImageView thumbnail = (ImageView) tabView.fastFindViewById(R.id.tab_thumbnail); - BitmapDrawable drawable = (BitmapDrawable) thumbnail.getDrawable(); - Bitmap bitmap = drawable.getBitmap(); - double bitmapRatio = bitmap.getWidth() * 1.0 / bitmap.getHeight(); - assertTrue( - "Actual ratio: " + bitmapRatio + "; Expected ratio: " + mExpectedRatio, - Math.abs(bitmapRatio - mExpectedRatio) + TabGridThumbnailView thumbnail = + (TabGridThumbnailView) tabView.fastFindViewById(R.id.tab_thumbnail); + double thumbnailViewRatio = thumbnail.getWidth() * 1.0 / thumbnail.getHeight(); + + assertTrue("Actual ratio: " + thumbnailViewRatio + + "; Expected ratio: " + mExpectedRatio, + Math.abs(thumbnailViewRatio - mExpectedRatio) <= TabContentManager.ASPECT_RATIO_PRECISION); } } + assertTrue("should have at least one valid ViewHolder", hasAtLeastOneValidViewHolder); } }
diff --git a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java index fc05c3f5..a627b2c5b 100644 --- a/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java +++ b/chrome/android/features/start_surface/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -1443,6 +1443,106 @@ StartSurfaceState.SHOWN_HOMEPAGE, mediator.getStartSurfaceState()); } + /** + * Tests the logic of StartSurfaceMediator#onBackPressedInternal() when the Start surface is + * showing but Tab switcher hasn't been created yet. + */ + @Test + public void testBackPressHandlerOnStartSurfaceWithoutTabSwitcherCreated() { + doReturn(false).when(mTabModelSelector).isIncognitoSelected(); + doReturn(false).when(mTabModelSelector).isIncognitoSelected(); + doReturn(mVoiceRecognitionHandler).when(mOmniboxStub).getVoiceRecognitionHandler(); + doReturn(true).when(mVoiceRecognitionHandler).isVoiceSearchEnabled(); + StartSurfaceMediator mediator = + createStartSurfaceMediator(/*isStartSurfaceEnabled=*/true, false); + + mediator.setStartSurfaceState(StartSurfaceState.SHOWN_HOMEPAGE); + Assert.assertEquals(StartSurfaceState.SHOWN_HOMEPAGE, mediator.getStartSurfaceState()); + + doReturn(true).when(mMainTabGridController).isDialogVisible(); + mediator.onBackPressed(); + verify(mMainTabGridController).onBackPressed(true); + + doReturn(false).when(mMainTabGridController).isDialogVisible(); + mediator.onBackPressed(); + verify(mMainTabGridController, times(2)).onBackPressed(true); + } + + /** + * Tests the logic of StartSurfaceMediator#onBackPressedInternal() when the Start surface is + * showing and the Tab switcher has been created. + */ + @Test + public void testBackPressHandlerOnStartSurfaceWithTabSwitcherCreated() { + doReturn(false).when(mTabModelSelector).isIncognitoSelected(); + doReturn(false).when(mTabModelSelector).isIncognitoSelected(); + doReturn(mVoiceRecognitionHandler).when(mOmniboxStub).getVoiceRecognitionHandler(); + doReturn(true).when(mVoiceRecognitionHandler).isVoiceSearchEnabled(); + + StartSurfaceMediator mediator = + createStartSurfaceMediator(/*isStartSurfaceEnabled=*/true, false); + mediator.setSecondaryTasksSurfacePropertyModel(mSecondaryTasksSurfacePropertyModel); + mediator.setSecondaryTasksSurfaceController(mSecondaryTasksSurfaceController); + + mediator.setStartSurfaceState(StartSurfaceState.SHOWN_HOMEPAGE); + Assert.assertEquals(StartSurfaceState.SHOWN_HOMEPAGE, mediator.getStartSurfaceState()); + + doReturn(true).when(mMainTabGridController).isDialogVisible(); + doReturn(true).when(mSecondaryTasksSurfaceController).isDialogVisible(); + mediator.onBackPressed(); + verify(mMainTabGridController, never()).onBackPressed(true); + verify(mSecondaryTasksSurfaceController, + description("Secondary task surface has a higher priority of handling back press")) + .onBackPressed(true); + + doReturn(true).when(mMainTabGridController).isDialogVisible(); + doReturn(false).when(mSecondaryTasksSurfaceController).isDialogVisible(); + mediator.onBackPressed(); + verify(mMainTabGridController).onBackPressed(true); + + doReturn(false).when(mMainTabGridController).isDialogVisible(); + doReturn(false).when(mSecondaryTasksSurfaceController).isDialogVisible(); + mediator.onBackPressed(); + verify(mMainTabGridController, times(2)).onBackPressed(true); + } + + /** + * Tests the logic of StartSurfaceMediator#onBackPressedInternal() when the Tab switcher is + * showing. + */ + @Test + public void testBackPressHandlerOnTabSwitcher() { + doReturn(false).when(mTabModelSelector).isIncognitoSelected(); + doReturn(false).when(mTabModelSelector).isIncognitoSelected(); + doReturn(mVoiceRecognitionHandler).when(mOmniboxStub).getVoiceRecognitionHandler(); + doReturn(true).when(mVoiceRecognitionHandler).isVoiceSearchEnabled(); + + StartSurfaceMediator mediator = + createStartSurfaceMediator(/*isStartSurfaceEnabled=*/true, false); + mediator.setSecondaryTasksSurfacePropertyModel(mSecondaryTasksSurfacePropertyModel); + mediator.setSecondaryTasksSurfaceController(mSecondaryTasksSurfaceController); + + mediator.setStartSurfaceState(StartSurfaceState.SHOWN_TABSWITCHER); + Assert.assertEquals(StartSurfaceState.SHOWN_TABSWITCHER, mediator.getStartSurfaceState()); + // The primary task surface is invisible when showing the Tab Switcher. + doReturn(false).when(mMainTabGridController).isDialogVisible(); + + doReturn(true).when(mSecondaryTasksSurfaceController).isDialogVisible(); + mediator.onBackPressed(); + verify(mMainTabGridController, never()).onBackPressed(false); + verify(mSecondaryTasksSurfaceController).onBackPressed(false); + + doReturn(false).when(mSecondaryTasksSurfaceController).isDialogVisible(); + verify(mSecondaryTasksSurfaceController).onBackPressed(false); + + mediator.setStartSurfaceState(StartSurfaceState.SHOWN_HOMEPAGE); + mediator.setStartSurfaceState(StartSurfaceState.SHOWN_TABSWITCHER); + Assert.assertEquals(StartSurfaceState.SHOWN_TABSWITCHER, mediator.getStartSurfaceState()); + mediator.onBackPressed(); + Assert.assertEquals("Should return to home page on back press.", + StartSurfaceState.SHOWN_HOMEPAGE, mediator.getStartSurfaceState()); + } + private StartSurfaceMediator createStartSurfaceMediator( boolean isStartSurfaceEnabled, boolean excludeMVTiles) { return createStartSurfaceMediator(
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index b429175..802453e 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -237,7 +237,10 @@ android_library("unit_device_javatests") { testonly = true - sources = [ "javatests/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardViewBinderTest.java" ] + sources = [ + "javatests/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardViewBinderTest.java", + "javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java", + ] deps = [ ":java", @@ -246,8 +249,11 @@ "//chrome/android/features/tab_ui:java", "//chrome/browser/tab:java", "//chrome/test/android:chrome_java_test_support_common", + "//components/browser_ui/widget/android:java", "//content/public/test/android:content_java_test_support", + "//third_party/android_sdk:android_test_base_java", "//third_party/androidx:androidx_appcompat_appcompat_resources_java", + "//third_party/androidx:androidx_recyclerview_recyclerview_java", "//third_party/androidx:androidx_test_runner_java", "//third_party/junit:junit", "//ui/android:ui_java_test_support",
diff --git a/chrome/android/features/tab_ui/DEPS b/chrome/android/features/tab_ui/DEPS index 79eedc5..8f96d0f 100644 --- a/chrome/android/features/tab_ui/DEPS +++ b/chrome/android/features/tab_ui/DEPS
@@ -18,4 +18,5 @@ "+components/search_engines/android/java/src/org/chromium/components/search_engines", "+components/module_installer", "+content/public/android/java/src/org/chromium/content_public/browser", + "+content/public/android/java/src/org/chromium/content_public/common", ]
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java index c9eb47e..62cd832 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -305,7 +305,7 @@ // Add 400px top margin to the recyclerView. RecyclerView recyclerView = cta.findViewById(R.id.tab_list_view); - float tabGridCardPadding = TabUiThemeProvider.getTabCardPaddingDimension(cta); + float tabGridCardPadding = TabUiThemeProvider.getTabGridCardMargin(cta); int deltaTopMargin = 400; ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) recyclerView.getLayoutParams(); @@ -1132,19 +1132,20 @@ if (noMatchException != null) throw noMatchException; Assert.assertTrue(v instanceof ListView); ListView listView = (ListView) v; + int menuItemCount = 1; verifyTabGridDialogToolbarMenuItem(listView, 0, cta.getString(R.string.tab_grid_dialog_toolbar_remove_from_group)); if (TabUiFeatureUtilities.ENABLE_TAB_GROUP_SHARING.getValue()) { - verifyTabGridDialogToolbarMenuItem(listView, 1, + menuItemCount += 1; + verifyTabGridDialogToolbarMenuItem(listView, menuItemCount - 1, cta.getString(R.string.tab_grid_dialog_toolbar_share_group)); } if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { - assertEquals(3, listView.getCount()); - verifyTabGridDialogToolbarMenuItem(listView, 2, + menuItemCount += 1; + verifyTabGridDialogToolbarMenuItem(listView, menuItemCount - 1, cta.getString(R.string.tab_grid_dialog_toolbar_edit_group_name)); - } else { - assertEquals(2, listView.getCount()); } + assertEquals(menuItemCount, listView.getCount()); }); }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java index 357c7026..2a036c4 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java
@@ -44,6 +44,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.test.espresso.NoMatchingRootException; +import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; import org.junit.Before; @@ -55,7 +56,6 @@ import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.compositor.layouts.Layout; @@ -100,6 +100,7 @@ public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus() .setBugComponent(ChromeRenderTestRule.Component.UI_BROWSER_MOBILE_TAB_GROUPS) + .setRevision(1) .build(); @Before @@ -130,13 +131,13 @@ } @Test - @MediumTest + @LargeTest @Feature({"RenderTest"}) - @FlakyTest(message = "https://crbug.com/1208386") + @DisabledTest(message = "https://crbug.com/1208386") public void testRenderStrip_Select5thTabIn10Tabs() throws IOException { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); AtomicReference<RecyclerView> recyclerViewReference = new AtomicReference<>(); - createTabs(cta, false, 10); + TabUiTestHelper.addBlankTabs(cta, false, 9); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 10); mergeAllNormalTabsToAGroup(cta); @@ -155,13 +156,13 @@ } @Test - @MediumTest + @LargeTest @Feature({"RenderTest"}) - @FlakyTest(message = "https://crbug.com/1208386") + @DisabledTest(message = "https://crbug.com/1208386") public void testRenderStrip_Select10thTabIn10Tabs() throws IOException { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); AtomicReference<RecyclerView> recyclerViewReference = new AtomicReference<>(); - createTabs(cta, false, 10); + TabUiTestHelper.addBlankTabs(cta, false, 9); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 10); mergeAllNormalTabsToAGroup(cta); @@ -180,13 +181,13 @@ } @Test - @MediumTest + @LargeTest @Feature({"RenderTest"}) - @FlakyTest(message = "https://crbug.com/1208386") + @DisabledTest(message = "https://crbug.com/1208386") public void testRenderStrip_AddTab() throws IOException { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); AtomicReference<RecyclerView> recyclerViewReference = new AtomicReference<>(); - createTabs(cta, false, 10); + TabUiTestHelper.addBlankTabs(cta, false, 9); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 10); mergeAllNormalTabsToAGroup(cta);
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMultiWindowTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMultiWindowTest.java index 2e84f97..d7b5059 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMultiWindowTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMultiWindowTest.java
@@ -13,7 +13,6 @@ import static org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper.waitForSecondChromeTabbedActivity; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.clickFirstCardFromTabSwitcher; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.clickFirstTabInDialog; -import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.createTabs; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.enterTabSwitcher; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.mergeAllIncognitoTabsToAGroup; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.mergeAllNormalTabsToAGroup; @@ -26,6 +25,7 @@ import android.support.test.InstrumentationRegistry; import androidx.annotation.RequiresApi; +import androidx.test.filters.LargeTest; import androidx.test.filters.MediumTest; import org.junit.Before; @@ -35,7 +35,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; @@ -65,7 +64,7 @@ @Before public void setUp() { - mActivityTestRule.startMainActivityFromLauncher(); + mActivityTestRule.startMainActivityOnBlankPage(); Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout(); assertTrue(layout instanceof TabSwitcherAndStartSurfaceLayout); CriteriaHelper.pollUiThread( @@ -73,14 +72,14 @@ } @Test - @MediumTest + @LargeTest @RequiresApi(Build.VERSION_CODES.N) - @DisabledTest(message = "https://crbug.com/1231616") public void testMoveTabsAcrossWindow_GTS_WithoutGroup() { final ChromeTabbedActivity cta1 = mActivityTestRule.getActivity(); - // Initially, we have 4 normal tabs and 3 incognito tabs in cta1. - createTabs(cta1, false, 4); - createTabs(cta1, true, 3); + // Initially, we have 4 normal tabs (including the one created at activity start) and 3 + // incognito tabs in cta1. + TabUiTestHelper.addBlankTabs(cta1, false, 3); + TabUiTestHelper.addBlankTabs(cta1, true, 3); verifyTabModelTabCount(cta1, 4, 3); // Enter tab switcher in cta1 in incognito mode. @@ -156,16 +155,16 @@ } @Test - @MediumTest + @LargeTest @RequiresApi(Build.VERSION_CODES.N) @Features. EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID, ChromeFeatureList.TAB_REPARENTING}) - @DisabledTest(message = "https://crbug.com/1163569") public void testMoveTabsAcrossWindow_GTS_WithGroup() { - // Initially, we have 5 normal tabs and 5 incognito tabs in cta1. + // Initially, we have 5 normal tabs (including the one created at activity start) and 5 + // incognito tabs in cta1. final ChromeTabbedActivity cta1 = mActivityTestRule.getActivity(); - createTabs(cta1, false, 5); - createTabs(cta1, true, 5); + TabUiTestHelper.addBlankTabs(cta1, false, 4); + TabUiTestHelper.addBlankTabs(cta1, true, 5); verifyTabModelTabCount(cta1, 5, 5); // Enter tab switcher in cta1 in incognito mode. @@ -249,10 +248,9 @@ ChromeFeatureList.TAB_REPARENTING}) public void testMoveLastIncognitoTab() { // clang-format on - // Initially, we have 1 normal tab and 1 incognito tab in cta1. + // Initially, we have 1 normal tab (created in #setup()) and 1 incognito tab in cta1. final ChromeTabbedActivity cta1 = mActivityTestRule.getActivity(); - createTabs(cta1, false, 1); - createTabs(cta1, true, 1); + TabUiTestHelper.addBlankTabs(cta1, true, 1); verifyTabModelTabCount(cta1, 1, 1); // Move the incognito tab to cta2.
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java index bc46bdc..aed34e5 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
@@ -60,6 +60,7 @@ import org.chromium.chrome.browser.layouts.LayoutTestUtils; import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tasks.pseudotab.PseudoTab; @@ -67,7 +68,9 @@ import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; +import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.content_public.common.ContentUrlConstants; import java.io.File; import java.lang.annotation.Retention; @@ -104,6 +107,23 @@ } /** + * Open additional tabs for the provided activity. The added tabs will be opened to + * "about:blank" and will not wait for the page to finish loading. + * @param cta The activity to add the tabs to. + * @param incognito Whether the tabs should be incognito. + * @param count The number of tabs to create. + */ + public static void addBlankTabs(ChromeTabbedActivity cta, boolean incognito, int count) { + for (int i = 0; i < count; i++) { + TestThreadUtils.runOnUiThreadBlocking(() -> { + cta.getTabCreator(incognito).createNewTab( + new LoadUrlParams(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL), + TabLaunchType.FROM_CHROME_UI, null); + }); + } + } + + /** * Enter tab switcher from a tab page. * @param cta The current running activity. */
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni index 898b42a..550520d 100644 --- a/chrome/android/features/tab_ui/tab_management_java_sources.gni +++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -43,7 +43,6 @@ "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java", - "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index a86c788..6b911908 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -94,6 +94,7 @@ add(ChromeFeatureList.FEED_LOADING_PLACEHOLDER); add(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS); add(ChromeFeatureList.IMMERSIVE_UI_MODE); + add(ChromeFeatureList.INCOGNITO_REAUTHENTICATION_FOR_ANDROID); add(ChromeFeatureList.INSTANT_START); add(ChromeFeatureList.INSTANCE_SWITCHER); add(ChromeFeatureList.INTEREST_FEED_V2);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java index 0ee12c7..89fd504 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
@@ -624,7 +624,7 @@ mNavbar.animate().alpha(1.f).setDuration(NAVBAR_FADE_DURATION_MS); } } else { - mNavbar.animate().alpha(0.f).setDuration(NAVBAR_FADE_DURATION_MS); + if (mNavbar != null) mNavbar.animate().alpha(0.f).setDuration(NAVBAR_FADE_DURATION_MS); } showNavbarButtons(show); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java index 0e55075a1..aeab8a3b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTest.java
@@ -22,9 +22,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.params.ParameterAnnotations; -import org.chromium.base.test.params.ParameterSet; -import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; @@ -32,18 +29,15 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.UrlUtils; -import org.chromium.chrome.R; import org.chromium.chrome.browser.download.DownloadTestRule.CustomMainActivityStart; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.OTRProfileID; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel; -import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeTabUtils; -import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.download.DownloadState; import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.offline_items_collection.FailState; @@ -51,6 +45,7 @@ import org.chromium.components.offline_items_collection.OfflineItem.Progress; import org.chromium.components.offline_items_collection.PendingState; import org.chromium.components.offline_items_collection.UpdateDelta; +import org.chromium.components.policy.test.annotations.Policies; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.test.util.DOMUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -61,21 +56,14 @@ import org.chromium.url.GURL; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** * Tests Chrome download feature by attempting to download some files. */ -@RunWith(ParameterizedRunner.class) -@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) +@RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class DownloadTest implements CustomMainActivityStart { - @ParameterAnnotations.ClassParameter - private static List<ParameterSet> sClassParams = Arrays.asList( - new ParameterSet().value(true).name("UseDownloadOfflineContentProviderEnabled"), - new ParameterSet().value(false).name("UseDownloadOfflineContentProviderDisabled")); - @Rule public DownloadTestRule mDownloadTestRule = new DownloadTestRule(this); @@ -99,8 +87,6 @@ FILENAME_GZIP }; - private boolean mUseDownloadOfflineContentProvider; - static class DownloadManagerRequestInterceptorForTest implements DownloadManagerService.DownloadManagerRequestInterceptor { public DownloadItem mDownloadItem; @@ -180,10 +166,6 @@ void resumeDownload(Intent intent) {} } - public DownloadTest(boolean useDownloadOfflineContentProvider) { - mUseDownloadOfflineContentProvider = useDownloadOfflineContentProvider; - } - @Before public void setUp() { deleteTestFiles(); @@ -201,11 +183,6 @@ @Override public void customMainActivityStart() throws InterruptedException { - if (mUseDownloadOfflineContentProvider) { - Features.getInstance().enable(ChromeFeatureList.DOWNLOAD_OFFLINE_CONTENT_PROVIDER); - } else { - Features.getInstance().disable(ChromeFeatureList.DOWNLOAD_OFFLINE_CONTENT_PROVIDER); - } mDownloadTestRule.startMainActivityOnBlankPage(); } @@ -266,19 +243,15 @@ @Test @MediumTest @Feature({"Downloads"}) - @DisabledTest(message = "crbug.com/147904") + @Policies.Add({ @Policies.Item(key = "PromptForDownloadLocation", string = "false") }) public void testCloseEmptyDownloadTab() throws Exception { mDownloadTestRule.loadUrl(mTestServer.getURL(TEST_DOWNLOAD_DIRECTORY + "get.html")); waitForFocus(); final int initialTabCount = mDownloadTestRule.getActivity().getCurrentTabModel().getCount(); + int currentCallCount = mDownloadTestRule.getChromeDownloadCallCount(); View currentView = mDownloadTestRule.getActivity().getActivityTab().getView(); - TouchCommon.longPressView(currentView); - - int callCount = mDownloadTestRule.getChromeDownloadCallCount(); - InstrumentationRegistry.getInstrumentation().invokeContextMenuAction( - mDownloadTestRule.getActivity(), R.id.contextmenu_open_in_new_tab, 0); - Assert.assertTrue(mDownloadTestRule.waitForChromeDownloadToFinish(callCount)); - Assert.assertTrue(mDownloadTestRule.hasDownload(FILENAME_GZIP, null)); + TouchCommon.singleClickView(currentView); + Assert.assertTrue(mDownloadTestRule.waitForChromeDownloadToFinish(currentCallCount)); CriteriaHelper.pollUiThread(() -> { Criteria.checkThat(mDownloadTestRule.getActivity().getCurrentTabModel().getCount(),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorTest.java index d9f8dac2..d111e007 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorTest.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.omnibox.suggestions.base; -import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; @@ -27,10 +26,11 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconFetchCompleteListener; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconType; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; -import org.chromium.components.favicon.LargeIconBridge; -import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; import org.chromium.ui.modelutil.PropertyModel; @@ -44,14 +44,10 @@ public class BaseSuggestionProcessorTest { private class TestBaseSuggestionProcessor extends BaseSuggestionViewProcessor { private final Context mContext; - private final LargeIconBridge mLargeIconBridge; - private final Runnable mRunable; - public TestBaseSuggestionProcessor(Context context, SuggestionHost suggestionHost, - LargeIconBridge largeIconBridge, Runnable runable) { - super(context, suggestionHost); + public TestBaseSuggestionProcessor( + Context context, SuggestionHost suggestionHost, FaviconFetcher faviconFetcher) { + super(context, suggestionHost, faviconFetcher); mContext = context; - mLargeIconBridge = largeIconBridge; - mRunable = runable; } @Override @@ -74,16 +70,12 @@ super.populateModel(suggestion, model, position); setSuggestionDrawableState(model, SuggestionDrawableState.Builder.forBitmap(mContext, mDefaultBitmap).build()); - fetchSuggestionFavicon(model, suggestion.getUrl(), mLargeIconBridge, mRunable); + fetchSuggestionFavicon(model, suggestion.getUrl()); } } - @Mock - SuggestionHost mSuggestionHost; - @Mock - LargeIconBridge mIconBridge; - @Mock - Runnable mRunnable; + private @Mock SuggestionHost mSuggestionHost; + private @Mock FaviconFetcher mFaviconFetcher; private TestBaseSuggestionProcessor mProcessor; private AutocompleteMatch mSuggestion; @@ -96,7 +88,7 @@ MockitoAnnotations.initMocks(this); mBitmap = Bitmap.createBitmap(1, 1, Config.ALPHA_8); mProcessor = new TestBaseSuggestionProcessor( - ContextUtils.getApplicationContext(), mSuggestionHost, mIconBridge, mRunnable); + ContextUtils.getApplicationContext(), mSuggestionHost, mFaviconFetcher); } /** @@ -111,15 +103,15 @@ @Test @SmallTest public void suggestionFavicons_showFaviconWhenAvailable() { - final ArgumentCaptor<LargeIconCallback> callback = - ArgumentCaptor.forClass(LargeIconCallback.class); + final ArgumentCaptor<FaviconFetchCompleteListener> callback = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); final GURL url = new GURL("http://url"); createSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, url); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); - verify(mIconBridge).getLargeIconForUrl(eq(url), anyInt(), callback.capture()); - callback.getValue().onLargeIconAvailable(mBitmap, 0, false, 0); + verify(mFaviconFetcher).fetchFaviconWithBackoff(eq(url), eq(false), callback.capture()); + callback.getValue().onFaviconFetchComplete(mBitmap, FaviconType.REGULAR); SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon2); @@ -130,15 +122,15 @@ @Test @SmallTest public void suggestionFavicons_doNotReplaceFallbackIconWhenNoFaviconIsAvailable() { - final ArgumentCaptor<LargeIconCallback> callback = - ArgumentCaptor.forClass(LargeIconCallback.class); + final ArgumentCaptor<FaviconFetchCompleteListener> callback = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); final GURL url = new GURL("http://url"); createSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, url); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); - verify(mIconBridge).getLargeIconForUrl(eq(url), anyInt(), callback.capture()); - callback.getValue().onLargeIconAvailable(null, 0, false, 0); + verify(mFaviconFetcher).fetchFaviconWithBackoff(eq(url), eq(false), callback.capture()); + callback.getValue().onFaviconFetchComplete(null, FaviconType.NONE); SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon2);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java index ba2536d..a2b12fd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionUnitTest.java
@@ -32,6 +32,7 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.UrlBarDelegate; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties; @@ -43,7 +44,6 @@ import org.chromium.chrome.browser.tab.SadTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.util.browser.Features; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.content_public.browser.test.NativeLibraryTestUtils; @@ -108,7 +108,7 @@ private View mSuggestionView; @Mock - private LargeIconBridge mIconBridge; + private FaviconFetcher mIconFetcher; @Mock private TemplateUrlService mTemplateUrlService; @@ -140,8 +140,8 @@ mModel = new PropertyModel.Builder(SuggestionViewProperties.ALL_KEYS).build(); mProcessor = new EditUrlSuggestionProcessor(ContextUtils.getApplicationContext(), - mSuggestionHost, mUrlBarDelegate, - () -> mIconBridge, () -> mTab, () -> mShareDelegate); + mSuggestionHost, mUrlBarDelegate, mIconFetcher, + () -> mTab, () -> mShareDelegate); }); doReturn(mTestUrl).when(mTab).getUrl();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java index 119b326..1c4dc664 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java
@@ -184,7 +184,11 @@ @Test @UiThreadTest @SmallTest - public void testReceiveNewTilesWithDataChanges() { + @DisabledTest( + message = + "https://crbug.com/1330627, https://crbug.com/1293208, https://crbug.com/1336742") + public void + testReceiveNewTilesWithDataChanges() { TileGroup tileGroup = initialiseTileGroup(URLS); // Notify the about different URLs, but the same number. #onTileCountChanged() should not be
diff --git a/chrome/app/chrome_exe_main_win.cc b/chrome/app/chrome_exe_main_win.cc index 5ba728c0..b3672a15 100644 --- a/chrome/app/chrome_exe_main_win.cc +++ b/chrome/app/chrome_exe_main_win.cc
@@ -19,6 +19,7 @@ #include "base/command_line.h" #include "base/containers/cxx20_erase.h" #include "base/debug/alias.h" +#include "base/debug/handle_hooks_win.h" #include "base/feature_list.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -31,6 +32,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" +#include "base/win/current_module.h" #include "base/win/registry.h" #include "base/win/win_util.h" #include "base/win/windows_version.h" @@ -300,12 +302,20 @@ const std::string process_type = command_line->GetSwitchValueASCII(switches::kProcessType); +#if !defined(COMPONENT_BUILD) && DCHECK_IS_ON() // In non-component mode, chrome.exe contains a separate instance of // base::FeatureList. Prevent accidental use of this here by forbidding use of // the one that's linked with chrome.exe. -#if !defined(COMPONENT_BUILD) && DCHECK_IS_ON() base::FeatureList::ForbidUseForCurrentModule(); -#endif + + // Patch the main EXE on non-component builds when DCHECKs are enabled. + // This allows detection of third party code that might attempt to meddle with + // Chrome's handles. This must be done when single-threaded to avoid other + // threads attempting to make calls through the hooks while they are being + // emplaced. + // Note: The DLL is patched separately, in chrome/app/chrome_main.cc. + base::debug::HandleHooks::AddIATPatch(CURRENT_MODULE()); +#endif // !defined(COMPONENT_BUILD) && !DCHECK_IS_ON() // Confirm that an explicit prefetch profile is used for all process types // except for the browser process. Any new process type will have to assign
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc index 2a517628..e67ea60 100644 --- a/chrome/app/chrome_main.cc +++ b/chrome/app/chrome_main.cc
@@ -32,6 +32,9 @@ #if BUILDFLAG(IS_WIN) #include "base/allocator/buildflags.h" +#include "base/dcheck_is_on.h" +#include "base/debug/handle_hooks_win.h" +#include "base/win/current_module.h" #if BUILDFLAG(USE_ALLOCATOR_SHIM) #include "base/allocator/allocator_shim.h" #endif @@ -90,7 +93,16 @@ base::UmaHistogramEnumeration("Windows.ChromeDllPrefetchResult", prefetch_result_code); install_static::InitializeFromPrimaryModule(); -#endif +#if !defined(COMPONENT_BUILD) && DCHECK_IS_ON() + // Patch the main EXE on non-component builds when DCHECKs are enabled. + // This allows detection of third party code that might attempt to meddle with + // Chrome's handles. This must be done when single-threaded to avoid other + // threads attempting to make calls through the hooks while they are being + // emplaced. + // Note: The EXE is patched separately, in chrome/app/chrome_exe_main_win.cc. + base::debug::HandleHooks::AddIATPatch(CURRENT_MODULE()); +#endif // !defined(COMPONENT_BUILD) && DCHECK_IS_ON() +#endif // BUILDFLAG(IS_WIN) ChromeMainDelegate chrome_main_delegate( base::TimeTicks::FromInternalValue(exe_entry_point_ticks));
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 34f6e3d..e958565 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -2517,13 +2517,13 @@ desc="Footer link in the Download Bubble"> Show all downloads </message> - <message name="IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SEPERATOR" - desc="A separator to place between download size and download time. A symbol, in this case a bullet •, with a white space before it and a white space after it, is used to separate them. If the bullet • resembles another symbol in the language, please translate the bullet • as a symbol (A) that is not easily mistaken for a number or letter in the language and (B) that is typically used to separate elements."> - ''' • ''' + <message name="IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR" + desc="The download status and message are separated by a symbol, in this case bullet •, with a white space before it and a white space after it. If the bullet • resembles another symbol in the language, please translate the bullet • as a symbol (A) that is not easily mistaken for a number or letter in the language and (B) that is typically used to separate elements."> + <ph name="STATUS">$1<ex>100/120 MB</ex></ph> • <ph name="MESSAGE">$2<ex>Opening in 10 seconds...</ex></ph> </message> - <message name="IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SYMBOL" - desc="A symbol for active downloads, in this case downward arrow ↓. If the downward arrow ↓ resembles another symbol in the language, please translate the downward arrow ↓ as a symbol that indicates a downward arrow"> - '''↓ ''' + <message name="IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_WITH_SYMBOL" + desc="Active downloads have a symbol associated with them, in this case a downward arrow ↓. If the downward arrow ↓ resembles another symbol in the language, please translate the downward arrow ↓ as a symbol that indicates a downward arrow"> + ↓ <ph name="STATUS">$1<ex>100/120 MB</ex></ph> </message> <message name="IDS_DOWNLOAD_BUBBLE_STATUS_RESUMING" desc="When resuming a download, let the user know we're resuming the download.">
diff --git a/chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SEPERATOR.png.sha1 b/chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR.png.sha1 similarity index 100% rename from chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SEPERATOR.png.sha1 rename to chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR.png.sha1
diff --git a/chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SYMBOL.png.sha1 b/chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_WITH_SYMBOL.png.sha1 similarity index 100% rename from chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SYMBOL.png.sha1 rename to chrome/app/generated_resources_grd/IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_WITH_SYMBOL.png.sha1
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 1493ebf..74aa267 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4147,14 +4147,8 @@ "sharing/click_to_call/click_to_call_ui_controller.h", "sharing/shared_clipboard/remote_copy_message_handler.cc", "sharing/shared_clipboard/remote_copy_message_handler.h", - "sharing/shared_clipboard/shared_clipboard_context_menu_observer.cc", - "sharing/shared_clipboard/shared_clipboard_context_menu_observer.h", "sharing/shared_clipboard/shared_clipboard_message_handler_desktop.cc", "sharing/shared_clipboard/shared_clipboard_message_handler_desktop.h", - "sharing/shared_clipboard/shared_clipboard_ui_controller.cc", - "sharing/shared_clipboard/shared_clipboard_ui_controller.h", - "sharing/shared_clipboard/shared_clipboard_utils.cc", - "sharing/shared_clipboard/shared_clipboard_utils.h", "sharing/sharing_app.cc", "sharing/sharing_app.h", "sharing/sharing_dialog.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 85de9ef..990f7433 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -6443,6 +6443,12 @@ kOsMac | kOsLinux | kOsLacros | kOsWin | kOsFuchsia, SINGLE_VALUE_TYPE(switches::kEnableUnsafeWebGPU)}, + {"enable-webgpu-developer-features", + flag_descriptions::kWebGpuDeveloperFeaturesName, + flag_descriptions::kWebGpuDeveloperFeaturesDescription, + kOsMac | kOsLinux | kOsLacros | kOsWin | kOsFuchsia, + SINGLE_VALUE_TYPE(switches::kEnableWebGPUDeveloperFeatures)}, + #if BUILDFLAG(IS_ANDROID) {"autofill-use-mobile-label-disambiguation", flag_descriptions::kAutofillUseMobileLabelDisambiguationName,
diff --git a/chrome/browser/accessibility/live_caption_controller_browsertest.cc b/chrome/browser/accessibility/live_caption_controller_browsertest.cc index 53210ab..56838e6c 100644 --- a/chrome/browser/accessibility/live_caption_controller_browsertest.cc +++ b/chrome/browser/accessibility/live_caption_controller_browsertest.cc
@@ -109,7 +109,7 @@ void OnErrorOnProfile(Profile* profile) { GetControllerForProfile(profile)->OnError( - GetCaptionBubbleContextBrowser(), CaptionBubbleErrorType::GENERIC, + GetCaptionBubbleContextBrowser(), CaptionBubbleErrorType::kGeneric, base::RepeatingClosure(), base::BindRepeating( [](CaptionBubbleErrorType error_type, bool checked) {}));
diff --git a/chrome/browser/accessibility/live_caption_speech_recognition_host.cc b/chrome/browser/accessibility/live_caption_speech_recognition_host.cc index d85cba76..09109800 100644 --- a/chrome/browser/accessibility/live_caption_speech_recognition_host.cc +++ b/chrome/browser/accessibility/live_caption_speech_recognition_host.cc
@@ -75,7 +75,7 @@ LiveCaptionController* live_caption_controller = GetLiveCaptionController(); if (live_caption_controller) live_caption_controller->OnError( - context_.get(), CaptionBubbleErrorType::GENERIC, + context_.get(), CaptionBubbleErrorType::kGeneric, base::RepeatingClosure(), base::BindRepeating( [](CaptionBubbleErrorType error_type, bool checked) {}));
diff --git a/chrome/browser/accessibility/live_caption_unavailability_notifier.cc b/chrome/browser/accessibility/live_caption_unavailability_notifier.cc index a0e813a..cca178ea 100644 --- a/chrome/browser/accessibility/live_caption_unavailability_notifier.cc +++ b/chrome/browser/accessibility/live_caption_unavailability_notifier.cc
@@ -133,7 +133,7 @@ // received from another audio stream. live_caption_controller->OnError( context_.get(), - CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED, + CaptionBubbleErrorType::kMediaFoundationRendererUnsupported, base::BindRepeating(&LiveCaptionUnavailabilityNotifier:: OnMediaFoundationRendererErrorClicked, weak_factory_.GetWeakPtr()),
diff --git a/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc b/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc index 45a39d48..e18fa2b 100644 --- a/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc +++ b/chrome/browser/accessibility/live_caption_unavailability_notifier_unittest.cc
@@ -33,7 +33,7 @@ void OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked( bool checked) { notifier_->OnMediaFoundationRendererErrorDoNotShowAgainCheckboxClicked( - CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED, checked); + CaptionBubbleErrorType::kMediaFoundationRendererUnsupported, checked); } protected:
diff --git a/chrome/browser/android/chrome_backup_agent.cc b/chrome/browser/android/chrome_backup_agent.cc index 9850236c..37f44b3 100644 --- a/chrome/browser/android/chrome_backup_agent.cc +++ b/chrome/browser/android/chrome_backup_agent.cc
@@ -20,7 +20,7 @@ // TODO(crbug.com/1305213): The data type toggles shouldn't be individually // listed here. -static_assert(39 == syncer::GetNumModelTypes(), +static_assert(40 == syncer::GetNumModelTypes(), "If the new type has a corresponding pref, add it here"); const char* backed_up_preferences_[] = { autofill::prefs::kAutofillWalletImportEnabled,
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 6d2eefe..12402bfbb 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -1597,6 +1597,7 @@ "//chromeos/dbus/userdataauth", "//chromeos/dbus/util", "//chromeos/dbus/virtual_file_provider", + "//chromeos/dbus/vm_plugin_dispatcher", "//chromeos/ime:gencode", "//chromeos/login/login_state", "//chromeos/services/assistant/public/cpp",
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc index ebfc53f4..b57a1bc 100644 --- a/chrome/browser/ash/accessibility/dictation_browsertest.cc +++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -1309,11 +1309,11 @@ "Hello, world! Good afternoon; good evening? Goodnight, world.", "Hello, world! Good afternoon; good evening? Goodnight, world."); RunHiddenMacro(/*DELETE_PREV_SENT*/ 18); - WaitForTextAreaValue("Hello, world! Good afternoon; good evening? "); + WaitForTextAreaValue("Hello, world! Good afternoon; good evening?"); RunHiddenMacro(/*DELETE_PREV_SENT*/ 18); - WaitForTextAreaValue("Hello, world! Good afternoon; "); + WaitForTextAreaValue("Hello, world! Good afternoon;"); RunHiddenMacro(/*DELETE_PREV_SENT*/ 18); - WaitForTextAreaValue("Hello, world! "); + WaitForTextAreaValue("Hello, world!"); } IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, DeletePrevSentTwoSentences) { @@ -1322,7 +1322,7 @@ SendFinalResultAndWaitForTextAreaValue("Hello, world. Goodnight, world.", "Hello, world. Goodnight, world."); RunHiddenMacro(/*DELETE_PREV_SENT*/ 18); - WaitForTextAreaValue("Hello, world. "); + WaitForTextAreaValue("Hello, world."); } IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, @@ -1335,7 +1335,7 @@ SendFinalResultAndWaitForCaretBoundsChanged("Move to the Previous character"); SendFinalResultAndWaitForCaretBoundsChanged("Move to the Previous character"); RunHiddenMacro(/*DELETE_PREV_SENT*/ 18); - WaitForTextAreaValue("Hello, world. d."); + WaitForTextAreaValue("Hello, world.d."); } IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, MoveByWord) { @@ -1431,6 +1431,20 @@ SendFinalResultAndWaitForTextAreaValue("delete", "This ."); } +IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, MoveBySentence) { + ToggleDictationWithKeystroke(); + WaitForRecognitionStarted(); + SendFinalResultAndWaitForTextAreaValue("Hello world! Goodnight world?", + "Hello world! Goodnight world?"); + RunMacroAndWaitForCaretBoundsChanged(/*NAV_PREV_SENT*/ 26); + SendFinalResultAndWaitForTextAreaValue( + "Good evening.", "Hello world! Good evening. Goodnight world?"); + RunMacroAndWaitForCaretBoundsChanged(/*NAV_NEXT_SENT*/ 25); + SendFinalResultAndWaitForTextAreaValue( + "Time for a midnight snack", + "Hello world! Good evening. Goodnight world? Time for a midnight snack"); +} + // Tests behavior of Dictation and installation of Pumpkin. class DictationPumpkinInstallTest : public DictationTest { protected:
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_util.h b/chrome/browser/ash/crosapi/browser_data_migrator_util.h index 50d2ef3..315665ff5 100644 --- a/chrome/browser/ash/crosapi/browser_data_migrator_util.h +++ b/chrome/browser/ash/crosapi/browser_data_migrator_util.h
@@ -295,7 +295,7 @@ }; // List of data types in Sync Data that have to stay in Ash and Ash only. -static_assert(39 == syncer::GetNumModelTypes(), +static_assert(40 == syncer::GetNumModelTypes(), "If adding a new sync data type, update the lists below if" " you want to keep the new data type in Ash only."); constexpr syncer::ModelType kAshOnlySyncDataTypes[] = { @@ -304,6 +304,7 @@ syncer::ModelType::OS_PREFERENCES, syncer::ModelType::OS_PRIORITY_PREFERENCES, syncer::ModelType::PRINTERS, + syncer::ModelType::PRINTERS_AUTHORIZATION_SERVERS, syncer::ModelType::WIFI_CONFIGURATIONS, syncer::ModelType::WORKSPACE_DESK, };
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc index 5a776eef..bd2184c 100644 --- a/chrome/browser/ash/crostini/ansible/ansible_management_service.cc +++ b/chrome/browser/ash/crostini/ansible/ansible_management_service.cc
@@ -58,7 +58,7 @@ std::move(callback).Run(false); return; } - if (container_id == ContainerId::GetDefault() && + if (container_id == DefaultContainerId() && !ShouldConfigureDefaultContainer(profile_)) { LOG(ERROR) << "Trying to configure default Crostini container when it " << "should not be configured"; @@ -251,7 +251,7 @@ const ContainerId& container_id, bool success) { DCHECK_GT(configuration_tasks_.count(container_id), 0); - if (success && container_id == ContainerId::GetDefault()) { + if (success && container_id == DefaultContainerId()) { profile_->GetPrefs()->SetBoolean(prefs::kCrostiniDefaultContainerConfigured, true); }
diff --git a/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc b/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc index 54db9ae..3b7211e 100644 --- a/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc +++ b/chrome/browser/ash/crostini/ansible/ansible_management_service_unittest.cc
@@ -147,7 +147,7 @@ vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED); ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&AnsibleManagementServiceTest::ExpectTrueResult, @@ -160,7 +160,7 @@ vm_tools::cicerone::InstallLinuxPackageResponse::FAILED); ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult, @@ -174,7 +174,7 @@ SetInstallAnsibleStatus(false); ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult, @@ -189,7 +189,7 @@ vm_tools::cicerone::ApplyAnsiblePlaybookResponse::FAILED); ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult, @@ -205,7 +205,7 @@ SetApplyAnsibleStatus(false); ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult, @@ -221,12 +221,12 @@ vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED); ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&ExpectResult, base::BindLambdaForTesting([&]() { ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&AnsibleManagementServiceTest::ExpectFalseResult, @@ -243,7 +243,7 @@ // Unsuccessful sequence of events. ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&ExpectResult, base::BindLambdaForTesting([&]() { @@ -253,7 +253,7 @@ test_helper_->SetUpPlaybookApplication( vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED); ansible_management_service()->ConfigureContainer( - ContainerId::GetDefault(), + DefaultContainerId(), profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath), base::BindOnce(&AnsibleManagementServiceTest::ExpectTrueResult,
diff --git a/chrome/browser/ash/crostini/crostini_export_import.cc b/chrome/browser/ash/crostini/crostini_export_import.cc index bece978..90284cac 100644 --- a/chrome/browser/ash/crostini/crostini_export_import.cc +++ b/chrome/browser/ash/crostini/crostini_export_import.cc
@@ -128,7 +128,7 @@ CrostiniExportImport::OperationData* CrostiniExportImport::NewOperationData( ExportImportType type) { - return NewOperationData(type, ContainerId::GetDefault()); + return NewOperationData(type, DefaultContainerId()); } void CrostiniExportImport::ExportContainer(ContainerId container_id,
diff --git a/chrome/browser/ash/crostini/crostini_installer.cc b/chrome/browser/ash/crostini/crostini_installer.cc index 1f4b5157..cc575f6 100644 --- a/chrome/browser/ash/crostini/crostini_installer.cc +++ b/chrome/browser/ash/crostini/crostini_installer.cc
@@ -626,7 +626,7 @@ if (!skip_launching_terminal_for_testing_) { // kInvalidDisplayId will launch terminal on the current active display. crostini::LaunchTerminal(profile_, display::kInvalidDisplayId, - crostini::ContainerId::GetDefault()); + crostini::DefaultContainerId()); } } @@ -665,7 +665,7 @@ restart_id_ = crostini::CrostiniManager::GetForProfile(profile_) ->RestartCrostiniWithOptions( - crostini::ContainerId::GetDefault(), std::move(restart_options_), + crostini::DefaultContainerId(), std::move(restart_options_), base::BindOnce(&CrostiniInstaller::OnCrostiniRestartFinished, weak_ptr_factory_.GetWeakPtr()), this);
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc index 52fecc8..a34a8ea 100644 --- a/chrome/browser/ash/crostini/crostini_manager.cc +++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -535,7 +535,7 @@ // Additional setup might be required in case of default Crostini container // such as installing Ansible in default container and applying // pre-determined configuration to the default container. - if (container_id_ == ContainerId::GetDefault() && + if (container_id_ == DefaultContainerId() && ShouldConfigureDefaultContainer(profile_)) { requests_[0].options.ansible_playbook = profile_->GetPrefs()->GetFilePath( prefs::kCrostiniAnsiblePlaybookFilePath); @@ -555,7 +555,7 @@ // it's possible in tests to end up here without a running container. Don't // try mounting sshfs in that case. auto info = crostini_manager_->GetContainerInfo(container_id_); - if (container_id_ == ContainerId::GetDefault() && info) { + if (container_id_ == DefaultContainerId() && info) { crostini_manager_->MountCrostiniFiles(container_id_, base::DoNothing(), true); } @@ -1168,7 +1168,7 @@ // Already shown the upgrade dialog. return false; } - if (container_id != ContainerId::GetDefault()) { + if (container_id != DefaultContainerId()) { return false; } bool upgradable = IsContainerUpgradeable(container_id); @@ -2561,7 +2561,7 @@ // The UI can only resize the default VM, so only (maybe) show the // notification for the default VM, if we got a value, and if the value isn't // an error (the API we call for space returns -1 on error). - if (vm_name == ContainerId::GetDefault().vm_name && + if (vm_name == DefaultContainerId().vm_name && response->free_bytes_has_value() && response->free_bytes() >= 0) { low_disk_notifier_->ShowNotificationIfAppropriate(response->free_bytes()); } @@ -3866,8 +3866,8 @@ void CrostiniManager::SuspendImminent( power_manager::SuspendImminent::Reason reason) { - auto info = GetContainerInfo(ContainerId::GetDefault()); - if (!crostini_sshfs_->IsSshfsMounted(ContainerId::GetDefault())) { + auto info = GetContainerInfo(DefaultContainerId()); + if (!crostini_sshfs_->IsSshfsMounted(DefaultContainerId())) { return; } @@ -3875,7 +3875,7 @@ auto token = base::UnguessableToken::Create(); chromeos::PowerManagerClient::Get()->BlockSuspend(token, "CrostiniManager"); crostini_sshfs_->UnmountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManager::OnRemoveSshfsCrostiniVolume, weak_ptr_factory_.GetWeakPtr(), token)); } @@ -3883,7 +3883,7 @@ void CrostiniManager::SuspendDone(base::TimeDelta sleep_duration) { // https://crbug.com/968060. Sshfs is unmounted before suspend, // call RestartCrostini to force remount if container is running. - ContainerId container_id = ContainerId::GetDefault(); + ContainerId container_id = DefaultContainerId(); if (GetContainerInfo(container_id)) { // TODO(crbug/1142321): Double-check if anything breaks if we change this // to just remount the sshfs mounts, in particular check 9p mounts. @@ -3903,7 +3903,7 @@ void CrostiniManager::RemoveUncleanSshfsMounts() { // TODO(crbug/1142321): Success metrics - crostini_sshfs_->UnmountCrostiniFiles(ContainerId::GetDefault(), + crostini_sshfs_->UnmountCrostiniFiles(DefaultContainerId(), base::DoNothing()); }
diff --git a/chrome/browser/ash/crostini/crostini_manager_unittest.cc b/chrome/browser/ash/crostini/crostini_manager_unittest.cc index 0de6899..56714d2 100644 --- a/chrome/browser/ash/crostini/crostini_manager_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
@@ -523,7 +523,7 @@ EnsureTerminaInstalled(); crostini_manager()->StartTerminaVm( - ContainerId::GetDefault().vm_name, disk_path, {}, 0, + DefaultContainerId().vm_name, disk_path, {}, 0, base::BindOnce(&ExpectSuccess, run_loop()->QuitClosure())); run_loop()->Run(); @@ -545,7 +545,7 @@ EnsureTerminaInstalled(); crostini_manager()->StartTerminaVm( - ContainerId::GetDefault().vm_name, disk_path, {}, 0, + DefaultContainerId().vm_name, disk_path, {}, 0, base::BindOnce(&ExpectSuccess, run_loop()->QuitClosure())); run_loop()->Run(); @@ -1165,7 +1165,7 @@ TEST_F(CrostiniManagerRestartTest, CancelOnContainerCreated) { cancel_on_container_created_ = true; restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1180,7 +1180,7 @@ fake_cicerone_client_->set_send_create_lxd_container_response_delay( base::TimeDelta::Max()); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1194,7 +1194,7 @@ fake_cicerone_client_->set_send_notify_lxd_container_created_signal_delay( base::TimeDelta::Max()); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1210,12 +1210,12 @@ fake_cicerone_client_->set_send_notify_lxd_container_created_signal_delay( base::TimeDelta::Max()); vm_tools::cicerone::LxdContainerDownloadingSignal signal; - signal.set_container_name(ContainerId::GetDefault().container_name); - signal.set_vm_name(ContainerId::GetDefault().vm_name); + signal.set_container_name(DefaultContainerId().container_name); + signal.set_vm_name(DefaultContainerId().vm_name); signal.set_owner_id(CryptohomeIdForProfile(profile())); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1239,7 +1239,7 @@ fake_cicerone_client_->set_lxd_container_created_signal_status( vm_tools::cicerone::LxdContainerCreatedSignal::UNKNOWN); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(), CrostiniResult::UNKNOWN_ERROR), this); @@ -1254,7 +1254,7 @@ TEST_F(CrostiniManagerRestartTest, CancelOnContainerStarted) { cancel_on_container_started_ = true; restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1268,7 +1268,7 @@ TEST_F(CrostiniManagerRestartTest, CancelOnContainerSetup) { cancel_on_container_setup_ = true; restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1283,7 +1283,7 @@ fake_cicerone_client_->set_send_set_up_lxd_container_user_response_delay( base::TimeDelta::Max()); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1299,7 +1299,7 @@ fake_cicerone_client_->set_send_start_lxd_container_response_delay( base::TimeDelta::Max()); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1313,7 +1313,7 @@ fake_cicerone_client_->set_send_container_started_signal_delay( base::TimeDelta::Max()); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -1330,13 +1330,13 @@ fake_cicerone_client_->set_send_container_started_signal_delay( base::TimeDelta::Max()); vm_tools::cicerone::LxdContainerStartingSignal signal; - signal.set_container_name(ContainerId::GetDefault().container_name); - signal.set_vm_name(ContainerId::GetDefault().vm_name); + signal.set_container_name(DefaultContainerId().container_name); + signal.set_vm_name(DefaultContainerId().vm_name); signal.set_owner_id(CryptohomeIdForProfile(profile())); signal.set_status(vm_tools::cicerone::LxdContainerStartingSignal::STARTING); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -2036,7 +2036,7 @@ response); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -2062,7 +2062,7 @@ response); restart_id_ = crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, base::Unretained(this), run_loop()->QuitClosure()), this); @@ -2424,7 +2424,7 @@ vm_tools::cicerone::InstallLinuxPackageResponse::FAILED); crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(), CrostiniResult::CONTAINER_CONFIGURATION_FAILED), this); @@ -2438,7 +2438,7 @@ SetInstallAnsibleStatus(false); crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(), CrostiniResult::CONTAINER_CONFIGURATION_FAILED), this); @@ -2453,7 +2453,7 @@ vm_tools::cicerone::ApplyAnsiblePlaybookResponse::FAILED); crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(), CrostiniResult::CONTAINER_CONFIGURATION_FAILED), this); @@ -2470,7 +2470,7 @@ SetApplyAnsibleStatus(false); crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(), CrostiniResult::CONTAINER_CONFIGURATION_FAILED), this); @@ -2485,7 +2485,7 @@ vm_tools::cicerone::ApplyAnsiblePlaybookResponse::STARTED); crostini_manager()->RestartCrostini( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(), CrostiniResult::SUCCESS), this);
diff --git a/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc b/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc index 344685e..5f7afc21 100644 --- a/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_package_notification_unittest.cc
@@ -71,8 +71,8 @@ CrostiniPackageNotification notification( profile_.get(), CrostiniPackageNotification::NotificationType::PACKAGE_INSTALL, - PackageOperationStatus::RUNNING, ContainerId::GetDefault(), - std::u16string(), kNotificationId, service_.get()); + PackageOperationStatus::RUNNING, DefaultContainerId(), std::u16string(), + kNotificationId, service_.get()); notification.UpdateProgress(PackageOperationStatus::SUCCEEDED, 100); EXPECT_EQ(notification.GetButtonCountForTesting(), 0); @@ -82,8 +82,8 @@ CrostiniPackageNotification notification( profile_.get(), CrostiniPackageNotification::NotificationType::PACKAGE_INSTALL, - PackageOperationStatus::RUNNING, ContainerId::GetDefault(), - std::u16string(), kNotificationId, service_.get()); + PackageOperationStatus::RUNNING, DefaultContainerId(), std::u16string(), + kNotificationId, service_.get()); auto app = CrostiniTestHelper::BasicApp(kDefaultAppFileId); crostini_test_helper_->AddApp(app); @@ -96,8 +96,8 @@ CrostiniPackageNotification notification( profile_.get(), CrostiniPackageNotification::NotificationType::PACKAGE_INSTALL, - PackageOperationStatus::RUNNING, ContainerId::GetDefault(), - std::u16string(), kNotificationId, service_.get()); + PackageOperationStatus::RUNNING, DefaultContainerId(), std::u16string(), + kNotificationId, service_.get()); auto app = CrostiniTestHelper::BasicApp(kDefaultAppFileId); crostini_test_helper_->AddApp(app);
diff --git a/chrome/browser/ash/crostini/crostini_package_service_unittest.cc b/chrome/browser/ash/crostini/crostini_package_service_unittest.cc index 854e3a3..122f21f 100644 --- a/chrome/browser/ash/crostini/crostini_package_service_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_package_service_unittest.cc
@@ -1023,7 +1023,7 @@ TEST_F(CrostiniPackageServiceTest, UninstallNotificationWaitsForAppListUpdate) { service_->QueueUninstallApplication(kDefaultAppId); - SendAppListUpdateSignal(ContainerId::GetDefault(), 1); + SendAppListUpdateSignal(DefaultContainerId(), 1); StartAndSignalUninstall(UninstallPackageProgressSignal::SUCCEEDED); @@ -1033,7 +1033,7 @@ UnorderedElementsAre( IsUninstallWaitingForAppListNotification(DEFAULT_APP))); - SendAppListUpdateSignal(ContainerId::GetDefault(), 0); + SendAppListUpdateSignal(DefaultContainerId(), 0); EXPECT_THAT( Printable(notification_display_service_->GetDisplayedNotificationsForType( @@ -1045,7 +1045,7 @@ UninstallNotificationDoesntWaitForAppListUpdate) { service_->QueueUninstallApplication(kDefaultAppId); - SendAppListUpdateSignal(ContainerId::GetDefault(), 0); + SendAppListUpdateSignal(DefaultContainerId(), 0); StartAndSignalUninstall(UninstallPackageProgressSignal::SUCCEEDED); @@ -1054,7 +1054,7 @@ NotificationHandler::Type::TRANSIENT)), UnorderedElementsAre(IsUninstallSuccessNotification(DEFAULT_APP))); - SendAppListUpdateSignal(ContainerId::GetDefault(), 1); + SendAppListUpdateSignal(DefaultContainerId(), 1); EXPECT_THAT( Printable(notification_display_service_->GetDisplayedNotificationsForType( @@ -1710,7 +1710,7 @@ TEST_F(CrostiniPackageServiceTest, InstallDisplaysProgressNotificationOnStart) { base::RunLoop run_loop; service_->QueueInstallLinuxPackage( - ContainerId::GetDefault(), package_file_url_, + DefaultContainerId(), package_file_url_, base::BindOnce(&ExpectedCrostiniResult, run_loop.QuitClosure(), CrostiniResult::SUCCESS)); run_loop.Run(); @@ -1723,8 +1723,8 @@ TEST_F(CrostiniPackageServiceTest, InstallUpdatesProgressNotificationOnDownloadingSignal) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); StartAndSignalInstall(InstallLinuxPackageProgressSignal::DOWNLOADING, 44 /*progress_percent*/); @@ -1737,8 +1737,8 @@ TEST_F(CrostiniPackageServiceTest, InstallUpdatesProgressNotificationOnInstallingSignal) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); StartAndSignalInstall(InstallLinuxPackageProgressSignal::INSTALLING, 44 /*progress_percent*/); @@ -1751,8 +1751,8 @@ TEST_F(CrostiniPackageServiceTest, InstallDisplaysSuccessNotificationOnSuccessSignal) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); StartAndSignalInstall(InstallLinuxPackageProgressSignal::SUCCEEDED); EXPECT_THAT( @@ -1763,8 +1763,8 @@ TEST_F(CrostiniPackageServiceTest, InstallDisplaysFailureNotificationOnFailedSignal) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); StartAndSignalInstall(InstallLinuxPackageProgressSignal::FAILED); EXPECT_THAT( @@ -1774,11 +1774,11 @@ } TEST_F(CrostiniPackageServiceTest, InstallNotificationWaitsForAppListUpdate) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); base::RunLoop().RunUntilIdle(); - SendAppListUpdateSignal(ContainerId::GetDefault(), 1); + SendAppListUpdateSignal(DefaultContainerId(), 1); StartAndSignalInstall(InstallLinuxPackageProgressSignal::SUCCEEDED); @@ -1787,7 +1787,7 @@ NotificationHandler::Type::TRANSIENT)), UnorderedElementsAre(IsInstallWaitingForAppListNotification())); - SendAppListUpdateSignal(ContainerId::GetDefault(), 0); + SendAppListUpdateSignal(DefaultContainerId(), 0); EXPECT_THAT( Printable(notification_display_service_->GetDisplayedNotificationsForType( @@ -1797,11 +1797,11 @@ TEST_F(CrostiniPackageServiceTest, InstallNotificationDoesntWaitForAppListUpdate) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); base::RunLoop().RunUntilIdle(); - SendAppListUpdateSignal(ContainerId::GetDefault(), 0); + SendAppListUpdateSignal(DefaultContainerId(), 0); StartAndSignalInstall(InstallLinuxPackageProgressSignal::SUCCEEDED); @@ -1810,7 +1810,7 @@ NotificationHandler::Type::TRANSIENT)), UnorderedElementsAre(IsInstallSuccessNotification())); - SendAppListUpdateSignal(ContainerId::GetDefault(), 1); + SendAppListUpdateSignal(DefaultContainerId(), 1); EXPECT_THAT( Printable(notification_display_service_->GetDisplayedNotificationsForType( @@ -1822,8 +1822,8 @@ InstallNotificationAppListUpdatesAreVmSpecific) { InstallLinuxPackageRequest request; - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); request = fake_cicerone_client_->get_most_recent_install_linux_package_request(); InstallLinuxPackageProgressSignal signal_progress = @@ -1855,8 +1855,8 @@ TEST_F(CrostiniPackageServiceTest, InstallNotificationAppListUpdatesFromUnknownContainersAreIgnored) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); base::RunLoop().RunUntilIdle(); @@ -1872,8 +1872,8 @@ } TEST_F(CrostiniPackageServiceTest, InstallNotificationFailsOnVmShutdown) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); base::RunLoop().RunUntilIdle(); @@ -1897,8 +1897,8 @@ } TEST_F(CrostiniPackageServiceTest, UninstallsQueuesBehindStartingUpInstall) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); service_->QueueUninstallApplication(kDefaultAppId); // Install doesn't show a notification until it gets a response, but uninstall @@ -1913,7 +1913,7 @@ TEST_F(CrostiniPackageServiceTest, InstallRunsInFrontOfQueuedUninstall) { base::RunLoop run_loop; service_->QueueInstallLinuxPackage( - ContainerId::GetDefault(), package_file_url_, + DefaultContainerId(), package_file_url_, base::BindOnce(&ExpectedCrostiniResult, run_loop.QuitClosure(), CrostiniResult::SUCCESS)); service_->QueueUninstallApplication(kDefaultAppId); @@ -1932,8 +1932,8 @@ } TEST_F(CrostiniPackageServiceTest, QueuedUninstallRunsAfterCompletedInstall) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); service_->QueueUninstallApplication(kDefaultAppId); StartAndSignalInstall(InstallLinuxPackageProgressSignal::SUCCEEDED); @@ -1957,8 +1957,8 @@ response.set_status(InstallLinuxPackageResponse::FAILED); response.set_failure_reason("No such file"); fake_cicerone_client_->set_install_linux_package_response(response); - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); service_->QueueUninstallApplication(kDefaultAppId); UninstallPackageOwningFileRequest request; @@ -1978,8 +1978,8 @@ TEST_F(CrostiniPackageServiceTest, QueuedUninstallRunsAfterFailedInstallSignal) { - service_->QueueInstallLinuxPackage(ContainerId::GetDefault(), - package_file_url_, base::DoNothing()); + service_->QueueInstallLinuxPackage(DefaultContainerId(), package_file_url_, + base::DoNothing()); service_->QueueUninstallApplication(kDefaultAppId); StartAndSignalInstall(InstallLinuxPackageProgressSignal::FAILED);
diff --git a/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc b/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc index 909d694..fa29a5f4 100644 --- a/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_port_forwarder_unittest.cc
@@ -31,7 +31,7 @@ class CrostiniPortForwarderTest : public testing::Test { public: CrostiniPortForwarderTest() - : default_container_id_(ContainerId::GetDefault()), + : default_container_id_(DefaultContainerId()), other_container_id_(ContainerId("other", "other")), inactive_container_id_(ContainerId("inactive", "inactive")) {}
diff --git a/chrome/browser/ash/crostini/crostini_sshfs.cc b/chrome/browser/ash/crostini/crostini_sshfs.cc index 34a4067..2871348fa 100644 --- a/chrome/browser/ash/crostini/crostini_sshfs.cc +++ b/chrome/browser/ash/crostini/crostini_sshfs.cc
@@ -97,7 +97,7 @@ return; } - if (container_id != ContainerId::GetDefault()) { + if (container_id != DefaultContainerId()) { LOG(ERROR) << "Unable to mount files for non-default container"; Finish(CrostiniSshfsResult::kNotDefaultContainer); return;
diff --git a/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc b/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc index 5639234..ec14b228 100644 --- a/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_sshfs_unittest.cc
@@ -167,12 +167,12 @@ }; TEST_F(CrostiniSshfsHelperTest, MountDiskMountsDisk) { - SetContainerRunning(ContainerId::GetDefault()); + SetContainerRunning(DefaultContainerId()); ExpectMountCalls(1); bool result = false; crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting([&result](bool res) { result = res; }), true); task_environment_.RunUntilIdle(); @@ -193,7 +193,7 @@ EXPECT_CALL(*disk_manager_, MountPath).Times(0); crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting([&result](bool res) { result = res; }), false); task_environment_.RunUntilIdle(); @@ -240,17 +240,17 @@ } TEST_F(CrostiniSshfsHelperTest, MultipleCallsAreQueuedAndOnlyMountOnce) { - SetContainerRunning(ContainerId::GetDefault()); + SetContainerRunning(DefaultContainerId()); ExpectMountCalls(1); int successes = 0; crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting( [&successes](bool result) { successes += result; }), false); crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting( [&successes](bool result) { successes += result; }), false); @@ -270,7 +270,7 @@ } TEST_F(CrostiniSshfsHelperTest, CanRemountAfterUnmount) { - SetContainerRunning(ContainerId::GetDefault()); + SetContainerRunning(DefaultContainerId()); ExpectMountCalls(2); EXPECT_CALL(*disk_manager_, UnmountPath) .WillOnce(testing::Invoke( @@ -281,15 +281,15 @@ })); crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting([](bool res) { EXPECT_TRUE(res); }), false); task_environment_.RunUntilIdle(); crostini_sshfs_->UnmountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting([](bool res) { EXPECT_TRUE(res); })); task_environment_.RunUntilIdle(); crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting([](bool res) { EXPECT_TRUE(res); }), false); task_environment_.RunUntilIdle(); @@ -308,16 +308,16 @@ } TEST_F(CrostiniSshfsHelperTest, ContainerShutdownClearsMountStatus) { - SetContainerRunning(ContainerId::GetDefault()); + SetContainerRunning(DefaultContainerId()); ExpectMountCalls(2); crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting([](bool res) { EXPECT_TRUE(res); }), false); task_environment_.RunUntilIdle(); - crostini_sshfs_->OnContainerShutdown(ContainerId::GetDefault()); + crostini_sshfs_->OnContainerShutdown(DefaultContainerId()); task_environment_.RunUntilIdle(); crostini_sshfs_->MountCrostiniFiles( - ContainerId::GetDefault(), + DefaultContainerId(), base::BindLambdaForTesting([](bool res) { EXPECT_TRUE(res); }), true); task_environment_.RunUntilIdle();
diff --git a/chrome/browser/ash/crostini/crostini_terminal.cc b/chrome/browser/ash/crostini/crostini_terminal.cc index dbbcf16..20665c3 100644 --- a/chrome/browser/ash/crostini/crostini_terminal.cc +++ b/chrome/browser/ash/crostini/crostini_terminal.cc
@@ -256,7 +256,7 @@ } // Look for vm_name and container_name in intent->extras. - ContainerId container_id = ContainerId::GetDefault(); + ContainerId container_id = DefaultContainerId(); std::string settings_profile; if (intent && intent->extras.has_value()) { for (const auto& extra : intent->extras.value()) {
diff --git a/chrome/browser/ash/crostini/crostini_terminal.h b/chrome/browser/ash/crostini/crostini_terminal.h index 924570b..9fd81d0 100644 --- a/chrome/browser/ash/crostini/crostini_terminal.h +++ b/chrome/browser/ash/crostini/crostini_terminal.h
@@ -113,17 +113,16 @@ const std::string& GetTerminalHomeUrl(); // Generate URL to launch terminal. -GURL GenerateTerminalURL( - Profile* profile, - const std::string& setings_profile, - const ContainerId& container_id = ContainerId::GetDefault(), - const std::string& cwd = "", - const std::vector<std::string>& terminal_args = {}); +GURL GenerateTerminalURL(Profile* profile, + const std::string& setings_profile, + const ContainerId& container_id = DefaultContainerId(), + const std::string& cwd = "", + const std::vector<std::string>& terminal_args = {}); // Launches the terminal tabbed app. void LaunchTerminal(Profile* profile, int64_t display_id = display::kInvalidDisplayId, - const ContainerId& container_id = ContainerId::GetDefault(), + const ContainerId& container_id = DefaultContainerId(), const std::string& cwd = "", const std::vector<std::string>& terminal_args = {});
diff --git a/chrome/browser/ash/crostini/crostini_terminal_unittest.cc b/chrome/browser/ash/crostini/crostini_terminal_unittest.cc index 3c3f47f..79a383d 100644 --- a/chrome/browser/ash/crostini/crostini_terminal_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_terminal_unittest.cc
@@ -21,13 +21,12 @@ TEST_F(CrostiniTerminalTest, GenerateTerminalURL) { content::BrowserTaskEnvironment task_environment; TestingProfile profile; - EXPECT_EQ( - GenerateTerminalURL(&profile, "", ContainerId::GetDefault(), "", {}), - "chrome-untrusted://terminal/html/terminal.html" - "?command=vmshell" - "&args[]=--vm_name%3Dtermina" - "&args[]=--target_container%3Dpenguin" - "&args[]=--owner_id%3Dtest"); + EXPECT_EQ(GenerateTerminalURL(&profile, "", DefaultContainerId(), "", {}), + "chrome-untrusted://terminal/html/terminal.html" + "?command=vmshell" + "&args[]=--vm_name%3Dtermina" + "&args[]=--target_container%3Dpenguin" + "&args[]=--owner_id%3Dtest"); EXPECT_EQ(GenerateTerminalURL(&profile, "red", ContainerId("test-vm", "test-container"), "/home/user", {"arg1"}),
diff --git a/chrome/browser/ash/crostini/crostini_upgrade_available_notification.cc b/chrome/browser/ash/crostini/crostini_upgrade_available_notification.cc index 6634e60a..24959286 100644 --- a/chrome/browser/ash/crostini/crostini_upgrade_available_notification.cc +++ b/chrome/browser/ash/crostini/crostini_upgrade_available_notification.cc
@@ -33,7 +33,7 @@ notification_(notification), closure_(std::move(closure)) { CrostiniManager::GetForProfile(profile_)->UpgradePromptShown( - ContainerId::GetDefault()); + DefaultContainerId()); } CrostiniUpgradeAvailableNotificationDelegate(
diff --git a/chrome/browser/ash/crostini/crostini_util.cc b/chrome/browser/ash/crostini/crostini_util.cc index 962fb11f..56677d4 100644 --- a/chrome/browser/ash/crostini/crostini_util.cc +++ b/chrome/browser/ash/crostini/crostini_util.cc
@@ -224,10 +224,6 @@ << container_id.container_name << "\")"; } -ContainerId ContainerId::GetDefault() { - return ContainerId(kCrostiniDefaultVmName, kCrostiniDefaultContainerName); -} - bool IsUninstallable(Profile* profile, const std::string& app_id) { if (!CrostiniFeatures::Get()->IsEnabled(profile)) { return false; @@ -259,8 +255,7 @@ bool ShouldAllowContainerUpgrade(Profile* profile) { return CrostiniFeatures::Get()->IsContainerUpgradeUIAllowed(profile) && crostini::CrostiniManager::GetForProfile(profile) - ->IsContainerUpgradeable(ContainerId( - kCrostiniDefaultVmName, kCrostiniDefaultContainerName)); + ->IsContainerUpgradeable(DefaultContainerId()); } void AddSpinner(crostini::CrostiniManager::RestartId restart_id, @@ -557,7 +552,7 @@ if (!CrostiniFeatures::Get()->IsContainerUpgradeUIAllowed(profile)) { return false; } - if (container_id != ContainerId::GetDefault()) { + if (container_id != DefaultContainerId()) { return false; } // If the warning dialog is already open we can add more callbacks to it, but
diff --git a/chrome/browser/ash/crostini/crostini_util.h b/chrome/browser/ash/crostini/crostini_util.h index 603ebc9..b6909f7 100644 --- a/chrome/browser/ash/crostini/crostini_util.h +++ b/chrome/browser/ash/crostini/crostini_util.h
@@ -74,8 +74,6 @@ base::flat_map<std::string, std::string> ToMap() const; base::Value::Dict ToDictValue() const; - static ContainerId GetDefault(); - std::string vm_name; std::string container_name; };
diff --git a/chrome/browser/ash/dbus/ash_dbus_helper.cc b/chrome/browser/ash/dbus/ash_dbus_helper.cc index 4b8f5973..6ac94d5 100644 --- a/chrome/browser/ash/dbus/ash_dbus_helper.cc +++ b/chrome/browser/ash/dbus/ash_dbus_helper.cc
@@ -67,6 +67,7 @@ #include "chromeos/dbus/userdataauth/cryptohome_pkcs11_client.h" #include "chromeos/dbus/userdataauth/install_attributes_client.h" #include "chromeos/dbus/userdataauth/userdataauth_client.h" +#include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "device/bluetooth/floss/floss_dbus_manager.h" #include "device/bluetooth/floss/floss_features.h" @@ -160,6 +161,7 @@ InitializeDBusClient<chromeos::U2FClient>(bus); InitializeDBusClient<chromeos::UserDataAuthClient>(bus); InitializeDBusClient<UpstartClient>(bus); + InitializeDBusClient<chromeos::VmPluginDispatcherClient>(bus); // Initialize the device settings service so that we'll take actions per // signals sent from the session manager. This needs to happen before @@ -215,6 +217,7 @@ bluez::BluezDBusManager::Shutdown(); } // Other D-Bus clients are shut down, also in reverse order of initialization. + chromeos::VmPluginDispatcherClient::Shutdown(); UpstartClient::Shutdown(); chromeos::UserDataAuthClient::Shutdown(); chromeos::U2FClient::Shutdown();
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index f14899a5..7dd01145 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -1704,7 +1704,7 @@ std::string DisplayName() override { return name_; } Profile* profile() override { return profile_; } crostini::ContainerId ContainerId() override { - return crostini::ContainerId::GetDefault(); + return crostini::DefaultContainerId(); } guest_os::VmType vm_type() override { @@ -1724,9 +1724,9 @@ public: explicit GuestOsTestVolume(Profile* profile, MockGuestOsMountProvider* provider) - : LocalTestVolume(util::GetGuestOsMountPointName( - profile, - crostini::ContainerId::GetDefault())), + : LocalTestVolume( + util::GetGuestOsMountPointName(profile, + crostini::DefaultContainerId())), provider_(provider) {} GuestOsTestVolume(const GuestOsTestVolume&) = delete;
diff --git a/chrome/browser/ash/file_manager/file_watcher.cc b/chrome/browser/ash/file_manager/file_watcher.cc index c0ac0747..639ff3a 100644 --- a/chrome/browser/ash/file_manager/file_watcher.cc +++ b/chrome/browser/ash/file_manager/file_watcher.cc
@@ -66,7 +66,7 @@ : crostini_manager_(crostini_manager), crostini_mount_(std::move(crostini_mount)), crostini_path_(std::move(crostini_path)), - container_id_(crostini::ContainerId::GetDefault()) {} + container_id_(crostini::DefaultContainerId()) {} ~CrostiniFileWatcher() override { if (file_watcher_callback_) {
diff --git a/chrome/browser/ash/file_manager/path_util.cc b/chrome/browser/ash/file_manager/path_util.cc index 69205db2..8762e05 100644 --- a/chrome/browser/ash/file_manager/path_util.cc +++ b/chrome/browser/ash/file_manager/path_util.cc
@@ -491,7 +491,7 @@ if (map_crostini_home) { absl::optional<crostini::ContainerInfo> container_info = crostini::CrostiniManager::GetForProfile(profile)->GetContainerInfo( - crostini::ContainerId::GetDefault()); + crostini::DefaultContainerId()); if (!container_info) { return false; } @@ -546,7 +546,7 @@ if (map_crostini_home) { absl::optional<crostini::ContainerInfo> container_info = crostini::CrostiniManager::GetForProfile(profile)->GetContainerInfo( - crostini::ContainerId::GetDefault()); + crostini::DefaultContainerId()); if (container_info && AppendRelativePath(container_info->homedir, inside, &relative_path)) { *file_system_url = mount_points->CreateExternalFileSystemURL(
diff --git a/chrome/browser/ash/file_manager/volume_manager.cc b/chrome/browser/ash/file_manager/volume_manager.cc index 72f76261..17fc537 100644 --- a/chrome/browser/ash/file_manager/volume_manager.cc +++ b/chrome/browser/ash/file_manager/volume_manager.cc
@@ -799,7 +799,7 @@ // Listen for crostini container shutdown and remove volume. crostini::CrostiniManager::GetForProfile(profile_) ->AddShutdownContainerCallback( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), base::BindOnce(&VolumeManager::RemoveSshfsCrostiniVolume, weak_ptr_factory_.GetWeakPtr(), sshfs_mount_path, base::BindOnce([](bool result) {
diff --git a/chrome/browser/ash/guest_os/guest_os_launcher.cc b/chrome/browser/ash/guest_os/guest_os_launcher.cc index c546f86..207b137 100644 --- a/chrome/browser/ash/guest_os/guest_os_launcher.cc +++ b/chrome/browser/ash/guest_os/guest_os_launcher.cc
@@ -61,7 +61,7 @@ LaunchCallback callback) { crostini::CrostiniManager::RestartOptions options; options.start_vm_only = just_termina; - auto container_id = crostini::ContainerId::GetDefault(); + auto container_id = crostini::DefaultContainerId(); crostini::CrostiniManager::GetForProfile(profile)->RestartCrostiniWithOptions( container_id, std::move(options), base::BindOnce(
diff --git a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc index fe88a18..ee91a18e 100644 --- a/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc +++ b/chrome/browser/ash/guest_os/guest_os_share_path_unittest.cc
@@ -41,6 +41,7 @@ #include "chromeos/ash/components/dbus/seneschal/seneschal_service.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dlcservice/dlcservice_client.h" +#include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h" #include "components/account_id/account_id.h" #include "components/drive/drive_pref_names.h" #include "components/prefs/pref_service.h" @@ -227,6 +228,7 @@ ash::CiceroneClient::InitializeFake(); ash::ConciergeClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); + chromeos::VmPluginDispatcherClient::InitializeFake(); fake_concierge_client_ = ash::FakeConciergeClient::Get(); fake_seneschal_client_ = ash::FakeSeneschalClient::Get(); @@ -236,6 +238,7 @@ GuestOsSharePathTest& operator=(const GuestOsSharePathTest&) = delete; ~GuestOsSharePathTest() override { + chromeos::VmPluginDispatcherClient::Shutdown(); ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown();
diff --git a/chrome/browser/ash/guest_os/guest_os_test_helpers.cc b/chrome/browser/ash/guest_os/guest_os_test_helpers.cc index fd552d2..131037d 100644 --- a/chrome/browser/ash/guest_os/guest_os_test_helpers.cc +++ b/chrome/browser/ash/guest_os/guest_os_test_helpers.cc
@@ -11,7 +11,7 @@ namespace guest_os { MockMountProvider::MockMountProvider() - : profile_(nullptr), container_id_(crostini::ContainerId::GetDefault()) {} + : profile_(nullptr), container_id_(crostini::DefaultContainerId()) {} MockMountProvider::MockMountProvider(Profile* profile, crostini::ContainerId container_id)
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc index 231705e..d50bcf4 100644 --- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc +++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -399,13 +399,12 @@ } uint32_t Utf16ToCodepoint(const std::u16string& str) { - int32_t index = 0; + size_t index = 0; base_icu::UChar32 codepoint = 0; base::ReadUnicodeCharacter(str.data(), str.length(), &index, &codepoint); // Should only contain a single codepoint. - DCHECK_GE(index, 0); - DCHECK_EQ(static_cast<size_t>(index), str.length() - 1); + DCHECK_EQ(index, str.length() - 1); return codepoint; }
diff --git a/chrome/browser/ash/login/chrome_restart_request.cc b/chrome/browser/ash/login/chrome_restart_request.cc index 3541546d..2475995 100644 --- a/chrome/browser/ash/login/chrome_restart_request.cc +++ b/chrome/browser/ash/login/chrome_restart_request.cc
@@ -153,6 +153,7 @@ ::switches::kDisableWebGLImageChromium, ::switches::kEnableWebGLImageChromium, ::switches::kEnableUnsafeWebGPU, + ::switches::kEnableWebGPUDeveloperFeatures, ::switches::kDisableWebRtcHWDecoding, ::switches::kDisableWebRtcHWEncoding, ::switches::kOzonePlatform,
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc index 0258817..9d43e78 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
@@ -85,6 +85,16 @@ return true; } +// Key-value pair to be added to FeedbackData when user grants consent to Google +// to follow-up on feedback report. See (go/feedback-user-consent-faq) for more +// information. +// Consent key matches cross-platform key. +constexpr char kFeedbackUserConsentKey[] = "feedbackUserCtlConsent"; +// Consent value matches JavaScript: `String(true)`. +constexpr char kFeedbackUserConsentGrantedValue[] = "true"; +// Consent value matches JavaScript: `String(false)`. +constexpr char kFeedbackUserConsentDeniedValue[] = "false"; + } // namespace ChromeOsFeedbackDelegate::ChromeOsFeedbackDelegate(Profile* profile) @@ -174,6 +184,16 @@ std::string(png_data->front_as<char>(), png_data->size())); } + // Append consent value to report. For cross platform implementations see: + // extensions/browser/api/feedback_private/feedback_private_api.cc + if (report->contact_user_consent_granted) { + feedback_data->AddLog(kFeedbackUserConsentKey, + kFeedbackUserConsentGrantedValue); + } else { + feedback_data->AddLog(kFeedbackUserConsentKey, + kFeedbackUserConsentDeniedValue); + } + const AttachedFilePtr& attached_file = report->attached_file; if (ShouldAddAttachment(attached_file)) { feedback_data->set_attached_filename(
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc index 7fd57eec..bf1d292 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate_browsertest.cc
@@ -55,6 +55,9 @@ constexpr char kPageUrl[] = "https://www.google.com/?q=123"; constexpr char kSignedInUserEmail[] = "test_user_email@gmail.com"; +constexpr char kFeedbackUserConsentKey[] = "feedbackUserCtlConsent"; +constexpr char kFeedbackUserConsentGrantedValue[] = "true"; +constexpr char kFeedbackUserConsentDeniedValue[] = "false"; const std::u16string kDescription = u"This is a fake description"; } // namespace @@ -157,6 +160,7 @@ // passed to SendFeedback method of the feedback service. // - System logs and histograms are included. // - Screenshot is included. +// - Consent granted. // TODO(xiangdongkong): Add tests for other flags once they are supported. // Currently, only load_system_info and send_histograms flags are implemented. IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, @@ -165,6 +169,7 @@ report->feedback_context = FeedbackContext::New(); report->description = kDescription; report->include_screenshot = true; + report->contact_user_consent_granted = true; report->include_system_logs_and_histograms = true; const FeedbackParams expected_params{/*is_internal_email=*/false, @@ -181,12 +186,19 @@ EXPECT_EQ(base::UTF16ToUTF8(kDescription), feedback_data->description()); // Verify screenshot is added to feedback data. EXPECT_GT(feedback_data->image().size(), 0); + // Verify consent data appended to sys_info map. + auto consent_granted = + feedback_data->sys_info()->find(kFeedbackUserConsentKey); + EXPECT_NE(feedback_data->sys_info()->end(), consent_granted); + EXPECT_EQ(kFeedbackUserConsentKey, consent_granted->first); + EXPECT_EQ(kFeedbackUserConsentGrantedValue, consent_granted->second); } // Test that feedback params and data are populated with correct data before // passed to SendFeedback method of the feedback service. // - System logs and histograms are not included. // - Screenshot is not included. +// - Consent not granted. IN_PROC_BROWSER_TEST_F(ChromeOsFeedbackDelegateTest, FeedbackDataPopulatedNotIncludeSysLogsOrScreenshot) { ReportPtr report = Report::New(); @@ -195,6 +207,7 @@ report->feedback_context->page_url = GURL(kPageUrl); report->description = kDescription; report->include_screenshot = false; + report->contact_user_consent_granted = false; report->include_system_logs_and_histograms = false; const FeedbackParams expected_params{/*is_internal_email=*/false, @@ -211,6 +224,12 @@ EXPECT_EQ(base::UTF16ToUTF8(kDescription), feedback_data->description()); // Verify no screenshot is added to feedback data. EXPECT_EQ("", feedback_data->image()); + // Verify consent data appended to sys_info map. + auto consent_denied = + feedback_data->sys_info()->find(kFeedbackUserConsentKey); + EXPECT_NE(feedback_data->sys_info()->end(), consent_denied); + EXPECT_EQ(kFeedbackUserConsentKey, consent_denied->first); + EXPECT_EQ(kFeedbackUserConsentDeniedValue, consent_denied->second); } // Test GetScreenshot returns correct data when there is a screenshot.
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc index cdab9ee..7e05452 100644 --- a/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc +++ b/chrome/browser/ash/plugin_vm/plugin_vm_files_unittest.cc
@@ -28,6 +28,7 @@ #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/vm_applications/apps.pb.h" +#include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h" #include "content/public/test/browser_task_environment.h" #include "storage/browser/file_system/external_mount_points.h" #include "storage/common/file_system/file_system_types.h" @@ -101,8 +102,10 @@ ash::CiceroneClient::InitializeFake(); ash::ConciergeClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); + chromeos::VmPluginDispatcherClient::InitializeFake(); } ~ScopedDBusThreadManager() { + chromeos::VmPluginDispatcherClient::Shutdown(); ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown();
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc index fa1190b6..f4dc605 100644 --- a/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc +++ b/chrome/browser/ash/plugin_vm/plugin_vm_installer_unittest.cc
@@ -30,6 +30,7 @@ #include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h" +#include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h" #include "components/account_id/account_id.h" #include "components/download/public/background_service/test/test_download_service.h" #include "components/drive/service/dummy_drive_service.h" @@ -166,6 +167,7 @@ void SetUp() override { chromeos::DBusThreadManager::Initialize(); ash::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr); + chromeos::VmPluginDispatcherClient::InitializeFake(); ASSERT_TRUE(profiles_dir_.CreateUniqueTempDir()); CreateProfile(); @@ -197,6 +199,7 @@ profile_.reset(); observer_.reset(); + chromeos::VmPluginDispatcherClient::Shutdown(); ash::ConciergeClient::Shutdown(); chromeos::DBusThreadManager::Shutdown(); chromeos::DlcserviceClient::Shutdown();
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc index 3f31a88..278e260f 100644 --- a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc +++ b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl.cc
@@ -122,15 +122,11 @@ PluginVmManagerImpl::PluginVmManagerImpl(Profile* profile) : profile_(profile), owner_id_(ash::ProfileHelper::GetUserIdHashFromProfile(profile)) { - chromeos::DBusThreadManager::Get() - ->GetVmPluginDispatcherClient() - ->AddObserver(this); + chromeos::VmPluginDispatcherClient::Get()->AddObserver(this); } PluginVmManagerImpl::~PluginVmManagerImpl() { - chromeos::DBusThreadManager::Get() - ->GetVmPluginDispatcherClient() - ->RemoveObserver(this); + chromeos::VmPluginDispatcherClient::Get()->RemoveObserver(this); } void PluginVmManagerImpl::OnPrimaryUserSessionStarted() { @@ -139,7 +135,7 @@ request.set_vm_name_uuid(kPluginVmName); // Probe the dispatcher. - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->ListVms( + chromeos::VmPluginDispatcherClient::Get()->ListVms( std::move(request), base::BindOnce( [](absl::optional<vm_tools::plugin_dispatcher::ListVmResponse> @@ -230,8 +226,8 @@ } // TODO(juwa): This may not work if the vm is STARTING|CONTINUING|RESUMING. - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->StopVm( - std::move(request), base::DoNothing()); + chromeos::VmPluginDispatcherClient::Get()->StopVm(std::move(request), + base::DoNothing()); } void PluginVmManagerImpl::RelaunchPluginVm() { @@ -249,7 +245,7 @@ request.set_vm_name_uuid(kPluginVmName); // TODO(dtor): This may not work if the vm is STARTING|CONTINUING|RESUMING. - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->SuspendVm( + chromeos::VmPluginDispatcherClient::Get()->SuspendVm( std::move(request), base::BindOnce(&PluginVmManagerImpl::OnSuspendVmForRelaunch, weak_ptr_factory_.GetWeakPtr())); @@ -460,7 +456,7 @@ request.set_owner_id(owner_id_); request.set_vm_name_uuid(kPluginVmName); - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->ListVms( + chromeos::VmPluginDispatcherClient::Get()->ListVms( std::move(request), base::BindOnce(&PluginVmManagerImpl::OnListVms, weak_ptr_factory_.GetWeakPtr(), @@ -540,7 +536,7 @@ request.set_owner_id(owner_id_); request.set_vm_name_uuid(kPluginVmName); - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->StartVm( + chromeos::VmPluginDispatcherClient::Get()->StartVm( std::move(request), base::BindOnce(&PluginVmManagerImpl::OnStartVm, weak_ptr_factory_.GetWeakPtr())); } @@ -582,7 +578,7 @@ request.set_owner_id(owner_id_); request.set_vm_name_uuid(kPluginVmName); - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->ShowVm( + chromeos::VmPluginDispatcherClient::Get()->ShowVm( std::move(request), base::BindOnce(&PluginVmManagerImpl::OnShowVm, weak_ptr_factory_.GetWeakPtr())); } @@ -722,7 +718,7 @@ request.set_stop_mode( vm_tools::plugin_dispatcher::VmStopMode::VM_STOP_MODE_SHUTDOWN); - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()->StopVm( + chromeos::VmPluginDispatcherClient::Get()->StopVm( std::move(request), base::BindOnce(&PluginVmManagerImpl::OnStopVmForUninstall, weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc index 41788d43..35bdc889 100644 --- a/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc +++ b/chrome/browser/ash/plugin_vm/plugin_vm_manager_impl_unittest.cc
@@ -31,6 +31,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dlcservice/fake_dlcservice_client.h" #include "chromeos/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h" +#include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" @@ -52,6 +53,7 @@ ash::CiceroneClient::InitializeFake(); ash::ConciergeClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); + chromeos::VmPluginDispatcherClient::InitializeFake(); testing_profile_ = std::make_unique<TestingProfile>(); test_helper_ = std::make_unique<PluginVmTestHelper>(testing_profile_.get()); plugin_vm_manager_ = static_cast<PluginVmManagerImpl*>( @@ -89,6 +91,7 @@ display_service_.reset(); test_helper_.reset(); testing_profile_.reset(); + chromeos::VmPluginDispatcherClient::Shutdown(); ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown(); @@ -98,7 +101,7 @@ protected: chromeos::FakeVmPluginDispatcherClient& VmPluginDispatcherClient() { return *static_cast<chromeos::FakeVmPluginDispatcherClient*>( - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()); + chromeos::VmPluginDispatcherClient::Get()); } ash::FakeConciergeClient& ConciergeClient() { return *ash::FakeConciergeClient::Get();
diff --git a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc index f4997cec..95d36d6 100644 --- a/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc +++ b/chrome/browser/ash/policy/handlers/lock_to_single_user_manager_unittest.cc
@@ -29,6 +29,7 @@ #include "chromeos/dbus/anomaly_detector/anomaly_detector_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/userdataauth/fake_cryptohome_misc_client.h" +#include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h" #include "components/account_id/account_id.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/prefs/testing_pref_service.h" @@ -48,7 +49,7 @@ void SetUp() override { // This is required before Concierge tests start calling - // DBusThreadManager::Get() for GetAnomalyDetectorClient. + // DBusThreadManager::Get() for GuestOsStabilityMonitor. chromeos::DBusThreadManager::Initialize(); ash::CiceroneClient::InitializeFake(); @@ -59,6 +60,7 @@ base::CommandLine::ForCurrentProcess()); chromeos::AnomalyDetectorClient::InitializeFake(); chromeos::CryptohomeMiscClient::InitializeFake(); + chromeos::VmPluginDispatcherClient::InitializeFake(); lock_to_single_user_manager_ = std::make_unique<LockToSingleUserManager>(); BrowserWithTestWindowTest::SetUp(); @@ -101,6 +103,7 @@ arc_service_manager_->set_browser_context(nullptr); arc_service_manager_.reset(); + chromeos::VmPluginDispatcherClient::Shutdown(); chromeos::CryptohomeMiscClient::Shutdown(); chromeos::AnomalyDetectorClient::Shutdown(); ash::SeneschalClient::Shutdown();
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc new file mode 100644 index 0000000..5ad4dc6 --- /dev/null +++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc
@@ -0,0 +1,154 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h" + +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/check.h" +#include "base/memory/ptr_util.h" +#include "chrome/common/channel_info.h" +#include "components/sync/base/report_unrecoverable_error.h" +#include "components/sync/model/client_tag_based_model_type_processor.h" +#include "components/sync/model/entity_change.h" +#include "components/sync/model/metadata_change_list.h" +#include "components/sync/model/model_error.h" +#include "components/sync/model/model_type_change_processor.h" +#include "components/sync/model/model_type_store.h" +#include "components/sync/model/model_type_store_base.h" +#include "components/sync/model/model_type_sync_bridge.h" +#include "components/sync/protocol/entity_data.h" +#include "components/sync/protocol/entity_specifics.pb.h" +#include "components/sync/protocol/printers_authorization_server_specifics.pb.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace ash::printing::oauth2 { + +std::unique_ptr<ProfileAuthServersSyncBridge> +ProfileAuthServersSyncBridge::Create( + Observer* observer, + syncer::OnceModelTypeStoreFactory store_factory) { + DCHECK(observer); + return base::WrapUnique(new ProfileAuthServersSyncBridge( + std::make_unique<syncer::ClientTagBasedModelTypeProcessor>( + syncer::PRINTERS_AUTHORIZATION_SERVERS, + base::BindRepeating(&syncer::ReportUnrecoverableError, + chrome::GetChannel())), + std::move(store_factory), observer)); +} + +std::unique_ptr<ProfileAuthServersSyncBridge> +ProfileAuthServersSyncBridge::CreateForTesting( + Observer* observer, + std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, + syncer::OnceModelTypeStoreFactory store_factory) { + DCHECK(observer); + DCHECK(change_processor); + return base::WrapUnique(new ProfileAuthServersSyncBridge( + std::move(change_processor), std::move(store_factory), observer)); +} + +ProfileAuthServersSyncBridge::~ProfileAuthServersSyncBridge() = default; + +ProfileAuthServersSyncBridge::ProfileAuthServersSyncBridge( + std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, + syncer::OnceModelTypeStoreFactory store_factory, + Observer* observer) + : syncer::ModelTypeSyncBridge(std::move(change_processor)), + observer_(observer) { + std::move(store_factory) + .Run(syncer::PRINTERS_AUTHORIZATION_SERVERS, + base::BindOnce(&ProfileAuthServersSyncBridge::OnStoreCreated, + weak_ptr_factory_.GetWeakPtr())); +} + +void ProfileAuthServersSyncBridge::OnStoreCreated( + const absl::optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore> store) { + if (error) { + change_processor()->ReportError(*error); + return; + } + + store_ = std::move(store); + store_->ReadAllData( + base::BindOnce(&ProfileAuthServersSyncBridge::OnReadAllData, + weak_ptr_factory_.GetWeakPtr())); +} + +void ProfileAuthServersSyncBridge::OnReadAllData( + const absl::optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> record_list) { + if (error) { + change_processor()->ReportError(*error); + return; + } + + for (const syncer::ModelTypeStore::Record& r : *record_list) { + sync_pb::PrintersAuthorizationServerSpecifics specifics; + if (!specifics.ParseFromString(r.value)) { + change_processor()->ReportError( + {FROM_HERE, "Failed to deserialize all specifics."}); + return; + } + servers_uris_.insert(specifics.uri()); + } + + // Data loaded. Load metadata. + store_->ReadAllMetadata( + base::BindOnce(&ProfileAuthServersSyncBridge::OnReadAllMetadata, + weak_ptr_factory_.GetWeakPtr())); +} + +void ProfileAuthServersSyncBridge::OnReadAllMetadata( + const absl::optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch) { + if (error) { + change_processor()->ReportError(*error); + return; + } + change_processor()->ModelReadyToSync(std::move(metadata_batch)); + observer_->OnProfileAuthorizationServersInitialized(); +} + +std::unique_ptr<syncer::MetadataChangeList> +ProfileAuthServersSyncBridge::CreateMetadataChangeList() { + return syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList(); +} + +absl::optional<syncer::ModelError> ProfileAuthServersSyncBridge::MergeSyncData( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_data) { + return absl::nullopt; +} + +absl::optional<syncer::ModelError> +ProfileAuthServersSyncBridge::ApplySyncChanges( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_changes) { + return absl::nullopt; +} + +void ProfileAuthServersSyncBridge::GetData(StorageKeyList storage_keys, + DataCallback callback) {} + +void ProfileAuthServersSyncBridge::GetAllDataForDebugging( + DataCallback callback) {} + +std::string ProfileAuthServersSyncBridge::GetClientTag( + const syncer::EntityData& entity_data) { + return GetStorageKey(entity_data); +} + +std::string ProfileAuthServersSyncBridge::GetStorageKey( + const syncer::EntityData& entity_data) { + DCHECK(entity_data.specifics.has_printers_authorization_server()); + return entity_data.specifics.printers_authorization_server().uri(); +} + +} // namespace ash::printing::oauth2
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h new file mode 100644 index 0000000..3b1d96bea --- /dev/null +++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h
@@ -0,0 +1,105 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ASH_PRINTING_OAUTH2_PROFILE_AUTH_SERVERS_SYNC_BRIDGE_H_ +#define CHROME_BROWSER_ASH_PRINTING_OAUTH2_PROFILE_AUTH_SERVERS_SYNC_BRIDGE_H_ + +#include <memory> +#include <set> +#include <string> + +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/sync/model/entity_change.h" +#include "components/sync/model/model_error.h" +#include "components/sync/model/model_type_store.h" +#include "components/sync/model/model_type_sync_bridge.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace syncer { +struct EntityData; +class ModelTypeChangeProcessor; +class MetadataChangeList; +} // namespace syncer + +namespace ash::printing::oauth2 { + +// This class is the bridge responsible for the synchronization of the list of +// trusted Authorization Servers between the user's profile and local storage. +class ProfileAuthServersSyncBridge : public syncer::ModelTypeSyncBridge { + public: + class Observer { + public: + // This method is called when the sync bridge is ready to process calls to + // AddAuthorizationServer(...). This method is called only once and it is + // always the first method called on the observer by the sync bridge. + virtual void OnProfileAuthorizationServersInitialized() = 0; + + protected: + virtual ~Observer() = default; + }; + + // Factory function. |observer| must not be nullptr. + static std::unique_ptr<ProfileAuthServersSyncBridge> Create( + Observer* observer, + syncer::OnceModelTypeStoreFactory store_factory); + + // Factory function for testing. |observer| and |change_processor| must not be + // nullptr. + static std::unique_ptr<ProfileAuthServersSyncBridge> CreateForTesting( + Observer* observer, + std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, + syncer::OnceModelTypeStoreFactory store_factory); + + ProfileAuthServersSyncBridge(const ProfileAuthServersSyncBridge&) = delete; + ProfileAuthServersSyncBridge& operator=(const ProfileAuthServersSyncBridge&) = + delete; + + ~ProfileAuthServersSyncBridge() override; + + private: + ProfileAuthServersSyncBridge( + std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor, + syncer::OnceModelTypeStoreFactory store_factory, + Observer* observer); + + // Callback for ModelTypeStore initialization. + void OnStoreCreated(const absl::optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore> store); + + // Callback from the store when all data are loaded. + void OnReadAllData( + const absl::optional<syncer::ModelError>& error, + std::unique_ptr<syncer::ModelTypeStore::RecordList> record_list); + + // Callback from the store when all metadata are loaded. + void OnReadAllMetadata(const absl::optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch); + + // Implementation of ModelTypeSyncBridge interface. + std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() + override; + absl::optional<syncer::ModelError> MergeSyncData( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_data) override; + absl::optional<syncer::ModelError> ApplySyncChanges( + std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, + syncer::EntityChangeList entity_changes) override; + void GetData(StorageKeyList storage_keys, DataCallback callback) override; + void GetAllDataForDebugging(DataCallback callback) override; + std::string GetClientTag(const syncer::EntityData& entity_data) override; + std::string GetStorageKey(const syncer::EntityData& entity_data) override; + + // The current trusted list of Authorization Servers URIs. + std::set<std::string> servers_uris_; + // The local storage. + std::unique_ptr<syncer::ModelTypeStore> store_; + + raw_ptr<Observer> const observer_; + base::WeakPtrFactory<ProfileAuthServersSyncBridge> weak_ptr_factory_{this}; +}; + +} // namespace ash::printing::oauth2 + +#endif // CHROME_BROWSER_ASH_PRINTING_OAUTH2_PROFILE_AUTH_SERVERS_SYNC_BRIDGE_H_
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc new file mode 100644 index 0000000..ab73d239 --- /dev/null +++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc
@@ -0,0 +1,58 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h" + +#include <memory> + +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "components/sync/model/model_type_store.h" +#include "components/sync/test/model/mock_model_type_change_processor.h" +#include "components/sync/test/model/model_type_store_test_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash::printing::oauth2 { +namespace { + +class MockProfileAuthServersSyncBridgeObserver + : public ProfileAuthServersSyncBridge::Observer { + public: + MOCK_METHOD(void, OnProfileAuthorizationServersInitialized, (), (override)); +}; + +class PrintingOAuth2ProfileAuthServersSyncBridgeTest : public testing::Test { + protected: + PrintingOAuth2ProfileAuthServersSyncBridgeTest() = default; + + void CreateBridge() { + ON_CALL(mock_processor_, IsTrackingMetadata()) + .WillByDefault(testing::Return(false)); + bridge_ = ProfileAuthServersSyncBridge::CreateForTesting( + &mock_observer_, mock_processor_.CreateForwardingProcessor(), + syncer::ModelTypeStoreTestUtil::FactoryForForwardingStore( + store_.get())); + } + + // In memory model type store needs to be able to post tasks. + base::test::SingleThreadTaskEnvironment task_environment_; + std::unique_ptr<syncer::ModelTypeStore> store_ = + syncer::ModelTypeStoreTestUtil::CreateInMemoryStoreForTest(); + testing::StrictMock<MockProfileAuthServersSyncBridgeObserver> mock_observer_; + testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_; + std::unique_ptr<ProfileAuthServersSyncBridge> bridge_; +}; + +TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest, Initialization) { + base::RunLoop loop; + CreateBridge(); + EXPECT_CALL(mock_observer_, OnProfileAuthorizationServersInitialized()) + .Times(1) + .WillOnce([&loop] { loop.Quit(); }); + loop.Run(); +} + +} // namespace +} // namespace ash::printing::oauth2
diff --git a/chrome/browser/ash/usb/cros_usb_detector.cc b/chrome/browser/ash/usb/cros_usb_detector.cc index 93f4a67c..f6ce174d 100644 --- a/chrome/browser/ash/usb/cros_usb_detector.cc +++ b/chrome/browser/ash/usb/cros_usb_detector.cc
@@ -37,7 +37,6 @@ #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/vector_icons/vector_icons.h" #include "content/public/browser/device_service.h" @@ -449,9 +448,7 @@ fastboot_device_filter_->protocol_code = kFastbootProtocol; ConciergeClient::Get()->AddVmObserver(this); - chromeos::DBusThreadManager::Get() - ->GetVmPluginDispatcherClient() - ->AddObserver(this); + chromeos::VmPluginDispatcherClient::Get()->AddObserver(this); disks::DiskMountManager::GetInstance()->AddObserver(this); } @@ -459,9 +456,7 @@ DCHECK_EQ(this, g_cros_usb_detector); disks::DiskMountManager::GetInstance()->RemoveObserver(this); ConciergeClient::Get()->RemoveVmObserver(this); - chromeos::DBusThreadManager::Get() - ->GetVmPluginDispatcherClient() - ->RemoveObserver(this); + chromeos::VmPluginDispatcherClient::Get()->RemoveObserver(this); g_cros_usb_detector = nullptr; }
diff --git a/chrome/browser/ash/usb/cros_usb_detector_unittest.cc b/chrome/browser/ash/usb/cros_usb_detector_unittest.cc index bbf637c..1c9ccb4a 100644 --- a/chrome/browser/ash/usb/cros_usb_detector_unittest.cc +++ b/chrome/browser/ash/usb/cros_usb_detector_unittest.cc
@@ -134,15 +134,17 @@ class CrosUsbDetectorTest : public BrowserWithTestWindowTest { public: CrosUsbDetectorTest() { + // Needed for ChunneldClient via GuestOsStabilityMonitor. chromeos::DBusThreadManager::Initialize(); ash::CiceroneClient::InitializeFake(); ConciergeClient::InitializeFake(); SeneschalClient::InitializeFake(); + chromeos::VmPluginDispatcherClient::InitializeFake(); fake_cicerone_client_ = ash::FakeCiceroneClient::Get(); fake_concierge_client_ = FakeConciergeClient::Get(); fake_vm_plugin_dispatcher_client_ = static_cast<chromeos::FakeVmPluginDispatcherClient*>( - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()); + chromeos::VmPluginDispatcherClient::Get()); mock_disk_mount_manager_ = new testing::NiceMock<disks::MockDiskMountManager>; @@ -154,6 +156,7 @@ ~CrosUsbDetectorTest() override { disks::DiskMountManager::Shutdown(); + chromeos::VmPluginDispatcherClient::Shutdown(); SeneschalClient::Shutdown(); ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown(); @@ -288,7 +291,6 @@ ash::FakeCiceroneClient* fake_cicerone_client_; FakeConciergeClient* fake_concierge_client_; - // Owned by chromeos::DBusThreadManager chromeos::FakeVmPluginDispatcherClient* fake_vm_plugin_dispatcher_client_; TestCrosUsbDeviceObserver usb_device_observer_;
diff --git a/chrome/browser/back_press/android/BUILD.gn b/chrome/browser/back_press/android/BUILD.gn index e79a1aa..d286fa4f 100644 --- a/chrome/browser/back_press/android/BUILD.gn +++ b/chrome/browser/back_press/android/BUILD.gn
@@ -42,7 +42,7 @@ } # On-device unit tests. -android_library("javatests") { +android_library("unit_device_javatests") { testonly = true sources = [
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc index 2b3e10ea..c01b6c2 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -41,7 +41,6 @@ #include "content/public/browser/browsing_data_filter_builder.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_usage_info.h" -#include "content/public/common/content_features.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/common/network_service_util.h" @@ -1077,9 +1076,8 @@ // quota system. GetMediaLicenseCount() is expected to always return 0 using // the new backend. // TODO(crbug.com/1307796): Fix GetCookiesTreeModelCount() to include quota - // nodes. - int count = - base::FeatureList::IsEnabled(features::kMediaLicenseBackend) ? 0 : 1; + // nodes. `count` should be 1 here. + int count = 0; SetDataForType(kMediaLicenseType); EXPECT_EQ(1, GetSiteDataCount()); EXPECT_EQ(count, GetMediaLicenseCount()); @@ -1128,9 +1126,8 @@ // quota system. GetMediaLicenseCount() is expected to always return 0 using // the new backend. // TODO(crbug.com/1307796): Fix GetCookiesTreeModelCount() to include quota - // nodes. - int count = - base::FeatureList::IsEnabled(features::kMediaLicenseBackend) ? 0 : 1; + // nodes. `count` should be 1 here. + int count = 0; SetDataForType(kMediaLicenseType); EXPECT_EQ(1, GetSiteDataCount()); EXPECT_EQ(count, GetMediaLicenseCount()); @@ -1149,9 +1146,8 @@ // quota system. GetMediaLicenseCount() is expected to always return 0 using // the new backend. // TODO(crbug.com/1307796): Fix GetCookiesTreeModelCount() to include quota - // nodes. - int count = - base::FeatureList::IsEnabled(features::kMediaLicenseBackend) ? 0 : 1; + // nodes. `count` should be 1 here. + int count = 0; // As the PRE_ test should run first, there should be one media license // still stored. The time of it's creation should be sometime before @@ -1180,7 +1176,9 @@ // http://crbug.com/909829. EXPECT_FALSE(HasDataForType(kMediaLicenseType)); - count = base::FeatureList::IsEnabled(features::kMediaLicenseBackend) ? 0 : 2; + // TODO(crbug.com/1307796): Fix GetCookiesTreeModelCount() to include quota + // nodes. `count` should be 2 here. + count = 0; // Create a media license for this domain. SetDataForType(kMediaLicenseType); EXPECT_EQ(count, GetMediaLicenseCount()); @@ -1192,7 +1190,9 @@ // media license, and leave the one created by the PRE_ test. RemoveAndWait(chrome_browsing_data_remover::DATA_TYPE_SITE_DATA, TimeEnum::kStart); - count = base::FeatureList::IsEnabled(features::kMediaLicenseBackend) ? 0 : 1; + // TODO(crbug.com/1307796): Fix GetCookiesTreeModelCount() to include quota + // nodes. `count` should be 1 here. + count = 0; EXPECT_EQ(1, GetSiteDataCount()); EXPECT_EQ(count, GetMediaLicenseCount()); EXPECT_FALSE(HasDataForType(kMediaLicenseType)); @@ -1221,9 +1221,8 @@ // quota system. GetMediaLicenseCount() is expected to always return 0 using // the new backend. // TODO(crbug.com/1307796): Fix GetCookiesTreeModelCount() to include quota - // nodes. - int count = - base::FeatureList::IsEnabled(features::kMediaLicenseBackend) ? 0 : 1; + // nodes. `count` should be 1 here. + int count = 0; SetDataForType(kMediaLicenseType); EXPECT_EQ(count, GetMediaLicenseCount()); EXPECT_TRUE(HasDataForType(kMediaLicenseType)); @@ -1291,12 +1290,6 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL(GetBrowser(), url)); for (const std::string& type : kStorageTypes) { - // TODO(crbug.com/1231162): This test was never run against the old media - // license backend (it fails), but we can run it against the new backend. - if (type == "MediaLicense" && - !base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - continue; - } SetDataForType(type); EXPECT_TRUE(HasDataForType(type)); }
diff --git a/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc b/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc index d4e3e910..958217f 100644 --- a/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc +++ b/chrome/browser/browsing_data/incognito_browsing_data_browsertest.cc
@@ -11,7 +11,6 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/test/bind.h" -#include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -29,7 +28,6 @@ #include "components/prefs/pref_service.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_usage_info.h" -#include "content/public/common/content_features.h" #include "content/public/common/content_paths.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" @@ -518,9 +516,8 @@ // quota system. GetMediaLicenseCount() is expected to always return 0 using // the new backend. // TODO(crbug.com/1307796): Fix GetCookiesTreeModelCount() to include quota - // nodes. - int count = - base::FeatureList::IsEnabled(features::kMediaLicenseBackend) ? 0 : 1; + // nodes. `count` should be 1 here. + int count = 0; SetDataForType(kMediaLicenseType); EXPECT_EQ(1, GetSiteDataCount()); EXPECT_EQ(count, GetMediaLicenseCount());
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index e684fa9..d0becae 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1789,6 +1789,8 @@ "../ash/printing/oauth2/http_exchange.h", "../ash/printing/oauth2/ipp_endpoint_token_fetcher.cc", "../ash/printing/oauth2/ipp_endpoint_token_fetcher.h", + "../ash/printing/oauth2/profile_auth_servers_sync_bridge.cc", + "../ash/printing/oauth2/profile_auth_servers_sync_bridge.h", "../ash/printing/oauth2/status_code.h", "../ash/printing/ppd_provider_factory.cc", "../ash/printing/ppd_provider_factory.h", @@ -3495,6 +3497,7 @@ "../ash/printing/oauth2/authorization_zone_unittest.cc", "../ash/printing/oauth2/http_exchange_unittest.cc", "../ash/printing/oauth2/ipp_endpoint_token_fetcher_unittest.cc", + "../ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc", "../ash/printing/oauth2/test_authorization_server.cc", "../ash/printing/oauth2/test_authorization_server.h", "../ash/printing/oauth2/test_authorization_server_unittest.cc",
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index e6b6166..5daacf4 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -2397,7 +2397,7 @@ installer_ui->ClickInstallForTesting(); })); crostini::CrostiniManager::GetForProfile(profile)->RestartCrostini( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), base::BindOnce( &AutotestPrivateRunCrostiniInstallerFunction::CrostiniRestarted, this)); @@ -2473,7 +2473,7 @@ } crostini::CrostiniExportImport::GetForProfile(profile)->ExportContainer( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), file_manager::util::GetDownloadsFolderForProfile(profile).Append(path), base::BindOnce(&AutotestPrivateExportCrostiniFunction::CrostiniExported, this)); @@ -2513,7 +2513,7 @@ return RespondNow(Error("Invalid import path must not reference parent")); } crostini::CrostiniExportImport::GetForProfile(profile)->ImportContainer( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), file_manager::util::GetDownloadsFolderForProfile(profile).Append(path), base::BindOnce(&AutotestPrivateImportCrostiniFunction::CrostiniImported, this));
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc index c82e706..6a3fdfb 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -828,7 +828,7 @@ Profile::FromBrowserContext(browser_context())->GetOriginalProfile(); DCHECK(crostini::CrostiniFeatures::Get()->IsEnabled(profile)); crostini::CrostiniManager::GetForProfile(profile)->RestartCrostini( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), base::BindOnce(&FileManagerPrivateMountCrostiniFunction::RestartCallback, this)); return RespondLater(); @@ -847,7 +847,7 @@ Profile::FromBrowserContext(browser_context())->GetOriginalProfile(); DCHECK(crostini::CrostiniFeatures::Get()->IsEnabled(profile)); crostini::CrostiniManager::GetForProfile(profile)->MountCrostiniFiles( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), base::BindOnce(&FileManagerPrivateMountCrostiniFunction::MountCallback, this), false); @@ -887,7 +887,7 @@ .path(); crostini::CrostiniExportImport::GetForProfile(profile)->ImportContainer( - crostini::ContainerId::GetDefault(), path, + crostini::DefaultContainerId(), path, base::BindOnce( [](base::FilePath path, crostini::CrostiniResult result) { if (result != crostini::CrostiniResult::SUCCESS) { @@ -1014,7 +1014,7 @@ profile, render_frame_host()); crostini::CrostiniPackageService::GetForProfile(profile)->GetLinuxPackageInfo( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), file_system_context->CrackURLInFirstPartyContext(GURL(params->url)), base::BindOnce(&FileManagerPrivateInternalGetLinuxPackageInfoFunction:: OnGetLinuxPackageInfo, @@ -1055,7 +1055,7 @@ crostini::CrostiniPackageService::GetForProfile(profile) ->QueueInstallLinuxPackage( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), file_system_context->CrackURLInFirstPartyContext(GURL(params->url)), base::BindOnce( &FileManagerPrivateInternalInstallLinuxPackageFunction::
diff --git a/chrome/browser/commerce/android/shopping_service_factory_android.cc b/chrome/browser/commerce/android/shopping_service_factory_android.cc index 229894e..ca9470b 100644 --- a/chrome/browser/commerce/android/shopping_service_factory_android.cc +++ b/chrome/browser/commerce/android/shopping_service_factory_android.cc
@@ -6,6 +6,7 @@ #include "base/android/scoped_java_ref.h" #include "chrome/browser/commerce/android/shopping_service_jni/ShoppingServiceFactory_jni.h" #include "chrome/browser/commerce/shopping_service_factory.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" #include "components/commerce/core/android/shopping_service_android.h" #include "components/commerce/core/shopping_service.h" @@ -22,9 +23,11 @@ ScopedJavaLocalRef<jobject> JNI_ShoppingServiceFactory_GetForProfile( JNIEnv* env, const JavaParamRef<jobject>& j_profile) { - ShoppingService* service = ShoppingServiceFactory::GetForBrowserContext( - ProfileAndroid::FromProfileAndroid(j_profile)); + Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); + CHECK(profile); + ShoppingService* service = + ShoppingServiceFactory::GetForBrowserContext(profile); CHECK(service); ShoppingServiceAndroid* bridge = static_cast<ShoppingServiceAndroid*>(
diff --git a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProvider.java b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProvider.java index 8276f2c..7d9ce5b 100644 --- a/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProvider.java +++ b/chrome/browser/commerce/merchant_viewer/android/java/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProvider.java
@@ -19,6 +19,10 @@ * Fetches {@link MerchantInfo} based on {@link GURL}. */ public void getDataForUrl(Profile profile, GURL url, Callback<MerchantInfo> callback) { + if (profile == null || profile.isOffTheRecord()) { + callback.onResult(null); + return; + } ShoppingServiceFactory.getForProfile(profile).getMerchantInfoForUrl(url, (gurl, info) -> callback.onResult(isValidMerchantTrustSignals(info) ? info : null)); }
diff --git a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProviderTest.java b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProviderTest.java index 2a22a61..fe200ed 100644 --- a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProviderTest.java +++ b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustSignalsDataProviderTest.java
@@ -99,6 +99,35 @@ } @Test + public void testGetDataForNullProfile() throws TimeoutException { + MerchantTrustSignalsDataProvider instance = getDataProvider(); + + MerchantTrustSignalsCallbackHelper callbackHelper = + new MerchantTrustSignalsCallbackHelper(); + + int callCount = callbackHelper.getCallCount(); + mockShoppingServiceResponse(mFakeMerchantTrustSignals); + instance.getDataForUrl(null, mMockDestinationGurl, callbackHelper::notifyCalled); + callbackHelper.waitForCallback(callCount); + Assert.assertNull(callbackHelper.getMerchantTrustSignalsResult()); + } + + @Test + public void testGetDataForIncognitoProfile() throws TimeoutException { + doReturn(true).when(mMockProfile).isOffTheRecord(); + MerchantTrustSignalsDataProvider instance = getDataProvider(); + + MerchantTrustSignalsCallbackHelper callbackHelper = + new MerchantTrustSignalsCallbackHelper(); + + int callCount = callbackHelper.getCallCount(); + mockShoppingServiceResponse(mFakeMerchantTrustSignals); + instance.getDataForUrl(mMockProfile, mMockDestinationGurl, callbackHelper::notifyCalled); + callbackHelper.waitForCallback(callCount); + Assert.assertNull(callbackHelper.getMerchantTrustSignalsResult()); + } + + @Test public void testIsValidMerchantTrustSignals() { MerchantTrustSignalsDataProvider instance = getDataProvider(); Assert.assertTrue(instance.isValidMerchantTrustSignals(mFakeMerchantTrustSignals));
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingFeatures.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingFeatures.java index b1766a4..e50f2cc 100644 --- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingFeatures.java +++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingFeatures.java
@@ -24,6 +24,7 @@ @VisibleForTesting public static final String ALLOW_DISABLE_PRICE_ANNOTATIONS_PARAM = "allow_disable_price_annotations"; + private static final String PRICE_DROP_IPH_ENABLED_PARAM = "enable_price_drop_iph"; private static final String PRICE_ANNOTATIONS_ENABLED_METRICS_WINDOW_DURATION_PARAM = "price_annotations_enabled_metrics_window_duration_ms"; @@ -119,4 +120,14 @@ } return isPriceTrackingEligible(); } + + public static boolean isPriceDropIphEnabled() { + if (FeatureList.isInitialized()) { + return isPriceTrackingEligible() + && ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( + ChromeFeatureList.COMMERCE_PRICE_TRACKING, PRICE_DROP_IPH_ENABLED_PARAM, + false); + } + return isPriceTrackingEligible(); + } } \ No newline at end of file
diff --git a/chrome/browser/component_updater/cros_component_installer_chromeos.cc b/chrome/browser/component_updater/cros_component_installer_chromeos.cc index c53c5ee..ec2d3319 100644 --- a/chrome/browser/component_updater/cros_component_installer_chromeos.cc +++ b/chrome/browser/component_updater/cros_component_installer_chromeos.cc
@@ -39,7 +39,7 @@ const ComponentConfig kConfigs[] = { {"cros-termina", ComponentConfig::PolicyType::kEnvVersion, "980.1", "e9d960f84f628e1f42d05de4046bb5b3154b6f1f65c08412c6af57a29aecaffb"}, - {"rtanalytics-full", ComponentConfig::PolicyType::kEnvVersion, "100.0", + {"rtanalytics-full", ComponentConfig::PolicyType::kEnvVersion, "103.0", "c93c3e1013c52100a20038b405ac854d69fa889f6dc4fa6f188267051e05e444"}, {"demo-mode-resources", ComponentConfig::PolicyType::kEnvVersion, "1.0", "93c093ebac788581389015e9c59c5af111d2fa5174d206eb795042e6376cbd10"},
diff --git a/chrome/browser/download/download_item_model_unittest.cc b/chrome/browser/download/download_item_model_unittest.cc index f3e279a6..e15a489 100644 --- a/chrome/browser/download/download_item_model_unittest.cc +++ b/chrome/browser/download/download_item_model_unittest.cc
@@ -117,6 +117,11 @@ .WillByDefault( Return(DownloadItem::TARGET_DISPOSITION_OVERWRITE)); ON_CALL(item_, IsPaused()).WillByDefault(Return(false)); + ON_CALL(item_, GetMixedContentStatus()) + .WillByDefault( + Return(download::DownloadItem::MixedContentStatus::SAFE)); + ON_CALL(item(), GetDangerType()) + .WillByDefault(Return(download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); } void SetupInterruptedDownloadItem(download::DownloadInterruptReason reason) { @@ -387,11 +392,6 @@ // For GetReceivedBytes()/GetTotalBytes(), we only check whether each is // non-zero. In addition, if |total_bytes| is zero, then // |time_remaining_known| is also false. - // - // .-- .TimeRemaining() is known. - // | .-- .GetOpenWhenComplete() - // | | .---- .IsPaused() - // | | | .---- .GetRerouteInfo() {0, 0, false, @@ -556,6 +556,7 @@ {}, "1/2 B, Paused", "1/2 B \xE2\x80\xA2 Paused"}, + {5, 5, false, false, false, {}, "", "5 B \xE2\x80\xA2 Done"}, {5, 5, true, true, false, kTestRerouteInfo, reroute_status, base::StrCat({"5 B \xE2\x80\xA2 ", reroute_status})}}; @@ -638,6 +639,63 @@ base::UTF16ToUTF8(model().GetShowInFolderText())); } +TEST_F(DownloadItemModelTest, CompletedBubbleWarningStatusText) { + SetupCompletedDownloadItem(base::Hours(1)); + SetStatusTextBuilder(/*for_bubble=*/true); + + const struct MixedContentStatusTestCase { + download::DownloadItem::MixedContentStatus mixed_content_status; + std::string expected_bubble_status_msg; + } kMixedContentStatusTestCases[] = { + {download::DownloadItem::MixedContentStatus::BLOCK, + "Blocked \xE2\x80\xA2 Insecure download"}, + {download::DownloadItem::MixedContentStatus::WARN, + "Blocked \xE2\x80\xA2 Insecure download"}, + }; + for (const auto& test_case : kMixedContentStatusTestCases) { + SetupDownloadItemDefaults(); + ON_CALL(item(), GetMixedContentStatus()) + .WillByDefault(Return(test_case.mixed_content_status)); + EXPECT_EQ(base::UTF16ToUTF8(model().GetStatusText()), + test_case.expected_bubble_status_msg); + } + + const struct DangerTypeTestCase { + download::DownloadDangerType danger_type; + std::string expected_bubble_status_msg; + } kDangerTypeTestCases[] = { + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, + "Blocked \xE2\x80\xA2 Dangerous"}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, + "Blocked \xE2\x80\xA2 Dangerous"}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST, + "Blocked \xE2\x80\xA2 Dangerous"}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE, + "Blocked \xE2\x80\xA2 Dangerous"}, + {download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, + "Blocked \xE2\x80\xA2 Dangerous"}, + {download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED, + "Blocked \xE2\x80\xA2 Encrypted"}, + {download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, + "Blocked \xE2\x80\xA2 Malware"}, + {download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE, + "Blocked \xE2\x80\xA2 Too big"}, + {download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING, + "Sensitive content"}, + {download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK, + "Blocked by your organization"}, + {download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING, + "Scan before opening"}, + }; + for (const auto& test_case : kDangerTypeTestCases) { + SetupDownloadItemDefaults(); + ON_CALL(item(), GetDangerType()) + .WillByDefault(Return(test_case.danger_type)); + EXPECT_EQ(base::UTF16ToUTF8(model().GetStatusText()), + test_case.expected_bubble_status_msg); + } +} + TEST_F(DownloadItemModelTest, ShouldShowInShelf) { SetupDownloadItemDefaults();
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index 65a5442..06698e1 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc
@@ -146,18 +146,21 @@ const char* const kPathPrefs[] = {prefs::kSaveFileDefaultDirectory, prefs::kDownloadDefaultDirectory}; for (const char* path_pref : kPathPrefs) { - const base::FilePath current = prefs->GetFilePath(path_pref); - base::FilePath migrated; - if (!current.empty() && - file_manager::util::MigratePathFromOldFormat( - profile_, GetDefaultDownloadDirectory(), current, &migrated)) { - prefs->SetFilePath(path_pref, migrated); - } else if (file_manager::util::MigrateToDriveFs(profile_, current, - &migrated)) { - prefs->SetFilePath(path_pref, migrated); - } else if (download_dir_util::ExpandDrivePolicyVariable(profile_, current, - &migrated)) { - prefs->SetFilePath(path_pref, migrated); + // Update the download directory if the pref is from user pref store. + if (prefs->FindPreference(path_pref)->IsUserControlled()) { + const base::FilePath current = prefs->GetFilePath(path_pref); + base::FilePath migrated; + if (!current.empty() && + file_manager::util::MigratePathFromOldFormat( + profile_, GetDefaultDownloadDirectory(), current, &migrated)) { + prefs->SetFilePath(path_pref, migrated); + } else if (file_manager::util::MigrateToDriveFs(profile_, current, + &migrated)) { + prefs->SetFilePath(path_pref, migrated); + } else if (download_dir_util::ExpandDrivePolicyVariable(profile_, current, + &migrated)) { + prefs->SetFilePath(path_pref, migrated); + } } } @@ -172,23 +175,26 @@ should_open_pdf_in_system_reader_ = prefs->GetBoolean(prefs::kOpenPdfDownloadInSystemReader); #endif - - base::FilePath current_download_dir = - prefs->GetFilePath(prefs::kDownloadDefaultDirectory); - if (!current_download_dir.IsAbsolute()) { - // If we have a relative path or an empty path, we should reset to a safe, - // well-known path. - prefs->SetFilePath(prefs::kDownloadDefaultDirectory, - GetDefaultDownloadDirectoryForProfile()); - } else if (!prefs->GetBoolean(prefs::kDownloadDirUpgraded)) { - // If the download path is dangerous we forcefully reset it. But if we do - // so we set a flag to make sure we only do it once, to avoid fighting - // the user if they really want it on an unsafe place such as the desktop. - if (DownloadPathIsDangerous(current_download_dir)) { + // Update the download directory if the pref is from user pref store. + if (prefs->FindPreference(prefs::kDownloadDefaultDirectory) + ->IsUserControlled()) { + base::FilePath current_download_dir = + prefs->GetFilePath(prefs::kDownloadDefaultDirectory); + if (!current_download_dir.IsAbsolute()) { + // If we have a relative path or an empty path, we should reset to a safe, + // well-known path. prefs->SetFilePath(prefs::kDownloadDefaultDirectory, GetDefaultDownloadDirectoryForProfile()); + } else if (!prefs->GetBoolean(prefs::kDownloadDirUpgraded)) { + // If the download path is dangerous we forcefully reset it. But if we do + // so we set a flag to make sure we only do it once, to avoid fighting + // the user if they really want it on an unsafe place such as the desktop. + if (DownloadPathIsDangerous(current_download_dir)) { + prefs->SetFilePath(prefs::kDownloadDefaultDirectory, + GetDefaultDownloadDirectoryForProfile()); + } + prefs->SetBoolean(prefs::kDownloadDirUpgraded, true); } - prefs->SetBoolean(prefs::kDownloadDirUpgraded, true); } prompt_for_download_.Init(prefs::kPromptForDownload, prefs); @@ -631,6 +637,11 @@ base::FilePath migrated_drive_path; // Managed prefs may force a legacy Drive path as the download path. Ensure // the path is valid when DriveFS is enabled. + if (!path.empty() && file_manager::util::MigratePathFromOldFormat( + profile_, GetDefaultDownloadDirectory(), path, + &migrated_drive_path)) { + return SanitizeDownloadTargetPath(migrated_drive_path); + } if (file_manager::util::MigrateToDriveFs(profile_, path, &migrated_drive_path)) { return SanitizeDownloadTargetPath(migrated_drive_path);
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc index a94ed196..39b00ee 100644 --- a/chrome/browser/download/download_prefs_unittest.cc +++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/download/download_prefs.h" #include "base/files/file_path.h" +#include "base/json/values_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" @@ -22,7 +23,9 @@ #include "url/gurl.h" #if BUILDFLAG(IS_CHROMEOS_ASH) +#include "base/test/scoped_running_on_chromeos.h" #include "chrome/browser/ash/drive/drive_integration_service.h" +#include "chrome/browser/ash/file_manager/fake_disk_mount_manager.h" #include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/profiles/profile_helper.h" @@ -441,6 +444,68 @@ DownloadPrefs download_prefs(&profile); EXPECT_TRUE(download_prefs.DownloadPath().IsAbsolute()) << "Default download directory is " << download_prefs.DownloadPath(); + EXPECT_EQ( + base::ValueToFilePath(*(profile.GetTestingPrefService()->GetUserPref( + prefs::kDownloadDefaultDirectory))) + .value(), + download_prefs.GetDefaultDownloadDirectory()); +} + +TEST(DownloadPrefsTest, ManagedRelativePathDoesNotChangeUserPref) { + content::BrowserTaskEnvironment task_environment; + TestingProfile profile; + + profile.GetTestingPrefService()->SetManagedPref( + prefs::kDownloadDefaultDirectory, + base::FilePathToValue(base::FilePath::FromUTF8Unsafe(".."))); + profile.GetTestingPrefService()->SetManagedPref( + prefs::kSaveFileDefaultDirectory, + base::FilePathToValue(base::FilePath::FromUTF8Unsafe("../../../"))); + EXPECT_FALSE(profile.GetPrefs() + ->GetFilePath(prefs::kDownloadDefaultDirectory) + .IsAbsolute()); + EXPECT_FALSE(profile.GetPrefs() + ->GetFilePath(prefs::kSaveFileDefaultDirectory) + .IsAbsolute()); + + DownloadPrefs download_prefs(&profile); + EXPECT_FALSE(profile.GetTestingPrefService()->GetUserPref( + prefs::kDownloadDefaultDirectory)); + EXPECT_FALSE(profile.GetTestingPrefService()->GetUserPref( + prefs::kSaveFileDefaultDirectory)); +} + +TEST(DownloadPrefsTest, RecommendedRelativePathDoesNotChangeUserPref) { + content::BrowserTaskEnvironment task_environment; + TestingProfile profile; + + base::FilePath save_dir = DownloadPrefs::GetDefaultDownloadDirectory().Append( + base::FilePath::FromUTF8Unsafe("tmp")); + profile.GetTestingPrefService()->SetRecommendedPref( + prefs::kDownloadDefaultDirectory, + base::FilePathToValue(base::FilePath::FromUTF8Unsafe(".."))); + profile.GetTestingPrefService()->SetRecommendedPref( + prefs::kSaveFileDefaultDirectory, + base::FilePathToValue(base::FilePath::FromUTF8Unsafe("../../../"))); + profile.GetTestingPrefService()->SetUserPref(prefs::kSaveFileDefaultDirectory, + base::FilePathToValue(save_dir)); + EXPECT_FALSE(profile.GetPrefs() + ->GetFilePath(prefs::kDownloadDefaultDirectory) + .IsAbsolute()); + EXPECT_EQ(profile.GetPrefs()->GetFilePath(prefs::kSaveFileDefaultDirectory), + save_dir); + + DownloadPrefs download_prefs(&profile); + EXPECT_FALSE(profile.GetTestingPrefService()->GetUserPref( + prefs::kDownloadDefaultDirectory)); + EXPECT_EQ(base::ValueToFilePath(profile.GetTestingPrefService()->GetUserPref( + prefs::kSaveFileDefaultDirectory)) + .value(), + save_dir); + + EXPECT_EQ(download_prefs.DownloadPath(), + DownloadPrefs::GetDefaultDownloadDirectory()); + EXPECT_EQ(download_prefs.SaveFilePath(), save_dir); } TEST(DownloadPrefsTest, DefaultPathChangedToInvalidValue) { @@ -595,6 +660,29 @@ EXPECT_EQ(prefs2.DownloadPath(), default_dir2); } } + +#if BUILDFLAG(IS_CHROMEOS_ASH) +// Tests that download path is correct when migrated from old format. +TEST(DownloadPrefsTest, DownloadPathWithMigrationFromOldFormat) { + content::BrowserTaskEnvironment task_environment; + base::FilePath default_download_dir = + DownloadPrefs::GetDefaultDownloadDirectory(); + base::FilePath path_from_pref = default_download_dir.Append("a").Append("b"); + ash::disks::DiskMountManager::InitializeForTesting( + new file_manager::FakeDiskMountManager); + + TestingProfile profile(base::FilePath("/home/chronos/u-0123456789abcdef")); + base::test::ScopedRunningOnChromeOS running_on_chromeos; + // Using a managed pref to set the download dir. + profile.GetTestingPrefService()->SetManagedPref( + prefs::kDownloadDefaultDirectory, base::FilePathToValue(path_from_pref)); + + DownloadPrefs prefs(&profile); + // The relative path should be preserved after migration. + EXPECT_EQ(prefs.DownloadPath(), + base::FilePath("/home/chronos/u-0123456789abcdef/MyFiles/a/b")); +} +#endif // BUILDFLAG(IS_CHROMEOS_ASH) #endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/download/download_ui_model.cc b/chrome/browser/download/download_ui_model.cc index 3faed886..a45307cb 100644 --- a/chrome/browser/download/download_ui_model.cc +++ b/chrome/browser/download/download_ui_model.cc
@@ -7,7 +7,6 @@ #include "base/feature_list.h" #include "base/i18n/rtl.h" #include "base/observer_list.h" -#include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "build/build_config.h" @@ -1159,17 +1158,19 @@ std::u16string DownloadUIModel::BubbleStatusTextBuilder::GetBubbleWarningStatusText() const { - std::u16string prefix = base::StrCat( - {l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_STATUS_BLOCKED), - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SEPERATOR)}); + // If the detail message is "Malware", then this returns "Blocked • Malware" + auto get_blocked_warning = [](int detail_message_id) { + return l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR, + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_STATUS_BLOCKED), + l10n_util::GetStringUTF16(detail_message_id)); + }; switch (model_->GetMixedContentStatus()) { case download::DownloadItem::MixedContentStatus::BLOCK: case download::DownloadItem::MixedContentStatus::WARN: // "Blocked • Insecure download" - return base::StrCat( - {prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_WARNING_STATUS_INSECURE)}); + return get_blocked_warning(IDS_DOWNLOAD_BUBBLE_WARNING_STATUS_INSECURE); case download::DownloadItem::MixedContentStatus::UNKNOWN: case download::DownloadItem::MixedContentStatus::SAFE: case download::DownloadItem::MixedContentStatus::VALIDATED: @@ -1181,30 +1182,24 @@ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: // "Blocked • Unknown source" if (model_->IsExtensionDownload()) - return base::StrCat( - {prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_STATUS_UNKNOWN_SOURCE)}); + return get_blocked_warning(IDS_DOWNLOAD_BUBBLE_STATUS_UNKNOWN_SOURCE); [[fallthrough]]; case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT: case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST: case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE: case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED: // "Blocked • Dangerous" - return base::StrCat({prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_STATUS_DANGEROUS)}); + return get_blocked_warning(IDS_DOWNLOAD_BUBBLE_STATUS_DANGEROUS); case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED: // "Blocked • Encrypted" - return base::StrCat({prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_STATUS_ENCRYPTED)}); + return get_blocked_warning(IDS_DOWNLOAD_BUBBLE_STATUS_ENCRYPTED); case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: // "Blocked • Malware" - return base::StrCat({prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_STATUS_MALWARE)}); + return get_blocked_warning(IDS_DOWNLOAD_BUBBLE_STATUS_MALWARE); case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE: // "Blocked • Too big" - return base::StrCat({prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_STATUS_TOO_BIG)}); + return get_blocked_warning(IDS_DOWNLOAD_BUBBLE_STATUS_TOO_BIG); case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT: { bool request_ap_verdicts = false; #if BUILDFLAG(FULL_SAFE_BROWSING) @@ -1217,9 +1212,8 @@ return request_ap_verdicts ? l10n_util::GetStringUTF16( IDS_DOWNLOAD_BUBBLE_STATUS_ADVANCED_PROTECTION) - : base::StrCat( - {prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_STATUS_UNCOMMON_FILE)}); + : get_blocked_warning( + IDS_DOWNLOAD_BUBBLE_STATUS_UNCOMMON_FILE); } case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING: @@ -1231,13 +1225,17 @@ return l10n_util::GetStringUTF16( IDS_DOWNLOAD_BUBBLE_INTERRUPTED_STATUS_BLOCKED_ORGANIZATION); case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING: + // "Scan before opening" return l10n_util::GetStringUTF16( IDS_DOWNLOAD_BUBBLE_STATUS_DEEP_SCANNING_PROMPT); case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING: #if BUILDFLAG(IS_ANDROID) + // "Scanning..." return l10n_util::GetStringUTF16( IDS_DOWNLOAD_BUBBLE_STATUS_ASYNC_SCANNING); #else + // Either "Checking with your organization's security policies..." or + // "Scanning..." return download::IsDownloadConnectorEnabled(model_->profile()) ? l10n_util::GetStringUTF16( IDS_DOWNLOAD_BUBBLE_STATUS_ASYNC_SCANNING_ENTERPRISE) @@ -1277,78 +1275,89 @@ // Indication of progress. (E.g.:"100/200 MB" or "100MB") std::u16string size_ratio = model_->GetProgressSizesString(); - std::u16string size_ratio_prefix = base::StrCat( - {size_ratio, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SEPERATOR)}); + // If the detail message is "Paused" and the size_ratio is "100/120 MB", then + // this returns "100/120 MB • Paused". + auto get_size_ratio_string = [size_ratio](std::u16string detail_message) { + return l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR, size_ratio, + detail_message); + }; + // If the detail message is "Opening in 10 seconds..." and the size_ratio is + // "100/120 MB", then this returns "↓ 100/120 MB • Opening in 10 seconds...". + auto get_active_download_size_ratio_string = + [size_ratio](std::u16string detail_message) { + return l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR, + l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_WITH_SYMBOL, size_ratio), + detail_message); + }; const auto completed_bytes = model_->GetCompletedBytes(); const auto total_bytes = model_->GetTotalBytes(); - std::u16string total_prefix = base::StrCat( - {ui::FormatBytes(total_bytes), - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SEPERATOR)}); + // If the detail message is "Done" and the total_byes is "120 MB", then + // this returns "120 MB • Done". + auto get_total_string = [total_bytes](std::u16string detail_message) { + return l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR, + ui::FormatBytes(total_bytes), detail_message); + }; // The download is a CRX (app, extension, theme, ...) and it is being unpacked // and validated. if (model_->AllDataSaved() && model_->IsExtensionDownload()) { - return base::StrCat( - {total_prefix, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CRX_INSTALL_RUNNING)}); + // "120 MB • Adding to Chrome..." + return get_total_string( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CRX_INSTALL_RUNNING)); } // A paused download: "100/120 MB • Paused" if (model_->IsPaused()) { - return base::StrCat({size_ratio_prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_PROGRESS_PAUSED)}); + return get_size_ratio_string( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_PROGRESS_PAUSED)); } // A download scheduled to be opened when complete: "↓ 100/120 MB • Opening in // 10 seconds" if (web_drive.empty() && model_->GetOpenWhenComplete()) { if (!time_remaining_known) - return base::StrCat( - {size_ratio_prefix, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_OPEN_WHEN_COMPLETE)}); + // "100/120 MB • Opening when complete" + return get_size_ratio_string( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_OPEN_WHEN_COMPLETE)); - return base::StrCat( - {l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SYMBOL), - size_ratio_prefix, - l10n_util::GetStringFUTF16( - IDS_DOWNLOAD_STATUS_OPEN_IN, - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, - ui::TimeFormat::LENGTH_LONG, - time_remaining))}); + // "↓ 100/120 MB • Opening in 10 seconds..." + return get_active_download_size_ratio_string(l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_STATUS_OPEN_IN, + ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, + ui::TimeFormat::LENGTH_LONG, time_remaining))); } // In progress download with known time left: "↓ 100/120 MB • 10 seconds left" if (time_remaining_known) { - return base::StrCat( - {l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SYMBOL), - size_ratio_prefix, - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING, - ui::TimeFormat::LENGTH_LONG, time_remaining)}); + return get_active_download_size_ratio_string( + ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING, + ui::TimeFormat::LENGTH_LONG, time_remaining)); } if (completed_bytes == 0) { // "0/120 MB • Starting..." - return base::StrCat({size_ratio_prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_STATUS_STARTING)}); + return get_size_ratio_string( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_STARTING)); } else if (completed_bytes < total_bytes || total_bytes == 0) { // In progress download with no known time left and non-zero completed // bytes: "100/120 MB • Resuming..." or "100 MB • Resuming..." - return base::StrCat( - {size_ratio_prefix, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_STATUS_RESUMING)}); + return get_size_ratio_string( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_STATUS_RESUMING)); } else if (web_drive.size()) { // If all bytes of the file has been downloaded and it is being rerouted: // "120 MB • Sending to <WEB_DRIVE>..." - return base::StrCat( - {total_prefix, - l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_UPLOADING, web_drive)}); + return get_total_string( + l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_UPLOADING, web_drive)); } else { // "120 MB • Done" - return base::StrCat({total_prefix, l10n_util::GetStringUTF16( - IDS_DOWNLOAD_BUBBLE_STATUS_DONE)}); + return get_total_string( + l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_STATUS_DONE)); } } @@ -1389,6 +1398,7 @@ std::u16string delta_str; if (model_->GetDangerType() == download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE) { + // "2 B • Done, no issues found" delta_str = l10n_util::GetStringUTF16( IDS_DOWNLOAD_BUBBLE_STATUS_DEEP_SCANNING_DONE); } else { @@ -1402,10 +1412,9 @@ ui::TimeFormat::LENGTH_LONG, time_elapsed); } - return base::StrCat( - {size_text, - l10n_util::GetStringUTF16(IDS_DOWNLOAD_BUBBLE_DOWNLOAD_SEPERATOR), - delta_str}); + return l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_BUBBLE_DOWNLOAD_STATUS_MESSAGE_WITH_SEPARATOR, size_text, + delta_str); } }
diff --git a/chrome/browser/enterprise/connectors/service_provider_config.cc b/chrome/browser/enterprise/connectors/service_provider_config.cc index 5be7de8a..216f8ae7 100644 --- a/chrome/browser/enterprise/connectors/service_provider_config.cc +++ b/chrome/browser/enterprise/connectors/service_provider_config.cc
@@ -137,22 +137,38 @@ constexpr GoogleDlpSupportedFiles kGoogleDlpSupportedFiles; +constexpr std::array<SupportedTag, 2> kGoogleDlpSupportedTags = {{ + { + .name = "malware", + .display_name = "Threat protection", + .max_file_size = 52428800, + .supported_files = &kAllFilesAllowed, + }, + { + .name = "dlp", + .display_name = "Sensitive data protection", + .max_file_size = 52428800, + .supported_files = &kGoogleDlpSupportedFiles, + }, +}}; + constexpr AnalysisConfig kGoogleAnalysisConfig = { .url = "https://safebrowsing.google.com/safebrowsing/uploads/scan", - .supported_tags = {{ - { - .name = "malware", - .display_name = "Threat protection", - .max_file_size = 52428800, - .supported_files = &kAllFilesAllowed, - }, - { - .name = "dlp", - .display_name = "Sensitive data protection", - .max_file_size = 52428800, - .supported_files = &kGoogleDlpSupportedFiles, - }, - }}, + .supported_tags = base::span<const SupportedTag>(kGoogleDlpSupportedTags), +}; + +constexpr std::array<SupportedTag, 1> kLocalTestSupportedTags = {{ + { + .name = "dlp", + .display_name = "Sensitive data protection", + .max_file_size = 52428800, + .supported_files = &kAllFilesAllowed, + }, +}}; + +constexpr AnalysisConfig kLocalTestAnalysisConfig = { + .local_path = "test_path", + .supported_tags = base::span<const SupportedTag>(kLocalTestSupportedTags), }; constexpr ReportingConfig kGoogleReportingConfig = { @@ -190,6 +206,15 @@ .file_system = &kBoxFileSystemConfig, }, }, + // TODO(b/226560946): Add the actual local content analysis service + // providers to this config. + { + "local_test", + { + .display_name = "Local Test", + .analysis = &kLocalTestAnalysisConfig, + }, + }, }); return &kServiceProviderConfig; }
diff --git a/chrome/browser/enterprise/connectors/service_provider_config.h b/chrome/browser/enterprise/connectors/service_provider_config.h index c2f2e2d6..a0976d87 100644 --- a/chrome/browser/enterprise/connectors/service_provider_config.h +++ b/chrome/browser/enterprise/connectors/service_provider_config.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/containers/fixed_flat_map.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/values.h" @@ -33,8 +34,12 @@ }; struct AnalysisConfig { + // Only 1 of `url` and `local_path` should be populated to differentiate + // between cloud analysis providers and local analysis providers. const char* url = nullptr; - std::array<SupportedTag, 2> supported_tags; + const char* local_path = nullptr; + + const base::span<const SupportedTag> supported_tags; }; struct ReportingConfig { @@ -62,7 +67,7 @@ }; using ServiceProviderConfig = - base::fixed_flat_map<base::StringPiece, ServiceProvider, 2>; + base::fixed_flat_map<base::StringPiece, ServiceProvider, 3>; // Returns the global service provider configuration, containing every service // provider and each of their supported Connector configs.
diff --git a/chrome/browser/enterprise/connectors/service_provider_config_unittest.cc b/chrome/browser/enterprise/connectors/service_provider_config_unittest.cc index 0c6e31be..0f0b46a6 100644 --- a/chrome/browser/enterprise/connectors/service_provider_config_unittest.cc +++ b/chrome/browser/enterprise/connectors/service_provider_config_unittest.cc
@@ -90,14 +90,15 @@ } // namespace -TEST(ServiceProviderConfigTest, CurrentConfig) { - // Since this class should only be initialized with 1 value for now, all - // that's needed is a single test on that value checking every field. +TEST(ServiceProviderConfigTest, Google) { const ServiceProviderConfig* config = GetServiceProviderConfig(); - ASSERT_TRUE(config->count("google")); ServiceProvider service_provider = config->at("google"); + ASSERT_TRUE(service_provider.analysis); + ASSERT_TRUE(service_provider.reporting); + ASSERT_FALSE(service_provider.file_system); + ASSERT_EQ("https://safebrowsing.google.com/safebrowsing/uploads/scan", std::string(service_provider.analysis->url)); ASSERT_TRUE(GURL(service_provider.analysis->url).is_valid()); @@ -105,21 +106,23 @@ std::string(service_provider.reporting->url)); ASSERT_TRUE(GURL(service_provider.reporting->url).is_valid()); - ASSERT_EQ(2u, service_provider.analysis->supported_tags.size()); - ASSERT_EQ(std::string(service_provider.analysis->supported_tags.at(0).name), + // The Google service provider has 2 tags: malware and dlp. + ASSERT_EQ(service_provider.analysis->supported_tags.size(), 2u); + ASSERT_EQ(std::string(service_provider.analysis->supported_tags[0].name), "malware"); - ASSERT_EQ(service_provider.analysis->supported_tags.at(0).max_file_size, + ASSERT_EQ(service_provider.analysis->supported_tags[0].max_file_size, kMaxFileSize); - ASSERT_EQ(std::string(service_provider.analysis->supported_tags.at(1).name), + ASSERT_EQ(std::string(service_provider.analysis->supported_tags[1].name), "dlp"); - ASSERT_EQ(service_provider.analysis->supported_tags.at(1).max_file_size, + ASSERT_EQ(service_provider.analysis->supported_tags[1].max_file_size, kMaxFileSize); + // Only a subset of mime types and extensions are supported by Google DLP, but // every type is supported by malware scanning. const auto* malware_supported_files = - service_provider.analysis->supported_tags.at(0).supported_files; + service_provider.analysis->supported_tags[0].supported_files; const auto* dlp_supported_files = - service_provider.analysis->supported_tags.at(1).supported_files; + service_provider.analysis->supported_tags[1].supported_files; for (const base::FilePath::StringType& type : SupportedDlpFileTypes()) { ASSERT_TRUE(dlp_supported_files->FileExtensionSupported(FilePath(type))); ASSERT_TRUE( @@ -138,9 +141,50 @@ ASSERT_FALSE(dlp_supported_files->MimeTypeSupported(type)); ASSERT_TRUE(malware_supported_files->MimeTypeSupported(type)); } +} +TEST(ServiceProviderConfigTest, LocalTest) { + const ServiceProviderConfig* config = GetServiceProviderConfig(); + ASSERT_TRUE(config->count("local_test")); + ServiceProvider service_provider = config->at("local_test"); + + ASSERT_TRUE(service_provider.analysis); + ASSERT_FALSE(service_provider.reporting); + ASSERT_FALSE(service_provider.file_system); + + ASSERT_FALSE(service_provider.analysis->url); + ASSERT_TRUE(service_provider.analysis->local_path); + ASSERT_EQ("test_path", std::string(service_provider.analysis->local_path)); + + // The test local service provider has 1 tag: dlp. + ASSERT_EQ(service_provider.analysis->supported_tags.size(), 1u); + ASSERT_EQ(std::string(service_provider.analysis->supported_tags[0].name), + "dlp"); + ASSERT_EQ(service_provider.analysis->supported_tags[0].max_file_size, + kMaxFileSize); + + // Every type of file is supported for the test local content analysis service + // provider. + const auto* dlp_supported_files = + service_provider.analysis->supported_tags[0].supported_files; + for (const base::FilePath::StringType& type : SupportedDlpFileTypes()) + ASSERT_TRUE(dlp_supported_files->FileExtensionSupported(FilePath(type))); + for (const base::FilePath::StringType& type : UnsupportedDlpFileTypes()) + ASSERT_TRUE(dlp_supported_files->FileExtensionSupported(FilePath(type))); + for (const std::string& type : SupportedDlpMimeTypes()) + ASSERT_TRUE(dlp_supported_files->MimeTypeSupported(type)); + for (const std::string& type : UnsupportedDlpMimeTypes()) + ASSERT_TRUE(dlp_supported_files->MimeTypeSupported(type)); +} + +TEST(ServiceProviderConfigTest, Box) { + const ServiceProviderConfig* config = GetServiceProviderConfig(); ASSERT_TRUE(config->count("box")); - service_provider = config->at("box"); + ServiceProvider service_provider = config->at("box"); + + ASSERT_FALSE(service_provider.analysis); + ASSERT_FALSE(service_provider.reporting); + ASSERT_TRUE(service_provider.file_system); ASSERT_EQ("https://box.com", std::string(service_provider.file_system->home)); ASSERT_EQ("https://account.box.com/api/oauth2/authorize",
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc index 4d2c202..30a4ccd 100644 --- a/chrome/browser/extensions/api/preference/preference_api.cc +++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -488,6 +488,10 @@ base::BindRepeating(&PreferenceEventRouter::OnAshPrefChanged, base::Unretained(this), pref_path, pref.extension_pref, pref.browser_pref))); + registrar_.Add( + pref.browser_pref, + base::BindRepeating(&PreferenceEventRouter::OnControlledPrefChanged, + base::Unretained(this), registrar_.prefs())); continue; } #endif @@ -508,6 +512,43 @@ PreferenceEventRouter::~PreferenceEventRouter() = default; #if BUILDFLAG(IS_CHROMEOS_LACROS) +void PreferenceEventRouter::OnControlledPrefChanged( + PrefService* pref_service, + const std::string& browser_pref) { + // This pref has a corresponding value in ash. We should send the updated + // value of the pref to ash. + auto* lacros_service = chromeos::LacrosService::Get(); + if (!lacros_service || + !lacros_service->IsAvailable<crosapi::mojom::Prefs>()) { + // Without the service, we cannot update this pref in ash. + LOG(ERROR) << ErrorUtils::FormatErrorMessage( + "API unavailable to set pref * in ash.", browser_pref); + return; + } + + crosapi::mojom::PrefPath pref_path = + PrefMapping::GetInstance()->GetPrefPathForPrefName(browser_pref); + // Should be a known pref path. Otherwise we would not have created this + // observer. + DCHECK(pref_path != crosapi::mojom::PrefPath::kUnknown); + + const PrefService::Preference* pref = + pref_service->FindPreference(browser_pref); + CHECK(pref); + if (pref->IsExtensionControlled()) { + // The pref has been set in lacros by an extension. + // Transmit the value to ash to be stored in the standalone browser + // prefstore. + lacros_service->GetRemote<crosapi::mojom::Prefs>()->SetPref( + pref_path, pref->GetValue()->Clone(), base::OnceClosure()); + } else { + // The pref hasn't been set in lacros. + // Remove any value from the standalone browser prefstore in ash. + lacros_service->GetRemote<crosapi::mojom::Prefs>() + ->ClearExtensionControlledPref(pref_path, base::OnceClosure()); + } +} + void PreferenceEventRouter::OnAshPrefChanged(crosapi::mojom::PrefPath pref_path, const std::string& extension_pref, const std::string& browser_pref, @@ -727,6 +768,13 @@ DCHECK(rv); EventRouter::Get(profile_)->RegisterObserver(this, event_name); } +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // On lacros, ensure the PreferenceEventRouter is always created to watch for + // and notify of any pref changes, even if there's no extension listeners. + // TODO(crbug.com/1334829): Abstract out lacros logic from the + // PreferenceEventRouter so we don't needlessly dispatch extension events. + EnsurePreferenceEventRouterCreated(); +#endif content_settings_store()->AddObserver(this); } @@ -754,10 +802,17 @@ } void PreferenceAPI::OnListenerAdded(const EventListenerInfo& details) { - preference_event_router_ = std::make_unique<PreferenceEventRouter>(profile_); + EnsurePreferenceEventRouterCreated(); EventRouter::Get(profile_)->UnregisterObserver(this); } +void PreferenceAPI::EnsurePreferenceEventRouterCreated() { + if (!preference_event_router_) { + preference_event_router_ = + std::make_unique<PreferenceEventRouter>(profile_); + } +} + void PreferenceAPI::OnContentSettingChanged(const std::string& extension_id, bool incognito) { if (incognito) {
diff --git a/chrome/browser/extensions/api/preference/preference_api.h b/chrome/browser/extensions/api/preference/preference_api.h index 5c0ce98..993fdc3 100644 --- a/chrome/browser/extensions/api/preference/preference_api.h +++ b/chrome/browser/extensions/api/preference/preference_api.h
@@ -75,6 +75,11 @@ absl::optional<::base::Value> opt_value, crosapi::mojom::PrefControlState control_state); + // Callback for lacros version of the prefs, to update ash in the event that + // they are changed. + void OnControlledPrefChanged(PrefService* pref_service, + const std::string& browser_pref); + std::vector<std::unique_ptr<crosapi::mojom::PrefObserver>> extension_pref_observers_; #endif @@ -159,6 +164,9 @@ // EventRouter::Observer implementation. void OnListenerAdded(const EventListenerInfo& details) override; + // Ensures that a PreferenceEventRouter is created only once. + void EnsurePreferenceEventRouterCreated(); + private: friend class BrowserContextKeyedAPIFactory<PreferenceAPI>;
diff --git a/chrome/browser/extensions/api/preference/preference_api_constants.cc b/chrome/browser/extensions/api/preference/preference_api_constants.cc index ba641ce..7e08388 100644 --- a/chrome/browser/extensions/api/preference/preference_api_constants.cc +++ b/chrome/browser/extensions/api/preference/preference_api_constants.cc
@@ -27,7 +27,7 @@ "Be sure to declare in your manifest what permissions you need."; const char kPrimaryProfileOnlyErrorMessage[] = - "You may only access this preference in the primary profile."; + "You may only access the preference '*' in the primary profile."; } // namespace preference_api_constants } // namespace extensions
diff --git a/chrome/browser/extensions/api/preference/preference_api_lacros_browsertest.cc b/chrome/browser/extensions/api/preference/preference_api_lacros_browsertest.cc index 7617830..9742fb2 100644 --- a/chrome/browser/extensions/api/preference/preference_api_lacros_browsertest.cc +++ b/chrome/browser/extensions/api/preference/preference_api_lacros_browsertest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/common/pref_names.h" #include "chromeos/crosapi/mojom/prefs.mojom-test-utils.h" +#include "chromeos/crosapi/mojom/prefs.mojom.h" #include "chromeos/lacros/lacros_service.h" #include "chromeos/lacros/lacros_test_helper.h" #include "chromeos/startup/browser_init_params.h" @@ -122,6 +123,15 @@ if (!IsServiceAvailable()) { return; } + absl::optional<::base::Value> out_value; + crosapi::mojom::PrefsAsyncWaiter async_waiter( + chromeos::LacrosService::Get()->GetRemote<crosapi::mojom::Prefs>().get()); + + // At start, the value in ash should not be set. + async_waiter.GetPref(crosapi::mojom::PrefPath::kAccessibilityAutoclickEnabled, + &out_value); + EXPECT_FALSE(out_value.value().GetBool()); + base::FilePath extension_path = test_data_dir_.AppendASCII("preference/lacros"); { @@ -135,6 +145,11 @@ } CheckPreferencesSet(); + // In ash, the value should now be set. + async_waiter.GetPref(crosapi::mojom::PrefPath::kAccessibilityAutoclickEnabled, + &out_value); + EXPECT_TRUE(out_value.value().GetBool()); + // The settings should not be reset when the extension is reloaded. { ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply); @@ -152,6 +167,15 @@ observer.WaitForExtensionUninstalled(); CheckPreferencesCleared(); + if (DoesAshSupportObservers()) { + // When the extension in uninstalled, the pref in lacros should be the + // default value (false). This only works if Ash correctly implements + // extension-controlled pref observers. + async_waiter.GetPref( + crosapi::mojom::PrefPath::kAccessibilityAutoclickEnabled, &out_value); + EXPECT_FALSE(out_value.value().GetBool()); + } + { ExtensionTestMessageListener listener("ready", ReplyBehavior::kWillReply); EXPECT_TRUE(LoadExtension(extension_path));
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc index 15ba00df..a48d9b71 100644 --- a/chrome/browser/extensions/updater/extension_updater_unittest.cc +++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -1507,7 +1507,11 @@ std::set<int> requests({0}); std::unique_ptr<ExtensionDownloader::ExtensionFetch> fetch = std::make_unique<ExtensionDownloader::ExtensionFetch>( - id, test_url, hash, version.GetString(), requests, fetch_priority); + ExtensionDownloaderTask(id, GURL() /*update_url*/, + ManifestLocation::kInternal, + false /*is_corrupt_reinstall*/, + 0 /*request_id*/, fetch_priority), + test_url, hash, version.GetString(), requests, fetch_priority); updater.downloader_->FetchUpdatedExtension(std::move(fetch), absl::nullopt); @@ -1550,7 +1554,11 @@ requests.insert(0); std::unique_ptr<ExtensionDownloader::ExtensionFetch> fetch = std::make_unique<ExtensionDownloader::ExtensionFetch>( - id, test_url, hash, version.GetString(), requests, + ExtensionDownloaderTask( + id, GURL() /*update_url*/, ManifestLocation::kInternal, + false /*is_corrupt_reinstall*/, 0 /*request_id*/, + DownloadFetchPriority::kBackground), + test_url, hash, version.GetString(), requests, DownloadFetchPriority::kBackground); updater.downloader_->FetchUpdatedExtension(std::move(fetch), absl::nullopt); @@ -1824,7 +1832,11 @@ requests.insert(0); std::unique_ptr<ExtensionDownloader::ExtensionFetch> extension_fetch = std::make_unique<ExtensionDownloader::ExtensionFetch>( - id, test_url, hash, version.GetString(), requests, + ExtensionDownloaderTask( + id, GURL() /*update_url*/, ManifestLocation::kInternal, + false /*is_corrupt_reinstall*/, 0 /*request_id*/, + DownloadFetchPriority::kBackground), + test_url, hash, version.GetString(), requests, DownloadFetchPriority::kBackground); updater.downloader_->FetchUpdatedExtension(std::move(extension_fetch), absl::nullopt); @@ -2046,11 +2058,19 @@ // Start two fetches std::unique_ptr<ExtensionDownloader::ExtensionFetch> fetch1 = std::make_unique<ExtensionDownloader::ExtensionFetch>( - id1, url1, hash1, version1, requests, + ExtensionDownloaderTask( + id1, GURL() /*update_url*/, ManifestLocation::kInternal, + false /*is_corrupt_reinstall*/, 0 /*request_id*/, + DownloadFetchPriority::kBackground), + url1, hash1, version1, requests, DownloadFetchPriority::kBackground); std::unique_ptr<ExtensionDownloader::ExtensionFetch> fetch2 = std::make_unique<ExtensionDownloader::ExtensionFetch>( - id2, url2, hash2, version2, requests, + ExtensionDownloaderTask( + id2, GURL() /*update_url*/, ManifestLocation::kInternal, + false /*is_corrupt_reinstall*/, 0 /*request_id*/, + DownloadFetchPriority::kBackground), + url2, hash2, version2, requests, DownloadFetchPriority::kBackground); updater.downloader_->FetchUpdatedExtension(std::move(fetch1), absl::optional<std::string>());
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 6b960d55..ff01e52 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2991,6 +2991,13 @@ "expiry_milestone": -1 }, { + "name": "enable-webgpu-developer-features", + "owners": [ "//third_party/blink/renderer/modules/webgpu/OWNERS" ], + // This flag is the only way for developers to use WebGPU features + // that are development-centric. + "expiry_milestone": -1 + }, + { "name": "enable-webrtc-analog-agc-clipping-control", "owners": [ "alessiob", "silen", "minyue" ], "expiry_milestone": 103
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json index d7a4d86c..1494c37 100644 --- a/chrome/browser/flag-never-expire-list.json +++ b/chrome/browser/flag-never-expire-list.json
@@ -66,6 +66,7 @@ "enable-webassembly-tiering", "enable-webgl-developer-extensions", "enable-webgl-draft-extensions", + "enable-webgpu-developer-features", "enable-zero-copy", "extensions-on-chrome-urls", "force-color-profile",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index e12e5ec..e51bdccc 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2856,6 +2856,11 @@ "Enabling this option allows web applications to access the WebGL " "extensions that are still in draft status."; +const char kWebGpuDeveloperFeaturesName[] = "WebGPU Developer Features"; +const char kWebGpuDeveloperFeaturesDescription[] = + "Enables web applications to access WebGPU features intended only for use " + "during development."; + const char kWebPaymentsExperimentalFeaturesName[] = "Experimental Web Payments API features"; const char kWebPaymentsExperimentalFeaturesDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 701ff70..ef09398 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1607,6 +1607,9 @@ extern const char kWebglDraftExtensionsName[]; extern const char kWebglDraftExtensionsDescription[]; +extern const char kWebGpuDeveloperFeaturesName[]; +extern const char kWebGpuDeveloperFeaturesDescription[]; + extern const char kWebPaymentsExperimentalFeaturesName[]; extern const char kWebPaymentsExperimentalFeaturesDescription[];
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java index 02a1ad65..25f9e39 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -29,7 +29,7 @@ * * To cache a flag from ChromeFeatureList: * - Set its default value by adding an entry to {@link #sDefaults}. - * - Add it to the list passed to {@link #cacheNativeFlags(List)}. + * - Add it to the list passed to {@link ChromeCachedFlags#cacheNativeFlags(List)}. * - Call {@link #isEnabled(String)} to query whether the cached flag is enabled. * Consider this the source of truth for whether the flag is turned on in the current session. * - When querying whether a cached feature is enabled from native, a @CalledByNative method can be @@ -49,60 +49,60 @@ private static Map<String, Boolean> sDefaults = ImmutableMap.<String, Boolean>builder() .put(ChromeFeatureList.ANONYMOUS_UPDATE_CHECKS, true) - .put(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID, false) - .put(ChromeFeatureList.LENS_CAMERA_ASSISTED_SEARCH, false) - .put(ChromeFeatureList.COMMAND_LINE_ON_NON_ROOTED, false) - .put(ChromeFeatureList.DOWNLOADS_AUTO_RESUMPTION_NATIVE, true) - .put(ChromeFeatureList.EARLY_LIBRARY_LOAD, true) - .put(ChromeFeatureList.ELASTIC_OVERSCROLL, true) - .put(ChromeFeatureList.ELIDE_PRIORITIZATION_OF_PRE_NATIVE_BOOTSTRAP_TASKS, true) - .put(ChromeFeatureList.IMMERSIVE_UI_MODE, false) - .put(ChromeFeatureList.OMNIBOX_ANDROID_AUXILIARY_SEARCH, false) - .put(ChromeFeatureList.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT, true) - .put(ChromeFeatureList.START_SURFACE_ANDROID, false) - .put(ChromeFeatureList.PAINT_PREVIEW_DEMO, false) - .put(ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP, false) - .put(ChromeFeatureList.PREFETCH_NOTIFICATION_SCHEDULING_INTEGRATION, false) - .put(ChromeFeatureList.STORE_HOURS, false) - .put(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, true) - .put(ChromeFeatureList.TAB_GROUPS_ANDROID, true) - .put(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID, false) - .put(ChromeFeatureList.TOOLBAR_USE_HARDWARE_BITMAP_DRAW, false) - .put(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS, false) - .put(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA, false) - .put(ChromeFeatureList.DYNAMIC_COLOR_ANDROID, true) - .put(ChromeFeatureList.DYNAMIC_COLOR_BUTTONS_ANDROID, false) - .put(ChromeFeatureList.INSTANT_START, false) - .put(ChromeFeatureList.TAB_TO_GTS_ANIMATION, true) - .put(ChromeFeatureList.TEST_DEFAULT_DISABLED, false) - .put(ChromeFeatureList.TEST_DEFAULT_ENABLED, true) - .put(ChromeFeatureList.INTEREST_FEED_V2, true) - .put(ChromeFeatureList.USE_CHIME_ANDROID_SDK, false) - .put(ChromeFeatureList.CCT_INCOGNITO_AVAILABLE_TO_THIRD_PARTY, false) - .put(ChromeFeatureList.READ_LATER, false) - .put(ChromeFeatureList.CCT_REMOVE_REMOTE_VIEW_IDS, true) - .put(ChromeFeatureList.CCT_INCOGNITO, true) - .put(ChromeFeatureList.EXPERIMENTS_FOR_AGSA, true) .put(ChromeFeatureList.APP_MENU_MOBILE_SITE_OPTION, false) - .put(ChromeFeatureList.OPTIMIZATION_GUIDE_PUSH_NOTIFICATIONS, false) - .put(ChromeFeatureList.NEW_WINDOW_APP_MENU, true) + .put(ChromeFeatureList.BACK_GESTURE_REFACTOR, false) + .put(ChromeFeatureList.CCT_INCOGNITO, true) + .put(ChromeFeatureList.CCT_INCOGNITO_AVAILABLE_TO_THIRD_PARTY, false) + .put(ChromeFeatureList.CCT_REMOVE_REMOTE_VIEW_IDS, true) .put(ChromeFeatureList.CCT_RESIZABLE_90_MAXIMUM_HEIGHT, false) .put(ChromeFeatureList.CCT_RESIZABLE_ALLOW_RESIZE_BY_USER_GESTURE, false) .put(ChromeFeatureList.CCT_RESIZABLE_FOR_FIRST_PARTIES, true) .put(ChromeFeatureList.CCT_RESIZABLE_FOR_THIRD_PARTIES, false) .put(ChromeFeatureList.CCT_TOOLBAR_CUSTOMIZATIONS, true) - .put(ChromeFeatureList.INSTANCE_SWITCHER, true) - .put(ChromeFeatureList.WEB_APK_TRAMPOLINE_ON_INITIAL_INTENT, true) + .put(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS, false) + .put(ChromeFeatureList.COMMAND_LINE_ON_NON_ROOTED, false) + .put(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID, false) + .put(ChromeFeatureList.CREATE_SAFEBROWSING_ON_STARTUP, false) + .put(ChromeFeatureList.CRITICAL_PERSISTED_TAB_DATA, false) + .put(ChromeFeatureList.DOWNLOADS_AUTO_RESUMPTION_NATIVE, true) + .put(ChromeFeatureList.DYNAMIC_COLOR_ANDROID, true) + .put(ChromeFeatureList.DYNAMIC_COLOR_BUTTONS_ANDROID, false) + .put(ChromeFeatureList.EARLY_LIBRARY_LOAD, true) + .put(ChromeFeatureList.ELASTIC_OVERSCROLL, true) + .put(ChromeFeatureList.ELIDE_PRIORITIZATION_OF_PRE_NATIVE_BOOTSTRAP_TASKS, true) + .put(ChromeFeatureList.EXPERIMENTS_FOR_AGSA, true) .put(ChromeFeatureList.FEED_LOADING_PLACEHOLDER, false) .put(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS, false) + .put(ChromeFeatureList.IMMERSIVE_UI_MODE, false) + .put(ChromeFeatureList.INCOGNITO_REAUTHENTICATION_FOR_ANDROID, false) + .put(ChromeFeatureList.INSTANCE_SWITCHER, true) + .put(ChromeFeatureList.INSTANT_START, false) + .put(ChromeFeatureList.INTEREST_FEED_V2, true) + .put(ChromeFeatureList.LENS_CAMERA_ASSISTED_SEARCH, false) + .put(ChromeFeatureList.NEW_WINDOW_APP_MENU, true) + .put(ChromeFeatureList.OMNIBOX_ANDROID_AUXILIARY_SEARCH, false) + .put(ChromeFeatureList.OPTIMIZATION_GUIDE_PUSH_NOTIFICATIONS, false) + .put(ChromeFeatureList.PAINT_PREVIEW_DEMO, false) + .put(ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP, false) + .put(ChromeFeatureList.PREFETCH_NOTIFICATION_SCHEDULING_INTEGRATION, false) + .put(ChromeFeatureList.READ_LATER, false) + .put(ChromeFeatureList.START_SURFACE_ANDROID, false) + .put(ChromeFeatureList.STORE_HOURS, false) + .put(ChromeFeatureList.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT, true) + .put(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, true) + .put(ChromeFeatureList.TAB_GROUPS_ANDROID, true) + .put(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID, false) .put(ChromeFeatureList.TAB_GROUPS_FOR_TABLETS, false) .put(ChromeFeatureList.TAB_STRIP_IMPROVEMENTS, false) - .put(ChromeFeatureList.BACK_GESTURE_REFACTOR, false) + .put(ChromeFeatureList.TAB_TO_GTS_ANIMATION, true) + .put(ChromeFeatureList.TEST_DEFAULT_DISABLED, false) + .put(ChromeFeatureList.TEST_DEFAULT_ENABLED, true) + .put(ChromeFeatureList.TOOLBAR_USE_HARDWARE_BITMAP_DRAW, false) .put(ChromeFeatureList.TRUSTED_WEB_ACTIVITY_NOTIFICATION_PERMISSION_DELEGATION, true) - .put(ChromeFeatureList.CREATE_SAFEBROWSING_ON_STARTUP, false) + .put(ChromeFeatureList.USE_CHIME_ANDROID_SDK, false) + .put(ChromeFeatureList.WEB_APK_TRAMPOLINE_ON_INITIAL_INTENT, true) .build(); - /** * Non-dynamic preference keys used historically for specific features. *
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManager.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManager.java index dae25b3..a8216b8 100644 --- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManager.java +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthManager.java
@@ -11,6 +11,7 @@ import org.chromium.chrome.browser.device_reauth.BiometricAuthRequester; import org.chromium.chrome.browser.device_reauth.ReauthenticatorBridge; +import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; @@ -82,7 +83,7 @@ // The implementation relies on {@link BiometricManager} which was introduced in API // level 29. Android Q is not supported due to a potential bug in BiometricPrompt. return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) - && ChromeFeatureList.isEnabled( + && CachedFeatureFlags.isEnabled( ChromeFeatureList.INCOGNITO_REAUTHENTICATION_FOR_ANDROID); }
diff --git a/chrome/browser/notifications/BUILD.gn b/chrome/browser/notifications/BUILD.gn index 1af211e..d5928adc 100644 --- a/chrome/browser/notifications/BUILD.gn +++ b/chrome/browser/notifications/BUILD.gn
@@ -110,6 +110,7 @@ "android/java/src/org/chromium/chrome/browser/notifications/PendingIntentProviderTest.java", "android/java/src/org/chromium/chrome/browser/notifications/StandardNotificationBuilderTest.java", "android/java/src/org/chromium/chrome/browser/notifications/ThrottlingNotificationSchedulerTest.java", + "android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java", "android/java/src/org/chromium/chrome/browser/notifications/channels/ChromeChannelDefinitionsTest.java", "android/java/src/org/chromium/chrome/browser/notifications/permissions/NotificationPermissionChangeReceiverTest.java", "android/java/src/org/chromium/chrome/browser/notifications/permissions/NotificationPermissionControllerTest.java", @@ -127,6 +128,7 @@ "//chrome/test/android:chrome_java_unit_test_support", "//components/browser_ui/notifications/android:java", "//components/embedder_support/android:junit_test_support", + "//components/url_formatter/android:url_formatter_java", "//third_party/android_deps:espresso_java", "//third_party/android_deps:robolectric_all_java", "//third_party/androidx:androidx_annotation_annotation_java", @@ -150,7 +152,6 @@ "android/java/src/org/chromium/chrome/browser/notifications/NotificationTestUtil.java", "android/java/src/org/chromium/chrome/browser/notifications/NotificationWrapperBuilderFactoryTest.java", "android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsInitializerTest.java", - "android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java", ] deps = [
diff --git a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java index 5d668a8..efe99283 100644 --- a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java +++ b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/channels/ChannelsUpdaterTest.java
@@ -15,28 +15,28 @@ import android.content.Context; import android.content.res.Resources; import android.os.Build; -import android.support.test.InstrumentationRegistry; import androidx.annotation.RequiresApi; -import androidx.test.filters.SmallTest; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; -import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.base.test.util.Batch; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; -import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.notifications.NotificationManagerProxy; import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl; import org.chromium.components.browser_ui.notifications.channels.ChannelsInitializer; -import org.chromium.content_public.browser.test.NativeLibraryTestUtils; +import org.chromium.components.url_formatter.UrlFormatter; +import org.chromium.components.url_formatter.UrlFormatterJni; import java.util.ArrayList; import java.util.Iterator; @@ -45,8 +45,7 @@ /** * Tests that ChannelsUpdater correctly initializes channels on the notification manager. */ -@RunWith(BaseJUnit4ClassRunner.class) -@Batch(Batch.UNIT_TESTS) +@RunWith(BaseRobolectricTestRunner.class) @RequiresApi(Build.VERSION_CODES.O) public class ChannelsUpdaterTest { private NotificationManagerProxy mNotificationManagerProxy; @@ -55,15 +54,16 @@ private Resources mMockResources; @Rule - public TestRule processor = new Features.JUnitProcessor(); + public JniMocker mJniMocker = new JniMocker(); + @Mock + private UrlFormatter.Natives mUrlFormatterJniMock; @Before public void setUp() { - // Not initializing the browser process is safe because - // UrlFormatter.formatUrlForSecurityDisplay() is stand-alone. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); + MockitoAnnotations.initMocks(this); + mJniMocker.mock(UrlFormatterJni.TEST_HOOKS, mUrlFormatterJniMock); - Context context = InstrumentationRegistry.getTargetContext(); + Context context = RuntimeEnvironment.getApplication(); mNotificationManagerProxy = new NotificationManagerProxyImpl(context); mMockResources = context.getResources(); @@ -89,7 +89,6 @@ } @Test - @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O) public void testShouldUpdateChannels_returnsFalsePreO() { @@ -99,7 +98,6 @@ } @Test - @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O) public void testShouldUpdateChannels_returnsTrueIfOAndNoSavedVersionInPrefs() { @@ -109,7 +107,6 @@ } @Test - @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O) public void testShouldUpdateChannels_returnsTrueIfOAndDifferentVersionInPrefs() { @@ -120,7 +117,6 @@ } @Test - @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O) public void testShouldUpdateChannels_returnsFalseIfOAndSameVersionInPrefs() { @@ -131,7 +127,6 @@ } @Test - @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O) public void testUpdateChannels_noopPreO() { @@ -146,7 +141,6 @@ } @Test - @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O) public void testUpdateChannels_createsExpectedChannelsAndUpdatesPref() { @@ -166,7 +160,6 @@ } @Test - @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O) public void testUpdateChannels_deletesLegacyChannelsAndCreatesExpectedOnes() {
diff --git a/chrome/browser/partnercustomizations/BUILD.gn b/chrome/browser/partnercustomizations/BUILD.gn index 0c9132e6..82482ef 100644 --- a/chrome/browser/partnercustomizations/BUILD.gn +++ b/chrome/browser/partnercustomizations/BUILD.gn
@@ -62,7 +62,7 @@ ] } -android_library("javatests") { +android_library("unit_device_javatests") { testonly = true sources = [ "junit/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizationsUnitTest.java",
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index d233f67..5008f1b 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -3423,14 +3423,9 @@ SendCopyCommandAndCheckCopyPasteClipboard("HEL"); } -// Flaky on Linux (https://crbug.com/1121446) -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -#define MAYBE_CombinedShiftArrowPresses DISABLED_CombinedShiftArrowPresses -#else -#define MAYBE_CombinedShiftArrowPresses CombinedShiftArrowPresses -#endif +// Flaky on multiple platforms (https://crbug.com/1121446) IN_PROC_BROWSER_TEST_F(PDFExtensionClipboardTest, - MAYBE_CombinedShiftArrowPresses) { + DISABLED_CombinedShiftArrowPresses) { LoadTestComboBoxPdfGetGuestContents(); // Give the editable combo box focus.
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 3fa6907..3e19cfac 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -73,8 +73,6 @@ #include "chrome/browser/sharing/click_to_call/click_to_call_metrics.h" #include "chrome/browser/sharing/click_to_call/click_to_call_utils.h" #include "chrome/browser/sharing/features.h" -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h" -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.h" #include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h" #include "chrome/browser/translate/chrome_translate_client.h" @@ -2087,7 +2085,6 @@ #if !BUILDFLAG(IS_FUCHSIA) AppendClickToCallItem(); #endif - AppendSharedClipboardItem(); // Add an ending separator if there are sharing items, otherwise remove the // starting separator iff we added one above. @@ -2127,18 +2124,6 @@ } #endif // !BUILDFLAG(IS_FUCHSIA) -void RenderViewContextMenu::AppendSharedClipboardItem() { - if (!ShouldOfferSharedClipboard(browser_context_, params_.selection_text)) - return; - - if (!shared_clipboard_context_menu_observer_) { - shared_clipboard_context_menu_observer_ = - std::make_unique<SharedClipboardContextMenuObserver>(this); - observers_.AddObserver(shared_clipboard_context_menu_observer_.get()); - } - shared_clipboard_context_menu_observer_->InitMenu(params_); -} - void RenderViewContextMenu::AppendRegionSearchItem() { // IDS_CONTENT_CONTEXT_LENS_REGION_SEARCH_ALT4 is the currently launched // string for the regions search menu item.
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h index e95f4669..f7f5df2a 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.h +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -48,7 +48,6 @@ class PrintPreviewContextMenuObserver; class Profile; class QuickAnswersMenuObserver; -class SharedClipboardContextMenuObserver; class SpellingMenuObserver; class SpellingOptionsSubMenuObserver; @@ -236,7 +235,6 @@ #if !BUILDFLAG(IS_FUCHSIA) void AppendClickToCallItem(); #endif - void AppendSharedClipboardItem(); void AppendRegionSearchItem(); bool AppendFollowUnfollowItem(); void AppendSendTabToSelfItem(bool add_separator); @@ -382,10 +380,6 @@ std::unique_ptr<ClickToCallContextMenuObserver> click_to_call_context_menu_observer_; - // Shared clipboard menu observer. - std::unique_ptr<SharedClipboardContextMenuObserver> - shared_clipboard_context_menu_observer_; - // The system app (if any) associated with the WebContents we're in. raw_ptr<const ash::SystemWebAppDelegate> system_app_ = nullptr;
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn index e9b0039..01a256ee 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
@@ -51,6 +51,7 @@ "dictation/macros/list_commands_macro.js", "dictation/macros/macro.js", "dictation/macros/macro_names.js", + "dictation/macros/nav_sent_macro.js", "dictation/macros/repeatable_key_press_macro.js", "dictation/macros/smart_delete_phrase_macro.js", "dictation/macros/smart_insert_before_macro.js", @@ -247,6 +248,7 @@ "dictation/macros/list_commands_macro.js", "dictation/macros/macro.js", "dictation/macros/macro_names.js", + "dictation/macros/nav_sent_macro.js", "dictation/macros/repeatable_key_press_macro.js", "dictation/macros/smart_delete_phrase_macro.js", "dictation/macros/smart_insert_before_macro.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js index 20d8b9f..64348e3 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/accessibility_common_test.js
@@ -41,7 +41,7 @@ async getPref(name) { return new Promise(resolve => { - chrome.settingsPrivate.getPref(name, (ret) => { + chrome.settingsPrivate.getPref(name, ret => { resolve(ret); }); });
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js index 4c7f27c..163ecf2f 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/autoclick/autoclick.js
@@ -73,7 +73,7 @@ this.scrollableBoundsListener_ = (x, y) => this.findScrollingContainerForPoint_(x, y); - chrome.automation.getDesktop((desktop) => { + chrome.automation.getDesktop(desktop => { this.desktop_ = desktop; // We use a hit test at a point to determine what automation node is
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js index 3c445b2a..768aa78 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation_test_base.js
@@ -228,7 +228,7 @@ */ async getPref(name) { return new Promise(resolve => { - chrome.settingsPrivate.getPref(name, (ret) => { + chrome.settingsPrivate.getPref(name, ret => { resolve(ret); }); });
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util.js index 2c51176..8a75968 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util.js
@@ -103,6 +103,62 @@ } /** + * Returns the start index of the sentence to the right of the caret. + * Indices are relative to `value`. Assumes that sentences are separated by + * punctuation specified in `EditingUtil.END_OF_SENTENCE_REGEX_`. If no next + * sentence can be found, returns `value.length`. + * @param {string} value + * @param {number} caretIndex + * @return {number} + */ + static navNextSent(value, caretIndex) { + const rightOfCaret = value.substring(caretIndex); + const index = rightOfCaret.search(EditingUtil.END_OF_SENTENCE_REGEX_); + if (index === -1) { + return value.length; + } + + // `index` should be relative to `value`; + return index + caretIndex + 1; + } + + /** + * Returns the start index of the sentence to the left of the caret. Indices + * are relative to `value`. Assumes that sentences are separated by + * punctuation specified in `EditingUtil.END_OF_SENTENCE_REGEX_`. If no + * previous sentence can be found, returns 0. + * @param {string} value + * @param {number} caretIndex + * @return {number|null} + */ + static navPrevSent(value, caretIndex) { + let encounteredText = false; + if (caretIndex === value.length) { + --caretIndex; + } + + while (caretIndex >= 0) { + const valueAtCaret = value[caretIndex]; + if (encounteredText && + EditingUtil.END_OF_SENTENCE_REGEX_.test(valueAtCaret)) { + // Adjust if there is whitespace immediately to the right of the caret. + return EditingUtil.BEGINS_WITH_WHITESPACE_REGEX_.test( + value[caretIndex + 1]) ? + caretIndex + 1 : + caretIndex; + } + + if (!EditingUtil.BEGINS_WITH_WHITESPACE_REGEX_.test(valueAtCaret) && + !EditingUtil.PUNCTUATION_REGEX_.test(valueAtCaret)) { + encounteredText = true; + } + --caretIndex; + } + + return 0; + } + + /** * Returns a RegExp that matches on the right-most occurrence of a phrase. * The returned RegExp is case insensitive and requires that `phrase` is * separated by word boundaries. @@ -134,3 +190,22 @@ return new RegExp(`(\\b${phrase}\\b )(?!.*\\b\\1\\b)`, 'i'); } } + +/** + * @private {!RegExp} + * @const + */ +EditingUtil.END_OF_SENTENCE_REGEX_ = /[;!.?]/; + +/** + * @private {!RegExp} + * @const + */ +EditingUtil.BEGINS_WITH_WHITESPACE_REGEX_ = /^\s/; + +/** + * @private {!RegExp} + * @const + */ +EditingUtil.PUNCTUATION_REGEX_ = + /[-$#"()*;:<>\n\\\/\{\}\[\]+='~`!@_.,?%\u2022\u25e6\u25a0]/g;
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util_test.js index 26907466..c976830b 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util_test.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/editing_util_test.js
@@ -241,3 +241,71 @@ assertEquals(5, selection.start); assertEquals(9, selection.end); }); + +SYNC_TEST_F('DictationEditingUtilTest', 'NavNextSent', function() { + let value; + let caretIndex; + const f = () => EditingUtil.navNextSent(value, caretIndex); + + // Simple. + value = 'Hello world. Goodnight world.'; + caretIndex = 0; + assertEquals(12, f()); + + // If the end of the sentence can't be found, then moving to the next sentence + // should take us to the end of the value. + value = 'Hello world goodnight world'; + caretIndex = 0; + assertEquals(value.length, f()); + + // Various punctuation. + value = 'This?\nIs! A. Test;'; + caretIndex = 0; + assertEquals(5, f()); + caretIndex = 5; + assertEquals(9, f()); + caretIndex = 9; + assertEquals(12, f()); + caretIndex = 12; + assertEquals(value.length, f()); + + + // Edge case: empty value. + value = ''; + caretIndex = 0; + assertEquals(0, f()); +}); + +SYNC_TEST_F('DictationEditingUtilTest', 'NavPrevSent', function() { + let value; + let caretIndex; + const f = () => EditingUtil.navPrevSent(value, caretIndex); + + // Simple. + value = 'Hello world. Goodnight world.'; + caretIndex = value.length; + assertEquals(12, f()); + + // If the end of the sentence can't be found, then moving to the previous + // sentence should take us to the beginning of the value. + value = 'Hello world goodnight world'; + caretIndex = value.length; + assertEquals(0, f()); + + // Various punctuation and whitespace. + value = 'This?\nIs! A. Test;'; + caretIndex = value.length; + assertEquals(12, f()); + caretIndex = 12; + assertEquals(9, f()); + + caretIndex = 9; + assertEquals(5, f()); + caretIndex = 5; + assertEquals(0, f()); + + // Edge case: empty value. + value = ''; + caretIndex = 0; + assertEquals(0, f()); +});
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js index 76dbf39..6c130e29 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js
@@ -178,44 +178,12 @@ const value = editableNode.value; const caretIndex = editableNode.textSelStart; - const prevSentenceStart = - this.findPrevSentenceStartIndex_(value, caretIndex); + const prevSentenceStart = EditingUtil.navPrevSent(value, caretIndex); const length = caretIndex - prevSentenceStart; this.deleteSurroundingText_(length, -length); } /** - * Returns the start index of the sentence to the left of the caret. Indices - * are relative to `text`. Assumes that sentences are separated by punctuation - * specified in `InputController.END_OF_SENTENCE_REGEX_`. - * @param {string} text - * @param {number} caretIndex The index of the text caret. - */ - findPrevSentenceStartIndex_(text, caretIndex) { - let encounteredText = false; - if (caretIndex === text.length) { - --caretIndex; - } - - while (caretIndex >= 0) { - const valueAtCaret = text[caretIndex]; - if (encounteredText && - InputController.END_OF_SENTENCE_REGEX_.test(valueAtCaret)) { - // Adjust if there is another sentence after this one. - return text[caretIndex + 1] === ' ' ? caretIndex + 2 : caretIndex; - } - - if (!InputController.BEGINS_WITH_WHITESPACE_REGEX_.test(valueAtCaret) && - !InputController.PUNCTUATION_REGEX_.test(valueAtCaret)) { - encounteredText = true; - } - --caretIndex; - } - - return 0; - } - - /** * @param {number} length The number of characters to be deleted. * @param {number} offset The offset from the caret position where deletion * will start. This value can be negative. @@ -307,6 +275,34 @@ editableNode.setSelection(selection.start, selection.end); } + + /** Moves the text caret to the next sentence. */ + navNextSent() { + const editableNode = this.focusHandler_.getEditableNode(); + if (!editableNode || !editableNode.value || + editableNode.textSelStart !== editableNode.textSelEnd) { + return; + } + + const value = editableNode.value; + const caretIndex = editableNode.textSelStart; + const newCaretIndex = EditingUtil.navNextSent(value, caretIndex); + editableNode.setSelection(newCaretIndex, newCaretIndex); + } + + /** Moves the text caret to the previous sentence. */ + navPrevSent() { + const editableNode = this.focusHandler_.getEditableNode(); + if (!editableNode || !editableNode.value || + editableNode.textSelStart !== editableNode.textSelEnd) { + return; + } + + const value = editableNode.value; + const caretIndex = editableNode.textSelStart; + const newCaretIndex = EditingUtil.navPrevSent(value, caretIndex); + editableNode.setSelection(newCaretIndex, newCaretIndex); + } } /** @@ -327,16 +323,3 @@ * @const */ InputController.BEGINS_WITH_WHITESPACE_REGEX_ = /^\s/; - -/** - * @private {!RegExp} - * @const - */ -InputController.PUNCTUATION_REGEX_ = - /[-$#"()*;:<>\n\\\/\{\}\[\]+='~`!@_.,?%\u2022\u25e6\u25a0]/g; - -/** - * @private {!RegExp} - * @const - */ -InputController.END_OF_SENTENCE_REGEX_ = /[;!.?]/g;
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js index 29c7a64..c3229b5 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js
@@ -4,6 +4,7 @@ import {DeletePrevSentMacro} from '/accessibility_common/dictation/macros/delete_prev_sent_macro.js'; import {MacroName} from '/accessibility_common/dictation/macros/macro_names.js'; +import {NavNextSentMacro, NavPrevSentMacro} from '/accessibility_common/dictation/macros/nav_sent_macro.js'; import {DeletePrevWordMacro, NavNextWordMacro, NavPrevWordMacro} from '/accessibility_common/dictation/macros/repeatable_key_press_macro.js'; import {SmartDeletePhraseMacro} from '/accessibility_common/dictation/macros/smart_delete_phrase_macro.js'; import {SmartInsertBeforeMacro} from '/accessibility_common/dictation/macros/smart_insert_before_macro.js'; @@ -38,10 +39,18 @@ new DeletePrevSentMacro(this.inputController_).runMacro(); break; case MacroName.NAV_NEXT_WORD: - new NavNextWordMacro(/*isRtlLocale=*/ false).runMacro(); + new NavNextWordMacro(/*isRTLLocale=*/ false).runMacro(); break; case MacroName.NAV_PREV_WORD: - new NavPrevWordMacro(/*isRtlLocale=*/ false).runMacro(); + new NavPrevWordMacro(/*isRTLLocale=*/ false).runMacro(); + break; + case MacroName.NAV_NEXT_SENT: + new NavNextSentMacro(this.inputController_, /*isRTLLocale=*/ false) + .runMacro(); + break; + case MacroName.NAV_PREV_SENT: + new NavPrevSentMacro(this.inputController_, /*isRTLLocale=*/ false) + .runMacro(); break; default: throw new Error(`Cannot run macro: ${name} for testing`); @@ -120,4 +129,6 @@ MacroName.SMART_REPLACE_PHRASE, MacroName.SMART_INSERT_BEFORE, MacroName.SMART_SELECT_BTWN_INCL, + MacroName.NAV_NEXT_SENT, + MacroName.NAV_PREV_SENT, ];
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js index 64de379..328477c0 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js
@@ -94,5 +94,11 @@ // Sets selection between two provided words or phrases. SMART_SELECT_BTWN_INCL: 24, + // Move the cursor to the next sentence. + NAV_NEXT_SENT: 25, + + // Move the cursor to the previous sentence. + NAV_PREV_SENT: 26, + // Any new actions should match with Voice Access's semantic tags. };
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/nav_sent_macro.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/nav_sent_macro.js new file mode 100644 index 0000000..197bb2fd --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/nav_sent_macro.js
@@ -0,0 +1,68 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {Macro} from '/accessibility_common/dictation/macros/macro.js'; +import {MacroName} from '/accessibility_common/dictation/macros/macro_names.js'; + +/** Implements a macro that moves the text caret to the next sentence. */ +export class NavNextSentMacro extends Macro { + /** + * @param {!InputController} inputController + * @param {boolean} isRTLLocale + */ + constructor(inputController, isRTLLocale) { + super(MacroName.NAV_NEXT_SENT); + /** @private {!InputController} */ + this.inputController_ = inputController; + /** @private {boolean} */ + this.isRTLLocale_ = isRTLLocale; + } + + /** @override */ + checkContext() { + return this.createSuccessCheckContextResult_( + /*willImmediatelyDisambiguate=*/ false); + } + + /** @override */ + runMacro() { + if (!this.inputController_.isActive()) { + return this.createRunMacroResult_( + /*isSuccess=*/ false, MacroError.FAILED_ACTUATION); + } + this.inputController_.navNextSent(); + return this.createRunMacroResult_(/*isSuccess=*/ true); + } +} + +/** Implements a macro that moves the text caret to the previous sentence. */ +export class NavPrevSentMacro extends Macro { + /** + * @param {!InputController} inputController + * @param {boolean} isRTLLocale + */ + constructor(inputController, isRTLLocale) { + super(MacroName.NAV_PREV_SENT); + /** @private {!InputController} */ + this.inputController_ = inputController; + /** @private {boolean} */ + this.isRTLLocale_ = isRTLLocale; + } + + /** @override */ + checkContext() { + return this.createSuccessCheckContextResult_( + /*willImmediatelyDisambiguate=*/ false); + } + + /** @override */ + runMacro() { + if (!this.inputController_.isActive()) { + return this.createRunMacroResult_( + /*isSuccess=*/ false, MacroError.FAILED_ACTUATION); + } + this.inputController_.navPrevSent(); + return this.createRunMacroResult_(/*isSuccess=*/ true); + } +}
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js index d1eaac66..c31eed2 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier.js
@@ -137,7 +137,7 @@ }, Magnifier.IGNORE_FOCUS_UPDATES_INITIALIZATION_MS); chrome.commandLinePrivate.hasSwitch( - 'enable-magnifier-debug-draw-rect', (enabled) => { + 'enable-magnifier-debug-draw-rect', enabled => { if (enabled) { this.magnifierDebugDrawRect_ = true; } @@ -170,7 +170,7 @@ * @private */ updateFromPrefs_(prefs) { - prefs.forEach((pref) => { + prefs.forEach(pref => { switch (pref.key) { case Magnifier.Prefs.SCREEN_MAGNIFIER_FOCUS_FOLLOWING: this.screenMagnifierFocusFollowing_ = Boolean(pref.value);
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier_test.js index 159f2cfc..2100c32 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier_test.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/magnifier/magnifier_test.js
@@ -16,7 +16,7 @@ async getNextMagnifierBounds() { return new Promise(resolve => { - const listener = (magnifierBounds) => { + const listener = magnifierBounds => { chrome.accessibilityPrivate.onMagnifierBoundsChanged.removeListener( listener); resolve(magnifierBounds); @@ -28,7 +28,7 @@ async getPref(name) { return new Promise(resolve => { - chrome.settingsPrivate.getPref(name, (ret) => { + chrome.settingsPrivate.getPref(name, ret => { resolve(ret); }); }); @@ -183,7 +183,7 @@ const magnifier = accessibilityCommon.getMagnifierForTest(); magnifier.setIsInitializingForTest(false); - const moveMenuSelectionAssertBounds = async (targetBounds) => { + const moveMenuSelectionAssertBounds = async targetBounds => { // Send arrow up key. chrome.accessibilityPrivate.sendSyntheticKeyEvent({ type:
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background_test.js index 47e1cc3..6c7b291 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel/panel_node_menu_background_test.js
@@ -14,7 +14,7 @@ // Fake PanelBridge. const PanelBridge = { - addMenuItem: (item, id) => PanelBridge.calls.append({item, id}), + addMenuItem: item => PanelBridge.calls.push(item), calls: [], }; @@ -33,18 +33,18 @@ assertMenuItemIndicatesNoNodesFound(item) { assertNotNullNorUndefined(item); assertEquals('None', item.title); - assertEquals(-1, item.callbackId); + assertEquals(-1, item.callbackNodeIndex); assertFalse(item.isActive); } assertItemMatches(expectedName, item, opt_isActive) { assertEquals(expectedName, item.title); assertTrue( - item.callbackId >= 0 && - item.callbackId < PanelNodeMenuBackground.callbackNodes_.length); + item.callbackNodeIndex >= 0 && + item.callbackNodeIndex < PanelNodeMenuBackground.callbackNodes_.length); assertEquals( expectedName, - PanelNodeMenuBackground.callbackNodes_[item.callbackId].name); + PanelNodeMenuBackground.callbackNodes_[item.callbackNodeIndex].name); if (opt_isActive) { assertTrue(item.isActive); } else { @@ -53,13 +53,13 @@ } assertMenusHaveNoNodesFoundExcept(id) { - for (const menu of PanelNodeMenuData.ALL_NODE_MENUS) { + for (const menu of ALL_NODE_MENU_DATA) { if (menu.menuId === id) { continue; } - const call = PanelBridge.calls.find(args => args.id === menu.menuId); + const call = PanelBridge.calls.find(item => item.menuId === menu.menuId); assertNotNullNorUndefined(call); - this.assertMenuItemIndicatesNoNodesFound(call.item); + this.assertMenuItemIndicatesNoNodesFound(call); } } @@ -68,24 +68,24 @@ PanelBackground.instance.createAllNodeMenuBackgrounds_(); } - isFormControl(args) { - return args.id === PanelNodeMenuId.FORM_CONTROL; + isFormControl(item) { + return item.menuId === PanelNodeMenuId.FORM_CONTROL; } - isHeading(args) { - return args.id === PanelNodeMenuId.HEADING; + isHeading(item) { + return item.menuId === PanelNodeMenuId.HEADING; } - isLandmark(args) { - return args.id === PanelNodeMenuId.LANDMARK; + isLandmark(item) { + return item.menuId === PanelNodeMenuId.LANDMARK; } - isLink(args) { - return args.id === PanelNodeMenuId.LINK; + isLink(item) { + return item.menuId === PanelNodeMenuId.LINK; } - isTable(args) { - return args.id === PanelNodeMenuId.TABLE; + isTable(item) { + return item.menuId === PanelNodeMenuId.TABLE; } get formControlsDoc() { @@ -158,8 +158,7 @@ // Expect that one element is added per menu, specifying that no nodes // of that type are found. - assertEquals( - PanelNodeMenuData.ALL_NODE_MENUS.length, PanelBridge.calls.length); + assertEquals(ALL_NODE_MENU_DATA.length, PanelBridge.calls.length); // Assert all menus have a no nodes found element. this.assertMenusHaveNoNodesFoundExcept(null); }); @@ -168,14 +167,12 @@ await this.runWithLoadedTree(this.headingsDoc); this.createAllNodeMenuBackgrounds(); - // Check that there are the correct number of calls (one for each menu, plus - // two extra for the additional headings found). - assertEquals( - PanelNodeMenuData.ALL_NODE_MENUS_.length + 2, PanelBridge.calls.length); + // Check that there are the correct number of calls (one for each menu, + // plus two extra for the additional headings found). + assertEquals(ALL_NODE_MENU_DATA.length + 2, PanelBridge.calls.length); // Expect that the three items are added to the headings menu - const headingItems = - PanelBridge.calls.findAll(this.isHeading).map(args => args.item); + const headingItems = PanelBridge.calls.findAll(this.isHeading); assertEquals(3, headingItems.length); this.assertItemMatches('Heading 1', headingItems.unshift()); @@ -189,14 +186,12 @@ await this.runWithLoadedTree(this.landmarksDoc); this.createAllNodeMenuBackgrounds(); - // Check that there are the correct number of calls (one for each menu, plus - // seven extra for the additional landmarks found). - assertEquals( - PanelNodeMenuData.ALL_NODE_MENUS_.length + 7, PanelBridge.calls.length); + // Check that there are the correct number of calls (one for each menu, + // plus seven extra for the additional landmarks found). + assertEquals(ALL_NODE_MENU_DATA.length + 7, PanelBridge.calls.length); // Verify that eight items were added to the landmarks menu. - const landmarkItems = - PanelBridge.calls.findAll(this.isLandmark).map(args => args.item); + const landmarkItems = PanelBridge.calls.findAll(this.isLandmark); assertEquals(8, landmarkItems.length); this.assertItemMatches('application', landmarkItems.unshift()); @@ -217,12 +212,10 @@ // Check that there are the correct number of calls (one for each menu, plus // three extra for the additional links found). - assertEquals( - PanelNodeMenuData.ALL_NODE_MENUS_.length + 3, PanelBridge.calls.length); + assertEquals(ALL_NODE_MENU_DATA.length + 3, PanelBridge.calls.length); // Verify that four items were added to the links menu. - const linkItems = - PanelBridge.calls.findAll(this.isLink).map(args => args.item); + const linkItems = PanelBridge.calls.findAll(this.isLink); assertEquals(4, linkItems.length); this.assertItemMatches('Link 1', linkItems.unshift()); @@ -240,13 +233,10 @@ // Check that there are the correct number of calls (one for each menu, // plus eight extra for the additional form controls found). - assertEquals( - PanelNodeMenuData.ALL_NODE_MENUS_.length + 8, - PanelBridge.calls.length); + assertEquals(ALL_NODE_MENU_DATA.length + 8, PanelBridge.calls.length); // Verify that nine items were added to the form controls menu. - const formItems = - PanelBridge.calls.findAll(this.isFormControl).map(args => args.item); + const formItems = PanelBridge.calls.findAll(this.isFormControl); assertEquals(9, formItems.length); this.assertItemMatches('button', formItems.unshift()); @@ -266,14 +256,12 @@ await this.runWithLoadedTree(this.tablesDoc); this.createAllNodeMenuBackgrounds(); - // Check that there are the correct number of calls (one for each menu, plus - // one extra for the additional links found). - assertEquals( - PanelNodeMenuData.ALL_NODE_MENUS_.length + 1, PanelBridge.calls.length); + // Check that there are the correct number of calls (one for each menu, + // plus one extra for the additional links found). + assertEquals(ALL_NODE_MENU_DATA.length + 1, PanelBridge.calls.length); // Verify that two items were added to the tables menu. - const tableItems = - PanelBridge.calls.findAll(this.isTable).map(args => args.item); + const tableItems = PanelBridge.calls.findAll(this.isTable); assertEquals(2, tableItems.length); this.assertItemMatches('grid', tableItems.unshift()); @@ -287,22 +275,21 @@ this.createAllNodeMenuBackgrounds(); // Check that there are the correct number of calls (one for each menu). - assertEquals( - PanelNodeMenuData.ALL_NODE_MENUS_.length, PanelBridge.calls.length); + assertEquals(ALL_NODE_MENU_DATA.length, PanelBridge.calls.length); // Check that each item was added to the correct menu. - const formItem = PanelBridge.calls.find(this.isFormControl).item; + const formItem = PanelBridge.calls.find(this.isFormControl); this.assertItemMatches('button', formItem); - const headingItem = PanelBridge.calls.find(this.isHeading).item; + const headingItem = PanelBridge.calls.find(this.isHeading); this.assertItemMatches('header', headingItem); - const landmarkItem = PanelBridge.calls.find(this.isLandmark).item; + const landmarkItem = PanelBridge.calls.find(this.isLandmark); this.assertItemMatches('region', landmarkItem); - const linkItem = PanelBridge.calls.find(this.isLink).item; + const linkItem = PanelBridge.calls.find(this.isLink); this.assertItemMatches('link', linkItem); - const tableItem = PanelBridge.calls.find(this.isTable).item; + const tableItem = PanelBridge.calls.find(this.isTable); this.assertItemMatches('table', tableItem); });
diff --git a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js index 3d5a7893..b6a10a68 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js +++ b/chrome/browser/resources/chromeos/accessibility/common/automation_predicate.js
@@ -815,7 +815,7 @@ /** @type {AutomationPredicate.Unary} */ AutomationPredicate.simpleListItem = AutomationPredicate.match({ anyPredicate: - [(node) => node.role === Role.LIST_ITEM && node.children.length === 2 && + [node => node.role === Role.LIST_ITEM && node.children.length === 2 && node.firstChild.role === Role.LIST_MARKER && node.lastChild.role === Role.STATIC_TEXT] }); @@ -876,7 +876,7 @@ AutomationPredicate.clickable = AutomationPredicate.match({ anyPredicate: [ AutomationPredicate.button, AutomationPredicate.link, - (node) => { + node => { return node.defaultActionVerb === chrome.automation.DefaultActionVerb.CLICK; }
diff --git a/chrome/browser/resources/chromeos/accessibility/common/automation_util_test.js b/chrome/browser/resources/chromeos/accessibility/common/automation_util_test.js index f5db965..a693382 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/automation_util_test.js +++ b/chrome/browser/resources/chromeos/accessibility/common/automation_util_test.js
@@ -208,7 +208,7 @@ assertEquals( 'x', AutomationUtil - .findLastNode(r, (n) => n.role === RoleType.GENERIC_CONTAINER) + .findLastNode(r, n => n.role === RoleType.GENERIC_CONTAINER) .name); }); @@ -223,8 +223,7 @@ `); assertEquals( 'outer', - AutomationUtil.findLastNode(r, (n) => n.role === RoleType.BUTTON) - .name); + AutomationUtil.findLastNode(r, n => n.role === RoleType.BUTTON).name); }); TEST_F( @@ -238,6 +237,6 @@ assertEquals( 'inner', AutomationUtil - .findLastNode(r, (n) => n.role === RoleType.GENERIC_CONTAINER) + .findLastNode(r, n => n.role === RoleType.GENERIC_CONTAINER) .name); });
diff --git a/chrome/browser/resources/chromeos/accessibility/common/event_generator_test.js b/chrome/browser/resources/chromeos/accessibility/common/event_generator_test.js index 23265ba..d67c801 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/event_generator_test.js +++ b/chrome/browser/resources/chromeos/accessibility/common/event_generator_test.js
@@ -21,7 +21,7 @@ 'EventGeneratorTest', 'DISABLED_MouseEventsProcessedSequentially', function() { const mouseEventLog = []; - chrome.accessibilityPrivate.sendSyntheticMouseEvent = (event) => + chrome.accessibilityPrivate.sendSyntheticMouseEvent = event => mouseEventLog.push(event); // Set a 1ms delay so that a timeout is set between the press and release.
diff --git a/chrome/browser/resources/chromeos/accessibility/common/event_handler.js b/chrome/browser/resources/chromeos/accessibility/common/event_handler.js index f3d78ee..68bf83c 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/event_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/common/event_handler.js
@@ -48,7 +48,7 @@ * Default is a function that always returns true. * @private {!function(chrome.automation.AutomationEvent): boolean} */ - this.predicate_ = options.predicate || ((e) => true); + this.predicate_ = options.predicate || (e => true); /** @private {boolean} */ this.listening_ = false; @@ -120,7 +120,7 @@ * @param {!chrome.automation.AutomationNode} node */ removeNode(node) { - this.nodes_ = this.nodes_.filter((n) => n !== node); + this.nodes_ = this.nodes_.filter(n => n !== node); if (this.listening_) { for (const type of this.types_) {
diff --git a/chrome/browser/resources/chromeos/accessibility/common/rect_util.js b/chrome/browser/resources/chromeos/accessibility/common/rect_util.js index 8d335761..099c682 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/rect_util.js +++ b/chrome/browser/resources/chromeos/accessibility/common/rect_util.js
@@ -57,14 +57,14 @@ * @param {ScreenRect|undefined} rect * @return {number} */ - area: (rect) => (rect ? rect.width * rect.height : 0), + area: rect => (rect ? rect.width * rect.height : 0), /** * Finds the bottom of a rect. * @param {!ScreenRect} rect * @return {number} */ - bottom: (rect) => rect.top + rect.height, + bottom: rect => rect.top + rect.height, /** * Returns the point at the center of the rectangle. @@ -72,7 +72,7 @@ * @return {!{x: number, y: number}} an object containing the x and y * coordinates of the center. */ - center: (rect) => { + center: rect => { const x = rect.left + Math.round(rect.width / 2); const y = rect.top + Math.round(rect.height / 2); return {x, y}; @@ -118,7 +118,7 @@ * @param {!ScreenRect} rect * @return {!ScreenRect} */ - deepCopy: (rect) => /** @type {!ScreenRect} */ (Object.assign({}, rect)), + deepCopy: rect => /** @type {!ScreenRect} */ (Object.assign({}, rect)), /** * Returns the largest rectangle contained within the outer rect that does not @@ -295,7 +295,7 @@ * @param {!ScreenRect} rect * @return {number} */ - right: (rect) => rect.left + rect.width, + right: rect => rect.left + rect.width, /* * @param {ScreenRect=} rect1 @@ -317,7 +317,7 @@ * @param {ScreenRect|undefined} rect * @return {string} */ - toString: (rect) => { + toString: rect => { let str = ''; if (rect) { str = rect.left + ',' + rect.top + ' '; @@ -355,7 +355,7 @@ * @param {!Array<!ScreenRect>} rects * @return {!ScreenRect} */ - unionAll: (rects) => { + unionAll: rects => { if (rects.length < 1) { return RectUtil.ZERO_RECT; }
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js index 865ffc5..f9ca297 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler.js
@@ -26,7 +26,7 @@ * default to always return true. * @private {!function(!chrome.automation.TreeChange)} */ - this.predicate_ = options.predicate || ((c) => true); + this.predicate_ = options.predicate || (c => true); /** @private {!function(!chrome.automation.TreeChange)} */ this.handler_ = change => this.onChange_(change);
diff --git a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js index 09401c7..1b44148 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js +++ b/chrome/browser/resources/chromeos/accessibility/common/repeated_tree_change_handler_test.js
@@ -39,8 +39,7 @@ const handler = () => this.handlerCallCount++; const repeatedHandler = new RepeatedTreeChangeHandler( - 'allTreeChanges', handler, - {predicate: (c) => c.type === 'nodeRemoved'}); + 'allTreeChanges', handler, {predicate: c => c.type === 'nodeRemoved'}); // Simulate events being fired. repeatedHandler.onChange_({type: 'nodeAdded'});
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js index 6bf9b05..590d6dd 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/common/testing/e2e_test_base.js
@@ -240,7 +240,7 @@ // Listener for both load complete and focus events that eventually // triggers the test. - const listener = async (event) => { + const listener = async event => { if (hasLacrosChromePath && !didNavigateForLacros) { // We have yet to request navigation in the Lacros tab. Do so now by // getting the default focus (the address bar), setting the value to @@ -302,8 +302,8 @@ */ runWithLoadedOptionsPage(callback, matchUrlRegExp = /options.html/) { callback = this.newCallback(callback); - chrome.automation.getDesktop((desktop) => { - const listener = (event) => { + chrome.automation.getDesktop(desktop => { + const listener = event => { if (!matchUrlRegExp.test(event.target.docUrl) || !event.target.docLoaded) { return;
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_input_ime.js b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_input_ime.js index d8a6f81..4d65b617 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_input_ime.js +++ b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_input_ime.js
@@ -52,7 +52,7 @@ * Adds a listener to onFocus. * @param {function<InputContext>} listener */ - addListener: (listener) => { + addListener: listener => { MockInputIme.onFocusListener_ = listener; }, @@ -60,7 +60,7 @@ * Removes the listener. * @param {function<InputContext>} listener */ - removeListener: (listener) => { + removeListener: listener => { if (MockInputIme.onFocusListener_ === listener) { MockInputIme.onFocusListener_ = null; } @@ -72,7 +72,7 @@ * Adds a listener to onBlur. * @param {function<number>} listener */ - addListener: (listener) => { + addListener: listener => { MockInputIme.onBlurListener_ = listener; }, @@ -80,7 +80,7 @@ * Removes the listener. * @param {function<number>} listener */ - removeListener: (listener) => { + removeListener: listener => { if (MockInputIme.onBlurListener_ === listener) { MockInputIme.onBlurListener_ = null; }
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js index 89ee2ca..b450508 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js +++ b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_speech_recognition_private.js
@@ -53,10 +53,10 @@ * removeListener: function(Function):void}} */ this.onStop = { - addListener: (listener) => { + addListener: listener => { this.onStopListener_ = listener; }, - removeListener: (listener) => { + removeListener: listener => { if (this.onStopListener_ === listener) { this.onStopListener_ = null; } @@ -69,10 +69,10 @@ * removeListener: function(Function):void}} */ this.onResult = { - addListener: (listener) => { + addListener: listener => { this.onResultListener_ = listener; }, - removeListener: (listener) => { + removeListener: listener => { if (this.onResultListener_ === listener) { this.onResultListener_ = null; } @@ -85,10 +85,10 @@ * removeListener: function(Function):void}} */ this.onError = { - addListener: (listener) => { + addListener: listener => { this.onErrorListener_ = listener; }, - removeListener: (listener) => { + removeListener: listener => { if (this.onErrorListener_ === listener) { this.onErrorListener_ = null; }
diff --git a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_storage.js b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_storage.js index cc25519..b8d9b0ae 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/testing/mock_storage.js +++ b/chrome/browser/resources/chromeos/accessibility/common/testing/mock_storage.js
@@ -19,8 +19,8 @@ /** * @param {Object<string, string>} updates Map from keys to values to store. */ - set: (updates) => { - Object.keys(updates).forEach((key) => { + set: updates => { + Object.keys(updates).forEach(key => { MockStorage.local_[key] = updates[key]; }); MockStorage.callOnChangedListeners(this.local_); @@ -40,7 +40,7 @@ * Removes the value with the given key. * @param {string} key The key to remove. */ - remove: (key) => { + remove: key => { delete MockStorage.local_[key]; MockStorage.callOnChangedListeners(this.local_); } @@ -50,8 +50,8 @@ /** * @param {Object<string, *>} updates Map from keys to values to store. */ - set: (updates) => { - Object.keys(updates).forEach((key) => { + set: updates => { + Object.keys(updates).forEach(key => { MockStorage.sync_[key] = updates[key]; }); MockStorage.callOnChangedListeners(this.sync_); @@ -71,7 +71,7 @@ * Removes the value with the given key. * @param {string} key The key to remove. */ - remove: (key) => { + remove: key => { delete MockStorage.sync_[key]; MockStorage.callOnChangedListeners(this.sync_); } @@ -82,7 +82,7 @@ * Set the onChanged callback. * @param {function(Object<string, *>)} */ - addListener: (callback) => { + addListener: callback => { MockStorage.callbacks_.push(callback); }, }, @@ -92,8 +92,8 @@ * This is functionality for testing and not part of the API. * @param {!Object<string, *>} opt_values */ - callOnChangedListeners: (opt_values) => { - MockStorage.callbacks_.forEach((callback) => { + callOnChangedListeners: opt_values => { + MockStorage.callbacks_.forEach(callback => { const baseObject = opt_values || MockStorage.sync_; const result = {}; for (const key in baseObject) {
diff --git a/chrome/browser/resources/chromeos/accessibility/common/tutorial/chromevox_tutorial.js b/chrome/browser/resources/chromeos/accessibility/common/tutorial/chromevox_tutorial.js index 8e8ca913..f8395d3c 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/tutorial/chromevox_tutorial.js +++ b/chrome/browser/resources/chromeos/accessibility/common/tutorial/chromevox_tutorial.js
@@ -407,11 +407,11 @@ // finished loading. this.hideAllScreens(); document.addEventListener('keydown', this.onKeyDown.bind(this)); - this.addEventListener('startpractice', (evt) => { + this.addEventListener('startpractice', evt => { this.isPracticeAreaActive = true; this.startNudges(NudgeType.PRACTICE_AREA); }); - this.addEventListener('endpractice', (evt) => { + this.addEventListener('endpractice', evt => { this.isPracticeAreaActive = false; this.startNudges(NudgeType.GENERAL); }); @@ -536,7 +536,7 @@ * which is defined on the Panel window. */ initializeNudges(type) { - const maybeGiveNudge = (msg) => { + const maybeGiveNudge = msg => { if (this.interactiveMode_) { // Do not announce message since ChromeVox blocks actions in interactive // mode. @@ -720,7 +720,7 @@ const link = document.createElement('a'); link.innerText = this.getMsg(resource.msgId); link.href = resource.link; - link.addEventListener('click', (evt) => { + link.addEventListener('click', evt => { this.stopNudges(); this.dispatchEvent(new CustomEvent( 'openUrl', {composed: true, detail: {url: link.href}}));
diff --git a/chrome/browser/resources/chromeos/accessibility/common/tutorial/lesson_container.js b/chrome/browser/resources/chromeos/accessibility/common/tutorial/lesson_container.js index efc2797..1a8ea3d 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/tutorial/lesson_container.js +++ b/chrome/browser/resources/chromeos/accessibility/common/tutorial/lesson_container.js
@@ -30,7 +30,7 @@ /** @override */ ready() { - this.$.lessonTemplate.addEventListener('dom-change', (evt) => { + this.$.lessonTemplate.addEventListener('dom-change', evt => { // Executes once all lessons have been added to the dom. this.onLessonsLoaded_(); });
diff --git a/chrome/browser/resources/chromeos/accessibility/common/tutorial/tutorial_lesson.js b/chrome/browser/resources/chromeos/accessibility/common/tutorial/tutorial_lesson.js index ded9699..31b09a9 100644 --- a/chrome/browser/resources/chromeos/accessibility/common/tutorial/tutorial_lesson.js +++ b/chrome/browser/resources/chromeos/accessibility/common/tutorial/tutorial_lesson.js
@@ -59,7 +59,7 @@ /** @override */ ready() { - this.$.contentTemplate.addEventListener('dom-change', (evt) => { + this.$.contentTemplate.addEventListener('dom-change', evt => { this.dispatchEvent(new CustomEvent('lessonready', {composed: true})); }); @@ -70,12 +70,12 @@ this.$.practiceContent.addEventListener( evt, event => this.onPracticeEvent(event), true); } - this.$.practiceContent.addEventListener('focus', (evt) => { + this.$.practiceContent.addEventListener('focus', evt => { // The practice area has the potential to overflow, so ensure elements // are scrolled into view when focused. evt.target.scrollIntoView(); }, true); - this.$.practiceContent.addEventListener('click', (evt) => { + this.$.practiceContent.addEventListener('click', evt => { // Intercept click events. For example, clicking a link will exit the // tutorial without this listener. evt.preventDefault(); @@ -139,7 +139,7 @@ const path = '../tutorial/practice_areas/' + this.practiceFile + '.html'; const xhr = new XMLHttpRequest(); xhr.open('GET', path, true); - xhr.onload = (evt) => { + xhr.onload = evt => { if (xhr.readyState === 4 && xhr.status === 200) { this.$.practiceContent.innerHTML = xhr.responseText; this.localizePracticeAreaContent();
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts.js b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts.js index 6e5a644..780f6a0 100644 --- a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts.js +++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts.js
@@ -80,7 +80,7 @@ const request = EnhancedNetworkTts.generateRequest(utterance, options); await (this.api_.getAudioDataWithCallback( request, - (response) => this.queueResponse_( + response => this.queueResponse_( response, audioStreamOptions, sendTtsAudio, sendError))); }
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_e2e_test_base.js index 5822346..37fb27e 100644 --- a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_e2e_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_e2e_test_base.js
@@ -18,12 +18,12 @@ this.onStopListeners = []; chrome.ttsEngine = { onSpeakWithAudioStream: { - addListener: (callback) => { + addListener: callback => { this.onSpeakWithAudioStreamListeners.push(callback); }, }, onStop: { - addListener: (callback) => { + addListener: callback => { this.onStopListeners.push(callback); }, }
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_unittest.js b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_unittest.js index ac2c3f8..1b663bb 100644 --- a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/enhanced_network_tts_unittest.js
@@ -242,7 +242,7 @@ expectedBuffers.map(buffer => Object.assign({}, buffer)); expectedBuffersWithoutLastBuffer[5].isLastBuffer = false; - let mockSendTtsAudio = (receivedBuffer) => { + let mockSendTtsAudio = receivedBuffer => { const expectedBuffer = expectedBuffers.shift(); assertEqualsJSON(expectedBuffer, receivedBuffer); }; @@ -250,7 +250,7 @@ decodedAudioData, sampleRate, bufferSize, timeInfo, mockSendTtsAudio, /* lastData= */ true); - mockSendTtsAudio = (receivedBuffer) => { + mockSendTtsAudio = receivedBuffer => { const expectedBuffer = expectedBuffersWithoutLastBuffer.shift(); assertEqualsJSON(expectedBuffer, receivedBuffer); };
diff --git a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/error_handling_unittest.js b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/error_handling_unittest.js index 7acbf8a..a1c15d6 100644 --- a/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/error_handling_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/enhanced_network_tts/error_handling_unittest.js
@@ -27,10 +27,10 @@ const utterance = 'test'; const options = {'voiceName': 'Enhanced TTS English (Australian Accent)'}; const audioStreamOptions = {'bufferSize': 10000, 'sampleRate': 22000}; - const sendTtsAudio = (receivedBuffer) => { + const sendTtsAudio = receivedBuffer => { throw new Error('Assertion failed: does not expect incoming buffer.'); }; - const sendError = (error) => { + const sendError = error => { assertEquals(error, 'Error: unable to get mojoPrivate bindings'); }; @@ -51,10 +51,10 @@ const utterance = 'test'; const options = {'voiceName': 'Enhanced TTS English (Australian Accent)'}; const audioStreamOptions = {'bufferSize': 10000, 'sampleRate': 22000}; - const sendTtsAudio = (receivedBuffer) => { + const sendTtsAudio = receivedBuffer => { throw new Error('Assertion failed: does not expect incoming buffer.'); }; - const sendError = (error) => { + const sendError = error => { assertEquals(error, 'Error: utterance too long'); };
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js index adf72dc..d0c0382 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/metrics_utils.js
@@ -15,7 +15,7 @@ static recordCancelIfSpeaking() { // TODO(b/1157214): Use select-to-speak's internal state instead of TTS // state. - chrome.tts.isSpeaking((speaking) => { + chrome.tts.isSpeaking(speaking => { if (speaking) { MetricsUtils.recordCancelEvent_(); }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils.js index e5a3c99..1d8efd7 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils.js
@@ -85,7 +85,7 @@ if (containingRoot.role === RoleType.ROOT_WEB_AREA) { const ancestors = AutomationUtil.getAncestors(containingRoot); const topRootWebArea = - ancestors.find((a) => a.role === RoleType.ROOT_WEB_AREA); + ancestors.find(a => a.role === RoleType.ROOT_WEB_AREA); if (topRootWebArea) { containingRoot = topRootWebArea; } @@ -96,7 +96,7 @@ } const nextNode = AutomationUtil.findNextNode( startNode, direction, NodeUtils.isValidLeafNode, { - root: (n) => containingRoot === n, + root: n => containingRoot === n, skipInitialSubtree: true, }); if (nextNode === null) { @@ -239,8 +239,7 @@ const nodes = AutomationUtil.findAllNodes( node, direction, /* pred= */ NodeUtils.isValidLeafNode, /* opt_restrictions= */ { - root: (node) => - node === blockParent, // Only traverse within the block + root: node => node === blockParent, // Only traverse within the block }); // Reverse the nodes if we were traversing backward, so the returned result
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils_unittest.js index 21743e06..03ff7db 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_navigation_utils_unittest.js
@@ -71,7 +71,7 @@ // paragraph 2. result = NodeNavigationUtils.getNodesForNextParagraph( nodeGroupForParagraph1, constants.Dir.FORWARD, - (nodes) => !(nodes.find( + nodes => !(nodes.find( n => n.parent === paragraph2) /* filter out nodes belong to paragraph 2 */)); assertEquals(result.length, 0); @@ -688,7 +688,7 @@ ({nodes, offset} = NodeNavigationUtils.getNodesForNextSentence( nodeGroupForParagraph1, 8 /* currentCharIndex */, constants.Dir.FORWARD, - (nodes) => !(nodes.find( + nodes => !(nodes.find( n => n.parent === paragraph2) /* filter out nodes belong to paragraph 2 */))); assertEquals(nodes.length, 0); @@ -737,7 +737,7 @@ ({nodes, offset} = NodeNavigationUtils.getNodesForNextSentence( nodeGroupForParagraph2, 0 /* currentCharIndex */, constants.Dir.BACKWARD, - (nodes) => !(nodes.find( + nodes => !(nodes.find( n => n.parent === paragraph1) /* filter out nodes belong to paragraph 1 */))); assertEquals(nodes.length, 0);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js index 8a86fc8..9cb07c43 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/node_utils.js
@@ -478,8 +478,7 @@ return AutomationUtil.findAllNodes( blockParent, constants.Dir.FORWARD, /* pred= */ NodeUtils.isValidLeafNode, /* opt_restrictions= */ { - root: (node) => - node === blockParent, // Only traverse within the block + root: node => node === blockParent, // Only traverse within the block }); }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js index eb251e2..cbb1a76 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/paragraph_utils.js
@@ -229,7 +229,7 @@ } node.unclippedBoundsForRange( - boundQueryStartIndex, boundQueryEndIndex, (b) => { + boundQueryStartIndex, boundQueryEndIndex, b => { // If the word is entirely out of the blockparent bounds, // replace the word with space characters. if (b.left + b.width <= leftBound || b.left >= rightBound ||
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js index 4f95d571..6529d3f 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/prefs_manager.js
@@ -78,14 +78,14 @@ var uiLocale = chrome.i18n.getMessage('@@ui_locale'); uiLocale = uiLocale.replace('_', '-').toLowerCase(); - chrome.tts.getVoices((voices) => { + chrome.tts.getVoices(voices => { this.validVoiceNames_ = new Set(); if (voices.length === 0) { return; } - voices.forEach((voice) => { + voices.forEach(voice => { if (!voice.eventTypes.includes(chrome.tts.EventType.START) || !voice.eventTypes.includes(chrome.tts.EventType.END) || !voice.eventTypes.includes(chrome.tts.EventType.WORD) || @@ -126,7 +126,7 @@ this.voiceNameFromLocale_ = firstVoiceName; } - chrome.storage.sync.get(['voice'], (prefs) => { + chrome.storage.sync.get(['voice'], prefs => { if (!prefs['voice']) { chrome.storage.sync.set({'voice': PrefsManager.SYSTEM_VOICE}); } @@ -162,7 +162,7 @@ // rate before doing migration logic. const getPrefsPromises = []; getPrefsPromises.push(new Promise((resolve, reject) => { - chrome.settingsPrivate.getPref('settings.tts.speech_rate', (pref) => { + chrome.settingsPrivate.getPref('settings.tts.speech_rate', pref => { if (pref === undefined) { reject(); } @@ -171,7 +171,7 @@ }); })); getPrefsPromises.push(new Promise((resolve, reject) => { - chrome.settingsPrivate.getPref('settings.tts.speech_pitch', (pref) => { + chrome.settingsPrivate.getPref('settings.tts.speech_pitch', pref => { if (pref === undefined) { reject(); } @@ -204,7 +204,7 @@ setPrefsPromises.push(new Promise((resolve, reject) => { chrome.settingsPrivate.setPref( 'settings.tts.speech_rate', stsRate, - '' /* unused, see crbug.com/866161 */, (success) => { + '' /* unused, see crbug.com/866161 */, success => { if (success) { resolve(); } else { @@ -215,7 +215,7 @@ setPrefsPromises.push(new Promise((resolve, reject) => { chrome.settingsPrivate.setPref( 'settings.tts.speech_pitch', stsPitch, - '' /* unused, see crbug.com/866161 */, (success) => { + '' /* unused, see crbug.com/866161 */, success => { if (success) { resolve(); } else { @@ -225,8 +225,7 @@ })); Promise.all(setPrefsPromises) .then( - () => this.onTtsSettingsMigrationSuccess_(), - (error) => { + () => this.onTtsSettingsMigrationSuccess_(), error => { console.log(error); this.migrationInProgress_ = false; }); @@ -236,7 +235,7 @@ this.onTtsSettingsMigrationSuccess_(); } }, - (error) => { + error => { console.log(error); this.migrationInProgress_ = false; }); @@ -261,7 +260,7 @@ initPreferences() { const updatePolicy = () => { chrome.settingsPrivate.getPref( - PrefsManager.ENHANCED_VOICES_POLICY_KEY, (pref) => { + PrefsManager.ENHANCED_VOICES_POLICY_KEY, pref => { if (pref === undefined) { return; } @@ -275,7 +274,7 @@ 'backgroundShading', 'navigationControls', 'enhancedNetworkVoices', 'enhancedVoicesDialogShown', 'enhancedVoiceName' ], - (prefs) => { + prefs => { if (prefs['voice']) { this.voiceNameFromPrefs_ = prefs['voice']; }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js index 46669486..974a402 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js
@@ -70,7 +70,7 @@ /** @private {number|undefined} */ this.intervalRef_; - chrome.automation.getDesktop((desktop) => { + chrome.automation.getDesktop(desktop => { this.desktop_ = desktop; // After the user selects a region of the screen, we do a hit test at @@ -179,7 +179,7 @@ // TODO(chrishall): do we want to (also?) expose this in preferences? chrome.commandLinePrivate.hasSwitch( - 'enable-experimental-accessibility-language-detection', (result) => { + 'enable-experimental-accessibility-language-detection', result => { this.enableLanguageDetectionIntegration_ = result; }); @@ -189,13 +189,13 @@ */ this.enhancedVoicesFlag_ = false; chrome.accessibilityPrivate.isFeatureEnabled( - AccessibilityFeature.ENHANCED_NETWORK_VOICES, (result) => { + AccessibilityFeature.ENHANCED_NETWORK_VOICES, result => { this.enhancedVoicesFlag_ = result; }); /** @private {number} Default speech rate set in system settings. */ this.systemSpeechRate_ = 1.0; - chrome.settingsPrivate.getPref(SPEECH_RATE_KEY, (pref) => { + chrome.settingsPrivate.getPref(SPEECH_RATE_KEY, pref => { if (!pref) { return; } @@ -263,7 +263,7 @@ var rect = this.inputHandler_.getMouseRect(); var nodes = []; - chrome.automation.getFocus((focusedNode) => { + chrome.automation.getFocus(focusedNode => { // In some cases, e.g. ARC++, the window received in the hit test request, // which is computed based on which window is the event handler for the // hit point, isn't the part of the tree that contains the actual @@ -453,7 +453,7 @@ if (!gsuiteAppRootNode) { return; } - chrome.tabs.query({active: true}, (tabs) => { + chrome.tabs.query({active: true}, tabs => { // Closure doesn't realize that we did a !gsuiteAppRootNode earlier // so we check again here. if (tabs.length === 0 || !gsuiteAppRootNode) { @@ -488,7 +488,7 @@ return; } this.scrollToSpokenNode_ = true; - const listener = (event) => { + const listener = event => { if (event.eventFrom !== 'action') { // User initiated event. Cancel all future scrolling to spoken nodes. // If the user wants a certain scroll position we will respect that. @@ -693,8 +693,8 @@ 'https://docs.sandbox.google.com/*' ] }, - (tabs) => { - tabs.forEach((tab) => { + tabs => { + tabs.forEach(tab => { chrome.tabs.executeScript(tab.id, {file: script}); }); }); @@ -850,7 +850,7 @@ * @private */ onPrefsChanged_(prefs) { - const ratePref = prefs.find((pref) => pref.key === SPEECH_RATE_KEY); + const ratePref = prefs.find(pref => pref.key === SPEECH_RATE_KEY); if (ratePref) { this.systemSpeechRate_ = ratePref.value; } @@ -870,7 +870,7 @@ } const {nodes, offset} = NodeNavigationUtils.getNodesForNextSentence( this.getCurrentNodeGroup_(), this.currentCharIndex_, direction, - (nodes) => this.skipPanel_(nodes)); + nodes => this.skipPanel_(nodes)); if (nodes.length === 0) { return; } @@ -893,7 +893,7 @@ const nodes = NodeNavigationUtils.getNodesForNextParagraph( this.getCurrentNodeGroup_(), direction, - (nodes) => this.skipPanel_(nodes)); + nodes => this.skipPanel_(nodes)); // Return early if the nodes are empty. if (nodes.length === 0) { return; @@ -914,7 +914,7 @@ */ skipPanel_(nodes) { return !AutomationUtil.getAncestors(nodes[0]).find( - (n) => UiManager.isPanel(n)); + n => UiManager.isPanel(n)); } /** @@ -933,7 +933,7 @@ // Without nodes to anchor on, navigate is not supported. this.supportsNavigationPanel_ = false; - options.onEvent = (event) => { + options.onEvent = event => { if (event.type === 'start') { this.onStateChanged_(SelectToSpeakState.SPEAKING); this.updateUi_(); @@ -1127,7 +1127,7 @@ const nodeGroupText = nodeGroup.text || ''; - options.onEvent = (event) => { + options.onEvent = event => { switch (event.type) { case chrome.tts.EventType.START: if (nodeGroup.nodes.length <= 0) { @@ -1443,10 +1443,10 @@ * @private */ isNodeInForeground_(node) { - return new Promise((resolve) => { + return new Promise(resolve => { this.desktop_.hitTestWithReply( - node.location.left, node.location.top, (nodeAtLocation) => { - chrome.automation.getFocus((focusedNode) => { + node.location.left, node.location.top, nodeAtLocation => { + chrome.automation.getFocus(focusedNode => { const window = NodeUtils.getNearestContainingWindow(nodeAtLocation); const currentWindow = NodeUtils.getNearestContainingWindow(node); @@ -1580,7 +1580,7 @@ const description = chrome.i18n.getMessage( 'select_to_speak_natural_voice_dialog_description'); chrome.accessibilityPrivate.showConfirmationDialog( - title, description, (confirm) => { + title, description, confirm => { this.prefsManager_.setEnhancedNetworkVoicesFromDialog(confirm); if (callback !== undefined) { callback(); @@ -1672,7 +1672,7 @@ // auto-dismissing behavior (see http://crbug.com/1157148), but also // navigation controls do not work well for control-rich interfaces that are // light on text (and therefore no sentence and paragraph structures). - return !nodes.some((n) => n.root && n.root.role === RoleType.DESKTOP); + return !nodes.some(n => n.root && n.root.role === RoleType.DESKTOP); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js index eeb5a9e..b7b4d6c47 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_mouse_selection_test.js
@@ -229,7 +229,7 @@ // stylus may act as a laser pointer unless it taps on the stylus options // button, which always opens on a tap regardless of the stylus behavior // selected. - this.runWithLoadedDesktop((desktop) => { + this.runWithLoadedDesktop(desktop => { this.tapTrayButton(desktop, () => { assertEquals(selectToSpeak.state_, SelectToSpeakState.SELECTING); const button = desktop.find({ @@ -240,8 +240,8 @@ // sure we actually don't start speech after the hittest and focus // callbacks are used to check which nodes should be spoken. desktop.addEventListener( - EventType.MOUSE_RELEASED, this.newCallback((evt) => { - chrome.automation.getFocus(this.newCallback((node) => { + EventType.MOUSE_RELEASED, this.newCallback(evt => { + chrome.automation.getFocus(this.newCallback(node => { assertEquals( selectToSpeak.state_, SelectToSpeakState.INACTIVE); assertFalse(this.mockTts.currentlySpeaking());
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js index d5053d31..d15e7c4 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js
@@ -63,7 +63,7 @@ waitForPanelFocus(root, callback) { callback = this.newCallback(callback); const focusCallback = () => { - chrome.automation.getFocus((node) => { + chrome.automation.getFocus(node => { if (!this.isNodeWithinPanel(node)) { return; } @@ -146,7 +146,7 @@ `; const root = await this.runWithLoadedTree(bodyHtml); this.mockTts.setOnSpeechCallbacks([ - this.newCallback((utterance) => { + this.newCallback(utterance => { // Speech for first click. assertTrue(this.mockTts.currentlySpeaking()); assertEquals(this.mockTts.pendingUtterances().length, 1); @@ -154,7 +154,7 @@ this.mockTts.pendingUtterances()[0], 'Sentence one . Sentence two.'); - this.mockTts.setOnSpeechCallbacks([this.newCallback((utterance) => { + this.mockTts.setOnSpeechCallbacks([this.newCallback(utterance => { // Speech for second click. assertTrue(this.mockTts.currentlySpeaking()); assertEquals(this.mockTts.pendingUtterances().length, 1); @@ -436,7 +436,7 @@ async function() { const bodyHtml = '<p>This is some <b>bold</b> text</p><p>Second paragraph</p>'; - const setFocusCallback = this.newCallback((root) => { + const setFocusCallback = this.newCallback(root => { const firstNode = this.findTextNode(root, 'This is some '); const lastNode = this.findTextNode(root, 'Second paragraph'); // Sets the selection from "is some" to "Second". @@ -816,7 +816,7 @@ 'SelectToSpeakNavigationControlTest', 'ResumeFromSelectionEndingInSpace', async function() { const bodyHtml = '<p>This is some text with space.</p>'; - const setFocusCallback = this.newCallback((root) => { + const setFocusCallback = this.newCallback(root => { const node = this.findTextNode(root, 'This is some text with space.'); // Sets the selection to "This ". chrome.automation.setDocumentSelection({ @@ -828,7 +828,7 @@ }); const root = await this.runWithLoadedTree(bodyHtml); root.addEventListener( - 'documentSelectionChanged', this.newCallback((event) => { + 'documentSelectionChanged', this.newCallback(event => { this.triggerReadSelectedText(); assertTrue(this.mockTts.currentlySpeaking()); @@ -1007,7 +1007,7 @@ {keyCode: SelectToSpeakConstants.SEARCH_KEY_CODE}); // Verify focus is still on button within panel. - chrome.automation.getFocus(this.newCallback((focusedNode) => { + chrome.automation.getFocus(this.newCallback(focusedNode => { assertEquals(focusedNode.role, RoleType.TOGGLE_BUTTON); assertTrue(this.isNodeWithinPanel(focusedNode)); })); @@ -1029,7 +1029,7 @@ const root = await this.runWithLoadedTree(bodyHtml); // Expect call to updateSelectToSpeakPanel to set panel to be hidden. chrome.accessibilityPrivate.updateSelectToSpeakPanel = - this.newCallback((visible) => { + this.newCallback(visible => { assertFalse(visible); });
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js index e2fdf62..0bb0e48 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js
@@ -20,7 +20,7 @@ const AccessibilityFeature = chrome.accessibilityPrivate.AccessibilityFeature; chrome.accessibilityPrivate.isFeatureEnabled( - AccessibilityFeature.ENHANCED_NETWORK_VOICES, (result) => { + AccessibilityFeature.ENHANCED_NETWORK_VOICES, result => { const newElem = document.getElementById('naturalVoicesOptions'); const legacyElem = document.getElementById('noNaturalVoicesOptions'); if (!result) { @@ -43,7 +43,7 @@ }); const select = document.getElementById('language'); - select.onchange = (_) => { + select.onchange = _ => { this.populateVoicesAndLanguages_(); }; @@ -52,7 +52,7 @@ 'naturalVoice', 'enhancedVoiceName', 'voiceName'); chrome.settingsPrivate.getPref( PrefsManager.ENHANCED_VOICES_POLICY_KEY, - (network_voices_allowed) => { + network_voices_allowed => { if (network_voices_allowed !== undefined && !network_voices_allowed.value) { // If the feature is disallowed, sets the checkbox to false. @@ -64,7 +64,7 @@ } else { // If the feature is allowed, syncs the checkbox with pref. this.syncCheckboxControlToPref_( - 'naturalVoices', 'enhancedNetworkVoices', (checked) => { + 'naturalVoices', 'enhancedNetworkVoices', checked => { this.setVoiceSelectionAndPreviewVisibility_( /* isVisible = */ checked); }); @@ -74,14 +74,14 @@ }); this.syncCheckboxControlToPref_( - 'wordHighlight', 'wordHighlight', (checked) => { + 'wordHighlight', 'wordHighlight', checked => { const elem = document.getElementById('highlightSubOption'); const select = document.getElementById('highlightColor'); this.setElementVisible(elem, checked); select.disabled = !checked; }); this.syncCheckboxControlToPref_( - 'backgroundShading', 'backgroundShading', (checked) => { + 'backgroundShading', 'backgroundShading', checked => { const elem = document.getElementById('backgroundPreviewContainer'); this.setElementVisible(elem, checked); }); @@ -171,7 +171,7 @@ * @private */ populateVoiceList_(selectId) { - chrome.tts.getVoices((voices) => { + chrome.tts.getVoices(voices => { const select = document.getElementById(selectId); // Add the system voice. this.initializeSelectWithDefault_( @@ -185,7 +185,7 @@ voices.sort(function(a, b) { return a.voiceName.localeCompare(b.voiceName || ''); }); - voices.forEach((voice) => { + voices.forEach(voice => { if (!this.isVoiceUsable_(voice) || (voice.extensionId === PrefsManager.ENHANCED_TTS_EXTENSION_ID)) { // Don't show network voices for legacy interface. @@ -209,7 +209,7 @@ * @private */ populateVoicesAndLanguages_() { - chrome.tts.getVoices((voices) => { + chrome.tts.getVoices(voices => { // Initialize language select. const languageSelect = document.getElementById('language'); const originalLanguageValue = @@ -280,7 +280,7 @@ const networkVoices = new Map(); const currentLocale = chrome.i18n.getUILanguage().toLowerCase() || ''; - voices.forEach((voice) => { + voices.forEach(voice => { if (!this.isVoiceUsable_(voice)) { return; } @@ -314,7 +314,7 @@ }); // Populate local and network selects. - voiceLanguagesList.forEach((voiceLang) => { + voiceLanguagesList.forEach(voiceLang => { this.appendVoicesToSelect_( localSelect, localVoices.get(voiceLang), /*numberVoices=*/ false); this.appendVoicesToSelect_(
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js index f444779..9b45378 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_prefs_test.js
@@ -71,15 +71,15 @@ // Once prefs are removed from storage, make sure the global prefs are // updated to the appropriate values. this.mockSettingsPrivate_.getPref( - 'settings.tts.speech_rate', this.newCallback((pref) => { + 'settings.tts.speech_rate', this.newCallback(pref => { assertEquals(rate, pref.value); })); this.mockSettingsPrivate_.getPref( - 'settings.tts.speech_pitch', this.newCallback((pref) => { + 'settings.tts.speech_pitch', this.newCallback(pref => { assertEquals(pitch, pref.value); })); }); - this.mockStorage_.onChanged.addListener((prefs) => { + this.mockStorage_.onChanged.addListener(prefs => { // checks that rate and pitch are removed. if (prefs !== undefined && !('rate' in prefs) && !('pitch' in prefs)) { onPrefsRemovedFromStorage();
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.js index fd4bc73..fd94a403 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager.js
@@ -93,7 +93,7 @@ /** @type {!chrome.tts.TtsOptions} */ (Object.assign({}, ttsOptions)); // Saves a copy of the ttsOptions for resume. Object.assign(this.clientTtsOptions_, ttsOptions); - modifiedOptions.onEvent = (event) => { + modifiedOptions.onEvent = event => { switch (event.type) { case chrome.tts.EventType.ERROR: if (this.isNetworkVoice_) { @@ -178,7 +178,7 @@ * @return {!Promise} */ pause() { - return new Promise((resolve) => { + return new Promise(resolve => { this.pauseCompleteCallback_ = () => { this.pauseCompleteCallback_ = null; resolve();
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js index f3f020a..c5ea9817d 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/tts_manager_unittest.js
@@ -13,7 +13,7 @@ getTtsOptions() { const options = /** @type {!chrome.tts.TtsOptions} */ ({}); - options.onEvent = (event) => this.receivedEvent = event; + options.onEvent = event => this.receivedEvent = event; return options; } }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.js index 28b30d60..da63e33 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/ui_manager.js
@@ -106,13 +106,13 @@ this.panelButton_ = null; // Cache desktop and listen to focus changes. - chrome.automation.getDesktop((desktop) => { + chrome.automation.getDesktop(desktop => { this.desktop_ = desktop; // Listen to focus changes so we can grab the floating panel when it // goes into focus, so it can be used later without having to search // through the entire tree. - desktop.addEventListener(EventType.FOCUS, (evt) => { + desktop.addEventListener(EventType.FOCUS, evt => { this.onFocusChange_(evt); }, true); }); @@ -303,7 +303,7 @@ 0; node.boundsForRange( currentWord.start - charIndexInParent, - currentWord.end - charIndexInParent, (bounds) => { + currentWord.end - charIndexInParent, bounds => { const highlights = bounds ? [bounds] : []; chrome.accessibilityPrivate.setHighlights( highlights, this.prefsManager_.highlightColor()); @@ -393,7 +393,7 @@ if (!node) { return false; } - return AutomationUtil.getAncestors(node).find((n) => { + return AutomationUtil.getAncestors(node).find(n => { return n.className === SELECT_TO_SPEAK_TRAY_CLASS_NAME; }) !== undefined; }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js index c003d13..2fe18e1 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/action_manager.js
@@ -235,7 +235,7 @@ } let actions = this.actionNode_.actions; const possibleActions = this.actionsForType_(this.currentMenuType_); - actions = actions.filter((a) => possibleActions.includes(a)); + actions = actions.filter(a => possibleActions.includes(a)); if (this.currentMenuType_ === SAConstants.MenuType.MAIN_MENU) { actions = this.addGlobalActions_(actions); }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js index 80acdab..4beaf1d4 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js
@@ -55,7 +55,7 @@ 'a valid CSS color string.')); return; } - manager.rings_.forEach((ring) => ring.color = color); + manager.rings_.forEach(ring => ring.color = color); } /** @@ -124,7 +124,7 @@ /** Clears all focus rings. */ static clearAll() { const manager = FocusRingManager.instance; - manager.rings_.forEach((ring) => { + manager.rings_.forEach(ring => { ring.rects = []; }); manager.updateFocusRings_(null, null); @@ -185,7 +185,7 @@ } const focusRings = []; - this.rings_.forEach((ring) => focusRings.push(ring)); + this.rings_.forEach(ring => focusRings.push(ring)); chrome.accessibilityPrivate.setFocusRings(focusRings); // Keep track of the nodes associated with each focus ring for testing
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js index e205c93..bc88931 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js
@@ -23,7 +23,7 @@ }; TEST_F('SwitchAccessFocusRingManagerTest', 'BackButtonFocus', function() { - this.runWithLoadedDesktop((desktop) => { + this.runWithLoadedDesktop(desktop => { // Focus the back button. Navigator.byItem.moveTo_( desktop.find({role: chrome.automation.RoleType.TAB}));
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js index 696e165..c57fb1dd 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager.js
@@ -103,7 +103,7 @@ /** @override */ exitKeyboard() { this.ignoreFocusInKeyboard_ = false; - const isKeyboard = (data) => data.group instanceof KeyboardRootNode; + const isKeyboard = data => data.group instanceof KeyboardRootNode; // If we are not in the keyboard, do nothing. if (!(this.group_ instanceof KeyboardRootNode) && !this.history_.containsDataMatchingPredicate(isKeyboard)) { @@ -164,7 +164,7 @@ /** @override */ moveBackward() { if (this.node_.isValidAndVisible()) { - this.tryMoving(this.node_.previous, (node) => node.previous, this.node_); + this.tryMoving(this.node_.previous, node => node.previous, this.node_); } else { this.moveToValidNode(); } @@ -173,7 +173,7 @@ /** @override */ moveForward() { if (this.node_.isValidAndVisible()) { - this.tryMoving(this.node_.next, (node) => node.next, this.node_); + this.tryMoving(this.node_.next, node => node.next, this.node_); } else { this.moveToValidNode(); } @@ -208,7 +208,7 @@ // Check if the top center is visible as a proxy for occlusion. It's // possible that other parts of the window are occluded, but in Chrome we // can't drag windows off the top of the screen. - this.desktop_.hitTestWithReply(center.x, location.top, (hitNode) => { + this.desktop_.hitTestWithReply(center.x, location.top, hitNode => { if (AutomationUtil.isDescendantOf(hitNode, node.automationNode)) { this.setNode_(node); } else if (node.isValidAndVisible()) { @@ -253,7 +253,7 @@ restart() { const point = Navigator.byPoint.currentPoint; SwitchAccess.mode = SAConstants.Mode.ITEM_SCAN; - this.desktop_.hitTestWithReply(point.x, point.y, (node) => { + this.desktop_.hitTestWithReply(point.x, point.y, node => { this.moveTo_(node); }); } @@ -416,7 +416,7 @@ new RepeatedTreeChangeHandler( chrome.automation.TreeChangeObserverFilter.ALL_TREE_CHANGES, treeChange => this.onTreeChange_(treeChange), { - predicate: (treeChange) => + predicate: treeChange => this.group_.findChild(treeChange.target) != null || this.group_.isEquivalentTo(treeChange.target) });
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js index 4115c30..226951e 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/item_scan_manager_test.js
@@ -34,9 +34,9 @@ const cache = new SACache(); if (!SwitchAccessPredicate.isGroup(pageContents, null, cache)) { pageContents = - new AutomationTreeWalker(pageContents, constants.Dir.FORWARD, { - visit: (node) => SwitchAccessPredicate.isGroup(node, null, cache) - }) + new AutomationTreeWalker( + pageContents, constants.Dir.FORWARD, + {visit: node => SwitchAccessPredicate.isGroup(node, null, cache)}) .next() .node; } @@ -174,7 +174,7 @@ node.addEventListener( chrome.automation.EventType.CHECKED_STATE_CHANGED, - this.newCallback((event) => { + this.newCallback(event => { assertEquals( node.name, event.target.name, 'Checked state changed on unexpected node'); @@ -383,7 +383,7 @@ // Wait for the potential value change. await new Promise(resolve => { input.automationNode.addEventListener( - chrome.automation.EventType.VALUE_CHANGED, (event) => { + chrome.automation.EventType.VALUE_CHANGED, event => { if (event.target.value === 'q') { resolve(); } @@ -436,7 +436,7 @@ }); await new Promise(resolve => { keyboard.automationNode.addEventListener( - chrome.automation.EventType.STATE_CHANGED, (event) => { + chrome.automation.EventType.STATE_CHANGED, event => { if (event.target.role === chrome.automation.RoleType.KEYBOARD && event.target.state.invisible) { resolve(); @@ -611,7 +611,7 @@ }); // The button is no longer in the tree because the screen is locked. - const predicate = (node) => node.name === 'kitties!' && + const predicate = node => node.name === 'kitties!' && node.role === chrome.automation.RoleType.BUTTON; assertNotNullNorUndefined( this.desktop_, 'this.desktop_ is null or undefined.');
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/metrics.js b/chrome/browser/resources/chromeos/accessibility/switch_access/metrics.js index 4546f93..af01687 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/metrics.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/metrics.js
@@ -9,7 +9,7 @@ /** * @param {string} menuAction */ - recordMenuAction: (menuAction) => { + recordMenuAction: menuAction => { const metricName = 'Accessibility.CrosSwitchAccess.MenuAction.' + SwitchAccessMetrics.toUpperCamelCase(menuAction); chrome.metricsPrivate.recordUserAction(metricName); @@ -19,10 +19,10 @@ * @param {string} str * @return {string} */ - toUpperCamelCase: (str) => { + toUpperCamelCase: str => { const wordRegex = /(?:^\w|[A-Z]|(?:\b|_)\w)/g; const underscoreAndWhitespaceRegex = /(\s|_)+/g; - return str.replace(wordRegex, (word) => word.toUpperCase()) + return str.replace(wordRegex, word => word.toUpperCase()) .replace(underscoreAndWhitespaceRegex, ''); } };
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js index 61c73a1..55db5c6 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node.js
@@ -298,7 +298,7 @@ super.onFocus(); this.childrenChangedHandler_ = new RepeatedEventHandler( this.automationNode, chrome.automation.EventType.CHILDREN_CHANGED, - (event) => { + event => { const cache = new SACache(); if (SwitchAccessPredicate.isInterestingSubtree(event.target, cache)) { this.refresh(); @@ -316,7 +316,7 @@ /** @override */ refreshChildren() { - const childConstructor = (node) => BasicNode.create(node, this); + const childConstructor = node => BasicNode.create(node, this); try { BasicRootNode.findAndSetChildren(this, childConstructor); } catch (e) { @@ -371,7 +371,7 @@ } const root = new BasicRootNode(rootNode); - const childConstructor = (node) => BasicNode.create(node, root); + const childConstructor = node => BasicNode.create(node, root); BasicRootNode.findAndSetChildren(root, childConstructor); return root; @@ -387,7 +387,7 @@ static findAndSetChildren(root, childConstructor) { const interestingChildren = BasicRootNode.getInterestingChildren(root); const children = interestingChildren.map(childConstructor) - .filter((child) => child.isValidAndVisible()); + .filter(child => child.isValidAndVisible()); if (children.length < 1) { throw SwitchAccess.error(
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js index e29f651..5694b978 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/basic_node_test.js
@@ -55,7 +55,7 @@ }); TEST_F('SwitchAccessBasicNodeTest', 'Equals', function() { - this.runWithLoadedDesktop((desktop) => { + this.runWithLoadedDesktop(desktop => { const desktopNode = DesktopNode.build(desktop); let childGroup = desktopNode.firstChild;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node.js index f8d903c..8407fcd 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node.js
@@ -48,7 +48,7 @@ } // Update this DesktopNode's children. - const childConstructor = (node) => BasicNode.create(node, this); + const childConstructor = node => BasicNode.create(node, this); DesktopNode.findAndSetChildren(this, childConstructor); // Set the new instance of that child to be the focused node. @@ -72,7 +72,7 @@ */ static build(desktop) { const root = new DesktopNode(desktop); - const childConstructor = (autoNode) => BasicNode.create(autoNode, root); + const childConstructor = autoNode => BasicNode.create(autoNode, root); DesktopNode.findAndSetChildren(root, childConstructor); return root;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js index 2b8109b..9820538e 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/desktop_node_test.js
@@ -17,7 +17,7 @@ }; TEST_F('SwitchAccessDesktopNodeTest', 'Build', function() { - this.runWithLoadedDesktop((desktop) => { + this.runWithLoadedDesktop(desktop => { const desktopNode = DesktopNode.build(desktop); const children = desktopNode.children;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js index 712100e..85360f8 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/group_node_test.js
@@ -18,7 +18,7 @@ TEST_F('SwitchAccessGroupNodeTest', 'NodesRemoved', function() { const website = `<button></button>`; - this.runWithLoadedTree(website, (rootWebArea) => { + this.runWithLoadedTree(website, rootWebArea => { const button = rootWebArea.find({role: chrome.automation.RoleType.BUTTON}); assertNotEquals(undefined, button);
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js index 11dd273..abea39a 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/keyboard_node.js
@@ -223,7 +223,7 @@ * @private */ static findAndSetChildren_(root) { - const childConstructor = (node) => new KeyboardNode(node, root); + const childConstructor = node => new KeyboardNode(node, root); const interestingChildren = root.automationNode.findAll({role: chrome.automation.RoleType.BUTTON}); /** @type {!Array<!SAChildNode>} */
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/modal_dialog_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/modal_dialog_node.js index 774e0a3c..475e2ad 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/modal_dialog_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/modal_dialog_node.js
@@ -22,7 +22,7 @@ */ static buildTree(dialogNode) { const root = new ModalDialogRootNode(dialogNode); - const childConstructor = (node) => BasicNode.create(node, root); + const childConstructor = node => BasicNode.create(node, root); BasicRootNode.findAndSetChildren(root, childConstructor); return root;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js index d3558a1..7869114 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js
@@ -329,8 +329,8 @@ /** @return {!chrome.accessibilityPrivate.ScreenRect} */ get location() { const children = this.children_.filter( - (c) => !c.ignoreWhenComputingUnionOfBoundingBoxes()); - const childLocations = children.map((c) => c.location); + c => !c.ignoreWhenComputingUnionOfBoundingBoxes()); + const childLocations = children.map(c => c.location); return RectUtil.unionAll(childLocations); } @@ -395,7 +395,7 @@ // Must have one interesting child whose location is important. return this.children_ .filter( - (child) => + child => !(child.ignoreWhenComputingUnionOfBoundingBoxes()) && child.isValidAndVisible()) .length >= 1; @@ -403,8 +403,7 @@ /** @return {SAChildNode} */ firstValidChild() { - const children = - this.children_.filter((child) => child.isValidAndVisible()); + const children = this.children_.filter(child => child.isValidAndVisible()); return children.length > 0 ? children[0] : null; } @@ -419,7 +418,7 @@ /** Called when a group should recalculate its children. */ refreshChildren() { - this.children = this.children.filter((child) => child.isValidAndVisible()); + this.children = this.children.filter(child => child.isValidAndVisible()); } /** Called when the group's children may have changed. */
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js index eeb9bbce..4df1e4b6 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/tab_node_test.js
@@ -17,7 +17,7 @@ }; TEST_F('SwitchAccessTabNodeTest', 'FindCloseButton', function() { - this.runWithLoadedDesktop((desktop) => { + this.runWithLoadedDesktop(desktop => { const tab = desktop.find({role: chrome.automation.RoleType.TAB}); // To find the close button, Switch Access relies on it being the only @@ -33,7 +33,7 @@ }); TEST_F('SwitchAccessTabNodeTest', 'Construction', function() { - this.runWithLoadedDesktop((desktop) => { + this.runWithLoadedDesktop(desktop => { Navigator.byItem.moveTo_( desktop.find({role: chrome.automation.RoleType.TAB}));
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/window_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/window_node.js index 9938657..1bf8e05 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/window_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/window_node.js
@@ -28,7 +28,7 @@ */ static buildTree(windowNode) { const root = new WindowRootNode(windowNode); - const childConstructor = (node) => BasicNode.create(node, root); + const childConstructor = node => BasicNode.create(node, root); BasicRootNode.findAndSetChildren(root, childConstructor); return root;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/point_scan_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/point_scan_manager_test.js index aac7d8e..80ab094 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/point_scan_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/point_scan_manager_test.js
@@ -92,7 +92,7 @@ const rootWebArea = await this.runWithLoadedTree(site); let setFocusRingsCallCount = 0; // Mock this API to track how many times it's called. - chrome.accessibilityPrivate.setFocusRings = (focusRings) => { + chrome.accessibilityPrivate.setFocusRings = focusRings => { setFocusRingsCallCount += 1; }; assertEquals(0, setFocusRingsCallCount);
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js index 9714677b..9ebdce5c 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/preference_manager.js
@@ -81,9 +81,9 @@ /** @private */ init_() { chrome.settingsPrivate.onPrefsChanged.addListener( - (prefs) => this.updateFromSettings_(prefs)); + prefs => this.updateFromSettings_(prefs)); chrome.settingsPrivate.getAllPrefs( - (prefs) => this.updateFromSettings_(prefs, true /* isFirstLoad */)); + prefs => this.updateFromSettings_(prefs, true /* isFirstLoad */)); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/compiler.js b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/compiler.js index 38f1e4ea..87a1ff6c 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/compiler.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/compiler.js
@@ -48,7 +48,7 @@ // Read all the files in the tests/ directory. const filenames = fs.readdirSync(testDir); - filenames.forEach((filename) => { + filenames.forEach(filename => { console.log('Compiling file: ', filename); const contents = fs.readFileSync(testDir + filename, {encoding: 'utf8'}); stream.write(parse(contents).output + '\n');
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js index 5fbbeda..b4fb73f 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/compiler/parser.js
@@ -3523,7 +3523,7 @@ const decreaseIndent = () => indent = indent.substring(2); let buffer = ''; - const addToBuffer = (text) => buffer += indent + text + '\n'; + const addToBuffer = text => buffer += indent + text + '\n'; const flushBuffer = () => { const result = buffer; buffer = ''; @@ -3549,7 +3549,7 @@ return flushBuffer(); }; - const finishTest = (opt_url) => { + const finishTest = opt_url => { decreaseIndent(); if (opt_url) { addToBuffer(`}, {url: ${opt_url.output}});`);
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/gen/saatlite_tests.js b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/gen/saatlite_tests.js index 40ad965..52ac2f1 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/gen/saatlite_tests.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/saatlite/gen/saatlite_tests.js
@@ -13,7 +13,7 @@ }; TEST_F('SwitchAccessSAATLiteTest', 'Demo', function() { - this.runWithLoadedTree('<button>Hi</button>', async (rootWebArea) => { + this.runWithLoadedTree('<button>Hi</button>', async rootWebArea => { TestUtility.startFocusInside(rootWebArea); TestUtility.pressNextSwitch(); TestUtility.pressPreviousSwitch();
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js index e57365e..157921e 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access.js
@@ -19,7 +19,7 @@ static initialize() { SwitchAccess.instance = new SwitchAccess(); - chrome.automation.getDesktop((desktop) => { + chrome.automation.getDesktop(desktop => { chrome.automation.getFocus(focus => { // Focus is available. Finish init without waiting for further events. // Disallow web view nodes, which indicate a root web area is still @@ -62,7 +62,7 @@ this.enableImprovedTextInput_ = false; chrome.commandLinePrivate.hasSwitch( - 'enable-experimental-accessibility-switch-access-text', (result) => { + 'enable-experimental-accessibility-switch-access-text', result => { this.enableImprovedTextInput_ = result; }); @@ -110,7 +110,7 @@ desktop, chrome.automation.EventType.CHILDREN_CHANGED, null /** callback */); - const onEvent = (event) => { + const onEvent = event => { if (event.target.matches(findParams)) { // If the event target is the node we're looking for, we've found it. eventHandler.stop();
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_e2e_test_base.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_e2e_test_base.js index c3591fa..115ca3b 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_e2e_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_e2e_test_base.js
@@ -38,7 +38,7 @@ * @return {!AutomationNode} */ findNodeById(id) { - const predicate = (node) => node.htmlAttributes.id === id; + const predicate = node => node.htmlAttributes.id === id; const nodeString = 'node with id "' + id + '"'; return this.findNodeMatchingPredicate(predicate, nodeString); } @@ -49,7 +49,7 @@ * @return {!AutomationNode} */ findNodeByNameAndRole(name, role) { - const predicate = (node) => node.name === name && node.role === role; + const predicate = node => node.name === name && node.role === role; const nodeString = 'node with name "' + name + '" and role ' + role; return this.findNodeMatchingPredicate(predicate, nodeString); } @@ -69,7 +69,7 @@ * @return {!Promise} */ untilFocusIs(expected) { - const doesMatch = (expected) => { + const doesMatch = expected => { const newNode = Navigator.byItem.node_; const automationNode = newNode.automationNode || {}; return (!expected.instance || newNode instanceof expected.instance) && @@ -102,7 +102,7 @@ return; } const original = Navigator.byItem.setNode_.bind(Navigator.byItem); - Navigator.byItem.setNode_ = (node) => { + Navigator.byItem.setNode_ = node => { original(node); lastFocusChangeTime = new Date(); if (doesMatch(expected)) {
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js index 869087e..a284a17 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js
@@ -99,7 +99,7 @@ // child is an interesting subtree. if (state[StateType.FOCUSABLE] || role === RoleType.MENU_ITEM) { const result = !node.children.some( - (child) => SwitchAccessPredicate.isInterestingSubtree(child, cache)); + child => SwitchAccessPredicate.isInterestingSubtree(child, cache)); cache.isActionable.set(node, result); return result; } @@ -181,7 +181,7 @@ * @param {AutomationNode} node * @return {boolean} */ - isVisible: (node) => Boolean( + isVisible: node => Boolean( !node.state[StateType.OFFSCREEN] && node.location && node.location.top >= 0 && node.location.left >= 0 && !node.state[StateType.INVISIBLE]), @@ -205,8 +205,7 @@ } const result = SwitchAccessPredicate.isActionable(node, cache) || node.children.some( - (child) => - SwitchAccessPredicate.isInterestingSubtree(child, cache)); + child => SwitchAccessPredicate.isInterestingSubtree(child, cache)); cache.isInterestingSubtree.set(node, result); return result; }, @@ -216,14 +215,14 @@ * @param {AutomationNode} node * @return {boolean} */ - isTextInput: (node) => Boolean(node && node.state[StateType.EDITABLE]), + isTextInput: node => Boolean(node && node.state[StateType.EDITABLE]), /** * Returns true if |node| should be considered a window. * @param {AutomationNode} node * @return {boolean} */ - isWindow: (node) => Boolean( + isWindow: node => Boolean( node && (node.role === chrome.automation.RoleType.WINDOW || (node.role === chrome.automation.RoleType.CLIENT && node.parent && @@ -235,7 +234,7 @@ * @param {!AutomationNode} scope * @return {!AutomationTreeWalkerRestriction} */ - restrictions: (scope) => { + restrictions: scope => { const cache = new SACache(); return { leaf: SwitchAccessPredicate.leaf(scope, cache), @@ -253,7 +252,7 @@ * @return {function(!AutomationNode): boolean} */ leaf(scope, cache) { - return (node) => !SwitchAccessPredicate.isInterestingSubtree(node, cache) || + return node => !SwitchAccessPredicate.isInterestingSubtree(node, cache) || (scope !== node && SwitchAccessPredicate.isInteresting(node, scope, cache)); }, @@ -266,7 +265,7 @@ * @return {function(!AutomationNode): boolean} */ root(scope) { - return (node) => scope === node; + return node => scope === node; }, /** @@ -278,7 +277,7 @@ * @return {function(!AutomationNode): boolean} */ visit(scope, cache) { - return (node) => node.role !== RoleType.DESKTOP && + return node => node.role !== RoleType.DESKTOP && SwitchAccessPredicate.isInteresting(node, scope, cache); } };
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js index c07a7ec..322752c 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager.js
@@ -250,7 +250,7 @@ */ static saveSelectStart() { const manager = TextNavigationManager.instance; - chrome.automation.getFocus((focusedNode) => { + chrome.automation.getFocus(focusedNode => { manager.selectionStartObject_ = focusedNode; manager.selectionStartIndex_ = manager.getSelectionIndexFromNode_( manager.selectionStartObject_, @@ -319,7 +319,7 @@ */ static saveSelectEnd() { const manager = TextNavigationManager.instance; - chrome.automation.getFocus((focusedNode) => { + chrome.automation.getFocus(focusedNode => { manager.selectionEndObject_ = focusedNode; manager.selectionEndIndex_ = manager.getSelectionIndexFromNode_( manager.selectionEndObject_,
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js index 81b0af4c..b316806 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/text_navigation_manager_test.js
@@ -155,7 +155,7 @@ * @param {!AutomationNode} inputNode */ function checkNodeIsFocused(inputNode) { - chrome.automation.getFocus((focusedNode) => { + chrome.automation.getFocus(focusedNode => { assertEquals(focusedNode.role, inputNode.role); }); }
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_print_server_dialog.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_print_server_dialog.js index df0254b..39761eb 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_print_server_dialog.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_print_server_dialog.js
@@ -7,94 +7,116 @@ * add a print server. */ -import '//resources/cr_elements/cr_button/cr_button.m.js'; -import '//resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import './cups_add_printer_dialog.js'; import './cups_printer_dialog_error.js'; import './cups_printer_shared_css.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {loadTimeData} from '../../i18n_setup.js'; +import {getPrintServerErrorText} from './cups_printer_dialog_util.js'; +import {CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, PrintServerResult} from './cups_printers_browser_proxy.js'; -import {getBaseName, getErrorText, getPrintServerErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid, matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; +/** @polymer */ +class AddPrintServerDialogElement extends PolymerElement { + static get is() { + return 'add-print-server-dialog'; + } -Polymer({ - _template: html`{__html_template__}`, - is: 'add-print-server-dialog', + static get template() { + return html`{__html_template__}`; + } - properties: { - /** @private {string} */ - printServerAddress_: { - type: String, - value: '', - }, + static get properties() { + return { + /** @private {string} */ + printServerAddress_: { + type: String, + value: '', + }, - /** @private {string} */ - errorText_: { - type: String, - value: '', - }, + /** @private {string} */ + errorText_: { + type: String, + value: '', + }, - /** @private {boolean} */ - inProgress_: { - type: Boolean, - value: false, - }, - }, + /** @private {boolean} */ + inProgress_: { + type: Boolean, + value: false, + }, + + }; + } + + constructor() { + super(); + + /** @private {!CupsPrintersBrowserProxy} */ + this.browserProxy_ = CupsPrintersBrowserProxyImpl.getInstance(); + } /** @private */ - onCancelTap_: function() { - this.$$('add-printer-dialog').close(); - }, + onCancelTap_() { + this.shadowRoot.querySelector('add-printer-dialog').close(); + } /** @private */ - onAddPrintServerTap_: function() { + onAddPrintServerTap_() { this.inProgress_ = true; - this.$$('#printServerAddressInput').invalid = false; - CupsPrintersBrowserProxyImpl.getInstance() - .queryPrintServer(this.printServerAddress_) + this.shadowRoot.querySelector('#printServerAddressInput').invalid = false; + this.browserProxy_.queryPrintServer(this.printServerAddress_) .then( this.onPrintServerAddedSucceeded_.bind(this), this.onPrintServerAddedFailed_.bind(this)); - }, + } /** * @param {!CupsPrintersList} printers * @private */ - onPrintServerAddedSucceeded_: function(printers) { + onPrintServerAddedSucceeded_(printers) { this.inProgress_ = false; - this.fire('add-print-server-and-show-toast', {printers: printers}); - this.$$('add-printer-dialog').close(); - }, + const addPrintServerEvent = + new CustomEvent('add-print-server-and-show-toast', { + bubbles: true, + composed: true, + detail: {printers}, + }); + this.dispatchEvent(addPrintServerEvent); + this.shadowRoot.querySelector('add-printer-dialog').close(); + } /** * @param {*} addPrintServerError * @private */ - onPrintServerAddedFailed_: function(addPrintServerError) { + onPrintServerAddedFailed_(addPrintServerError) { this.inProgress_ = false; if (addPrintServerError === PrintServerResult.INCORRECT_URL) { - this.$$('#printServerAddressInput').invalid = true; + this.shadowRoot.querySelector('#printServerAddressInput').invalid = true; return; } this.errorText_ = getPrintServerErrorText( /** @type {PrintServerResult} */ (addPrintServerError)); - }, + } /** * Keypress event handler. If enter is pressed, trigger the add event. * @param {!Event} event * @private */ - onKeypress_: function(event) { + onKeypress_(event) { if (event.key !== 'Enter') { return; } event.stopPropagation(); this.onAddPrintServerTap_(); - }, -}); + } +} + +customElements.define( + AddPrintServerDialogElement.is, AddPrintServerDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_dialog.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_dialog.js index d5dfbab..e6c7d81d 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_dialog.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_dialog.js
@@ -2,27 +2,37 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** 'add-printer-dialog' is the template of the Add Printer dialog. */ -import '//resources/cr_elements/cr_dialog/cr_dialog.m.js'; -import '//resources/cr_elements/icons.m.js'; -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +/** + * @fileoverview 'add-printer-dialog' is the template of the Add Printer + * dialog. + */ +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; +import 'chrome://resources/cr_elements/icons.m.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import './cups_printer_shared_css.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {getBaseName, getErrorText, getPrintServerErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid, matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; +/** @polymer */ +class AddPrinterDialogElement extends PolymerElement { + static get is() { + return 'add-printer-dialog'; + } -Polymer({ - _template: html`{__html_template__}`, - is: 'add-printer-dialog', + static get template() { + return html`{__html_template__}`; + } /** @private */ - attached() { + connectedCallback() { + super.connectedCallback(); + this.$.dialog.showModal(); - }, + } close() { this.$.dialog.close(); - }, -}); + } +} + +customElements.define(AddPrinterDialogElement.is, AddPrinterDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manually_dialog.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manually_dialog.js index 21deecd..bf6959f 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manually_dialog.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manually_dialog.js
@@ -7,6 +7,19 @@ * manually enter the information to set up a new printer. */ +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_components/localized_link/localized_link.js'; +import './cups_add_printer_dialog.js'; +import './cups_printer_dialog_error.js'; +import './cups_add_print_server_dialog.js'; +import './cups_printer_shared_css.js'; + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getErrorText, isNameAndAddressValid} from './cups_printer_dialog_util.js'; +import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, PrinterMakeModel, PrinterSetupResult} from './cups_printers_browser_proxy.js'; + function getEmptyPrinter_() { return { ppdManufacturer: '', @@ -29,57 +42,61 @@ }; } -import {afterNextRender, Polymer, html, flush, Templatizer, TemplateInstanceBase} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +/** @polymer */ +class AddPrinterManuallyDialogElement extends PolymerElement { + static get is() { + return 'add-printer-manually-dialog'; + } -import '//resources/cr_elements/cr_button/cr_button.m.js'; -import '//resources/cr_elements/cr_input/cr_input.m.js'; -import '//resources/cr_components/localized_link/localized_link.js'; -import {loadTimeData} from '../../i18n_setup.js'; -import './cups_add_printer_dialog.js'; -import './cups_printer_dialog_error.js'; -import './cups_add_print_server_dialog.js'; -import {sortPrinters, matchesSearchTerm, getBaseName, getErrorText, isNetworkProtocol, isNameAndAddressValid, isPPDInfoValid, getPrintServerErrorText} from './cups_printer_dialog_util.js'; -import './cups_printer_shared_css.js'; -import {CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrinterInfo, PrinterSetupResult, CupsPrintersList, PrinterPpdMakeModel, ManufacturersInfo, ModelsInfo, PrintServerResult, PrinterMakeModel} from './cups_printers_browser_proxy.js'; + static get template() { + return html`{__html_template__}`; + } -Polymer({ - _template: html`{__html_template__}`, - is: 'add-printer-manually-dialog', + static get properties() { + return { + /** @type {!CupsPrinterInfo} */ + newPrinter: {type: Object, notify: true, value: getEmptyPrinter_}, - properties: { - /** @type {!CupsPrinterInfo} */ - newPrinter: {type: Object, notify: true, value: getEmptyPrinter_}, + /** @private */ + addPrinterInProgress_: { + type: Boolean, + value: false, + }, - /** @private */ - addPrinterInProgress_: { - type: Boolean, - value: false, - }, + /** + * The error text to be displayed on the dialog. + * @private + */ + errorText_: { + type: String, + value: '', + }, - /** - * The error text to be displayed on the dialog. - * @private - */ - errorText_: { - type: String, - value: '', - }, + /** @private */ + showPrinterQueue_: { + type: Boolean, + value: true, + }, + }; + } - /** @private */ - showPrinterQueue_: { - type: Boolean, - value: true, - }, - }, + static get observers() { + return [ + 'printerInfoChanged_(newPrinter.*)', + ]; + } - observers: [ - 'printerInfoChanged_(newPrinter.*)', - ], + constructor() { + super(); + + /** @private {!CupsPrintersBrowserProxy} */ + this.browserProxy_ = CupsPrintersBrowserProxyImpl.getInstance(); + } /** @private */ onCancelTap_() { - this.$$('add-printer-dialog').close(); - }, + this.shadowRoot.querySelector('add-printer-dialog').close(); + } /** * Handler for addCupsPrinter success. @@ -87,11 +104,15 @@ * @private */ onAddPrinterSucceeded_(result) { - this.fire( - 'show-cups-printer-toast', - {resultCode: result, printerName: this.newPrinter.printerName}); - this.$$('add-printer-dialog').close(); - }, + const showCupsPrinterToastEvent = + new CustomEvent('show-cups-printer-toast', { + bubbles: true, + composed: true, + detail: {resultCode: result, printerName: this.newPrinter.printerName} + }); + this.dispatchEvent(showCupsPrinterToastEvent); + this.shadowRoot.querySelector('add-printer-dialog').close(); + } /** * Handler for addCupsPrinter failure. @@ -101,7 +122,16 @@ onAddPrinterFailed_(result) { this.errorText_ = getErrorText( /** @type {PrinterSetupResult} */ (result)); - }, + } + + /** @private */ + openManufacturerModelDialog_() { + const event = new CustomEvent('open-manufacturer-model-dialog', { + bubbles: true, + composed: true, + }); + this.dispatchEvent(event); + } /** * Handler for getPrinterInfo success. @@ -125,16 +155,15 @@ // Add the printer if it's configurable. Otherwise, forward to the // manufacturer dialog. if (info.ppdReferenceResolved) { - CupsPrintersBrowserProxyImpl.getInstance() - .addCupsPrinter(this.newPrinter) + this.browserProxy_.addCupsPrinter(this.newPrinter) .then( this.onAddPrinterSucceeded_.bind(this), this.onAddPrinterFailed_.bind(this)); } else { - this.$$('add-printer-dialog').close(); - this.fire('open-manufacturer-model-dialog'); + this.shadowRoot.querySelector('add-printer-dialog').close(); + this.openManufacturerModelDialog_(); } - }, + } /** * Handler for getPrinterInfo failure. @@ -150,7 +179,7 @@ } this.errorText_ = getErrorText( /** @type {PrinterSetupResult} */ (result)); - }, + } /** @private */ addPressed_() { @@ -158,20 +187,25 @@ if (this.newPrinter.printerProtocol === 'ipp' || this.newPrinter.printerProtocol === 'ipps') { - CupsPrintersBrowserProxyImpl.getInstance() - .getPrinterInfo(this.newPrinter) + this.browserProxy_.getPrinterInfo(this.newPrinter) .then(this.onPrinterFound_.bind(this), this.infoFailed_.bind(this)); } else { - this.$$('add-printer-dialog').close(); - this.fire('open-manufacturer-model-dialog'); + this.shadowRoot.querySelector('add-printer-dialog').close(); + this.openManufacturerModelDialog_(); } - }, + } /** @private */ - onPrintServerTap_: function() { - this.$$('add-printer-dialog').close(); - this.fire('open-add-print-server-dialog'); - }, + onPrintServerTap_() { + this.shadowRoot.querySelector('add-printer-dialog').close(); + + const openAddPrintServerDialogEvent = + new CustomEvent('open-add-print-server-dialog', { + bubbles: true, + composed: true, + }); + this.dispatchEvent(openAddPrintServerDialogEvent); + } /** * @param {!Event} event @@ -181,7 +215,7 @@ // Queue input should be hidden when protocol is set to "App Socket". this.showPrinterQueue_ = event.target.value !== 'socket'; this.set('newPrinter.printerProtocol', event.target.value); - }, + } /** * @return {boolean} Whether the add printer button is enabled. @@ -190,13 +224,13 @@ canAddPrinter_() { return !this.addPrinterInProgress_ && isNameAndAddressValid(this.newPrinter); - }, + } /** @private */ printerInfoChanged_() { this.$.printerAddressInput.invalid = false; this.errorText_ = ''; - }, + } /** * Keypress event handler. If enter is pressed, printer is added if @@ -213,5 +247,8 @@ if (this.canAddPrinter_()) { this.addPressed_(); } - }, -}); + } +} + +customElements.define( + AddPrinterManuallyDialogElement.is, AddPrinterManuallyDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.js index 96ce71a2..122ed05 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_add_printer_manufacturer_model_dialog.js
@@ -7,106 +7,125 @@ * 'add-printer-manufacturer-model-dialog' is a dialog in which the user can * manually select the manufacture and model of the new printer. */ -import '//resources/cr_elements/cr_button/cr_button.m.js'; -import '//resources/cr_elements/cr_input/cr_input.m.js'; -import '//resources/cr_components/localized_link/localized_link.js'; +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_components/localized_link/localized_link.js'; import './cups_add_printer_dialog.js'; import './cups_printer_dialog_error.js'; import './cups_printer_shared_css.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; -import {getBaseName, getErrorText, getPrintServerErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid, matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; +import {getBaseName, getErrorText, isPPDInfoValid} from './cups_printer_dialog_util.js'; +import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, ManufacturersInfo, ModelsInfo, PrinterSetupResult} from './cups_printers_browser_proxy.js'; -Polymer({ - _template: html`{__html_template__}`, - is: 'add-printer-manufacturer-model-dialog', +/** @polymer */ +class AddPrinterManufacturerModelDialogElement extends PolymerElement { + static get is() { + return 'add-printer-manufacturer-model-dialog'; + } - properties: { - /** @type {!CupsPrinterInfo} */ - activePrinter: { - type: Object, - notify: true, - }, + static get template() { + return html`{__html_template__}`; + } - /** @type {?Array<string>} */ - manufacturerList: Array, + static get properties() { + return { + /** @type {!CupsPrinterInfo} */ + activePrinter: { + type: Object, + notify: true, + }, - /** @type {?Array<string>} */ - modelList: Array, + /** @type {?Array<string>} */ + manufacturerList: Array, - /** - * Whether the user selected PPD file is valid. - * @private - */ - invalidPPD_: { - type: Boolean, - value: false, - }, + /** @type {?Array<string>} */ + modelList: Array, - /** - * The base name of a newly selected PPD file. - * @private - */ - newUserPPD_: String, + /** + * Whether the user selected PPD file is valid. + * @private + */ + invalidPPD_: { + type: Boolean, + value: false, + }, - /** - * The URL to a printer's EULA. - * @private - */ - eulaUrl_: { - type: String, - value: '', - }, + /** + * The base name of a newly selected PPD file. + * @private + */ + newUserPPD_: String, - /** @private */ - addPrinterInProgress_: { - type: Boolean, - value: false, - }, + /** + * The URL to a printer's EULA. + * @private + */ + eulaUrl_: { + type: String, + value: '', + }, - /** - * The error text to be displayed on the dialog. - * @private - */ - errorText_: { - type: String, - value: '', - }, + /** @private */ + addPrinterInProgress_: { + type: Boolean, + value: false, + }, - /** - * Indicates whether the value in the Manufacturer dropdown is a valid - * printer manufacturer. - * @private - */ - isManufacturerInvalid_: Boolean, + /** + * The error text to be displayed on the dialog. + * @private + */ + errorText_: { + type: String, + value: '', + }, - /** - * Indicates whether the value in the Model dropdown is a valid printer - * model. - * @private - */ - isModelInvalid_: Boolean, - }, + /** + * Indicates whether the value in the Manufacturer dropdown is a valid + * printer manufacturer. + * @private + */ + isManufacturerInvalid_: Boolean, - observers: [ - 'selectedManufacturerChanged_(activePrinter.ppdManufacturer)', - 'selectedModelChanged_(activePrinter.ppdModel)', - ], + /** + * Indicates whether the value in the Model dropdown is a valid printer + * model. + * @private + */ + isModelInvalid_: Boolean, + }; + } + + static get observers() { + return [ + 'selectedManufacturerChanged_(activePrinter.ppdManufacturer)', + 'selectedModelChanged_(activePrinter.ppdModel)', + + ]; + } + + constructor() { + super(); + + /** @private {!CupsPrintersBrowserProxy} */ + this.browserProxy_ = CupsPrintersBrowserProxyImpl.getInstance(); + } /** @override */ - attached() { - CupsPrintersBrowserProxyImpl.getInstance() - .getCupsPrinterManufacturersList() - .then(this.manufacturerListChanged_.bind(this)); - }, + connectedCallback() { + super.connectedCallback(); + + this.browserProxy_.getCupsPrinterManufacturersList().then( + this.manufacturerListChanged_.bind(this)); + } close() { - this.$$('add-printer-dialog').close(); - }, + this.shadowRoot.querySelector('add-printer-dialog').close(); + } /** * Handler for addCupsPrinter success. @@ -114,11 +133,16 @@ * @private */ onPrinterAddedSucceeded_(result) { - this.fire( - 'show-cups-printer-toast', - {resultCode: result, printerName: this.activePrinter.printerName}); + const showCupsPrinterToastEvent = + new CustomEvent('show-cups-printer-toast', { + bubbles: true, + composed: true, + detail: + {resultCode: result, printerName: this.activePrinter.printerName}, + }); + this.dispatchEvent(showCupsPrinterToastEvent); this.close(); - }, + } /** * Handler for addCupsPrinter failure. @@ -129,7 +153,7 @@ this.addPrinterInProgress_ = false; this.errorText_ = getErrorText( /** @type {PrinterSetupResult} */ (result)); - }, + } /** * If the printer is a nearby printer, return make + model with the subtext. @@ -147,7 +171,7 @@ return loadTimeData.getStringF( 'manufacturerAndModelAdditionalInformation', this.activePrinter.printerName); - }, + } /** * @param {string} manufacturer The manufacturer for which we are retrieving @@ -159,11 +183,10 @@ this.set('activePrinter.ppdModel', ''); this.modelList = []; if (manufacturer && manufacturer.length !== 0) { - CupsPrintersBrowserProxyImpl.getInstance() - .getCupsPrinterModelsList(manufacturer) + this.browserProxy_.getCupsPrinterModelsList(manufacturer) .then(this.modelListChanged_.bind(this)); } - }, + } /** * Attempts to get the EULA Url if the selected printer has one. @@ -178,11 +201,11 @@ return; } - CupsPrintersBrowserProxyImpl.getInstance() + this.browserProxy_ .getEulaUrl( this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel) .then(this.onGetEulaUrlCompleted_.bind(this)); - }, + } /** * @param {string} eulaUrl The URL for the printer's EULA. @@ -190,7 +213,7 @@ */ onGetEulaUrlCompleted_(eulaUrl) { this.eulaUrl_ = eulaUrl; - }, + } /** * @param {!ManufacturersInfo} manufacturersInfo @@ -202,11 +225,11 @@ } this.manufacturerList = manufacturersInfo.manufacturers; if (this.activePrinter.ppdManufacturer.length !== 0) { - CupsPrintersBrowserProxyImpl.getInstance() + this.browserProxy_ .getCupsPrinterModelsList(this.activePrinter.ppdManufacturer) .then(this.modelListChanged_.bind(this)); } - }, + } /** * @param {!ModelsInfo} modelsInfo @@ -216,13 +239,13 @@ if (modelsInfo.success) { this.modelList = modelsInfo.models; } - }, + } /** @private */ onBrowseFile_() { - CupsPrintersBrowserProxyImpl.getInstance().getCupsPrinterPPDPath().then( + this.browserProxy_.getCupsPrinterPPDPath().then( this.printerPPDPathChanged_.bind(this)); - }, + } /** * @param {string} path The full path to the selected PPD file @@ -232,24 +255,22 @@ this.set('activePrinter.printerPPDPath', path); this.invalidPPD_ = !path; this.newUserPPD_ = getBaseName(path); - }, + } /** @private */ onCancelTap_() { this.close(); - CupsPrintersBrowserProxyImpl.getInstance().cancelPrinterSetUp( - this.activePrinter); - }, + this.browserProxy_.cancelPrinterSetUp(this.activePrinter); + } /** @private */ addPrinter_() { this.addPrinterInProgress_ = true; - CupsPrintersBrowserProxyImpl.getInstance() - .addCupsPrinter(this.activePrinter) + this.browserProxy_.addCupsPrinter(this.activePrinter) .then( this.onPrinterAddedSucceeded_.bind(this), this.onPrinterAddedFailed_.bind(this)); - }, + } /** * @param {string} ppdManufacturer @@ -264,5 +285,9 @@ return !addPrinterInProgress && isPPDInfoValid(ppdManufacturer, ppdModel, printerPPDPath) && !isManufacturerInvalid && !isModelInvalid; - }, -}); + } +} + +customElements.define( + AddPrinterManufacturerModelDialogElement.is, + AddPrinterManufacturerModelDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_edit_printer_dialog.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_edit_printer_dialog.js index 0bfec1d4..b38ec37 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_edit_printer_dialog.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_edit_printer_dialog.js
@@ -7,196 +7,212 @@ * existing printer's information and re-configure it. */ -import '//resources/cr_elements/cr_button/cr_button.m.js'; -import '//resources/cr_elements/cr_input/cr_input.m.js'; -import '//resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js'; -import '//resources/cr_elements/shared_style_css.m.js'; -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; -import '//resources/cr_components/localized_link/localized_link.js'; +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js'; +import 'chrome://resources/cr_elements/shared_style_css.m.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; +import 'chrome://resources/cr_components/localized_link/localized_link.js'; import './cups_add_printer_dialog.js'; import './cups_printer_dialog_error.js'; import './cups_printer_shared_css.js'; -import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from '//resources/cr_components/chromeos/network/mojo_interface_provider.m.js'; -import {NetworkListenerBehavior} from '//resources/cr_components/chromeos/network/network_listener_behavior.m.js'; -import {OncMojo} from '//resources/cr_components/chromeos/network/onc_mojo.m.js'; -import {CrScrollableBehavior} from '//resources/cr_elements/cr_scrollable_behavior.m.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from 'chrome://resources/cr_components/chromeos/network/mojo_interface_provider.m.js'; +import {NetworkListenerBehavior, NetworkListenerBehaviorInterface} from 'chrome://resources/cr_components/chromeos/network/network_listener_behavior.m.js'; +import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js'; +import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/js/i18n_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; - -import {loadTimeData} from '../../i18n_setup.js'; import {recordSettingChange} from '../metrics_recorder.js'; -import {getBaseName, getErrorText, getPrintServerErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid, matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; - -Polymer({ - _template: html`{__html_template__}`, - is: 'settings-cups-edit-printer-dialog', - - behaviors: [ - I18nBehavior, - NetworkListenerBehavior, - ], - - properties: { - /** - * The currently saved printer. - * @type {CupsPrinterInfo} - */ - activePrinter: Object, - - /** - * Printer that holds the modified changes to activePrinter and only - * applies these changes when the save button is clicked. - * @type {CupsPrinterInfo} - */ - pendingPrinter_: Object, - - /** - * If the printer needs to be re-configured. - * @private {boolean} - */ - needsReconfigured_: { - type: Boolean, - value: false, - }, - - /** - * The current PPD in use by the printer. - * @private - */ - userPPD_: String, +import {getBaseName, getErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid} from './cups_printer_dialog_util.js'; +import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, ManufacturersInfo, ModelsInfo, PrinterPpdMakeModel, PrinterSetupResult} from './cups_printers_browser_proxy.js'; - /** - * Tracks whether the dialog is fully initialized. This is required because - * the dialog isn't fully initialized until Model and Manufacturer are set. - * Allows us to ignore changes made to these fields until initialization is - * complete. - * @private - */ - arePrinterFieldsInitialized_: { - type: Boolean, - value: false, - }, +/** + * @constructor + * @extends {PolymerElement} + * @implements {I18nBehaviorInterface} + * @implements {NetworkListenerBehaviorInterface} + */ +const SettingsCupsEditPrinterDialogElementBase = + mixinBehaviors([I18nBehavior, NetworkListenerBehavior], PolymerElement); - /** - * If the printer info has changed since loading this dialog. This will - * only track the freeform input fields, since the other fields contain - * input selected from dropdown menus. - * @private - */ - printerInfoChanged_: { - type: Boolean, - value: false, - }, +/** @polymer */ +class SettingsCupsEditPrinterDialogElement extends + SettingsCupsEditPrinterDialogElementBase { + static get is() { + return 'settings-cups-edit-printer-dialog'; + } - networkProtocolActive_: { - type: Boolean, - computed: 'isNetworkProtocol_(pendingPrinter_.printerProtocol)', - }, + static get template() { + return html`{__html_template__}`; + } - /** @type {?Array<string>} */ - manufacturerList: Array, + static get properties() { + return { + /** + * The currently saved printer. + * @type {CupsPrinterInfo} + */ + activePrinter: Object, - /** @type {?Array<string>} */ - modelList: Array, + /** + * Printer that holds the modified changes to activePrinter and only + * applies these changes when the save button is clicked. + * @type {CupsPrinterInfo} + */ + pendingPrinter_: Object, - /** - * Whether the user selected PPD file is valid. - * @private - */ - invalidPPD_: { - type: Boolean, - value: false, - }, + /** + * If the printer needs to be re-configured. + * @private {boolean} + */ + needsReconfigured_: { + type: Boolean, + value: false, + }, - /** - * The base name of a newly selected PPD file. - * @private - */ - newUserPPD_: String, + /** + * The current PPD in use by the printer. + * @private + */ + userPPD_: String, - /** - * The URL to a printer's EULA. - * @private - */ - eulaUrl_: { - type: String, - value: '', - }, + /** + * Tracks whether the dialog is fully initialized. This is required + * because the dialog isn't fully initialized until Model and Manufacturer + * are set. Allows us to ignore changes made to these fields until + * initialization is complete. + * @private + */ + arePrinterFieldsInitialized_: { + type: Boolean, + value: false, + }, - /** @private */ - isOnline_: { - type: Boolean, - value: true, - }, + /** + * If the printer info has changed since loading this dialog. This will + * only track the freeform input fields, since the other fields contain + * input selected from dropdown menus. + * @private + */ + printerInfoChanged_: { + type: Boolean, + value: false, + }, - /** - * The error text to be displayed on the dialog. - * @private - */ - errorText_: { - type: String, - value: '', - }, + networkProtocolActive_: { + type: Boolean, + computed: 'isNetworkProtocol_(pendingPrinter_.printerProtocol)', + }, - /** - * Indicates whether the value in the Manufacturer dropdown is a valid - * printer manufacturer. - * @private - */ - isManufacturerInvalid_: { - type: Boolean, - value: false, - }, + /** @type {?Array<string>} */ + manufacturerList: Array, - /** - * Indicates whether the value in the Model dropdown is a valid printer - * model. - * @private - */ - isModelInvalid_: { - type: Boolean, - value: false, - }, - }, + /** @type {?Array<string>} */ + modelList: Array, - observers: [ - 'printerPathChanged_(pendingPrinter_.*)', - 'selectedEditManufacturerChanged_(pendingPrinter_.ppdManufacturer)', - 'onModelChanged_(pendingPrinter_.ppdModel)', - ], + /** + * Whether the user selected PPD file is valid. + * @private + */ + invalidPPD_: { + type: Boolean, + value: false, + }, - /** @private {?chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */ - networkConfig_: null, + /** + * The base name of a newly selected PPD file. + * @private + */ + newUserPPD_: String, + + /** + * The URL to a printer's EULA. + * @private + */ + eulaUrl_: { + type: String, + value: '', + }, + + /** @private */ + isOnline_: { + type: Boolean, + value: true, + }, + + /** + * The error text to be displayed on the dialog. + * @private + */ + errorText_: { + type: String, + value: '', + }, + + /** + * Indicates whether the value in the Manufacturer dropdown is a valid + * printer manufacturer. + * @private + */ + isManufacturerInvalid_: { + type: Boolean, + value: false, + }, + + /** + * Indicates whether the value in the Model dropdown is a valid printer + * model. + * @private + */ + isModelInvalid_: { + type: Boolean, + value: false, + }, + }; + } + + static get observers() { + return [ + 'printerPathChanged_(pendingPrinter_.*)', + 'selectedEditManufacturerChanged_(pendingPrinter_.ppdManufacturer)', + 'onModelChanged_(pendingPrinter_.ppdModel)', + ]; + } /** @override */ - created() { + constructor() { + super(); + + /** @private {!CupsPrintersBrowserProxy} */ + this.browserProxy_ = CupsPrintersBrowserProxyImpl.getInstance(); + + /** @private {!chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */ this.networkConfig_ = MojoInterfaceProviderImpl.getInstance().getMojoServiceRemote(); - }, + } /** @override */ - attached() { + connectedCallback() { + super.connectedCallback(); + // Create a copy of activePrinter so that we can modify its fields. this.pendingPrinter_ = /** @type{CupsPrinterInfo} */ (Object.assign({}, this.activePrinter)); this.refreshNetworks_(); - CupsPrintersBrowserProxyImpl.getInstance() + this.browserProxy_ .getPrinterPpdManufacturerAndModel(this.pendingPrinter_.printerId) .then( this.onGetPrinterPpdManufacturerAndModel_.bind(this), this.onGetPrinterPpdManufacturerAndModelFailed_.bind(this)); - CupsPrintersBrowserProxyImpl.getInstance() - .getCupsPrinterManufacturersList() - .then(this.manufacturerListChanged_.bind(this)); + this.browserProxy_.getCupsPrinterManufacturersList().then( + this.manufacturerListChanged_.bind(this)); this.userPPD_ = getBaseName(this.pendingPrinter_.printerPPDPath); - }, + } /** * CrosNetworkConfigObserver impl @@ -208,7 +224,7 @@ this.isOnline_ = networks.some(function(network) { return OncMojo.connectionStateIsConnected(network.connectionState); }); - }, + } /** * @param {!{path: string, value: string}} change @@ -218,7 +234,7 @@ if (change.path !== 'pendingPrinter_.printerName') { this.needsReconfigured_ = true; } - }, + } /** * @param {!Event} event @@ -227,17 +243,17 @@ onProtocolChange_(event) { this.set('pendingPrinter_.printerProtocol', event.target.value); this.onPrinterInfoChange_(); - }, + } /** @private */ onPrinterInfoChange_() { this.printerInfoChanged_ = true; - }, + } /** @private */ onCancelTap_() { - this.$$('add-printer-dialog').close(); - }, + this.shadowRoot.querySelector('add-printer-dialog').close(); + } /** * Handler for update|reconfigureCupsPrinter success. @@ -245,11 +261,17 @@ * @private */ onPrinterEditSucceeded_(result) { - this.fire( - 'show-cups-printer-toast', - {resultCode: result, printerName: this.activePrinter.printerName}); - this.$$('add-printer-dialog').close(); - }, + const showCupsPrinterToastEvent = + new CustomEvent('show-cups-printer-toast', { + bubbles: true, + composed: true, + detail: + {resultCode: result, printerName: this.activePrinter.printerName}, + }); + this.dispatchEvent(showCupsPrinterToastEvent); + + this.shadowRoot.querySelector('add-printer-dialog').close(); + } /** * Handler for update|reconfigureCupsPrinter failure. @@ -259,7 +281,7 @@ onPrinterEditFailed_(result) { this.errorText_ = getErrorText( /** @type {PrinterSetupResult} */ (result)); - }, + } /** @private */ onSaveTap_() { @@ -267,21 +289,20 @@ if (!this.needsReconfigured_ || !this.isOnline_) { // If we don't need to reconfigure or we are offline, just update the // printer name. - CupsPrintersBrowserProxyImpl.getInstance() + this.browserProxy_ .updateCupsPrinter( this.activePrinter.printerId, this.activePrinter.printerName) .then( this.onPrinterEditSucceeded_.bind(this), this.onPrinterEditFailed_.bind(this)); } else { - CupsPrintersBrowserProxyImpl.getInstance() - .reconfigureCupsPrinter(this.activePrinter) + this.browserProxy_.reconfigureCupsPrinter(this.activePrinter) .then( this.onPrinterEditSucceeded_.bind(this), this.onPrinterEditFailed_.bind(this)); } recordSettingChange(); - }, + } /** * @return {string} The i18n string for the dialog title. @@ -291,7 +312,7 @@ return this.pendingPrinter_.isManaged ? this.i18n('viewPrinterDialogTitle') : this.i18n('editPrinterDialogTitle'); - }, + } /** * @param {!CupsPrinterInfo} printer @@ -311,7 +332,7 @@ } else { return ''; } - }, + } /** * Handler for getPrinterPpdManufacturerAndModel() success case. @@ -325,7 +346,7 @@ // |needsReconfigured_| needs to reset to false after |ppdManufacturer| and // |ppdModel| are initialized to their correct values. this.needsReconfigured_ = false; - }, + } /** * Handler for getPrinterPpdManufacturerAndModel() failure case. @@ -333,7 +354,7 @@ */ onGetPrinterPpdManufacturerAndModelFailed_() { this.needsReconfigured_ = false; - }, + } /** * @param {string} protocol @@ -342,7 +363,7 @@ */ isNetworkProtocol_(protocol) { return isNetworkProtocol(protocol); - }, + } /** * @return {boolean} Whether the current printer was auto configured. @@ -350,7 +371,7 @@ */ isAutoconfPrinter_() { return this.pendingPrinter_.printerPpdReference.autoconf; - }, + } /** * @return {boolean} Whether the Save button is enabled. @@ -360,7 +381,7 @@ return this.printerInfoChanged_ && (this.isPrinterConfigured_() || !this.isOnline_) && !this.isManufacturerInvalid_ && !this.isModelInvalid_; - }, + } /** * @param {string} manufacturer The manufacturer for which we are retrieving @@ -372,11 +393,10 @@ this.set('pendingPrinter_.ppdModel', ''); this.modelList = []; if (!!manufacturer && manufacturer.length !== 0) { - CupsPrintersBrowserProxyImpl.getInstance() - .getCupsPrinterModelsList(manufacturer) + this.browserProxy_.getCupsPrinterModelsList(manufacturer) .then(this.modelListChanged_.bind(this)); } - }, + } /** * Sets printerInfoChanged_ to true to show that the model has changed. Also @@ -397,7 +417,7 @@ } this.attemptPpdEulaFetch_(); - }, + } /** * @param {string} eulaUrl The URL for the printer's EULA. @@ -405,13 +425,13 @@ */ onGetEulaUrlCompleted_(eulaUrl) { this.eulaUrl_ = eulaUrl; - }, + } /** @private */ onBrowseFile_() { - CupsPrintersBrowserProxyImpl.getInstance().getCupsPrinterPPDPath().then( + this.browserProxy_.getCupsPrinterPPDPath().then( this.printerPPDPathChanged_.bind(this)); - }, + } /** * @param {!ManufacturersInfo} manufacturersInfo @@ -423,11 +443,11 @@ } this.manufacturerList = manufacturersInfo.manufacturers; if (this.pendingPrinter_.ppdManufacturer.length !== 0) { - CupsPrintersBrowserProxyImpl.getInstance() + this.browserProxy_ .getCupsPrinterModelsList(this.pendingPrinter_.ppdManufacturer) .then(this.modelListChanged_.bind(this)); } - }, + } /** * @param {!ModelsInfo} modelsInfo @@ -443,7 +463,7 @@ // |modelList|. this.attemptPpdEulaFetch_(); } - }, + } /** * @param {string} path The full path to the selected PPD file @@ -457,7 +477,7 @@ this.onPrinterInfoChange_(); } this.userPPD_ = getBaseName(path); - }, + } /** * Returns true if the printer has valid name, address, and valid PPD or was @@ -472,7 +492,7 @@ this.pendingPrinter_.ppdManufacturer, this.pendingPrinter_.ppdModel, this.pendingPrinter_.printerPPDPath)); - }, + } /** * Helper function to copy over modified fields to activePrinter. @@ -490,7 +510,7 @@ // Set ppdModel since there is an observer that clears ppdmodel's value when // ppdManufacturer changes. this.activePrinter.ppdModel = this.pendingPrinter_.ppdModel; - }, + } /** * Callback function when networks change. @@ -506,7 +526,7 @@ .then((responseParams) => { this.onActiveNetworksChanged(responseParams.result); }); - }, + } /** * Returns true if the printer protocol select field should be enabled. @@ -528,7 +548,7 @@ } return this.isOnline_ && this.networkProtocolActive_; - }, + } /** * Attempts fetching for the EULA Url based off of the current printer's @@ -541,11 +561,11 @@ return; } - CupsPrintersBrowserProxyImpl.getInstance() + this.browserProxy_ .getEulaUrl( this.pendingPrinter_.ppdManufacturer, this.pendingPrinter_.ppdModel) .then(this.onGetEulaUrlCompleted_.bind(this)); - }, + } /** * @return {boolean} True if we're on an active network and the printer @@ -560,7 +580,7 @@ } return this.networkProtocolActive_; - }, + } /** * @return {boolean} True if the printer is managed or not online. @@ -569,6 +589,9 @@ isInputFieldReadonly_() { return !this.isOnline_ || (this.pendingPrinter_ && this.pendingPrinter_.isManaged); - }, + } +} -}); +customElements.define( + SettingsCupsEditPrinterDialogElement.is, + SettingsCupsEditPrinterDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js index c2578333..2f6262c 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_enterprise_printers.js
@@ -2,21 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; -import '//resources/cr_elements/icons.m.js'; -import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import '//resources/polymer/v3_0/iron-list/iron-list.js'; +/** + * @fileoverview 'settings-cups-enterprise-printers' is a list container for + * Enterprise Printers. + */ + +import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; +import 'chrome://resources/cr_elements/icons.m.js'; +import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; +import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; import './cups_printers_entry.js'; import '../../settings_shared_css.js'; -import {ListPropertyUpdateBehavior} from '//resources/js/list_property_update_behavior.m.js'; -import {WebUIListenerBehavior} from '//resources/js/web_ui_listener_behavior.m.js'; -import {html, Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {ListPropertyUpdateBehavior, ListPropertyUpdateBehaviorInterface} from 'chrome://resources/js/list_property_update_behavior.m.js'; +import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; import {PrinterListEntry} from './cups_printer_types.js'; import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl} from './cups_printers_browser_proxy.js'; -import {CupsPrintersEntryListBehavior} from './cups_printers_entry_list_behavior.js'; +import {CupsPrintersEntryListBehavior, CupsPrintersEntryListBehaviorInterface} from './cups_printers_entry_list_behavior.js'; // If the Show more button is visible, the minimum number of printers we show // is 3. @@ -35,109 +40,131 @@ } /** - * @fileoverview 'settings-cups-enterprise-printers' is a list container for - * Enterprise Printers. + * @constructor + * @extends {PolymerElement} + * @implements {CupsPrintersEntryListBehaviorInterface} + * @implements {ListPropertyUpdateBehaviorInterface} + * @implements {WebUIListenerBehaviorInterface} */ -Polymer({ - _template: html`{__html_template__}`, - is: 'settings-cups-enterprise-printers', +const SettingsCupsEnterprisePrintersElementBase = mixinBehaviors( + [ + CupsPrintersEntryListBehavior, ListPropertyUpdateBehavior, + WebUIListenerBehavior + ], + PolymerElement); - // ListPropertyUpdateBehavior is used in CupsPrintersEntryListBehavior. - behaviors: [ - CupsPrintersEntryListBehavior, - ListPropertyUpdateBehavior, - WebUIListenerBehavior, - ], +/** @polymer */ +class SettingsCupsEnterprisePrintersElement extends + SettingsCupsEnterprisePrintersElementBase { + static get is() { + return 'settings-cups-enterprise-printers'; + } - properties: { - /** - * Search term for filtering |enterprisePrinters|. - * @type {string} - */ - searchTerm: { - type: String, - value: '', - }, + static get template() { + return html`{__html_template__}`; + } - /** @type {?CupsPrinterInfo} */ - activePrinter: { - type: Object, - notify: true, - }, + static get properties() { + return { + /** + * Search term for filtering |enterprisePrinters|. + * @type {string} + */ + searchTerm: { + type: String, + value: '', + }, - /** - * @type {number} - * @private - */ - activePrinterListEntryIndex_: { - type: Number, - value: -1, - }, + /** @type {?CupsPrinterInfo} */ + activePrinter: { + type: Object, + notify: true, + }, - printersCount: { - type: Number, - computed: 'getFilteredPrintersLength_(filteredPrinters_.*)', - notify: true, - }, + /** + * @type {number} + * @private + */ + activePrinterListEntryIndex_: { + type: Number, + value: -1, + }, - /** - * List of printers filtered through a search term. - * @type {!Array<!PrinterListEntry>} - * @private - */ - filteredPrinters_: { - type: Array, - value: () => [], - }, + printersCount: { + type: Number, + computed: 'getFilteredPrintersLength_(filteredPrinters_.*)', + notify: true, + }, - /** - * Keeps track of whether the user has tapped the Show more button. A search - * term will expand the collapsed list, so we need to keep track of whether - * the list expanded because of a search term or because the user tapped on - * the Show more button. - * @private - */ - hasShowMoreBeenTapped_: { - type: Boolean, - value: false, - }, + /** + * List of printers filtered through a search term. + * @type {!Array<!PrinterListEntry>} + * @private + */ + filteredPrinters_: { + type: Array, + value: () => [], + }, - /** - * Used by FocusRowBehavior to track the last focused element on a row. - * @private - */ - lastFocused_: Object, + /** + * Keeps track of whether the user has tapped the Show more button. A + * search term will expand the collapsed list, so we need to keep track of + * whether the list expanded because of a search term or because the user + * tapped on the Show more button. + * @private + */ + hasShowMoreBeenTapped_: { + type: Boolean, + value: false, + }, - /** - * Used by FocusRowBehavior to track if the list has been blurred. - * @private - */ - listBlurred_: Boolean, - }, + /** + * Used by FocusRowBehavior to track the last focused element on a row. + * @private + */ + lastFocused_: Object, - listeners: { - 'open-action-menu': 'onOpenActionMenu_', - }, + /** + * Used by FocusRowBehavior to track if the list has been blurred. + * @private + */ + listBlurred_: Boolean, + }; + } - observers: [ - 'onSearchOrPrintersChanged_(enterprisePrinters.*, searchTerm, ' + - 'hasShowMoreBeenTapped_)', - ], - - /** @private {CupsPrintersBrowserProxy} */ - browserProxy_: null, - - /** - * The number of printers we display if hidden printers are allowed. - * kMinVisiblePrinters is the default value and we never show fewer printers - * if the Show more button is visible. - */ - visiblePrinterCounter_: kMinVisiblePrinters, + static get observers() { + return [ + 'onSearchOrPrintersChanged_(enterprisePrinters.*, searchTerm, ' + + 'hasShowMoreBeenTapped_)', + ]; + } /** @override */ - created() { + constructor() { + super(); + + /** @private {!CupsPrintersBrowserProxy} */ this.browserProxy_ = CupsPrintersBrowserProxyImpl.getInstance(); - }, + + /** + * The number of printers we display if hidden printers are allowed. + * kMinVisiblePrinters is the default value and we never show fewer printers + * if the Show more button is visible. + */ + this.visiblePrinterCounter_ = kMinVisiblePrinters; + } + + ready() { + super.ready(); + this.addEventListener('open-action-menu', (event) => { + this.onOpenActionMenu_( + /** + @type {!CustomEvent<{target: !HTMLElement, item: + !PrinterListEntry}>} + */ + (event)); + }); + } /** * Redoes the search whenever |searchTerm| or |enterprisePrinters| changes. @@ -165,12 +192,12 @@ this.updateList( 'filteredPrinters_', printer => printer.printerInfo.printerId, updatedPrinters); - }, + } /** @private */ onShowMoreTap_() { this.hasShowMoreBeenTapped_ = true; - }, + } /** * Keeps track of whether the Show more button should be visible which means @@ -198,7 +225,7 @@ } return true; - }, + } /** * @return {boolean} Returns true if the no search message should be visible. @@ -206,7 +233,7 @@ */ showNoSearchResultsMessage_() { return !!this.searchTerm && !this.filteredPrinters_.length; - }, + } /** * @return {number} Length of |filteredPrinters_|. @@ -214,7 +241,7 @@ */ getFilteredPrintersLength_() { return this.filteredPrinters_.length; - }, + } /** * @param {!CustomEvent<{target: !HTMLElement, item: !PrinterListEntry}>} e @@ -230,18 +257,24 @@ .printerInfo; const target = /** @type {!HTMLElement} */ (e.detail.target); - this.$$('cr-action-menu').showAt(target); - }, + this.shadowRoot.querySelector('cr-action-menu').showAt(target); + } /** @private */ onViewTap_() { // Event is caught by 'settings-cups-printers'. - this.fire('edit-cups-printer-details'); + const editCupsPrinterDetailsEvent = new CustomEvent( + 'edit-cups-printer-details', {bubbles: true, composed: true}); + this.dispatchEvent(editCupsPrinterDetailsEvent); this.closeActionMenu_(); - }, + } /** @private */ closeActionMenu_() { - this.$$('cr-action-menu').close(); - }, -}); + this.shadowRoot.querySelector('cr-action-menu').close(); + } +} + +customElements.define( + SettingsCupsEnterprisePrintersElement.is, + SettingsCupsEnterprisePrintersElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js index 21db7fb..b38f991 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_nearby_printers.js
@@ -6,112 +6,142 @@ * @fileoverview 'settings-cups-nearby-printers' is a list container for * Nearby Printers. */ -import '//resources/polymer/v3_0/iron-list/iron-list.js'; +import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; import './cups_printers_entry.js'; import '../../settings_shared_css.js'; -import {ListPropertyUpdateBehavior} from '//resources/js/list_property_update_behavior.m.js'; -import {WebUIListenerBehavior} from '//resources/js/web_ui_listener_behavior.m.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {ListPropertyUpdateBehavior, ListPropertyUpdateBehaviorInterface} from 'chrome://resources/js/list_property_update_behavior.m.js'; +import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {recordSettingChange} from '../metrics_recorder.js'; -import {getBaseName, getErrorText, getPrintServerErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid, matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; -import {PrinterListEntry, PrinterType} from './cups_printer_types.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; -import {CupsPrintersEntryListBehavior} from './cups_printers_entry_list_behavior.js'; -import {CupsPrintersEntryManager} from './cups_printers_entry_manager.js'; +import {matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; +import {PrinterListEntry} from './cups_printer_types.js'; +import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, PrinterSetupResult} from './cups_printers_browser_proxy.js'; +import {CupsPrintersEntryListBehavior, CupsPrintersEntryListBehaviorInterface} from './cups_printers_entry_list_behavior.js'; -Polymer({ - _template: html`{__html_template__}`, - is: 'settings-cups-nearby-printers', +/** + * @constructor + * @extends {PolymerElement} + * @implements {CupsPrintersEntryListBehaviorInterface} + * @implements {ListPropertyUpdateBehaviorInterface} + * @implements {WebUIListenerBehaviorInterface} + */ +const SettingsCupsNearbyPrintersElementBase = mixinBehaviors( + [ + CupsPrintersEntryListBehavior, ListPropertyUpdateBehavior, + WebUIListenerBehavior + ], + PolymerElement); - // ListPropertyUpdateBehavior is used in CupsPrintersEntryListBehavior. - behaviors: [ - CupsPrintersEntryListBehavior, - ListPropertyUpdateBehavior, - WebUIListenerBehavior, - ], +/** @polymer */ +class SettingsCupsNearbyPrintersElement extends + SettingsCupsNearbyPrintersElementBase { + static get is() { + return 'settings-cups-nearby-printers'; + } - properties: { - /** - * Search term for filtering |nearbyPrinters|. - * @type {string} - */ - searchTerm: { - type: String, - value: '', - }, + static get template() { + return html`{__html_template__}`; + } - /** - * This value is set to true if UserPrintersAllowed policy is enabled. - */ - userPrintersAllowed: { - type: Boolean, - value: false, - }, + static get properties() { + return { + /** + * Search term for filtering |nearbyPrinters|. + * @type {string} + */ + searchTerm: { + type: String, + value: '', + }, - /** @type {?CupsPrinterInfo} */ - activePrinter: { - type: Object, - notify: true, - }, + /** + * This value is set to true if UserPrintersAllowed policy is enabled. + */ + userPrintersAllowed: { + type: Boolean, + value: false, + }, - printersCount: { - type: Number, - computed: 'getFilteredPrintersLength_(filteredPrinters_.*)', - notify: true, - }, + /** @type {?CupsPrinterInfo} */ + activePrinter: { + type: Object, + notify: true, + }, - /** - * @type {number} - * @private - */ - activePrinterListEntryIndex_: { - type: Number, - value: -1, - }, + printersCount: { + type: Number, + computed: 'getFilteredPrintersLength_(filteredPrinters_.*)', + notify: true, + }, - /** - * List of printers filtered through a search term. - * @type {!Array<!PrinterListEntry>} - * @private - */ - filteredPrinters_: { - type: Array, - value: () => [], - }, + /** + * @type {number} + * @private + */ + activePrinterListEntryIndex_: { + type: Number, + value: -1, + }, - /** - * Used by FocusRowBehavior to track the last focused element on a row. - * @private - */ - lastFocused_: Object, + /** + * List of printers filtered through a search term. + * @type {!Array<!PrinterListEntry>} + * @private + */ + filteredPrinters_: { + type: Array, + value: () => [], + }, - /** - * Used by FocusRowBehavior to track if the list has been blurred. - * @private - */ - listBlurred_: Boolean, + /** + * Used by FocusRowBehavior to track the last focused element on a row. + * @private + */ + lastFocused_: Object, - /** - * This is set to true while waiting for a response during a printer setup. - * @type {boolean} - * @private - */ - savingPrinter_: { - type: Boolean, - value: false, - }, - }, + /** + * Used by FocusRowBehavior to track if the list has been blurred. + * @private + */ + listBlurred_: Boolean, - listeners: { - 'add-automatic-printer': 'onAddAutomaticPrinter_', - 'add-print-server-printer': 'onAddPrintServerPrinter_', - 'query-discovered-printer': 'onQueryDiscoveredPrinter_', - }, + /** + * This is set to true while waiting for a response during a printer + * setup. + * @type {boolean} + * @private + */ + savingPrinter_: { + type: Boolean, + value: false, + }, + }; + } - observers: ['onSearchOrPrintersChanged_(nearbyPrinters.*, searchTerm)'], + static get observers() { + return ['onSearchOrPrintersChanged_(nearbyPrinters.*, searchTerm)']; + } + + ready() { + super.ready(); + this.addEventListener('add-automatic-printer', (event) => { + this.onAddAutomaticPrinter_( + /** @type {!CustomEvent<{item: !PrinterListEntry}>} */ (event)); + }); + + this.addEventListener('add-print-server-printer', (event) => { + this.onAddPrintServerPrinter_( + /** @type {!CustomEvent<{item: !PrinterListEntry}>} */ (event)); + }); + + this.addEventListener('query-discovered-printer', (event) => { + this.onQueryDiscoveredPrinter_( + /** @type {!CustomEvent<{item: !PrinterListEntry}>} */ (event)); + }); + } /** * Redoes the search whenever |searchTerm| or |nearbyPrinters| changes. @@ -133,7 +163,7 @@ this.updateList( 'filteredPrinters_', printer => printer.printerInfo.printerId, updatedPrinters); - }, + } /** * @param {!CustomEvent<{item: !PrinterListEntry}>} e @@ -151,7 +181,7 @@ this, item.printerInfo.printerName), this.onAddNearbyPrinterFailed_.bind(this)); recordSettingChange(); - }, + } /** * @param {!CustomEvent<{item: !PrinterListEntry}>} e @@ -168,7 +198,7 @@ this.onAddNearbyPrintersSucceeded_.bind( this, item.printerInfo.printerName), this.onAddNearbyPrinterFailed_.bind(this)); - }, + } /** * @param {!CustomEvent<{item: !PrinterListEntry}>} e @@ -191,7 +221,7 @@ this, item.printerInfo.printerName), queryDiscoveredPrinterFailed); recordSettingChange(); - }, + } /** * Retrieves the index of |item| in |nearbyPrinters_| and sets that printer as @@ -207,7 +237,24 @@ this.activePrinter = this.get(['nearbyPrinters', this.activePrinterListEntryIndex_]) .printerInfo; - }, + } + + /** + * @param {!PrinterSetupResult} resultCode + * @param {string} printerName + * @private + */ + showCupsPrinterToast_(resultCode, printerName) { + const event = new CustomEvent('show-cups-printer-toast', { + bubbles: true, + composed: true, + detail: { + resultCode, + printerName, + } + }); + this.dispatchEvent(event); + } /** * Handler for addDiscoveredPrinter success. @@ -217,10 +264,8 @@ */ onAddNearbyPrintersSucceeded_(printerName, result) { this.savingPrinter_ = false; - this.fire( - 'show-cups-printer-toast', - {resultCode: result, printerName: printerName}); - }, + this.showCupsPrinterToast_(result, printerName); + } /** * Handler for addDiscoveredPrinter failure. @@ -229,11 +274,9 @@ */ onAddNearbyPrinterFailed_(printer) { this.savingPrinter_ = false; - this.fire('show-cups-printer-toast', { - resultCode: PrinterSetupResult.PRINTER_UNREACHABLE, - printerName: printer.printerName - }); - }, + this.showCupsPrinterToast_( + PrinterSetupResult.PRINTER_UNREACHABLE, printer.printerName); + } /** * Handler for queryDiscoveredPrinter success. @@ -243,10 +286,8 @@ */ onQueryDiscoveredPrinterSucceeded_(printerName, result) { this.savingPrinter_ = false; - this.fire( - 'show-cups-printer-toast', - {resultCode: result, printerName: printerName}); - }, + this.showCupsPrinterToast_(result, printerName); + } /** * Handler for queryDiscoveredPrinter failure. @@ -255,10 +296,14 @@ */ onQueryDiscoveredPrinterFailed_(printer) { this.savingPrinter_ = false; - this.fire( - 'open-manufacturer-model-dialog-for-specified-printer', - {item: /** @type {CupsPrinterInfo} */ (printer)}); - }, + const openManufacturerDialogEvent = new CustomEvent( + 'open-manufacturer-model-dialog-for-specified-printer', { + bubbles: true, + composed: true, + detail: {item: /** @type {CupsPrinterInfo} */ (printer)} + }); + this.dispatchEvent(openManufacturerDialogEvent); + } /** * @return {boolean} Returns true if the no search message should be visible. @@ -266,7 +311,7 @@ */ showNoSearchResultsMessage_() { return !!this.searchTerm && !this.filteredPrinters_.length; - }, + } /** * @private @@ -274,5 +319,8 @@ */ getFilteredPrintersLength_() { return this.filteredPrinters_.length; - }, -}); + } +} + +customElements.define( + SettingsCupsNearbyPrintersElement.is, SettingsCupsNearbyPrintersElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_error.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_error.js index 9f51e80c..ef3f1fe 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_error.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_error.js
@@ -5,23 +5,30 @@ /** * 'printer-dialog-error' is the error container for dialogs. */ -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import './cups_printer_shared_css.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {getBaseName, getErrorText, getPrintServerErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid, matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; +/** @polymer */ +class PrinterDialogErrorElement extends PolymerElement { + static get is() { + return 'printer-dialog-error'; + } -Polymer({ - _template: html`{__html_template__}`, - is: 'printer-dialog-error', + static get template() { + return html`{__html_template__}`; + } - properties: { - /** The error text to be displayed on the dialog. */ - errorText: { - type: String, - value: '', - }, - }, -}); + static get properties() { + return { + /** The error text to be displayed on the dialog. */ + errorText: { + type: String, + value: '', + }, + }; + } +} + +customElements.define(PrinterDialogErrorElement.is, PrinterDialogErrorElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_util.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_util.js index a77b7bd2..55365a3 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_util.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_dialog_util.js
@@ -12,24 +12,24 @@ * @fileoverview Utility functions that are used in Cups printer setup dialogs. */ - /** - * @param {string} protocol - * @return {boolean} Whether |protocol| is a network protocol - */ +/** + * @param {string} protocol + * @return {boolean} Whether |protocol| is a network protocol + */ export function isNetworkProtocol(protocol) { return ['ipp', 'ipps', 'http', 'https', 'socket', 'lpd'].includes(protocol); } - /** - * Returns true if the printer's name and address is valid. This function - * uses regular expressions to determine whether the provided printer name - * and address are valid. Address can be either an ipv4/6 address or a - * hostname followed by an optional port. - * NOTE: The regular expression for hostnames will allow hostnames that are - * over 255 characters. - * @param {CupsPrinterInfo} printer - * @return {boolean} - */ +/** + * Returns true if the printer's name and address is valid. This function + * uses regular expressions to determine whether the provided printer name + * and address are valid. Address can be either an ipv4/6 address or a + * hostname followed by an optional port. + * NOTE: The regular expression for hostnames will allow hostnames that are + * over 255 characters. + * @param {CupsPrinterInfo} printer + * @return {boolean} + */ export function isNameAndAddressValid(printer) { if (!printer) { return false; @@ -78,22 +78,22 @@ (ipv6AddressRegex.test(address) && !invalidIpv6Regex.test(address)); } - /** - * Returns true if the printer's manufacturer and model or ppd path is valid. - * @param {string} manufacturer - * @param {string} model - * @param {string} ppdPath - * @return {boolean} - */ +/** + * Returns true if the printer's manufacturer and model or ppd path is valid. + * @param {string} manufacturer + * @param {string} model + * @param {string} ppdPath + * @return {boolean} + */ export function isPPDInfoValid(manufacturer, model, ppdPath) { return !!((manufacturer && model) || ppdPath); } - /** - * Returns the base name of a filepath. - * @param {string} path The full path of the file - * @return {string} The base name of the file - */ +/** + * Returns the base name of a filepath. + * @param {string} path The full path of the file + * @return {string} The base name of the file + */ export function getBaseName(path) { if (path && path.length > 0) { return path.substring(path.lastIndexOf('/') + 1); @@ -101,110 +101,110 @@ return ''; } - /** - * A function used for sorting printer names based on the current locale's - * collation order. - * @param {!CupsPrinterInfo} first - * @param {!CupsPrinterInfo} second - * @return {number} The result of the comparison. - */ - function alphabeticalSort(first, second) { - return first.printerName.toLocaleLowerCase().localeCompare( - second.printerName.toLocaleLowerCase()); +/** + * A function used for sorting printer names based on the current locale's + * collation order. + * @param {!CupsPrinterInfo} first + * @param {!CupsPrinterInfo} second + * @return {number} The result of the comparison. + */ +function alphabeticalSort(first, second) { + return first.printerName.toLocaleLowerCase().localeCompare( + second.printerName.toLocaleLowerCase()); +} + +/** + * Return the error string corresponding to the result code. + * @param {!PrinterSetupResult} result + * @return {string} + */ +export function getErrorText(result) { + switch (result) { + case PrinterSetupResult.FATAL_ERROR: + return loadTimeData.getString('printerAddedFatalErrorMessage'); + case PrinterSetupResult.PRINTER_UNREACHABLE: + return loadTimeData.getString('printerAddedUnreachableMessage'); + case PrinterSetupResult.DBUS_ERROR: + // Simply return a generic error message as this error should only + // occur when a call to Dbus fails which isn't meaningful to the user. + return loadTimeData.getString('printerAddedFailedMessage'); + case PrinterSetupResult.NATIVE_PRINTERS_NOT_ALLOWED: + return loadTimeData.getString( + 'printerAddedNativePrintersNotAllowedMessage'); + case PrinterSetupResult.INVALID_PRINTER_UPDATE: + return loadTimeData.getString('editPrinterInvalidPrinterUpdate'); + case PrinterSetupResult.PPD_TOO_LARGE: + return loadTimeData.getString('printerAddedPpdTooLargeMessage'); + case PrinterSetupResult.INVALID_PPD: + return loadTimeData.getString('printerAddedInvalidPpdMessage'); + case PrinterSetupResult.PPD_NOT_FOUND: + return loadTimeData.getString('printerAddedPpdNotFoundMessage'); + case PrinterSetupResult.PPD_UNRETRIEVABLE: + return loadTimeData.getString('printerAddedPpdUnretrievableMessage'); + default: + assertNotReached(); + } +} + +/** + * Return the error string corresponding to the result code for print servers. + * @param {!PrintServerResult} result + * @return {string} + */ +export function getPrintServerErrorText(result) { + switch (result) { + case PrintServerResult.CONNECTION_ERROR: + return loadTimeData.getString('printServerConnectionError'); + case PrintServerResult.CANNOT_PARSE_IPP_RESPONSE: + case PrintServerResult.HTTP_ERROR: + return loadTimeData.getString('printServerConfigurationErrorMessage'); + default: + assertNotReached(); + } +} + +/** + * We sort by printer type, which is based off of a maintained list in + * cups_printers_types.js. If the types are the same, we sort alphabetically. + * @param {!PrinterListEntry} first + * @param {!PrinterListEntry} second + * @return {number} + */ +export function sortPrinters(first, second) { + if (first.printerType === second.printerType) { + return alphabeticalSort(first.printerInfo, second.printerInfo); } - /** - * Return the error string corresponding to the result code. - * @param {!PrinterSetupResult} result - * @return {string} - */ - export function getErrorText(result) { - switch (result) { - case PrinterSetupResult.FATAL_ERROR: - return loadTimeData.getString('printerAddedFatalErrorMessage'); - case PrinterSetupResult.PRINTER_UNREACHABLE: - return loadTimeData.getString('printerAddedUnreachableMessage'); - case PrinterSetupResult.DBUS_ERROR: - // Simply return a generic error message as this error should only - // occur when a call to Dbus fails which isn't meaningful to the user. - return loadTimeData.getString('printerAddedFailedMessage'); - case PrinterSetupResult.NATIVE_PRINTERS_NOT_ALLOWED: - return loadTimeData.getString( - 'printerAddedNativePrintersNotAllowedMessage'); - case PrinterSetupResult.INVALID_PRINTER_UPDATE: - return loadTimeData.getString('editPrinterInvalidPrinterUpdate'); - case PrinterSetupResult.PPD_TOO_LARGE: - return loadTimeData.getString('printerAddedPpdTooLargeMessage'); - case PrinterSetupResult.INVALID_PPD: - return loadTimeData.getString('printerAddedInvalidPpdMessage'); - case PrinterSetupResult.PPD_NOT_FOUND: - return loadTimeData.getString('printerAddedPpdNotFoundMessage'); - case PrinterSetupResult.PPD_UNRETRIEVABLE: - return loadTimeData.getString('printerAddedPpdUnretrievableMessage'); - default: - assertNotReached(); - } - } + return first.printerType - second.printerType; +} - /** - * Return the error string corresponding to the result code for print servers. - * @param {!PrintServerResult} result - * @return {string} - */ - export function getPrintServerErrorText(result) { - switch (result) { - case PrintServerResult.CONNECTION_ERROR: - return loadTimeData.getString('printServerConnectionError'); - case PrintServerResult.CANNOT_PARSE_IPP_RESPONSE: - case PrintServerResult.HTTP_ERROR: - return loadTimeData.getString('printServerConfigurationErrorMessage'); - default: - assertNotReached(); - } - } +/** + * @param {!CupsPrinterInfo} printer + * @param {string} searchTerm + * @return {boolean} True if the printer has |searchTerm| in its name. + */ +export function matchesSearchTerm(printer, searchTerm) { + return printer.printerName.toLowerCase().includes(searchTerm.toLowerCase()); +} - /** - * We sort by printer type, which is based off of a maintained list in - * cups_printers_types.js. If the types are the same, we sort alphabetically. - * @param {!PrinterListEntry} first - * @param {!PrinterListEntry} second - * @return {number} - */ - export function sortPrinters(first, second) { - if (first.printerType === second.printerType) { - return alphabeticalSort(first.printerInfo, second.printerInfo); - } +/** + * @param {!PrinterListEntry} first + * @param {!PrinterListEntry} second + * @return {boolean} + */ +function arePrinterIdsEqual(first, second) { + return first.printerInfo.printerId === second.printerInfo.printerId; +} - return first.printerType - second.printerType; - } - - /** - * @param {!CupsPrinterInfo} printer - * @param {string} searchTerm - * @return {boolean} True if the printer has |searchTerm| in its name. - */ - export function matchesSearchTerm(printer, searchTerm) { - return printer.printerName.toLowerCase().includes(searchTerm.toLowerCase()); - } - - /** - * @param {!PrinterListEntry} first - * @param {!PrinterListEntry} second - * @return {boolean} - */ - function arePrinterIdsEqual(first, second) { - return first.printerInfo.printerId === second.printerInfo.printerId; - } - - /** - * Finds the printers that are in |firstArr| but not in |secondArr|. - * @param {!Array<!PrinterListEntry>} firstArr - * @param {!Array<!PrinterListEntry>} secondArr - * @return {!Array<!PrinterListEntry>} - */ - export function findDifference(firstArr, secondArr) { - return firstArr.filter(p1 => { - return !secondArr.some( - p2 => p2.printerInfo.printerId === p1.printerInfo.printerId); - }); - } +/** + * Finds the printers that are in |firstArr| but not in |secondArr|. + * @param {!Array<!PrinterListEntry>} firstArr + * @param {!Array<!PrinterListEntry>} secondArr + * @return {!Array<!PrinterListEntry>} + */ +export function findDifference(firstArr, secondArr) { + return firstArr.filter(p1 => { + return !secondArr.some( + p2 => p2.printerInfo.printerId === p1.printerInfo.printerId); + }); +}
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.js index 6a37f68f..53e890a 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printer_shared_css.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 '//resources/cr_elements/md_select_css.m.js'; -import '//resources/cr_elements/shared_vars_css.m.js'; -import '//resources/cr_elements/shared_style_css.m.js'; +import 'chrome://resources/cr_elements/md_select_css.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; +import 'chrome://resources/cr_elements/shared_style_css.m.js'; import '../../settings_shared_css.js'; const template = document.createElement('template'); template.innerHTML = ` <dom-module id="cups-printer-shared">{__html_template__}</dom-module> `; -document.body.appendChild(template.content.cloneNode(true)); \ No newline at end of file +document.body.appendChild(template.content.cloneNode(true));
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers.js index 47d7e75..43318004 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers.js
@@ -8,193 +8,206 @@ * set up legacy & non-CloudPrint printers on ChromeOS by leveraging CUPS (the * unix printing system) and the many open source drivers built for CUPS. */ + // TODO(xdai): Rename it to 'settings-cups-printers-page'. -import '//resources/cr_elements/cr_button/cr_button.m.js'; -import '//resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; -import '//resources/cr_elements/cr_toast/cr_toast.js'; -import '//resources/cr_elements/policy/cr_policy_pref_indicator.m.js'; -import '//resources/js/action_link.js'; -import '//resources/cr_elements/action_link_css.m.js'; -import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; +import 'chrome://resources/cr_elements/cr_toast/cr_toast.js'; +import 'chrome://resources/cr_elements/policy/cr_policy_pref_indicator.m.js'; +import 'chrome://resources/js/action_link.js'; +import 'chrome://resources/cr_elements/action_link_css.m.js'; +import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import './cups_settings_add_printer_dialog.js'; import './cups_edit_printer_dialog.js'; import './cups_enterprise_printers.js'; import './cups_printer_shared_css.js'; import './cups_saved_printers.js'; import './cups_nearby_printers.js'; -import '//resources/cr_components/localized_link/localized_link.js'; +import 'chrome://resources/cr_components/localized_link/localized_link.js'; import '../../icons.html.js'; -import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from '//resources/cr_components/chromeos/network/mojo_interface_provider.m.js'; -import {NetworkListenerBehavior} from '//resources/cr_components/chromeos/network/network_listener_behavior.m.js'; -import {OncMojo} from '//resources/cr_components/chromeos/network/onc_mojo.m.js'; -import {assert, assertNotReached} from '//resources/js/assert.m.js'; -import {addWebUIListener, removeWebUIListener, sendWithPromise, WebUIListener} from '//resources/js/cr.m.js'; -import {focusWithoutInk} from '//resources/js/cr/ui/focus_without_ink.m.js'; -import {loadTimeData} from '//resources/js/load_time_data.m.js'; -import {WebUIListenerBehavior} from '//resources/js/web_ui_listener_behavior.m.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from 'chrome://resources/cr_components/chromeos/network/mojo_interface_provider.m.js'; +import {NetworkListenerBehavior, NetworkListenerBehaviorInterface} from 'chrome://resources/cr_components/chromeos/network/network_listener_behavior.m.js'; +import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {addWebUIListener, removeWebUIListener, sendWithPromise, WebUIListener} from 'chrome://resources/js/cr.m.js'; +import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {afterNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {Route, Router} from '../../router.js'; -import {DeepLinkingBehavior} from '../deep_linking_behavior.js'; +import {Route} from '../../router.js'; +import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior} from '../route_observer_behavior.js'; +import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; import {PrinterListEntry, PrinterType} from './cups_printer_types.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; +import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, PrinterSetupResult} from './cups_printers_browser_proxy.js'; import {CupsPrintersEntryManager} from './cups_printers_entry_manager.js'; -Polymer({ - _template: html`{__html_template__}`, - is: 'settings-cups-printers', +/** + * @constructor + * @extends {PolymerElement} + * @implements {DeepLinkingBehaviorInterface} + * @implements {NetworkListenerBehaviorInterface} + * @implements {RouteObserverBehaviorInterface} + * @implements {WebUIListenerBehaviorInterface} + */ +const SettingsCupsPrintersElementBase = mixinBehaviors( + [ + DeepLinkingBehavior, NetworkListenerBehavior, RouteObserverBehavior, + WebUIListenerBehavior + ], + PolymerElement); - behaviors: [ - DeepLinkingBehavior, - NetworkListenerBehavior, - RouteObserverBehavior, - WebUIListenerBehavior, - ], +/** @polymer */ +class SettingsCupsPrintersElement extends SettingsCupsPrintersElementBase { + static get is() { + return 'settings-cups-printers'; + } - properties: { - /** @type {!Array<!CupsPrinterInfo>} */ - printers: { - type: Array, - notify: true, - }, + static get template() { + return html`{__html_template__}`; + } - prefs: Object, + static get properties() { + return { + /** @type {!Array<!CupsPrinterInfo>} */ + printers: { + type: Array, + notify: true, + }, - /** @type {?CupsPrinterInfo} */ - activePrinter: { - type: Object, - notify: true, - }, + prefs: Object, - /** @private {?WebUIListener} */ - onPrintersChangedListener_: { - type: Object, - value: null, - }, + /** @type {?CupsPrinterInfo} */ + activePrinter: { + type: Object, + notify: true, + }, - /** @private {?WebUIListener} */ - onEnterprisePrintersChangedListener_: { - type: Object, - value: null, - }, + /** @private {?WebUIListener} */ + onPrintersChangedListener_: { + type: Object, + value: null, + }, - searchTerm: { - type: String, - }, + /** @private {?WebUIListener} */ + onEnterprisePrintersChangedListener_: { + type: Object, + value: null, + }, - /** This is also used as an attribute for css styling. */ - canAddPrinter: { - type: Boolean, - reflectToAttribute: true, - }, + searchTerm: { + type: String, + }, - /** - * @type {!Array<!PrinterListEntry>} - * @private - */ - savedPrinters_: { - type: Array, - value: () => [], - }, + /** This is also used as an attribute for css styling. */ + canAddPrinter: { + type: Boolean, + reflectToAttribute: true, + }, - /** - * @type {!Array<!PrinterListEntry>} - * @private - */ - enterprisePrinters_: { - type: Array, - value: () => [], - }, + /** + * @type {!Array<!PrinterListEntry>} + * @private + */ + savedPrinters_: { + type: Array, + value: () => [], + }, - /** @private */ - attemptedLoadingPrinters_: { - type: Boolean, - value: false, - }, + /** + * @type {!Array<!PrinterListEntry>} + * @private + */ + enterprisePrinters_: { + type: Array, + value: () => [], + }, - /** @private */ - showCupsEditPrinterDialog_: Boolean, + /** @private */ + attemptedLoadingPrinters_: { + type: Boolean, + value: false, + }, - /**@private */ - addPrinterResultText_: String, + /** @private */ + showCupsEditPrinterDialog_: Boolean, - /**@private */ - nearbyPrintersAriaLabel_: { - type: String, - computed: 'getNearbyPrintersAriaLabel_(nearbyPrinterCount_)', - }, + /**@private */ + addPrinterResultText_: String, - /**@private */ - savedPrintersAriaLabel_: { - type: String, - computed: 'getSavedPrintersAriaLabel_(savedPrinterCount_)', - }, + /**@private */ + nearbyPrintersAriaLabel_: { + type: String, + computed: 'getNearbyPrintersAriaLabel_(nearbyPrinterCount_)', + }, - /**@private */ - enterprisePrintersAriaLabel_: { - type: String, - computed: 'getEnterprisePrintersAriaLabel_(enterprisePrinterCount_)', - }, + /**@private */ + savedPrintersAriaLabel_: { + type: String, + computed: 'getSavedPrintersAriaLabel_(savedPrinterCount_)', + }, - /**@private */ - nearbyPrinterCount_: { - type: Number, - value: 0, - }, + /**@private */ + enterprisePrintersAriaLabel_: { + type: String, + computed: 'getEnterprisePrintersAriaLabel_(enterprisePrinterCount_)', + }, - /**@private */ - savedPrinterCount_: { - type: Number, - value: 0, - }, + /**@private */ + nearbyPrinterCount_: { + type: Number, + value: 0, + }, - /** @private */ - enterprisePrinterCount_: { - type: Number, - value: 0, - }, + /**@private */ + savedPrinterCount_: { + type: Number, + value: 0, + }, - /** - * Used by DeepLinkingBehavior to focus this page's deep links. - * @type {!Set<!chromeos.settings.mojom.Setting>} - */ - supportedSettingIds: { - type: Object, - value: () => new Set([ - chromeos.settings.mojom.Setting.kAddPrinter, - chromeos.settings.mojom.Setting.kSavedPrinters, - ]), - }, - }, + /** @private */ + enterprisePrinterCount_: { + type: Number, + value: 0, + }, - listeners: { - 'edit-cups-printer-details': 'onShowCupsEditPrinterDialog_', - 'show-cups-printer-toast': 'openResultToast_', - 'add-print-server-and-show-toast': 'addPrintServerAndShowResultToast_', - 'open-manufacturer-model-dialog-for-specified-printer': - 'openManufacturerModelDialogForSpecifiedPrinter_', - }, - - /** @private {?chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */ - networkConfig_: null, - - /** @private {CupsPrintersEntryManager} */ - entryManager_: null, + /** + * Used by DeepLinkingBehavior to focus this page's deep links. + * @type {!Set<!chromeos.settings.mojom.Setting>} + */ + supportedSettingIds: { + type: Object, + value: () => new Set([ + chromeos.settings.mojom.Setting.kAddPrinter, + chromeos.settings.mojom.Setting.kSavedPrinters, + ]), + }, + }; + } /** @override */ - created() { + constructor() { + super(); + + /** @private {!chromeos.networkConfig.mojom.CrosNetworkConfigRemote} */ this.networkConfig_ = MojoInterfaceProviderImpl.getInstance().getMojoServiceRemote(); + + + /** @private {!CupsPrintersEntryManager} */ this.entryManager_ = CupsPrintersEntryManager.getInstance(); - }, + + /** @private */ + this.addPrintServerResultText_ = ''; + } /** @override */ - attached() { + connectedCallback() { + super.connectedCallback(); + this.networkConfig_ .getNetworkStateList({ filter: chromeos.networkConfig.mojom.FilterType.kActive, @@ -204,12 +217,36 @@ .then((responseParams) => { this.onActiveNetworksChanged(responseParams.result); }); - }, + } /** @override */ ready() { + super.ready(); + this.updateCupsPrintersList_(); - }, + + this.addEventListener( + 'edit-cups-printer-details', this.onShowCupsEditPrinterDialog_); + this.addEventListener('show-cups-printer-toast', (event) => { + this.openResultToast_( + /** + * @type {!CustomEvent<!{ + * resultCode: PrinterSetupResult, + * printerName: string + * }>} + */ + (event)); + }); + this.addEventListener('add-print-server-and-show-toast', (event) => { + this.addPrintServerAndShowResultToast_( + /** @type {!CustomEvent<!{printers: !CupsPrintersList}>} */ (event)); + }); + this.addEventListener( + 'open-manufacturer-model-dialog-for-specified-printer', (event) => { + this.openManufacturerModelDialogForSpecifiedPrinter_( + /** @type {!CustomEvent<{item: !CupsPrinterInfo}>} */ (event)); + }); + } /** * Overridden from DeepLinkingBehavior. @@ -224,7 +261,7 @@ } afterNextRender(this, () => { - const savedPrinters = this.$$('#savedPrinters'); + const savedPrinters = this.shadowRoot.querySelector('#savedPrinters'); const printerEntry = savedPrinters && savedPrinters.$$('settings-cups-printers-entry'); const deepLinkElement = printerEntry && printerEntry.$$('#moreActions'); @@ -236,7 +273,7 @@ }); // Stop deep link attempt since we completed it manually. return false; - }, + } /** * RouteObserverBehavior @@ -262,7 +299,7 @@ this.onEnterprisePrintersChanged_.bind(this)); this.updateCupsPrintersList_(); this.attemptDeepLink(); - }, + } /** * CrosNetworkConfigObserver impl @@ -271,14 +308,14 @@ * @private */ onActiveNetworksChanged(networks) { - this.canAddPrinter = networks.some(function(network) { + this.canAddPrinter = networks.some((network) => { // Note: Check for kOnline rather than using // OncMojo.connectionStateIsConnected() since the latter could return true // for networks without connectivity (e.g., captive portals). return network.connectionState === chromeos.networkConfig.mojom.ConnectionStateType.kOnline; }); - }, + } /** * @param {!CustomEvent<!{ @@ -307,7 +344,7 @@ } this.$.errorToast.show(); - }, + } /** * @param {!CustomEvent<!{ @@ -315,7 +352,7 @@ * }>} event * @private */ - addPrintServerAndShowResultToast_: function(event) { + addPrintServerAndShowResultToast_(event) { this.entryManager_.addPrintServerPrinters(event.detail.printers); const length = event.detail.printers.printerList.length; if (length === 0) { @@ -329,7 +366,7 @@ loadTimeData.getStringF('printServerFoundManyPrinters', length); } this.$.printServerErrorToast.show(); - }, + } /** * @param {!CustomEvent<{item: !CupsPrinterInfo}>} e @@ -339,7 +376,7 @@ const item = e.detail.item; this.$.addPrinterDialog.openManufacturerModelDialogForSpecifiedPrinter( item); - }, + } /** @private */ updateCupsPrintersList_() { @@ -349,7 +386,7 @@ CupsPrintersBrowserProxyImpl.getInstance() .getCupsEnterprisePrintersList() .then(this.onEnterprisePrintersChanged_.bind(this)); - }, + } /** * @param {!CupsPrintersList} cupsPrintersList @@ -363,7 +400,7 @@ // Used to delay rendering nearby and add printer sections to prevent // "Add Printer" flicker when clicking "Printers" in settings page. this.attemptedLoadingPrinters_ = true; - }, + } /** * @param {!CupsPrintersList} cupsPrintersList @@ -374,27 +411,28 @@ printer => /** @type {!PrinterListEntry} */ ( {printerInfo: printer, printerType: PrinterType.ENTERPRISE})); this.entryManager_.setEnterprisePrintersList(this.enterprisePrinters_); - }, + } /** @private */ onAddPrinterTap_() { this.$.addPrinterDialog.open(); - }, + } /** @private */ onAddPrinterDialogClose_() { - focusWithoutInk(assert(this.$$('#addManualPrinterIcon'))); - }, + focusWithoutInk( + assert(this.shadowRoot.querySelector('#addManualPrinterIcon'))); + } /** @private */ onShowCupsEditPrinterDialog_() { this.showCupsEditPrinterDialog_ = true; - }, + } /** @private */ onEditPrinterDialogClose_() { this.showCupsEditPrinterDialog_ = false; - }, + } /** * @param {string} searchTerm @@ -409,7 +447,7 @@ return !this.printers.some(printer => { return printer.printerName.toLowerCase().includes(searchTerm); }); - }, + } /** * @param {boolean} connectedToNetwork Whether the device is connected to @@ -421,7 +459,7 @@ */ addPrinterButtonActive_(connectedToNetwork, userPrintersAllowed) { return connectedToNetwork && userPrintersAllowed; - }, + } /** * @return {boolean} Whether |savedPrinters_| is empty. @@ -429,7 +467,7 @@ */ doesAccountHaveSavedPrinters_() { return !!this.savedPrinters_.length; - }, + } /** * @return {boolean} Whether |enterprisePrinters_| is empty. @@ -437,7 +475,7 @@ */ doesAccountHaveEnterprisePrinters_() { return !!this.enterprisePrinters_.length; - }, + } /** @private */ getSavedPrintersAriaLabel_() { @@ -450,7 +488,7 @@ printerLabel = 'savedPrintersCountMany'; } return loadTimeData.getStringF(printerLabel, this.savedPrinterCount_); - }, + } /** @private */ getNearbyPrintersAriaLabel_() { @@ -463,7 +501,7 @@ printerLabel = 'nearbyPrintersCountMany'; } return loadTimeData.getStringF(printerLabel, this.nearbyPrinterCount_); - }, + } /** @private */ getEnterprisePrintersAriaLabel_() { @@ -476,5 +514,8 @@ printerLabel = 'enterprisePrintersCountMany'; } return loadTimeData.getStringF(printerLabel, this.enterprisePrinterCount_); - }, -}); + } +} + +customElements.define( + SettingsCupsPrintersElement.is, SettingsCupsPrintersElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_browser_proxy.js index c559794..b45552d 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_browser_proxy.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_browser_proxy.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 {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js'; - /** * @fileoverview A helper object used from the "CUPS printing" section to * interact with the browser. Used only on Chrome OS. */ +import {sendWithPromise} from 'chrome://resources/js/cr.m.js'; + /** * @typedef {{ * isManaged: boolean, @@ -227,10 +227,23 @@ openScanningApp() {} } +/** @type {?CupsPrintersBrowserProxy} */ +let instance = null; + /** * @implements {CupsPrintersBrowserProxy} */ export class CupsPrintersBrowserProxyImpl { + /** @return {!CupsPrintersBrowserProxy} */ + static getInstance() { + return instance || (instance = new CupsPrintersBrowserProxyImpl()); + } + + /** @param {!CupsPrintersBrowserProxy} obj */ + static setInstanceForTesting(obj) { + instance = obj; + } + /** @override */ getCupsSavedPrintersList() { return sendWithPromise('getCupsSavedPrintersList'); @@ -326,5 +339,3 @@ chrome.send('openScanningApp'); } } - -addSingletonGetter(CupsPrintersBrowserProxyImpl);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js index 9974f83..78bc3f9 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry.js
@@ -6,76 +6,110 @@ * @fileoverview 'settings-cups-printers-entry' is a component that holds a * printer. */ -import '//resources/cr_elements/cr_button/cr_button.m.js'; -import '//resources/polymer/v3_0/iron-icon/iron-icon.js'; +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import '../../settings_shared_css.js'; -import {FocusRowBehavior} from '//resources/js/cr/ui/focus_row_behavior.m.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {FocusRowBehavior, FocusRowBehaviorInterface} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; import {PrinterListEntry, PrinterType} from './cups_printer_types.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; -Polymer({ - _template: html`{__html_template__}`, - is: 'settings-cups-printers-entry', +/** + * @constructor + * @extends {PolymerElement} + * @implements {FocusRowBehaviorInterface} + */ +const SettingsCupsPrintersEntryElementBase = + mixinBehaviors([FocusRowBehavior], PolymerElement); - behaviors: [ - FocusRowBehavior, - ], - properties: { - /** @type {!PrinterListEntry} */ - printerEntry: Object, +/** @polymer */ +class SettingsCupsPrintersEntryElement extends + SettingsCupsPrintersEntryElementBase { + static get is() { + return 'settings-cups-printers-entry'; + } - /** - * TODO(jimmyxgong): Determine how subtext should be set and what - * information it should have, including necessary ARIA labeling - * The additional information subtext for a printer. - * @type {string} - */ - subtext: {type: String, value: ''}, + static get template() { + return html`{__html_template__}`; + } - /** - * This value is set to true if the printer is in saving mode. - */ - savingPrinter: Boolean, + static get properties() { + return { + /** @type {!PrinterListEntry} */ + printerEntry: Object, - /** - * This value is set to true if UserPrintersAllowed policy is enabled. - */ - userPrintersAllowed: { - type: Boolean, - value: false, - } - }, + /** + * TODO(jimmyxgong): Determine how subtext should be set and what + * information it should have, including necessary ARIA labeling + * The additional information subtext for a printer. + * @type {string} + */ + subtext: {type: String, value: ''}, + + /** + * This value is set to true if the printer is in saving mode. + */ + savingPrinter: Boolean, + + /** + * This value is set to true if UserPrintersAllowed policy is enabled. + */ + userPrintersAllowed: { + type: Boolean, + value: false, + } + }; + } /** * Fires a custom event when the menu button is clicked. Sends the details of * the printer and where the menu should appear. */ onOpenActionMenuTap_(e) { - this.fire('open-action-menu', { - target: e.target, - item: this.printerEntry, + const openActionMenuEvent = new CustomEvent('open-action-menu', { + bubbles: true, + composed: true, + detail: { + target: e.target, + item: this.printerEntry, + }, }); - }, + this.dispatchEvent(openActionMenuEvent); + } /** @private */ onAddDiscoveredPrinterTap_(e) { - this.fire('query-discovered-printer', {item: this.printerEntry}); - }, + const queryDiscoveredPrinterEvent = + new CustomEvent('query-discovered-printer', { + bubbles: true, + composed: true, + detail: {item: this.printerEntry}, + }); + this.dispatchEvent(queryDiscoveredPrinterEvent); + } /** @private */ onAddAutomaticPrinterTap_() { - this.fire('add-automatic-printer', {item: this.printerEntry}); - }, + const addAutomaticPrinterEvent = new CustomEvent('add-automatic-printer', { + bubbles: true, + composed: true, + detail: {item: this.printerEntry}, + }); + this.dispatchEvent(addAutomaticPrinterEvent); + } /** @private */ - onAddServerPrinterTap_: function() { - this.fire('add-print-server-printer', {item: this.printerEntry}); - }, + onAddServerPrinterTap_() { + const addPrintServer = new CustomEvent('add-print-server-printer', { + bubbles: true, + composed: true, + detail: {item: this.printerEntry}, + }); + this.dispatchEvent(addPrintServer); + } /** * @return {boolean} @@ -84,7 +118,7 @@ showActionsMenu_() { return this.printerEntry.printerType === PrinterType.SAVED || this.printerEntry.printerType === PrinterType.ENTERPRISE; - }, + } /** * @return {boolean} @@ -92,7 +126,7 @@ */ isDiscoveredPrinter_() { return this.printerEntry.printerType === PrinterType.DISCOVERED; - }, + } /** * @return {boolean} @@ -100,7 +134,7 @@ */ isAutomaticPrinter_() { return this.printerEntry.printerType === PrinterType.AUTOMATIC; - }, + } /** * @return {boolean} @@ -108,7 +142,7 @@ */ isPrintServerPrinter_() { return this.printerEntry.printerType === PrinterType.PRINTSERVER; - }, + } /** * @return {boolean} @@ -116,15 +150,18 @@ */ isConfigureDisabled_() { return !this.userPrintersAllowed || this.savingPrinter; - }, + } getSaveButtonAria_() { return loadTimeData.getStringF( 'savePrinterAria', this.printerEntry.printerInfo.printerName); - }, + } getSetupButtonAria_() { return loadTimeData.getStringF( 'setupPrinterAria', this.printerEntry.printerInfo.printerName); - }, -}); + } +} + +customElements.define( + SettingsCupsPrintersEntryElement.is, SettingsCupsPrintersEntryElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js index 6b7d484..081bff9 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.js
@@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assert} from 'chrome://resources/js/assert.m.js'; - -import {findDifference} from './cups_printer_dialog_util.js'; -import {PrinterListEntry} from './cups_printer_types.js'; -import {CupsPrintersEntryManager} from './cups_printers_entry_manager.js'; - /** * @fileoverview Polymer behavior for observing CupsPrintersEntryManager events. * Use this behavior if you want to receive a dynamically updated list of both * saved and nearby printers. */ +import {assert} from 'chrome://resources/js/assert.m.js'; + +import {findDifference} from './cups_printer_dialog_util.js'; +import {PrinterListEntry} from './cups_printer_types.js'; +import {CupsPrintersEntryManager} from './cups_printers_entry_manager.js'; + /** @polymerBehavior */ export const CupsPrintersEntryListBehavior = { properties: { @@ -127,4 +127,24 @@ /** @param{!Array<!PrinterListEntry>} removedPrinters */ onSavedPrintersRemoved(removedPrinters) {}, -}; \ No newline at end of file +}; + +/** @interface */ +export class CupsPrintersEntryListBehaviorInterface { + constructor() { + /** @type {!Array<!PrinterListEntry>} */ + this.savedPrinters; + + /** @type {!Array<!PrinterListEntry>} */ + this.nearbyPrinters; + + /** @type {!Array<!PrinterListEntry>} */ + this.enterprisePrinters; + } + + /** @param {!Array<!PrinterListEntry>} addedPrinters */ + onSavedPrintersAdded(addedPrinters) {} + + /** @param {!Array<!PrinterListEntry>} removedPrinters */ + onSavedPrintersRemoved(removedPrinters) {} +}
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_manager.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_manager.js index bef4ace..860114e 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_manager.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_manager.js
@@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {addSingletonGetter, addWebUIListener, removeWebUIListener} from 'chrome://resources/js/cr.m.js'; -import {WebUIListener} from 'chrome://resources/js/cr.m.js'; +import {addWebUIListener, removeWebUIListener, WebUIListener} from 'chrome://resources/js/cr.m.js'; import {findDifference} from './cups_printer_dialog_util.js'; import {PrinterListEntry, PrinterType} from './cups_printer_types.js'; @@ -28,12 +27,25 @@ */ let PrintersListCallback; +/** @type {?CupsPrintersEntryManager} */ +let instance = null; + /** * Class for managing printer entries. Holds Saved, Nearby, Enterprise, Print * Server printers and notifies observers of any applicable changes to either * printer lists. */ export class CupsPrintersEntryManager { + /** @return {!CupsPrintersEntryManager} */ + static getInstance() { + return instance || (instance = new CupsPrintersEntryManager()); + } + + /** @param {!CupsPrintersEntryManager} obj */ + static setInstanceForTesting(obj) { + instance = obj; + } + constructor() { /** @private {!Array<!PrinterListEntry>} */ this.savedPrinters_ = []; @@ -249,5 +261,3 @@ listener => listener(this.enterprisePrinters_)); } } - -addSingletonGetter(CupsPrintersEntryManager);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js index 30d5fc7..ed78bf2 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_saved_printers.js
@@ -2,24 +2,28 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; -import '//resources/cr_elements/icons.m.js'; -import '//resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; -import '//resources/polymer/v3_0/iron-list/iron-list.js'; +/** + * @fileoverview 'settings-cups-saved-printers' is a list container for Saved + * Printers. + */ + +import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; +import 'chrome://resources/cr_elements/icons.m.js'; +import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; +import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; import './cups_printers_entry.js'; import '../../settings_shared_css.js'; -import {ListPropertyUpdateBehavior} from '//resources/js/list_property_update_behavior.m.js'; -import {WebUIListenerBehavior} from '//resources/js/web_ui_listener_behavior.m.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {ListPropertyUpdateBehavior, ListPropertyUpdateBehaviorInterface} from 'chrome://resources/js/list_property_update_behavior.m.js'; +import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {recordSettingChange} from '../metrics_recorder.js'; -import {getBaseName, getErrorText, getPrintServerErrorText, isNameAndAddressValid, isNetworkProtocol, isPPDInfoValid, matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; -import {PrinterListEntry, PrinterType} from './cups_printer_types.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; -import {CupsPrintersEntryListBehavior} from './cups_printers_entry_list_behavior.js'; - +import {matchesSearchTerm, sortPrinters} from './cups_printer_dialog_util.js'; +import {PrinterListEntry} from './cups_printer_types.js'; +import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl} from './cups_printers_browser_proxy.js'; +import {CupsPrintersEntryListBehavior, CupsPrintersEntryListBehaviorInterface} from './cups_printers_entry_list_behavior.js'; // If the Show more button is visible, the minimum number of printers we show // is 3. @@ -38,118 +42,144 @@ } /** - * @fileoverview 'settings-cups-saved-printers' is a list container for Saved - * Printers. + * @constructor + * @extends {PolymerElement} + * @implements {CupsPrintersEntryListBehaviorInterface} + * @implements {ListPropertyUpdateBehaviorInterface} + * @implements {WebUIListenerBehaviorInterface} */ -Polymer({ - _template: html`{__html_template__}`, - is: 'settings-cups-saved-printers', +const SettingsCupsSavedPrintersElementBase = mixinBehaviors( + [ + CupsPrintersEntryListBehavior, ListPropertyUpdateBehavior, + WebUIListenerBehavior + ], + PolymerElement); - // ListPropertyUpdateBehavior is used in CupsPrintersEntryListBehavior. - behaviors: [ - CupsPrintersEntryListBehavior, - ListPropertyUpdateBehavior, - WebUIListenerBehavior, - ], +/** @polymer */ +class SettingsCupsSavedPrintersElement extends + SettingsCupsSavedPrintersElementBase { + static get is() { + return 'settings-cups-saved-printers'; + } - properties: { - /** - * Search term for filtering |savedPrinters|. - * @type {string} - */ - searchTerm: { - type: String, - value: '', - }, + static get template() { + return html`{__html_template__}`; + } - /** @type {?CupsPrinterInfo} */ - activePrinter: { - type: Object, - notify: true, - }, + static get properties() { + return { + /** + * Search term for filtering |savedPrinters|. + * @type {string} + */ + searchTerm: { + type: String, + value: '', + }, - printersCount: { - type: Number, - computed: 'getFilteredPrintersLength_(filteredPrinters_.*)', - notify: true, - }, + /** @type {?CupsPrinterInfo} */ + activePrinter: { + type: Object, + notify: true, + }, - /** - * @type {number} - * @private - */ - activePrinterListEntryIndex_: { - type: Number, - value: -1, - }, + printersCount: { + type: Number, + computed: 'getFilteredPrintersLength_(filteredPrinters_.*)', + notify: true, + }, - /** - * List of printers filtered through a search term. - * @type {!Array<!PrinterListEntry>} - * @private - */ - filteredPrinters_: { - type: Array, - value: () => [], - }, + /** + * @type {number} + * @private + */ + activePrinterListEntryIndex_: { + type: Number, + value: -1, + }, - /** - * Array of new PrinterListEntry's that were added during this session. - * @type {!Array<!PrinterListEntry>} - * @private - */ - newPrinters_: { - type: Array, - value: () => [], - }, + /** + * List of printers filtered through a search term. + * @type {!Array<!PrinterListEntry>} + * @private + */ + filteredPrinters_: { + type: Array, + value: () => [], + }, - /** - * Keeps track of whether the user has tapped the Show more button. A search - * term will expand the collapsed list, so we need to keep track of whether - * the list expanded because of a search term or because the user tapped on - * the Show more button. - * @private - */ - hasShowMoreBeenTapped_: { - type: Boolean, - value: false, - }, + /** + * Array of new PrinterListEntry's that were added during this session. + * @type {!Array<!PrinterListEntry>} + * @private + */ + newPrinters_: { + type: Array, + value: () => [], + }, - /** - * Used by FocusRowBehavior to track the last focused element on a row. - * @private - */ - lastFocused_: Object, + /** + * Keeps track of whether the user has tapped the Show more button. A + * search term will expand the collapsed list, so we need to keep track of + * whether the list expanded because of a search term or because the user + * tapped on the Show more button. + * @private + */ + hasShowMoreBeenTapped_: { + type: Boolean, + value: false, + }, - /** - * Used by FocusRowBehavior to track if the list has been blurred. - * @private - */ - listBlurred_: Boolean, - }, + /** + * Used by FocusRowBehavior to track the last focused element on a row. + * @private + */ + lastFocused_: Object, - listeners: { - 'open-action-menu': 'onOpenActionMenu_', - }, + /** + * Used by FocusRowBehavior to track if the list has been blurred. + * @private + */ + listBlurred_: Boolean, + }; + } - observers: - ['onSearchOrPrintersChanged_(savedPrinters.*, searchTerm,' + - 'hasShowMoreBeenTapped_, newPrinters_.*)'], - - /** @private {CupsPrintersBrowserProxy} */ - browserProxy_: null, - - /** - * The number of printers we display if hidden printers are allowed. - * kMinVisiblePrinters is the default value and we never show fewer printers - * if the Show more button is visible. - */ - visiblePrinterCounter_: kMinVisiblePrinters, + static get observers() { + return [ + 'onSearchOrPrintersChanged_(savedPrinters.*, searchTerm,' + + 'hasShowMoreBeenTapped_, newPrinters_.*)' + ]; + } /** @override */ - created() { + constructor() { + super(); + + /** @private {CupsPrintersBrowserProxy} */ this.browserProxy_ = CupsPrintersBrowserProxyImpl.getInstance(); - }, + + /** + * The number of printers we display if hidden printers are allowed. + * kMinVisiblePrinters is the default value and we never show fewer printers + * if the Show more button is visible. + * @private + */ + this.visiblePrinterCounter_ = kMinVisiblePrinters; + } + + /** @override */ + ready() { + super.ready(); + + this.addEventListener('open-action-menu', (event) => { + this.onOpenActionMenu_( + /** + * @type {!CustomEvent<{target: !HTMLElement, item: + * !PrinterListEntry}>} + */ + (event)); + }); + } /** * Redoes the search whenever |searchTerm| or |savedPrinters| changes. @@ -165,7 +195,7 @@ this.updateList( 'filteredPrinters_', printer => printer.printerInfo.printerId, updatedPrinters); - }, + } /** * @param {!CustomEvent<{target: !HTMLElement, item: !PrinterListEntry}>} e @@ -181,15 +211,20 @@ .printerInfo; const target = /** @type {!HTMLElement} */ (e.detail.target); - this.$$('cr-action-menu').showAt(target); - }, + this.shadowRoot.querySelector('cr-action-menu').showAt(target); + } /** @private */ onEditTap_() { // Event is caught by 'settings-cups-printers'. - this.fire('edit-cups-printer-details'); + const editCupsPrinterDetailsEvent = + new CustomEvent('edit-cups-printer-details', { + bubbles: true, + composed: true, + }); + this.dispatchEvent(editCupsPrinterDetailsEvent); this.closeActionMenu_(); - }, + } /** @private */ onRemoveTap_() { @@ -197,14 +232,14 @@ this.activePrinter.printerId, this.activePrinter.printerName); recordSettingChange(); this.activePrinter = null; - this.activeListEntryIndex_ = -1; + this.activePrinterListEntryIndex_ = -1; this.closeActionMenu_(); - }, + } /** @private */ onShowMoreTap_() { this.hasShowMoreBeenTapped_ = true; - }, + } /** * Gets the printers to be shown in the UI. These printers are filtered @@ -232,12 +267,12 @@ (printer, idx) => idx < this.visiblePrinterCounter_); } return updatedPrinters; - }, + } /** @private */ closeActionMenu_() { - this.$$('cr-action-menu').close(); - }, + this.shadowRoot.querySelector('cr-action-menu').close(); + } /** * @return {boolean} Returns true if the no search message should be visible. @@ -245,7 +280,7 @@ */ showNoSearchResultsMessage_() { return !!this.searchTerm && !this.filteredPrinters_.length; - }, + } /** @param{!Array<!PrinterListEntry>} addedPrinters */ onSavedPrintersAdded(addedPrinters) { @@ -256,7 +291,7 @@ } this.set('newPrinters_', currArr); - }, + } /** @param{!Array<!PrinterListEntry>} removedPrinters */ onSavedPrintersRemoved(removedPrinters) { @@ -275,7 +310,7 @@ } this.set('newPrinters_', currArr); - }, + } /** * Keeps track of whether the Show more button should be visible which means @@ -303,7 +338,7 @@ } return true; - }, + } /** * Moves printers that are in |newPrinters_| to position |toIndex| of @@ -326,7 +361,7 @@ moveEntryInPrinters(printerArr, idx, toIndex); } } - }, + } /** * @private @@ -334,5 +369,8 @@ */ getFilteredPrintersLength_() { return this.filteredPrinters_.length; - }, -}); + } +} + +customElements.define( + SettingsCupsSavedPrintersElement.is, SettingsCupsSavedPrintersElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_settings_add_printer_dialog.js b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_settings_add_printer_dialog.js index 94ec809..5836c5588 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/cups_settings_add_printer_dialog.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/cups_settings_add_printer_dialog.js
@@ -14,6 +14,17 @@ * add a print server. */ +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_components/localized_link/localized_link.js'; +import './cups_add_print_server_dialog.js'; +import './cups_add_printer_manually_dialog.js'; +import './cups_add_printer_manufacturer_model_dialog.js'; +import './cups_printer_shared_css.js'; + +import {html, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {CupsPrinterInfo} from './cups_printers_browser_proxy.js'; + /** * Different dialogs in add printer flow. * @enum {string} @@ -51,68 +62,67 @@ }; } +/** @polymer */ +class SettingsCupsAddPrinterDialogElement extends PolymerElement { + static get is() { + return 'settings-cups-add-printer-dialog'; + } -import {afterNextRender, Polymer, html, flush, Templatizer, TemplateInstanceBase} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + static get template() { + return html`{__html_template__}`; + } -import '//resources/cr_elements/cr_input/cr_input.m.js'; -import '//resources/cr_components/localized_link/localized_link.js'; -import {loadTimeData} from '../../i18n_setup.js'; -import './cups_add_print_server_dialog.js'; -import './cups_add_printer_manually_dialog.js'; -import './cups_add_printer_manufacturer_model_dialog.js'; -import {sortPrinters, matchesSearchTerm, getBaseName, getErrorText, isNetworkProtocol, isNameAndAddressValid, isPPDInfoValid, getPrintServerErrorText} from './cups_printer_dialog_util.js'; -import './cups_printer_shared_css.js'; -import {CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrinterInfo, PrinterSetupResult, CupsPrintersList, PrinterPpdMakeModel, ManufacturersInfo, ModelsInfo, PrintServerResult, PrinterMakeModel} from './cups_printers_browser_proxy.js'; + static get properties() { + return { + /** @type {!CupsPrinterInfo} */ + newPrinter: { + type: Object, + }, -Polymer({ - _template: html`{__html_template__}`, - is: 'settings-cups-add-printer-dialog', + /** @private {string} */ + previousDialog_: String, - properties: { - /** @type {!CupsPrinterInfo} */ - newPrinter: { - type: Object, - }, + /** @private {string} */ + currentDialog_: String, - /** @private {string} */ - previousDialog_: String, + /** @private {boolean} */ + showManuallyAddDialog_: { + type: Boolean, + value: false, + }, - /** @private {string} */ - currentDialog_: String, + /** @private {boolean} */ + showManufacturerDialog_: { + type: Boolean, + value: false, + }, - /** @private {boolean} */ - showManuallyAddDialog_: { - type: Boolean, - value: false, - }, + /** @private {boolean} */ + showAddPrintServerDialog_: { + type: Boolean, + value: false, + }, + }; + } - /** @private {boolean} */ - showManufacturerDialog_: { - type: Boolean, - value: false, - }, + ready() { + super.ready(); - /** @private {boolean} */ - showAddPrintServerDialog_: { - type: Boolean, - value: false, - }, - }, - - listeners: { - 'open-manually-add-printer-dialog': 'openManuallyAddPrinterDialog_', - 'open-manufacturer-model-dialog': - 'openManufacturerModelDialogForCurrentPrinter_', - 'open-add-print-server-dialog': 'openPrintServerDialog_', - 'no-detected-printer': 'onNoDetectedPrinter_', - }, + this.addEventListener( + 'open-manually-add-printer-dialog', this.openManuallyAddPrinterDialog_); + this.addEventListener( + 'open-manufacturer-model-dialog', + this.openManufacturerModelDialogForCurrentPrinter_); + this.addEventListener( + 'open-add-print-server-dialog', this.openPrintServerDialog_); + } /** Opens the Add manual printer dialog. */ open() { this.resetData_(); this.switchDialog_( '', AddPrinterDialogs.MANUALLY, 'showManuallyAddDialog_'); - }, + } /** * Reset all the printer data in the Add printer flow. @@ -122,35 +132,35 @@ if (this.newPrinter) { this.newPrinter = getEmptyPrinter_(); } - }, + } /** @private */ openManuallyAddPrinterDialog_() { this.switchDialog_( this.currentDialog_, AddPrinterDialogs.MANUALLY, 'showManuallyAddDialog_'); - }, + } /** @private */ openManufacturerModelDialogForCurrentPrinter_() { this.switchDialog_( this.currentDialog_, AddPrinterDialogs.MANUFACTURER, 'showManufacturerDialog_'); - }, + } /** @param {!CupsPrinterInfo} printer */ openManufacturerModelDialogForSpecifiedPrinter(printer) { this.newPrinter = printer; this.switchDialog_( '', AddPrinterDialogs.MANUFACTURER, 'showManufacturerDialog_'); - }, + } /** @private */ - openPrintServerDialog_: function() { + openPrintServerDialog_() { this.switchDialog_( this.currentDialog_, AddPrinterDialogs.PRINTSERVER, 'showAddPrintServerDialog_'); - }, + } /** * Switch dialog from |fromDialog| to |toDialog|. @@ -165,11 +175,15 @@ this.currentDialog_ = toDialog; this.set(domIfBooleanName, true); - this.async(function() { - const dialog = this.$$(toDialog); + microTask.run(() => { + const dialog = this.shadowRoot.querySelector(toDialog); dialog.addEventListener('close', () => { this.set(domIfBooleanName, false); }); }); - }, -}); + } +} + +customElements.define( + SettingsCupsAddPrinterDialogElement.is, + SettingsCupsAddPrinterDialogElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js b/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js index 3ed8b84..143e0f00 100644 --- a/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js +++ b/chrome/browser/resources/settings/chromeos/os_printing_page/os_printing_page.js
@@ -7,67 +7,88 @@ import '../../settings_shared_css.js'; import './cups_printers.js'; -import {assert, assertNotReached} from '//resources/js/assert.m.js'; -import {loadTimeData} from '//resources/js/load_time_data.m.js'; -import {afterNextRender, flush, html, Polymer, TemplateInstanceBase, Templatizer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Route, Router} from '../../router.js'; -import {DeepLinkingBehavior} from '../deep_linking_behavior.js'; +import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.js'; import {recordSettingChange} from '../metrics_recorder.js'; import {routes} from '../os_route.js'; -import {RouteObserverBehavior} from '../route_observer_behavior.js'; +import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; -import {CupsPrinterInfo, CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl, CupsPrintersList, ManufacturersInfo, ModelsInfo, PrinterMakeModel, PrinterPpdMakeModel, PrinterSetupResult, PrintServerResult} from './cups_printers_browser_proxy.js'; +import {CupsPrintersBrowserProxy, CupsPrintersBrowserProxyImpl} from './cups_printers_browser_proxy.js'; -Polymer({ - _template: html`{__html_template__}`, - is: 'os-settings-printing-page', +/** + * @constructor + * @extends {PolymerElement} + * @implements {DeepLinkingBehaviorInterface} + * @implements {RouteObserverBehaviorInterface} + */ +const OsSettingsPrintingPageElementBase = mixinBehaviors( + [ + DeepLinkingBehavior, + RouteObserverBehavior, + ], + PolymerElement); - behaviors: [ - DeepLinkingBehavior, - RouteObserverBehavior, - ], +/** @polymer */ +class OsSettingsPrintingPageElement extends OsSettingsPrintingPageElementBase { + static get is() { + return 'os-settings-printing-page'; + } - properties: { - /** Preferences state. */ - prefs: { - type: Object, - notify: true, - }, + static get template() { + return html`{__html_template__}`; + } - /** Printer search string. */ - searchTerm: { - type: String, - }, - - /** @private {!Map<string, string>} */ - focusConfig_: { - type: Object, - value() { - const map = new Map(); - if (routes.CUPS_PRINTERS) { - map.set(routes.CUPS_PRINTERS.path, '#cupsPrinters'); - } - return map; + static get properties() { + return { + /** Preferences state. */ + prefs: { + type: Object, + notify: true, }, - }, - /** - * Used by DeepLinkingBehavior to focus this page's deep links. - * @type {!Set<!chromeos.settings.mojom.Setting>} - */ - supportedSettingIds: { - type: Object, - value: () => new Set([ - chromeos.settings.mojom.Setting.kPrintJobs, - chromeos.settings.mojom.Setting.kScanningApp - ]), - }, - }, + /** Printer search string. */ + searchTerm: { + type: String, + }, + + /** @private {!Map<string, string>} */ + focusConfig_: { + type: Object, + value() { + const map = new Map(); + if (routes.CUPS_PRINTERS) { + map.set(routes.CUPS_PRINTERS.path, '#cupsPrinters'); + } + return map; + }, + }, + + /** + * Used by DeepLinkingBehavior to focus this page's deep links. + * @type {!Set<!chromeos.settings.mojom.Setting>} + */ + supportedSettingIds: { + type: Object, + value: () => new Set([ + chromeos.settings.mojom.Setting.kPrintJobs, + chromeos.settings.mojom.Setting.kScanningApp + ]), + }, + }; + } + + constructor() { + super(); + + /** @private {!CupsPrintersBrowserProxy} */ + this.browserProxy_ = CupsPrintersBrowserProxyImpl.getInstance(); + } /** * @param {!Route} route - * @param {!Route} oldRoute + * @param {!Route=} oldRoute */ currentRouteChanged(route, oldRoute) { // Does not apply to this page. @@ -76,21 +97,24 @@ } this.attemptDeepLink(); - }, + } /** @private */ onTapCupsPrinters_() { Router.getInstance().navigateTo(routes.CUPS_PRINTERS); - }, + } /** @private */ onOpenPrintManagement_() { - CupsPrintersBrowserProxyImpl.getInstance().openPrintManagementApp(); - }, + this.browserProxy_.openPrintManagementApp(); + } /** @private */ onOpenScanningApp_() { - CupsPrintersBrowserProxyImpl.getInstance().openScanningApp(); + this.browserProxy_.openScanningApp(); recordSettingChange(chromeos.settings.mojom.Setting.kScanningApp); } -}); +} + +customElements.define( + OsSettingsPrintingPageElement.is, OsSettingsPrintingPageElement);
diff --git a/chrome/browser/resources/settings/controls/settings_textarea.html b/chrome/browser/resources/settings/controls/settings_textarea.html index 8e3e477..879eb5f 100644 --- a/chrome/browser/resources/settings/controls/settings_textarea.html +++ b/chrome/browser/resources/settings/controls/settings_textarea.html
@@ -38,6 +38,7 @@ display: block; visibility: hidden; white-space: pre-wrap; + word-wrap: break-word; } :host([autogrow]) #mirror,
diff --git a/chrome/browser/resources/settings/languages_page/languages_settings_metrics_proxy.ts b/chrome/browser/resources/settings/languages_page/languages_settings_metrics_proxy.ts index 41149e56..f7b0281 100644 --- a/chrome/browser/resources/settings/languages_page/languages_settings_metrics_proxy.ts +++ b/chrome/browser/resources/settings/languages_page/languages_settings_metrics_proxy.ts
@@ -22,6 +22,7 @@ DISABLE_TRANSLATE_FOR_SINGLE_LANGUAGE = 6, ENABLE_TRANSLATE_FOR_SINGLE_LANGUAGE = 7, LANGUAGE_LIST_REORDERED = 8, + CHANGE_CHROME_LANGUAGE = 9, } /**
diff --git a/chrome/browser/resources/settings/languages_page/languages_subpage.ts b/chrome/browser/resources/settings/languages_page/languages_subpage.ts index 8500880..0534e9e 100644 --- a/chrome/browser/resources/settings/languages_page/languages_subpage.ts +++ b/chrome/browser/resources/settings/languages_page/languages_subpage.ts
@@ -415,6 +415,8 @@ this.detailLanguage_!.language.code); this.languageHelper.moveLanguageToFront( this.detailLanguage_!.language.code); + LanguageSettingsMetricsProxyImpl.getInstance().recordSettingsMetric( + LanguageSettingsActionType.CHANGE_CHROME_LANGUAGE); this.closeMenuSoon_(); }
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.cc deleted file mode 100644 index bdffb4c..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.cc +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h" - -#include "base/bind.h" -#include "build/build_config.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/renderer_context_menu/render_view_context_menu.h" -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h" -#include "chrome/browser/sharing/sharing_constants.h" -#include "chrome/browser/sharing/sharing_metrics.h" -#include "chrome/grit/generated_resources.h" -#include "components/sync_device_info/device_info.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/models/image_model.h" -#include "ui/color/color_id.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/paint_vector_icon.h" - -SharedClipboardContextMenuObserver::SubMenuDelegate::SubMenuDelegate( - SharedClipboardContextMenuObserver* parent) - : parent_(parent) {} - -SharedClipboardContextMenuObserver::SubMenuDelegate::~SubMenuDelegate() = - default; - -bool SharedClipboardContextMenuObserver::SubMenuDelegate::IsCommandIdEnabled( - int command_id) const { - // All supported commands are enabled in sub menu. - return true; -} - -void SharedClipboardContextMenuObserver::SubMenuDelegate::ExecuteCommand( - int command_id, - int event_flags) { - if (command_id < kSubMenuFirstDeviceCommandId || - command_id > kSubMenuLastDeviceCommandId) - return; - int device_index = command_id - kSubMenuFirstDeviceCommandId; - parent_->SendSharedClipboardMessage(device_index); -} - -SharedClipboardContextMenuObserver::SharedClipboardContextMenuObserver( - RenderViewContextMenuProxy* proxy) - : proxy_(proxy), - controller_(SharedClipboardUiController::GetOrCreateFromWebContents( - proxy_->GetWebContents())) {} - -SharedClipboardContextMenuObserver::~SharedClipboardContextMenuObserver() = - default; - -void SharedClipboardContextMenuObserver::InitMenu( - const content::ContextMenuParams& params) { - text_ = params.selection_text; - devices_ = controller_->GetDevices(); - LogSharingDevicesToShow(controller_->GetFeatureMetricsPrefix(), - nullptr /* No suffix */, devices_.size()); - - if (devices_.empty()) - return; - - if (devices_.size() == 1) { -#if BUILDFLAG(IS_MAC) - proxy_->AddMenuItem( - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE, - l10n_util::GetStringFUTF16( - IDS_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE, - base::UTF8ToUTF16(devices_[0]->client_name()))); -#else - proxy_->AddMenuItemWithIcon( - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE, - l10n_util::GetStringFUTF16( - IDS_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE, - base::UTF8ToUTF16(devices_[0]->client_name())), - ui::ImageModel::FromVectorIcon(controller_->GetVectorIcon(), - ui::kColorMenuIcon, - ui::SimpleMenuModel::kDefaultIconSize)); -#endif - } else { - BuildSubMenu(); -#if BUILDFLAG(IS_MAC) - proxy_->AddSubMenu( - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES, - l10n_util::GetStringUTF16( - IDS_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES), - sub_menu_model_.get()); -#else - proxy_->AddSubMenuWithStringIdAndIcon( - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES, - IDS_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES, - sub_menu_model_.get(), - ui::ImageModel::FromVectorIcon(controller_->GetVectorIcon(), - ui::kColorMenuIcon, - ui::SimpleMenuModel::kDefaultIconSize)); -#endif - } -} - -void SharedClipboardContextMenuObserver::BuildSubMenu() { - sub_menu_model_ = std::make_unique<ui::SimpleMenuModel>(&sub_menu_delegate_); - - int command_id = kSubMenuFirstDeviceCommandId; - for (const auto& device : devices_) { - if (command_id > kSubMenuLastDeviceCommandId) - break; - sub_menu_model_->AddItem(command_id++, - base::UTF8ToUTF16(device->client_name())); - } -} - -bool SharedClipboardContextMenuObserver::IsCommandIdSupported(int command_id) { - size_t device_count = devices_.size(); - if (device_count == 0) - return false; - - if (device_count == 1) { - return command_id == - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE; - } else { - return command_id == - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES; - } -} - -bool SharedClipboardContextMenuObserver::IsCommandIdEnabled(int command_id) { - // All supported commands are enabled. - return true; -} - -void SharedClipboardContextMenuObserver::ExecuteCommand(int command_id) { - if (command_id == - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE) { - DCHECK_EQ(1u, devices_.size()); - SendSharedClipboardMessage(0); - } -} - -void SharedClipboardContextMenuObserver::SendSharedClipboardMessage( - int chosen_device_index) { - if (static_cast<size_t>(chosen_device_index) >= devices_.size()) - return; - LogSharingSelectedIndex(controller_->GetFeatureMetricsPrefix(), - nullptr /* No suffix */, chosen_device_index); - - controller_->OnDeviceSelected(text_, *devices_[chosen_device_index]); - LogSharedClipboardSelectedTextSize(text_.size()); -}
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h b/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h deleted file mode 100644 index ce9ceee..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_CONTEXT_MENU_OBSERVER_H_ -#define CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_CONTEXT_MENU_OBSERVER_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/gtest_prod_util.h" -#include "base/memory/raw_ptr.h" -#include "components/renderer_context_menu/render_view_context_menu_observer.h" -#include "ui/base/models/simple_menu_model.h" - -namespace syncer { -class DeviceInfo; -} // namespace syncer - -class RenderViewContextMenuProxy; -class SharedClipboardUiController; - -class SharedClipboardContextMenuObserver - : public RenderViewContextMenuObserver { - public: - class SubMenuDelegate : public ui::SimpleMenuModel::Delegate { - public: - explicit SubMenuDelegate(SharedClipboardContextMenuObserver* parent); - - SubMenuDelegate(const SubMenuDelegate&) = delete; - SubMenuDelegate& operator=(const SubMenuDelegate&) = delete; - - ~SubMenuDelegate() override; - - bool IsCommandIdEnabled(int command_id) const override; - void ExecuteCommand(int command_id, int event_flags) override; - - private: - const raw_ptr<SharedClipboardContextMenuObserver> parent_; - }; - - explicit SharedClipboardContextMenuObserver( - RenderViewContextMenuProxy* proxy); - - SharedClipboardContextMenuObserver( - const SharedClipboardContextMenuObserver&) = delete; - SharedClipboardContextMenuObserver& operator=( - const SharedClipboardContextMenuObserver&) = delete; - - ~SharedClipboardContextMenuObserver() override; - - // RenderViewContextMenuObserver implementation. - void InitMenu(const content::ContextMenuParams& params) override; - bool IsCommandIdSupported(int command_id) override; - bool IsCommandIdEnabled(int command_id) override; - void ExecuteCommand(int command_id) override; - - private: - FRIEND_TEST_ALL_PREFIXES(SharedClipboardContextMenuObserverTest, - SingleDevice_ShowMenu); - FRIEND_TEST_ALL_PREFIXES(SharedClipboardContextMenuObserverTest, - MultipleDevices_ShowMenu); - FRIEND_TEST_ALL_PREFIXES(SharedClipboardContextMenuObserverTest, - MultipleDevices_MoreThanMax_ShowMenu); - - void BuildSubMenu(); - - void SendSharedClipboardMessage(int chosen_device_index); - - raw_ptr<RenderViewContextMenuProxy> proxy_ = nullptr; - - raw_ptr<SharedClipboardUiController> controller_ = nullptr; - - std::vector<std::unique_ptr<syncer::DeviceInfo>> devices_; - - SubMenuDelegate sub_menu_delegate_{this}; - - std::u16string text_; - - std::unique_ptr<ui::SimpleMenuModel> sub_menu_model_; -}; - -#endif // CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_CONTEXT_MENU_OBSERVER_H_
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer_unittest.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer_unittest.cc deleted file mode 100644 index f267218..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer_unittest.cc +++ /dev/null
@@ -1,226 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/renderer_context_menu/mock_render_view_context_menu.h" -#include "chrome/browser/sharing/fake_device_info.h" -#include "chrome/browser/sharing/features.h" -#include "chrome/browser/sharing/mock_sharing_service.h" -#include "chrome/browser/sharing/sharing_constants.h" -#include "chrome/browser/sharing/sharing_service_factory.h" -#include "chrome/browser/sharing/vapid_key_manager.h" -#include "components/sync_device_info/device_info.h" -#include "content/public/browser/context_menu_params.h" -#include "content/public/test/browser_task_environment.h" -#include "content/public/test/test_renderer_host.h" -#include "content/public/test/web_contents_tester.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; -using ::testing::ByMove; -using ::testing::Eq; -using ::testing::NiceMock; -using ::testing::Property; -using ::testing::Return; - -using SharingMessage = chrome_browser_sharing::SharingMessage; - -namespace { - -const char16_t kText[] = u"Some random text to be copied."; - -class SharedClipboardContextMenuObserverTest : public testing::Test { - public: - SharedClipboardContextMenuObserverTest() = default; - - SharedClipboardContextMenuObserverTest( - const SharedClipboardContextMenuObserverTest&) = delete; - SharedClipboardContextMenuObserverTest& operator=( - const SharedClipboardContextMenuObserverTest&) = delete; - - ~SharedClipboardContextMenuObserverTest() override = default; - - void SetUp() override { - web_contents_ = content::WebContentsTester::CreateTestWebContents( - menu_.GetBrowserContext(), nullptr); - menu_.set_web_contents(web_contents_.get()); - SharingServiceFactory::GetInstance()->SetTestingFactory( - menu_.GetBrowserContext(), - base::BindRepeating([](content::BrowserContext* context) - -> std::unique_ptr<KeyedService> { - return std::make_unique<NiceMock<MockSharingService>>(); - })); - observer_ = std::make_unique<SharedClipboardContextMenuObserver>(&menu_); - menu_.SetObserver(observer_.get()); - } - - void InitMenu(const std::u16string text) { - content::ContextMenuParams params; - params.selection_text = text; - observer_->InitMenu(params); - sharing_message.mutable_shared_clipboard_message()->set_text( - base::UTF16ToUTF8(text)); - } - - std::vector<std::unique_ptr<syncer::DeviceInfo>> CreateFakeDevices( - int count) { - std::vector<std::unique_ptr<syncer::DeviceInfo>> devices; - for (int i = 0; i < count; i++) { - devices.emplace_back(CreateFakeDeviceInfo( - base::StrCat({"guid", base::NumberToString(i)}), "name")); - } - return devices; - } - - protected: - NiceMock<MockSharingService>* service() { - return static_cast<NiceMock<MockSharingService>*>( - SharingServiceFactory::GetForBrowserContext(menu_.GetBrowserContext())); - } - - content::BrowserTaskEnvironment task_environment_; - content::RenderViewHostTestEnabler test_render_host_factories_; - MockRenderViewContextMenu menu_{/* incognito= */ false}; - std::unique_ptr<content::WebContents> web_contents_; - std::unique_ptr<SharedClipboardContextMenuObserver> observer_; - SharingMessage sharing_message; -}; - -} // namespace - -MATCHER_P(ProtoEquals, message, "") { - std::string expected_serialized, actual_serialized; - message.SerializeToString(&expected_serialized); - arg.SerializeToString(&actual_serialized); - return expected_serialized == actual_serialized; -} - -TEST_F(SharedClipboardContextMenuObserverTest, NoDevices_DoNotShowMenu) { - auto devices = CreateFakeDevices(0); - - EXPECT_CALL(*service(), GetDeviceCandidates(_)) - .WillOnce(Return(ByMove(std::move(devices)))); - - InitMenu(kText); - - EXPECT_EQ(0U, menu_.GetMenuSize()); -} - -TEST_F(SharedClipboardContextMenuObserverTest, SingleDevice_ShowMenu) { - auto devices = CreateFakeDevices(1); - auto guid = devices[0]->guid(); - - EXPECT_CALL(*service(), GetDeviceCandidates(_)) - .WillOnce(Return(ByMove(std::move(devices)))); - - InitMenu(kText); - ASSERT_EQ(1U, menu_.GetMenuSize()); - - MockRenderViewContextMenu::MockMenuItem item; - ASSERT_TRUE(menu_.GetMenuItem(0, &item)); - EXPECT_EQ(IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE, - item.command_id); - - // Emulate click on the device. - EXPECT_CALL(*service(), - SendMessageToDevice(Property(&syncer::DeviceInfo::guid, guid), - Eq(kSharingMessageTTL), - ProtoEquals(sharing_message), _)) - .Times(1); - menu_.ExecuteCommand( - IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_SINGLE_DEVICE, 0); -} - -TEST_F(SharedClipboardContextMenuObserverTest, MultipleDevices_ShowMenu) { - constexpr int device_count = 3; - auto devices = CreateFakeDevices(device_count); - std::vector<std::string> guids; - for (auto& device : devices) - guids.push_back(device->guid()); - - EXPECT_CALL(*service(), GetDeviceCandidates(_)) - .WillOnce(Return(ByMove(std::move(devices)))); - - InitMenu(kText); - ASSERT_EQ(device_count + 1U, menu_.GetMenuSize()); - - // Assert item ordering. - MockRenderViewContextMenu::MockMenuItem item; - ASSERT_TRUE(menu_.GetMenuItem(0, &item)); - EXPECT_EQ(IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES, - item.command_id); - - for (int i = 0; i < device_count; i++) { - ASSERT_TRUE(menu_.GetMenuItem(i + 1, &item)); - EXPECT_EQ(kSubMenuFirstDeviceCommandId + i, item.command_id); - } - - // Emulate clicks on all commands to check for commands with no device - // assigned. - for (int i = 0; i < kMaxDevicesShown; i++) { - if (i < device_count) { - EXPECT_CALL(*service(), - SendMessageToDevice( - Property(&syncer::DeviceInfo::guid, guids[i]), - Eq(kSharingMessageTTL), ProtoEquals(sharing_message), _)) - .Times(1); - } else { - EXPECT_CALL(*service(), SendMessageToDevice(_, _, _, _)).Times(0); - } - observer_->sub_menu_delegate_.ExecuteCommand( - kSubMenuFirstDeviceCommandId + i, 0); - } -} - -TEST_F(SharedClipboardContextMenuObserverTest, - MultipleDevices_MoreThanMax_ShowMenu) { - int device_count = kMaxDevicesShown + 1; - auto devices = CreateFakeDevices(device_count); - std::vector<std::string> guids; - for (auto& device : devices) - guids.push_back(device->guid()); - - EXPECT_CALL(*service(), GetDeviceCandidates(_)) - .WillOnce(Return(ByMove(std::move(devices)))); - - InitMenu(kText); - ASSERT_EQ(kMaxDevicesShown + 1U, menu_.GetMenuSize()); - - // Assert item ordering. - MockRenderViewContextMenu::MockMenuItem item; - ASSERT_TRUE(menu_.GetMenuItem(0, &item)); - EXPECT_EQ(IDC_CONTENT_CONTEXT_SHARING_SHARED_CLIPBOARD_MULTIPLE_DEVICES, - item.command_id); - - for (int i = 0; i < kMaxDevicesShown; i++) { - ASSERT_TRUE(menu_.GetMenuItem(i + 1, &item)); - EXPECT_EQ(kSubMenuFirstDeviceCommandId + i, item.command_id); - } - - // Emulate clicks on all device commands to check for commands outside valid - // range too. - for (int i = 0; i < device_count; i++) { - if (i < kMaxDevicesShown) { - EXPECT_CALL(*service(), - SendMessageToDevice( - Property(&syncer::DeviceInfo::guid, guids[i]), - Eq(kSharingMessageTTL), ProtoEquals(sharing_message), _)) - .Times(1); - } else { - EXPECT_CALL(*service(), SendMessageToDevice(_, _, _, _)).Times(0); - } - observer_->sub_menu_delegate_.ExecuteCommand( - kSubMenuFirstDeviceCommandId + i, 0); - } -}
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.cc deleted file mode 100644 index 3fea8e32..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.cc +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h" - -#include <utility> - -#include "base/callback.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/sharing/sharing_constants.h" -#include "chrome/browser/sharing/sharing_dialog.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_finder.h" -#include "chrome/grit/generated_resources.h" -#include "components/sync_device_info/device_info.h" -#include "content/public/browser/web_contents.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/strings/grit/ui_strings.h" - -// static -SharedClipboardUiController* -SharedClipboardUiController::GetOrCreateFromWebContents( - content::WebContents* web_contents) { - // Use active WebContents if available. - Browser* browser = chrome::FindBrowserWithWebContents(web_contents); - if (browser) - web_contents = browser->tab_strip_model()->GetActiveWebContents(); - SharedClipboardUiController::CreateForWebContents(web_contents); - return SharedClipboardUiController::FromWebContents(web_contents); -} - -SharedClipboardUiController::SharedClipboardUiController( - content::WebContents* web_contents) - : SharingUiController(web_contents), - content::WebContentsUserData<SharedClipboardUiController>(*web_contents) { -} - -SharedClipboardUiController::~SharedClipboardUiController() = default; - -void SharedClipboardUiController::OnDeviceSelected( - const std::u16string& text, - const syncer::DeviceInfo& device) { - text_ = text; - OnDeviceChosen(device); -} - -std::u16string SharedClipboardUiController::GetTitle( - SharingDialogType dialog_type) { - // Shared clipboard only shows error dialogs. - DCHECK_EQ(SharingDialogType::kErrorDialog, dialog_type); - - if (send_result() == SharingSendMessageResult::kPayloadTooLarge) { - return l10n_util::GetStringUTF16( - IDS_BROWSER_SHARING_SHARED_CLIPBOARD_ERROR_DIALOG_TITLE_PAYLOAD_TOO_LARGE); - } - - return SharingUiController::GetTitle(dialog_type); -} - -PageActionIconType SharedClipboardUiController::GetIconType() { - return PageActionIconType::kSharedClipboard; -} - -sync_pb::SharingSpecificFields::EnabledFeatures -SharedClipboardUiController::GetRequiredFeature() const { - return sync_pb::SharingSpecificFields::SHARED_CLIPBOARD_V2; -} - -// No need for apps for shared clipboard feature -void SharedClipboardUiController::DoUpdateApps(UpdateAppsCallback callback) { - std::move(callback).Run(std::vector<SharingApp>()); -} - -void SharedClipboardUiController::OnDeviceChosen( - const syncer::DeviceInfo& device) { - chrome_browser_sharing::SharingMessage sharing_message; - sharing_message.mutable_shared_clipboard_message()->set_text( - base::UTF16ToUTF8(text_)); - - SendMessageToDevice(device, /*response_timeout=*/absl::nullopt, - std::move(sharing_message), - /*callback=*/absl::nullopt); -} - -void SharedClipboardUiController::OnAppChosen(const SharingApp& app) { - // Do nothing - there is no apps -} - -std::u16string SharedClipboardUiController::GetContentType() const { - return l10n_util::GetStringUTF16(IDS_BROWSER_SHARING_CONTENT_TYPE_TEXT); -} - -std::u16string SharedClipboardUiController::GetErrorDialogText() const { - if (send_result() == SharingSendMessageResult::kPayloadTooLarge) { - return l10n_util::GetStringUTF16( - IDS_BROWSER_SHARING_SHARED_CLIPBOARD_ERROR_DIALOG_TEXT_PAYLOAD_TOO_LARGE); - } - - return SharingUiController::GetErrorDialogText(); -} - -const gfx::VectorIcon& SharedClipboardUiController::GetVectorIcon() const { - return kCopyIcon; -} - -std::u16string SharedClipboardUiController::GetTextForTooltipAndAccessibleName() - const { - return l10n_util::GetStringUTF16(IDS_OMNIBOX_TOOLTIP_SHARED_CLIPBOARD); -} - -SharingFeatureName SharedClipboardUiController::GetFeatureMetricsPrefix() - const { - return SharingFeatureName::kSharedClipboard; -} - -WEB_CONTENTS_USER_DATA_KEY_IMPL(SharedClipboardUiController);
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h b/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h deleted file mode 100644 index f60cb2a..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_UI_CONTROLLER_H_ -#define CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_UI_CONTROLLER_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/memory/weak_ptr.h" -#include "chrome/browser/sharing/sharing_ui_controller.h" -#include "chrome/browser/ui/page_action/page_action_icon_type.h" -#include "content/public/browser/web_contents_user_data.h" - -namespace content { -class WebContents; -} // namespace content - -class SharedClipboardUiController - : public SharingUiController, - public content::WebContentsUserData<SharedClipboardUiController> { - public: - static SharedClipboardUiController* GetOrCreateFromWebContents( - content::WebContents* web_contents); - - SharedClipboardUiController(const SharedClipboardUiController&) = delete; - SharedClipboardUiController& operator=(const SharedClipboardUiController&) = - delete; - - ~SharedClipboardUiController() override; - - void OnDeviceSelected(const std::u16string& text, - const syncer::DeviceInfo& device); - - // Overridden from SharingUiController: - std::u16string GetTitle(SharingDialogType dialog_type) override; - PageActionIconType GetIconType() override; - sync_pb::SharingSpecificFields::EnabledFeatures GetRequiredFeature() - const override; - void OnDeviceChosen(const syncer::DeviceInfo& device) override; - void OnAppChosen(const SharingApp& app) override; - std::u16string GetContentType() const override; - std::u16string GetErrorDialogText() const override; - const gfx::VectorIcon& GetVectorIcon() const override; - std::u16string GetTextForTooltipAndAccessibleName() const override; - SharingFeatureName GetFeatureMetricsPrefix() const override; - - protected: - explicit SharedClipboardUiController(content::WebContents* web_contents); - - // Overridden from SharingUiController: - void DoUpdateApps(UpdateAppsCallback callback) override; - - private: - friend class content::WebContentsUserData<SharedClipboardUiController>; - - std::u16string text_; - - base::WeakPtrFactory<SharedClipboardUiController> weak_ptr_factory_{this}; - - WEB_CONTENTS_USER_DATA_KEY_DECL(); -}; - -#endif // CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_UI_CONTROLLER_H_
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller_unittest.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller_unittest.cc deleted file mode 100644 index 09a1758..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller_unittest.cc +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h" - -#include <memory> - -#include "base/guid.h" -#include "base/memory/ptr_util.h" -#include "base/memory/raw_ptr.h" -#include "base/strings/strcat.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/sharing/fake_device_info.h" -#include "chrome/browser/sharing/features.h" -#include "chrome/browser/sharing/mock_sharing_service.h" -#include "chrome/browser/sharing/sharing_constants.h" -#include "chrome/browser/sharing/sharing_service_factory.h" -#include "chrome/test/base/testing_profile.h" -#include "components/gcm_driver/fake_gcm_driver.h" -#include "components/gcm_driver/instance_id/instance_id_driver.h" -#include "components/sync/protocol/device_info_specifics.pb.h" -#include "components/sync_device_info/fake_device_info_tracker.h" -#include "components/sync_preferences/testing_pref_service_syncable.h" -#include "content/public/test/browser_task_environment.h" -#include "content/public/test/test_renderer_host.h" -#include "content/public/test/web_contents_tester.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -using ::testing::Eq; -using ::testing::Property; - -namespace { - -const char16_t kText[] = u"Text to be copied"; -const char kExpectedText[] = "Text to be copied"; -const char kReceiverGuid[] = "test_receiver_guid"; -const char kReceiverName[] = "test_receiver_name"; - -class SharedClipboardUiControllerTest : public testing::Test { - public: - SharedClipboardUiControllerTest() = default; - - void SetUp() override { - web_contents_ = - content::WebContentsTester::CreateTestWebContents(&profile_, nullptr); - SharingServiceFactory::GetInstance()->SetTestingFactory( - &profile_, base::BindRepeating([](content::BrowserContext* context) - -> std::unique_ptr<KeyedService> { - return std::make_unique<testing::NiceMock<MockSharingService>>(); - })); - std::unique_ptr<syncer::DeviceInfo> device_info = - CreateFakeDeviceInfo(kReceiverGuid, kReceiverName); - controller_ = SharedClipboardUiController::GetOrCreateFromWebContents( - web_contents_.get()); - controller_->OnDeviceSelected(kText, *device_info.get()); - } - - protected: - testing::NiceMock<MockSharingService>* service() { - return static_cast<testing::NiceMock<MockSharingService>*>( - SharingServiceFactory::GetForBrowserContext(&profile_)); - } - - content::BrowserTaskEnvironment task_environment_; - content::RenderViewHostTestEnabler test_render_host_factories_; - TestingProfile profile_; - std::unique_ptr<content::WebContents> web_contents_; - raw_ptr<SharedClipboardUiController> controller_ = nullptr; -}; -} // namespace - -MATCHER_P(ProtoEquals, message, "") { - std::string expected_serialized, actual_serialized; - message.SerializeToString(&expected_serialized); - arg.SerializeToString(&actual_serialized); - return expected_serialized == actual_serialized; -} - -// Check the call to sharing service when a device is chosen. -TEST_F(SharedClipboardUiControllerTest, OnDeviceChosen) { - std::unique_ptr<syncer::DeviceInfo> device_info = - CreateFakeDeviceInfo(kReceiverGuid, kReceiverName); - - chrome_browser_sharing::SharingMessage sharing_message; - sharing_message.mutable_shared_clipboard_message()->set_text(kExpectedText); - EXPECT_CALL( - *service(), - SendMessageToDevice(Property(&syncer::DeviceInfo::guid, kReceiverGuid), - Eq(kSharingMessageTTL), ProtoEquals(sharing_message), - testing::_)); - controller_->OnDeviceChosen(*device_info.get()); -} - -// Check the call to sharing service to get all synced devices. -TEST_F(SharedClipboardUiControllerTest, GetSyncedDevices) { - EXPECT_CALL(*service(), - GetDeviceCandidates( - Eq(sync_pb::SharingSpecificFields::SHARED_CLIPBOARD_V2))); - controller_->GetDevices(); -}
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.cc deleted file mode 100644 index 25f5e29a..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.cc +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sharing/sharing_service.h" -#include "chrome/browser/sharing/sharing_service_factory.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_service.h" -#include "content/public/browser/browser_context.h" - -bool ShouldOfferSharedClipboard(content::BrowserContext* browser_context, - const std::u16string& text) { - // TODO(https://crbug.com/1311675): Remove this function and all its call - // sites. - return false; -}
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.h b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.h deleted file mode 100644 index e2d0c3fc..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.h +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_UTILS_H_ -#define CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_UTILS_H_ - -#include <string> - - -namespace content { -class BrowserContext; -} // namespace content - -bool ShouldOfferSharedClipboard(content::BrowserContext* browser_context, - const std::u16string& text); - -#endif // CHROME_BROWSER_SHARING_SHARED_CLIPBOARD_SHARED_CLIPBOARD_UTILS_H_
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc deleted file mode 100644 index 3e77479..0000000 --- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer.h" - -#include <memory> - -#include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" -#include "chrome/browser/sharing/mock_sharing_service.h" -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_utils.h" -#include "chrome/browser/sharing/sharing_device_source.h" -#include "chrome/browser/sharing/sharing_fcm_handler.h" -#include "chrome/browser/sharing/sharing_fcm_sender.h" -#include "chrome/browser/sharing/sharing_handler_registry.h" -#include "chrome/browser/sharing/sharing_service.h" -#include "chrome/browser/sharing/sharing_service_factory.h" -#include "chrome/browser/sharing/sharing_sync_preference.h" -#include "chrome/browser/sharing/vapid_key_manager.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/testing_profile.h" -#include "components/prefs/pref_service.h" -#include "content/public/test/browser_task_environment.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::_; -using ::testing::ByMove; -using ::testing::Eq; -using ::testing::NiceMock; -using ::testing::Return; - -namespace { - -const char16_t kText[] = u"Some text to copy to phone device."; - -class MockSharingDeviceRegistration : public SharingDeviceRegistration { - public: - MockSharingDeviceRegistration() - : SharingDeviceRegistration(/*pref_service=*/nullptr, - /*sharing_sync_preference=*/nullptr, - /*vapid_key_manager=*/nullptr, - /*instance_id_driver=*/nullptr, - /*sync_service=*/nullptr) {} - - MockSharingDeviceRegistration(const MockSharingDeviceRegistration&) = delete; - MockSharingDeviceRegistration& operator=( - const MockSharingDeviceRegistration&) = delete; - - ~MockSharingDeviceRegistration() override = default; - - MOCK_CONST_METHOD0(IsSharedClipboardSupported, bool()); -}; - -class SharedClipboardUtilsTest : public testing::Test { - public: - SharedClipboardUtilsTest() = default; - - SharedClipboardUtilsTest(const SharedClipboardUtilsTest&) = delete; - SharedClipboardUtilsTest& operator=(const SharedClipboardUtilsTest&) = delete; - - ~SharedClipboardUtilsTest() override = default; - - void SetUp() override { - SharingServiceFactory::GetInstance()->SetTestingFactory( - &profile_, base::BindRepeating(&SharedClipboardUtilsTest::CreateService, - base::Unretained(this))); - } - - protected: - std::unique_ptr<KeyedService> CreateService( - content::BrowserContext* context) { - return create_service_ ? std::make_unique<MockSharingService>() : nullptr; - } - - base::test::ScopedFeatureList scoped_feature_list_; - content::BrowserTaskEnvironment task_environment_; - TestingProfile profile_; - bool create_service_ = true; -}; - -} // namespace - -// TODO(https://crbug.com/1311675): Remove this test and file once all the -// shared clipboard implementation is gone. -TEST_F(SharedClipboardUtilsTest, UIFlagDisabled_DoNotShowMenu) { - EXPECT_FALSE(ShouldOfferSharedClipboard(&profile_, kText)); -}
diff --git a/chrome/browser/sync/sync_service_factory_unittest.cc b/chrome/browser/sync/sync_service_factory_unittest.cc index c5ee7e8..e83102b 100644 --- a/chrome/browser/sync/sync_service_factory_unittest.cc +++ b/chrome/browser/sync/sync_service_factory_unittest.cc
@@ -82,7 +82,7 @@ // Returns the collection of default datatypes. syncer::ModelTypeSet DefaultDatatypes() { - static_assert(39 == syncer::GetNumModelTypes(), + static_assert(40 == syncer::GetNumModelTypes(), "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled)."); @@ -126,6 +126,7 @@ datatypes.Put(syncer::OS_PRIORITY_PREFERENCES); } datatypes.Put(syncer::PRINTERS); + // TODO(pawliczek): Add PRINTERS_AUTHORIZATION_SERVERS when ready. datatypes.Put(syncer::WIFI_CONFIGURATIONS); datatypes.Put(syncer::WORKSPACE_DESK); #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc index b1a8e7c..bbcf676 100644 --- a/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_standalone_transport_sync_test.cc
@@ -30,7 +30,7 @@ namespace { syncer::ModelTypeSet AllowedTypesInStandaloneTransportMode() { - static_assert(39 == syncer::GetNumModelTypes(), + static_assert(40 == syncer::GetNumModelTypes(), "Add new types below if they run in transport mode"); // Only some special allowlisted types (and control types) are allowed in // standalone transport mode. @@ -42,11 +42,12 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) // OS sync types run in transport mode. if (chromeos::features::IsSyncSettingsCategorizationEnabled()) { - allowed_types.PutAll({syncer::APPS, syncer::APP_SETTINGS, syncer::APP_LIST, - syncer::APP_SETTINGS, syncer::ARC_PACKAGE, - syncer::PRINTERS, syncer::OS_PREFERENCES, - syncer::OS_PRIORITY_PREFERENCES, syncer::WEB_APPS, - syncer::WORKSPACE_DESK}); + allowed_types.PutAll( + {syncer::APPS, syncer::APP_SETTINGS, syncer::APP_LIST, + syncer::APP_SETTINGS, syncer::ARC_PACKAGE, syncer::PRINTERS, + syncer::PRINTERS_AUTHORIZATION_SERVERS, syncer::OS_PREFERENCES, + syncer::OS_PRIORITY_PREFERENCES, syncer::WEB_APPS, + syncer::WORKSPACE_DESK}); } allowed_types.Put(syncer::WIFI_CONFIGURATIONS); #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.cc b/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.cc index 7ad5ee3..778cb1e 100644 --- a/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.cc +++ b/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.cc
@@ -7,10 +7,12 @@ #include <string> #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/site_instance.h" +#include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" namespace { @@ -47,16 +49,20 @@ BackForwardCacheTask::BackForwardCacheTask( content::RenderFrameHost* render_frame_host, - RendererTask* parent_task) + RendererTask* parent_task, + WebContentsTaskProvider* task_provider) : RendererTask( GetTaskTitle(render_frame_host, parent_task), nullptr, // TODO(crbug.com/1225508): Set Favicon for main frames. render_frame_host), - parent_task_(parent_task) {} + parent_task_(parent_task), + task_provider_(task_provider) {} // For the top level BackForwardCacheTask |parent_task_| is nullptr. Task* BackForwardCacheTask::GetParentTask() const { - return parent_task_; + return parent_task_ ? parent_task_ + : task_provider_->GetTaskOfFrame( + web_contents()->GetPrimaryMainFrame()); } // The top page calls the default Activate().
diff --git a/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.h b/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.h index 3d0abc90..602e967 100644 --- a/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.h +++ b/chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.h
@@ -14,13 +14,16 @@ namespace task_manager { +class WebContentsTaskProvider; + // Defines a concrete renderer task that can represent processes stored in the // BackForwardCache. Tasks are added for each cached main frame, as well as for // each separate SiteInstance for subframes within a cached page. class BackForwardCacheTask : public RendererTask { public: BackForwardCacheTask(content::RenderFrameHost* render_frame_host, - RendererTask* parent_task); + RendererTask* parent_task, + WebContentsTaskProvider* task_provider); BackForwardCacheTask(const BackForwardCacheTask&) = delete; BackForwardCacheTask& operator=(const BackForwardCacheTask&) = delete; ~BackForwardCacheTask() override = default; @@ -41,6 +44,8 @@ // task is not guaranteed. // For cached main frame tasks |parent_task_| is nullptr. raw_ptr<RendererTask> parent_task_; + // The provider has the same lifespan as the task manager. + const raw_ptr<WebContentsTaskProvider> task_provider_; }; } // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.cc b/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.cc index 9244ac5..a75663f 100644 --- a/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.cc +++ b/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.cc
@@ -8,6 +8,7 @@ #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/site_instance.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -19,28 +20,28 @@ /*title=*/u"", /*icon=*/nullptr, /*subframe=*/render_frame_host), - render_frame_host_(render_frame_host), + site_instance_(render_frame_host->GetSiteInstance()), embedder_task_(embedder_task) { set_title(GetTitle()); } void FencedFrameTask::Activate() { - DCHECK(embedder_task_); embedder_task_->Activate(); } +const task_manager::Task* FencedFrameTask::GetParentTask() const { + return embedder_task_; +} + void FencedFrameTask::UpdateTitle() { set_title(GetTitle()); } std::u16string FencedFrameTask::GetTitle() const { - DCHECK(render_frame_host_); - const auto message_id = - render_frame_host_->GetBrowserContext()->IsOffTheRecord() - ? IDS_TASK_MANAGER_FENCED_FRAME_INCOGNITO_PREFIX - : IDS_TASK_MANAGER_FENCED_FRAME_PREFIX; - const auto title = - base::UTF8ToUTF16(render_frame_host_->GetLastCommittedURL().spec()); + const auto message_id = site_instance_->GetBrowserContext()->IsOffTheRecord() + ? IDS_TASK_MANAGER_FENCED_FRAME_INCOGNITO_PREFIX + : IDS_TASK_MANAGER_FENCED_FRAME_PREFIX; + const auto title = base::UTF8ToUTF16(site_instance_->GetSiteURL().spec()); return l10n_util::GetStringFUTF16(message_id, title); }
diff --git a/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.h b/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.h index b8b79e9..fad12c1 100644 --- a/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.h +++ b/chrome/browser/task_manager/providers/web_contents/fenced_frame_task.h
@@ -10,6 +10,7 @@ namespace content { class RenderFrameHost; +class SiteInstance; } // namespace content namespace task_manager { @@ -25,6 +26,7 @@ // task_manager::Task: void Activate() override; + const task_manager::Task* GetParentTask() const override; // task_manager::RendererTask: void UpdateTitle() override; void UpdateFavicon() override {} @@ -32,22 +34,17 @@ private: std::u16string GetTitle() const; + // The site instance is owned by the RFH and the RFH always outlives the task. // A FencedFrame task is deleted when: - // 1, a navigation happens to the fenced frame, so - // |WebContentsEntry::RenderFrameHostChanged| is fired. Clearly in this - // case both the embedder frame (hence the task) as well as the FF's RFH - // are always alive. - // 2, when the user closes the tab / terminates the embedder process from task - // manager/ terminates the FF's process from task manager. In the three - // cases the task will be deleted from - // |WebContentsEntry::RenderFrameDeleted|. When the user closes the tab or - // terminates the embedder process, the tasks will be deleted in a - // bottom-up fashion, from FF to embedder FF; when the user terminates the - // process of the FF, FF's frame is deleted. So in the three cases the RFH - // and embedder task are also guaranteed to outlive the FF task. - raw_ptr<content::RenderFrameHost> render_frame_host_; + // 1, a navigation happens to the FencedFrame (FF), so + // |WebContentsEntry::RenderFrameHostChanged| is fired. Clearly the FF's + // RFH is alive (thus the site instance). + // 2, when the fenced frame is destroyed (by either terminating the embedder + // or FF's process). The |RenderFrameDeleted| will be triggered to delete + // the task. At that point the RFH is still alive. + const raw_ptr<content::SiteInstance> site_instance_; // Allows us to focus on the embedder's tab. - raw_ptr<RendererTask> embedder_task_; + const raw_ptr<RendererTask> embedder_task_; }; } // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/web_contents/prerender_task.cc b/chrome/browser/task_manager/providers/web_contents/prerender_task.cc index bb644c90..0ac0a662 100644 --- a/chrome/browser/task_manager/providers/web_contents/prerender_task.cc +++ b/chrome/browser/task_manager/providers/web_contents/prerender_task.cc
@@ -6,20 +6,23 @@ #include "base/check.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.h" #include "chrome/grit/generated_resources.h" -#include "chrome/grit/theme_resources.h" -#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" namespace task_manager { -PrerenderTask::PrerenderTask(content::RenderFrameHost* render_frame_host) +PrerenderTask::PrerenderTask(content::RenderFrameHost* render_frame_host, + WebContentsTaskProvider* task_provider) : RendererTask( /*title=*/u"", /*icon=*/nullptr, /*subframe=*/render_frame_host), - render_frame_host_(render_frame_host) { + render_frame_host_(render_frame_host), + task_provider_(task_provider) { DCHECK(render_frame_host_); DCHECK_EQ(render_frame_host->GetLifecycleState(), content::RenderFrameHost::LifecycleState::kPrerendering); @@ -28,12 +31,15 @@ PrerenderTask::~PrerenderTask() = default; +const Task* PrerenderTask::GetParentTask() const { + return task_provider_->GetTaskOfFrame(web_contents()->GetPrimaryMainFrame()); +} + void PrerenderTask::UpdateTitle() { set_title(GetTitle()); } std::u16string PrerenderTask::GetTitle() const { - DCHECK(render_frame_host_); const auto title = base::UTF8ToUTF16(render_frame_host_->GetLastCommittedURL().spec()); return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRERENDER_PREFIX, title);
diff --git a/chrome/browser/task_manager/providers/web_contents/prerender_task.h b/chrome/browser/task_manager/providers/web_contents/prerender_task.h index bc3aedf..3741a7cf6 100644 --- a/chrome/browser/task_manager/providers/web_contents/prerender_task.h +++ b/chrome/browser/task_manager/providers/web_contents/prerender_task.h
@@ -14,14 +14,19 @@ namespace task_manager { +class WebContentsTaskProvider; + // Defines a task manager entry for a Prerender2 rule. class PrerenderTask : public RendererTask { public: - explicit PrerenderTask(content::RenderFrameHost* render_frame_host); + explicit PrerenderTask(content::RenderFrameHost* render_frame_host, + WebContentsTaskProvider* task_provider); PrerenderTask(const PrerenderTask&) = delete; PrerenderTask& operator=(const PrerenderTask&) = delete; ~PrerenderTask() override; + // task_manager::Task: + const Task* GetParentTask() const override; // task_manager::RendererTask: void UpdateTitle() override; void UpdateFavicon() override {} @@ -32,7 +37,9 @@ // prerender2 task is deleted at |WebContentsEntry::RenderFrameDeleted| and // |WebContentsEntry::RenderFrameHostStateChange|, and at both occasions the // RFH is still alive. - raw_ptr<content::RenderFrameHost> render_frame_host_; + const raw_ptr<content::RenderFrameHost> render_frame_host_; + // The provider has the same lifespan as the task manager. + const raw_ptr<WebContentsTaskProvider> task_provider_; }; } // namespace task_manager
diff --git a/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc b/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc index 9ad8dec9..7eef369b 100644 --- a/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc +++ b/chrome/browser/task_manager/providers/web_contents/subframe_task_browsertest.cc
@@ -39,6 +39,14 @@ std::u16string()); } +std::u16string PrefixExpectedBFCacheTitle(const std::string& title, + bool is_subframe) { + const auto msg_id = is_subframe + ? IDS_TASK_MANAGER_BACK_FORWARD_CACHE_SUBFRAME_PREFIX + : IDS_TASK_MANAGER_BACK_FORWARD_CACHE_PREFIX; + return l10n_util::GetStringFUTF16(msg_id, base::UTF8ToUTF16(title)); +} + std::u16string PrefixExpectedTabTitle(const std::string& title) { return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX, base::UTF8ToUTF16(title)); @@ -133,7 +141,25 @@ ? 4U : 1U, task_manager.tasks().size()); - const Task* simple_page_task = task_manager.tasks().front(); + + const auto& tasks = task_manager.tasks(); + // Main page and two cross-origin iframes. + if (content::BackForwardCache::IsSameSiteBackForwardCacheFeatureEnabled()) { + EXPECT_EQ( + PrefixExpectedBFCacheTitle("http://a.com/", /*is_subframe=*/false), + tasks[0]->title()); + EXPECT_EQ(PrefixExpectedBFCacheTitle("http://b.com/", + /*is_subframe=*/true), + tasks[1]->title()); + EXPECT_EQ(PrefixExpectedBFCacheTitle("http://c.com/", + /*is_subframe=*/true), + tasks[2]->title()); + } + // When navigation to |kSimplePageUrl| happens, tasks are first created for + // page a.com and two cross-origin iframes b.com and c.com from + // |RenderFrameHostStateChange|, then the task for |kSimplePageUrl| is created + // from |DidFinishNavigation| when the navigation completes. Thus |.back()|. + const Task* simple_page_task = tasks.back(); EXPECT_EQ(Task::RENDERER, simple_page_task->GetType()); EXPECT_EQ(PrefixExpectedTabTitle("Title Of Awesomeness"), simple_page_task->title());
diff --git a/chrome/browser/task_manager/providers/web_contents/tab_contents_tag_browsertest.cc b/chrome/browser/task_manager/providers/web_contents/tab_contents_tag_browsertest.cc index 8e9521a5..b1bea20 100644 --- a/chrome/browser/task_manager/providers/web_contents/tab_contents_tag_browsertest.cc +++ b/chrome/browser/task_manager/providers/web_contents/tab_contents_tag_browsertest.cc
@@ -24,6 +24,7 @@ #include "content/public/browser/back_forward_cache.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/site_instance.h" #include "content/public/test/browser_test.h" #include "content/public/test/fenced_frame_test_util.h" #include "content/public/test/test_utils.h" @@ -134,7 +135,7 @@ TabContentsTagTest() { EXPECT_TRUE(embedded_test_server()->Start()); } TabContentsTagTest(const TabContentsTagTest&) = delete; TabContentsTagTest& operator=(const TabContentsTagTest&) = delete; - ~TabContentsTagTest() override {} + ~TabContentsTagTest() override = default; void AddNewTestTabAt(int index, const char* test_page_file) { int tabs_count_before = tabs_count(); @@ -297,6 +298,11 @@ browser()->tab_strip_model()->GetActiveWebContents()); FaviconWaiter waiter(favicon_driver); waiter.WaitForFaviconWithURL(GetUrlOfFile("/favicon/icon.png")); + const auto favicon_url = browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetSiteInstance() + ->GetSiteURL(); // Check that the task manager uses the specified favicon for the page. base::FilePath test_dir; @@ -324,13 +330,18 @@ // same-site main frame navigations, we'll get a new task because we are // changing RenderFrameHosts. Note that the previous page's task might still // be around if the previous page is saved in the back-forward cache. - ASSERT_EQ( - content::BackForwardCache::IsSameSiteBackForwardCacheFeatureEnabled() - ? 2U - : 1U, - task_manager.tasks().size()); - task = task_manager.tasks().front(); + if (content::BackForwardCache::IsSameSiteBackForwardCacheFeatureEnabled()) { + ASSERT_EQ(2U, task_manager.tasks().size()); + ASSERT_EQ( + l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACK_FORWARD_CACHE_PREFIX, + base::UTF8ToUTF16(favicon_url.spec())), + task_manager.tasks().front()->title()); + } else { + ASSERT_EQ(1U, task_manager.tasks().size()); + } } + + task = task_manager.tasks().back(); ASSERT_EQ(GetDefaultTitleForUrl(no_favicon_page_url), task->title()); // Check that the task manager uses the default favicon for the page.
diff --git a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc index 3a3d7a2..612001f2 100644 --- a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc +++ b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc
@@ -12,7 +12,10 @@ #include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/notreached.h" #include "chrome/browser/task_manager/providers/web_contents/back_forward_cache_task.h" +#include "chrome/browser/task_manager/providers/web_contents/fenced_frame_task.h" +#include "chrome/browser/task_manager/providers/web_contents/prerender_task.h" #include "chrome/browser/task_manager/providers/web_contents/subframe_task.h" #include "chrome/browser/task_manager/providers/web_contents/web_contents_tags_manager.h" #include "content/public/browser/navigation_handle.h" @@ -64,7 +67,6 @@ RenderFrameHost* render_frame_host, RenderFrameHost::LifecycleState old_state, RenderFrameHost::LifecycleState new_state) override; - void RenderFrameCreated(RenderFrameHost*) override; void WebContentsDestroyed() override; void OnRendererUnresponsive(RenderProcessHost* render_process_host) override; void DidFinishNavigation( @@ -74,7 +76,7 @@ void RenderFrameReady(int process_routing_id, int frame_routing_id); private: - // Defines a callback for WebContents::ForEachFrame() to create a + // Defines a callback for WebContents::ForEachRenderFrameHost() to create a // corresponding task for the given |render_frame_host| and notifying the // provider's observer of the new task. void CreateTaskForFrame(RenderFrameHost* render_frame_host); @@ -104,7 +106,7 @@ base::flat_map<SiteInstance*, SiteInstanceInfo> site_instance_infos_; // States whether we did record a main frame for this entry. - raw_ptr<SiteInstance> main_frame_site_instance_ = nullptr; + raw_ptr<SiteInstance> primary_main_frame_site_instance_ = nullptr; base::WeakPtrFactory<WebContentsEntry> weak_factory_{this}; }; @@ -122,7 +124,7 @@ void WebContentsTaskProvider::WebContentsEntry::CreateAllTasks() { DCHECK(web_contents()->GetPrimaryMainFrame()); - web_contents()->ForEachFrame(base::BindRepeating( + web_contents()->ForEachRenderFrameHost(base::BindRepeating( &WebContentsEntry::CreateTaskForFrame, base::Unretained(this))); } @@ -138,7 +140,7 @@ } site_instance_infos_.clear(); - main_frame_site_instance_ = nullptr; + primary_main_frame_site_instance_ = nullptr; } RendererTask* WebContentsTaskProvider::WebContentsEntry::GetTaskForFrame( @@ -175,8 +177,6 @@ void WebContentsTaskProvider::WebContentsEntry::RenderFrameHostChanged( RenderFrameHost* old_host, RenderFrameHost* new_host) { - DCHECK(new_host->IsActive()); - // The navigating frame and its subframes are now pending deletion. Stop // tracking them immediately rather than when they are destroyed. The order of // deletion is important. The children must be removed first. @@ -184,12 +184,11 @@ ClearTasksForDescendantsOf(old_host); ClearTaskForFrame(old_host); } - - CreateTaskForFrame(new_host); + // Tasks creation for |new_host| is delayed to |DidFinishNavigation|. } -// Only handle frames entering or exiting -// RenderFrameHost::LifecycleState::kInBackForwardCache. +// Handles creation and deletion of BFCache tasks for pages entering and leaving +// the BFCache, and deletion of prerender tasks after prerendering activation. void WebContentsTaskProvider::WebContentsEntry::RenderFrameHostStateChanged( RenderFrameHost* render_frame_host, RenderFrameHost::LifecycleState old_state, @@ -199,18 +198,14 @@ if (new_state == RenderFrameHost::LifecycleState::kInBackForwardCache) CreateTaskForFrame(render_frame_host); -} -void WebContentsTaskProvider::WebContentsEntry::RenderFrameCreated( - RenderFrameHost* render_frame_host) { - DCHECK(render_frame_host->IsRenderFrameLive()); - - // Skip pending/speculative hosts. We'll create tasks for these if the - // navigation commits, at which point RenderFrameHostChanged() will fire. - if (!render_frame_host->IsActive()) - return; - - CreateTaskForFrame(render_frame_host); + // |RenderFrameDeleted| is not fired for prerender page activation so we need + // to delete prerender task. |RenderFrameHostStateChanged| is the earliest + // event of the prerendering activation flow. + if (old_state == RenderFrameHost::LifecycleState::kPrerendering && + new_state == RenderFrameHost::LifecycleState::kActive) { + ClearTaskForFrame(render_frame_host); + } } void WebContentsTaskProvider::WebContentsEntry::RenderFrameReady( @@ -252,9 +247,47 @@ void WebContentsTaskProvider::WebContentsEntry::DidFinishNavigation( content::NavigationHandle* navigation_handle) { - // We only need to update tasks for primary main frame navigations. - if (!navigation_handle->IsInPrimaryMainFrame()) + // No task creation/update for downloads and HTTP204/205. + if (!navigation_handle->HasCommitted()) { return; + } + + // Creation. + // + // Create a task if we have not encountered this site instance before, or it + // is a new RenderFrameHost for this site instance. For same-document + // navigation, since neither |RenderFrameDeleted| nor |RenderFrameHostChanged| + // is fired to delete the existing task, we do not recreate them. + // + // TODO(crbug.com/1183630): DidFinishNavigation is not called when we create + // initial empty documents, and as a result, we will not create new tasks for + // these empty documents if they are in a different process from their + // embedder/opener (eg: an empty fenced frame or a blank tab created by + // window.open('', '_blank', 'noopener')). Ideally, we would call + // CreateTaskForFrame inside RenderFrameCreated instead (which is called for + // initial documents), but CreateTaskForFrame uses RFH::GetLifecycleState, + // which cannot currently be called inside RenderFrameCreated (due to a DCHECK + // which doesn't allow the method to be called when the state is + // 'kSpeculative'). + auto* rfh = navigation_handle->GetRenderFrameHost(); + auto* site_instance = rfh->GetSiteInstance(); + auto it = site_instance_infos_.find(site_instance); + if (!navigation_handle->IsSameDocument() && + (it == site_instance_infos_.end() || + it->second.frames.find(rfh) == it->second.frames.end())) { + CreateTaskForFrame(rfh); + } + + // Update. + // + // We only need to update tasks for primary main frame navigations. + // FencedFrame task gets the title from |SiteInstance::GetSiteURL()| which + // does not change for the same site instance, thus no need to update; + // prerender does not support multiple navigations thus no need to update its + // title. + if (!navigation_handle->IsInPrimaryMainFrame()) { + return; + } RendererTask* main_frame_task = GetTaskForFrame(web_contents()->GetPrimaryMainFrame()); @@ -288,21 +321,39 @@ void WebContentsTaskProvider::WebContentsEntry::CreateTaskForFrame( RenderFrameHost* render_frame_host) { + DCHECK(render_frame_host); // Currently we do not track speculative RenderFrameHosts or RenderFrameHosts // which are pending deletion. - DCHECK(render_frame_host); - DCHECK(render_frame_host->IsActive() || - render_frame_host->GetLifecycleState() == - RenderFrameHost::LifecycleState::kInBackForwardCache); + const auto rfh_state = render_frame_host->GetLifecycleState(); + switch (rfh_state) { + case RenderFrameHost::LifecycleState::kPrerendering: + case RenderFrameHost::LifecycleState::kInBackForwardCache: + case RenderFrameHost::LifecycleState::kActive: + break; + default: + NOTREACHED(); + break; + } - // Exclude sad tabs and sad OOPIFs. - if (!render_frame_host->IsRenderFrameLive()) + // Exclude sad tabs, sad OOPIFs. + if (!render_frame_host->IsRenderFrameLive()) { return; + } + + // Another instance of this class will be created for inner WebContents. If we + // iterate into an inner WebContents that is not associated with `this`, skip + // it, so we don't create duplicated tasks. Task creation for RenderFrameHosts + // not associated with a WebContents should be handled by a different type of + // TaskProvider. + if (content::WebContents::FromRenderFrameHost(render_frame_host) != + web_contents()) { + return; + } // Exclude frames in the same SiteInstance or same process as their parent; // |site_instance_infos_| only contains local roots. content::SiteInstance* site_instance = render_frame_host->GetSiteInstance(); - auto* parent = render_frame_host->GetParent(); + auto* parent = render_frame_host->GetParentOrOuterDocument(); if (parent && (site_instance == parent->GetSiteInstance() || site_instance->GetProcess() == parent->GetSiteInstance()->GetProcess())) { @@ -310,9 +361,10 @@ } bool site_instance_exists = site_instance_infos_.count(site_instance) != 0; - bool is_primary_main_frame = - (render_frame_host == web_contents()->GetPrimaryMainFrame()); - bool site_instance_is_main = (site_instance == main_frame_site_instance_); + auto* primary_main_rfh = web_contents()->GetPrimaryMainFrame(); + bool is_primary_main_frame = (render_frame_host == primary_main_rfh); + bool site_instance_is_main = + (site_instance == primary_main_frame_site_instance_); std::unique_ptr<RendererTask> new_task; @@ -321,22 +373,26 @@ // represented by a SubframeTask. if (!site_instance_exists || (is_primary_main_frame && !site_instance_is_main)) { - if (render_frame_host->GetLifecycleState() == - RenderFrameHost::LifecycleState::kInBackForwardCache) { - // Use RFH::GetMainFrame instead web_contents()->GetMainFrame() because - // the BFCached frames are not the currently active main frame. + auto* primary_main_frame_task = GetTaskForFrame(primary_main_rfh); + if (rfh_state == RenderFrameHost::LifecycleState::kInBackForwardCache) { + // Use RFH::GetMainFrame instead web_contents()->GetPrimaryMainFrame() + // because the BFCached frames are not the currently active main frame. RenderFrameHost* main_frame = render_frame_host->GetMainFrame(); new_task = std::make_unique<BackForwardCacheTask>( - render_frame_host, GetTaskForFrame(main_frame)); + render_frame_host, GetTaskForFrame(main_frame), provider_); + } else if (rfh_state == RenderFrameHost::LifecycleState::kPrerendering) { + new_task = std::make_unique<PrerenderTask>(render_frame_host, provider_); } else if (is_primary_main_frame) { const WebContentsTag* tag = WebContentsTag::FromWebContents(web_contents()); new_task = tag->CreateTask(provider_); - main_frame_site_instance_ = site_instance; + primary_main_frame_site_instance_ = site_instance; + } else if (render_frame_host->IsFencedFrameRoot()) { + new_task = std::make_unique<FencedFrameTask>(render_frame_host, + primary_main_frame_task); } else { - new_task = std::make_unique<SubframeTask>( - render_frame_host, - GetTaskForFrame(web_contents()->GetPrimaryMainFrame())); + new_task = std::make_unique<SubframeTask>(render_frame_host, + primary_main_frame_task); } } @@ -385,27 +441,30 @@ site_instance_infos_.erase(itr); provider_->NotifyObserverTaskRemoved(renderer_task.get()); - if (site_instance == main_frame_site_instance_) - main_frame_site_instance_ = nullptr; + if (site_instance == primary_main_frame_site_instance_) + primary_main_frame_site_instance_ = nullptr; } #if DCHECK_IS_ON() // Whenever we have a task, we should have a main frame site instance. - // However, when a tab is destroyed and there was a BFCached Task, the main - // task may be cleaned up before the BFCached Task. + // However, when a tab is destroyed and there was a BFCached Task or a + // prerender task, the main task may be cleaned up before the + // BFCached/prerender Task. BFCache or prerender tasks will be deleted + // asynchronously after the main frame is deleted. - bool only_bfcache_rfhs = true; - for (auto& entry : site_instance_infos_) { - for (auto* rfh : entry.second.frames) { - if (rfh->GetLifecycleState() != - RenderFrameHost::LifecycleState::kInBackForwardCache) { - only_bfcache_rfhs = false; + bool only_bfcache_or_prerender_rfhs = true; + for (auto& [site_instance, site_instance_info] : site_instance_infos_) { + for (auto* rfh : site_instance_info.frames) { + const auto state = rfh->GetLifecycleState(); + if (state != RenderFrameHost::LifecycleState::kInBackForwardCache && + state != RenderFrameHost::LifecycleState::kPrerendering) { + only_bfcache_or_prerender_rfhs = false; } } } - - DCHECK(only_bfcache_rfhs || site_instance_infos_.empty() == - (main_frame_site_instance_ == nullptr)); + DCHECK(only_bfcache_or_prerender_rfhs || + site_instance_infos_.empty() == + (primary_main_frame_site_instance_ == nullptr)); #endif }
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc index cb8c7c0b..1b3782d 100644 --- a/chrome/browser/task_manager/task_manager_browsertest.cc +++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -10,6 +10,8 @@ #include "base/files/file_path.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/strings/strcat.h" +#include "base/strings/string_piece_forward.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -18,6 +20,8 @@ #include "chrome/browser/devtools/devtools_window_testing.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/notifications/notification_test_util.h" +#include "chrome/browser/predictors/autocomplete_action_predictor.h" +#include "chrome/browser/predictors/autocomplete_action_predictor_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/task_manager/task_manager_browsertest_util.h" #include "chrome/browser/task_manager/task_manager_interface.h" @@ -28,6 +32,8 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/web_applications/extensions/web_app_extension_shortcut.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/in_process_browser_test.h" @@ -35,6 +41,7 @@ #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/confirm_infobar_delegate.h" #include "components/infobars/core/infobar.h" +#include "components/url_formatter/url_formatter.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/page_navigator.h" @@ -44,7 +51,9 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h" +#include "content/public/test/fenced_frame_test_util.h" #include "content/public/test/no_renderer_crashes_assertion.h" +#include "content/public/test/prerender_test_util.h" #include "content/public/test/test_navigation_observer.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" @@ -53,20 +62,32 @@ #include "services/strings/grit/services_strings.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/page_transition_types.h" #include "url/gurl.h" +#include "url/url_constants.h" using content::WebContents; using task_manager::browsertest_util::ColumnSpecifier; using task_manager::browsertest_util::MatchAboutBlankTab; using task_manager::browsertest_util::MatchAnyApp; +using task_manager::browsertest_util::MatchAnyBFCache; using task_manager::browsertest_util::MatchAnyExtension; +using task_manager::browsertest_util::MatchAnyFencedFrame; +using task_manager::browsertest_util::MatchAnyIncognitoFencedFrame; +using task_manager::browsertest_util::MatchAnyIncognitoTab; +using task_manager::browsertest_util::MatchAnyPrerender; using task_manager::browsertest_util::MatchAnySubframe; using task_manager::browsertest_util::MatchAnyTab; using task_manager::browsertest_util::MatchAnyUtility; using task_manager::browsertest_util::MatchApp; +using task_manager::browsertest_util::MatchBFCache; using task_manager::browsertest_util::MatchExtension; +using task_manager::browsertest_util::MatchFencedFrame; +using task_manager::browsertest_util::MatchIncognitoFencedFrame; +using task_manager::browsertest_util::MatchIncognitoTab; +using task_manager::browsertest_util::MatchPrerender; using task_manager::browsertest_util::MatchSubframe; using task_manager::browsertest_util::MatchTab; using task_manager::browsertest_util::MatchUtility; @@ -1374,3 +1395,632 @@ subframe_b_index < subframe_d_index); } } + +//============================================================================== +// Prerender tasks test. +namespace { +// Prerender trigger page URL. +const char kMainPageUrl[] = "/title2.html"; +// The prerendered URL. +const char kPrerenderURL[] = "/title1.html"; + +class AutocompleteActionPredictorObserverImpl + : public predictors::AutocompleteActionPredictor::Observer { + public: + explicit AutocompleteActionPredictorObserverImpl( + predictors::AutocompleteActionPredictor* predictor) { + observation_.Observe(predictor); + } + + ~AutocompleteActionPredictorObserverImpl() override = default; + + void WaitForInitialization() { + base::RunLoop loop; + waiting_ = loop.QuitClosure(); + loop.Run(); + } + + // predictors::AutocompleteActionPredictor::Observer: + void OnInitialized() override { + DCHECK(waiting_); + std::move(waiting_).Run(); + } + + base::ScopedObservation<predictors::AutocompleteActionPredictor, + predictors::AutocompleteActionPredictor::Observer> + observation_{this}; + base::OnceClosure waiting_; +}; + +class PrerenderTaskBrowserTest : public TaskManagerBrowserTest { + public: + PrerenderTaskBrowserTest() { + // `blink::features::kPrerender2` and + // `blink::features::kPrerender2MemoryControls` are enabled in + // |prerender_helper_|. + prerender_helper_ = std::make_unique<content::test::PrerenderTestHelper>( + base::BindRepeating(&PrerenderTaskBrowserTest::GetActiveWebContents, + base::Unretained(this))); + EXPECT_TRUE(blink::features::IsPrerender2Enabled()); + feature_list_.InitWithFeaturesAndParameters( + /*enabled_features=*/ + { + {features::kBackForwardCache, + {{"enable_same_site", "true"}, + {"TimeToLiveInBackForwardCacheInSeconds", "3600"}}}, + {features::kOmniboxTriggerForPrerender2, {}}, + }, + /*disabled_features=*/{}); + EXPECT_TRUE(content::BackForwardCache::IsBackForwardCacheFeatureEnabled()); + } + PrerenderTaskBrowserTest(const PrerenderTaskBrowserTest&) = delete; + PrerenderTaskBrowserTest& operator=(const PrerenderTaskBrowserTest&) = delete; + ~PrerenderTaskBrowserTest() override = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + content::IsolateAllSitesForTesting(command_line); + ASSERT_TRUE(content::AreAllSitesIsolatedForTesting()); + TaskManagerBrowserTest::SetUpCommandLine(command_line); + } + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + embedded_test_server()->ServeFilesFromDirectory( + base::PathService::CheckedGet(chrome::DIR_TEST_DATA)); + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + embedded_test_server()->StartAcceptingConnections(); + } + + void NavigateTo(base::StringPiece page_url) const { + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL(page_url))); + } + + WebContents* GetActiveWebContents() { + return browser()->tab_strip_model()->GetActiveWebContents(); + } + + predictors::AutocompleteActionPredictor* GetAutocompleteActionPredictor() { + return predictors::AutocompleteActionPredictorFactory::GetForProfile( + browser()->profile()); + } + + void WaitForAutocompleteActionPredictorInitialization() { + if (GetAutocompleteActionPredictor()->initialized()) { + return; + } + AutocompleteActionPredictorObserverImpl predictor_observer( + GetAutocompleteActionPredictor()); + predictor_observer.WaitForInitialization(); + } + + WebContents* NavigateToURLWithDispositionAndTransition( + const GURL& url, + WindowOpenDisposition disposition, + ui::PageTransition transition) { + return GetActiveWebContents()->OpenURL(content::OpenURLParams( + url, content::Referrer(), disposition, transition, + /*is_renderer_initiated=*/false)); + } + + content::test::PrerenderTestHelper* prerender_helper() { + return prerender_helper_.get(); + } + + // Prerender's task title is constructed from |RFH->GetLastCommittedURL|, + // which contains the port of the testing webserver. + std::string port() const { + return base::NumberToString(embedded_test_server()->port()); + } + + private: + std::unique_ptr<content::test::PrerenderTestHelper> prerender_helper_; + base::test::ScopedFeatureList feature_list_; +}; + +} // namespace + +// Tests that the task manager properly: +// 1. shows the Prerender entry when the speculation rule is injected; +// 2. shows the Prerender entry when the manager is closed and reopened. +// 3. deletes the Prerender entry when the prerendered page is activated. +IN_PROC_BROWSER_TEST_F(PrerenderTaskBrowserTest, ProperlyShowsTasks) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(kMainPageUrl); + + const auto prerender_gurl = embedded_test_server()->GetURL(kPrerenderURL); + + // Inject the speculation rule and wait for prerender to complete. + prerender_helper()->AddPrerender(prerender_gurl); + + // Must have one tab task, one prerender task. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchPrerender(prerender_gurl.spec()))); + + // "Close" the task manager and "reopen" it. We should see the same tasks. + HideTaskManager(); + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchPrerender(prerender_gurl.spec()))); + + // Activate the prerender page. The triggering page is placed in BFCache, + // and the prerendered page is activated. + content::test::PrerenderHostObserver obs(*GetActiveWebContents(), + prerender_gurl); + content::test::PrerenderTestHelper::NavigatePrimaryPage( + *GetActiveWebContents(), prerender_gurl); + ASSERT_TRUE(obs.was_activated()); + + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyBFCache())); + // Take out the "http://". + const auto tab_title = + url_formatter::FormatUrl(embedded_test_server()->GetURL(kPrerenderURL)); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab(base::UTF16ToUTF8(tab_title)))); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchBFCache("http://127.0.0.1/"))); +} + +// Tests that the task manager properly deletes the prerender task once the +// prerender is cancelled. +IN_PROC_BROWSER_TEST_F(PrerenderTaskBrowserTest, + DeletesTaskAfterPrerenderKilled) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(kMainPageUrl); + + const auto prerender_gurl = embedded_test_server()->GetURL(kPrerenderURL); + prerender_helper()->AddPrerender(prerender_gurl); + + // Must have one tab task, one prerender task. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchPrerender(prerender_gurl.spec()))); + + // Terminate the prerender task, which should signal the task manager to + // remove the prerender task entry. + { + content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes; + int prerender_row = + FindResourceIndex(MatchPrerender(prerender_gurl.spec())); + ASSERT_NE(-1, prerender_row); + ASSERT_TRUE(model()->GetTabId(prerender_row).is_valid()); + model()->Kill(prerender_row); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + } +} + +// Tests that the task manager properly deletes the task of the trigger tab and +// prerender when the trigger is terminated. +IN_PROC_BROWSER_TEST_F(PrerenderTaskBrowserTest, + DeletesTaskAfterTriggerPageKilled) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(kMainPageUrl); + + const auto prerender_gurl = embedded_test_server()->GetURL(kPrerenderURL); + prerender_helper()->AddPrerender(prerender_gurl); + + // Must have one tab task, one prerender task. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchPrerender(prerender_gurl.spec()))); + + // Terminate the prerender task, which should signal the task manager to + // remove the prerender task entry. + { + content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes; + int trigger_row = FindResourceIndex(MatchTab("Title Of Awesomeness")); + ASSERT_NE(-1, trigger_row); + ASSERT_TRUE(model()->GetTabId(trigger_row).is_valid()); + model()->Kill(trigger_row); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender())); + } +} + +// Test that the autocomplete action predictor trigger Prerender tasks are +// properly displayed. Such predictor is used to trigger Omnibox Prerender. +IN_PROC_BROWSER_TEST_F(PrerenderTaskBrowserTest, + ProperlyShowsPrerenderTaskByAutocompletePredictor) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(kMainPageUrl); + + ASSERT_TRUE(GetAutocompleteActionPredictor()); + WaitForAutocompleteActionPredictorInitialization(); + const auto prerender_gurl = embedded_test_server()->GetURL(kPrerenderURL); + GetAutocompleteActionPredictor()->StartPrerendering( + prerender_gurl, *(browser()->tab_strip_model()->GetActiveWebContents()), + gfx::Size(50, 50)); + + // One task for main page and one for the prerendered page. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchPrerender(prerender_gurl.spec()))); + // Main task stays after prerendered task is terminated. + { + content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes; + int prerender_row = + FindResourceIndex(MatchPrerender(prerender_gurl.spec())); + ASSERT_NE(-1, prerender_row); + ASSERT_TRUE(model()->GetTabId(prerender_row).is_valid()); + model()->Kill(prerender_row); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender())); + } + // Both tasks are deleted after main task is terminated. + { + // Use a different URL because re-using the same URL does not trigger new + // prerendering: + // https://crsrc.org/c/chrome/browser/predictors/autocomplete_action_predictor.cc;l=208;drc=a08a4e1c3f6862b3b1385b8a040a4fdb524e509d + const char kNewPrerenderURL[] = "/title3.html"; + const auto new_prerender_gurl = + embedded_test_server()->GetURL(kNewPrerenderURL); + GetAutocompleteActionPredictor()->StartPrerendering( + embedded_test_server()->GetURL(kNewPrerenderURL), + *GetActiveWebContents(), gfx::Size(50, 50)); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchPrerender(new_prerender_gurl.spec()))); + + content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes; + int trigger_row = FindResourceIndex(MatchTab("Title Of Awesomeness")); + ASSERT_NE(-1, trigger_row); + ASSERT_TRUE(model()->GetTabId(trigger_row).is_valid()); + model()->Kill(trigger_row); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender())); + } +} + +// Test that the Omnibox-triggered prerender activation clears the prerender +// entry in the task manager. +IN_PROC_BROWSER_TEST_F(PrerenderTaskBrowserTest, + OmniboxPrerenderActivationClearsTask) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(kMainPageUrl); + + ASSERT_TRUE(GetAutocompleteActionPredictor()); + WaitForAutocompleteActionPredictorInitialization(); + const auto prerender_gurl = embedded_test_server()->GetURL(kPrerenderURL); + GetAutocompleteActionPredictor()->StartPrerendering( + prerender_gurl, *GetActiveWebContents(), gfx::Size(50, 50)); + + // One task for main page and one for the prerendered page. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyPrerender())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchPrerender(prerender_gurl.spec()))); + + // Activate the Omnibox prerender, after which the prerender task should + // disappear. + content::test::PrerenderHostObserver obs(*GetActiveWebContents(), + prerender_gurl); + // |ui::PAGE_TRANSITION_FROM_ADDRESS_BAR| augmentation is required for omnibox + // activation. + auto* web_contents = NavigateToURLWithDispositionAndTransition( + prerender_gurl, WindowOpenDisposition::CURRENT_TAB, + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR)); + obs.WaitForActivation(); + ASSERT_TRUE(obs.was_activated()); + ASSERT_EQ(web_contents, GetActiveWebContents()); // Current tab. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyPrerender())); + // Take out the "http://". + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, + MatchTab(base::UTF16ToUTF8(url_formatter::FormatUrl(prerender_gurl))))); +} + +//============================================================================== +// FencedFrame tasks test. +namespace { + +class FencedFrameTaskBrowserTest : public TaskManagerBrowserTest { + public: + FencedFrameTaskBrowserTest() { + EXPECT_TRUE(blink::features::IsFencedFramesEnabled()); + EXPECT_TRUE(blink::features::IsFencedFramesMPArchBased()); + } + FencedFrameTaskBrowserTest(const FencedFrameTaskBrowserTest&) = delete; + FencedFrameTaskBrowserTest& operator=(const FencedFrameTaskBrowserTest&) = + delete; + ~FencedFrameTaskBrowserTest() override = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + content::IsolateAllSitesForTesting(command_line); + ASSERT_TRUE(content::AreAllSitesIsolatedForTesting()); + TaskManagerBrowserTest::SetUpCommandLine(command_line); + } + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + https_server()->ServeFilesFromDirectory( + base::PathService::CheckedGet(chrome::DIR_TEST_DATA)); + https_server()->SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); + content::SetupCrossSiteRedirector(https_server()); + ASSERT_TRUE(https_server()->InitializeAndListen()); + https_server()->StartAcceptingConnections(); + } + + void NavigateTo(Browser* browser, + base::StringPiece host, + base::StringPiece rel_url) { + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser, https_server()->GetURL(host, rel_url))); + } + + std::string GetFencedFrameTitle(base::StringPiece host) const { + return base::StrCat({"https://", host, "/"}); + } + + net::EmbeddedTestServer* https_server() { return &https_server_; } + + content::test::FencedFrameTestHelper* helper() { return helper_.get(); } + + private: + base::test::ScopedFeatureList feature_list_; + net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS}; + std::unique_ptr<content::test::FencedFrameTestHelper> helper_ = + std::make_unique<content::test::FencedFrameTestHelper>(); +}; + +} // namespace + +// Testing that the task manager properly displays fenced frame tasks with +// re-opening task manager, and with fenced frame navigations. +IN_PROC_BROWSER_TEST_F(FencedFrameTaskBrowserTest, ProperlyShowsTasks) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(browser(), "a.test", "/title2.html"); + // Create two fenced frames. + auto* main_frame = browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetPrimaryMainFrame(); + const auto initial_gurl = + https_server()->GetURL("a.test", "/fenced_frames/title1.html"); + content::RenderFrameHostWrapper fenced_frame_rfh( + helper()->CreateFencedFrame(main_frame, initial_gurl)); + ASSERT_TRUE(fenced_frame_rfh); + + // One task for the embedder. Same origin fenced frame does not show up in the + // task manager. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + + // Navigate the same-site FF to a cross-site url. The changes should be + // reflected in the task manager. + const auto cross_site_gurl = + https_server()->GetURL("b.test", "/fenced_frames/title2.html"); + helper()->NavigateFrameInFencedFrameTree(fenced_frame_rfh.get(), + cross_site_gurl); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, MatchFencedFrame(GetFencedFrameTitle("b.test")))); + + // Close the task manager and re-open it, all tasks should be re-created. + HideTaskManager(); + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, MatchFencedFrame(GetFencedFrameTitle("b.test")))); + + // Terminate the fenced frame. The embedder frame remains intact. + { + content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes; + int fenced_frame_row = + FindResourceIndex(MatchFencedFrame(GetFencedFrameTitle("b.test"))); + ASSERT_NE(-1, fenced_frame_row); + ASSERT_TRUE(model()->GetTabId(fenced_frame_row).is_valid()); + model()->Kill(fenced_frame_row); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + } + // Re-create the fenced frame and terminate the embedding frame. The + // embedder's task and the remaining fenced frame tasks are destroyed. + { + helper()->CreateFencedFrame(main_frame, initial_gurl); + content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes; + int embedder_row = FindResourceIndex(MatchTab("Title Of Awesomeness")); + ASSERT_NE(-1, embedder_row); + ASSERT_TRUE(model()->GetTabId(embedder_row).is_valid()); + model()->Kill(embedder_row); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyFencedFrame())); + } +} + +// Test that the empty fenced frame (one without a `src`) is not shown in the +// task manager. Not shown because we cannot observe any navigation events for +// fenced frame creation (only |RenderFrameCreated| is triggered). +IN_PROC_BROWSER_TEST_F(FencedFrameTaskBrowserTest, EmptyFencedFrameNotShown) { + const std::string kEmptyFencedFrameSnippet = R"( + const ff = document.createElement("fencedframe"); + document.body.appendChild(ff); + )"; + + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(browser(), "a.test", "/title2.html"); + + auto* main_frame = browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetPrimaryMainFrame(); + ASSERT_TRUE(content::ExecJs(main_frame, kEmptyFencedFrameSnippet)); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, MatchAnyFencedFrame())); + + // Navigation on the empty fenced frame should create an entry. + auto* fenced_frame_rfh = + content::test::FencedFrameTestHelper::GetMostRecentlyAddedFencedFrame( + main_frame); + ASSERT_NE(fenced_frame_rfh, nullptr); + const auto fenced_frame_gurl = + https_server()->GetURL("b.test", "/fenced_frames/title1.html"); + helper()->NavigateFrameInFencedFrameTree(fenced_frame_rfh, fenced_frame_gurl); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, MatchFencedFrame(GetFencedFrameTitle("b.test")))); +} + +// Tests that the task manager properly shows tasks in Incognito mode. +IN_PROC_BROWSER_TEST_F(FencedFrameTaskBrowserTest, ShowsIncognitoTask) { + auto* incognito_browser = CreateIncognitoBrowser(); + ASSERT_NE(incognito_browser, nullptr); + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(incognito_browser, "a.test", "/title2.html"); + auto* main_frame = incognito_browser->tab_strip_model() + ->GetActiveWebContents() + ->GetPrimaryMainFrame(); + const auto fenced_frame_gurl = + https_server()->GetURL("b.test", "/fenced_frames/title1.html"); + content::RenderFrameHostWrapper ff_rfh( + helper()->CreateFencedFrame(main_frame, fenced_frame_gurl)); + ASSERT_TRUE(ff_rfh); + // Two tasks: one for the incognito main frame and another for the incognito + // fenced frames. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyIncognitoTab())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchAnyIncognitoFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchIncognitoTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, MatchIncognitoFencedFrame(GetFencedFrameTitle("b.test")))); +} + +// Test that clicking on the task manager fenced frame task row brings the focus +// to the embedder page. +IN_PROC_BROWSER_TEST_F(FencedFrameTaskBrowserTest, TaskActivationChangesFocus) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(browser(), "a.test", "/title2.html"); + // Create one fenced frame. + auto* main_frame = browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetPrimaryMainFrame(); + const auto fenced_frame_gurl = + https_server()->GetURL("b.test", "/fenced_frames/title1.html"); + content::RenderFrameHostWrapper ff_rfh( + helper()->CreateFencedFrame(main_frame, fenced_frame_gurl)); + ASSERT_TRUE(ff_rfh); + + // One main tab task, one fenced frame task. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, MatchFencedFrame(GetFencedFrameTitle("b.test")))); + + // Open a new tab of "about:blank". This appends an active WebContents at + // index 1. + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(url::kAboutBlankURL), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + + // The WebContents of "about:blank" is active. + ASSERT_EQ(browser()->tab_strip_model()->active_index(), 1); + + const int fenced_frame_task_row = + FindResourceIndex(MatchFencedFrame(GetFencedFrameTitle("b.test"))); + model()->Activate(fenced_frame_task_row); + + // The WebContents of the embedder page is active. + ASSERT_EQ(browser()->tab_strip_model()->active_index(), 0); +} + +// Test that same-document navigation does not change the task's title. +IN_PROC_BROWSER_TEST_F(FencedFrameTaskBrowserTest, + NoTitleChangeForSameDocNavigation) { + ShowTaskManager(); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAboutBlankTab())); + + NavigateTo(browser(), "a.test", "/title2.html"); + // Create one fenced frame. + auto* main_frame = browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetPrimaryMainFrame(); + const auto fenced_frame_gurl = + https_server()->GetURL("b.test", "/fenced_frames/title1.html"); + content::RenderFrameHostWrapper ff_rfh( + helper()->CreateFencedFrame(main_frame, fenced_frame_gurl)); + ASSERT_TRUE(ff_rfh); + + // One main tab task, one fenced frame task. + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, MatchFencedFrame(GetFencedFrameTitle("b.test")))); + + // Same-doc navigation of the fenced frame. + const auto same_doc_navi_gurl = https_server()->GetURL( + "b.test", base::StrCat({"/fenced_frames/title1.html", "#same_doc_navi"})); + helper()->NavigateFrameInFencedFrameTree(ff_rfh.get(), same_doc_navi_gurl); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyTab())); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, MatchAnyFencedFrame())); + ASSERT_NO_FATAL_FAILURE( + WaitForTaskManagerRows(1, MatchTab("Title Of Awesomeness"))); + ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows( + 1, MatchFencedFrame(GetFencedFrameTitle("b.test")))); +}
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.cc b/chrome/browser/task_manager/task_manager_browsertest_util.cc index 89d7309..52cb54a 100644 --- a/chrome/browser/task_manager/task_manager_browsertest_util.cc +++ b/chrome/browser/task_manager/task_manager_browsertest_util.cc
@@ -187,9 +187,9 @@ observer.RunUntilSatisfied(); } -std::u16string MatchTab(const char* title) { +std::u16string MatchTab(base::StringPiece title) { return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX, - base::ASCIIToUTF16(title)); + base::UTF8ToUTF16(title)); } std::u16string MatchAnyTab() { @@ -200,6 +200,15 @@ return MatchTab("about:blank"); } +std::u16string MatchIncognitoTab(base::StringPiece title) { + return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_INCOGNITO_PREFIX, + base::UTF8ToUTF16(title)); +} + +std::u16string MatchAnyIncognitoTab() { + return MatchIncognitoTab("*"); +} + std::u16string MatchExtension(const char* title) { return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_EXTENSION_PREFIX, base::ASCIIToUTF16(title)); @@ -262,5 +271,40 @@ return MatchUtility(u"*"); } +std::u16string MatchBFCache(base::StringPiece title) { + return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACK_FORWARD_CACHE_PREFIX, + base::UTF8ToUTF16(title)); +} + +std::u16string MatchAnyBFCache() { + return MatchBFCache("*"); +} + +std::u16string MatchPrerender(base::StringPiece title) { + return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRERENDER_PREFIX, + base::UTF8ToUTF16(title)); +} + +std::u16string MatchAnyPrerender() { + return MatchPrerender("*"); +} + +std::u16string MatchFencedFrame(base::StringPiece title) { + return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_FENCED_FRAME_PREFIX, + base::UTF8ToUTF16(title)); +} + +std::u16string MatchAnyFencedFrame() { + return MatchFencedFrame("*"); +} + +std::u16string MatchIncognitoFencedFrame(base::StringPiece title) { + return l10n_util::GetStringFUTF16( + IDS_TASK_MANAGER_FENCED_FRAME_INCOGNITO_PREFIX, base::UTF8ToUTF16(title)); +} + +std::u16string MatchAnyIncognitoFencedFrame() { + return MatchIncognitoFencedFrame("*"); +} } // namespace browsertest_util } // namespace task_manager
diff --git a/chrome/browser/task_manager/task_manager_browsertest_util.h b/chrome/browser/task_manager/task_manager_browsertest_util.h index fa4a85e..40d80e6 100644 --- a/chrome/browser/task_manager/task_manager_browsertest_util.h +++ b/chrome/browser/task_manager/task_manager_browsertest_util.h
@@ -15,6 +15,7 @@ #include <string> +#include "base/strings/string_piece_forward.h" namespace task_manager { namespace browsertest_util { @@ -60,9 +61,11 @@ size_t min_column_value); // ASCII matcher convenience functions for use with WaitForTaskManagerRows() -std::u16string MatchTab(const char* title); // "Tab: " + title +std::u16string MatchTab(base::StringPiece title); // "Tab: " + title std::u16string MatchAnyTab(); // "Tab: *" std::u16string MatchAboutBlankTab(); // "Tab: about:blank" +std::u16string MatchIncognitoTab(base::StringPiece title); +std::u16string MatchAnyIncognitoTab(); std::u16string MatchExtension(const char* title); // "Extension: " + title std::u16string MatchAnyExtension(); // "Extension: *" std::u16string MatchApp(const char* title); // "App: " + title @@ -78,7 +81,14 @@ // "Utility: " + title std::u16string MatchUtility(const std::u16string& title); std::u16string MatchAnyUtility(); // "Utility: *" - +std::u16string MatchBFCache(base::StringPiece title); +std::u16string MatchAnyBFCache(); +std::u16string MatchPrerender(base::StringPiece title); +std::u16string MatchAnyPrerender(); +std::u16string MatchFencedFrame(base::StringPiece title); +std::u16string MatchAnyFencedFrame(); +std::u16string MatchIncognitoFencedFrame(base::StringPiece title); +std::u16string MatchAnyIncognitoFencedFrame(); } // namespace browsertest_util } // namespace task_manager
diff --git a/chrome/browser/task_manager/task_manager_tester.cc b/chrome/browser/task_manager/task_manager_tester.cc index 14b9adf9..34d7128 100644 --- a/chrome/browser/task_manager/task_manager_tester.cc +++ b/chrome/browser/task_manager/task_manager_tester.cc
@@ -180,6 +180,10 @@ model_->KillTask(row); } +void TaskManagerTester::Activate(int row) { + model_->ActivateTask(row); +} + void TaskManagerTester::GetRowsGroupRange(int row, int* out_start, int* out_length) {
diff --git a/chrome/browser/task_manager/task_manager_tester.h b/chrome/browser/task_manager/task_manager_tester.h index e7dd24d..ef7df21 100644 --- a/chrome/browser/task_manager/task_manager_tester.h +++ b/chrome/browser/task_manager/task_manager_tester.h
@@ -55,6 +55,9 @@ // Kill the process of |row|. void Kill(int row); + // Activate the task of |row|. + void Activate(int row); + // Gets the start index and length of the group to which the task at // |row_index| belongs. void GetRowsGroupRange(int row, int* out_start, int* out_length);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3f1321a6..a9210cc2 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2237,6 +2237,8 @@ "ash/default_pinned_apps.h", "ash/desks/chrome_desks_templates_delegate.cc", "ash/desks/chrome_desks_templates_delegate.h", + "ash/desks/chrome_desks_util.cc", + "ash/desks/chrome_desks_util.h", "ash/desks/desks_client.cc", "ash/desks/desks_client.h", "ash/desks/desks_templates_app_launch_handler.cc",
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn index 5f1c6af..f4dae72 100644 --- a/chrome/browser/ui/android/omnibox/BUILD.gn +++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -63,6 +63,7 @@ "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfo.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java", + "java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcher.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalDelegate.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxQueryTileCoordinator.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxSuggestionUiType.java", @@ -369,6 +370,8 @@ "java/src/org/chromium/chrome/browser/omnibox/suggestions/CachedZeroSuggestionsManagerUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilderUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManagerUnitTest.java", + "java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java", + "java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java", @@ -379,6 +382,7 @@ "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionSelectionManagerUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/carousel/BaseCarouselSuggestionViewBinderUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorUnitTest.java", + "java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/header/HeaderViewBinderUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java", @@ -415,6 +419,7 @@ "//components/embedder_support/android:util_java", "//components/externalauth/android:java", "//components/favicon/android:java", + "//components/image_fetcher:java", "//components/omnibox/browser:browser_java", "//components/omnibox/browser:test_util_java", "//components/search_engines/android:java", @@ -430,6 +435,7 @@ "//third_party/androidx:androidx_recyclerview_recyclerview_java", "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_runner_java", + "//third_party/hamcrest:hamcrest_core_java", "//third_party/hamcrest:hamcrest_library_java", "//third_party/junit", "//third_party/mockito:mockito_java",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java index ce044c9..1ac7e25a 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
@@ -65,9 +65,9 @@ * <p>The coordinator creates and owns elements within this component. */ -public final class LocationBarCoordinator implements LocationBar, NativeInitObserver, - OmniboxSuggestionsDropdownEmbedder, - AutocompleteDelegate { +public class LocationBarCoordinator implements LocationBar, NativeInitObserver, + OmniboxSuggestionsDropdownEmbedder, + AutocompleteDelegate { /** Identifies coordinators with methods specific to a device type. */ public interface SubCoordinator { /** Destroys SubCoordinator. */
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index ad9a743..0466d02 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -295,6 +295,11 @@ return mStatusCoordinator; } + @VisibleForTesting + public void setStatusCoordinatorForTesting(StatusCoordinator statusCoordinator) { + mStatusCoordinator = statusCoordinator; + } + /* package */ void setUrlActionContainerVisibility(int visibility) { mUrlActionContainer.setVisibility(visibility); }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java index 5a499a0..44714c8 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListBuilder.java
@@ -55,6 +55,7 @@ private @Nullable HeaderProcessor mHeaderProcessor; private @Nullable Supplier<ShareDelegate> mShareDelegateSupplier; private @Nullable ImageFetcher mImageFetcher; + private @Nullable FaviconFetcher mFaviconFetcher; private @Nullable LargeIconBridge mIconBridge; private @NonNull BookmarkState mBookmarkState; @Px @@ -87,22 +88,23 @@ final Supplier<ShareDelegate> shareSupplier = () -> mShareDelegateSupplier == null ? null : mShareDelegateSupplier.get(); + mFaviconFetcher = new FaviconFetcher(context, iconBridgeSupplier); + mHeaderProcessor = new HeaderProcessor(context, host, delegate); registerSuggestionProcessor(new EditUrlSuggestionProcessor( - context, host, delegate, iconBridgeSupplier, mActivityTabSupplier, shareSupplier)); + context, host, delegate, mFaviconFetcher, mActivityTabSupplier, shareSupplier)); registerSuggestionProcessor( new AnswerSuggestionProcessor(context, host, textProvider, imageFetcherSupplier)); registerSuggestionProcessor( - new ClipboardSuggestionProcessor(context, host, iconBridgeSupplier)); + new ClipboardSuggestionProcessor(context, host, mFaviconFetcher)); registerSuggestionProcessor( new EntitySuggestionProcessor(context, host, imageFetcherSupplier)); registerSuggestionProcessor(new TailSuggestionProcessor(context, host)); - registerSuggestionProcessor( - new MostVisitedTilesProcessor(context, host, iconBridgeSupplier)); + registerSuggestionProcessor(new MostVisitedTilesProcessor(context, host, mFaviconFetcher)); registerSuggestionProcessor(new PedalSuggestionProcessor(context, host, textProvider, - iconBridgeSupplier, mBookmarkState, mOmniboxPedalDelegate, delegate)); + mFaviconFetcher, mBookmarkState, mOmniboxPedalDelegate, delegate)); registerSuggestionProcessor(new BasicSuggestionProcessor( - context, host, textProvider, iconBridgeSupplier, mBookmarkState)); + context, host, textProvider, mFaviconFetcher, mBookmarkState)); } void destroy() { @@ -153,6 +155,10 @@ mImageFetcher = null; } + if (mFaviconFetcher != null) { + mFaviconFetcher.clearCache(); + } + mIconBridge = new LargeIconBridge(profile); mImageFetcher = ImageFetcherFactory.createImageFetcher(ImageFetcherConfig.IN_MEMORY_ONLY, profile.getProfileKey(), GlobalDiscardableReferencePool.getReferencePool(), @@ -195,11 +201,9 @@ * @param hasFocus Indicates whether URL bar is now focused. */ void onUrlFocusChange(boolean hasFocus) { - if (!hasFocus && mImageFetcher != null) { - mImageFetcher.clear(); - } - if (!hasFocus) { + if (mImageFetcher != null) mImageFetcher.clear(); + if (mFaviconFetcher != null) mFaviconFetcher.clearCache(); mBuiltListHasFullyConcealedElements = false; }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcher.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcher.java new file mode 100644 index 0000000..5c018db1 --- /dev/null +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcher.java
@@ -0,0 +1,235 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.omnibox.suggestions; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.LruCache; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; + +import org.chromium.base.supplier.Supplier; +import org.chromium.base.task.PostTask; +import org.chromium.chrome.browser.omnibox.R; +import org.chromium.components.browser_ui.widget.RoundedIconGenerator; +import org.chromium.components.favicon.LargeIconBridge; +import org.chromium.content_public.browser.UiThreadTaskTraits; +import org.chromium.url.GURL; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Favicon fetching mechanism with multi-step fallback functionality. + * The class supports very simple caching mechanism which remembers what type of icon is available + * for a given URL to reduce number of JNI and object creation calls. + */ +public class FaviconFetcher { + /** + * Maximum number of IconAvailability records to keep. + * The cache used here is cheap (cost of one GURL and one int per entry), but + * allows us to reduce number of JNI calls for URLs we already confirmed to have + * no icons. + */ + private static final int MAX_ICON_AVAILABILITY_RECORDS = 256; + + /** Variants of available Favicons. */ + @IntDef({FaviconType.NONE, FaviconType.REGULAR, FaviconType.SMALL, FaviconType.GENERATED}) + @Retention(RetentionPolicy.SOURCE) + public @interface FaviconType { + // No favicon or fallback icon is available. + int NONE = 0; + // A regular size favicon is available. + int REGULAR = 1; + // Regular size favicon is not available, but small favicon is. + int SMALL = 2; + // Neither regular nor small favicon is available - fall back to RoundedIconGenerator. + int GENERATED = 3; + } + + /** Receiver of the Favicon fetch. */ + public interface FaviconFetchCompleteListener { + /** + * Invoked when a favicon fetch is complete. + * @param bitmap The resulting bitmap; may be null if favicon could not be retrieved for + * the supplied URL (reported with FaviconType.NONE). + * @param type The type of a favicon that was retrieved, or FaviconType.NONE if favicon + * could not be retrieved/acquired from any source. + */ + void onFaviconFetchComplete(@Nullable Bitmap bitmap, @FaviconType int type); + } + + private final @NonNull LruCache<GURL, Integer> mFaviconTypeCache; + private final @NonNull Supplier<LargeIconBridge> mIconBridgeSupplier; + private int mDesiredFaviconWidthPx; + private @NonNull RoundedIconGenerator mIconGenerator; + + /** + * Constructor. + * + * @param context An Android context. + * @param iconBridgeSupplier Supplier of the LargeIconBridge used to fetch site favicons. + */ + public FaviconFetcher( + @NonNull Context context, @NonNull Supplier<LargeIconBridge> iconBridgeSupplier) { + mIconBridgeSupplier = iconBridgeSupplier; + mDesiredFaviconWidthPx = context.getResources().getDimensionPixelSize( + R.dimen.omnibox_suggestion_favicon_size); + + int fallbackIconSize = + context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_size); + int fallbackIconColor = context.getColor(R.color.default_favicon_background_color); + int fallbackIconTextSize = + context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_text_size); + mIconGenerator = new RoundedIconGenerator(fallbackIconSize, fallbackIconSize, + fallbackIconSize / 2, fallbackIconColor, fallbackIconTextSize); + + mFaviconTypeCache = new LruCache(MAX_ICON_AVAILABILITY_RECORDS); + } + + /** + * Retrieve a favicon for a particular URL, retrying the fetch request with a smaller size if + * the requested size does not yield any results. + * + * @param url The url to retrieve a favicon for. + * @param allowGeneratedIcon When true, Fetcher will generate a favicon if all fetch attempts + * have failed. + * @param callback The callback to invoke with a favicon, once the result is known. + * The callback will be invoked with fallback bitmap if favicon cannot be retrieved. + */ + public void fetchFaviconWithBackoff(@NonNull GURL url, boolean allowGeneratedIcon, + @NonNull FaviconFetchCompleteListener callback) { + // Check for possible former records on the favicon to determine where to look for it. + @FaviconType + Integer faviconType = mFaviconTypeCache.get(url); + if (faviconType == null) { + faviconType = FaviconType.REGULAR; + } + + // If there are no regular favicons, and the caller rejects generated ones, abort. + if ((faviconType == FaviconType.GENERATED) && !allowGeneratedIcon) { + callback.onFaviconFetchComplete(null, FaviconType.NONE); + return; + } + + FaviconFetchCompleteListener backoffListener = new FaviconFetchCompleteListener() { + @Override + public void onFaviconFetchComplete(@Nullable Bitmap icon, @FaviconType int type) { + // Pass an icon directly to the callee if the fetch succeeded. + if (icon != null) { + // Remember the type of an icon to avoid backoff the next time we need this + // icon. + mFaviconTypeCache.put(url, type); + callback.onFaviconFetchComplete(icon, type); + return; + } + + // Back off and try again otherwise. + switch (type) { + case FaviconType.REGULAR: + fetchFaviconType(url, FaviconType.SMALL, this); + break; + + case FaviconType.SMALL: + // At this point it's safe to assume the only type we can offer is a + // generated icon. This is because REGULAR and SMALL icon fetches have + // already failed. This is a minor optimization that helps us reduce number + // of calls to LargeIconBridge. Note this is safe even if we don't want + // generated icons. This is because we won't be generating an icon in such + // case. + mFaviconTypeCache.put(url, FaviconType.GENERATED); + + if (allowGeneratedIcon) { + fetchFaviconType(url, FaviconType.GENERATED, this); + break; + } + // fallthrough: we don't allow generated icons. + + case FaviconType.GENERATED: + default: + callback.onFaviconFetchComplete(null, FaviconType.NONE); + break; + } + } + }; + + fetchFaviconType(url, faviconType, backoffListener); + } + + /** + * For a supplied url, retrieve a favicon of desired faviconType and deliver the result via the + * supplied callback. + * All fetches are done asynchronously, but the caller should expect a synchronous call in some + * cases, eg if an icon cannot be retrieved because a corresponding provider is not available. + * + * @param url The url to retrieve a favicon for. + * @param faviconType The specific type of favicon to retrieve. + * @param callback The callback that will be invoked with the result. + */ + private void fetchFaviconType(@NonNull GURL url, @FaviconType int faviconType, + @NonNull FaviconFetchCompleteListener callback) { + LargeIconBridge iconBridge = mIconBridgeSupplier.get(); + + // Determine if we need LargeIconBridge for this fetch, and abort early if we can't fulfill + // the request. + if ((faviconType == FaviconType.REGULAR || faviconType == FaviconType.SMALL) + && (iconBridge == null)) { + callback.onFaviconFetchComplete(null, faviconType); + return; + } + + switch (faviconType) { + case FaviconType.REGULAR: + iconBridge.getLargeIconForUrl(url, mDesiredFaviconWidthPx, + (icon, fallbackColor, isFallbackColorDefault, + iconType) -> callback.onFaviconFetchComplete(icon, faviconType)); + return; + + case FaviconType.SMALL: + iconBridge.getLargeIconForUrl(url, mDesiredFaviconWidthPx / 2, + (icon, fallbackColor, isFallbackColorDefault, + iconType) -> callback.onFaviconFetchComplete(icon, faviconType)); + return; + + case FaviconType.GENERATED: + PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> { + Bitmap icon = mIconGenerator.generateIconForUrl(url); + callback.onFaviconFetchComplete(icon, faviconType); + }); + return; + + default: + assert false : "Invalid favicon type requested: " + faviconType; + callback.onFaviconFetchComplete(null, faviconType); + return; + } + } + + /** Clear all cached entries. */ + public void clearCache() { + mFaviconTypeCache.evictAll(); + } + + /** + * Overrides RoundedIconGenerator for testing. + * @param generator RoundedIconGenerator to use. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + void setRoundedIconGeneratorForTesting(@NonNull RoundedIconGenerator generator) { + mIconGenerator = generator; + } + + /** + * Overrides desired favicon size for testing. + * @param desiredFaviconSizePx Desired favicon size in pixels. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + void setDesiredFaviconSizeForTesting(int desiredFaviconSizePx) { + mDesiredFaviconWidthPx = desiredFaviconSizePx; + } +}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java new file mode 100644 index 0000000..e7a86091 --- /dev/null +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/FaviconFetcherUnitTest.java
@@ -0,0 +1,276 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.omnibox.suggestions; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import android.graphics.Bitmap; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.Px; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLog; +import org.robolectric.shadows.ShadowLooper; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconFetchCompleteListener; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconType; +import org.chromium.components.browser_ui.widget.RoundedIconGenerator; +import org.chromium.components.favicon.LargeIconBridge; +import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback; +import org.chromium.url.GURL; +import org.chromium.url.JUnitTestGURLs; + +/** + * Tests for {@link FaviconFetcher}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowLooper.class}) +public final class FaviconFetcherUnitTest { + private static final GURL NAV_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1); + private static final GURL NAV_URL_2 = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_2); + private static final int FALLBACK_COLOR = 0xACE0BA5E; + private static final int REGULAR_FAVICON_SIZE_PX = 100; + private static final int SMALL_FAVICON_SIZE_PX = REGULAR_FAVICON_SIZE_PX / 2; + + public @Rule MockitoRule mockitoRule = MockitoJUnit.rule(); + + private Activity mActivity; + private ArgumentCaptor<LargeIconCallback> mIconCallbackCaptor = + ArgumentCaptor.forClass(LargeIconCallback.class); + + private FaviconFetcher mFetcher; + + private @Mock Bitmap mGeneratedIconBitmap; + private @Mock Bitmap mFavIconBitmap; + private @Mock LargeIconBridge mLargeIconBridge; + private @Mock RoundedIconGenerator mIconGenerator; + private @Mock FaviconFetchCompleteListener mCallback; + + @Before + public void setUp() { + // Enable logs to be printed along with possible test failures. + ShadowLog.stream = System.out; + + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); + + mFetcher = new FaviconFetcher(mActivity, () -> mLargeIconBridge); + mFetcher.setRoundedIconGeneratorForTesting(mIconGenerator); + mFetcher.setDesiredFaviconSizeForTesting(REGULAR_FAVICON_SIZE_PX); + + when(mIconGenerator.generateIconForUrl(any(GURL.class))).thenReturn(mGeneratedIconBitmap); + when(mLargeIconBridge.getLargeIconForUrl(any(), anyInt(), mIconCallbackCaptor.capture())) + .thenReturn(true); + } + + /** + * Confirm that icon of expected size was requested from LargeIconBridge, and report a + * supplied bitmap back to the caller. + * + * @param bitmap The bitmap to return to the caller (may be null). + */ + private void verifyLargeIconBridgeRequest( + @NonNull GURL url, @Px int size, @Nullable Bitmap bitmap) { + ShadowLooper.runUiThreadTasks(); + verify(mLargeIconBridge, times(1)) + .getLargeIconForUrl(eq(url), eq(size), mIconCallbackCaptor.capture()); + mIconCallbackCaptor.getValue().onLargeIconAvailable(bitmap, FALLBACK_COLOR, true, 0); + } + + /** + * Confirm that icon was requested from RoundedIconGenerator, and report a + * supplied bitmap back to the caller. + * + * @param bitmap The bitmap to return to the caller (may be null). + */ + private void verifyRoundedIconRequest(@NonNull GURL url, @Nullable Bitmap bitmap) { + doReturn(bitmap).when(mIconGenerator).generateIconForUrl(eq(url)); + ShadowLooper.runUiThreadTasks(); + verify(mIconGenerator, times(1)).generateIconForUrl(eq(url)); + } + + /** + * Confirm the type of icon reported to the caller. + * + * @param bitmap The expected bitmap. + * @param type The expected favicon type. + */ + private void verifyReturnedIcon(@Nullable Bitmap bitmap, @FaviconType int type) { + verify(mCallback, times(1)).onFaviconFetchComplete(eq(bitmap), eq(type)); + } + + /** + * Confirm no unexpected calls were made to any of our data producers or consumers and + * clear all counters. + */ + private void verifyNoOtherInteractionsAndClearInteractions() { + if (mLargeIconBridge != null) { + verifyNoMoreInteractions(mLargeIconBridge); + clearInvocations(mLargeIconBridge); + } + verifyNoMoreInteractions(mIconGenerator, mCallback); + clearInvocations(mIconGenerator, mCallback); + } + + @Test + public void testIconRetrieval_noLargeIconBridge() { + // Favicon service does not exist, so we should expect a _single_ call to + // RoundedIconGenerator. + mLargeIconBridge = null; + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyRoundedIconRequest(NAV_URL, mGeneratedIconBitmap); + verifyReturnedIcon(mGeneratedIconBitmap, FaviconType.GENERATED); + verifyNoOtherInteractionsAndClearInteractions(); + } + + @Test + public void testIconRetrieval_largeIconAvailableWithNoBackoff() { + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, mFavIconBitmap); + verifyReturnedIcon(mFavIconBitmap, FaviconType.REGULAR); + verifyNoOtherInteractionsAndClearInteractions(); + + // Try again, blocking generated icons. + mFetcher.fetchFaviconWithBackoff(NAV_URL, false, mCallback); + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, mFavIconBitmap); + verifyReturnedIcon(mFavIconBitmap, FaviconType.REGULAR); + verifyNoOtherInteractionsAndClearInteractions(); + } + + @Test + public void testIconRetrieval_backOffToSmallIcon() { + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, null); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, mFavIconBitmap); + verifyReturnedIcon(mFavIconBitmap, FaviconType.SMALL); + verifyNoOtherInteractionsAndClearInteractions(); + + // Try again, blocking generated icons. Observe we go directly for small icon. + mFetcher.fetchFaviconWithBackoff(NAV_URL, false, mCallback); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, mFavIconBitmap); + verifyReturnedIcon(mFavIconBitmap, FaviconType.SMALL); + verifyNoOtherInteractionsAndClearInteractions(); + } + + @Test + public void testIconRetrieval_backOffToGeneratedIcon() { + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, null); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, null); + verifyRoundedIconRequest(NAV_URL, mGeneratedIconBitmap); + verifyReturnedIcon(mGeneratedIconBitmap, FaviconType.GENERATED); + verifyNoOtherInteractionsAndClearInteractions(); + + // Try again, observe we go directly for generated icon. + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyRoundedIconRequest(NAV_URL, mGeneratedIconBitmap); + verifyReturnedIcon(mGeneratedIconBitmap, FaviconType.GENERATED); + verifyNoOtherInteractionsAndClearInteractions(); + } + + @Test + public void testIconRetrieval_backOffWithNoGeneratedIcons() { + mFetcher.fetchFaviconWithBackoff(NAV_URL, false, mCallback); + + // Expect _no_ calls to icon generator. + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, null); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, null); + verifyReturnedIcon(null, FaviconType.NONE); + verifyNoOtherInteractionsAndClearInteractions(); + + // Try again, allowing generated icons. Observe we go directly for generated icon. + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyRoundedIconRequest(NAV_URL, mGeneratedIconBitmap); + verifyReturnedIcon(mGeneratedIconBitmap, FaviconType.GENERATED); + verifyNoOtherInteractionsAndClearInteractions(); + + // Try again, rejecting generated icons. Observe we go directly for generated icon. + mFetcher.fetchFaviconWithBackoff(NAV_URL, false, mCallback); + verifyReturnedIcon(null, FaviconType.NONE); + verifyNoOtherInteractionsAndClearInteractions(); + } + + @Test + public void testIconRetrieval_nullBitmapWhenAllMechanismFail() { + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, null); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, null); + verifyRoundedIconRequest(NAV_URL, null); + verifyReturnedIcon(null, FaviconType.NONE); + verifyNoOtherInteractionsAndClearInteractions(); + + // Note: re-trying with no generated icons should result with immediate stop. + mFetcher.fetchFaviconWithBackoff(NAV_URL, false, mCallback); + verifyReturnedIcon(null, FaviconType.NONE); + verifyNoOtherInteractionsAndClearInteractions(); + } + + @Test + public void testIconRetrieval_differentUrlsDontCollide() { + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, null); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, null); + verifyRoundedIconRequest(NAV_URL, mGeneratedIconBitmap); + verifyReturnedIcon(mGeneratedIconBitmap, FaviconType.GENERATED); + verifyNoOtherInteractionsAndClearInteractions(); + + // Try another URL and confirm we're looking for a regular icon first. + mFetcher.fetchFaviconWithBackoff(NAV_URL_2, true, mCallback); + verifyLargeIconBridgeRequest(NAV_URL_2, REGULAR_FAVICON_SIZE_PX, mFavIconBitmap); + verifyReturnedIcon(mFavIconBitmap, FaviconType.REGULAR); + verifyNoOtherInteractionsAndClearInteractions(); + + // Try the previous URL again and see we already fall back to generated icon. + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyRoundedIconRequest(NAV_URL, mGeneratedIconBitmap); + verifyReturnedIcon(mGeneratedIconBitmap, FaviconType.GENERATED); + verifyNoOtherInteractionsAndClearInteractions(); + } + + @Test + public void testIconRetrieval_clearingCacheRestartsEntireFlow() { + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, null); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, null); + verifyRoundedIconRequest(NAV_URL, null); + verifyReturnedIcon(null, FaviconType.NONE); + verifyNoOtherInteractionsAndClearInteractions(); + + mFetcher.clearCache(); + + // Retry. Expect the exact same flow with that same URL. + mFetcher.fetchFaviconWithBackoff(NAV_URL, true, mCallback); + verifyLargeIconBridgeRequest(NAV_URL, REGULAR_FAVICON_SIZE_PX, null); + verifyLargeIconBridgeRequest(NAV_URL, SMALL_FAVICON_SIZE_PX, null); + verifyRoundedIconRequest(NAV_URL, null); + verifyReturnedIcon(null, FaviconType.NONE); + verifyNoOtherInteractionsAndClearInteractions(); + } +}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java index fb8133c..4e4b8e5 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
@@ -45,7 +45,7 @@ public AnswerSuggestionProcessor(Context context, SuggestionHost suggestionHost, UrlBarEditingTextStateProvider editingTextProvider, Supplier<ImageFetcher> imageFetcherSupplier) { - super(context, suggestionHost); + super(context, suggestionHost, null); mSuggestionHost = suggestionHost; mPendingAnswerRequestUrls = new HashMap<>(); mUrlBarEditingTextProvider = editingTextProvider;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java similarity index 93% rename from chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java index aea7307..78a95e7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java
@@ -12,7 +12,6 @@ import static org.mockito.Mockito.when; import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.text.Spannable; @@ -21,17 +20,18 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.annotation.Config; import org.chromium.base.Callback; import org.chromium.base.ContextUtils; -import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.base.test.UiThreadTest; -import org.chromium.base.test.util.Batch; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; @@ -47,33 +47,30 @@ import org.chromium.components.omnibox.SuggestionAnswer; import org.chromium.components.omnibox.SuggestionAnswer.ImageLine; import org.chromium.components.omnibox.SuggestionAnswer.TextField; -import org.chromium.content_public.browser.test.NativeLibraryTestUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; +import org.chromium.url.ShadowGURL; import java.util.Arrays; /** * Tests for {@link AnswerSuggestionProcessor}. */ -@RunWith(BaseJUnit4ClassRunner.class) -@Batch(Batch.UNIT_TESTS) +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowGURL.class}) public class AnswerSuggestionProcessorUnitTest { private static final @AnswerType int ANSWER_TYPES[] = {AnswerType.DICTIONARY, AnswerType.FINANCE, AnswerType.KNOWLEDGE_GRAPH, AnswerType.SPORTS, AnswerType.SUNRISE, AnswerType.TRANSLATION, AnswerType.WEATHER, AnswerType.WHEN_IS, AnswerType.CURRENCY}; - @Mock - SuggestionHost mSuggestionHost; + public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule(); - @Mock - UrlBarEditingTextStateProvider mUrlStateProvider; + private @Mock SuggestionHost mSuggestionHost; + private @Mock UrlBarEditingTextStateProvider mUrlStateProvider; + private @Mock ImageFetcher mImageFetcher; + private @Mock Bitmap mBitmap; - @Mock - ImageFetcher mImageFetcher; - - private Bitmap mBitmap; private AnswerSuggestionProcessor mProcessor; /** @@ -170,17 +167,8 @@ /* additionalText */ null, /* statusText */ null, url); } - public AnswerSuggestionProcessorUnitTest() { - // SetUp runs on the UI thread because we're using UiThreadTestRule, so do native library - // loading here, which happens on the Instrumentation thread. - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - } - @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mBitmap = Bitmap.createBitmap(1, 1, Config.ALPHA_8); - mProcessor = new AnswerSuggestionProcessor(ContextUtils.getApplicationContext(), mSuggestionHost, mUrlStateProvider, () -> mImageFetcher); } @@ -202,7 +190,6 @@ @Test @SmallTest - @UiThreadTest public void regularAnswer_order() { final SuggestionTestHelper suggHelper = createAnswerSuggestion(AnswerType.KNOWLEDGE_GRAPH, "Query", 1, "Answer", 1, null); @@ -216,7 +203,6 @@ @Test @SmallTest - @UiThreadTest public void dictionaryAnswer_order() { final SuggestionTestHelper suggHelper = createAnswerSuggestion(AnswerType.DICTIONARY, "Query", 1, "Answer", 1, null); @@ -229,7 +215,6 @@ @Test @SmallTest - @UiThreadTest public void calculationAnswer_order() { final SuggestionTestHelper suggHelper = createCalculationSuggestion("12345", "123 + 45"); processSuggestion(suggHelper); @@ -240,7 +225,6 @@ @Test @SmallTest - @UiThreadTest public void regularAnswer_shortMultiline() { final SuggestionTestHelper suggHelper = createAnswerSuggestion(AnswerType.KNOWLEDGE_GRAPH, "", 1, "", 3, null); @@ -252,7 +236,6 @@ @Test @SmallTest - @UiThreadTest public void dictionaryAnswer_shortMultiline() { final SuggestionTestHelper suggHelper = createAnswerSuggestion(AnswerType.DICTIONARY, "", 1, "", 3, null); @@ -266,7 +249,6 @@ // Check that multiline titles are truncated to a single line. @Test @SmallTest - @UiThreadTest public void regularAnswer_truncatedMultiline() { final SuggestionTestHelper suggHelper = createAnswerSuggestion(AnswerType.KNOWLEDGE_GRAPH, "", 3, "", 10, null); @@ -278,7 +260,6 @@ @Test @SmallTest - @UiThreadTest public void dictionaryAnswer_truncatedMultiline() { final SuggestionTestHelper suggHelper = createAnswerSuggestion(AnswerType.DICTIONARY, "", 3, "", 10, null); @@ -291,7 +272,6 @@ // Image fetching and icon association tests. @Test @SmallTest - @UiThreadTest public void answerImage_fallbackIcons() { for (@AnswerType int type : ANSWER_TYPES) { SuggestionTestHelper suggHelper = createAnswerSuggestion(type, "", 1, "", 1, null); @@ -303,7 +283,6 @@ @Test @SmallTest - @UiThreadTest public void answerImage_iconAssociation() { SuggestionTestHelper suggHelper = createAnswerSuggestion(AnswerType.DICTIONARY, "", 1, "", 1, null); @@ -349,7 +328,6 @@ @Test @SmallTest - @UiThreadTest public void answerImage_repeatedUrlsAreFetchedOnlyOnce() { final String url1 = "http://site1.com"; final String url2 = "http://site2.com"; @@ -373,7 +351,6 @@ @Test @SmallTest - @UiThreadTest public void answerImage_bitmapReplacesIconForAllSuggestionsWithSameUrl() { final String url = "http://site.com"; final SuggestionTestHelper sugg1 = @@ -413,7 +390,6 @@ @Test @SmallTest - @UiThreadTest public void answerImage_failedBitmapFetchDoesNotClearIcons() { final String url = "http://site.com"; final ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); @@ -433,7 +409,6 @@ @Test @SmallTest - @UiThreadTest public void answerImage_noImageFetchWhenFetcherIsUnavailable() { final String url = "http://site.com"; mImageFetcher = null; @@ -445,7 +420,6 @@ @Test @SmallTest - @UiThreadTest public void answerImage_associatedModelsAreErasedFromPendingListAfterImageFetch() { ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); final String url = "http://site1.com";
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java index 2579766..b07be211 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.omnibox.suggestions.base; import android.content.Context; -import android.graphics.Bitmap; import android.graphics.Typeface; import android.text.Spannable; import android.text.style.StyleSpan; @@ -16,10 +15,10 @@ import org.chromium.chrome.browser.omnibox.MatchClassificationStyle; import org.chromium.chrome.browser.omnibox.R; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatch.MatchClassification; import org.chromium.ui.modelutil.PropertyModel; @@ -32,8 +31,9 @@ * A class that handles base properties and model for most suggestions. */ public abstract class BaseSuggestionViewProcessor implements SuggestionProcessor { - private final Context mContext; - private final SuggestionHost mSuggestionHost; + private final @NonNull Context mContext; + private final @NonNull SuggestionHost mSuggestionHost; + private final @Nullable FaviconFetcher mFaviconFetcher; private final int mDesiredFaviconWidthPx; private final int mDecorationImageSizePx; private final int mSuggestionSizePx; @@ -41,8 +41,10 @@ /** * @param context Current context. * @param host A handle to the object using the suggestions. + * @param faviconFetcher A mechanism to use to retrieve favicons. */ - public BaseSuggestionViewProcessor(Context context, SuggestionHost host) { + public BaseSuggestionViewProcessor(@NonNull Context context, @NonNull SuggestionHost host, + @Nullable FaviconFetcher faviconFetcher) { mContext = context; mSuggestionHost = host; mDesiredFaviconWidthPx = mContext.getResources().getDimensionPixelSize( @@ -51,6 +53,7 @@ R.dimen.omnibox_suggestion_decoration_image_size); mSuggestionSizePx = mContext.getResources().getDimensionPixelSize( R.dimen.omnibox_suggestion_semicompact_height); + mFaviconFetcher = faviconFetcher; } /** @@ -201,24 +204,15 @@ * * @param model Model representing current suggestion. * @param url Target URL the suggestion points to. - * @param iconBridge A {@link LargeIconBridge} supplies site favicons. - * @param onIconFetched Optional callback that will be invoked after successful fetch of a - * favicon. */ - protected void fetchSuggestionFavicon(PropertyModel model, GURL url, LargeIconBridge iconBridge, - @Nullable Runnable onIconFetched) { - if (url == null || iconBridge == null) return; - - iconBridge.getLargeIconForUrl(url, mDesiredFaviconWidthPx, - (Bitmap icon, int fallbackColor, boolean isFallbackColorDefault, int iconType) -> { - if (icon == null) return; - - setSuggestionDrawableState(model, - SuggestionDrawableState.Builder.forBitmap(mContext, icon).build()); - if (onIconFetched != null) { - onIconFetched.run(); - } - }); + protected void fetchSuggestionFavicon(PropertyModel model, GURL url) { + assert mFaviconFetcher != null : "You must supply the FaviconFetcher in order to use it"; + mFaviconFetcher.fetchFaviconWithBackoff(url, false, (icon, type) -> { + if (icon != null) { + setSuggestionDrawableState( + model, SuggestionDrawableState.Builder.forBitmap(mContext, icon).build()); + } + }); } /**
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java index af599e7d..71ecdce 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java
@@ -10,19 +10,17 @@ import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.omnibox.MatchClassificationStyle; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.R; import org.chromium.chrome.browser.omnibox.UrlBarData; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProcessor; import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionDrawableState; import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable; -import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionIcon; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; @@ -41,9 +39,7 @@ boolean isBookmarked(GURL url); } private final @NonNull UrlBarEditingTextStateProvider mUrlBarEditingTextProvider; - private final @NonNull Supplier<LargeIconBridge> mIconBridgeSupplier; private final @NonNull BookmarkState mBookmarkState; - private final int mDesiredFaviconWidthPx; /** * @param context An Android context. @@ -55,14 +51,10 @@ public BasicSuggestionProcessor(@NonNull Context context, @NonNull SuggestionHost suggestionHost, @NonNull UrlBarEditingTextStateProvider editingTextProvider, - @NonNull Supplier<LargeIconBridge> iconBridgeSupplier, - @NonNull BookmarkState bookmarkState) { - super(context, suggestionHost); + @NonNull FaviconFetcher faviconFetcher, @NonNull BookmarkState bookmarkState) { + super(context, suggestionHost, faviconFetcher); - mDesiredFaviconWidthPx = getContext().getResources().getDimensionPixelSize( - R.dimen.omnibox_suggestion_favicon_size); mUrlBarEditingTextProvider = editingTextProvider; - mIconBridgeSupplier = iconBridgeSupplier; mBookmarkState = bookmarkState; } @@ -88,74 +80,31 @@ * Note that the stock icons do not include Favicon - Favicon is only declared * when we know we have a valid and large enough site favicon to present. */ - private @SuggestionIcon int getSuggestionIconType(AutocompleteMatch suggestion) { + private @DrawableRes int getSuggestionIcon(AutocompleteMatch suggestion) { if (suggestion.isSearchSuggestion()) { switch (suggestion.getType()) { case OmniboxSuggestionType.VOICE_SUGGEST: - return SuggestionIcon.VOICE; + return R.drawable.btn_mic; case OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED: case OmniboxSuggestionType.SEARCH_HISTORY: - return SuggestionIcon.HISTORY; + return R.drawable.ic_history_googblue_24dp; default: if (suggestion.getSubtypes().contains(/* SUBTYPE_TRENDS = */ 143)) { - return SuggestionIcon.TRENDS; + return R.drawable.trending_up_black_24dp; } - return SuggestionIcon.MAGNIFIER; + return R.drawable.ic_suggestion_magnifier; } } else { if (mBookmarkState.isBookmarked(suggestion.getUrl())) { - return SuggestionIcon.BOOKMARK; + return R.drawable.btn_star; } else { - return SuggestionIcon.GLOBE; + return R.drawable.ic_globe_24dp; } } } - private void updateSuggestionIcon(AutocompleteMatch suggestion, PropertyModel model) { - @SuggestionIcon - int type = getSuggestionIconType(suggestion); - @DrawableRes - int icon = R.drawable.ic_suggestion_magnifier; - - switch (type) { - case SuggestionIcon.BOOKMARK: - icon = R.drawable.btn_star; - break; - - case SuggestionIcon.HISTORY: - icon = R.drawable.ic_history_googblue_24dp; - break; - - case SuggestionIcon.GLOBE: - icon = R.drawable.ic_globe_24dp; - break; - - case SuggestionIcon.MAGNIFIER: - icon = R.drawable.ic_suggestion_magnifier; - break; - - case SuggestionIcon.VOICE: - icon = R.drawable.btn_mic; - break; - - case SuggestionIcon.TRENDS: - icon = R.drawable.trending_up_black_24dp; - break; - - default: - // All other cases are invalid. - assert false : "Suggestion type " + type + " is not valid."; - } - - model.set(SuggestionViewProperties.SUGGESTION_ICON_TYPE, type); - setSuggestionDrawableState(model, - SuggestionDrawableState.Builder.forDrawableRes(getContext(), icon) - .setAllowTint(true) - .build()); - } - @Override public void populateModel(AutocompleteMatch suggestion, PropertyModel model, int position) { super.populateModel(suggestion, model, position); @@ -179,13 +128,16 @@ final SuggestionSpannable textLine1 = getSuggestedQuery(suggestion, !isSearchSuggestion, !urlHighlighted); - updateSuggestionIcon(suggestion, model); + setSuggestionDrawableState(model, + SuggestionDrawableState.Builder + .forDrawableRes(getContext(), getSuggestionIcon(suggestion)) + .setAllowTint(true) + .build()); + model.set(SuggestionViewProperties.IS_SEARCH_SUGGESTION, isSearchSuggestion); model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT, textLine1); model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT, textLine2); - fetchSuggestionFavicon(model, suggestion.getUrl(), mIconBridgeSupplier.get(), () -> { - model.set(SuggestionViewProperties.SUGGESTION_ICON_TYPE, SuggestionIcon.FAVICON); - }); + fetchSuggestionFavicon(model, suggestion.getUrl()); model.set(SuggestionViewProperties.ALLOW_WRAP_AROUND, isSearchSuggestion); if (!mUrlBarEditingTextProvider.getTextWithoutAutocomplete().trim().equalsIgnoreCase(
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java index e78ca074..70a75e3 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java
@@ -4,14 +4,15 @@ package org.chromium.chrome.browser.omnibox.suggestions.basic; -import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; +import static org.robolectric.Shadows.shadowOf; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; +import androidx.annotation.DrawableRes; import androidx.test.filters.SmallTest; import org.junit.Assert; @@ -28,17 +29,17 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; +import org.chromium.chrome.browser.omnibox.R; import org.chromium.chrome.browser.omnibox.ShadowUrlBarData; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconFetchCompleteListener; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties; import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionDrawableState; -import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties.SuggestionIcon; import org.chromium.chrome.test.util.browser.Features; -import org.chromium.components.favicon.LargeIconBridge; -import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; import org.chromium.ui.modelutil.PropertyModel; @@ -58,19 +59,24 @@ public class BasicSuggestionProcessorUnitTest { private static final GURL EXTERNAL_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1); private static final GURL INTERNAL_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.NTP_URL); + private static final @DrawableRes int ICON_BOOKMARK = R.drawable.btn_star; + private static final @DrawableRes int ICON_GLOBE = R.drawable.ic_globe_24dp; + private static final @DrawableRes int ICON_HISTORY = R.drawable.ic_history_googblue_24dp; + private static final @DrawableRes int ICON_MAGNIFIER = R.drawable.ic_suggestion_magnifier; + private static final @DrawableRes int ICON_TRENDS = R.drawable.trending_up_black_24dp; + private static final @DrawableRes int ICON_VOICE = R.drawable.btn_mic; + private static final @DrawableRes int ICON_FAVICON = 0; // Favicons do not come from resources. - private static final Map<Integer, String> ICON_TYPE_NAMES = - new HashMap<Integer, String>(SuggestionIcon.TOTAL_COUNT) { - { - put(SuggestionIcon.UNSET, "UNSET"); - put(SuggestionIcon.BOOKMARK, "BOOKMARK"); - put(SuggestionIcon.HISTORY, "HISTORY"); - put(SuggestionIcon.GLOBE, "GLOBE"); - put(SuggestionIcon.MAGNIFIER, "MAGNIFIER"); - put(SuggestionIcon.VOICE, "VOICE"); - put(SuggestionIcon.FAVICON, "FAVICON"); - } - }; + private static final Map<Integer, String> ICON_TYPE_NAMES = new HashMap<Integer, String>() { + { + put(ICON_BOOKMARK, "BOOKMARK"); + put(ICON_HISTORY, "HISTORY"); + put(ICON_GLOBE, "GLOBE"); + put(ICON_MAGNIFIER, "MAGNIFIER"); + put(ICON_VOICE, "VOICE"); + put(ICON_FAVICON, "FAVICON"); + } + }; private static final Map<Integer, String> SUGGESTION_TYPE_NAMES = new HashMap<Integer, String>( OmniboxSuggestionType.NUM_TYPES) { @@ -101,9 +107,9 @@ public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule(); private @Mock SuggestionHost mSuggestionHost; - private @Mock LargeIconBridge mIconBridge; private @Mock UrlBarEditingTextStateProvider mUrlBarText; private @Mock Bitmap mBitmap; + private @Mock FaviconFetcher mIconFetcher; private BasicSuggestionProcessor mProcessor; private AutocompleteMatch mSuggestion; @@ -124,7 +130,7 @@ public void setUp() { doReturn("").when(mUrlBarText).getTextWithoutAutocomplete(); mProcessor = new BasicSuggestionProcessor(ContextUtils.getApplicationContext(), - mSuggestionHost, mUrlBarText, () -> mIconBridge, mIsBookmarked); + mSuggestionHost, mUrlBarText, mIconFetcher, mIsBookmarked); } /** @@ -162,35 +168,37 @@ } private void assertSuggestionTypeAndIcon( - @OmniboxSuggestionType int expectedType, @SuggestionIcon int expectedIcon) { - int actualIcon = mModel.get(SuggestionViewProperties.SUGGESTION_ICON_TYPE); + @OmniboxSuggestionType int expectedType, @DrawableRes int expectedIconRes) { + SuggestionDrawableState sds = mModel.get(BaseSuggestionViewProperties.ICON); + @DrawableRes + int actualIconRes = shadowOf(sds.drawable).getCreatedFromResId(); Assert.assertEquals( String.format("%s: Want Icon %s, Got %s", SUGGESTION_TYPE_NAMES.get(expectedType), - ICON_TYPE_NAMES.get(expectedIcon), ICON_TYPE_NAMES.get(actualIcon)), - expectedIcon, actualIcon); + ICON_TYPE_NAMES.get(expectedIconRes), ICON_TYPE_NAMES.get(actualIconRes)), + expectedIconRes, actualIconRes); } @Test @SmallTest public void getSuggestionIconTypeForSearch_Default() { int[][] testCases = { - {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.HISTORY_URL, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.HISTORY_TITLE, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.HISTORY_BODY, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.HISTORY_KEYWORD, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.NAVSUGGEST, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.SEARCH_HISTORY, SuggestionIcon.HISTORY}, - {OmniboxSuggestionType.SEARCH_SUGGEST, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, SuggestionIcon.HISTORY}, - {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.MAGNIFIER}, - {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.VOICE}, - {OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.MAGNIFIER}, + {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ICON_MAGNIFIER}, + {OmniboxSuggestionType.HISTORY_URL, ICON_MAGNIFIER}, + {OmniboxSuggestionType.HISTORY_TITLE, ICON_MAGNIFIER}, + {OmniboxSuggestionType.HISTORY_BODY, ICON_MAGNIFIER}, + {OmniboxSuggestionType.HISTORY_KEYWORD, ICON_MAGNIFIER}, + {OmniboxSuggestionType.NAVSUGGEST, ICON_MAGNIFIER}, + {OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, ICON_MAGNIFIER}, + {OmniboxSuggestionType.SEARCH_HISTORY, ICON_HISTORY}, + {OmniboxSuggestionType.SEARCH_SUGGEST, ICON_MAGNIFIER}, + {OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, ICON_MAGNIFIER}, + {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, ICON_MAGNIFIER}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, ICON_HISTORY}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, ICON_MAGNIFIER}, + {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, ICON_MAGNIFIER}, + {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, ICON_MAGNIFIER}, + {OmniboxSuggestionType.VOICE_SUGGEST, ICON_VOICE}, + {OmniboxSuggestionType.DOCUMENT_SUGGESTION, ICON_MAGNIFIER}, }; mProcessor.onNativeInitialized(); @@ -205,23 +213,23 @@ @SmallTest public void getSuggestionIconTypeForUrl_Default() { int[][] testCases = { - {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.HISTORY_URL, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.HISTORY_TITLE, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.HISTORY_BODY, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.HISTORY_KEYWORD, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.NAVSUGGEST, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_HISTORY, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_SUGGEST, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.GLOBE}, - {OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.GLOBE}, + {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ICON_GLOBE}, + {OmniboxSuggestionType.HISTORY_URL, ICON_GLOBE}, + {OmniboxSuggestionType.HISTORY_TITLE, ICON_GLOBE}, + {OmniboxSuggestionType.HISTORY_BODY, ICON_GLOBE}, + {OmniboxSuggestionType.HISTORY_KEYWORD, ICON_GLOBE}, + {OmniboxSuggestionType.NAVSUGGEST, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_HISTORY, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_SUGGEST, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, ICON_GLOBE}, + {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, ICON_GLOBE}, + {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, ICON_GLOBE}, + {OmniboxSuggestionType.VOICE_SUGGEST, ICON_GLOBE}, + {OmniboxSuggestionType.DOCUMENT_SUGGESTION, ICON_GLOBE}, }; mProcessor.onNativeInitialized(); @@ -236,23 +244,23 @@ @SmallTest public void getSuggestionIconTypeForBookmarks_Default() { int[][] testCases = { - {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.HISTORY_URL, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.HISTORY_TITLE, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.HISTORY_BODY, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.HISTORY_KEYWORD, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.NAVSUGGEST, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_HISTORY, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_SUGGEST, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.BOOKMARK}, - {OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.BOOKMARK}, + {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ICON_BOOKMARK}, + {OmniboxSuggestionType.HISTORY_URL, ICON_BOOKMARK}, + {OmniboxSuggestionType.HISTORY_TITLE, ICON_BOOKMARK}, + {OmniboxSuggestionType.HISTORY_BODY, ICON_BOOKMARK}, + {OmniboxSuggestionType.HISTORY_KEYWORD, ICON_BOOKMARK}, + {OmniboxSuggestionType.NAVSUGGEST, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_HISTORY, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_SUGGEST, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, ICON_BOOKMARK}, + {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, ICON_BOOKMARK}, + {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, ICON_BOOKMARK}, + {OmniboxSuggestionType.VOICE_SUGGEST, ICON_BOOKMARK}, + {OmniboxSuggestionType.DOCUMENT_SUGGESTION, ICON_BOOKMARK}, }; mIsBookmarked.mState = true; @@ -269,12 +277,12 @@ @SmallTest public void getSuggestionIconTypeForTrendingQueries() { int[][] testCases = { - {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, SuggestionIcon.TRENDS}, - {OmniboxSuggestionType.SEARCH_HISTORY, SuggestionIcon.HISTORY}, - {OmniboxSuggestionType.SEARCH_SUGGEST, SuggestionIcon.TRENDS}, - {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, SuggestionIcon.TRENDS}, - {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, SuggestionIcon.HISTORY}, - {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.VOICE}, + {OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ICON_TRENDS}, + {OmniboxSuggestionType.SEARCH_HISTORY, ICON_HISTORY}, + {OmniboxSuggestionType.SEARCH_SUGGEST, ICON_TRENDS}, + {OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, ICON_TRENDS}, + {OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, ICON_HISTORY}, + {OmniboxSuggestionType.VOICE_SUGGEST, ICON_VOICE}, }; mProcessor.onNativeInitialized(); @@ -343,16 +351,16 @@ @Test @SmallTest public void suggestionFavicons_showFaviconWhenAvailable() { - final ArgumentCaptor<LargeIconCallback> callback = - ArgumentCaptor.forClass(LargeIconCallback.class); + final ArgumentCaptor<FaviconFetchCompleteListener> callback = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); mProcessor.onNativeInitialized(); createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ""); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); - verify(mIconBridge) - .getLargeIconForUrl(eq(mSuggestion.getUrl()), anyInt(), callback.capture()); - callback.getValue().onLargeIconAvailable(mBitmap, 0, false, 0); + verify(mIconFetcher) + .fetchFaviconWithBackoff(eq(mSuggestion.getUrl()), eq(false), callback.capture()); + callback.getValue().onFaviconFetchComplete(mBitmap, FaviconType.REGULAR); SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon2); @@ -363,16 +371,16 @@ @Test @SmallTest public void suggestionFavicons_doNotReplaceFallbackIconWhenNoFaviconIsAvailable() { - final ArgumentCaptor<LargeIconCallback> callback = - ArgumentCaptor.forClass(LargeIconCallback.class); + final ArgumentCaptor<FaviconFetchCompleteListener> callback = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); mProcessor.onNativeInitialized(); createUrlSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, ""); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); - verify(mIconBridge) - .getLargeIconForUrl(eq(mSuggestion.getUrl()), anyInt(), callback.capture()); - callback.getValue().onLargeIconAvailable(null, 0, false, 0); + verify(mIconFetcher) + .fetchFaviconWithBackoff(eq(mSuggestion.getUrl()), eq(false), callback.capture()); + callback.getValue().onFaviconFetchComplete(null, FaviconType.NONE); SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon2);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java index a7d807ea..e4fe147 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java
@@ -4,42 +4,17 @@ package org.chromium.chrome.browser.omnibox.suggestions.basic; -import androidx.annotation.IntDef; - import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties; import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey; -import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - /** * The properties associated with rendering the default suggestion view. */ public class SuggestionViewProperties { - @IntDef({SuggestionIcon.UNSET, SuggestionIcon.BOOKMARK, SuggestionIcon.HISTORY, - SuggestionIcon.GLOBE, SuggestionIcon.MAGNIFIER, SuggestionIcon.VOICE, - SuggestionIcon.FAVICON, SuggestionIcon.TRENDS, SuggestionIcon.TOTAL_COUNT}) - @Retention(RetentionPolicy.SOURCE) - public @interface SuggestionIcon { - int UNSET = 0; - int BOOKMARK = 1; - int HISTORY = 2; - int GLOBE = 3; - int MAGNIFIER = 4; - int VOICE = 5; - int FAVICON = 6; - int TRENDS = 7; - int TOTAL_COUNT = 8; - } - - /** The suggestion icon type shown. @see SuggestionIcon. Used for metric collection purposes. */ - public static final WritableIntPropertyKey SUGGESTION_ICON_TYPE = new WritableIntPropertyKey(); - /** Whether suggestion is a search suggestion. */ public static final WritableBooleanPropertyKey IS_SEARCH_SUGGESTION = new WritableBooleanPropertyKey(); @@ -56,8 +31,8 @@ public static final WritableBooleanPropertyKey ALLOW_WRAP_AROUND = new WritableBooleanPropertyKey(); - public static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] {IS_SEARCH_SUGGESTION, - SUGGESTION_ICON_TYPE, TEXT_LINE_1_TEXT, TEXT_LINE_2_TEXT, ALLOW_WRAP_AROUND}; + public static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] { + IS_SEARCH_SUGGESTION, TEXT_LINE_1_TEXT, TEXT_LINE_2_TEXT, ALLOW_WRAP_AROUND}; public static final PropertyKey[] ALL_KEYS = PropertyModel.concatKeys(ALL_UNIQUE_KEYS, BaseSuggestionViewProperties.ALL_KEYS);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java index 71a94209..5ea721a 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java
@@ -13,9 +13,9 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.metrics.RecordUserAction; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.R; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProcessor; @@ -23,7 +23,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionDrawableState; import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.ui.modelutil.PropertyModel; @@ -31,17 +30,14 @@ /** A class that handles model and view creation for the clipboard suggestions. */ public class ClipboardSuggestionProcessor extends BaseSuggestionViewProcessor { - private final Supplier<LargeIconBridge> mIconBridgeSupplier; - /** * @param context An Android context. * @param suggestionHost A handle to the object using the suggestions. - * @param iconBridgeSupplier A {@link LargeIconBridge} supplies site favicons. + * @param faviconFetcher Mechanism used to retrieve favicons. */ - public ClipboardSuggestionProcessor(Context context, SuggestionHost suggestionHost, - Supplier<LargeIconBridge> iconBridgeSupplier) { - super(context, suggestionHost); - mIconBridgeSupplier = iconBridgeSupplier; + public ClipboardSuggestionProcessor( + Context context, SuggestionHost suggestionHost, FaviconFetcher faviconFetcher) { + super(context, suggestionHost, faviconFetcher); } @Override @@ -145,7 +141,7 @@ if (isUrlSuggestion) { // Update favicon for URL if it is available. - fetchSuggestionFavicon(model, suggestion.getUrl(), mIconBridgeSupplier.get(), null); + fetchSuggestionFavicon(model, suggestion.getUrl()); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorUnitTest.java index 6b5aa19..162206c 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorUnitTest.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.omnibox.suggestions.clipboard; -import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.verify; @@ -34,6 +33,9 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconFetchCompleteListener; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties; @@ -41,8 +43,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewViewBinder; -import org.chromium.components.favicon.LargeIconBridge; -import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; import org.chromium.ui.modelutil.PropertyModel; @@ -63,7 +63,7 @@ public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule(); private @Mock SuggestionHost mSuggestionHost; - private @Mock LargeIconBridge mIconBridge; + private @Mock FaviconFetcher mIconFetcher; private @Mock Resources mResources; private Context mContext; @@ -81,7 +81,7 @@ mContext = new ContextThemeWrapper( ContextUtils.getApplicationContext(), R.style.Theme_BrowserUI_DayNight); mBitmap = Bitmap.createBitmap(10, 5, Bitmap.Config.ARGB_8888); - mProcessor = new ClipboardSuggestionProcessor(mContext, mSuggestionHost, () -> mIconBridge); + mProcessor = new ClipboardSuggestionProcessor(mContext, mSuggestionHost, mIconFetcher); mRootView = new LinearLayout(mContext); mTitleTextView = new TextView(mContext); mTitleTextView.setId(R.id.line_1); @@ -149,14 +149,14 @@ @Test @SmallTest public void clipboardSuggestion_showsFaviconWhenAvailable() { - final ArgumentCaptor<LargeIconCallback> callback = - ArgumentCaptor.forClass(LargeIconCallback.class); + final ArgumentCaptor<FaviconFetchCompleteListener> callback = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); createClipboardSuggestionAndClickReveal(OmniboxSuggestionType.CLIPBOARD_URL, TEST_URL); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); - verify(mIconBridge).getLargeIconForUrl(eq(TEST_URL), anyInt(), callback.capture()); - callback.getValue().onLargeIconAvailable(mBitmap, 0, false, 0); + verify(mIconFetcher).fetchFaviconWithBackoff(eq(TEST_URL), eq(false), callback.capture()); + callback.getValue().onFaviconFetchComplete(mBitmap, FaviconType.REGULAR); SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon2); @@ -167,14 +167,14 @@ @Test @SmallTest public void clipboardSuggestion_showsFallbackIconWhenNoFaviconIsAvailable() { - final ArgumentCaptor<LargeIconCallback> callback = - ArgumentCaptor.forClass(LargeIconCallback.class); + final ArgumentCaptor<FaviconFetchCompleteListener> callback = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); createClipboardSuggestionAndClickReveal(OmniboxSuggestionType.CLIPBOARD_URL, TEST_URL); SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon1); - verify(mIconBridge).getLargeIconForUrl(eq(TEST_URL), anyInt(), callback.capture()); - callback.getValue().onLargeIconAvailable(null, 0, false, 0); + verify(mIconFetcher).fetchFaviconWithBackoff(eq(TEST_URL), eq(false), callback.capture()); + callback.getValue().onFaviconFetchComplete(null, FaviconType.NONE); SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON); Assert.assertNotNull(icon2); @@ -184,13 +184,13 @@ @Test @SmallTest public void clipobardSuggestion_urlAndTextDirection() { - final ArgumentCaptor<LargeIconCallback> callback = - ArgumentCaptor.forClass(LargeIconCallback.class); + final ArgumentCaptor<FaviconFetchCompleteListener> callback = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); // URL createClipboardSuggestionAndClickReveal(OmniboxSuggestionType.CLIPBOARD_URL, TEST_URL); Assert.assertFalse(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION)); - verify(mIconBridge).getLargeIconForUrl(eq(TEST_URL), anyInt(), callback.capture()); - callback.getValue().onLargeIconAvailable(null, 0, false, 0); + verify(mIconFetcher).fetchFaviconWithBackoff(eq(TEST_URL), eq(false), callback.capture()); + callback.getValue().onFaviconFetchComplete(null, FaviconType.NONE); Assert.assertEquals(TextView.TEXT_DIRECTION_LTR, mLastSetTextDirection); // Text
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java index 7e273415..005283b 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
@@ -11,6 +11,7 @@ import org.chromium.chrome.browser.history_clusters.HistoryClustersTabHelper; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.R; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.UrlBarDelegate; @@ -23,7 +24,6 @@ import org.chromium.chrome.browser.share.ShareDelegate.ShareOrigin; import org.chromium.chrome.browser.tab.SadTab; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.ukm.UkmRecorder; import org.chromium.ui.base.Clipboard; @@ -42,9 +42,6 @@ /** The delegate for accessing the location bar for observation and modification. */ private final UrlBarDelegate mUrlBarDelegate; - /** Supplies site favicons. */ - private final Supplier<LargeIconBridge> mIconBridgeSupplier; - /** The delegate for accessing the sharing feature. */ private final Supplier<ShareDelegate> mShareDelegateSupplier; @@ -58,13 +55,12 @@ * @param locationBarDelegate A means of modifying the location bar. */ public EditUrlSuggestionProcessor(Context context, SuggestionHost suggestionHost, - UrlBarDelegate locationBarDelegate, Supplier<LargeIconBridge> iconBridgeSupplier, + UrlBarDelegate locationBarDelegate, FaviconFetcher faviconFetcher, Supplier<Tab> tabSupplier, Supplier<ShareDelegate> shareDelegateSupplier) { - super(context, suggestionHost); + super(context, suggestionHost, faviconFetcher); mContext = context; mUrlBarDelegate = locationBarDelegate; - mIconBridgeSupplier = iconBridgeSupplier; mTabSupplier = tabSupplier; mShareDelegateSupplier = shareDelegateSupplier; } @@ -145,7 +141,7 @@ .build(), R.string.bookmark_item_edit, () -> onEditLink(suggestion)))); - fetchSuggestionFavicon(model, suggestion.getUrl(), mIconBridgeSupplier.get(), null); + fetchSuggestionFavicon(model, suggestion.getUrl()); } @Override
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java index 18e5a90..69cc7ec 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessor.java
@@ -54,7 +54,7 @@ */ public EntitySuggestionProcessor(Context context, SuggestionHost suggestionHost, Supplier<ImageFetcher> imageFetcherSupplier) { - super(context, suggestionHost); + super(context, suggestionHost, null); mSuggestionHost = suggestionHost; mPendingImageRequests = new HashMap<>(); mImageFetcherSupplier = imageFetcherSupplier;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java similarity index 81% rename from chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java rename to chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java index 8bd979eb..dae972a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java
@@ -10,7 +10,6 @@ import static org.mockito.Mockito.verify; import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; @@ -20,18 +19,19 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.annotation.Config; import org.chromium.base.BaseSwitches; import org.chromium.base.Callback; import org.chromium.base.ContextUtils; -import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.base.test.UiThreadTest; -import org.chromium.base.test.util.Batch; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; @@ -40,24 +40,28 @@ import org.chromium.components.image_fetcher.ImageFetcher; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; -import org.chromium.content_public.browser.test.NativeLibraryTestUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; +import org.chromium.url.JUnitTestGURLs; +import org.chromium.url.ShadowGURL; /** * Tests for {@link EntitySuggestionProcessor}. */ -@RunWith(BaseJUnit4ClassRunner.class) -@Batch(Batch.UNIT_TESTS) +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowGURL.class}) @CommandLineFlags.Add(BaseSwitches.DISABLE_LOW_END_DEVICE_MODE) public class EntitySuggestionProcessorUnitTest { - @Mock - SuggestionHost mSuggestionHost; + private static final GURL WEB_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_1); + private static final GURL WEB_URL_2 = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_2); + private static final GURL SEARCH_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.SEARCH_URL); - @Mock - ImageFetcher mImageFetcher; + public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule(); - private Bitmap mBitmap; + private @Mock SuggestionHost mSuggestionHost; + private @Mock ImageFetcher mImageFetcher; + private @Mock Bitmap mBitmap; + private EntitySuggestionProcessor mProcessor; /** @@ -103,11 +107,6 @@ @Before public void setUp() { - MockitoAnnotations.initMocks(this); - NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess(); - - mBitmap = Bitmap.createBitmap(1, 1, Config.ALPHA_8); - mProcessor = new EntitySuggestionProcessor( ContextUtils.getApplicationContext(), mSuggestionHost, () -> mImageFetcher); } @@ -118,10 +117,8 @@ @Test @SmallTest - @UiThreadTest public void contentTest_basicContent() { - SuggestionTestHelper suggHelper = - createSuggestion("subject", "details", null, GURL.emptyGURL()); + SuggestionTestHelper suggHelper = createSuggestion("subject", "details", null, SEARCH_URL); processSuggestion(suggHelper); Assert.assertEquals( "subject", suggHelper.mModel.get(EntitySuggestionViewProperties.SUBJECT_TEXT)); @@ -131,9 +128,8 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_noColorOrImage() { - SuggestionTestHelper suggHelper = createSuggestion("", "", null, GURL.emptyGURL()); + SuggestionTestHelper suggHelper = createSuggestion("", "", null, SEARCH_URL); processSuggestion(suggHelper); Assert.assertNotNull(suggHelper.getIcon()); @@ -142,9 +138,8 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_validHexColor() { - SuggestionTestHelper suggHelper = createSuggestion("", "", "#fedcba", GURL.emptyGURL()); + SuggestionTestHelper suggHelper = createSuggestion("", "", "#fedcba", SEARCH_URL); processSuggestion(suggHelper); Assert.assertThat(suggHelper.getIcon(), instanceOf(ColorDrawable.class)); @@ -154,9 +149,8 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_validNamedColor() { - SuggestionTestHelper suggHelper = createSuggestion("", "", "red", GURL.emptyGURL()); + SuggestionTestHelper suggHelper = createSuggestion("", "", "red", SEARCH_URL); processSuggestion(suggHelper); Assert.assertThat(suggHelper.getIcon(), instanceOf(ColorDrawable.class)); @@ -166,32 +160,29 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_invalidColor() { // Note, fallback is the bitmap drawable representing a search loupe. - SuggestionTestHelper suggHelper = createSuggestion("", "", "", GURL.emptyGURL()); + SuggestionTestHelper suggHelper = createSuggestion("", "", "", SEARCH_URL); processSuggestion(suggHelper); Assert.assertThat(suggHelper.getIcon(), instanceOf(BitmapDrawable.class)); - suggHelper = createSuggestion("", "", "#", GURL.emptyGURL()); + suggHelper = createSuggestion("", "", "#", SEARCH_URL); processSuggestion(suggHelper); Assert.assertThat(suggHelper.getIcon(), instanceOf(BitmapDrawable.class)); - suggHelper = createSuggestion("", "", "invalid", GURL.emptyGURL()); + suggHelper = createSuggestion("", "", "invalid", SEARCH_URL); processSuggestion(suggHelper); Assert.assertThat(suggHelper.getIcon(), instanceOf(BitmapDrawable.class)); } @Test @SmallTest - @UiThreadTest public void decorationTest_basicSuccessfulBitmapFetch() { - final GURL url = new GURL("http://site.com"); - SuggestionTestHelper suggHelper = createSuggestion("", "", "red", url); + SuggestionTestHelper suggHelper = createSuggestion("", "", "red", WEB_URL); processSuggestion(suggHelper); final ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); - verify(mImageFetcher).fetchImage(eq(createParams(url.getSpec())), callback.capture()); + verify(mImageFetcher).fetchImage(eq(createParams(WEB_URL.getSpec())), callback.capture()); Assert.assertThat(suggHelper.getIcon(), instanceOf(ColorDrawable.class)); callback.getValue().onResult(mBitmap); @@ -201,39 +192,34 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_repeatedUrlsAreFetchedOnlyOnce() { - final GURL url1 = new GURL("http://site1.com"); - final GURL url2 = new GURL("http://site2.com"); - final SuggestionTestHelper sugg1 = createSuggestion("", "", "", url1); - final SuggestionTestHelper sugg2 = createSuggestion("", "", "", url1); - final SuggestionTestHelper sugg3 = createSuggestion("", "", "", url2); - final SuggestionTestHelper sugg4 = createSuggestion("", "", "", url2); + final SuggestionTestHelper sugg1 = createSuggestion("", "", "", WEB_URL); + final SuggestionTestHelper sugg2 = createSuggestion("", "", "", WEB_URL); + final SuggestionTestHelper sugg3 = createSuggestion("", "", "", WEB_URL_2); + final SuggestionTestHelper sugg4 = createSuggestion("", "", "", WEB_URL_2); processSuggestion(sugg1); processSuggestion(sugg2); processSuggestion(sugg3); processSuggestion(sugg4); - verify(mImageFetcher).fetchImage(eq(createParams(url1.getSpec())), any()); - verify(mImageFetcher).fetchImage(eq(createParams(url2.getSpec())), any()); + verify(mImageFetcher).fetchImage(eq(createParams(WEB_URL.getSpec())), any()); + verify(mImageFetcher).fetchImage(eq(createParams(WEB_URL_2.getSpec())), any()); } @Test @SmallTest - @UiThreadTest public void decorationTest_bitmapReplacesIconForAllSuggestionsWithSameUrl() { - final GURL url = new GURL("http://site.com"); - final SuggestionTestHelper sugg1 = createSuggestion("", "", "", url); - final SuggestionTestHelper sugg2 = createSuggestion("", "", "", url); - final SuggestionTestHelper sugg3 = createSuggestion("", "", "", url); + final SuggestionTestHelper sugg1 = createSuggestion("", "", "", WEB_URL); + final SuggestionTestHelper sugg2 = createSuggestion("", "", "", WEB_URL); + final SuggestionTestHelper sugg3 = createSuggestion("", "", "", WEB_URL); processSuggestion(sugg1); processSuggestion(sugg2); processSuggestion(sugg3); final ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); - verify(mImageFetcher).fetchImage(eq(createParams(url.getSpec())), callback.capture()); + verify(mImageFetcher).fetchImage(eq(createParams(WEB_URL.getSpec())), callback.capture()); final Drawable icon1 = sugg1.getIcon(); final Drawable icon2 = sugg2.getIcon(); @@ -259,14 +245,12 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_failedBitmapFetchDoesNotReplaceIcon() { - final GURL url = new GURL("http://site.com"); - final SuggestionTestHelper suggHelper = createSuggestion("", "", null, url); + final SuggestionTestHelper suggHelper = createSuggestion("", "", null, WEB_URL); processSuggestion(suggHelper); final ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); - verify(mImageFetcher).fetchImage(eq(createParams(url.getSpec())), callback.capture()); + verify(mImageFetcher).fetchImage(eq(createParams(WEB_URL.getSpec())), callback.capture()); final Drawable oldIcon = suggHelper.getIcon(); callback.getValue().onResult(null); @@ -278,14 +262,12 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_failedBitmapFetchDoesNotReplaceColor() { - final GURL url = new GURL("http://site.com"); - final SuggestionTestHelper suggHelper = createSuggestion("", "", "red", url); + final SuggestionTestHelper suggHelper = createSuggestion("", "", "red", WEB_URL); processSuggestion(suggHelper); final ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); - verify(mImageFetcher).fetchImage(eq(createParams(url.getSpec())), callback.capture()); + verify(mImageFetcher).fetchImage(eq(createParams(WEB_URL.getSpec())), callback.capture()); final Drawable oldIcon = suggHelper.getIcon(); callback.getValue().onResult(null); @@ -297,17 +279,15 @@ @Test @SmallTest - @UiThreadTest public void decorationTest_updatedModelsAreRemovedFromPendingRequestsList() { - final GURL url = new GURL("http://site1.com"); - final SuggestionTestHelper sugg1 = createSuggestion("", "", "", url); - final SuggestionTestHelper sugg2 = createSuggestion("", "", "", url); + final SuggestionTestHelper sugg1 = createSuggestion("", "", "", WEB_URL); + final SuggestionTestHelper sugg2 = createSuggestion("", "", "", WEB_URL); processSuggestion(sugg1); processSuggestion(sugg2); final ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); - verify(mImageFetcher).fetchImage(eq(createParams(url.getSpec())), callback.capture()); + verify(mImageFetcher).fetchImage(eq(createParams(WEB_URL.getSpec())), callback.capture()); verify(mImageFetcher).fetchImage(any(), any()); final Drawable icon1 = sugg1.getIcon();
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java index 2b3a888..4b36b543 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessor.java
@@ -5,16 +5,14 @@ package org.chromium.chrome.browser.omnibox.suggestions.mostvisited; import android.content.Context; -import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; -import androidx.annotation.VisibleForTesting; +import androidx.appcompat.content.res.AppCompatResources; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.R; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; @@ -23,10 +21,7 @@ import org.chromium.chrome.browser.omnibox.suggestions.carousel.BaseCarouselSuggestionViewProperties; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.components.browser_ui.styles.ChromeColors; -import org.chromium.components.browser_ui.widget.RoundedIconGenerator; -import org.chromium.components.browser_ui.widget.TintedDrawable; import org.chromium.components.browser_ui.widget.tile.TileViewProperties; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.PropertyModel; @@ -41,36 +36,24 @@ public class MostVisitedTilesProcessor extends BaseCarouselSuggestionProcessor { private final @NonNull Context mContext; private final @NonNull SuggestionHost mSuggestionHost; - private final @NonNull Supplier<LargeIconBridge> mIconBridgeSupplier; + private final @NonNull FaviconFetcher mFaviconFetcher; private final int mMinCarouselItemViewHeight; - private final int mDesiredFaviconWidthPx; - private @NonNull RoundedIconGenerator mIconGenerator; /** * Constructor. * * @param context An Android context. * @param host SuggestionHost receiving notifications about user actions. - * @param iconBridgeSupplier Supplier of the LargeIconBridge used to fetch site favicons. + * @param faviconFetcher Class retrieving favicons for the MV Tiles. */ public MostVisitedTilesProcessor(@NonNull Context context, @NonNull SuggestionHost host, - @NonNull Supplier<LargeIconBridge> iconBridgeSupplier) { + @NonNull FaviconFetcher faviconFetcher) { super(context); mContext = context; mSuggestionHost = host; - mIconBridgeSupplier = iconBridgeSupplier; + mFaviconFetcher = faviconFetcher; mMinCarouselItemViewHeight = mContext.getResources().getDimensionPixelSize(R.dimen.tile_view_min_height); - mDesiredFaviconWidthPx = mContext.getResources().getDimensionPixelSize( - R.dimen.omnibox_suggestion_favicon_size); - - int fallbackIconSize = - mContext.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_size); - int fallbackIconColor = mContext.getColor(R.color.default_favicon_background_color); - int fallbackIconTextSize = - mContext.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_text_size); - mIconGenerator = new RoundedIconGenerator(fallbackIconSize, fallbackIconSize, - fallbackIconSize / 2, fallbackIconColor, fallbackIconTextSize); } @Override @@ -98,7 +81,6 @@ final List<AutocompleteMatch.SuggestTile> tiles = suggestion.getSuggestTiles(); final int tilesCount = tiles.size(); final List<ListItem> tileList = new ArrayList<>(tilesCount); - final LargeIconBridge iconBridge = mIconBridgeSupplier.get(); for (int elementIndex = 0; elementIndex < tilesCount; elementIndex++) { final PropertyModel tileModel = new PropertyModel(TileViewProperties.ALL_KEYS); @@ -119,41 +101,31 @@ }); if (tiles.get(elementIndex).isSearch) { - Drawable drawable = TintedDrawable.constructTintedDrawable( - mContext, R.drawable.ic_suggestion_magnifier); // Note: we should never show most visited tiles in incognito mode. Catch this early // if we ever do. assert model.get(SuggestionCommonProperties.COLOR_SCHEME) != BrandedColorScheme.INCOGNITO; - drawable.setTintList( + tileModel.set(TileViewProperties.ICON_TINT, ChromeColors.getSecondaryIconTint(mContext, /* isIncognito= */ false)); - tileModel.set(TileViewProperties.ICON, drawable); + tileModel.set(TileViewProperties.ICON, + AppCompatResources.getDrawable( + mContext, R.drawable.ic_suggestion_magnifier)); tileModel.set(TileViewProperties.CONTENT_DESCRIPTION, mContext.getString( R.string.accessibility_omnibox_most_visited_tile_search, title)); } else { + tileModel.set(TileViewProperties.ICON_TINT, null); tileModel.set(TileViewProperties.CONTENT_DESCRIPTION, mContext.getString( R.string.accessibility_omnibox_most_visited_tile_navigate, title, url.getHost())); - if (iconBridge != null) { - // TODO(https://crbug.com/1335507): Cache the generated bitmaps. - // This is not needed for the experimentation purposes (this block is currently - // used very infrequently - only to offer zero-prefix URL suggestions on URL - // visit). This must be addressed before MV Carousel can be offered in more - // contexts. Consider unifying cache with LargeIconBridge if possible. - Bitmap fallbackIcon = mIconGenerator.generateIconForUrl(url); - tileModel.set(TileViewProperties.ICON, new BitmapDrawable(fallbackIcon)); - - iconBridge.getLargeIconForUrl(tiles.get(elementIndex).url, - mDesiredFaviconWidthPx, - (Bitmap icon, int fallbackColor, boolean isFallbackColorDefault, - int iconType) -> { - if (icon == null) return; - setIcon(tileModel, icon); - }); - } + tileModel.set(TileViewProperties.SMALL_ICON_ROUNDING_RADIUS, + mContext.getResources().getDimensionPixelSize( + R.dimen.omnibox_carousel_icon_rounding_radius)); + mFaviconFetcher.fetchFaviconWithBackoff(url, true, (icon, type) -> { + tileModel.set(TileViewProperties.ICON, new BitmapDrawable(icon)); + }); } tileList.add(new ListItem( @@ -163,26 +135,4 @@ model.set(BaseCarouselSuggestionViewProperties.TILES, tileList); model.set(BaseCarouselSuggestionViewProperties.SHOW_TITLE, false); } - - /** - * Sets the large icon to the supplied tile's model. - * - * @param tileModel The model for the specific tile view to be modified. - * @param icon The icon to apply. - */ - private void setIcon(@NonNull PropertyModel tileModel, @NonNull Bitmap icon) { - tileModel.set(TileViewProperties.SMALL_ICON_ROUNDING_RADIUS, - mContext.getResources().getDimensionPixelSize( - R.dimen.omnibox_carousel_icon_rounding_radius)); - tileModel.set(TileViewProperties.ICON, new BitmapDrawable(icon)); - } - - /** - * Overrides RoundedIconGenerator for testing. - * @param RoundedIconGenerator Generator to use. - */ - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - void setRoundedIconGeneratorForTesting(@NonNull RoundedIconGenerator generator) { - mIconGenerator = generator; - } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java index a99be51..1cb8ef5 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/mostvisited/MostVisitedTilesProcessorUnitTest.java
@@ -8,13 +8,13 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; import android.app.Activity; @@ -33,16 +33,16 @@ import org.mockito.junit.MockitoRule; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLog; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.R; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher.FaviconFetchCompleteListener; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.carousel.BaseCarouselSuggestionItemViewBuilder; import org.chromium.chrome.browser.omnibox.suggestions.carousel.BaseCarouselSuggestionViewProperties; -import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.components.browser_ui.widget.tile.TileViewProperties; -import org.chromium.components.favicon.LargeIconBridge; -import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatch.SuggestTile; import org.chromium.components.omnibox.AutocompleteMatchBuilder; @@ -64,34 +64,33 @@ private static final GURL NAV_URL_2 = JUnitTestGURLs.getGURL(JUnitTestGURLs.URL_2); private static final GURL SEARCH_URL = JUnitTestGURLs.getGURL(JUnitTestGURLs.SEARCH_URL); private static final int FALLBACK_COLOR = 0xACE0BA5E; + private static final int DESIRED_FAVICON_SIZE_PX = 100; public @Rule MockitoRule mockitoRule = MockitoJUnit.rule(); private Activity mActivity; private PropertyModel mPropertyModel; private MostVisitedTilesProcessor mProcessor; - private ArgumentCaptor<LargeIconCallback> mIconCallbackCaptor = - ArgumentCaptor.forClass(LargeIconCallback.class); private AutocompleteMatch mMatch; + private ArgumentCaptor<FaviconFetchCompleteListener> mIconCallbackCaptor = + ArgumentCaptor.forClass(FaviconFetchCompleteListener.class); + private @Mock Bitmap mFaviconBitmap; private @Mock SuggestionHost mSuggestionHost; - private @Mock LargeIconBridge mLargeIconBridge; - private @Mock RoundedIconGenerator mIconGenerator; - private @Mock Bitmap mGeneratedIconBitmap; - private @Mock Bitmap mLargeIconBitmap; + private @Mock FaviconFetcher mFaviconFetcher; @Before public void setUp() { + // Enable logs to be printed along with possible test failures. + ShadowLog.stream = System.out; mActivity = Robolectric.buildActivity(Activity.class).setup().get(); mActivity.setTheme(R.style.Theme_BrowserUI_DayNight); - mProcessor = - new MostVisitedTilesProcessor(mActivity, mSuggestionHost, () -> mLargeIconBridge); - mProcessor.setRoundedIconGeneratorForTesting(mIconGenerator); - when(mIconGenerator.generateIconForUrl(any(GURL.class))).thenReturn(mGeneratedIconBitmap); - when(mLargeIconBridge.getLargeIconForUrl(any(), anyInt(), mIconCallbackCaptor.capture())) - .thenReturn(true); + doNothing() + .when(mFaviconFetcher) + .fetchFaviconWithBackoff(any(), anyBoolean(), mIconCallbackCaptor.capture()); + mProcessor = new MostVisitedTilesProcessor(mActivity, mSuggestionHost, mFaviconFetcher); mPropertyModel = mProcessor.createModel(); } @@ -111,8 +110,7 @@ public void testDecorations_searchTile() { List<ListItem> tileList = populateTilePropertiesForTiles(0, new SuggestTile("title", SEARCH_URL, true)); - verifyNoMoreInteractions(mIconGenerator); - verifyNoMoreInteractions(mLargeIconBridge); + verifyNoMoreInteractions(mFaviconFetcher); assertEquals(1, tileList.size()); ListItem tileItem = tileList.get(0); @@ -125,12 +123,13 @@ } @Test - public void testDecorations_navTile_generatedIconOnly() { + public void testDecorations_navTile() { List<ListItem> tileList = populateTilePropertiesForTiles(0, new SuggestTile("title", NAV_URL, false)); - verify(mIconGenerator, times(1)).generateIconForUrl(eq(NAV_URL)); - verify(mLargeIconBridge, times(1)).getLargeIconForUrl(eq(NAV_URL), anyInt(), any()); + verify(mFaviconFetcher, times(1)).fetchFaviconWithBackoff(eq(NAV_URL), anyBoolean(), any()); + mIconCallbackCaptor.getValue().onFaviconFetchComplete(mFaviconBitmap, 0); + // Since we "retrieved" an icon from LargeIconBridge, we should not generate a fallback. assertEquals(1, tileList.size()); ListItem tileItem = tileList.get(0); PropertyModel tileModel = tileItem.model; @@ -140,52 +139,7 @@ assertEquals(BaseCarouselSuggestionItemViewBuilder.ViewType.TILE_VIEW, tileItem.type); assertThat(drawable, instanceOf(BitmapDrawable.class)); Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); - assertEquals(mGeneratedIconBitmap, bitmap); - } - - @Test - public void testDecorations_navTile_fallbackColor() { - List<ListItem> tileList = - populateTilePropertiesForTiles(0, new SuggestTile("title", NAV_URL, false)); - verify(mIconGenerator, times(1)).generateIconForUrl(eq(NAV_URL)); - verify(mLargeIconBridge, times(1)).getLargeIconForUrl(eq(NAV_URL), anyInt(), any()); - // Report no icon, only color. - mIconCallbackCaptor.getValue().onLargeIconAvailable(null, FALLBACK_COLOR, true, 0); - - // The logic should ignore the fallback color and focus only on the presence of an - // actual icon. If no icon is available, we should retain the original generated icon. - assertEquals(1, tileList.size()); - ListItem tileItem = tileList.get(0); - PropertyModel tileModel = tileItem.model; - Drawable drawable = tileModel.get(TileViewProperties.ICON); - - assertEquals(BaseCarouselSuggestionItemViewBuilder.ViewType.TILE_VIEW, tileItem.type); - assertThat(drawable, instanceOf(BitmapDrawable.class)); - Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); - assertEquals(mGeneratedIconBitmap, bitmap); - } - - @Test - public void testDecorations_navTile_actualIcon() { - List<ListItem> tileList = - populateTilePropertiesForTiles(0, new SuggestTile("title", NAV_URL, false)); - verify(mIconGenerator, times(1)).generateIconForUrl(eq(NAV_URL)); - verify(mLargeIconBridge, times(1)).getLargeIconForUrl(eq(NAV_URL), anyInt(), any()); - // Report no icon, only color. - mIconCallbackCaptor.getValue().onLargeIconAvailable( - mLargeIconBitmap, FALLBACK_COLOR, true, 0); - - // In the presence of actual icon we should expect to see that icon being applied to the - // model. - assertEquals(1, tileList.size()); - ListItem tileItem = tileList.get(0); - PropertyModel tileModel = tileItem.model; - Drawable drawable = tileModel.get(TileViewProperties.ICON); - - assertEquals(BaseCarouselSuggestionItemViewBuilder.ViewType.TILE_VIEW, tileItem.type); - assertThat(drawable, instanceOf(BitmapDrawable.class)); - Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); - assertEquals(mLargeIconBitmap, bitmap); + assertEquals(mFaviconBitmap, bitmap); } @Test @@ -214,8 +168,7 @@ .onSuggestionClicked(eq(mMatch), eq(3), eq(SEARCH_URL)); verifyNoMoreInteractions(mSuggestionHost); - verifyNoMoreInteractions(mIconGenerator); - verifyNoMoreInteractions(mLargeIconBridge); + verifyNoMoreInteractions(mFaviconFetcher); } @Test @@ -244,8 +197,7 @@ .onDeleteMatchElement(eq(mMatch), eq("search1"), eq(1), eq(0)); verifyNoMoreInteractions(mSuggestionHost); - verifyNoMoreInteractions(mIconGenerator); - verifyNoMoreInteractions(mLargeIconBridge); + verifyNoMoreInteractions(mFaviconFetcher); } @Test @@ -270,8 +222,7 @@ ordered.verify(mSuggestionHost, times(1)).setOmniboxEditingText(eq(SEARCH_URL.getSpec())); verifyNoMoreInteractions(mSuggestionHost); - verifyNoMoreInteractions(mIconGenerator); - verifyNoMoreInteractions(mLargeIconBridge); + verifyNoMoreInteractions(mFaviconFetcher); } @Test
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java index 4afe9a8..a2dbe80 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/pedal/PedalSuggestionProcessor.java
@@ -10,9 +10,9 @@ import androidx.annotation.VisibleForTesting; import androidx.collection.ArraySet; -import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteDelegate; +import org.chromium.chrome.browser.omnibox.suggestions.FaviconFetcher; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxPedalDelegate; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; @@ -20,7 +20,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties; import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.pedal.PedalSuggestionViewProperties.PedalIcon; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.action.OmniboxPedal; import org.chromium.ui.modelutil.PropertyModel; @@ -42,18 +41,17 @@ * @param context An Android context. * @param suggestionHost A handle to the object using the suggestions. * @param editingTextProvider A means of accessing the text in the omnibox. - * @param iconBridgeSupplier A means of accessing the large icon bridge. + * @param faviconFetcher A means of accessing the large icon bridge. * @param bookmarkBridgeSupplier A means of accessing the bookmark information. * @param omniboxPedalDelegate A delegate that will responsible for pedals. */ public PedalSuggestionProcessor(@NonNull Context context, @NonNull SuggestionHost suggestionHost, @NonNull UrlBarEditingTextStateProvider editingTextProvider, - @NonNull Supplier<LargeIconBridge> iconBridgeSupplier, - @NonNull BookmarkState bookmarkState, + @NonNull FaviconFetcher faviconFetcher, @NonNull BookmarkState bookmarkState, @NonNull OmniboxPedalDelegate omniboxPedalDelegate, @NonNull AutocompleteDelegate autocompleteDelegate) { - super(context, suggestionHost, editingTextProvider, iconBridgeSupplier, bookmarkState); + super(context, suggestionHost, editingTextProvider, faviconFetcher, bookmarkState); mOmniboxPedalDelegate = omniboxPedalDelegate; mAutocompleteDelegate = autocompleteDelegate; } @@ -128,4 +126,4 @@ } mLastVisiblePedals.clear(); } -} \ No newline at end of file +}
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java index 1ceb3fe..cc1ffb61 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tail/TailSuggestionProcessor.java
@@ -27,7 +27,7 @@ * @param suggestionHost A handle to the object using the suggestions. */ public TailSuggestionProcessor(Context context, SuggestionHost suggestionHost) { - super(context, suggestionHost); + super(context, suggestionHost, null); mAlignTailSuggestions = DeviceFormFactor.isNonMultiDisplayContextOnTablet(context); }
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialogTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialogTest.java index 37ea209b..37dc481 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialogTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmManagedSyncDataDialogTest.java
@@ -32,6 +32,7 @@ import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.ui.test.util.BlankUiTestActivity; @@ -101,6 +102,7 @@ @Test @LargeTest + @DisableIf.Build(sdk_is_greater_than = 25, message = "https://crbug.com/1336718 - failing on O") public void testDialogIsDismissedWhenRecreated() throws Exception { showManagedSyncDataDialog(); onView(withText(R.string.sign_in_managed_account))
diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn index 5b37441..ede8733 100644 --- a/chrome/browser/ui/android/toolbar/BUILD.gn +++ b/chrome/browser/ui/android/toolbar/BUILD.gn
@@ -287,6 +287,7 @@ "java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java", "java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java", "java/src/org/chromium/chrome/browser/toolbar/top/ToolbarSnapshotStateTest.java", + "java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java", "java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarInteractabilityManagerTest.java", "java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarOverlayMediatorTest.java", ]
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java index 6d4051e..a10283a 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTablet.java
@@ -71,15 +71,19 @@ extends ToolbarLayout implements OnClickListener, View.OnLongClickListener { private ObjectAnimator mTabSwitcherModeAnimation; - /** Downloads page for offline access. */ + /** + * Downloads page for offline access. + */ public interface OfflineDownloader { /** * Trigger the download of a page. + * * @param context Context to pull resources from. * @param tab Tab containing the page to download. */ void downloadPage(Context context, Tab tab); } + private HomeButton mHomeButton; private ImageButton mBackButton; private ImageButton mForwardButton; @@ -113,6 +117,7 @@ /** * Constructs a ToolbarTablet object. + * * @param context The Context in which this View object is created. * @param attrs The AttributeSet that was specified with this View. */ @@ -172,8 +177,8 @@ } /** - * Sets up key listeners after native initialization is complete, so that we can invoke - * native functions. + * Sets up key listeners after native initialization is complete, so that we can invoke native + * functions. */ @Override public void onNativeLibraryReady() { @@ -600,6 +605,11 @@ @Override void onAccessibilityStatusChanged(boolean enabled) { + enableTabStackButton(enabled); + } + + @VisibleForTesting + void enableTabStackButton(boolean enabled) { mShowTabStack = (enabled && isAccessibilityTabSwitcherPreferenceEnabled()) || isGridTabSwitcherEnabled(); updateSwitcherButtonVisibility(mShowTabStack); @@ -714,6 +724,7 @@ /** * Sets the toolbar start padding based on whether the buttons are visible. + * * @param buttonsVisible Whether the toolbar buttons are visible. */ private void setStartPaddingBasedOnButtonVisibility(boolean buttonsVisible) { @@ -726,7 +737,7 @@ /** * @return The difference in start padding when the buttons are visible and when they are not - * visible. + * visible. */ public int getStartPaddingDifferenceForButtonVisibilityAnimation() { // If the home button is visible then the padding doesn't change. @@ -828,4 +839,24 @@ return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS, "enable_launch_polish", false); } + + @VisibleForTesting + ImageButton[] getToolbarButtons() { + return mToolbarButtons; + } + + @VisibleForTesting + ObjectAnimator getTabSwitcherModeAnimation() { + return mTabSwitcherModeAnimation; + } + + @VisibleForTesting + void enableButtonVisibilityChangeAnimationForTesting() { + mShouldAnimateButtonVisibilityChange = true; + } + + @VisibleForTesting + void setToolbarButtonsVisibleForTesting(boolean value) { + mToolbarButtonsVisible = value; + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java new file mode 100644 index 0000000..4785147 --- /dev/null +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarTabletUnitTest.java
@@ -0,0 +1,304 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package org.chromium.chrome.browser.toolbar.top; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.animation.ObjectAnimator; +import android.app.Activity; +import android.graphics.drawable.Drawable; +import android.os.Looper; +import android.view.View; +import android.widget.ImageButton; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.Shadows; +import org.robolectric.annotation.LooperMode; +import org.robolectric.shadows.ShadowToast; + +import org.chromium.base.FeatureList; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.omnibox.LocationBarCoordinator; +import org.chromium.chrome.browser.omnibox.LocationBarCoordinatorTablet; +import org.chromium.chrome.browser.omnibox.LocationBarLayout; +import org.chromium.chrome.browser.omnibox.status.StatusCoordinator; +import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.Features.EnableFeatures; + +import java.util.ArrayList; + +/** + * Unit tests for @{@link ToolbarTablet} + */ +@LooperMode(LooperMode.Mode.PAUSED) +@RunWith(BaseRobolectricTestRunner.class) +public final class ToolbarTabletUnitTest { + @Rule + public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); + @Mock + private LocationBarCoordinator mLocationBar; + @Mock + private Drawable mDrawable; + @Mock + private LocationBarCoordinatorTablet mLocationBarTablet; + @Mock + private StatusCoordinator mStatusCoordinator; + @Mock + private MenuButtonCoordinator mMenuButtonCoordinator; + @Mock + private View mContainerView; + private Activity mActivity; + private ToolbarTablet mToolbarTablet; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mActivity = Robolectric.buildActivity(Activity.class).setup().get(); + mActivity.setTheme(org.chromium.chrome.tab_ui.R.style.Theme_BrowserUI_DayNight); + mToolbarTablet = (ToolbarTablet) mActivity.getLayoutInflater().inflate( + org.chromium.chrome.R.layout.toolbar_tablet, null); + when(mLocationBar.getTabletCoordinator()).thenReturn(mLocationBarTablet); + when(mLocationBarTablet.getBackground()).thenReturn(mDrawable); + mToolbarTablet.setLocationBarCoordinator(mLocationBar); + LocationBarLayout locationBarLayout = mToolbarTablet.findViewById(R.id.location_bar); + locationBarLayout.setStatusCoordinatorForTesting(mStatusCoordinator); + mToolbarTablet.setMenuButtonCoordinatorForTesting(mMenuButtonCoordinator); + } + + @After + public void tearDown() { + disableGridTabSwitcher(); + } + + @Test + public void onMeasureShortWidth_hidesToolbarButtons() { + mToolbarTablet.measure(300, 300); + + ImageButton[] btns = mToolbarTablet.getToolbarButtons(); + for (ImageButton btn : btns) { + assertEquals( + "Toolbar button visibility is not as expected", View.GONE, btn.getVisibility()); + } + } + + @Test + public void onMeasureLargeWidth_showsToolbarButtons() { + mToolbarTablet.measure(700, 300); + + ImageButton[] btns = mToolbarTablet.getToolbarButtons(); + for (ImageButton btn : btns) { + assertEquals("Toolbar button visibility is not as expected", View.VISIBLE, + btn.getVisibility()); + } + } + + @Test + public void onMeasureSmallWidthWithAnimation_hidesToolbarButtons() { + for (ImageButton btn : mToolbarTablet.getToolbarButtons()) { + when(mLocationBar.createHideButtonAnimatorForTablet(btn)) + .thenReturn(ObjectAnimator.ofFloat(btn, View.ALPHA, 0.f)); + } + when(mLocationBar.getHideButtonsWhenUnfocusedAnimatorsForTablet(anyInt())) + .thenReturn(new ArrayList<>()); + + mToolbarTablet.enableButtonVisibilityChangeAnimationForTesting(); + // Call + mToolbarTablet.measure(300, 300); + Shadows.shadowOf(Looper.getMainLooper()).idle(); + // Verify + ImageButton[] btns = mToolbarTablet.getToolbarButtons(); + for (ImageButton btn : btns) { + assertEquals( + "Toolbar button visibility is not as expected", View.GONE, btn.getVisibility()); + } + } + + @Test + public void onMeasureLargeWidthWithAnimation_showsToolbarButtons() { + mToolbarTablet.setToolbarButtonsVisibleForTesting(false); + mToolbarTablet.enableButtonVisibilityChangeAnimationForTesting(); + for (ImageButton btn : mToolbarTablet.getToolbarButtons()) { + when(mLocationBar.createShowButtonAnimatorForTablet(btn)) + .thenReturn(ObjectAnimator.ofFloat(btn, View.ALPHA, 1.f)); + } + when(mLocationBar.getShowButtonsWhenUnfocusedAnimatorsForTablet(anyInt())) + .thenReturn(new ArrayList<>()); + // Call + mToolbarTablet.measure(700, 300); + Shadows.shadowOf(Looper.getMainLooper()).idle(); + // Verify + ImageButton[] btns = mToolbarTablet.getToolbarButtons(); + for (ImageButton btn : btns) { + assertEquals("Toolbar button visibility is not as expected", View.VISIBLE, + btn.getVisibility()); + } + } + + @EnableFeatures(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS) + @Test + public void testSetTabSwitcherModeOn_hidesToolbar() { + assertEquals("Initial Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + // Call + mToolbarTablet.setTabSwitcherMode(true, false, false, mMenuButtonCoordinator); + mToolbarTablet.getTabSwitcherModeAnimation().end(); + assertEquals( + "Toolbar visibility is not as expected", View.GONE, mToolbarTablet.getVisibility()); + verify(mLocationBar).setUrlBarFocusable(false); + } + + @EnableFeatures(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS) + @Test + public void testSetTabSwitcherModeOff_showsToolbar() { + // Hide toolbar as initial state. + mToolbarTablet.setVisibility(View.GONE); + // Call + mToolbarTablet.setTabSwitcherMode(false, false, false, mMenuButtonCoordinator); + mToolbarTablet.getTabSwitcherModeAnimation().end(); + assertEquals("Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + verify(mLocationBar).setUrlBarFocusable(true); + } + + @EnableFeatures(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS) + @Test + public void testSetTabSwitcherPolishModeOff_toolbarStillVisible() { + enableGridTabSwitcher(true); + assertEquals("Initial Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + // Call + mToolbarTablet.setTabSwitcherMode(false, false, false, mMenuButtonCoordinator); + assertEquals("Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + verify(mLocationBar).setUrlBarFocusable(true); + } + + @EnableFeatures(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS) + @Test + public void testSetTabSwitcherPolishModeOn_toolbarStillVisible() { + enableGridTabSwitcher(true); + assertEquals("Initial Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + // Call + mToolbarTablet.setTabSwitcherMode(true, false, false, mMenuButtonCoordinator); + assertEquals("Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + verify(mLocationBar).setUrlBarFocusable(false); + } + + @Test + public void testSetTabSwitcherOnGTSDisabled_hidesViews() { + // Enable tab stack button when GTS is disabled + mToolbarTablet.enableTabStackButton(true); + when(mLocationBar.getContainerView()).thenReturn(mContainerView); + assertEquals("Initial Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + // Call + mToolbarTablet.setTabSwitcherMode(true, false, false, mMenuButtonCoordinator); + assertFalse("Button should not be enabled", + mToolbarTablet.findViewById(R.id.back_button).isEnabled()); + assertFalse("Button should not be enabled", + mToolbarTablet.findViewById(R.id.forward_button).isEnabled()); + assertFalse("Button should not be enabled", + mToolbarTablet.findViewById(R.id.refresh_button).isEnabled()); + verify(mContainerView).setVisibility(View.INVISIBLE); + verify(mMenuButtonCoordinator).setAppMenuUpdateBadgeSuppressed(true); + } + + @Test + public void testSetTabSwitcherOffGTSDisabled_showsViews() { + // Enable tab stack button when GTS is disabled + mToolbarTablet.enableTabStackButton(true); + when(mLocationBar.getContainerView()).thenReturn(mContainerView); + assertEquals("Initial Toolbar visibility is not as expected", View.VISIBLE, + mToolbarTablet.getVisibility()); + // Call + mToolbarTablet.setTabSwitcherMode(false, false, false, mMenuButtonCoordinator); + verify(mContainerView).setVisibility(View.VISIBLE); + verify(mMenuButtonCoordinator).setAppMenuUpdateBadgeSuppressed(false); + } + + @Test + public void testOnLongClick() { + longClickAndVerifyToast(R.id.refresh_button, R.string.refresh); + longClickAndVerifyToast(R.id.bookmark_button, R.string.menu_bookmark); + longClickAndVerifyToast(R.id.save_offline_button, R.string.menu_download); + } + + @Test + public void testUpdateBackButtonVisibility() { + ImageButton btn = mToolbarTablet.findViewById(R.id.back_button); + mToolbarTablet.updateBackButtonVisibility(true); + assertTrue("Button should be enabled", btn.isEnabled()); + assertTrue("Button should be focused", btn.isFocusable()); + mToolbarTablet.updateBackButtonVisibility(false); + assertFalse("Button should not be enabled", btn.isEnabled()); + assertFalse("Button should not be focused", btn.isFocusable()); + } + + @Test + public void testUpdateForwardButtonVisibility() { + ImageButton btn = mToolbarTablet.findViewById(R.id.forward_button); + mToolbarTablet.updateForwardButtonVisibility(true); + assertTrue("Button should be enabled", btn.isEnabled()); + assertTrue("Button should be focused", btn.isFocusable()); + mToolbarTablet.updateForwardButtonVisibility(false); + assertFalse("Button should not be enabled", btn.isEnabled()); + assertFalse("Button should not be focused", btn.isFocusable()); + } + + @Test + public void testUpdateReloadButtonVisibility() { + ImageButton btn = mToolbarTablet.findViewById(R.id.refresh_button); + mToolbarTablet.updateReloadButtonVisibility(true); + assertTrue("Button should be enabled", btn.isEnabled()); + assertEquals("Button drawable level is not as expected", 1, btn.getDrawable().getLevel()); + assertEquals("Button description is not as expected", + mActivity.getResources().getString(R.string.accessibility_btn_stop_loading), + btn.getContentDescription()); + mToolbarTablet.updateReloadButtonVisibility(false); + assertEquals("Button drawable level is not as expected", 0, btn.getDrawable().getLevel()); + assertEquals("Button description is not as expected", + mActivity.getResources().getString(R.string.accessibility_btn_refresh), + btn.getContentDescription()); + assertTrue("Button should be enabled", btn.isEnabled()); + } + + private void longClickAndVerifyToast(int viewId, int stringId) { + mToolbarTablet.onLongClick(mToolbarTablet.findViewById(viewId)); + assertTrue("Toast is not as expected", + ShadowToast.showedCustomToast( + mActivity.getResources().getString(stringId), R.id.toast_text)); + } + + private void enableGridTabSwitcher(boolean enablePolish) { + FeatureList.TestValues testValues = new FeatureList.TestValues(); + testValues.addFeatureFlagOverride(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS, true); + testValues.addFieldTrialParamOverride(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS, + "enable_launch_polish", String.valueOf(enablePolish)); + FeatureList.setTestValues(testValues); + } + + private void disableGridTabSwitcher() { + FeatureList.TestValues testValues = new FeatureList.TestValues(); + testValues.addFeatureFlagOverride(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS, false); + FeatureList.setTestValues(testValues); + } +}
diff --git a/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc b/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc index f4666b2..4914236 100644 --- a/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc +++ b/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/ash/desks/chrome_desks_util.h" #include "chrome/browser/ui/ash/desks/desks_client.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_tabstrip.h" @@ -39,6 +40,7 @@ #include "components/app_restore/full_restore_save_handler.h" #include "components/app_restore/full_restore_utils.h" #include "components/app_restore/restore_data.h" +#include "components/app_restore/tab_group_info.h" #include "components/app_restore/window_properties.h" #include "components/favicon/core/favicon_service.h" #include "components/favicon_base/favicon_util.h" @@ -278,11 +280,17 @@ if (tab_strip_model) { app_launch_info->urls = GetURLsIfApplicable(tab_strip_model); app_launch_info->active_tab_index = tab_strip_model->active_index(); + if (tab_strip_model->SupportsTabGroups()) { + app_launch_info->tab_group_infos = + chrome_desks_util::ConvertTabGroupsToTabGroupInfos( + tab_strip_model->group_model()); + } std::move(callback).Run(std::move(app_launch_info)); return; } if (app_id == app_constants::kLacrosAppId) { + // TODO(avynn): Add lacros support for tab groups. const std::string* lacros_window_id = window->GetProperty(app_restore::kLacrosWindowId); DCHECK(lacros_window_id);
diff --git a/chrome/browser/ui/ash/desks/chrome_desks_util.cc b/chrome/browser/ui/ash/desks/chrome_desks_util.cc new file mode 100644 index 0000000..de003bb --- /dev/null +++ b/chrome/browser/ui/ash/desks/chrome_desks_util.cc
@@ -0,0 +1,64 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/tabs/tab_group.h" +#include "chrome/browser/ui/tabs/tab_group_model.h" +#include "components/app_restore/tab_group_info.h" +#include "components/tab_groups/tab_group_id.h" +#include "components/tab_groups/tab_group_visual_data.h" + +namespace { + +const std::vector<int> ConvertRangeToTabGroupIndices(const gfx::Range& range) { + std::vector<int> indices; + + for (uint32_t index = range.start(); index < range.end(); ++index) { + indices.push_back(static_cast<int>(index)); + } + + return indices; +} + +} // namespace + +namespace chrome_desks_util { + +absl::optional<std::vector<app_restore::TabGroupInfo>> +ConvertTabGroupsToTabGroupInfos(const TabGroupModel* group_model) { + DCHECK(group_model); + const std::vector<tab_groups::TabGroupId>& listed_group_ids = + group_model->ListTabGroups(); + + if (listed_group_ids.size() == 0) { + return absl::nullopt; + } + + std::vector<app_restore::TabGroupInfo> tab_groups; + for (const tab_groups::TabGroupId& group_id : listed_group_ids) { + const TabGroup* tab_group = group_model->GetTabGroup(group_id); + tab_groups.emplace_back( + gfx::Range(tab_group->ListTabs()), + tab_groups::TabGroupVisualData(*(tab_group->visual_data()))); + } + + return tab_groups; +} + +void AttachTabGroupsToBrowserInstance( + const std::vector<app_restore::TabGroupInfo>& tab_groups, + Browser* browser) { + TabStripModel* tab_strip_model = browser->tab_strip_model(); + + for (const app_restore::TabGroupInfo& tab_group : tab_groups) { + tab_groups::TabGroupId new_group_id = tab_strip_model->AddToNewGroup( + ConvertRangeToTabGroupIndices(tab_group.tab_range)); + tab_strip_model->group_model() + ->GetTabGroup(new_group_id) + ->SetVisualData(tab_group.visual_data); + } +} + +} // namespace chrome_desks_util
diff --git a/chrome/browser/ui/ash/desks/chrome_desks_util.h b/chrome/browser/ui/ash/desks/chrome_desks_util.h new file mode 100644 index 0000000..a730ef7 --- /dev/null +++ b/chrome/browser/ui/ash/desks/chrome_desks_util.h
@@ -0,0 +1,32 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_ASH_DESKS_CHROME_DESKS_UTIL_H_ +#define CHROME_BROWSER_UI_ASH_DESKS_CHROME_DESKS_UTIL_H_ + +#include <memory> + +class TabGroupModel; + +namespace app_restore { +struct TabGroupInfo; +} // namespace app_restore + +namespace chrome_desks_util { + +// Given a TabGroupModel that contains at least a single TabGroup this method +// returns a populated optional vector that contains app_Restore::TabGroupInfo +// representations of the TabGroups contained within the model. +absl::optional<std::vector<app_restore::TabGroupInfo>> +ConvertTabGroupsToTabGroupInfos(const TabGroupModel* group_model); + +// Given a vector of TabGroupInfo this function attaches tab groups to the +// out_browser instance passed as the second parameter. +void AttachTabGroupsToBrowserInstance( + const std::vector<app_restore::TabGroupInfo>& tab_groups, + Browser* browser); + +} // namespace chrome_desks_util + +#endif
diff --git a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc index 75d0538..187d342 100644 --- a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc +++ b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
@@ -49,12 +49,16 @@ #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h" #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.h" +#include "chrome/browser/ui/ash/desks/chrome_desks_util.h" #include "chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_group.h" +#include "chrome/browser/ui/tabs/tab_group_model.h" #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" @@ -69,11 +73,14 @@ #include "components/app_restore/full_restore_save_handler.h" #include "components/app_restore/full_restore_utils.h" #include "components/app_restore/restore_data.h" +#include "components/app_restore/tab_group_info.h" #include "components/app_restore/window_properties.h" #include "components/keep_alive_registry/keep_alive_types.h" #include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/policy/policy_constants.h" #include "components/services/app_service/public/cpp/app_types.h" +#include "components/tab_groups/tab_group_color.h" +#include "components/tab_groups/tab_group_visual_data.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" @@ -86,6 +93,7 @@ #include "ui/display/screen.h" #include "ui/display/test/display_manager_test_api.h" #include "ui/events/test/event_generator.h" +#include "ui/gfx/range/range.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/label_button.h" #include "url/gurl.h" @@ -111,6 +119,7 @@ "[{\"version\":1,\"uuid\":\"%s\",\"name\": \"test admin template\"," "\"created_time_usec\": \"1633535632\",\"updated_time_usec\": " "\"1633535632\",\"desk\":{}}]"; +constexpr char kTestTabGroupNameFormat[] = "test_tab_group_%u"; Browser* FindBrowser(int32_t window_id) { for (auto* browser : *BrowserList::GetInstance()) { @@ -310,6 +319,25 @@ return templates; } +// Creates a vector of tab groups based on the vector of GURLs passed into it. +// A tab group will be created for each individual tab. +std::vector<app_restore::TabGroupInfo> MakeExpectedTabGroupsBasedOnTabVector( + const std::vector<GURL>& urls) { + std::vector<app_restore::TabGroupInfo> tab_groups; + + for (uint32_t index = 0; index < urls.size(); ++index) { + tab_groups.emplace_back( + gfx::Range(index, index + 1), + tab_groups::TabGroupVisualData( + base::UTF8ToUTF16( + base::StringPrintf(kTestTabGroupNameFormat, index)), + tab_groups::TabGroupColorId( + static_cast<tab_groups::TabGroupColorId>(index % 8)))); + } + + return tab_groups; +} + class MockDesksTemplatesAppLaunchHandler : public DesksTemplatesAppLaunchHandler { public: @@ -399,18 +427,17 @@ Browser* CreateBrowser( const std::vector<GURL>& urls, absl::optional<size_t> active_url_index = absl::nullopt) { - Browser::CreateParams params(Browser::TYPE_NORMAL, profile(), - /*user_gesture=*/false); - Browser* browser = Browser::Create(params); - // Create a new tab and make sure the urls have loaded. - for (size_t i = 0; i < urls.size(); i++) { - content::TestNavigationObserver navigation_observer(urls[i]); - navigation_observer.StartWatchingNewWebContents(); - chrome::AddTabAt( - browser, urls[i], /*index=*/-1, - /*foreground=*/!active_url_index || active_url_index.value() == i); - navigation_observer.Wait(); - } + Browser* browser = CreateBrowserImpl(urls, active_url_index); + browser->window()->Show(); + return browser; + } + + Browser* CreateBrowserWithTabGroups( + const std::vector<GURL>& urls, + const std::vector<app_restore::TabGroupInfo>& tab_groups) { + Browser* browser = CreateBrowserImpl(urls, absl::nullopt); + + chrome_desks_util::AttachTabGroupsToBrowserInstance(tab_groups, browser); browser->window()->Show(); return browser; } @@ -443,6 +470,23 @@ } private: + Browser* CreateBrowserImpl(const std::vector<GURL>& urls, + absl::optional<size_t> active_url_index) { + Browser::CreateParams params(Browser::TYPE_NORMAL, profile(), + /*user_gesture=*/false); + Browser* browser = Browser::Create(params); + // Create a new tab and make sure the urls have loaded. + for (size_t i = 0; i < urls.size(); i++) { + content::TestNavigationObserver navigation_observer(urls[i]); + navigation_observer.StartWatchingNewWebContents(); + chrome::AddTabAt( + browser, urls[i], /*index=*/-1, + /*foreground=*/!active_url_index || active_url_index.value() == i); + navigation_observer.Wait(); + } + return browser; + } + base::test::ScopedFeatureList scoped_feature_list_; }; @@ -474,6 +518,49 @@ EXPECT_EQ(data->urls.value(), urls); } +// Tests that a browser's tab groups can be captured correctly in a saved desk. +IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, CaptureBrowserTabGroupsTest) { + std::vector<GURL> tabs = {GURL(kExampleUrl1), GURL(kExampleUrl2)}; + std::vector<app_restore::TabGroupInfo> expected_tab_groups = + MakeExpectedTabGroupsBasedOnTabVector(tabs); + + // Create a new browser and add a few tabs to it. + Browser* browser = CreateBrowserWithTabGroups(tabs, expected_tab_groups); + aura::Window* window = browser->window()->GetNativeWindow(); + + const int32_t browser_window_id = + window->GetProperty(app_restore::kWindowIdKey); + // Get current tabs from browser. + std::vector<GURL> urls = GetURLsForBrowserWindow(browser); + + ash::ToggleOverview(); + ash::WaitForOverviewEnterAnimation(); + + ClickSaveDeskAsTemplateButton(); + + std::vector<const ash::DeskTemplate*> templates = GetAllEntries(); + ASSERT_EQ(1u, templates.size()); + + const ash::DeskTemplate* desk_template = templates.front(); + const app_restore::RestoreData* restore_data = + desk_template->desk_restore_data(); + const auto& app_id_to_launch_list = restore_data->app_id_to_launch_list(); + EXPECT_EQ(1u, app_id_to_launch_list.size()); + + // Find `browser` window's app restore data. + auto iter = app_id_to_launch_list.find(app_constants::kChromeAppId); + ASSERT_TRUE(iter != app_id_to_launch_list.end()); + auto app_restore_data_iter = iter->second.find(browser_window_id); + ASSERT_TRUE(app_restore_data_iter != iter->second.end()); + const auto& data = app_restore_data_iter->second; + // Check the urls are captured correctly in the `desk_template`. + EXPECT_EQ(urls, data->urls.value()); + + // We don't care about the order of the tab groups. + EXPECT_THAT(expected_tab_groups, testing::UnorderedElementsAreArray( + data->tab_group_infos.value())); +} + // Tests that incognito browser windows will NOT be captured in the desk // template. IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, CaptureIncognitoBrowserTest) { @@ -832,6 +919,51 @@ browser_window->parent()); } +// Tests that launching a template that contains a browser window with tab +// groups works as expected. +IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest, + LaunchTemplateWithBrowserWindowTabGroups) { + ASSERT_TRUE(DesksClient::Get()); + + // Create a new browser and add a few tabs to it, and specify the active tab + // index. + std::vector<GURL> creation_urls = {GURL(kExampleUrl1), GURL(kExampleUrl2), + GURL(kExampleUrl3)}; + std::vector<app_restore::TabGroupInfo> expected_tab_groups = + MakeExpectedTabGroupsBasedOnTabVector(creation_urls); + + Browser* browser = + CreateBrowserWithTabGroups(creation_urls, expected_tab_groups); + + // Get current tabs from browser. + const std::vector<GURL> urls = GetURLsForBrowserWindow(browser); + + // Enter overview and save the current desk as a template. + ash::ToggleOverview(); + ash::WaitForOverviewEnterAnimation(); + + ClickSaveDeskAsTemplateButton(); + + ClickFirstTemplateItem(); + + // Wait for the tabs to load. + content::RunAllTasksUntilIdle(); + + // Verify that the browser was launched with the correct urls and active tab. + Browser* new_browser = FindLaunchedBrowserByURLs(urls); + ASSERT_TRUE(new_browser); + + absl::optional<std::vector<app_restore::TabGroupInfo>> got_tab_groups = + chrome_desks_util::ConvertTabGroupsToTabGroupInfos( + new_browser->tab_strip_model()->group_model()); + + EXPECT_TRUE(got_tab_groups.has_value()); + + // We don't care about the order of the tab groups. + EXPECT_THAT(expected_tab_groups, + testing::UnorderedElementsAreArray(got_tab_groups.value())); +} + // Tests that browser session restore isn't triggered when we launch a template // that contains a browser window. IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
diff --git a/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc b/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc index e33ed88..5c80f14e 100644 --- a/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc +++ b/chrome/browser/ui/ash/desks/desks_templates_app_launch_handler.cc
@@ -19,11 +19,13 @@ #include "chrome/browser/ash/app_restore/arc_app_launch_handler.h" #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/ash/desks/chrome_desks_util.h" #include "chrome/browser/ui/ash/desks/desks_client.h" #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_group_model.h" #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "components/app_constants/constants.h" @@ -52,7 +54,6 @@ ? maybe_app_name.value() : app_id; } - } // namespace DesksTemplatesAppLaunchHandler::DesksTemplatesAppLaunchHandler(Profile* profile) @@ -214,6 +215,11 @@ base::checked_cast<int32_t>(i) == *active_tab_index)); } + if (app_restore_data->tab_group_infos.has_value()) { + chrome_desks_util::AttachTabGroupsToBrowserInstance( + app_restore_data->tab_group_infos.value(), browser); + } + // We need to handle minimized windows separately since unlike other // window types, it's not shown. if (window_state_type &&
diff --git a/chrome/browser/ui/page_action/page_action_icon_type.h b/chrome/browser/ui/page_action/page_action_icon_type.h index 9cf8822e..779cbe4 100644 --- a/chrome/browser/ui/page_action/page_action_icon_type.h +++ b/chrome/browser/ui/page_action/page_action_icon_type.h
@@ -21,7 +21,6 @@ kSaveAutofillAddress, kSaveCard, kSendTabToSelf, - kSharedClipboard, kSharingHub, kSideSearch, kSmsRemoteFetcher,
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc index 8737a1ba..f466ec3 100644 --- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc +++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -174,7 +174,7 @@ void OnError(CaptionBubbleContext* caption_bubble_context) { GetController()->OnError( - caption_bubble_context, CaptionBubbleErrorType::GENERIC, + caption_bubble_context, CaptionBubbleErrorType::kGeneric, base::RepeatingClosure(), base::BindRepeating( [](CaptionBubbleErrorType error_type, bool checked) {})); @@ -187,7 +187,7 @@ void OnMediaFoundationError(CaptionBubbleContext* caption_bubble_context) { GetController()->OnError( caption_bubble_context, - CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED, + CaptionBubbleErrorType::kMediaFoundationRendererUnsupported, base::RepeatingClosure(), base::BindRepeating( [](CaptionBubbleErrorType error_type, bool checked) {}));
diff --git a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc index 820f44a..d68c15a4 100644 --- a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc +++ b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view.cc
@@ -57,8 +57,8 @@ OnStateChanged(); ansible_management_service_->ConfigureContainer( - crostini::ContainerId::GetDefault(), - default_container_ansible_filepath_, base::DoNothing()); + crostini::DefaultContainerId(), default_container_ansible_filepath_, + base::DoNothing()); return false; } DCHECK_EQ(state_, State::ERROR);
diff --git a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc index bb8d31b..3f3cd5a 100644 --- a/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc +++ b/chrome/browser/ui/views/crostini/crostini_ansible_software_config_view_browsertest.cc
@@ -59,9 +59,8 @@ vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal; signal.set_status( vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::SUCCEEDED); - signal.set_vm_name(crostini::ContainerId::GetDefault().vm_name); - signal.set_container_name( - crostini::ContainerId::GetDefault().container_name); + signal.set_vm_name(crostini::DefaultContainerId().vm_name); + signal.set_container_name(crostini::DefaultContainerId().container_name); ansible_management_service()->OnApplyAnsiblePlaybookProgress(signal); } else { EXPECT_NE(nullptr, ActiveView()); @@ -69,9 +68,8 @@ vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal signal; signal.set_status( vm_tools::cicerone::ApplyAnsiblePlaybookProgressSignal::FAILED); - signal.set_vm_name(crostini::ContainerId::GetDefault().vm_name); - signal.set_container_name( - crostini::ContainerId::GetDefault().container_name); + signal.set_vm_name(crostini::DefaultContainerId().vm_name); + signal.set_container_name(crostini::DefaultContainerId().container_name); signal.set_failure_details("apple"); ansible_management_service()->OnApplyAnsiblePlaybookProgress(signal); } @@ -289,7 +287,7 @@ IN_PROC_BROWSER_TEST_F(CrostiniAnsibleSoftwareConfigViewBrowserTest, AnsibleConfigFlow_Successful) { ansible_management_service()->ConfigureContainer( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), browser()->profile()->GetPrefs()->GetFilePath( crostini::prefs::kCrostiniAnsiblePlaybookFilePath), base::BindLambdaForTesting([&](bool success) { run_loop()->Quit(); })); @@ -305,7 +303,7 @@ // there. SetInstallAnsibleStatus(false); ansible_management_service()->ConfigureContainer( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), browser()->profile()->GetPrefs()->GetFilePath( crostini::prefs::kCrostiniAnsiblePlaybookFilePath), base::BindLambdaForTesting([&](bool success) { run_loop()->Quit(); })); @@ -321,7 +319,7 @@ // Set apply failure SetApplyAnsibleStatus(false); ansible_management_service()->ConfigureContainer( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), browser()->profile()->GetPrefs()->GetFilePath( crostini::prefs::kCrostiniAnsiblePlaybookFilePath), base::BindLambdaForTesting(
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 2c4fd2aa..5acc434 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -217,7 +217,6 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/base/theme_provider.h" #include "ui/base/window_open_disposition.h" -#include "ui/color/color_provider.h" #include "ui/compositor/layer.h" #include "ui/compositor/paint_recorder.h" #include "ui/content_accelerators/accelerator_util.h" @@ -454,19 +453,14 @@ METADATA_HEADER(ContentsSeparator); ContentsSeparator() { + SetBackground( + views::CreateThemedSolidBackground(kColorToolbarContentAreaSeparator)); + // BrowserViewLayout will respect either the height or width of this, // depending on orientation, not simultaneously both. SetPreferredSize( gfx::Size(views::Separator::kThickness, views::Separator::kThickness)); } - - private: - // views::View: - void OnThemeChanged() override { - SetBackground(views::CreateSolidBackground( - GetColorProvider()->GetColor(kColorToolbarContentAreaSeparator))); - View::OnThemeChanged(); - } }; BEGIN_METADATA(ContentsSeparator, views::View) @@ -2386,9 +2380,12 @@ SharingDialog* BrowserView::ShowSharingDialog( content::WebContents* web_contents, SharingDialogData data) { + // TODO(https://crbug.com/1311680): Remove this altogether. This used to + // be hardcoded to anchor off the shared clipboard bubble, but that bubble is + // now gone altogether. auto* dialog_view = new SharingDialogView(toolbar_button_provider()->GetAnchorView( - PageActionIconType::kSharedClipboard), + PageActionIconType::kClickToCall), web_contents, std::move(data)); views::BubbleDialogDelegateView::CreateBubble(dialog_view)->Show();
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_controller.cc b/chrome/browser/ui/views/page_action/page_action_icon_controller.cc index 23c226e..0e1505f6 100644 --- a/chrome/browser/ui/views/page_action/page_action_icon_controller.cc +++ b/chrome/browser/ui/views/page_action/page_action_icon_controller.cc
@@ -10,7 +10,6 @@ #include "base/feature_list.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sharing/click_to_call/click_to_call_ui_controller.h" -#include "chrome/browser/sharing/shared_clipboard/shared_clipboard_ui_controller.h" #include "chrome/browser/sharing/sms/sms_remote_fetcher_ui_controller.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h" @@ -175,19 +174,6 @@ params.command_updater, params.icon_label_bubble_delegate, params.page_action_icon_delegate)); break; - case PageActionIconType::kSharedClipboard: - add_page_action_icon( - type, - std::make_unique<SharingIconView>( - params.icon_label_bubble_delegate, - params.page_action_icon_delegate, - base::BindRepeating([](content::WebContents* contents) { - return static_cast<SharingUiController*>( - SharedClipboardUiController::GetOrCreateFromWebContents( - contents)); - }), - base::BindRepeating(SharingDialogView::GetAsBubble))); - break; case PageActionIconType::kSharingHub: add_page_action_icon( type, std::make_unique<sharing_hub::SharingHubIconView>(
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc index 061c41807..6ff74ada 100644 --- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc +++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
@@ -23,7 +23,6 @@ #include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" #include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h" -#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "chromeos/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h" #include "components/account_id/account_id.h" @@ -72,7 +71,7 @@ fake_concierge_client_->set_disk_image_progress_signal_connected(true); fake_vm_plugin_dispatcher_client_ = static_cast<chromeos::FakeVmPluginDispatcherClient*>( - chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()); + chromeos::VmPluginDispatcherClient::Get()); network_connection_tracker_ = network::TestNetworkConnectionTracker::CreateInstance();
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc index bd57b508..85cebb7 100644 --- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc +++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
@@ -137,7 +137,7 @@ return; } crostini_manager->RestartCrostini( - crostini::ContainerId::GetDefault(), + crostini::DefaultContainerId(), base::BindOnce( [](base::OnceClosure launch_closure, crostini::CrostiniResult result) {
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc index 5f179e1..69d57473 100644 --- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc +++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
@@ -59,7 +59,7 @@ Redisplay(); CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( crostini::UpgradeDialogEvent::kDidBackup); - upgrader_ui_delegate_->Backup(crostini::ContainerId::GetDefault(), + upgrader_ui_delegate_->Backup(crostini::DefaultContainerId(), show_file_chooser, web_contents_->GetWeakPtr()); } @@ -69,14 +69,14 @@ void CrostiniUpgraderPageHandler::Upgrade() { Redisplay(); - upgrader_ui_delegate_->Upgrade(crostini::ContainerId::GetDefault()); + upgrader_ui_delegate_->Upgrade(crostini::DefaultContainerId()); } void CrostiniUpgraderPageHandler::Restore() { Redisplay(); CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( crostini::UpgradeDialogEvent::kDidRestore); - upgrader_ui_delegate_->Restore(crostini::ContainerId::GetDefault(), + upgrader_ui_delegate_->Restore(crostini::DefaultContainerId(), web_contents_->GetWeakPtr()); }
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index 22b6025..e7c606c3b 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -27,9 +27,9 @@ #include "chrome/browser/search_provider_logos/logo_service_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/sync/sync_service_factory.h" -#include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/webui/browser_command/browser_command_handler.h" #include "chrome/browser/ui/webui/cr_components/most_visited/most_visited_handler.h" #include "chrome/browser/ui/webui/customize_themes/chrome_customize_themes_handler.h" @@ -73,6 +73,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/web_ui_util.h" +#include "ui/color/color_provider.h" #include "ui/native_theme/native_theme.h" #include "ui/resources/grit/webui_generated_resources.h" #include "url/url_util.h" @@ -732,18 +733,9 @@ void NewTabPageUI::OnThemeChanged() { base::Value::Dict update; - - const ui::ThemeProvider* theme_provider = - webui::GetThemeProvider(web_contents_); - // TODO(crbug.com/1299925): Always mock theme provider in tests so that - // `theme_provider` is never nullptr. - if (theme_provider) { - auto background_color = - theme_provider->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND); - update.Set("backgroundColor", skia::SkColorToHexString(background_color)); - } else { - update.Set("backgroundColor", ""); - } + const ui::ColorProvider& color_provider = web_contents_->GetColorProvider(); + auto background_color = color_provider.GetColor(kColorNewTabPageBackground); + update.Set("backgroundColor", skia::SkColorToHexString(background_color)); content::WebUIDataSource::Update(profile_, chrome::kChromeUINewTabPageHost, std::move(update)); }
diff --git a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_handler.cc b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_handler.cc index 77c6201..718ddd9 100644 --- a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_handler.cc +++ b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_handler.cc
@@ -8,12 +8,14 @@ #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/webui/ntp/ntp_resource_cache.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/pref_names.h" #include "chrome/grit/theme_resources.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_contents.h" +#include "ui/color/color_provider.h" #include "ui/gfx/color_utils.h" NewTabPageThirdPartyHandler::NewTabPageThirdPartyHandler( @@ -53,16 +55,17 @@ const ui::ThemeProvider* theme_provider = webui::GetThemeProvider(web_contents_); DCHECK(theme_provider); + const ui::ColorProvider& color_provider = web_contents_->GetColorProvider(); most_visited->background_color = - theme_provider->GetColor(ThemeProperties::COLOR_NTP_SHORTCUT); + color_provider.GetColor(kColorNewTabPageMostVisitedTileBackground); most_visited->use_white_tile_icon = color_utils::IsDark(most_visited->background_color); most_visited->use_title_pill = false; - theme->text_color = theme_provider->GetColor(ThemeProperties::COLOR_NTP_TEXT); + theme->text_color = color_provider.GetColor(kColorNewTabPageText); most_visited->is_dark = !color_utils::IsDark(theme->text_color); - theme->color_background = color_utils::SkColorToRgbaString( - GetThemeColor(webui::GetNativeTheme(web_contents_), *theme_provider, - ThemeProperties::COLOR_NTP_BACKGROUND)); + theme->color_background = color_utils::SkColorToRgbaString(GetThemeColor( + webui::GetNativeTheme(web_contents_), web_contents_->GetColorProvider(), + kColorNewTabPageBackground)); if (theme_provider->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) { theme->background_tiling = GetNewTabBackgroundTilingCSS(*theme_provider); theme->background_position =
diff --git a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc index a69f085..dd334a0 100644 --- a/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/webui/cr_components/most_visited/most_visited_handler.h" #include "chrome/browser/ui/webui/customize_themes/chrome_customize_themes_handler.h" #include "chrome/browser/ui/webui/favicon_source.h" @@ -33,6 +34,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/color/color_provider.h" #include "ui/gfx/color_utils.h" #include "ui/resources/grit/webui_generated_resources.h" #include "url/url_util.h" @@ -66,14 +68,15 @@ // TODO(crbug.com/1299925): Always mock theme provider in tests so that // `theme_provider` is never nullptr. if (theme_provider) { + const ui::ColorProvider& color_provider = web_contents->GetColorProvider(); source->AddString("backgroundPosition", GetNewTabBackgroundPositionCSS(*theme_provider)); source->AddString("backgroundTiling", GetNewTabBackgroundTilingCSS(*theme_provider)); source->AddString("colorBackground", color_utils::SkColorToRgbaString(GetThemeColor( - webui::GetNativeTheme(web_contents), *theme_provider, - ThemeProperties::COLOR_NTP_BACKGROUND))); + webui::GetNativeTheme(web_contents), color_provider, + kColorNewTabPageBackground))); // TODO(crbug.com/1056758): don't get theme id from profile. source->AddString("themeId", profile->GetPrefs()->GetString(prefs::kCurrentThemeID)); @@ -81,10 +84,11 @@ theme_provider->HasCustomImage(IDR_THEME_NTP_BACKGROUND) ? "has-custom-background" : ""); - source->AddString("isdark", !color_utils::IsDark(theme_provider->GetColor( - ThemeProperties::COLOR_NTP_TEXT)) - ? "dark" - : ""); + source->AddString( + "isdark", + !color_utils::IsDark(color_provider.GetColor(kColorNewTabPageText)) + ? "dark" + : ""); } else { source->AddString("backgroundPosition", ""); source->AddString("backgroundTiling", "");
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc index 8048353..65bb8cb 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/cookie_controls/cookie_controls_service.h" #include "chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h" #include "chrome/browser/ui/layout_constants.h" @@ -51,6 +52,7 @@ #include "ui/base/theme_provider.h" #include "ui/base/webui/jstemplate_builder.h" #include "ui/base/webui/web_ui_util.h" +#include "ui/color/color_provider.h" #include "ui/gfx/color_utils.h" #include "ui/native_theme/native_theme.h" @@ -96,9 +98,9 @@ } // namespace SkColor GetThemeColor(const ui::NativeTheme* native_theme, - const ui::ThemeProvider& tp, + const ui::ColorProvider& cp, int id) { - SkColor color = tp.GetColor(id); + SkColor color = cp.GetColor(id); // If web contents are being inverted because the system is in high-contrast // mode, any system theme colors we use must be inverted too to cancel out. return native_theme->GetPlatformHighContrastColorScheme() == @@ -436,8 +438,9 @@ profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); // Colors. + const ui::ColorProvider& cp = web_contents->GetColorProvider(); substitutions["colorBackground"] = color_utils::SkColorToRgbaString( - GetThemeColor(native_theme, *tp, ThemeProperties::COLOR_NTP_BACKGROUND)); + GetThemeColor(native_theme, cp, kColorNewTabPageBackground)); substitutions["backgroundPosition"] = GetNewTabBackgroundPositionCSS(*tp); substitutions["backgroundTiling"] = GetNewTabBackgroundTilingCSS(*tp); @@ -463,17 +466,17 @@ const ui::ThemeProvider* tp = webui::GetThemeProvider(web_contents); DCHECK(tp); + const ui::ColorProvider& cp = web_contents->GetColorProvider(); // Get our theme colors. SkColor color_background = - GetThemeColor(native_theme, *tp, ThemeProperties::COLOR_NTP_BACKGROUND); - SkColor color_text = - GetThemeColor(native_theme, *tp, ThemeProperties::COLOR_NTP_TEXT); + GetThemeColor(native_theme, cp, kColorNewTabPageBackground); + SkColor color_text = GetThemeColor(native_theme, cp, kColorNewTabPageText); SkColor color_text_light = - GetThemeColor(native_theme, *tp, ThemeProperties::COLOR_NTP_TEXT_LIGHT); + GetThemeColor(native_theme, cp, kColorNewTabPageTextLight); - SkColor color_section_border = GetThemeColor( - native_theme, *tp, ThemeProperties::COLOR_NTP_SECTION_BORDER); + SkColor color_section_border = + GetThemeColor(native_theme, cp, kColorNewTabPageSectionBorder); // Generate the replacements. ui::TemplateReplacements substitutions; @@ -486,7 +489,7 @@ substitutions["colorBackground"] = color_utils::SkColorToRgbaString(color_background); substitutions["colorLink"] = color_utils::SkColorToRgbString( - GetThemeColor(native_theme, *tp, ThemeProperties::COLOR_NTP_LINK)); + GetThemeColor(native_theme, cp, kColorNewTabPageLink)); substitutions["backgroundPosition"] = GetNewTabBackgroundPositionCSS(*tp); substitutions["backgroundTiling"] = GetNewTabBackgroundTilingCSS(*tp); substitutions["colorTextRgba"] = color_utils::SkColorToRgbaString(color_text);
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h index 19fab17d..b7a5780 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
@@ -31,11 +31,12 @@ } namespace ui { +class ColorProvider; class ThemeProvider; } SkColor GetThemeColor(const ui::NativeTheme* native_theme, - const ui::ThemeProvider& tp, + const ui::ColorProvider& cp, int id); std::string GetNewTabBackgroundPositionCSS( const ui::ThemeProvider& theme_provider);
diff --git a/chrome/browser/user_education/BUILD.gn b/chrome/browser/user_education/BUILD.gn index d2b95be8..584f8a1c 100644 --- a/chrome/browser/user_education/BUILD.gn +++ b/chrome/browser/user_education/BUILD.gn
@@ -30,7 +30,7 @@ resources_package = "org.chromium.chrome.browser.user_education" } -android_library("javatests") { +android_library("unit_device_javatests") { testonly = true sources = [ "java/src/org/chromium/chrome/browser/user_education/UserEducationHelperTest.java" ] deps = [
diff --git a/chrome/browser/video_tutorials/internal/BUILD.gn b/chrome/browser/video_tutorials/internal/BUILD.gn index 7cd9672..7064c077 100644 --- a/chrome/browser/video_tutorials/internal/BUILD.gn +++ b/chrome/browser/video_tutorials/internal/BUILD.gn
@@ -169,7 +169,7 @@ ] } - android_library("javatests") { + android_library("unit_device_javatests") { testonly = true sources = [ @@ -186,7 +186,7 @@ "//chrome/browser/flags:java", "//chrome/browser/video_tutorials:java", "//chrome/browser/video_tutorials:test_support_java", - "//chrome/test/android:chrome_java_integration_test_support", + "//chrome/test/android:chrome_java_unit_test_support", "//components/thin_webview:java", "//content/public/test/android:content_java_test_support", "//third_party/android_deps:espresso_java",
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 3fd7b143..30a9473 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1655294346-c876148f524c81c174531ff766e1fa43d90b9791.profdata +chrome-linux-main-1655315802-81d864008e6376e5b47455e1b42857e9b316eb80.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 5164718..d81d9305 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1655294346-4a5bc99f5b4fe93c7d4763d8221e8218e91122e8.profdata +chrome-mac-arm-main-1655315802-6327d5236b3274d9db4bcef3b32ca9cf9b5aab2f.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 5575052d..5678c305 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1655294346-f4e35791941cc71d1365cea78981b45b64b6c434.profdata +chrome-mac-main-1655315802-fa5ce9679a0b26173e4bb435e646fb867684eb4a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 14f67552..3a2226eb 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1655294346-a80f753b10bef44bf5fb84f9fb2fd5f4d81a5751.profdata +chrome-win32-main-1655315802-ea1cdc796e9bd324873db95d23f31e04f5ae5db1.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 71636c83..7480933 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1655294346-90cd3cca84f28e326c3c9cd179fadbca0e32005e.profdata +chrome-win64-main-1655305046-49e31d8168e3841e34a4495d3f79e78d5a3b9592.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 35795e3..81d2688 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6457,12 +6457,9 @@ "../browser/sessions/restore_on_startup_policy_handler_unittest.cc", "../browser/sessions/tab_restore_service_unittest.cc", "../browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc", - "../browser/sharing/shared_clipboard/shared_clipboard_context_menu_observer_unittest.cc", "../browser/sharing/shared_clipboard/shared_clipboard_message_handler_desktop_unittest.cc", "../browser/sharing/shared_clipboard/shared_clipboard_test_base.cc", "../browser/sharing/shared_clipboard/shared_clipboard_test_base.h", - "../browser/sharing/shared_clipboard/shared_clipboard_ui_controller_unittest.cc", - "../browser/sharing/shared_clipboard/shared_clipboard_utils_unittest.cc", "../browser/sharing/sms/sms_remote_fetcher_unittest.cc", "../browser/signin/signin_promo_unittest.cc", "../browser/speech/extension_api/extension_manifests_tts_unittest.cc",
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc index b51753c..00e5e6d 100644 --- a/chrome/test/base/chrome_test_launcher.cc +++ b/chrome/test/base/chrome_test_launcher.cc
@@ -58,6 +58,7 @@ #if BUILDFLAG(IS_WIN) #include <Shlobj.h> +#include "base/debug/handle_hooks_win.h" #include "base/win/registry.h" #include "base/win/scoped_com_initializer.h" #include "chrome/app/chrome_crash_reporter_client_win.h" @@ -255,7 +256,10 @@ #if BUILDFLAG(IS_WIN) // Create a primordial InstallDetails instance for the test. install_static::ScopedInstallDetails install_details; -#endif + + // Install handle hooks for tests only. + base::debug::HandleHooks::PatchLoadedModules(); +#endif // BUILDFLAG(IS_WIN) const auto& command_line = *base::CommandLine::ForCurrentProcess();
diff --git a/chrome/test/chromedriver/key_converter.cc b/chrome/test/chromedriver/key_converter.cc index 76c1c2da..46c3fed 100644 --- a/chrome/test/chromedriver/key_converter.cc +++ b/chrome/test/chromedriver/key_converter.cc
@@ -622,7 +622,7 @@ if (!action_object->GetString("value", &raw_key)) return Status(kUnknownError, "missing 'value'"); - int32_t char_index = 0; + size_t char_index = 0; base_icu::UChar32 code_point; base::ReadUnicodeCharacter(raw_key.c_str(), raw_key.size(), &char_index, &code_point);
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc index 87d1551..34f0475 100644 --- a/chrome/test/chromedriver/window_commands.cc +++ b/chrome/test/chromedriver/window_commands.cc
@@ -1400,12 +1400,11 @@ bool valid = action_item->GetString("value", &key); if (valid) { // check if key is a single unicode code point - int32_t char_index = 0; + size_t char_index = 0; base_icu::UChar32 code_point; - valid = - base::ReadUnicodeCharacter(key.c_str(), key.size(), &char_index, - &code_point) && - static_cast<std::string::size_type>(char_index + 1) == key.size(); + valid = base::ReadUnicodeCharacter(key.c_str(), key.size(), + &char_index, &code_point) && + char_index + 1 == key.size(); } if (!valid) return Status(kInvalidArgument,
diff --git a/chrome/test/data/android/download/get.html b/chrome/test/data/android/download/get.html index cfcc875..1387f19f 100644 --- a/chrome/test/data/android/download/get.html +++ b/chrome/test/data/android/download/get.html
@@ -1,3 +1,3 @@ <html><body style="height:100%;"> - <a href="test.gzip" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;">test.gzip</a> + <a href="test.gzip" target="_blank" style="display:block;position:absolute;top:0;left:0;width:100%;height:100%;">test.gzip</a> </body></html>
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js index d36ba6f..78b16b5 100644 --- a/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js +++ b/chrome/test/data/webui/chromeos/os_feedback_ui/share_data_page_test.js
@@ -9,6 +9,7 @@ import {FeedbackFlowState} from 'chrome://os-feedback/feedback_flow.js'; import {ShareDataPageElement} from 'chrome://os-feedback/share_data_page.js'; import {mojoString16ToString, stringToMojoString16} from 'chrome://resources/ash/common/mojo_utils.js'; +import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js'; import {eventToPromise, flushTasks, isVisible} from '../../test_util.js'; @@ -89,14 +90,17 @@ // Verify the back button is in the page. assertEquals('Back', getElementContent('#buttonBack')); + assertTrue(page.i18nExists('backButtonLabel')); // Verify the send button is in the page. assertEquals('Send', getElementContent('#buttonSend')); // Verify the attach files label is in the page. + assertTrue(page.i18nExists('attachFilesLabel')); assertEquals('Attach files', getElementContent('#attachFilesLabel')); // Verify the user email label is in the page. + assertTrue(page.i18nExists('userEmailLabel')); assertEquals('Email', getElementContent('#userEmailLabel')); // Verify the share diagnostic data label is in the page. @@ -365,4 +369,92 @@ fakeFileData, /** @type {!Array<Number>} */ (attachedFile.fileData.bytes)); }); + + /** + * Test that when page initially loaded "user-consent" checkbox is false and + * expected localize message displayed. + */ + test('UserConsentGrantedCheckbox_StartsFalse', async () => { + const expectedUserConsentMessage = + 'We may email you for more information or updates'; + await initializePage(); + + assertTrue(page.i18nExists('userConsentLabel')); + + const userConsentCheckboxChecked = + getElement('#userConsentCheckbox').checked; + const userConsentText = getElementContent('#userConsentLabel'); + + assertFalse(userConsentCheckboxChecked); + assertEquals(expectedUserConsentMessage, userConsentText); + }); + + /** + * Test that report "contact_user_consent_granted" matches "user-consent" + * checkbox value. + */ + test( + 'UserConsentGrantedCheckbox_UpdatesReportContactUserConsentGranted', + async () => { + await initializePage(); + page.feedbackContext = fakeFeedbackContext; + getElement('#userConsentCheckbox').checked = true; + await flushTasks(); + + const reportWithConsent = (await clickSendAndWait(page)).report; + + assertTrue(reportWithConsent.contactUserConsentGranted); + + page.reEnableSendReportButton(); + page.feedbackContext = fakeFeedbackContext; + getElement('#userConsentCheckbox').checked = false; + await flushTasks(); + + const reportWithoutConsent = (await clickSendAndWait(page)).report; + assertFalse(reportWithoutConsent.contactUserConsentGranted); + }); + + /** + * Test that when report is anonymous (no email provided), "user-consent" + * checkbox is disabled and value is false. + */ + test( + 'UserConsentGrantedCheckbox_ReportAnonymous_FalseAndDisabled', + async () => { + await initializePage(); + page.feedbackContext = fakeFeedbackContext; + const disabledInputClass = 'disabled-input-text'; + + const consentLabel = getElement('#userConsentLabel'); + const consentCheckbox = getElement('#userConsentCheckbox'); + const emailDropdown = getElement('#userEmailDropDown'); + + // Select the email. + emailDropdown.value = 'test.user2@test.com'; + await flushTasks(); + + // With email selected and consent not granted. + assertFalse(consentCheckbox.disabled); + assertFalse(consentCheckbox.checked); + assertFalse(consentLabel.classList.contains(disabledInputClass)); + + // Check checkbox. + consentCheckbox.click(); + await flushTasks(); + + // With email selected and consent granted. + assertFalse(consentCheckbox.disabled); + assertTrue(consentCheckbox.checked); + assertFalse(consentLabel.classList.contains(disabledInputClass)); + + // Select the "Do Not Provide Email" option. + emailDropdown.value = ''; + emailDropdown.dispatchEvent(new CustomEvent('change')); + flush(); + + // With anonymous email selected and consent not granted. + assertTrue(consentCheckbox.disabled); + assertFalse(consentCheckbox.checked); + assertTrue(consentLabel.classList.contains(disabledInputClass)); + }); }
diff --git a/chrome/test/data/webui/js/cr/ui/BUILD.gn b/chrome/test/data/webui/js/cr/ui/BUILD.gn index a8a825d..12b5ee8 100644 --- a/chrome/test/data/webui/js/cr/ui/BUILD.gn +++ b/chrome/test/data/webui/js/cr/ui/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/chromeos/ui_mode.gni") import("//third_party/closure_compiler/compile_js.gni") js_library("array_data_model_test") { @@ -28,36 +29,38 @@ ] } -js_library("grid_test") { - deps = [ - "../../..:chai_assert", - "//ui/webui/resources/js/cr/ui:array_data_model.m", - "//ui/webui/resources/js/cr/ui:grid.m", - ] -} +if (is_chromeos_ash) { + js_library("grid_test") { + deps = [ + "../../..:chai_assert", + "//ui/webui/resources/js/cr/ui:array_data_model.m", + "//ui/webui/resources/js/cr/ui:grid.m", + ] + } -js_library("list_selection_model_test") { - deps = [ - ":list_selection_model_test_util", - "../../..:chai_assert", - "//ui/webui/resources/js/cr/ui:list_selection_model.m", - ] -} + js_library("list_selection_model_test") { + deps = [ + ":list_selection_model_test_util", + "../../..:chai_assert", + "//ui/webui/resources/js/cr/ui:list_selection_model.m", + ] + } -js_library("list_selection_model_test_util") { - deps = [ - "../../..:chai_assert", - "//ui/webui/resources/js/cr/ui:list_selection_model.m", - "//ui/webui/resources/js/cr/ui:list_single_selection_model.m", - ] -} + js_library("list_selection_model_test_util") { + deps = [ + "../../..:chai_assert", + "//ui/webui/resources/js/cr/ui:list_selection_model.m", + "//ui/webui/resources/js/cr/ui:list_single_selection_model.m", + ] + } -js_library("list_single_selection_model_test") { - deps = [ - ":list_selection_model_test_util", - "../../..:chai_assert", - "//ui/webui/resources/js/cr/ui:list_single_selection_model.m", - ] + js_library("list_single_selection_model_test") { + deps = [ + ":list_selection_model_test_util", + "../../..:chai_assert", + "//ui/webui/resources/js/cr/ui:list_single_selection_model.m", + ] + } } js_library("list_test") { @@ -109,14 +112,19 @@ ":array_data_model_test", ":command_test", ":context_menu_handler_test", - ":grid_test", - ":list_selection_model_test", - ":list_selection_model_test_util", - ":list_single_selection_model_test", ":list_test", ":menu_button_test", ":menu_test", ":position_util_test", ":splitter_test", ] + + if (is_chromeos_ash) { + deps += [ + ":grid_test", + ":list_selection_model_test", + ":list_selection_model_test_util", + ":list_single_selection_model_test", + ] + } }
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn index 5d13862..3abed204 100644 --- a/chrome/test/data/webui/settings/BUILD.gn +++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -35,6 +35,7 @@ preprocessed_files += [ "test_languages_browser_proxy.ts", "languages_page_tests.ts", + "languages_page_metrics_test_browser.ts", ] } @@ -155,7 +156,6 @@ } else { non_preprocessed_files += [ "fake_language_settings_private.ts", - "languages_page_metrics_test_browser.ts", "languages_subpage_details_tests.ts", "languages_subpage_tests.ts", "languages_tests.ts",
diff --git a/chrome/test/data/webui/settings/chromeos/cups_printer_entry_tests.js b/chrome/test/data/webui/settings/chromeos/cups_printer_entry_tests.js index a0044c0e..dc4e3762d 100644 --- a/chrome/test/data/webui/settings/chromeos/cups_printer_entry_tests.js +++ b/chrome/test/data/webui/settings/chromeos/cups_printer_entry_tests.js
@@ -72,9 +72,13 @@ verifyFilteredPrinters(printerEntryListTestElement, searchTerm); if (expectedVisiblePrinters.length) { - assertTrue(printerEntryListTestElement.$$('#no-search-results').hidden); + assertTrue(printerEntryListTestElement.shadowRoot + .querySelector('#no-search-results') + .hidden); } else { - assertFalse(printerEntryListTestElement.$$('#no-search-results').hidden); + assertFalse(printerEntryListTestElement.shadowRoot + .querySelector('#no-search-results') + .hidden); } } @@ -156,13 +160,15 @@ createPrinterEntry(PrinterType.SAVED); // Assert that three dot menu is not shown before the dom is updated. - assertFalse(!!printerEntryTestElement.$$('.icon-more-vert')); + assertFalse( + !!printerEntryTestElement.shadowRoot.querySelector('.icon-more-vert')); flush(); // Three dot menu should be visible when |printerType| is set to // PrinterType.SAVED. - assertTrue(!!printerEntryTestElement.$$('.icon-more-vert')); + assertTrue( + !!printerEntryTestElement.shadowRoot.querySelector('.icon-more-vert')); }); test('disableButtonWhenSavingPrinterOrDisallowedByPolicy', function() { @@ -176,7 +182,8 @@ printerEntryTestElement.printerEntry = createPrinterEntry(printerTypes[i]); flush(); - const actionButton = printerEntryTestElement.$$(printerIds[i]); + const actionButton = + printerEntryTestElement.shadowRoot.querySelector(printerIds[i]); printerEntryTestElement.savingPrinter = true; printerEntryTestElement.userPrintersAllowed = true; assertTrue(actionButton.disabled);
diff --git a/chrome/test/data/webui/settings/chromeos/cups_printer_landing_page_tests.js b/chrome/test/data/webui/settings/chromeos/cups_printer_landing_page_tests.js index f1e4afa..eace098 100644 --- a/chrome/test/data/webui/settings/chromeos/cups_printer_landing_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/cups_printer_landing_page_tests.js
@@ -45,7 +45,7 @@ * @private */ function initializeEditDialog(page) { - const editDialog = page.$$('#editPrinterDialog'); + const editDialog = page.shadowRoot.querySelector('#editPrinterDialog'); assertTrue(!!editDialog); // Edit dialog will reset |ppdModel| when |ppdManufacturer| is set. Must @@ -146,15 +146,18 @@ */ function verifySearchQueryResults( printersElement, expectedVisiblePrinters, searchTerm) { - const printerEntryListTestElement = printersElement.$$('#printerEntryList'); + const printerEntryListTestElement = + printersElement.shadowRoot.querySelector('#printerEntryList'); verifyVisiblePrinters(printerEntryListTestElement, expectedVisiblePrinters); verifyFilteredPrinters(printerEntryListTestElement, searchTerm); if (expectedVisiblePrinters.length) { - assertTrue(printersElement.$$('#no-search-results').hidden); + assertTrue( + printersElement.shadowRoot.querySelector('#no-search-results').hidden); } else { - assertFalse(printersElement.$$('#no-search-results').hidden); + assertFalse( + printersElement.shadowRoot.querySelector('#no-search-results').hidden); } } @@ -169,8 +172,9 @@ const printerList = cupsPrintersBrowserProxy.printerList.printerList; const savedPrinterEntries = getPrinterEntries(savedPrintersElement); - clickButton(savedPrinterEntries[index].$$('.icon-more-vert')); - clickButton(savedPrintersElement.$$('#removeButton')); + clickButton( + savedPrinterEntries[index].shadowRoot.querySelector('.icon-more-vert')); + clickButton(savedPrintersElement.shadowRoot.querySelector('#removeButton')); return cupsPrintersBrowserProxy.whenCalled('removeCupsPrinter') .then(function() { @@ -236,7 +240,8 @@ // |cupsPrinterBrowserProxy| needs to have a list of saved printers before // initializing the landing page. cupsPrintersBrowserProxy.printerList = {printerList: printerList}; - CupsPrintersBrowserProxyImpl.instance_ = cupsPrintersBrowserProxy; + CupsPrintersBrowserProxyImpl.setInstanceForTesting( + cupsPrintersBrowserProxy); page = document.createElement('settings-cups-printers'); document.body.appendChild(page); @@ -276,12 +281,14 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); // List component contained by CupsSavedPrinters. const savedPrintersList = - savedPrintersElement.$$('settings-cups-printers-entry-list'); + savedPrintersElement.shadowRoot.querySelector( + 'settings-cups-printers-entry-list'); const printerListEntries = getPrinterEntries(savedPrintersElement); @@ -302,7 +309,8 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); return removeAllPrinters( @@ -329,22 +337,23 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); - savedPrintersList = - savedPrintersElement.$$('settings-cups-printers-entry-list'); + savedPrintersList = savedPrintersElement.shadowRoot.querySelector( + 'settings-cups-printers-entry-list'); savedPrinterEntries = getPrinterEntries(savedPrintersElement); verifyPrintersList(savedPrinterEntries, printerList); - assertTrue(!!page.$$('#savedPrinters')); + assertTrue(!!page.shadowRoot.querySelector('#savedPrinters')); return removeAllPrinters( cupsPrintersBrowserProxy, savedPrintersElement); }) .then(() => { - assertFalse(!!page.$$('#savedPrinters')); + assertFalse(!!page.shadowRoot.querySelector('#savedPrinters')); }); }); @@ -364,28 +373,32 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); savedPrinterEntries = getPrinterEntries(savedPrintersElement); // Update the printer name of the first entry. - clickButton(savedPrinterEntries[0].$$('.icon-more-vert')); - clickButton(savedPrintersElement.$$('#editButton')); + clickButton(savedPrinterEntries[0].shadowRoot.querySelector( + '.icon-more-vert')); + clickButton( + savedPrintersElement.shadowRoot.querySelector('#editButton')); flush(); editDialog = initializeEditDialog(page); // Change name of printer and save the change. - const nameField = editDialog.$$('.printer-name-input'); + const nameField = + editDialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); nameField.value = expectedName; nameField.fire('input'); flush(); - clickButton(editDialog.$$('.action-button')); + clickButton(editDialog.shadowRoot.querySelector('.action-button')); return cupsPrintersBrowserProxy.whenCalled('updateCupsPrinter'); }) @@ -416,35 +429,42 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); savedPrinterEntries = getPrinterEntries(savedPrintersElement); // Edit the first entry. - clickButton(savedPrinterEntries[0].$$('.icon-more-vert')); - clickButton(savedPrintersElement.$$('#editButton')); + clickButton(savedPrinterEntries[0].shadowRoot.querySelector( + '.icon-more-vert')); + clickButton( + savedPrintersElement.shadowRoot.querySelector('#editButton')); flush(); editDialog = initializeEditDialog(page); - const nameField = editDialog.$$('.printer-name-input'); + const nameField = + editDialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); nameField.value = expectedName; nameField.fire('input'); - const addressField = editDialog.$$('#printerAddress'); + const addressField = + editDialog.shadowRoot.querySelector('#printerAddress'); assertTrue(!!addressField); addressField.value = expectedAddress; addressField.fire('input'); - assertFalse(editDialog.$$('.cancel-button').hidden); - assertFalse(editDialog.$$('.action-button').hidden); + assertFalse( + editDialog.shadowRoot.querySelector('.cancel-button').hidden); + assertFalse( + editDialog.shadowRoot.querySelector('.action-button').hidden); flush(); - clickButton(editDialog.$$('.action-button')); + clickButton(editDialog.shadowRoot.querySelector('.action-button')); return cupsPrintersBrowserProxy.whenCalled('reconfigureCupsPrinter'); }) @@ -472,7 +492,8 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerListEntries = getPrinterEntries(savedPrintersElement); @@ -531,7 +552,8 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerListEntries = getPrinterEntries(savedPrintersElement); @@ -578,9 +600,12 @@ .then(async () => { // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); - const printerEntryList = savedPrintersElement.$$('#printerEntryList'); + const printerEntryList = + savedPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); const printerListEntries = getPrinterEntries(savedPrintersElement); printerEntryList.focus(); printerEntryList.dispatchEvent(arrowDownEvent); @@ -614,10 +639,12 @@ flush(); - const savedPrinters = page.$$('settings-cups-saved-printers'); - const printerEntry = - savedPrinters && savedPrinters.$$('settings-cups-printers-entry'); - const deepLinkElement = printerEntry && printerEntry.$$('#moreActions'); + const savedPrinters = + page.shadowRoot.querySelector('settings-cups-saved-printers'); + const printerEntry = savedPrinters && + savedPrinters.shadowRoot.querySelector('settings-cups-printers-entry'); + const deepLinkElement = + printerEntry && printerEntry.shadowRoot.querySelector('#moreActions'); await waitAfterNextRender(deepLinkElement); assertEquals( deepLinkElement, getDeepActiveElement(), @@ -635,11 +662,13 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerEntryListTestElement = - savedPrintersElement.$$('#printerEntryList'); + savedPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); verifyVisiblePrinters(printerEntryListTestElement, [ createPrinterListEntry('google', '4', 'id4', PrinterType.SAVED), @@ -648,7 +677,8 @@ ]); // Assert that the Show more button is hidden because printer list // length is <= 3. - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Newly added printers will always be visible and inserted to the // top of the list. @@ -663,7 +693,8 @@ printerEntryListTestElement, expectedVisiblePrinters); // Assert that the Show more button is still hidden because all newly // added printers are visible. - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); }); }); @@ -679,11 +710,13 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerEntryListTestElement = - savedPrintersElement.$$('#printerEntryList'); + savedPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); // There are 4 total printers but only 3 printers are visible and 1 is // hidden underneath the Show more section. @@ -694,11 +727,14 @@ ]); // Assert that the Show more button is shown since printer list length // is > 3. - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Click on the Show more button. - clickButton(savedPrintersElement.$$('#show-more-icon')); - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + clickButton( + savedPrintersElement.shadowRoot.querySelector('#show-more-icon')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Clicking on the Show more button reveals all hidden printers. verifyVisiblePrinters(printerEntryListTestElement, [ createPrinterListEntry('google', '4', 'id4', PrinterType.SAVED), @@ -721,11 +757,13 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerEntryListTestElement = - savedPrintersElement.$$('#printerEntryList'); + savedPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); // There are 4 total printers but only 3 printers are visible and 1 is // hidden underneath the Show more section. @@ -736,7 +774,8 @@ ]); // Assert that the Show more button is shown since printer list length // is > 3. - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Newly added printers will always be visible. addNewSavedPrinter(createCupsPrinterInfo('test5', '5', 'id5')); @@ -747,7 +786,8 @@ createPrinterListEntry('test2', '2', 'id2', PrinterType.SAVED) ]); // Assert that the Show more button is still shown. - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); }); }); @@ -764,11 +804,13 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerEntryListTestElement = - savedPrintersElement.$$('#printerEntryList'); + savedPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); // There are 5 total printers but only 3 printers are visible and 2 // are hidden underneath the Show more section. @@ -779,7 +821,8 @@ ]); // Assert that the Show more button is shown since printer list length // is > 3. - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Simulate removing 'google' printer. removeSavedPrinter('id3'); @@ -792,7 +835,8 @@ createPrinterListEntry('google3', '5', 'id5', PrinterType.SAVED), createPrinterListEntry('test1', '1', 'id1', PrinterType.SAVED) ]); - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Simulate removing 'google2' printer. removeSavedPrinter('id4'); @@ -803,7 +847,8 @@ createPrinterListEntry('test1', '1', 'id1', PrinterType.SAVED), createPrinterListEntry('test2', '2', 'id2', PrinterType.SAVED) ]); - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); }); }); @@ -821,11 +866,13 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerEntryListTestElement = - savedPrintersElement.$$('#printerEntryList'); + savedPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); // There are 6 total printers but only 3 printers are visible and 3 // are hidden underneath the Show more section. @@ -836,7 +883,8 @@ ]); // Assert that the Show more button is shown since printer list length // is > 3. - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Set search term to 'google' and expect 4 visible printers. let searchTerm = 'google'; @@ -854,7 +902,8 @@ ], searchTerm); // Having a search term should hide the Show more button. - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Search for a term with no matching printers. Expect Show more // button to still be hidden. @@ -863,7 +912,8 @@ flush(); verifySearchQueryResults(savedPrintersElement, [], searchTerm); - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Change search term and expect new set of visible printers. searchTerm = 'test'; @@ -876,7 +926,8 @@ createPrinterListEntry('test2', '2', 'id2', PrinterType.SAVED) ], searchTerm); - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Remove the search term and expect the collapsed list to appear // again. @@ -892,7 +943,8 @@ savedPrintersElement, expectedVisiblePrinters, searchTerm); verifyVisiblePrinters( printerEntryListTestElement, expectedVisiblePrinters); - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); }); }); @@ -908,11 +960,13 @@ // Wait for saved printers to populate. flush(); - savedPrintersElement = page.$$('settings-cups-saved-printers'); + savedPrintersElement = + page.shadowRoot.querySelector('settings-cups-saved-printers'); assertTrue(!!savedPrintersElement); const printerEntryListTestElement = - savedPrintersElement.$$('#printerEntryList'); + savedPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); // There are 4 total printers but only 3 printers are visible and 1 is // hidden underneath the Show more section. @@ -923,7 +977,8 @@ ]); // Assert that the Show more button is shown since printer list length // is > 3. - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Add a new printer and expect it to be at the top of the list. addNewSavedPrinter(createCupsPrinterInfo('newPrinter', '5', 'id5')); @@ -933,7 +988,8 @@ createPrinterListEntry('google2', '4', 'id4', PrinterType.SAVED), createPrinterListEntry('test1', '1', 'id1', PrinterType.SAVED) ]); - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Now simulate removing printer 'test1'. removeSavedPrinter('id1'); @@ -946,7 +1002,8 @@ createPrinterListEntry('google', '3', 'id3', PrinterType.SAVED), createPrinterListEntry('google2', '4', 'id4', PrinterType.SAVED) ]); - assertTrue(!!savedPrintersElement.$$('#show-more-container')); + assertTrue(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Remove another printer and assert that we still have 3 visible // printers but now 'test2' is our third visible printer. @@ -957,7 +1014,8 @@ createPrinterListEntry('test2', '2', 'id2', PrinterType.SAVED) ]); // Printer list length is <= 3, Show more button should be hidden. - assertFalse(!!savedPrintersElement.$$('#show-more-container')); + assertFalse(!!savedPrintersElement.shadowRoot.querySelector( + '#show-more-container')); }); }); }); @@ -980,7 +1038,8 @@ const mojom = chromeos.networkConfig.mojom; cupsPrintersBrowserProxy = new TestCupsPrintersBrowserProxy(); - CupsPrintersBrowserProxyImpl.instance_ = cupsPrintersBrowserProxy; + CupsPrintersBrowserProxyImpl.setInstanceForTesting( + cupsPrintersBrowserProxy); // Simulate internet connection. wifi1 = OncMojo.getDefaultNetworkState(mojom.NetworkType.kWiFi, 'wifi1'); @@ -1015,7 +1074,8 @@ ]; return flushTasks().then(() => { - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertTrue(!!nearbyPrintersElement); // Assert that no printers have been detected. @@ -1064,7 +1124,8 @@ ]; return flushTasks().then(() => { - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertTrue(!!nearbyPrintersElement); // Simuluate finding nearby printers. @@ -1088,7 +1149,8 @@ return flushTasks() .then(() => { - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertTrue(!!nearbyPrintersElement); // Simuluate finding nearby printers. @@ -1102,11 +1164,13 @@ // printer has the correct button. const nearbyPrinterEntries = getPrinterEntries(nearbyPrintersElement); assertEquals(1, nearbyPrinterEntries.length); - assertTrue(!!nearbyPrinterEntries[0].$$('.save-printer-button')); + assertTrue(!!nearbyPrinterEntries[0].shadowRoot.querySelector( + '.save-printer-button')); // Add an automatic printer and assert that that the toast // notification is shown. - addButton = nearbyPrinterEntries[0].$$('.save-printer-button'); + addButton = nearbyPrinterEntries[0].shadowRoot.querySelector( + '.save-printer-button'); clickButton(addButton); // Add button should be disabled during setup. assertTrue(addButton.disabled); @@ -1117,7 +1181,9 @@ assertFalse(addButton.disabled); const expectedToastMessage = 'Added ' + automaticPrinterList[0].printerName; - verifyErrorToastMessage(expectedToastMessage, page.$$('#errorToast')); + verifyErrorToastMessage( + expectedToastMessage, + page.shadowRoot.querySelector('#errorToast')); }); }); @@ -1128,7 +1194,8 @@ createCupsPrinterInfo('third', '2', 'id5'), ]; return flushTasks().then(async () => { - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); // Block so that FocusRowBehavior.attached can run. await waitAfterNextRender(nearbyPrintersElement); @@ -1143,33 +1210,41 @@ // executed. await waitAfterNextRender(nearbyPrintersElement); const nearbyPrinterEntries = getPrinterEntries(nearbyPrintersElement); - const printerEntryList = nearbyPrintersElement.$$('#printerEntryList'); + const printerEntryList = + nearbyPrintersElement.shadowRoot.querySelector('#printerEntryList'); - nearbyPrinterEntries[0].$$('#entry').focus(); + nearbyPrinterEntries[0].shadowRoot.querySelector('#entry').focus(); assertEquals( - nearbyPrinterEntries[0].$$('#entry'), getDeepActiveElement()); + nearbyPrinterEntries[0].shadowRoot.querySelector('#entry'), + getDeepActiveElement()); // Ensure that we can navigate through items in a row getDeepActiveElement().dispatchEvent(arrowRightEvent); assertEquals( - nearbyPrinterEntries[0].$$('#setupPrinterButton'), + nearbyPrinterEntries[0].shadowRoot.querySelector( + '#setupPrinterButton'), getDeepActiveElement()); getDeepActiveElement().dispatchEvent(arrowLeftEvent); assertEquals( - nearbyPrinterEntries[0].$$('#entry'), getDeepActiveElement()); + nearbyPrinterEntries[0].shadowRoot.querySelector('#entry'), + getDeepActiveElement()); // Ensure that we can navigate through printer rows printerEntryList.dispatchEvent(arrowDownEvent); assertEquals( - nearbyPrinterEntries[1].$$('#entry'), getDeepActiveElement()); + nearbyPrinterEntries[1].shadowRoot.querySelector('#entry'), + getDeepActiveElement()); printerEntryList.dispatchEvent(arrowDownEvent); assertEquals( - nearbyPrinterEntries[2].$$('#entry'), getDeepActiveElement()); + nearbyPrinterEntries[2].shadowRoot.querySelector('#entry'), + getDeepActiveElement()); printerEntryList.dispatchEvent(arrowUpEvent); assertEquals( - nearbyPrinterEntries[1].$$('#entry'), getDeepActiveElement()); + nearbyPrinterEntries[1].shadowRoot.querySelector('#entry'), + getDeepActiveElement()); printerEntryList.dispatchEvent(arrowUpEvent); assertEquals( - nearbyPrinterEntries[0].$$('#entry'), getDeepActiveElement()); + nearbyPrinterEntries[0].shadowRoot.querySelector('#entry'), + getDeepActiveElement()); }); }); @@ -1182,7 +1257,8 @@ return flushTasks() .then(() => { - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertTrue(!!nearbyPrintersElement); // Simuluate finding nearby printers. @@ -1196,7 +1272,8 @@ // the correct icon button. const nearbyPrinterEntries = getPrinterEntries(nearbyPrintersElement); assertEquals(1, nearbyPrinterEntries.length); - assertTrue(!!nearbyPrinterEntries[0].$$('#setupPrinterButton')); + assertTrue(!!nearbyPrinterEntries[0].shadowRoot.querySelector( + '#setupPrinterButton')); // Force a failure with adding a discovered printer. cupsPrintersBrowserProxy.setAddDiscoveredPrinterFailure( @@ -1204,7 +1281,8 @@ // Assert that clicking on the setup button shows the advanced // configuration dialog. - setupButton = nearbyPrinterEntries[0].$$('#setupPrinterButton'); + setupButton = nearbyPrinterEntries[0].shadowRoot.querySelector( + '#setupPrinterButton'); clickButton(setupButton); // Setup button should be disabled during setup. assertTrue(setupButton.disabled); @@ -1215,22 +1293,25 @@ assertFalse(setupButton.disabled); flush(); - const addDialog = page.$$('#addPrinterDialog'); - manufacturerDialog = - addDialog.$$('add-printer-manufacturer-model-dialog'); + const addDialog = page.shadowRoot.querySelector('#addPrinterDialog'); + manufacturerDialog = addDialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog'); assertTrue(!!manufacturerDialog); return cupsPrintersBrowserProxy.whenCalled( 'getCupsPrinterManufacturersList'); }) .then(() => { - const addButton = manufacturerDialog.$$('#addPrinterButton'); + const addButton = + manufacturerDialog.shadowRoot.querySelector('#addPrinterButton'); assertTrue(addButton.disabled); // Populate the manufacturer and model fields to enable the Add // button. - manufacturerDialog.$$('#manufacturerDropdown').value = 'make'; - const modelDropdown = manufacturerDialog.$$('#modelDropdown'); + manufacturerDialog.shadowRoot.querySelector('#manufacturerDropdown') + .value = 'make'; + const modelDropdown = + manufacturerDialog.shadowRoot.querySelector('#modelDropdown'); modelDropdown.value = 'model'; clickButton(addButton); @@ -1241,7 +1322,9 @@ // message when adding a discovered printer. const expectedToastMessage = 'Added ' + discoveredPrinterList[0].printerName; - verifyErrorToastMessage(expectedToastMessage, page.$$('#errorToast')); + verifyErrorToastMessage( + expectedToastMessage, + page.shadowRoot.querySelector('#errorToast')); }); }); @@ -1256,9 +1339,10 @@ // We require internet to be able to add a new printer. Connecting to // a network without connectivity should be equivalent to not being // connected to a network. - assertTrue(!!page.$$('#cloudOffIcon')); - assertTrue(!!page.$$('#connectionMessage')); - assertTrue(!!page.$$('#addManualPrinterIcon').disabled); + assertTrue(!!page.shadowRoot.querySelector('#cloudOffIcon')); + assertTrue(!!page.shadowRoot.querySelector('#connectionMessage')); + assertTrue( + !!page.shadowRoot.querySelector('#addManualPrinterIcon').disabled); }); }); @@ -1273,9 +1357,10 @@ .then(() => { // Expect offline text to show up when no internet is // connected. - assertTrue(!!page.$$('#cloudOffIcon')); - assertTrue(!!page.$$('#connectionMessage')); - assertTrue(!!page.$$('#addManualPrinterIcon').disabled); + assertTrue(!!page.shadowRoot.querySelector('#cloudOffIcon')); + assertTrue(!!page.shadowRoot.querySelector('#connectionMessage')); + assertTrue(!!page.shadowRoot.querySelector('#addManualPrinterIcon') + .disabled); // Simulate connecting to a network with connectivity. wifi1.connectionState = @@ -1302,11 +1387,13 @@ flush(); - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertTrue(!!nearbyPrintersElement); printerEntryListTestElement = - nearbyPrintersElement.$$('#printerEntryList'); + nearbyPrintersElement.shadowRoot.querySelector( + '#printerEntryList'); assertTrue(!!printerEntryListTestElement); const nearbyPrinterEntries = getPrinterEntries(nearbyPrintersElement); @@ -1325,11 +1412,12 @@ ]; return flushTasks().then(() => { - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertTrue(!!nearbyPrintersElement); printerEntryListTestElement = - nearbyPrintersElement.$$('#printerEntryList'); + nearbyPrintersElement.shadowRoot.querySelector('#printerEntryList'); assertTrue(!!printerEntryListTestElement); // Simuluate finding nearby printers. @@ -1411,11 +1499,12 @@ ]; return flushTasks().then(() => { - nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertTrue(!!nearbyPrintersElement); printerEntryListTestElement = - nearbyPrintersElement.$$('#printerEntryList'); + nearbyPrintersElement.shadowRoot.querySelector('#printerEntryList'); assertTrue(!!printerEntryListTestElement); // Simuluate finding nearby printers. @@ -1492,7 +1581,8 @@ // |cupsPrinterBrowserProxy| needs to have a list of printers before // initializing the landing page. cupsPrintersBrowserProxy.printerList = {printerList: printerList}; - CupsPrintersBrowserProxyImpl.instance_ = cupsPrintersBrowserProxy; + CupsPrintersBrowserProxyImpl.setInstanceForTesting( + cupsPrintersBrowserProxy); page = document.createElement('settings-cups-printers'); document.body.appendChild(page); @@ -1513,10 +1603,11 @@ // Wait for saved printers to populate. flush(); - enterprisePrintersElement = - page.$$('settings-cups-enterprise-printers'); + enterprisePrintersElement = page.shadowRoot.querySelector( + 'settings-cups-enterprise-printers'); printerEntryListTestElement = - enterprisePrintersElement.$$('#printerEntryList'); + enterprisePrintersElement.shadowRoot.querySelector( + '#printerEntryList'); verifyVisiblePrinters(printerEntryListTestElement, [ createPrinterListEntry('test1', '1', 'id1', PrinterType.ENTERPRISE), createPrinterListEntry('test2', '2', 'id2', PrinterType.ENTERPRISE), @@ -1537,43 +1628,57 @@ // Wait for enterprise printers to populate. flush(); - enterprisePrintersElement = - page.$$('settings-cups-enterprise-printers'); + enterprisePrintersElement = page.shadowRoot.querySelector( + 'settings-cups-enterprise-printers'); assertTrue(!!enterprisePrintersElement); const enterprisePrinterEntries = getPrinterEntries(enterprisePrintersElement); // Users are not allowed to remove enterprise printers. - const removeButton = enterprisePrintersElement.$$('#removeButton'); + const removeButton = + enterprisePrintersElement.shadowRoot.querySelector( + '#removeButton'); assertTrue(removeButton.disabled); - clickButton(enterprisePrinterEntries[0].$$('.icon-more-vert')); - clickButton(enterprisePrintersElement.$$('#viewButton')); + clickButton(enterprisePrinterEntries[0].shadowRoot.querySelector( + '.icon-more-vert')); + clickButton(enterprisePrintersElement.shadowRoot.querySelector( + '#viewButton')); flush(); editDialog = initializeEditDialog(page); - const nameField = editDialog.$$('.printer-name-input'); + const nameField = + editDialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); assertEquals('test1', nameField.value); assertTrue(nameField.readonly); - assertTrue(editDialog.$$('#printerAddress').readonly); - assertTrue(editDialog.$$('.md-select').disabled); - assertTrue(editDialog.$$('#printerQueue').readonly); - assertTrue(editDialog.$$('#printerPPDManufacturer').readonly); + assertTrue( + editDialog.shadowRoot.querySelector('#printerAddress').readonly); + assertTrue( + editDialog.shadowRoot.querySelector('.md-select').disabled); + assertTrue( + editDialog.shadowRoot.querySelector('#printerQueue').readonly); + assertTrue( + editDialog.shadowRoot.querySelector('#printerPPDManufacturer') + .readonly); // The "specify PDD" section should be hidden. - assertTrue(editDialog.$$('.browse-button').parentElement.hidden); - assertTrue(editDialog.$$('#ppdLabel').hidden); + assertTrue(editDialog.shadowRoot.querySelector('.browse-button') + .parentElement.hidden); + assertTrue(editDialog.shadowRoot.querySelector('#ppdLabel').hidden); // Save and Cancel buttons should be hidden. Close button should be // visible. - assertTrue(editDialog.$$('.cancel-button').hidden); - assertTrue(editDialog.$$('.action-button').hidden); - assertFalse(editDialog.$$('.close-button').hidden); + assertTrue( + editDialog.shadowRoot.querySelector('.cancel-button').hidden); + assertTrue( + editDialog.shadowRoot.querySelector('.action-button').hidden); + assertFalse( + editDialog.shadowRoot.querySelector('.close-button').hidden); }); }); @@ -1589,12 +1694,13 @@ // Wait for enterprise printers to populate. flush(); - enterprisePrintersElement = - page.$$('settings-cups-enterprise-printers'); + enterprisePrintersElement = page.shadowRoot.querySelector( + 'settings-cups-enterprise-printers'); assertTrue(!!enterprisePrintersElement); const printerEntryListTestElement = - enterprisePrintersElement.$$('#printerEntryList'); + enterprisePrintersElement.shadowRoot.querySelector( + '#printerEntryList'); // There are 4 total printers but only 3 printers are visible and 1 is // hidden underneath the Show more section. @@ -1605,11 +1711,14 @@ ]); // Assert that the Show more button is shown since printer list length // is > 3. - assertTrue(!!enterprisePrintersElement.$$('#show-more-container')); + assertTrue(!!enterprisePrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Click on the Show more button. - clickButton(enterprisePrintersElement.$$('#show-more-icon')); - assertFalse(!!enterprisePrintersElement.$$('#show-more-container')); + clickButton(enterprisePrintersElement.shadowRoot.querySelector( + '#show-more-icon')); + assertFalse(!!enterprisePrintersElement.shadowRoot.querySelector( + '#show-more-container')); // Clicking on the Show more button reveals all hidden printers. verifyVisiblePrinters(printerEntryListTestElement, [ createPrinterListEntry('test1', '1', 'id1', PrinterType.ENTERPRISE),
diff --git a/chrome/test/data/webui/settings/chromeos/cups_printer_page_tests.js b/chrome/test/data/webui/settings/chromeos/cups_printer_page_tests.js index 53133ce..b75225b 100644 --- a/chrome/test/data/webui/settings/chromeos/cups_printer_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/cups_printer_page_tests.js
@@ -44,8 +44,8 @@ suite('CupsAddPrinterDialogTests', function() { function fillAddManuallyDialog(addDialog) { - const name = addDialog.$$('#printerNameInput'); - const address = addDialog.$$('#printerAddressInput'); + const name = addDialog.shadowRoot.querySelector('#printerNameInput'); + const address = addDialog.shadowRoot.querySelector('#printerAddressInput'); assertTrue(!!name); name.value = 'Test printer'; @@ -53,21 +53,21 @@ assertTrue(!!address); address.value = '127.0.0.1'; - const addButton = addDialog.$$('#addPrinterButton'); + const addButton = addDialog.shadowRoot.querySelector('#addPrinterButton'); assertTrue(!!addButton); assertFalse(addButton.disabled); } function clickAddButton(dialog) { assertTrue(!!dialog, 'Dialog is null for add'); - const addButton = dialog.$$('.action-button'); + const addButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!addButton, 'Button is null'); addButton.click(); } function clickCancelButton(dialog) { assertTrue(!!dialog, 'Dialog is null for cancel'); - const cancelButton = dialog.$$('.cancel-button'); + const cancelButton = dialog.shadowRoot.querySelector('.cancel-button'); assertTrue(!!cancelButton, 'Button is null'); cancelButton.click(); } @@ -80,16 +80,18 @@ function mockAddPrinterInputKeyboardPress(crInputId) { // Start in add manual dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); // Test that pressing Enter before all the fields are populated does not // advance to the next dialog. - const input = addDialog.$$(crInputId); + const input = addDialog.shadowRoot.querySelector(crInputId); keyEventOn(input, 'keypress', /*keycode=*/ 13, [], 'Enter'); flush(); - assertFalse(!!dialog.$$('add-printer-manufacturer-model-dialog')); + assertFalse(!!dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog')); assertFalse(dialog.showManufacturerDialog_); assertTrue(dialog.showManuallyAddDialog_); @@ -101,7 +103,8 @@ keyEventOn(input, 'keypress', /*keycode=*/ 16, [], 'Shift'); flush(); - assertFalse(!!dialog.$$('add-printer-manufacturer-model-dialog')); + assertFalse(!!dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog')); assertFalse(dialog.showManufacturerDialog_); assertTrue(dialog.showManuallyAddDialog_); @@ -118,7 +121,8 @@ setup(function() { cupsPrintersBrowserProxy = new TestCupsPrintersBrowserProxy(); - CupsPrintersBrowserProxyImpl.instance_ = cupsPrintersBrowserProxy; + CupsPrintersBrowserProxyImpl.setInstanceForTesting( + cupsPrintersBrowserProxy); PolymerTest.clearBody(); page = document.createElement('settings-cups-printers'); @@ -126,7 +130,7 @@ page.enableUpdatedUi_ = false; document.body.appendChild(page); assertTrue(!!page); - dialog = page.$$('settings-cups-add-printer-dialog'); + dialog = page.shadowRoot.querySelector('settings-cups-add-printer-dialog'); assertTrue(!!dialog); dialog.open(); @@ -202,12 +206,13 @@ */ test('ValidAddOpensModelSelection', function() { // Starts in add manual dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); fillAddManuallyDialog(addDialog); - addDialog.$$('.action-button').click(); + addDialog.shadowRoot.querySelector('.action-button').click(); flush(); // Upon rejection, show model. @@ -218,7 +223,8 @@ }) .then(function() { // Showing model selection. - assertTrue(!!dialog.$$('add-printer-manufacturer-model-dialog')); + assertTrue(!!dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog')); assertTrue(dialog.showManufacturerDialog_); assertFalse(dialog.showManuallyAddDialog_); @@ -231,7 +237,8 @@ */ test('GetPrinterInfoFailsGeneralError', function() { // Starts in add manual dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); @@ -242,7 +249,7 @@ PrinterSetupResult.FATAL_ERROR); // Attempt to add the printer. - addDialog.$$('.action-button').click(); + addDialog.shadowRoot.querySelector('.action-button').click(); flush(); // Upon rejection, show model. @@ -250,8 +257,11 @@ .then(function(result) { // The general error should be showing. assertTrue(!!addDialog.errorText_); - const generalErrorElement = addDialog.$$('printer-dialog-error'); - assertFalse(generalErrorElement.$$('#error-container').hidden); + const generalErrorElement = + addDialog.shadowRoot.querySelector('printer-dialog-error'); + assertFalse( + generalErrorElement.shadowRoot.querySelector('#error-container') + .hidden); }); }); @@ -262,7 +272,8 @@ */ test('GetPrinterInfoFailsUnreachableError', function() { // Starts in add manual dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); @@ -273,14 +284,15 @@ PrinterSetupResult.PRINTER_UNREACHABLE); // Attempt to add the printer. - addDialog.$$('.action-button').click(); + addDialog.shadowRoot.querySelector('.action-button').click(); flush(); // Upon rejection, show model. return cupsPrintersBrowserProxy.whenCalled('getPrinterInfo') .then(function(result) { // The printer address input should be marked as invalid. - assertTrue(addDialog.$$('#printerAddressInput').invalid); + assertTrue(addDialog.shadowRoot.querySelector('#printerAddressInput') + .invalid); }); }); @@ -290,7 +302,8 @@ */ test('NoBlankQueries', function() { // Starts in add manual dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); fillAddManuallyDialog(addDialog); @@ -304,14 +317,14 @@ cupsPrintersBrowserProxy.manufacturers = ['ManufacturerA', 'ManufacturerB', 'Chromites']; - addDialog.$$('.action-button').click(); + addDialog.shadowRoot.querySelector('.action-button').click(); flush(); return cupsPrintersBrowserProxy .whenCalled('getCupsPrinterManufacturersList') .then(function() { - const modelDialog = - dialog.$$('add-printer-manufacturer-model-dialog'); + const modelDialog = dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog'); assertTrue(!!modelDialog); // Manufacturer dialog has been rendered and the model list was not // requested. We're done. @@ -358,7 +371,8 @@ }; // Press the add button to advance dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); clickAddButton(addDialog); @@ -370,7 +384,8 @@ .then(function() { flush(); // Cancel setup with the cancel button. - clickCancelButton(dialog.$$('add-printer-manufacturer-model-dialog')); + clickCancelButton(dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog')); return cupsPrintersBrowserProxy.whenCalled('cancelPrinterSetUp'); }) .then(function(printer) { @@ -385,12 +400,13 @@ */ test('getEulaUrlGetsCalledOnModelChange', function() { // Start in add manual dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); fillAddManuallyDialog(addDialog); - addDialog.$$('.action-button').click(); + addDialog.shadowRoot.querySelector('.action-button').click(); flush(); const expectedEulaLink = 'chrome://os-credits/#google'; @@ -406,17 +422,20 @@ return cupsPrintersBrowserProxy .whenCalled('getCupsPrinterManufacturersList') .then(function() { - modelDialog = dialog.$$('add-printer-manufacturer-model-dialog'); + modelDialog = dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog'); assertTrue(!!modelDialog); - urlElement = modelDialog.$$('#eulaUrl'); + urlElement = modelDialog.shadowRoot.querySelector('#eulaUrl'); // Check that the EULA text is not shown. assertTrue(urlElement.hidden); cupsPrintersBrowserProxy.setEulaUrl(expectedEulaLink); - modelDialog.$$('#manufacturerDropdown').value = expectedManufacturer; - modelDropdown = modelDialog.$$('#modelDropdown'); + modelDialog.shadowRoot.querySelector('#manufacturerDropdown').value = + expectedManufacturer; + modelDropdown = + modelDialog.shadowRoot.querySelector('#modelDropdown'); modelDropdown.value = expectedModel; return verifyGetEulaUrlWasCalled( cupsPrintersBrowserProxy, expectedManufacturer, expectedModel); @@ -457,7 +476,8 @@ test('AddButtonDisabledAfterClicking', function() { // From the add manually dialog, click the add button to advance to the // manufacturer dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); fillAddManuallyDialog(addDialog); @@ -469,16 +489,19 @@ return cupsPrintersBrowserProxy .whenCalled('getCupsPrinterManufacturersList') .then(function() { - const manufacturerDialog = - dialog.$$('add-printer-manufacturer-model-dialog'); + const manufacturerDialog = dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog'); assertTrue(!!manufacturerDialog); // Populate the manufacturer and model fields to enable the add // button. - manufacturerDialog.$$('#manufacturerDropdown').value = 'make'; - manufacturerDialog.$$('#modelDropdown').value = 'model'; + manufacturerDialog.shadowRoot.querySelector('#manufacturerDropdown') + .value = 'make'; + manufacturerDialog.shadowRoot.querySelector('#modelDropdown').value = + 'model'; - const addButton = manufacturerDialog.$$('#addPrinterButton'); + const addButton = + manufacturerDialog.shadowRoot.querySelector('#addPrinterButton'); assertTrue(!!addButton); assertFalse(addButton.disabled); addButton.click(); @@ -503,7 +526,8 @@ }) .then(function() { // Showing model selection. - assertTrue(!!dialog.$$('add-printer-manufacturer-model-dialog')); + assertTrue(!!dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog')); assertTrue(dialog.showManufacturerDialog_); assertFalse(dialog.showManuallyAddDialog_); }); @@ -520,7 +544,8 @@ }) .then(function() { // Showing model selection. - assertFalse(!!dialog.$$('add-printer-configuring-dialog')); + assertFalse(!!dialog.shadowRoot.querySelector( + 'add-printer-configuring-dialog')); assertTrue(dialog.showManufacturerDialog_); assertFalse(dialog.showManuallyAddDialog_); }); @@ -537,7 +562,8 @@ }) .then(function() { // Showing model selection. - assertTrue(!!dialog.$$('add-printer-manufacturer-model-dialog')); + assertTrue(!!dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog')); assertTrue(dialog.showManufacturerDialog_); assertFalse(dialog.showManuallyAddDialog_); }); @@ -550,7 +576,8 @@ test('AddButtonDisabledAfterClicking', function() { // From the add manually dialog, click the add button to advance to the // manufacturer dialog. - const addDialog = dialog.$$('add-printer-manually-dialog'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); assertTrue(!!addDialog); flush(); fillAddManuallyDialog(addDialog); @@ -560,15 +587,17 @@ return cupsPrintersBrowserProxy .whenCalled('getCupsPrinterManufacturersList') .then(function() { - const manufacturerDialog = - dialog.$$('add-printer-manufacturer-model-dialog'); + const manufacturerDialog = dialog.shadowRoot.querySelector( + 'add-printer-manufacturer-model-dialog'); assertTrue(!!manufacturerDialog); const manufacturerDropdown = - manufacturerDialog.$$('#manufacturerDropdown'); + manufacturerDialog.shadowRoot.querySelector( + '#manufacturerDropdown'); const modelDropdown = - manufacturerDialog.$$('#modelDropdown'); - const addButton = manufacturerDialog.$$('#addPrinterButton'); + manufacturerDialog.shadowRoot.querySelector('#modelDropdown'); + const addButton = + manufacturerDialog.shadowRoot.querySelector('#addPrinterButton'); // Set the starting values for manufacturer and model dropdown. manufacturerDropdown.value = 'make'; @@ -577,33 +606,40 @@ // Mimic typing in random input. Make sure the Add button becomes // disabled. - manufacturerDropdown.$$('#search').value = 'hlrRkJQkNsh'; - manufacturerDropdown.$$('#search').fire('input'); + manufacturerDropdown.shadowRoot.querySelector('#search').value = + 'hlrRkJQkNsh'; + manufacturerDropdown.shadowRoot.querySelector('#search').fire( + 'input'); assertTrue(addButton.disabled); // Then mimic typing in the original value to re-enable the Add // button. - manufacturerDropdown.$$('#search').value = 'make'; - manufacturerDropdown.$$('#search').fire('input'); + manufacturerDropdown.shadowRoot.querySelector('#search').value = + 'make'; + manufacturerDropdown.shadowRoot.querySelector('#search').fire( + 'input'); assertFalse(addButton.disabled); // Mimic typing in random input. Make sure the Add button becomes // disabled. - modelDropdown.$$('#search').value = 'hlrRkJQkNsh'; - modelDropdown.$$('#search').fire('input'); + modelDropdown.shadowRoot.querySelector('#search').value = + 'hlrRkJQkNsh'; + modelDropdown.shadowRoot.querySelector('#search').fire('input'); assertTrue(addButton.disabled); // Then mimic typing in the original value to re-enable the Add // button. - modelDropdown.$$('#search').value = 'model'; - modelDropdown.$$('#search').fire('input'); + modelDropdown.shadowRoot.querySelector('#search').value = 'model'; + modelDropdown.shadowRoot.querySelector('#search').fire('input'); assertFalse(addButton.disabled); }); }); test('Queue input is hidden when protocol is App Socket', () => { - const addDialog = dialog.$$('add-printer-manually-dialog'); - let printerQueueInput = addDialog.$$('#printerQueueInput'); + const addDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); + let printerQueueInput = + addDialog.shadowRoot.querySelector('#printerQueueInput'); const select = addDialog.shadowRoot.querySelector('select'); assertTrue(!!printerQueueInput); @@ -611,14 +647,16 @@ select.dispatchEvent(new CustomEvent('change'), {'bubbles': true}); flush(); - printerQueueInput = addDialog.$$('#printerQueueInput'); + printerQueueInput = + addDialog.shadowRoot.querySelector('#printerQueueInput'); assertFalse(!!printerQueueInput); select.value = 'http'; select.dispatchEvent(new CustomEvent('change'), {'bubbles': true}); flush(); - printerQueueInput = addDialog.$$('#printerQueueInput'); + printerQueueInput = + addDialog.shadowRoot.querySelector('#printerQueueInput'); assertTrue(!!printerQueueInput); }); }); @@ -640,7 +678,8 @@ cupsPrintersBrowserProxy = new TestCupsPrintersBrowserProxy(); - CupsPrintersBrowserProxyImpl.instance_ = cupsPrintersBrowserProxy; + CupsPrintersBrowserProxyImpl.setInstanceForTesting( + cupsPrintersBrowserProxy); // Simulate internet connection. wifi1 = OncMojo.getDefaultNetworkState(mojom.NetworkType.kWiFi, 'wifi1'); @@ -669,7 +708,7 @@ */ function clickSaveButton(dialog) { assertTrue(!!dialog, 'Dialog is null for save'); - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); dialog.printerInfoChanged_ = true; assertFalse(saveButton.disabled); assertTrue(!!saveButton, 'Button is null'); @@ -682,7 +721,7 @@ */ function clickCancelButton(dialog) { assertTrue(!!dialog, 'Dialog is null for cancel'); - const cancelButton = dialog.$$('.cancel-button'); + const cancelButton = dialog.shadowRoot.querySelector('.cancel-button'); assertTrue(!!cancelButton, 'Button is null'); cancelButton.click(); } @@ -713,7 +752,7 @@ // Trigger the edit dialog to open. page.fire('edit-cups-printer-details'); flush(); - dialog = page.$$('settings-cups-edit-printer-dialog'); + dialog = page.shadowRoot.querySelector('settings-cups-edit-printer-dialog'); // This proxy function gets called whenever the edit dialog is initialized. return cupsPrintersBrowserProxy.whenCalled('getCupsPrinterModelsList'); } @@ -728,16 +767,18 @@ /*model=*/ 'model', /*protocol=*/ 'usb', /*serverAddress=*/ '') .then(() => { // Assert that the protocol is USB. - assertEquals('usb', dialog.$$('.md-select').value); + assertEquals( + 'usb', dialog.shadowRoot.querySelector('.md-select').value); // Edit the printer name. - const nameField = dialog.$$('.printer-name-input'); + const nameField = + dialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); nameField.value = 'edited printer'; nameField.fire('input'); // Assert that the "Save" button is enabled. - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertTrue(!saveButton.disabled); }); @@ -753,10 +794,10 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - assertTrue(!!dialog.$$('#printerName')); - assertTrue(!!dialog.$$('#printerAddress')); + assertTrue(!!dialog.shadowRoot.querySelector('#printerName')); + assertTrue(!!dialog.shadowRoot.querySelector('#printerAddress')); - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertTrue(saveButton.disabled); @@ -794,15 +835,17 @@ /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ expectedProtocol, /*serverAddress=*/ '') .then(() => { - const nameField = dialog.$$('.printer-name-input'); + const nameField = + dialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); nameField.value = 'edited printer name'; - const addressField = dialog.$$('#printerAddress'); + const addressField = + dialog.shadowRoot.querySelector('#printerAddress'); assertTrue(!!addressField); addressField.value = '9.9.9.9'; - const protocolField = dialog.$$('.md-select'); + const protocolField = dialog.shadowRoot.querySelector('.md-select'); assertTrue(!!protocolField); protocolField.value = 'http'; @@ -825,7 +868,8 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - const nameField = dialog.$$('.printer-name-input'); + const nameField = + dialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); nameField.value = expectedName; @@ -852,11 +896,12 @@ .then(() => { // Editing more than just the printer name requires reconfiguring the // printer. - const addressField = dialog.$$('#printerAddress'); + const addressField = + dialog.shadowRoot.querySelector('#printerAddress'); assertTrue(!!addressField); addressField.value = expectedAddress; - const queueField = dialog.$$('#printerQueue'); + const queueField = dialog.shadowRoot.querySelector('#printerQueue'); assertTrue(!!queueField); queueField.value = expectedQueue; @@ -882,11 +927,12 @@ .then(() => { // Editing more than just the printer name requires reconfiguring the // printer. - const addressField = dialog.$$('#printerAddress'); + const addressField = + dialog.shadowRoot.querySelector('#printerAddress'); assertTrue(!!addressField); addressField.value = expectedAddress; - const queueField = dialog.$$('#printerQueue'); + const queueField = dialog.shadowRoot.querySelector('#printerQueue'); assertTrue(!!queueField); queueField.value = expectedQueue; @@ -909,7 +955,8 @@ /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { // Assert that the manufacturer and model drop-downs are shown. - assertFalse(dialog.$$('#makeAndModelSection').hidden); + assertFalse( + dialog.shadowRoot.querySelector('#makeAndModelSection').hidden); }); }); @@ -923,7 +970,8 @@ /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { // Assert that the manufacturer and model drop-downs are hidden. - assertTrue(!dialog.$$('#makeAndModelSection').if); + assertTrue( + !dialog.shadowRoot.querySelector('#makeAndModelSection').if); }); }); @@ -936,11 +984,12 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertTrue(saveButton.disabled); - const nameField = dialog.$$('.printer-name-input'); + const nameField = + dialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); nameField.value = 'edited printer'; nameField.fire('input'); @@ -958,11 +1007,12 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertTrue(saveButton.disabled); - const addressField = dialog.$$('#printerAddress'); + const addressField = + dialog.shadowRoot.querySelector('#printerAddress'); assertTrue(!!addressField); addressField.value = 'newAddress:789'; addressField.fire('input'); @@ -980,11 +1030,11 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertTrue(saveButton.disabled); - const queueField = dialog.$$('#printerQueue'); + const queueField = dialog.shadowRoot.querySelector('#printerQueue'); assertTrue(!!queueField); queueField.value = 'newqueueinfo'; queueField.fire('input'); @@ -1002,11 +1052,11 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertTrue(saveButton.disabled); - const dropDown = dialog.$$('.md-select'); + const dropDown = dialog.shadowRoot.querySelector('.md-select'); dropDown.value = 'http'; dropDown.dispatchEvent(new CustomEvent('change'), {'bubbles': true}); flush(); @@ -1030,11 +1080,12 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - saveButton = dialog.$$('.action-button'); + saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertTrue(saveButton.disabled); - const makeDropDown = dialog.$$('#printerPPDManufacturer'); + const makeDropDown = + dialog.shadowRoot.querySelector('#printerPPDManufacturer'); makeDropDown.value = 'HP'; makeDropDown.dispatchEvent( new CustomEvent('change'), {'bubbles': true}); @@ -1046,7 +1097,8 @@ // Saving is disabled until a model is selected. assertTrue(saveButton.disabled); - const modelDropDown = dialog.$$('#printerPPDModel'); + const modelDropDown = + dialog.shadowRoot.querySelector('#printerPPDModel'); modelDropDown.value = 'HP 910'; modelDropDown.dispatchEvent( new CustomEvent('change'), {'bubbles': true}); @@ -1074,7 +1126,7 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - urlElement = dialog.$$('#eulaUrl'); + urlElement = dialog.shadowRoot.querySelector('#eulaUrl'); // Check that the EULA text is hidden. assertTrue(urlElement.hidden); @@ -1082,8 +1134,9 @@ // so we have to reset the resolver before the next call. resetGetEulaUrl(cupsPrintersBrowserProxy, eulaLink); - dialog.$$('#printerPPDManufacturer').value = expectedManufacturer; - modelDropdown = dialog.$$('#printerPPDModel'); + dialog.shadowRoot.querySelector('#printerPPDManufacturer').value = + expectedManufacturer; + modelDropdown = dialog.shadowRoot.querySelector('#printerPPDModel'); modelDropdown.value = expectedModel; return verifyGetEulaUrlWasCalled( @@ -1132,14 +1185,15 @@ /*autoconf=*/ false, /*manufacturer=*/ 'make', /*model=*/ 'model', /*protocol=*/ 'ipp', /*serverAddress=*/ '') .then(() => { - const nameField = dialog.$$('.printer-name-input'); + const nameField = + dialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); nameField.value = expectedName; nameField.fire('input'); flush(); - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertFalse(saveButton.disabled); @@ -1160,11 +1214,13 @@ /*serverAddress=*/ 'ipp://192.168.1.1:631') .then(() => { // Verify the only the name field is not disabled. - assertTrue(dialog.$$('#printerAddress').disabled); - assertTrue(dialog.$$('.md-select').disabled); - assertTrue(dialog.$$('#printerQueue').disabled); + assertTrue( + dialog.shadowRoot.querySelector('#printerAddress').disabled); + assertTrue(dialog.shadowRoot.querySelector('.md-select').disabled); + assertTrue(dialog.shadowRoot.querySelector('#printerQueue').disabled); - const nameField = dialog.$$('.printer-name-input'); + const nameField = + dialog.shadowRoot.querySelector('.printer-name-input'); assertTrue(!!nameField); assertFalse(nameField.disabled); @@ -1173,7 +1229,7 @@ flush(); - const saveButton = dialog.$$('.action-button'); + const saveButton = dialog.shadowRoot.querySelector('.action-button'); assertTrue(!!saveButton); assertFalse(saveButton.disabled); @@ -1205,7 +1261,8 @@ cupsPrintersBrowserProxy = new TestCupsPrintersBrowserProxy(); - CupsPrintersBrowserProxyImpl.instance_ = cupsPrintersBrowserProxy; + CupsPrintersBrowserProxyImpl.setInstanceForTesting( + cupsPrintersBrowserProxy); PolymerTest.clearBody(); Router.getInstance().navigateTo(routes.CUPS_PRINTERS); @@ -1213,7 +1270,7 @@ page = document.createElement('settings-cups-printers'); document.body.appendChild(page); assertTrue(!!page); - dialog = page.$$('settings-cups-add-printer-dialog'); + dialog = page.shadowRoot.querySelector('settings-cups-add-printer-dialog'); assertTrue(!!dialog); flush(); @@ -1247,8 +1304,8 @@ */ function getPrintServerDialog(page) { assertTrue(!!page); - dialog = page.$$('settings-cups-add-printer-dialog'); - return dialog.$$('add-print-server-dialog'); + dialog = page.shadowRoot.querySelector('settings-cups-add-printer-dialog'); + return dialog.shadowRoot.querySelector('add-print-server-dialog'); } /** @@ -1266,23 +1323,27 @@ dialog.open(); flush(); - const addPrinterDialog = dialog.$$('add-printer-manually-dialog'); + const addPrinterDialog = + dialog.shadowRoot.querySelector('add-printer-manually-dialog'); // Switch to Add print server dialog. - addPrinterDialog.$$('#print-server-button').click(); + addPrinterDialog.shadowRoot.querySelector('#print-server-button').click(); flush(); - const printServerDialog = dialog.$$('add-print-server-dialog'); + const printServerDialog = + dialog.shadowRoot.querySelector('add-print-server-dialog'); assertTrue(!!printServerDialog); flush(); cupsPrintersBrowserProxy.setQueryPrintServerResult(error); return flushTasks().then(() => { // Fill dialog with the server address. - const address = printServerDialog.$$('#printServerAddressInput'); + const address = printServerDialog.shadowRoot.querySelector( + '#printServerAddressInput'); assertTrue(!!address); address.value = address; // Add the print server. - const button = printServerDialog.$$('.action-button'); + const button = + printServerDialog.shadowRoot.querySelector('.action-button'); // Button should not be disabled before clicking on it. assertTrue(!button.disabled); button.click(); @@ -1300,7 +1361,8 @@ function verifyErrorMessage(expectedError) { // Assert that the dialog did not close on errors. const printServerDialog = getPrintServerDialog(page); - const dialogError = printServerDialog.$$('#server-dialog-error'); + const dialogError = + printServerDialog.shadowRoot.querySelector('#server-dialog-error'); // Assert that the dialog error is displayed. assertTrue(!dialogError.hidden); assertEquals(loadTimeData.getString(expectedError), dialogError.errorText); @@ -1314,7 +1376,7 @@ function verifyToastMessage(expectedMessage, numPrinters) { // We always display the total number of printers found from a print // server. - const toast = page.$$('#printServerErrorToast'); + const toast = page.shadowRoot.querySelector('#printServerErrorToast'); assertTrue(toast.open); assertEquals( loadTimeData.getStringF(expectedMessage, numPrinters), @@ -1376,7 +1438,7 @@ // added to the entry manager. assertEquals(2, entryManager.printServerPrinters.length); const nearbyPrintersElement = - page.$$('settings-cups-nearby-printers'); + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertEquals(2, nearbyPrintersElement.nearbyPrinters.length); }); }); @@ -1419,7 +1481,8 @@ // Verify that we now only have 1 printer in print server printers // list. assertEquals(1, entryManager.printServerPrinters.length); - const nearbyPrintersElement = page.$$('settings-cups-nearby-printers'); + const nearbyPrintersElement = + page.shadowRoot.querySelector('settings-cups-nearby-printers'); assertEquals(1, nearbyPrintersElement.nearbyPrinters.length); // Verify we correctly removed the duplicate printer, 'idA', since // it exists in the saved printer list. Expect only 'idB' in @@ -1439,7 +1502,9 @@ // Assert that the dialog did not close on errors. assertTrue(!!printServerDialog); // Assert that the address input field is invalid. - assertTrue(printServerDialog.$$('#printServerAddressInput').invalid); + assertTrue(printServerDialog.shadowRoot + .querySelector('#printServerAddressInput') + .invalid); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/cups_printer_test_utils.js b/chrome/test/data/webui/settings/chromeos/cups_printer_test_utils.js index c9604b0..e920d553 100644 --- a/chrome/test/data/webui/settings/chromeos/cups_printer_test_utils.js +++ b/chrome/test/data/webui/settings/chromeos/cups_printer_test_utils.js
@@ -78,7 +78,8 @@ * @private */ export function getPrinterEntries(printersElement) { - const entryList = printersElement.$$('#printerEntryList'); + const entryList = + printersElement.shadowRoot.querySelector('#printerEntryList'); return entryList.querySelectorAll( 'settings-cups-printers-entry:not([hidden])'); }
diff --git a/chrome/test/data/webui/settings/chromeos/os_printing_page_tests.js b/chrome/test/data/webui/settings/chromeos/os_printing_page_tests.js index 9fc44d2..a84b2a6 100644 --- a/chrome/test/data/webui/settings/chromeos/os_printing_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_printing_page_tests.js
@@ -44,8 +44,9 @@ flush(); - const deepLinkElement = printingPage.$$('#printManagement') - .shadowRoot.querySelector('cr-icon-button'); + const deepLinkElement = + printingPage.shadowRoot.querySelector('#printManagement') + .shadowRoot.querySelector('cr-icon-button'); await waitAfterNextRender(deepLinkElement); assertEquals( deepLinkElement, getDeepActiveElement(), @@ -61,8 +62,9 @@ flush(); - const deepLinkElement = printingPage.$$('#scanningApp') - .shadowRoot.querySelector('cr-icon-button'); + const deepLinkElement = + printingPage.shadowRoot.querySelector('#scanningApp') + .shadowRoot.querySelector('cr-icon-button'); await waitAfterNextRender(deepLinkElement); assertEquals( deepLinkElement, getDeepActiveElement(),
diff --git a/chrome/test/data/webui/settings/languages_page_metrics_test_browser.ts b/chrome/test/data/webui/settings/languages_page_metrics_test_browser.ts index f8baef2..59e1c9c 100644 --- a/chrome/test/data/webui/settings/languages_page_metrics_test_browser.ts +++ b/chrome/test/data/webui/settings/languages_page_metrics_test_browser.ts
@@ -160,6 +160,31 @@ await languageSettingsMetricsProxy.whenCalled('recordSettingsMetric')); }); + // <if expr="is_win"> + test('records when chrome language is changed', async () => { + // Adding language with supportsUI = true in + // fake_language_settings_private.ts + languageHelper.enableLanguage('sw'); + // Testing the 'Change Chrome Language' button with 'sw' + const languagesSection = + languagesSubpage.shadowRoot!.querySelector('#languagesSection'); + assertTrue(!!languagesSection); + const menuButton = languagesSection.querySelector<HTMLElement>( + '.list-item cr-icon-button#more-sw'); + assertTrue(!!menuButton); + menuButton.click(); + flush(); + const actionMenu = languagesSubpage.$.menu.get(); + assertTrue(actionMenu.open); + const item = actionMenu.querySelector<HTMLElement>('#uiLanguageItem'); + assertTrue(!!item); + item.click(); + assertEquals( + LanguageSettingsActionType.CHANGE_CHROME_LANGUAGE, + await languageSettingsMetricsProxy.whenCalled('recordSettingsMetric')); + }); + // </if> + test('records on language list reorder', async () => { // Add several languages. for (const language of ['en-CA', 'en-US', 'tk', 'no']) {
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index 7afaa765..1769883 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -638,6 +638,8 @@ "app/server/win/com_classes_legacy_unittest.cc", "policy/win/group_policy_manager_unittest.cc", "test/integration_tests_win.cc", + "unittest_util_win.cc", + "unittest_util_win.h", "util_win_unittest.cc", "win/installer_api_unittest.cc", "win/manifest_util_unittest.cc",
diff --git a/chrome/updater/app/server/win/com_classes_legacy.cc b/chrome/updater/app/server/win/com_classes_legacy.cc index 5d11b41..dd3df8ed 100644 --- a/chrome/updater/app/server/win/com_classes_legacy.cc +++ b/chrome/updater/app/server/win/com_classes_legacy.cc
@@ -700,7 +700,8 @@ if (const base::win::RegKey command_key( root, - base::StrCat({app_key_name, L"\\", kRegKeyCommands, command_id}) + base::StrCat( + {app_key_name, L"\\", kRegKeyCommands, L"\\", command_id}) .c_str(), Wow6432(KEY_QUERY_VALUE)); !command_key.Valid()) {
diff --git a/chrome/updater/app/server/win/com_classes_legacy_unittest.cc b/chrome/updater/app/server/win/com_classes_legacy_unittest.cc index 81f19081..252c824 100644 --- a/chrome/updater/app/server/win/com_classes_legacy_unittest.cc +++ b/chrome/updater/app/server/win/com_classes_legacy_unittest.cc
@@ -14,19 +14,19 @@ #include "base/command_line.h" #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/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" #include "base/time/time.h" -#include "base/win/registry.h" #include "base/win/scoped_handle.h" #include "base/win/scoped_variant.h" #include "chrome/updater/test_scope.h" +#include "chrome/updater/unittest_util_win.h" #include "chrome/updater/win/test/test_executables.h" #include "chrome/updater/win/test/test_strings.h" -#include "chrome/updater/win/win_constants.h" #include "chrome/updater/win/win_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,54 +35,28 @@ namespace updater { namespace { -const wchar_t kAppId1[] = L"{3B1A3CCA-0525-4418-93E6-A0DB3398EC9B}"; +constexpr wchar_t kAppId1[] = L"{3B1A3CCA-0525-4418-93E6-A0DB3398EC9B}"; -const wchar_t kCmdExe[] = L"cmd.exe"; -const wchar_t kBadCmdLine[] = L"\"c:\\Program Files\\cmd.exe\""; -const wchar_t kCmdLineValid[] = +constexpr wchar_t kBadCmdLine[] = L"\"c:\\Program Files\\cmd.exe\""; +constexpr wchar_t kCmdLineValid[] = L"\"C:\\Program Files\\Windows Media Player\\wmpnscfg.exe\" /Close"; -const wchar_t kCmdId1[] = L"command 1"; -const wchar_t kCmdId2[] = L"command 2"; +constexpr wchar_t kCmdId1[] = L"command 1"; +constexpr wchar_t kCmdId2[] = L"command 2"; } // namespace class LegacyAppCommandWebImplTest : public testing::Test { protected: LegacyAppCommandWebImplTest() - : test_process_command_line_(base::CommandLine::NO_PROGRAM) {} + : cmd_exe_command_line_(base::CommandLine::NO_PROGRAM) {} ~LegacyAppCommandWebImplTest() override = default; void SetUp() override { - base::FilePath system_path; - ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &system_path)); - - const base::FilePath from_test_process = system_path.Append(kCmdExe); - if (GetTestScope() == UpdaterScope::kUser) { - test_process_command_line_ = base::CommandLine(from_test_process); - return; - } - - base::FilePath programfiles_path; - ASSERT_TRUE( - base::PathService::Get(base::DIR_PROGRAM_FILES, &programfiles_path)); - ASSERT_TRUE(base::CreateTemporaryDirInDir( - programfiles_path, L"com_classes_legacy_unittest", &temp_directory_)); - base::FilePath test_process_path; - test_process_path = temp_directory_.Append(kCmdExe); - - ASSERT_TRUE(base::CopyFile(from_test_process, test_process_path)); - test_process_command_line_ = base::CommandLine(test_process_path); + SetupCmdExe(cmd_exe_command_line_, temp_programfiles_dir_); } - void TearDown() override { - base::win::RegKey(UpdaterScopeToHKeyRoot(GetTestScope()), L"", - Wow6432(DELETE)) - .DeleteKey(GetClientKeyName(kAppId1).c_str()); - - if (!temp_directory_.empty()) - base::DeletePathRecursively(temp_directory_); - } + void TearDown() override { DeleteAppClientKey(kAppId1); } template <typename T> absl::optional<std::wstring> MakeCommandLine( @@ -118,7 +92,7 @@ const std::wstring& command_line_format, const std::vector<std::wstring>& parameters) { CreateAppClientKey(app_id); - CreateCommand(app_id, command_id, command_line_format); + CreateAppCommandRegistry(app_id, command_id, command_line_format); Microsoft::WRL::ComPtr<LegacyAppCommandWebImpl> app_command_web; if (HRESULT hr = LegacyAppCommandWebImpl::CreateLegacyAppCommandWebImpl( @@ -136,7 +110,7 @@ const std::wstring& command_line_format, Microsoft::WRL::ComPtr<LegacyAppCommandWebImpl>& app_command_web) { CreateAppClientKey(app_id); - CreateCommand(app_id, command_id, command_line_format); + CreateAppCommandRegistry(app_id, command_id, command_line_format); return LegacyAppCommandWebImpl::CreateLegacyAppCommandWebImpl( GetTestScope(), app_id, command_id, app_command_web); @@ -152,43 +126,13 @@ void NoCmdTest() { Microsoft::WRL::ComPtr<LegacyAppCommandWebImpl> app_command_web; CreateAppClientKey(kAppId1); - CreateCommand(kAppId1, kCmdId1, kCmdLineValid); + CreateAppCommandRegistry(kAppId1, kCmdId1, kCmdLineValid); EXPECT_HRESULT_FAILED( LegacyAppCommandWebImpl::CreateLegacyAppCommandWebImpl( GetTestScope(), kAppId1, kCmdId2, app_command_web)); } - std::wstring GetClientKeyName(const std::wstring& app_id) { - return base::StrCat({CLIENTS_KEY, app_id}); - } - - std::wstring GetCommandKeyName(const std::wstring& app_id, - const std::wstring& command_id) { - return base::StrCat( - {CLIENTS_KEY, app_id, L"\\", kRegKeyCommands, command_id}); - } - - void CreateAppClientKey(const std::wstring& app_id) { - base::win::RegKey client_key; - EXPECT_EQ( - client_key.Create(UpdaterScopeToHKeyRoot(GetTestScope()), - GetClientKeyName(app_id).c_str(), Wow6432(KEY_WRITE)), - ERROR_SUCCESS); - } - - void CreateCommand(const std::wstring& app_id, - const std::wstring& cmd_id, - const std::wstring& cmd_line) { - base::win::RegKey command_key; - EXPECT_EQ(command_key.Create(UpdaterScopeToHKeyRoot(GetTestScope()), - GetCommandKeyName(app_id, cmd_id).c_str(), - Wow6432(KEY_WRITE)), - ERROR_SUCCESS); - EXPECT_EQ(command_key.WriteValue(kRegValueCommandLine, cmd_line.c_str()), - ERROR_SUCCESS); - } - void WaitForUpdateCompletion( Microsoft::WRL::ComPtr<LegacyAppCommandWebImpl>& app_command_web, const base::TimeDelta& timeout) { @@ -211,8 +155,8 @@ .GetCommandLineString(); } - base::CommandLine test_process_command_line_; - base::FilePath temp_directory_; + base::CommandLine cmd_exe_command_line_; + base::ScopedTempDir temp_programfiles_dir_; }; TEST_F(LegacyAppCommandWebImplTest, InvalidPaths) { @@ -413,8 +357,8 @@ Microsoft::WRL::ComPtr<LegacyAppCommandWebImpl> app_command_web; ASSERT_HRESULT_SUCCEEDED(CreateAppCommandWeb( kAppId1, kCmdId1, - base::StrCat({test_process_command_line_.GetCommandLineString(), - L" /c \"exit 7\""}), + base::StrCat( + {cmd_exe_command_line_.GetCommandLineString(), L" /c \"exit 7\""}), app_command_web)); UINT status = 0; @@ -446,8 +390,8 @@ Microsoft::WRL::ComPtr<LegacyAppCommandWebImpl> app_command_web; ASSERT_HRESULT_SUCCEEDED(CreateAppCommandWeb( kAppId1, kCmdId1, - base::StrCat({test_process_command_line_.GetCommandLineString(), - L" /c \"exit %1\""}), + base::StrCat( + {cmd_exe_command_line_.GetCommandLineString(), L" /c \"exit %1\""}), app_command_web)); ASSERT_HRESULT_SUCCEEDED(
diff --git a/chrome/updater/persisted_data_unittest.cc b/chrome/updater/persisted_data_unittest.cc index 0e502c6..355a9577 100644 --- a/chrome/updater/persisted_data_unittest.cc +++ b/chrome/updater/persisted_data_unittest.cc
@@ -160,7 +160,6 @@ EXPECT_EQ(metadata_os.wServicePackMinor, os.wServicePackMinor); EXPECT_EQ(metadata_os.wSuiteMask, os.wSuiteMask); EXPECT_EQ(metadata_os.wProductType, os.wProductType); - EXPECT_EQ(metadata_os.wReserved, os.wReserved); } #endif
diff --git a/chrome/updater/unittest_util_win.cc b/chrome/updater/unittest_util_win.cc new file mode 100644 index 0000000..beb5dea2 --- /dev/null +++ b/chrome/updater/unittest_util_win.cc
@@ -0,0 +1,86 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/updater/unittest_util_win.h" + +#include <windows.h> + +#include <string> + +#include "base/base_paths_win.h" +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/path_service.h" +#include "base/strings/strcat.h" +#include "base/win/registry.h" +#include "chrome/updater/test_scope.h" +#include "chrome/updater/win/win_constants.h" +#include "chrome/updater/win/win_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace updater { + +std::wstring GetClientKeyName(const std::wstring& app_id) { + return base::StrCat({CLIENTS_KEY, app_id}); +} + +std::wstring GetAppCommandKeyName(const std::wstring& app_id, + const std::wstring& command_id) { + return base::StrCat( + {CLIENTS_KEY, app_id, L"\\", kRegKeyCommands, L"\\", command_id}); +} + +void CreateAppClientKey(const std::wstring& app_id) { + base::win::RegKey client_key; + EXPECT_EQ( + client_key.Create(UpdaterScopeToHKeyRoot(GetTestScope()), + GetClientKeyName(app_id).c_str(), Wow6432(KEY_WRITE)), + ERROR_SUCCESS); +} + +void DeleteAppClientKey(const std::wstring& app_id) { + base::win::RegKey(UpdaterScopeToHKeyRoot(GetTestScope()), L"", + Wow6432(DELETE)) + .DeleteKey(GetClientKeyName(app_id).c_str()); +} + +void CreateAppCommandRegistry(const std::wstring& app_id, + const std::wstring& cmd_id, + const std::wstring& cmd_line) { + base::win::RegKey command_key; + EXPECT_EQ(command_key.Create(UpdaterScopeToHKeyRoot(GetTestScope()), + GetAppCommandKeyName(app_id, cmd_id).c_str(), + Wow6432(KEY_WRITE)), + ERROR_SUCCESS); + EXPECT_EQ(command_key.WriteValue(kRegValueCommandLine, cmd_line.c_str()), + ERROR_SUCCESS); +} + +void SetupCmdExe(base::CommandLine& cmd_exe_command_line, + base::ScopedTempDir& temp_programfiles_dir) { + constexpr wchar_t kCmdExe[] = L"cmd.exe"; + + base::FilePath system_path; + ASSERT_TRUE(base::PathService::Get(base::DIR_SYSTEM, &system_path)); + + const base::FilePath cmd_exe_system_path = system_path.Append(kCmdExe); + if (GetTestScope() == UpdaterScope::kUser) { + cmd_exe_command_line = base::CommandLine(cmd_exe_system_path); + return; + } + + base::FilePath programfiles_path; + ASSERT_TRUE( + base::PathService::Get(base::DIR_PROGRAM_FILES, &programfiles_path)); + ASSERT_TRUE( + temp_programfiles_dir.CreateUniqueTempDirUnderPath(programfiles_path)); + base::FilePath cmd_exe_path; + cmd_exe_path = temp_programfiles_dir.GetPath().Append(kCmdExe); + + ASSERT_TRUE(base::CopyFile(cmd_exe_system_path, cmd_exe_path)); + cmd_exe_command_line = base::CommandLine(cmd_exe_path); +} + +} // namespace updater
diff --git a/chrome/updater/unittest_util_win.h b/chrome/updater/unittest_util_win.h new file mode 100644 index 0000000..1a84dadb --- /dev/null +++ b/chrome/updater/unittest_util_win.h
@@ -0,0 +1,49 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_UPDATER_UNITTEST_UTIL_WIN_H_ +#define CHROME_UPDATER_UNITTEST_UTIL_WIN_H_ + +#include <string> + +#include "base/command_line.h" +#include "base/files/scoped_temp_dir.h" + +namespace updater { + +// Returns the registry path `Software\{CompanyName}\Update\Clients\{app_id}`. +std::wstring GetClientKeyName(const std::wstring& app_id); + +// Returns the registry path +// `Software\{CompanyName}\Update\Clients\{app_id}\Commands\{command_id}`. +std::wstring GetAppCommandKeyName(const std::wstring& app_id, + const std::wstring& command_id); + +// Creates the key `{HKLM\HKCU}\Software\{CompanyName}\Update\Clients\{app_id}`. +// `{HKLM\HKCU}` is determined by the current test scope. +void CreateAppClientKey(const std::wstring& app_id); + +// Deletes the key `{HKLM\HKCU}\Software\{CompanyName}\Update\Clients\{app_id}`. +// `{HKLM\HKCU}` is determined by the current test scope. +void DeleteAppClientKey(const std::wstring& app_id); + +// Creates the key +// `{HKRoot}\Software\{CompanyName}\Update\Clients\{app_id}\Commands\{cmd_id}`, +// and adds a `CommandLine` REG_SZ entry with the value `cmd_line`. `{HKRoot}` +// is determined by the current test scope. +void CreateAppCommandRegistry(const std::wstring& app_id, + const std::wstring& cmd_id, + const std::wstring& cmd_line); + +// Returns the path to "cmd.exe" in `cmd_exe_command_line` based on the current +// test scope: +// * "%systemroot%\system32\cmd.exe" for user test scope. +// * "%programfiles%\`temp_parent_dir`\cmd.exe" for system test scope. +// `temp_parent_dir` is owned by the caller. +void SetupCmdExe(base::CommandLine& cmd_exe_command_line, + base::ScopedTempDir& temp_parent_dir); + +} // namespace updater + +#endif // CHROME_UPDATER_UNITTEST_UTIL_WIN_H_
diff --git a/chrome/updater/win/win_util_unittest.cc b/chrome/updater/win/win_util_unittest.cc index 557cd0ed..aa5044a6 100644 --- a/chrome/updater/win/win_util_unittest.cc +++ b/chrome/updater/win/win_util_unittest.cc
@@ -157,7 +157,6 @@ EXPECT_EQ(rtl_os_version->wServicePackMinor, os.wServicePackMinor); EXPECT_EQ(rtl_os_version->wSuiteMask, os.wSuiteMask); EXPECT_EQ(rtl_os_version->wProductType, os.wProductType); - EXPECT_EQ(rtl_os_version->wReserved, os.wReserved); } TEST(WinUtil, CompareOSVersions_SameAsCurrent) {
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index bb3e9dd9..d0d312f 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -3398,6 +3398,9 @@ Tips on writing feedback </message> <!-- Share Data Page --> + <message name="IDS_FEEDBACK_TOOL_BACK_BUTTON_LABEL" desc="label for the back button to return to a prior page"> + Back + </message> <message name="IDS_FEEDBACK_TOOL_DESCRIPTION_HINT" desc="Label for the hint in description textarea"> Share your feedback or describe your issue. If possible, include steps to reproduce your issue. </message> @@ -3416,6 +3419,9 @@ <message name="IDS_FEEDBACK_TOOL_SCREENSHOT_LABEL" desc="Label for the screenshot field"> Screenshot </message> + <message name="IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL" desc="Label for checkbox indicating whether the user agrees to be contacted back."> + We may email you for more information or updates + </message> <!-- Confirmation Page --> <message name="IDS_FEEDBACK_TOOL_PAGE_TITLE_AFTER_SENT" desc="Label showing a thank you message as the title of the confirmation page after a report has been sent."> Thanks for your feedback
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_BACK_BUTTON_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_BACK_BUTTON_LABEL.png.sha1 new file mode 100644 index 0000000..14da21f --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_BACK_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@ +21581966d3d1c22e6ca58a00e132a64de15ca3c6 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL.png.sha1 new file mode 100644 index 0000000..b37089c --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_USER_CONSENT_LABEL.png.sha1
@@ -0,0 +1 @@ +f5b1adaf5e8efe949ff318672c6d7c1349b230a7 \ No newline at end of file
diff --git a/chromeos/dbus/dbus_clients_browser.cc b/chromeos/dbus/dbus_clients_browser.cc index cb65bfc9..3821c6cb 100644 --- a/chromeos/dbus/dbus_clients_browser.cc +++ b/chromeos/dbus/dbus_clients_browser.cc
@@ -44,8 +44,6 @@ #include "chromeos/dbus/update_engine/update_engine_client.h" #include "chromeos/dbus/virtual_file_provider/fake_virtual_file_provider_client.h" #include "chromeos/dbus/virtual_file_provider/virtual_file_provider_client.h" -#include "chromeos/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h" -#include "chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h" namespace chromeos { @@ -102,8 +100,6 @@ virtual_file_provider_client_ = CREATE_DBUS_CLIENT(VirtualFileProviderClient, use_real_clients); - vm_plugin_dispatcher_client_ = - CREATE_DBUS_CLIENT(VmPluginDispatcherClient, use_real_clients); } DBusClientsBrowser::~DBusClientsBrowser() = default; @@ -129,7 +125,6 @@ smb_provider_client_->Init(system_bus); update_engine_client_->Init(system_bus); virtual_file_provider_client_->Init(system_bus); - vm_plugin_dispatcher_client_->Init(system_bus); } } // namespace chromeos
diff --git a/chromeos/dbus/dbus_clients_browser.h b/chromeos/dbus/dbus_clients_browser.h index 0e1bb471..e4b16b2e 100644 --- a/chromeos/dbus/dbus_clients_browser.h +++ b/chromeos/dbus/dbus_clients_browser.h
@@ -33,7 +33,6 @@ class SmbProviderClient; class UpdateEngineClient; class VirtualFileProviderClient; -class VmPluginDispatcherClient; // Owns D-Bus clients. // TODO(jamescook): Rename this class. "Browser" refers to the browser process @@ -74,7 +73,6 @@ std::unique_ptr<SmbProviderClient> smb_provider_client_; std::unique_ptr<UpdateEngineClient> update_engine_client_; std::unique_ptr<VirtualFileProviderClient> virtual_file_provider_client_; - std::unique_ptr<VmPluginDispatcherClient> vm_plugin_dispatcher_client_; }; } // namespace chromeos
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index 8d699bc..2500105 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -126,11 +126,6 @@ : nullptr; } -VmPluginDispatcherClient* DBusThreadManager::GetVmPluginDispatcherClient() { - return clients_browser_ ? clients_browser_->vm_plugin_dispatcher_client_.get() - : nullptr; -} - #undef RETURN_DBUS_CLIENT void DBusThreadManager::InitializeClients() {
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index 8e7f3cf..b5f02e7 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h
@@ -34,7 +34,6 @@ class SmbProviderClient; class UpdateEngineClient; class VirtualFileProviderClient; -class VmPluginDispatcherClient; // THIS CLASS IS BEING DEPRECATED. See README.md for guidelines and // https://crbug.com/647367 for details. @@ -88,7 +87,6 @@ SmbProviderClient* GetSmbProviderClient(); UpdateEngineClient* GetUpdateEngineClient(); VirtualFileProviderClient* GetVirtualFileProviderClient(); - VmPluginDispatcherClient* GetVmPluginDispatcherClient(); private: DBusThreadManager();
diff --git a/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.cc b/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.cc index 2bc1ab33..0e7d083ef 100644 --- a/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.cc +++ b/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.cc
@@ -8,10 +8,12 @@ #include <utility> #include "base/bind.h" +#include "base/check_op.h" #include "base/location.h" #include "base/logging.h" #include "base/observer_list.h" #include "base/threading/thread_task_runner_handle.h" +#include "chromeos/dbus/vm_plugin_dispatcher/fake_vm_plugin_dispatcher_client.h" #include "dbus/bus.h" #include "dbus/message.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -20,10 +22,15 @@ namespace dispatcher = vm_tools::plugin_dispatcher; namespace chromeos { +namespace { + +VmPluginDispatcherClient* g_instance = nullptr; + +} // namespace class VmPluginDispatcherClientImpl : public VmPluginDispatcherClient { public: - VmPluginDispatcherClientImpl() {} + VmPluginDispatcherClientImpl() = default; VmPluginDispatcherClientImpl(const VmPluginDispatcherClientImpl&) = delete; VmPluginDispatcherClientImpl& operator=(const VmPluginDispatcherClientImpl&) = @@ -76,7 +83,6 @@ std::move(callback)); } - protected: void Init(dbus::Bus* bus) override { vm_plugin_dispatcher_proxy_ = bus->GetObjectProxy( dispatcher::kVmPluginDispatcherServiceName, @@ -192,12 +198,36 @@ base::WeakPtrFactory<VmPluginDispatcherClientImpl> weak_ptr_factory_{this}; }; -VmPluginDispatcherClient::VmPluginDispatcherClient() = default; +VmPluginDispatcherClient::VmPluginDispatcherClient() { + CHECK(!g_instance); + g_instance = this; +} -VmPluginDispatcherClient::~VmPluginDispatcherClient() = default; +VmPluginDispatcherClient::~VmPluginDispatcherClient() { + CHECK_EQ(this, g_instance); + g_instance = nullptr; +} -std::unique_ptr<VmPluginDispatcherClient> VmPluginDispatcherClient::Create() { - return std::make_unique<VmPluginDispatcherClientImpl>(); +// static +void VmPluginDispatcherClient::Initialize(dbus::Bus* bus) { + CHECK(bus); + (new VmPluginDispatcherClientImpl())->Init(bus); +} + +// static +void VmPluginDispatcherClient::InitializeFake() { + new FakeVmPluginDispatcherClient(); +} + +// static +void VmPluginDispatcherClient::Shutdown() { + CHECK(g_instance); + delete g_instance; +} + +// static +VmPluginDispatcherClient* VmPluginDispatcherClient::Get() { + return g_instance; } } // namespace chromeos
diff --git a/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h b/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h index 15b28f11..1b7976b 100644 --- a/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h +++ b/chromeos/dbus/vm_plugin_dispatcher/vm_plugin_dispatcher_client.h
@@ -5,8 +5,6 @@ #ifndef CHROMEOS_DBUS_VM_PLUGIN_DISPATCHER_VM_PLUGIN_DISPATCHER_CLIENT_H_ #define CHROMEOS_DBUS_VM_PLUGIN_DISPATCHER_VM_PLUGIN_DISPATCHER_CLIENT_H_ -#include <memory> - #include "base/component_export.h" #include "base/observer_list_types.h" #include "chromeos/dbus/common/dbus_client.h" @@ -73,17 +71,26 @@ virtual void WaitForServiceToBeAvailable( dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback) = 0; - // Creates an instance of VmPluginDispatcherClient. - static std::unique_ptr<VmPluginDispatcherClient> Create(); + // Creates and initializes the global instance. |bus| must not be null. + static void Initialize(dbus::Bus* bus); + + // Creates and initializes a fake global instance. + static void InitializeFake(); + + // Destroys the global instance if it has been initialized. + static void Shutdown(); + + // Returns the global instance if initialized. May return null. + static VmPluginDispatcherClient* Get(); VmPluginDispatcherClient(const VmPluginDispatcherClient&) = delete; VmPluginDispatcherClient& operator=(const VmPluginDispatcherClient&) = delete; - ~VmPluginDispatcherClient() override; - protected: - // Create() should be used instead. + // Initialize() should be used instead. VmPluginDispatcherClient(); + + ~VmPluginDispatcherClient() override; }; } // namespace chromeos
diff --git a/chromeos/network/shill_property_util.cc b/chromeos/network/shill_property_util.cc index 51e5933..0b970a8f 100644 --- a/chromeos/network/shill_property_util.cc +++ b/chromeos/network/shill_property_util.cc
@@ -32,7 +32,7 @@ // Replace non UTF8 characters in |str| with a replacement character. std::string ValidateUTF8(const std::string& str) { std::string result; - for (int32_t index = 0; index < static_cast<int32_t>(str.size()); ++index) { + for (size_t index = 0; index < str.size(); ++index) { base_icu::UChar32 code_point_out; bool is_unicode_char = base::ReadUnicodeCharacter(str.c_str(), str.size(), &index, &code_point_out);
diff --git a/components/background_task_scheduler/BUILD.gn b/components/background_task_scheduler/BUILD.gn index 0d73ea8..2903479 100644 --- a/components/background_task_scheduler/BUILD.gn +++ b/components/background_task_scheduler/BUILD.gn
@@ -103,6 +103,10 @@ include_android_sdk = false testonly = true sources = [ + "internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java", + "internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java", + "internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java", + "internal/android/java/src/org/chromium/components/background_task_scheduler/internal/MockBackgroundTaskSchedulerDelegate.java", "internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskGcmTaskServiceTest.java", "internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskJobServiceTest.java", "internal/android/junit/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerAlarmManagerTest.java", @@ -131,6 +135,7 @@ "//base:base_java_test_support", "//base:base_junit_test_support", "//components/background_task_scheduler:public_java", + "//content/public/test/android:content_java_test_support", "//third_party/android_deps:chromium_play_services_availability_shadows_java", "//third_party/android_deps:robolectric_all_java", "//third_party/junit",
diff --git a/components/background_task_scheduler/internal/BUILD.gn b/components/background_task_scheduler/internal/BUILD.gn index 1a63bcb..7c27d4b6 100644 --- a/components/background_task_scheduler/internal/BUILD.gn +++ b/components/background_task_scheduler/internal/BUILD.gn
@@ -86,30 +86,4 @@ "android/java/src/org/chromium/components/background_task_scheduler/internal/TaskInfoBridge.java", ] } - - android_library("background_task_scheduler_javatests") { - testonly = true - - sources = [ - "android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java", - "android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java", - "android/javatests/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java", - "android/javatests/src/org/chromium/components/background_task_scheduler/internal/MockBackgroundTaskSchedulerDelegate.java", - ] - - deps = [ - ":internal_java", - "$google_play_services_package:google_play_services_base_java", - "$google_play_services_package:google_play_services_basement_java", - "$google_play_services_package:google_play_services_gcm_java", - "$google_play_services_package:google_play_services_tasks_java", - "//base:base_java_test_support", - "//components/background_task_scheduler:background_task_scheduler_task_ids_java", - "//components/background_task_scheduler:public_java", - "//content/public/test/android:content_java_test_support", - "//third_party/android_support_test_runner:runner_java", - "//third_party/androidx:androidx_test_runner_java", - "//third_party/junit", - ] - } }
diff --git a/components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java similarity index 89% rename from components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java rename to components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java index 1137963..c7e59d1 100644 --- a/components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java +++ b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerImplWithMockTest.java
@@ -4,25 +4,27 @@ package org.chromium.components.background_task_scheduler.internal; -import androidx.test.filters.SmallTest; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; -import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.components.background_task_scheduler.BackgroundTaskScheduler; import org.chromium.components.background_task_scheduler.TaskIds; import org.chromium.components.background_task_scheduler.TaskInfo; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.gms.shadows.ShadowChromiumPlayServicesAvailability; import java.util.concurrent.TimeUnit; /** * Tests for {@link BackgroundTaskSchedulerImpl}. */ -@RunWith(BaseJUnit4ClassRunner.class) +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, + shadows = {ShadowGcmNetworkManager.class, ShadowChromiumPlayServicesAvailability.class}) public class BackgroundTaskSchedulerImplWithMockTest { private static final int TEST_MINUTES = 10; @@ -37,7 +39,6 @@ } @Test - @SmallTest public void testOneOffTaskScheduling() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create() @@ -53,7 +54,6 @@ } @Test - @SmallTest public void testPeriodicTaskScheduling() { TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create() @@ -69,7 +69,6 @@ } @Test - @SmallTest public void testTaskCanceling() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create()
diff --git a/components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java similarity index 88% rename from components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java rename to components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java index 8a4b33e..c799393 100644 --- a/components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java +++ b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerJobServiceTest.java
@@ -8,16 +8,14 @@ import android.os.Build; import android.os.Bundle; import android.os.PersistableBundle; -import android.support.test.InstrumentationRegistry; - -import androidx.test.filters.SmallTest; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; -import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.components.background_task_scheduler.TaskIds; import org.chromium.components.background_task_scheduler.TaskInfo; @@ -27,7 +25,7 @@ /** * Tests for {@link BackgroundTaskSchedulerJobService}. */ -@RunWith(BaseJUnit4ClassRunner.class) +@RunWith(BaseRobolectricTestRunner.class) @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1) public class BackgroundTaskSchedulerJobServiceTest { private static final long CLOCK_TIME_MS = 1415926535000L; @@ -45,20 +43,18 @@ } @Test - @SmallTest public void testOneOffTaskWithDeadline() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build(); TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), oneOffTask); + RuntimeEnvironment.getApplication(), oneOffTask); Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId()); Assert.assertFalse(jobInfo.isPeriodic()); Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getMaxExecutionDelayMillis()); } @Test - @SmallTest public void testOneOffTaskWithDeadlineAndExpiration() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create() .setWindowEndTimeMs(TIME_200_MIN_TO_MS) @@ -66,7 +62,7 @@ .build(); TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), oneOffTask); + RuntimeEnvironment.getApplication(), oneOffTask); Assert.assertEquals(END_TIME_WITH_DEADLINE_MS, jobInfo.getMaxExecutionDelayMillis()); Assert.assertEquals(CLOCK_TIME_MS, jobInfo.getExtras().getLong(BackgroundTaskSchedulerGcmNetworkManager @@ -77,7 +73,6 @@ } @Test - @SmallTest public void testOneOffTaskWithWindow() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create() .setWindowStartTimeMs(TIME_100_MIN_TO_MS) @@ -85,7 +80,7 @@ .build(); TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), oneOffTask); + RuntimeEnvironment.getApplication(), oneOffTask); Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId()); Assert.assertFalse(jobInfo.isPeriodic()); Assert.assertEquals(TIME_100_MIN_TO_MS, jobInfo.getMinLatencyMillis()); @@ -93,7 +88,6 @@ } @Test - @SmallTest public void testOneOffTaskWithWindowAndExpiration() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create() .setWindowStartTimeMs(TIME_100_MIN_TO_MS) @@ -102,7 +96,7 @@ .build(); TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), oneOffTask); + RuntimeEnvironment.getApplication(), oneOffTask); Assert.assertEquals( oneOffTask.getOneOffInfo().getWindowStartTimeMs(), jobInfo.getMinLatencyMillis()); Assert.assertEquals(END_TIME_WITH_DEADLINE_MS, jobInfo.getMaxExecutionDelayMillis()); @@ -115,20 +109,18 @@ } @Test - @SmallTest public void testPeriodicTaskWithoutFlex() { TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create().setIntervalMs(TIME_200_MIN_TO_MS).build(); TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), periodicTask); + RuntimeEnvironment.getApplication(), periodicTask); Assert.assertEquals(periodicTask.getTaskId(), jobInfo.getId()); Assert.assertTrue(jobInfo.isPeriodic()); Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getIntervalMillis()); } @Test - @SmallTest public void testPeriodicTaskWithFlex() { TaskInfo.TimingInfo timingInfo = TaskInfo.PeriodicInfo.create() .setIntervalMs(TIME_200_MIN_TO_MS) @@ -136,7 +128,7 @@ .build(); TaskInfo periodicTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).build(); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), periodicTask); + RuntimeEnvironment.getApplication(), periodicTask); Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getIntervalMillis()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { Assert.assertEquals(TIME_50_MIN_TO_MS, jobInfo.getFlexMillis()); @@ -144,7 +136,6 @@ } @Test - @SmallTest public void testTaskInfoWithExtras() { Bundle taskExtras = new Bundle(); taskExtras.putString("foo", "bar"); @@ -155,7 +146,7 @@ TaskInfo oneOffTask = TaskInfo.createTask(TaskIds.TEST, timingInfo).setExtras(taskExtras).build(); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), oneOffTask); + RuntimeEnvironment.getApplication(), oneOffTask); Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId()); PersistableBundle jobExtras = jobInfo.getExtras(); PersistableBundle persistableBundle = jobExtras.getPersistableBundle( @@ -167,25 +158,22 @@ } @Test - @SmallTest public void testTaskInfoWithManyConstraints() { TaskInfo.TimingInfo timingInfo = TaskInfo.OneOffInfo.create().setWindowEndTimeMs(TIME_200_MIN_TO_MS).build(); TaskInfo.Builder taskBuilder = TaskInfo.createTask(TaskIds.TEST, timingInfo); JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), - taskBuilder.setIsPersisted(true).build()); + RuntimeEnvironment.getApplication(), taskBuilder.setIsPersisted(true).build()); Assert.assertTrue(jobInfo.isPersisted()); jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), + RuntimeEnvironment.getApplication(), taskBuilder.setRequiredNetworkType(TaskInfo.NetworkType.UNMETERED).build()); Assert.assertEquals(JobInfo.NETWORK_TYPE_UNMETERED, jobInfo.getNetworkType()); jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo( - InstrumentationRegistry.getTargetContext(), - taskBuilder.setRequiresCharging(true).build()); + RuntimeEnvironment.getApplication(), taskBuilder.setRequiresCharging(true).build()); Assert.assertTrue(jobInfo.isRequireCharging()); } }
diff --git a/components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java similarity index 94% rename from components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java rename to components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java index 2b82b3c..420375c 100644 --- a/components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java +++ b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BundleToPersistableBundleConverterTest.java
@@ -8,27 +8,22 @@ import android.os.Bundle; import android.os.PersistableBundle; -import androidx.test.filters.SmallTest; - import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.MinAndroidSdkLevel; import java.util.ArrayList; import java.util.Arrays; import java.util.Set; -/** - * Tests for {@link BundleToPersistableBundleConverter}. - */ -@RunWith(BaseJUnit4ClassRunner.class) +/** Tests for {@link BundleToPersistableBundleConverter}. */ +@RunWith(BaseRobolectricTestRunner.class) @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP_MR1) public class BundleToPersistableBundleConverterTest { @Test - @SmallTest public void testAllValidConversions() { Bundle bundle = new Bundle(); bundle.putString("s", "bar"); @@ -61,7 +56,6 @@ } @Test - @SmallTest public void testSomeBadConversions() { Bundle bundle = new Bundle(); bundle.putString("s", "this should be there"); @@ -85,7 +79,6 @@ } @Test - @SmallTest public void testNullValue() { Bundle bundle = new Bundle(); bundle.putString("foo", "value1");
diff --git a/components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/MockBackgroundTaskSchedulerDelegate.java b/components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/MockBackgroundTaskSchedulerDelegate.java similarity index 100% rename from components/background_task_scheduler/internal/android/javatests/src/org/chromium/components/background_task_scheduler/internal/MockBackgroundTaskSchedulerDelegate.java rename to components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/MockBackgroundTaskSchedulerDelegate.java
diff --git a/components/crash/android/BUILD.gn b/components/crash/android/BUILD.gn index b7ef049..d20c61a 100644 --- a/components/crash/android/BUILD.gn +++ b/components/crash/android/BUILD.gn
@@ -39,23 +39,11 @@ sources += _jni_sources } -android_library("javatests") { - testonly = true - sources = [ "javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java" ] - deps = [ - ":java", - "//base:base_java_test_support", - "//components/minidump_uploader:minidump_uploader_java_test_support", - "//content/public/test/android:content_java_test_support", - "//third_party/androidx:androidx_test_runner_java", - "//third_party/junit", - ] -} - robolectric_library("junit") { testonly = true sources = [ "junit/src/org/chromium/components/crash/LogcatCrashExtractorTest.java", + "junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java", "junit/src/org/chromium/components/crash/anr/AnrCollectorTest.java", ] deps = [ @@ -64,7 +52,10 @@ ":java", "//base:base_java_test_support", "//base:base_junit_test_support", + "//components/minidump_uploader:minidump_uploader_java_test_support", + "//content/public/test/android:content_java_test_support", "//third_party/android_deps:robolectric_all_java", + "//third_party/androidx:androidx_test_runner_java", "//third_party/junit", ] }
diff --git a/components/crash/android/javatests/src/org/chromium/components/crash/DEPS b/components/crash/android/junit/src/org/chromium/components/crash/DEPS similarity index 97% rename from components/crash/android/javatests/src/org/chromium/components/crash/DEPS rename to components/crash/android/junit/src/org/chromium/components/crash/DEPS index 877e2a4d..aa93591 100644 --- a/components/crash/android/javatests/src/org/chromium/components/crash/DEPS +++ b/components/crash/android/junit/src/org/chromium/components/crash/DEPS
@@ -1,3 +1,3 @@ include_rules = [ "+content/public/test/android", -] \ No newline at end of file +]
diff --git a/components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java b/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java similarity index 96% rename from components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java rename to components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java index 5bff277..f425b2c 100644 --- a/components/crash/android/javatests/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java +++ b/components/crash/android/junit/src/org/chromium/components/crash/PureJavaExceptionReporterTest.java
@@ -11,7 +11,8 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Batch; import org.chromium.components.minidump_uploader.CrashTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -23,7 +24,8 @@ /** * Unittests for {@link PureJavaExceptionReporter}. */ -@RunWith(BaseJUnit4ClassRunner.class) +@RunWith(BaseRobolectricTestRunner.class) +@Batch(Batch.UNIT_TESTS) public class PureJavaExceptionReporterTest { @Rule public CrashTestRule mTestRule = new CrashTestRule();
diff --git a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java index 40db301..6a5b1fc 100644 --- a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java +++ b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/delegate/ColorPickerDialogRenderTest.java
@@ -22,6 +22,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.R; @@ -37,6 +38,7 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(BaseJUnit4RunnerDelegate.class) +@Batch(Batch.UNIT_TESTS) public class ColorPickerDialogRenderTest extends BlankUiTestActivityTestCase { @ParameterAnnotations.ClassParameter private static List<ParameterSet> sClassParams =
diff --git a/components/live_caption/views/caption_bubble.cc b/components/live_caption/views/caption_bubble.cc index ac3258fe..d85500a2 100644 --- a/components/live_caption/views/caption_bubble.cc +++ b/components/live_caption/views/caption_bubble.cc
@@ -90,23 +90,6 @@ static constexpr int kErrorMessageBetweenChildSpacingDip = 16; static constexpr int kNoActivityIntervalSeconds = 5; -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. These should be the same as -// LiveCaptionSessionEvent in enums.xml. -enum class SessionEvent { - // We began showing captions for an audio stream. - kStreamStarted = 0, - // The audio stream ended and the caption bubble closes. - kStreamEnded = 1, - // The close button was clicked, so we stopped listening to an audio stream. - kCloseButtonClicked = 2, - kMaxValue = kCloseButtonClicked, -}; - -void LogSessionEvent(SessionEvent event) { - base::UmaHistogramEnumeration("Accessibility.LiveCaption.Session", event); -} - std::unique_ptr<views::ImageButton> BuildImageButton( views::Button::PressedCallback callback, const int tooltip_text_id) { @@ -752,7 +735,7 @@ #if BUILDFLAG(IS_WIN) if (error_type == - CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED) { + CaptionBubbleErrorType::kMediaFoundationRendererUnsupported) { media_foundation_renderer_error_message_->SetVisible(has_error); generic_error_message_->SetVisible(false); } else { @@ -1087,7 +1070,7 @@ void CaptionBubble::MediaFoundationErrorCheckboxPressed() { #if BUILDFLAG(IS_WIN) error_silenced_callback_.Run( - CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED, + CaptionBubbleErrorType::kMediaFoundationRendererUnsupported, media_foundation_renderer_error_checkbox_->GetChecked()); #endif } @@ -1095,7 +1078,13 @@ bool CaptionBubble::HasMediaFoundationError() { return (model_ && model_->HasError() && model_->ErrorType() == - CaptionBubbleErrorType::MEDIA_FOUNDATION_RENDERER_UNSUPPORTED); + CaptionBubbleErrorType::kMediaFoundationRendererUnsupported); +} + +void CaptionBubble::LogSessionEvent(SessionEvent event) { + if (model_ && !model_->HasError()) { + base::UmaHistogramEnumeration("Accessibility.LiveCaption.Session2", event); + } } bool CaptionBubble::HasActivity() {
diff --git a/components/live_caption/views/caption_bubble.h b/components/live_caption/views/caption_bubble.h index d60a0d9..e646a4a2 100644 --- a/components/live_caption/views/caption_bubble.h +++ b/components/live_caption/views/caption_bubble.h
@@ -41,6 +41,19 @@ class CaptionBubbleFrameView; class CaptionBubbleLabel; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. These should be the same as +// LiveCaptionSessionEvent in enums.xml. +enum class SessionEvent { + // We began showing captions for an audio stream. + kStreamStarted = 0, + // The audio stream ended and the caption bubble closes. + kStreamEnded = 1, + // The close button was clicked, so we stopped listening to an audio stream. + kCloseButtonClicked = 2, + kMaxValue = kCloseButtonClicked, +}; + /////////////////////////////////////////////////////////////////////////////// // Caption Bubble // @@ -160,6 +173,8 @@ void MediaFoundationErrorCheckboxPressed(); bool HasMediaFoundationError(); + void LogSessionEvent(SessionEvent event); + // Unowned. Owned by views hierarchy. raw_ptr<CaptionBubbleLabel> label_; raw_ptr<views::Label> title_;
diff --git a/components/live_caption/views/caption_bubble_model.cc b/components/live_caption/views/caption_bubble_model.cc index a88886c..e120189 100644 --- a/components/live_caption/views/caption_bubble_model.cc +++ b/components/live_caption/views/caption_bubble_model.cc
@@ -5,6 +5,7 @@ #include "components/live_caption/views/caption_bubble_model.h" #include "base/callback_forward.h" +#include "base/metrics/histogram_functions.h" #include "components/live_caption/caption_bubble_context.h" #include "components/live_caption/views/caption_bubble.h" @@ -33,7 +34,7 @@ if (observer_) { observer_->OnTextChanged(); observer_->OnErrorChanged( - CaptionBubbleErrorType::GENERIC, base::RepeatingClosure(), + CaptionBubbleErrorType::kGeneric, base::RepeatingClosure(), base::BindRepeating( [](CaptionBubbleErrorType error_type, bool checked) {})); } @@ -55,7 +56,7 @@ has_error_ = false; if (observer_) observer_->OnErrorChanged( - CaptionBubbleErrorType::GENERIC, base::RepeatingClosure(), + CaptionBubbleErrorType::kGeneric, base::RepeatingClosure(), base::BindRepeating( [](CaptionBubbleErrorType error_type, bool checked) {})); } @@ -77,9 +78,12 @@ OnDoNotShowAgainClickedCallback error_silenced_callback) { has_error_ = true; error_type_ = error_type; - if (observer_) + if (observer_) { + base::UmaHistogramEnumeration( + "Accessibility.LiveCaption.CaptionBubbleError", error_type); observer_->OnErrorChanged(error_type, std::move(error_clicked_callback), std::move(error_silenced_callback)); + } } void CaptionBubbleModel::ClearText() {
diff --git a/components/live_caption/views/caption_bubble_model.h b/components/live_caption/views/caption_bubble_model.h index 06fbc2c7..26e53d5 100644 --- a/components/live_caption/views/caption_bubble_model.h +++ b/components/live_caption/views/caption_bubble_model.h
@@ -15,7 +15,14 @@ class CaptionBubble; class CaptionBubbleContext; -enum CaptionBubbleErrorType { GENERIC, MEDIA_FOUNDATION_RENDERER_UNSUPPORTED }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum CaptionBubbleErrorType { + kGeneric = 0, + kMediaFoundationRendererUnsupported = 1, + kMaxValue = kMediaFoundationRendererUnsupported +}; + using OnErrorClickedCallback = base::RepeatingCallback<void()>; using OnDoNotShowAgainClickedCallback = base::RepeatingCallback<void(CaptionBubbleErrorType, bool)>; @@ -93,7 +100,7 @@ bool has_error_ = false; // The most recent error type encountered. - CaptionBubbleErrorType error_type_ = CaptionBubbleErrorType::GENERIC; + CaptionBubbleErrorType error_type_ = CaptionBubbleErrorType::kGeneric; // The CaptionBubble observing changes to this model. raw_ptr<CaptionBubble> observer_ = nullptr;
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc index 6faecc06..083b312 100644 --- a/components/pdf/renderer/pdf_accessibility_tree.cc +++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -250,8 +250,9 @@ int char_index) { std::string chars_utf8; for (uint32_t i = 0; i < text_run.len; ++i) { - base::WriteUnicodeCharacter(chars[char_index + i].unicode_character, - &chars_utf8); + base::WriteUnicodeCharacter( + static_cast<base_icu::UChar32>(chars[char_index + i].unicode_character), + &chars_utf8); } return chars_utf8; }
diff --git a/components/signin/public/android/BUILD.gn b/components/signin/public/android/BUILD.gn index 464c819..0983c4c 100644 --- a/components/signin/public/android/BUILD.gn +++ b/components/signin/public/android/BUILD.gn
@@ -127,7 +127,7 @@ sources = [ "javatests/res/drawable/test_profile_picture.xml" ] } -android_library("javatests") { +android_library("unit_device_javatests") { testonly = true deps = [ ":java",
diff --git a/components/strictmode/android/BUILD.gn b/components/strictmode/android/BUILD.gn index 5997c7d..403a30c 100644 --- a/components/strictmode/android/BUILD.gn +++ b/components/strictmode/android/BUILD.gn
@@ -18,7 +18,7 @@ ] } -android_library("javatests") { +android_library("unit_device_javatests") { testonly = true sources = [ "javatests/src/org/chromium/components/strictmode/ThreadStrictModeInterceptorTest.java" ] deps = [
diff --git a/components/sync/base/model_type.cc b/components/sync/base/model_type.cc index 85360b4..35d173e 100644 --- a/components/sync/base/model_type.cc +++ b/components/sync/base/model_type.cc
@@ -162,6 +162,10 @@ {HISTORY, "HISTORY", "history", "History", sync_pb::EntitySpecifics::kHistoryFieldNumber, ModelTypeForHistograms::kHistory}, + {PRINTERS_AUTHORIZATION_SERVERS, "PRINTERS_AUTHORIZATION_SERVER", + "printers_authorization_servers", "Printers Authorization Servers", + sync_pb::EntitySpecifics::kPrintersAuthorizationServerFieldNumber, + ModelTypeForHistograms::kPrintersAuthorizationServers}, // ---- Proxy types ---- {PROXY_TABS, "", "", "Tabs", -1, ModelTypeForHistograms::kProxyTabs}, // ---- Control Types ---- @@ -173,11 +177,11 @@ static_assert(std::size(kModelTypeInfoMap) == GetNumModelTypes(), "kModelTypeInfoMap should have GetNumModelTypes() elements"); -static_assert(39 == syncer::GetNumModelTypes(), +static_assert(40 == syncer::GetNumModelTypes(), "When adding a new type, update enum SyncModelTypes in enums.xml " "and suffix SyncModelType in histograms.xml."); -static_assert(39 == syncer::GetNumModelTypes(), +static_assert(40 == syncer::GetNumModelTypes(), "When adding a new type, update kAllocatorDumpNameAllowlist in " "base/trace_event/memory_infra_background_allowlist.cc."); @@ -259,6 +263,9 @@ case PRINTERS: specifics->mutable_printer(); break; + case PRINTERS_AUTHORIZATION_SERVERS: + specifics->mutable_printers_authorization_server(); + break; case READING_LIST: specifics->mutable_reading_list(); break; @@ -321,7 +328,7 @@ } ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { - static_assert(39 == syncer::GetNumModelTypes(), + static_assert(40 == syncer::GetNumModelTypes(), "When adding new protocol types, the following type lookup " "logic must be updated."); if (specifics.has_bookmark()) @@ -398,6 +405,8 @@ return WORKSPACE_DESK; if (specifics.has_history()) return HISTORY; + if (specifics.has_printers_authorization_server()) + return PRINTERS_AUTHORIZATION_SERVERS; // This client version doesn't understand |specifics|. DVLOG(1) << "Unknown datatype in sync proto."; @@ -405,7 +414,7 @@ } ModelTypeSet EncryptableUserTypes() { - static_assert(39 == syncer::GetNumModelTypes(), + static_assert(40 == syncer::GetNumModelTypes(), "If adding an unencryptable type, remove from " "encryptable_user_types below."); ModelTypeSet encryptable_user_types = UserTypes();
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h index 9636c9b..29a038f 100644 --- a/components/sync/base/model_type.h +++ b/components/sync/base/model_type.h
@@ -136,6 +136,8 @@ // WEBAUTHN_CREDENTIAL, // Synced history. An entity roughly corresponds to a navigation. HISTORY, + // Trusted Authorization Servers for printers. ChromeOS only. + PRINTERS_AUTHORIZATION_SERVERS, // Proxy types are excluded from the sync protocol, but are still considered // real user types. By convention, we prefix them with 'PROXY_' to distinguish @@ -233,7 +235,8 @@ kAutofillWalletOffer = 49, kWorkspaceDesk = 50, kHistory = 51, - kMaxValue = kHistory + kPrintersAuthorizationServers = 52, + kMaxValue = kPrintersAuthorizationServers }; // Used to mark the type of EntitySpecifics that has no actual data. @@ -256,7 +259,7 @@ ARC_PACKAGE, PRINTERS, READING_LIST, USER_EVENTS, NIGORI, USER_CONSENTS, SEND_TAB_TO_SELF, SECURITY_EVENTS, WEB_APPS, WIFI_CONFIGURATIONS, OS_PREFERENCES, OS_PRIORITY_PREFERENCES, SHARING_MESSAGE, WORKSPACE_DESK, - HISTORY); + HISTORY, PRINTERS_AUTHORIZATION_SERVERS); } // These are the normal user-controlled types. This is to distinguish from
diff --git a/components/sync/base/model_type_unittest.cc b/components/sync/base/model_type_unittest.cc index 93f127d..c929c48f 100644 --- a/components/sync/base/model_type_unittest.cc +++ b/components/sync/base/model_type_unittest.cc
@@ -47,6 +47,7 @@ EXPECT_TRUE(IsRealDataType(APPS)); EXPECT_TRUE(IsRealDataType(ARC_PACKAGE)); EXPECT_TRUE(IsRealDataType(PRINTERS)); + EXPECT_TRUE(IsRealDataType(PRINTERS_AUTHORIZATION_SERVERS)); EXPECT_TRUE(IsRealDataType(READING_LIST)); }
diff --git a/components/sync/base/user_selectable_type.cc b/components/sync/base/user_selectable_type.cc index 4bf73c7..7b4c7bf 100644 --- a/components/sync/base/user_selectable_type.cc +++ b/components/sync/base/user_selectable_type.cc
@@ -51,6 +51,7 @@ if (!chromeos::features::IsSyncSettingsCategorizationEnabled()) { // SyncSettingsCategorization makes Printers a separate OS setting. model_types.Put(PRINTERS); + model_types.Put(PRINTERS_AUTHORIZATION_SERVERS); // Workspace desk template is an OS-only feature. When // SyncSettingsCategorization is disabled, WORKSPACE_DESK should be @@ -127,10 +128,10 @@ APPS, {APP_LIST, APPS, APP_SETTINGS, ARC_PACKAGE, WEB_APPS}}; case UserSelectableOsType::kOsPreferences: - return { - kOsPreferencesTypeName, - OS_PREFERENCES, - {OS_PREFERENCES, OS_PRIORITY_PREFERENCES, PRINTERS, WORKSPACE_DESK}}; + return {kOsPreferencesTypeName, + OS_PREFERENCES, + {OS_PREFERENCES, OS_PRIORITY_PREFERENCES, PRINTERS, + PRINTERS_AUTHORIZATION_SERVERS, WORKSPACE_DESK}}; case UserSelectableOsType::kOsWifiConfigurations: return {kOsWifiConfigurationsTypeName, WIFI_CONFIGURATIONS,
diff --git a/components/sync/driver/resources/BUILD.gn b/components/sync/driver/resources/BUILD.gn index c26d83c..9aa9e0f8 100644 --- a/components/sync/driver/resources/BUILD.gn +++ b/components/sync/driver/resources/BUILD.gn
@@ -69,7 +69,7 @@ ":chrome_sync", #":data", - ":search", + #":search", ":sync_index", ":sync_log", @@ -101,7 +101,7 @@ js_library("search") { deps = [ "//ui/webui/resources/js:util.m", - "//ui/webui/resources/js/cr/ui:splitter", + "//ui/webui/resources/js/cr/ui:list.m", ] }
diff --git a/components/sync/driver/resources/index.html b/components/sync/driver/resources/index.html index b3d7237..e05b762 100644 --- a/components/sync/driver/resources/index.html +++ b/components/sync/driver/resources/index.html
@@ -158,7 +158,7 @@ <div id="sync-node-browser-container"> <div id="sync-node-tree-container"> </div> - <div id="sync-node-splitter"></div> + <cr-splitter id="sync-node-splitter"></cr-splitter> <div id="node-details"> <table> <tr> @@ -221,7 +221,7 @@ <div id="sync-results-container"> <list id="sync-results-list"></list> - <div id="sync-results-splitter"></div> + <cr-splitter id="sync-results-splitter"></cr-splitter> <div id="sync-result-details-container"> <pre id="sync-result-details"></pre> </div>
diff --git a/components/sync/driver/resources/search.js b/components/sync/driver/resources/search.js index 47f4127..377c8ad 100644 --- a/components/sync/driver/resources/search.js +++ b/components/sync/driver/resources/search.js
@@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {decorate} from 'chrome://resources/js/cr/ui.m.js'; +import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.js'; + import {ArrayDataModel} from 'chrome://resources/js/cr/ui/array_data_model.m.js'; import {List} from 'chrome://resources/js/cr/ui/list.m.js'; -import {Splitter} from 'chrome://resources/js/cr/ui/splitter.js'; import {$, getRequiredElement} from 'chrome://resources/js/util.m.js'; import {decorateQuickQueryControls, decorateSearchControls} from './sync_search.js'; -decorate('#sync-results-splitter', Splitter); - decorateQuickQueryControls( document.getElementsByClassName('sync-search-quicklink'), /** @type {!HTMLButtonElement} */ ($('sync-search-submit')),
diff --git a/components/sync/driver/resources/sync_node_browser.js b/components/sync/driver/resources/sync_node_browser.js index 1ce98b1b..0f3f862 100644 --- a/components/sync/driver/resources/sync_node_browser.js +++ b/components/sync/driver/resources/sync_node_browser.js
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.js'; import 'chrome://resources/cr_elements/cr_tree/cr_tree.js'; import 'chrome://resources/cr_elements/cr_tree/cr_tree_item.js'; -import {define as crUiDefine} from 'chrome://resources/js/cr/ui.m.js'; -import {Splitter} from 'chrome://resources/js/cr/ui/splitter.js'; import {$} from 'chrome://resources/js/util.m.js'; import {getAllNodes} from './chrome_sync.js'; @@ -158,20 +157,12 @@ document.addEventListener('DOMContentLoaded', function(e) { $('node-browser-refresh-button').addEventListener('click', refresh); - const customSplitter = crUiDefine('div'); - - customSplitter.prototype = { - __proto__: Splitter.prototype, - - handleSplitterDragEnd(e) { - Splitter.prototype.handleSplitterDragEnd.apply(this, arguments); - const treeElement = $('sync-node-tree-container'); - const newWidth = parseFloat(treeElement.style.width); - treeElement.style.minWidth = Math.max(newWidth, 50) + 'px'; - } - }; - - customSplitter.decorate($('sync-node-splitter')); + const splitter = document.querySelector('#sync-node-splitter'); + splitter.addEventListener('resize', () => { + const treeElement = document.querySelector('#sync-node-tree-container'); + const newWidth = parseFloat(treeElement.style.width); + treeElement.style.minWidth = Math.max(newWidth, 50) + 'px'; + }); // Automatically trigger a refresh the first time this tab is selected. document.querySelector('cr-tab-box')
diff --git a/components/sync/driver/sync_user_settings_impl.cc b/components/sync/driver/sync_user_settings_impl.cc index 94c6852..cc309eaa 100644 --- a/components/sync/driver/sync_user_settings_impl.cc +++ b/components/sync/driver/sync_user_settings_impl.cc
@@ -252,7 +252,7 @@ #endif types.RetainAll(registered_model_types_); - static_assert(39 == GetNumModelTypes(), + static_assert(40 == GetNumModelTypes(), "If adding a new sync data type, update the list below below if" " you want to disable the new data type for local sync."); types.PutAll(ControlTypes());
diff --git a/components/sync/driver/sync_user_settings_impl_unittest.cc b/components/sync/driver/sync_user_settings_impl_unittest.cc index e06e7ac..883c7bf 100644 --- a/components/sync/driver/sync_user_settings_impl_unittest.cc +++ b/components/sync/driver/sync_user_settings_impl_unittest.cc
@@ -39,9 +39,9 @@ } #else // Ignore all Chrome OS types on non-Chrome OS platforms. - user_types.RemoveAll({APP_LIST, ARC_PACKAGE, OS_PREFERENCES, - OS_PRIORITY_PREFERENCES, PRINTERS, WIFI_CONFIGURATIONS, - WORKSPACE_DESK}); + user_types.RemoveAll( + {APP_LIST, ARC_PACKAGE, OS_PREFERENCES, OS_PRIORITY_PREFERENCES, PRINTERS, + PRINTERS_AUTHORIZATION_SERVERS, WIFI_CONFIGURATIONS, WORKSPACE_DESK}); #endif return user_types; }
diff --git a/components/sync/engine/cycle/data_type_tracker.cc b/components/sync/engine/cycle/data_type_tracker.cc index 31832431..350938b 100644 --- a/components/sync/engine/cycle/data_type_tracker.cc +++ b/components/sync/engine/cycle/data_type_tracker.cc
@@ -84,6 +84,7 @@ case APP_LIST: case ARC_PACKAGE: case PRINTERS: + case PRINTERS_AUTHORIZATION_SERVERS: case READING_LIST: case USER_CONSENTS: case SEND_TAB_TO_SELF: @@ -138,6 +139,7 @@ case APP_LIST: case ARC_PACKAGE: case PRINTERS: + case PRINTERS_AUTHORIZATION_SERVERS: case READING_LIST: case USER_CONSENTS: case SEND_TAB_TO_SELF:
diff --git a/components/sync/nigori/nigori_state.cc b/components/sync/nigori/nigori_state.cc index c2ebd2c1..3511e1e 100644 --- a/components/sync/nigori/nigori_state.cc +++ b/components/sync/nigori/nigori_state.cc
@@ -64,7 +64,7 @@ void UpdateNigoriSpecificsFromEncryptedTypes( ModelTypeSet encrypted_types, sync_pb::NigoriSpecifics* specifics) { - static_assert(39 == GetNumModelTypes(), + static_assert(40 == GetNumModelTypes(), "If adding an encryptable type, update handling below."); specifics->set_encrypt_bookmarks(encrypted_types.Has(BOOKMARKS)); specifics->set_encrypt_preferences(encrypted_types.Has(PREFERENCES)); @@ -86,6 +86,8 @@ specifics->set_encrypt_app_list(encrypted_types.Has(APP_LIST)); specifics->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE)); specifics->set_encrypt_printers(encrypted_types.Has(PRINTERS)); + specifics->set_encrypt_printers_authorization_servers( + encrypted_types.Has(PRINTERS_AUTHORIZATION_SERVERS)); specifics->set_encrypt_reading_list(encrypted_types.Has(READING_LIST)); specifics->set_encrypt_send_tab_to_self( encrypted_types.Has(SEND_TAB_TO_SELF));
diff --git a/components/sync/protocol/entity_specifics.proto b/components/sync/protocol/entity_specifics.proto index 6078b07d..dee2616 100644 --- a/components/sync/protocol/entity_specifics.proto +++ b/components/sync/protocol/entity_specifics.proto
@@ -38,6 +38,7 @@ import "components/sync/protocol/password_specifics.proto"; import "components/sync/protocol/preference_specifics.proto"; import "components/sync/protocol/printer_specifics.proto"; +import "components/sync/protocol/printers_authorization_server_specifics.proto"; import "components/sync/protocol/priority_preference_specifics.proto"; import "components/sync/protocol/reading_list_specifics.proto"; import "components/sync/protocol/search_engine_specifics.proto"; @@ -155,6 +156,7 @@ // the server and by Play Services. (crbug.com/1223853) WebauthnCredentialSpecifics webauthn_credential = 895275; HistorySpecifics history = 963985; + PrintersAuthorizationServerSpecifics printers_authorization_server = 974304; } reserved 218175; reserved "wifi_credential";
diff --git a/components/sync/protocol/nigori_specifics.proto b/components/sync/protocol/nigori_specifics.proto index 8d076e4..421d562 100644 --- a/components/sync/protocol/nigori_specifics.proto +++ b/components/sync/protocol/nigori_specifics.proto
@@ -221,4 +221,8 @@ // Boolean corresponding to whether workspace desk should be encrypted. optional bool encrypt_workspace_desk = 51; + + // Boolean corresponding to whether printers authorization server items should + // be encrypted. + optional bool encrypt_printers_authorization_servers = 52; }
diff --git a/components/sync/protocol/printers_authorization_server_specifics.proto b/components/sync/protocol/printers_authorization_server_specifics.proto new file mode 100644 index 0000000..06275c4 --- /dev/null +++ b/components/sync/protocol/printers_authorization_server_specifics.proto
@@ -0,0 +1,25 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Sync protocol datatype extension for printer data. + +// If you change or add any fields in this file, update proto_visitors.h and +// potentially proto_enum_conversions.{h, cc}. + +syntax = "proto2"; + +option java_multiple_files = true; +option java_package = "org.chromium.components.sync.protocol"; + +option optimize_for = LITE_RUNTIME; + +package sync_pb; + +// Represents trusted Authorization Server for printers. +message PrintersAuthorizationServerSpecifics { + // Universal Resource Identifier for the authorization server on the network. + // The scheme must be https. Example: https://address.example:port/path/path. + // This field must be unique and is required. + optional string uri = 1; +}
diff --git a/components/sync/protocol/proto_value_conversions.cc b/components/sync/protocol/proto_value_conversions.cc index 3e840db..65a2a25 100644 --- a/components/sync/protocol/proto_value_conversions.cc +++ b/components/sync/protocol/proto_value_conversions.cc
@@ -33,6 +33,7 @@ #include "components/sync/protocol/password_specifics.pb.h" #include "components/sync/protocol/preference_specifics.pb.h" #include "components/sync/protocol/printer_specifics.pb.h" +#include "components/sync/protocol/printers_authorization_server_specifics.pb.h" #include "components/sync/protocol/priority_preference_specifics.pb.h" #include "components/sync/protocol/proto_visitors.h" #include "components/sync/protocol/reading_list_specifics.pb.h" @@ -321,6 +322,7 @@ IMPLEMENT_PROTO_TO_VALUE(PreferenceSpecifics) IMPLEMENT_PROTO_TO_VALUE(PrinterPPDReference) IMPLEMENT_PROTO_TO_VALUE(PrinterSpecifics) +IMPLEMENT_PROTO_TO_VALUE(PrintersAuthorizationServerSpecifics) IMPLEMENT_PROTO_TO_VALUE(PriorityPreferenceSpecifics) IMPLEMENT_PROTO_TO_VALUE(ReadingListSpecifics) IMPLEMENT_PROTO_TO_VALUE(SearchEngineSpecifics)
diff --git a/components/sync/protocol/proto_value_conversions.h b/components/sync/protocol/proto_value_conversions.h index a800d0c1..e83278a 100644 --- a/components/sync/protocol/proto_value_conversions.h +++ b/components/sync/protocol/proto_value_conversions.h
@@ -47,6 +47,7 @@ class PreferenceSpecifics; class PrinterPPDReference; class PrinterSpecifics; +class PrintersAuthorizationServerSpecifics; class PriorityPreferenceSpecifics; class ReadingListSpecifics; class SearchEngineSpecifics; @@ -184,6 +185,11 @@ std::unique_ptr<base::DictionaryValue> PrinterSpecificsToValue( const sync_pb::PrinterSpecifics& printer_specifics); +std::unique_ptr<base::DictionaryValue> +PrintersAuthorizationServerSpecificsToValue( + const sync_pb::PrintersAuthorizationServerSpecifics& + printers_authorization_server_specifics); + std::unique_ptr<base::DictionaryValue> PriorityPreferenceSpecificsToValue( const sync_pb::PriorityPreferenceSpecifics& proto);
diff --git a/components/sync/protocol/proto_value_conversions_unittest.cc b/components/sync/protocol/proto_value_conversions_unittest.cc index 46bead76f..6ab6c335 100644 --- a/components/sync/protocol/proto_value_conversions_unittest.cc +++ b/components/sync/protocol/proto_value_conversions_unittest.cc
@@ -57,7 +57,7 @@ DEFINE_SPECIFICS_TO_VALUE_TEST(encrypted) -static_assert(39 == syncer::GetNumModelTypes(), +static_assert(40 == syncer::GetNumModelTypes(), "When adding a new field, add a DEFINE_SPECIFICS_TO_VALUE_TEST " "for your field below, and optionally a test for the specific " "conversions."); @@ -84,6 +84,7 @@ DEFINE_SPECIFICS_TO_VALUE_TEST(password) DEFINE_SPECIFICS_TO_VALUE_TEST(preference) DEFINE_SPECIFICS_TO_VALUE_TEST(printer) +DEFINE_SPECIFICS_TO_VALUE_TEST(printers_authorization_server) DEFINE_SPECIFICS_TO_VALUE_TEST(priority_preference) DEFINE_SPECIFICS_TO_VALUE_TEST(reading_list) DEFINE_SPECIFICS_TO_VALUE_TEST(search_engine)
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index 2d8bddd9..23ae6a45 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -33,6 +33,7 @@ #include "components/sync/protocol/persisted_entity_data.pb.h" #include "components/sync/protocol/preference_specifics.pb.h" #include "components/sync/protocol/printer_specifics.pb.h" +#include "components/sync/protocol/printers_authorization_server_specifics.pb.h" #include "components/sync/protocol/priority_preference_specifics.pb.h" #include "components/sync/protocol/proto_enum_conversions.h" #include "components/sync/protocol/reading_list_specifics.pb.h" @@ -462,7 +463,7 @@ } VISIT_PROTO_FIELDS(const sync_pb::EntitySpecifics& proto) { - static_assert(39 == GetNumModelTypes(), + static_assert(40 == GetNumModelTypes(), "When adding a new protocol type, you will likely need to add " "it here as well."); VISIT(encrypted); @@ -488,6 +489,7 @@ VISIT(password); VISIT(preference); VISIT(printer); + VISIT(printers_authorization_server); VISIT(priority_preference); VISIT(reading_list); VISIT(search_engine); @@ -827,6 +829,10 @@ VISIT(make_and_model); } +VISIT_PROTO_FIELDS(const sync_pb::PrintersAuthorizationServerSpecifics& proto) { + VISIT(uri); +} + VISIT_PROTO_FIELDS(const sync_pb::PriorityPreferenceSpecifics& proto) { VISIT(preference); }
diff --git a/components/sync/protocol/protocol_sources.gni b/components/sync/protocol/protocol_sources.gni index d73f98f..ba612f8 100644 --- a/components/sync/protocol/protocol_sources.gni +++ b/components/sync/protocol/protocol_sources.gni
@@ -47,6 +47,7 @@ "persisted_entity_data.proto", "preference_specifics.proto", "printer_specifics.proto", + "printers_authorization_server_specifics.proto", "priority_preference_specifics.proto", "reading_list_specifics.proto", "search_engine_specifics.proto",
diff --git a/components/ukm/debug/BUILD.gn b/components/ukm/debug/BUILD.gn index ad53401..d464fd8 100644 --- a/components/ukm/debug/BUILD.gn +++ b/components/ukm/debug/BUILD.gn
@@ -2,7 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//third_party/closure_compiler/compile_js.gni") +import("//tools/grit/preprocess_if_expr.gni") +import("//tools/typescript/ts_library.gni") source_set("util") { sources = [ @@ -16,13 +17,16 @@ ] } -js_type_check("closure_compile") { - deps = [ ":ukm_internals" ] +preprocess_if_expr("preprocess") { + in_folder = "." + out_folder = target_gen_dir + in_files = [ "ukm_internals.ts" ] } -js_library("ukm_internals") { - deps = [ - "//ui/webui/resources/js:cr", - "//ui/webui/resources/js:util", - ] +ts_library("build_ts") { + root_dir = target_gen_dir + out_dir = "$target_gen_dir/tsc" + in_files = [ "ukm_internals.ts" ] + deps = [ "//ui/webui/resources:library" ] + extra_deps = [ ":preprocess" ] }
diff --git a/components/ukm/debug/ukm_internals.js b/components/ukm/debug/ukm_internals.ts similarity index 66% rename from components/ukm/debug/ukm_internals.js rename to components/ukm/debug/ukm_internals.ts index 991fd1d..6ed0ad67 100644 --- a/components/ukm/debug/ukm_internals.js +++ b/components/ukm/debug/ukm_internals.ts
@@ -4,80 +4,69 @@ // <if expr="is_ios"> import 'chrome://resources/js/ios/web_ui.js'; + // </if> +import {assert} from 'chrome://resources/js/assert_ts.js'; import {sendWithPromise} from 'chrome://resources/js/cr.m.js'; import {$, createElementWithClassName} from 'chrome://resources/js/util.m.js'; -/** - * @typedef {{ - * name: string, - * value: !Array<number> - * }} - */ -let Metric; +type Metric = { + name: string, + value: [number, number], +}; -/** - * @typedef {{ - * name: string, - * metrics: !Array<!Metric> - * }} - */ -let UkmEntry; +type UkmEntry = { + name: string, + metrics: Metric[], +}; -/** - * @typedef {{ - * url: string, - * id: !Array<number>, - * entries: !Array<UkmEntry>, - * }} - */ -let UkmDataSource; +type UkmDataSource = { + id: [number, number], + entries: UkmEntry[], + url?: string, +}; /** * The Ukm data sent from the browser. - * @typedef {{ - * state: boolean, - * client_id: !Array<number>, - * session_id: string, - * sources: !Array<!UkmDataSource>, - * is_sampling_enabled: boolean, - * }} */ -let UkmData; +type UkmData = { + state: boolean, + client_id: number[], + session_id: string, + sources: UkmDataSource[], + is_sampling_enabled: boolean, +}; /** * Stores source id and number of entries shown. If there is a new source id * or there are new entries in Ukm recorder, then all the entries for * the new source ID will be displayed. - * @type{Map<string, number>} */ -const ClearedSources = new Map(); +const clearedSources: Map<string, number> = new Map(); /** * Cached sources to persist beyond the log cut. This will ensure that the data * on the page don't disappear if there is a log cut. The caching will * start when the page is loaded and when the data is refreshed. * Stored data is sourceid -> UkmDataSource with array of distinct entries. - * @type{Map<string, !UkmDataSource>} */ -const CachedSources = new Map(); +const cachedSources: Map<string, UkmDataSource> = new Map(); /** * Text for empty url. - * @type {string} */ -const URL_EMPTY = 'missing'; +const URL_EMPTY: string = 'missing'; /** * Converts a pair of JS 32 bin number to 64 bit hex string. This is used to * pass 64 bit numbers from UKM like client id and 64 bit metrics to * the javascript. - * @param {!Array<number>} num A pair of javascript signed int. - * @return {string} unsigned int64 as hex number or a decimal number if the + * @param num A pair of javascript signed int. + * @return unsigned int64 as hex number or a decimal number if the * value is smaller than 32bit. */ -function as64Bit(num) { +function as64Bit(num: [number, number]): string { if (num.length !== 2) { return '0'; } @@ -93,19 +82,19 @@ /** * Sets the display option of all the elements in HtmlCollection to the value * passed. - * @param {!HTMLCollection<!Element>} collection Collection of Elements. */ -function setDisplayStyle(collection, display_value) { - for (const el of collection) { - el.style.display = display_value; +function setDisplayStyle( + elements: NodeListOf<HTMLElement>, displayValue: string) { + for (const el of elements) { + el.style.display = displayValue; } } /** * Remove all the child elements. - * @param {!Element} parent Parent element whose children will get removed. + * @param parent Parent element whose children will get removed. */ -function removeChildren(parent) { +function removeChildren(parent: Element) { while (parent.firstChild) { parent.removeChild(parent.firstChild); } @@ -113,13 +102,14 @@ /** * Create card for URL. - * @param {!Array<!UkmDataSource>} sourcesForUrl Sources that are for same URL. - * @param {string} url URL or Source id as hex string if the URL is missing. - * @param {!Element} sourcesDiv Sources div where this card will be added to. - * @param {!Map<string, ?string>} displayState Map from source id to value - * of display property of the entries div. + * @param sourcesForUrl Sources that are for same URL. + * @param sourcesDiv Sources div where this card will be added to. + * @param displayState Map from source id to value of display property of the + * entries div. */ -function createUrlCard(sourcesForUrl, url, sourcesDiv, displayState) { +function createUrlCard( + sourcesForUrl: UkmDataSource[], sourcesDiv: Element, + displayState: Map<string, string>) { const sourceDiv = createElementWithClassName('div', 'url_card'); sourcesDiv.appendChild(sourceDiv); if (!sourcesForUrl || sourcesForUrl.length === 0) { @@ -127,8 +117,8 @@ } for (const source of sourcesForUrl) { // This div allows hiding of the metrics per URL. - const sourceContainer = /** @type {!Element} */ (createElementWithClassName( - 'div', 'source_container')); + const sourceContainer = /** @type {!Element} */ ( + createElementWithClassName('div', 'source_container')); sourceDiv.appendChild(sourceContainer); createUrlHeader(source.url, source.id, sourceContainer); createSourceCard( @@ -138,22 +128,23 @@ /** * Create header containing URL and source ID data. - * @param {?string} url URL. - * @param {!Array<number>} id SourceId as hex. - * @param {!Element} sourceDiv Div under which header will get added. + * @param id SourceId as hex. + * @param sourceDiv Div under which header will get added. */ -function createUrlHeader(url, id, sourceDiv) { +function createUrlHeader( + url: string|undefined, id: [number, number], sourceDiv: Element) { const headerElement = createElementWithClassName('div', 'collapsible_header'); sourceDiv.appendChild(headerElement); - const urlElement = createElementWithClassName('span', 'url'); + const urlElement = createElementWithClassName('span', 'url') as HTMLElement; urlElement.innerText = url ? url : URL_EMPTY; headerElement.appendChild(urlElement); - const idElement = createElementWithClassName('span', 'sourceid'); + const idElement = + createElementWithClassName('span', 'sourceid') as HTMLElement; idElement.innerText = as64Bit(id); headerElement.appendChild(idElement); // Make the click on header toggle entries div. headerElement.addEventListener('click', () => { - const content = headerElement.nextElementSibling; + const content = headerElement.nextElementSibling as HTMLElement; if (content.style.display === 'block') { content.style.display = 'none'; } else { @@ -164,14 +155,15 @@ /** * Create a card with UKM Source data. - * @param {!UkmDataSource} source UKM source data. - * @param {!Element} sourceDiv Source div where this card will be added to. - * @param {?string} displayState If display style of this source id is modified + * @param source UKM source data. + * @param sourceDiv Source div where this card will be added to. + * @param displayState If display style of this source id is modified * then the state of the display style. */ -function createSourceCard(source, sourceDiv, displayState) { +function createSourceCard( + source: UkmDataSource, sourceDiv: Element, displayState: string|undefined) { const metricElement = - /** @type {!Element} */ (createElementWithClassName('div', 'entries')); + createElementWithClassName('div', 'entries') as HTMLElement; sourceDiv.appendChild(metricElement); const sortedEntry = source.entries.sort((x, y) => x.name.localeCompare(y.name)); @@ -192,10 +184,10 @@ /** * Create UKM Entry Table. - * @param {!UkmEntry} entry A Ukm metrics Entry. - * @param {!Element} sourceDiv Element whose children will be the entries. + * @param entry A Ukm metrics Entry. + * @param sourceDiv Element whose children will be the entries. */ -function createEntryTable(entry, sourceDiv) { +function createEntryTable(entry: UkmEntry, sourceDiv: Element) { // Add first column to the table. const entryTable = createElementWithClassName('table', 'entry_table'); entryTable.setAttribute('value', entry.name); @@ -203,7 +195,7 @@ const firstRow = document.createElement('tr'); entryTable.appendChild(firstRow); const entryName = createElementWithClassName('td', 'entry_name'); - entryName.setAttribute('rowspan', 0); + entryName.setAttribute('rowspan', '0'); entryName.textContent = entry.name; firstRow.appendChild(entryName); @@ -229,11 +221,12 @@ * urls alphabetically. * If the URL field is missing, the source ID will be used as the * URL for the purpose of grouping and sorting. - * @param {!Array<!UkmDataSource>} sources List of UKM data for a source . - * @return {!Map<string, !Array<!UkmDataSource>>} Mapping in the sorted - * order of URL from URL to list of sources for the URL. + * @param sources List of UKM data for a source . + * @return Mapping in the sorted order of URL from URL to list of sources for + * the URL. */ -function urlToSourcesMapping(sources) { +function urlToSourcesMapping(sources: UkmDataSource[]): + Map<string, UkmDataSource[]> { const unsorted = new Map(); for (const source of sources) { const key = source.url ? source.url : as64Bit(source.id); @@ -244,8 +237,8 @@ } } // Sort the map by URLs. - return new Map(Array.from(unsorted).sort( - (s1,s2) => s1[0].localeCompare(s2[0]))); + return new Map( + Array.from(unsorted).sort((s1, s2) => s1[0].localeCompare(s2[0]))); } @@ -258,10 +251,12 @@ toggleExpand.addEventListener('click', () => { if (toggleExpand.textContent === 'Expand') { toggleExpand.textContent = 'Collapse'; - setDisplayStyle(document.getElementsByClassName('entries'), 'block'); + setDisplayStyle( + document.body.querySelectorAll<HTMLElement>('.entries'), 'block'); } else { toggleExpand.textContent = 'Expand'; - setDisplayStyle(document.getElementsByClassName('entries'), 'none'); + setDisplayStyle( + document.body.querySelectorAll<HTMLElement>('.entries'), 'none'); } }); } @@ -277,8 +272,8 @@ // Note it won't be able to clear if UKM logs got cut during this call. sendWithPromise('requestUkmData').then((/** @type {UkmData} */ data) => { updateUkmCache(data); - for (const s of CachedSources.values()) { - ClearedSources.set(as64Bit(s.id), s.entries.length); + for (const s of cachedSources.values()) { + clearedSources.set(as64Bit(s.id), s.entries.length); } }); $('toggle_expand').textContent = 'Expand'; @@ -288,10 +283,12 @@ /** * Populate thread ids from the high bit of source id in sources. - * @param {!Array<!UkmDataSource>} sources Array of UKM source. + * @param sources Array of UKM source. */ -function populateThreadIds(sources) { - const threadIdSelect = $('thread_ids'); +function populateThreadIds(sources: UkmDataSource[]) { + const threadIdSelect = + document.body.querySelector<HTMLSelectElement>('#thread_ids'); + assert(threadIdSelect); const currentOptions = new Set(Array.from(threadIdSelect.options).map(o => o.value)); // The first 32 bit of the ID is the recorder ID, convert it to a positive @@ -315,10 +312,10 @@ * by name to ensure that two entries containing the same metrics and values in * different orders have identical string representation to avoid cache * duplication. - * @param {UkmEntry} entry UKM entry to be stringified. - * @return {string} Normalized string representation of the entry. + * @param entry UKM entry to be stringified. + * @return Normalized string representation of the entry. */ -function normalizeToString(entry) { +function normalizeToString(entry: UkmEntry): string { entry.metrics.sort((x, y) => x.name.localeCompare(y.name)); return JSON.stringify(entry); } @@ -330,24 +327,25 @@ * timestamp with entries. So only distinct entries will be recorded in the * cache. i.e if two entries have exactly the same set of metrics then one * of the entry will not be kept in the cache. - * @param {UkmData} data New UKM data to add to cache. + * @param data New UKM data to add to cache. */ -function updateUkmCache(data) { +function updateUkmCache(data: UkmData) { for (const source of data.sources) { const key = as64Bit(source.id); - if (!CachedSources.has(key)) { - const mergedSource = {id: source.id, entries: source.entries}; + if (!cachedSources.has(key)) { + const mergedSource: + UkmDataSource = {id: source.id, entries: source.entries}; if (source.url) { mergedSource.url = source.url; } - CachedSources.set(key, mergedSource); + cachedSources.set(key, mergedSource); } else { // Merge distinct entries from the source. - const existingEntries = new Set(CachedSources.get(key).entries.map( + const existingEntries = new Set(cachedSources.get(key)!.entries.map( cachedEntry => normalizeToString(cachedEntry))); for (const sourceEntry of source.entries) { if (!existingEntries.has(normalizeToString(sourceEntry))) { - CachedSources.get(key).entries.push(sourceEntry); + cachedSources.get(key)!.entries.push(sourceEntry); } } } @@ -361,10 +359,11 @@ function updateUkmData() { sendWithPromise('requestUkmData').then((/** @type {UkmData} */ data) => { updateUkmCache(data); - if ($('include_cache').checked) { - data.sources = [...CachedSources.values()]; + if (document.body.querySelector<HTMLInputElement>( + '#include_cache')!.checked) { + data.sources = [...cachedSources.values()]; } - $('state').innerText = data.state? 'ENABLED' : 'DISABLED'; + $('state').innerText = data.state ? 'ENABLED' : 'DISABLED'; $('clientid').innerText = '0x' + data.client_id; $('sessionid').innerText = data.session_id; $('is_sampling_enabled').innerText = data.is_sampling_enabled; @@ -384,14 +383,15 @@ // for example, expanded state. const currentDisplayState = new Map(); for (const el of document.getElementsByClassName('source_container')) { - currentDisplayState.set(el.querySelector('.sourceid').textContent, - el.querySelector('.entries').style.display); + currentDisplayState.set( + el.querySelector<HTMLElement>('.sourceid')!.textContent, + el.querySelector<HTMLElement>('.entries')!.style.display); } - const urlToSources = urlToSourcesMapping( - filterSourcesUsingFormOptions(data.sources)); + const urlToSources = + urlToSourcesMapping(filterSourcesUsingFormOptions(data.sources)); for (const url of urlToSources.keys()) { - const sourcesForUrl = urlToSources.get(url); - createUrlCard(sourcesForUrl, url, sourcesDiv, currentDisplayState); + const sourcesForUrl = urlToSources.get(url)!; + createUrlCard(sourcesForUrl, sourcesDiv, currentDisplayState); } populateThreadIds(data.sources); }); @@ -400,23 +400,23 @@ /** * Filter sources that have been recorded previously. If it sees a source id * where number of entries has decreased then it will add a warning. - * @param {!Array<!UkmDataSource>} sources All the sources currently in - * UKM recorder. - * @return {!Array<!UkmDataSource>} Sources which are new or have a new entry - * logged for them. + * @param sources All the sources currently in UKM recorder. + * @return Sources which are new or have a new entry logged for them. */ -function filterSourcesUsingFormOptions(sources) { +function filterSourcesUsingFormOptions(sources: UkmDataSource[]): + UkmDataSource[] { // Filter sources based on if they have been cleared. - const newSources = sources.filter(source => ( - // Keep sources if it is newly generated since clearing earlier. - !ClearedSources.has(as64Bit(source.id)) || - // Keep sources if it has increased entities since clearing earlier. - (source.entries.length > ClearedSources.get(as64Bit(source.id))) - )); + const newSources = sources.filter( + source => ( + // Keep sources if it is newly generated since clearing earlier. + !clearedSources.has(as64Bit(source.id)) || + // Keep sources if it has increased entities since clearing earlier. + (source.entries.length > clearedSources.get(as64Bit(source.id))!))); // Applies the filter from Metrics selector. const newSourcesWithEntriesCleared = newSources.map(source => { - const metricsFilterValue = $('metrics_select').value; + const metricsFilterValue = + document.body.querySelector<HTMLInputElement>('#metrics_select')!.value; if (metricsFilterValue) { const metricsRe = new RegExp(metricsFilterValue); source.entries = source.entries.filter(e => metricsRe.test(e.name)); @@ -425,10 +425,21 @@ }); // Filter sources based on the status of check-boxes. - const filteredSources = newSourcesWithEntriesCleared.filter(source => ( - (!$('hide_no_url').checked || source.url) && - (!$('hide_no_metrics').checked || source.entries.length) - )); + const filteredSources = newSourcesWithEntriesCleared.filter(source => { + const noUrlCheckbox = + document.body.querySelector<HTMLInputElement>('#hide_no_url'); + assert(noUrlCheckbox); + const noMetricsCheckbox = + document.body.querySelector<HTMLInputElement>('#hide_no_metrics'); + assert(noMetricsCheckbox); + + return (!noUrlCheckbox.checked || source.url) && + (!noMetricsCheckbox.checked || source.entries.length); + }); + + const threadIds = + document.body.querySelector<HTMLSelectElement>('#thread_ids'); + assert(threadIds); // Filter sources based on thread id (High bits of UKM Recorder ID). const threadsFilteredSource = filteredSources.filter(source => { @@ -439,8 +450,7 @@ // If a UKM is recorded with a custom source id or in renderer, it will // have a unique value for this shared by all metrics that use the // same thread. - const selectedOption = - $('thread_ids').options[$('thread_ids').selectedIndex]; + const selectedOption = threadIds.options[threadIds.selectedIndex]; // Return true if either of the following is true - // No option is selected or selected option is "All" or the hexadecimal // representation of source id is matching. @@ -449,8 +459,11 @@ }); // Filter URLs based on URL selector input. + const urlSelect = + document.body.querySelector<HTMLInputElement>('#url_select'); + assert(urlSelect); return threadsFilteredSource.filter(source => { - const urlFilterValue = $('url_select').value; + const urlFilterValue = urlSelect.value; if (urlFilterValue) { const urlRe = new RegExp(urlFilterValue); // Will also match missing URLs by default.
diff --git a/components/update_client/protocol_serializer_json.cc b/components/update_client/protocol_serializer_json.cc index 4990950..6d698b7 100644 --- a/components/update_client/protocol_serializer_json.cc +++ b/components/update_client/protocol_serializer_json.cc
@@ -33,8 +33,8 @@ request_node->SetKey("sessionid", Value(request.session_id)); request_node->SetKey("requestid", Value(request.request_id)); request_node->SetKey("@updater", Value(request.updatername)); - request_node->SetKey("prodversion", Value(request.updaterversion)); - request_node->SetKey("updaterversion", Value(request.prodversion)); + request_node->SetKey("prodversion", Value(request.prodversion)); + request_node->SetKey("updaterversion", Value(request.updaterversion)); request_node->SetKey("@os", Value(request.operating_system)); request_node->SetKey("arch", Value(request.arch)); request_node->SetKey("nacl_arch", Value(request.nacl_arch));
diff --git a/components/url_formatter/android/BUILD.gn b/components/url_formatter/android/BUILD.gn index 06b27dd..cf39d43 100644 --- a/components/url_formatter/android/BUILD.gn +++ b/components/url_formatter/android/BUILD.gn
@@ -25,7 +25,7 @@ [ "java/src/org/chromium/components/url_formatter/UrlFormatter.java" ] } -android_library("url_formatter_javatests") { +android_library("unit_device_javatests") { testonly = true sources = [ "javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java" ]
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index 443b418..c9f2c23 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -972,7 +972,17 @@ return; } - if (absl::holds_alternative<RegionCaptureCropId>(target_->sub_target)) { + // If the target is in a different renderer than the root renderer (indicated + // by having a different frame sink ID), we currently cannot provide + // reasonable metadata about the region capture rect. For more context, see + // https://crbug.com/1327560. + // + // TODO(https://crbug.com/1335175): Provide accurate bounds for elements + // embedded in different renderers. + const bool is_same_frame_sink_as_requested = + resolved_target_->GetFrameSinkId() == target_->frame_sink_id; + if (absl::holds_alternative<RegionCaptureCropId>(target_->sub_target) && + is_same_frame_sink_as_requested) { const float scale_factor = frame_metadata.device_scale_factor; metadata.region_capture_rect = scale_factor ? ScaleToEnclosingRect(capture_region, 1.0f / scale_factor)
diff --git a/content/BUILD.gn b/content/BUILD.gn index 7f214c56..5143494 100644 --- a/content/BUILD.gn +++ b/content/BUILD.gn
@@ -94,6 +94,7 @@ "content_resources.pak", ] deps = [ + "//components/ukm/debug:build_ts", "//content/browser/resources/histograms:build_ts", "//gpu/ipc/common:vulkan_interface_webui_js", "//ui/base/mojom:mojom_js",
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 85461ea..c6a6501 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2767,8 +2767,6 @@ sources += [ "media/cdm_file_impl.cc", "media/cdm_file_impl.h", - "media/cdm_storage_impl.cc", - "media/cdm_storage_impl.h", "media/media_license_database.cc", "media/media_license_database.h", "media/media_license_manager.cc",
diff --git a/content/browser/attribution_reporting/attribution_internals_ui.h b/content/browser/attribution_reporting/attribution_internals_ui.h index 2587d7e..e2b8712 100644 --- a/content/browser/attribution_reporting/attribution_internals_ui.h +++ b/content/browser/attribution_reporting/attribution_internals_ui.h
@@ -7,8 +7,7 @@ #include <memory> -#include "content/browser/attribution_reporting/attribution_internals.mojom.h" -#include "content/common/content_export.h" +#include "content/browser/attribution_reporting/attribution_internals.mojom-forward.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/webui_config.h" #include "content/public/common/url_constants.h" @@ -18,6 +17,8 @@ class AttributionInternalsHandlerImpl; class AttributionInternalsUI; +class RenderFrameHost; +class WebUI; // WebUIConfig for chrome://attribution-internals page class AttributionInternalsUIConfig @@ -29,14 +30,13 @@ }; // WebUI which handles serving the chrome://attribution-internals page. -class CONTENT_EXPORT AttributionInternalsUI : public WebUIController { +class AttributionInternalsUI : public WebUIController { public: explicit AttributionInternalsUI(WebUI* web_ui); - AttributionInternalsUI(const AttributionInternalsUI& other) = delete; - AttributionInternalsUI& operator=(const AttributionInternalsUI& other) = - delete; - AttributionInternalsUI(AttributionInternalsUI&& other) = delete; - AttributionInternalsUI& operator=(AttributionInternalsUI&& other) = delete; + AttributionInternalsUI(const AttributionInternalsUI&) = delete; + AttributionInternalsUI& operator=(const AttributionInternalsUI&) = delete; + AttributionInternalsUI(AttributionInternalsUI&&) = delete; + AttributionInternalsUI& operator=(AttributionInternalsUI&&) = delete; ~AttributionInternalsUI() override; // WebUIController overrides:
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.h b/content/browser/attribution_reporting/attribution_manager_impl.h index 17434b76..0f59521 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.h +++ b/content/browser/attribution_reporting/attribution_manager_impl.h
@@ -10,7 +10,6 @@ #include <vector> #include "base/callback_forward.h" -#include "base/compiler_specific.h" #include "base/containers/circular_deque.h" #include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" @@ -76,11 +75,10 @@ StoragePartitionImpl* storage_partition, const base::FilePath& user_data_directory, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy); - AttributionManagerImpl(const AttributionManagerImpl& other) = delete; - AttributionManagerImpl& operator=(const AttributionManagerImpl& other) = - delete; - AttributionManagerImpl(AttributionManagerImpl&& other) = delete; - AttributionManagerImpl& operator=(AttributionManagerImpl&& other) = delete; + AttributionManagerImpl(const AttributionManagerImpl&) = delete; + AttributionManagerImpl& operator=(const AttributionManagerImpl&) = delete; + AttributionManagerImpl(AttributionManagerImpl&&) = delete; + AttributionManagerImpl& operator=(AttributionManagerImpl&&) = delete; ~AttributionManagerImpl() override; // AttributionManager:
diff --git a/content/browser/attribution_reporting/rate_limit_table.h b/content/browser/attribution_reporting/rate_limit_table.h index 30766ffc..77f8b706 100644 --- a/content/browser/attribution_reporting/rate_limit_table.h +++ b/content/browser/attribution_reporting/rate_limit_table.h
@@ -12,7 +12,6 @@ #include "base/sequence_checker.h" #include "base/thread_annotations.h" #include "base/time/time.h" -#include "content/browser/attribution_reporting/attribution_storage.h" #include "content/browser/attribution_reporting/stored_source.h" #include "content/common/content_export.h" @@ -51,10 +50,10 @@ }; explicit RateLimitTable(const AttributionStorageDelegate* delegate); - RateLimitTable(const RateLimitTable& other) = delete; - RateLimitTable& operator=(const RateLimitTable& other) = delete; - RateLimitTable(RateLimitTable&& other) = delete; - RateLimitTable& operator=(RateLimitTable&& other) = delete; + RateLimitTable(const RateLimitTable&) = delete; + RateLimitTable& operator=(const RateLimitTable&) = delete; + RateLimitTable(RateLimitTable&&) = delete; + RateLimitTable& operator=(RateLimitTable&&) = delete; ~RateLimitTable(); // Creates the table in |db| if it doesn't exist.
diff --git a/content/browser/attribution_reporting/send_result.h b/content/browser/attribution_reporting/send_result.h index 1dd24e2f..ed8dc359 100644 --- a/content/browser/attribution_reporting/send_result.h +++ b/content/browser/attribution_reporting/send_result.h
@@ -5,8 +5,6 @@ #ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_SEND_RESULT_H_ #define CONTENT_BROWSER_ATTRIBUTION_REPORTING_SEND_RESULT_H_ -#include "content/common/content_export.h" - namespace content { // Struct that contains data about sent reports. Some info is displayed in the @@ -14,7 +12,7 @@ // TODO(apaseltiner): Consider replacing this struct with a single int that // contains either HTTP response code, network error, or custom values for // `Status::kDropped` and `Status::kFailedToAssemble`. -struct CONTENT_EXPORT SendResult { +struct SendResult { enum class Status { kSent, // The report failed without receiving response headers.
diff --git a/content/browser/buckets/bucket_manager_host.cc b/content/browser/buckets/bucket_manager_host.cc index 2a06ec9..81998f6 100644 --- a/content/browser/buckets/bucket_manager_host.cc +++ b/content/browser/buckets/bucket_manager_host.cc
@@ -104,7 +104,7 @@ } void BucketManagerHost::Keys(KeysCallback callback) { - manager_->quota_manager_proxy()->GetBucketsForStorageKey( + manager_->quota_manager_proxy()->GetBucketsForStorageKeyDeleteExpired( blink::StorageKey(origin_), blink::mojom::StorageType::kTemporary, base::SequencedTaskRunnerHandle::Get(), base::BindOnce(&BucketManagerHost::DidGetBuckets,
diff --git a/content/browser/media/cdm_file_impl.cc b/content/browser/media/cdm_file_impl.cc index 38542a3..feba9c0 100644 --- a/content/browser/media/cdm_file_impl.cc +++ b/content/browser/media/cdm_file_impl.cc
@@ -4,33 +4,19 @@ #include "content/browser/media/cdm_file_impl.h" -#include <set> #include <utility> #include "base/bind.h" #include "base/callback.h" -#include "base/feature_list.h" #include "base/logging.h" #include "base/metrics/histogram_functions.h" -#include "base/notreached.h" #include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "content/browser/media/media_license_storage_host.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/common/content_features.h" -#include "media/base/bind_to_current_loop.h" #include "media/cdm/cdm_type.h" #include "media/mojo/mojom/cdm_storage.mojom.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "storage/browser/file_system/file_stream_reader.h" -#include "storage/browser/file_system/file_stream_writer.h" -#include "storage/browser/file_system/file_system_context.h" -#include "storage/browser/file_system/file_system_operation_context.h" -#include "storage/browser/file_system/file_system_url.h" #include "storage/browser/quota/quota_manager.h" #include "storage/common/file_system/file_system_types.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -54,329 +40,8 @@ const char kWriteTimeUmaName[] = "Media.EME.CdmFileIO.TimeTo.WriteFile"; const char kDeleteTimeUmaName[] = "Media.EME.CdmFileIO.TimeTo.DeleteFile"; -std::string GetTempFileName(const std::string& file_name) { - DCHECK(!base::StartsWith(file_name, std::string(1, kTemporaryFilePrefix), - base::CompareCase::SENSITIVE)); - return kTemporaryFilePrefix + file_name; -} - -// The file system is different for each CDM and each origin. So track files -// in use based on (origin, CDM type, file name). -struct FileLockKey { - FileLockKey(const url::Origin& origin, - const media::CdmType& cdm_type, - const std::string& file_name) - : origin(origin), cdm_type(cdm_type), file_name(file_name) {} - ~FileLockKey() = default; - - // Allow use as a key in std::set. - bool operator<(const FileLockKey& other) const { - return std::tie(origin, cdm_type, file_name) < - std::tie(other.origin, other.cdm_type, other.file_name); - } - - url::Origin origin; - media::CdmType cdm_type; - std::string file_name; -}; - -// File map shared by all CdmFileImpl objects to prevent read/write race. -// A lock must be acquired before opening a file to ensure that the file is not -// currently in use. The lock must be held until the file is closed. -class FileLockMap { - public: - FileLockMap() = default; - - FileLockMap(const FileLockMap&) = delete; - FileLockMap& operator=(const FileLockMap&) = delete; - - ~FileLockMap() = default; - - // Acquire a lock on the file represented by |key|. Returns true if |key| - // is not currently in use, false otherwise. - bool AcquireFileLock(const FileLockKey& key) { - DVLOG(3) << __func__ << " file: " << key.file_name; - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // Add a new entry. If |key| already has an entry, insert() tells so - // with the second piece of the returned value and does not modify - // the original. - return file_lock_map_.insert(key).second; - } - - // Release the lock held on the file represented by |key|. - void ReleaseFileLock(const FileLockKey& key) { - DVLOG(3) << __func__ << " file: " << key.file_name; - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - auto entry = file_lock_map_.find(key); - if (entry == file_lock_map_.end()) { - NOTREACHED() << "Unable to release lock on file " << key.file_name; - return; - } - - file_lock_map_.erase(entry); - } - - private: - // Note that this map is never deleted. As entries are removed when a file - // is closed, it should never get too large. - std::set<FileLockKey> file_lock_map_; - - THREAD_CHECKER(thread_checker_); -}; - -// The FileLockMap is a global lock map shared by all CdmFileImpl instances. -FileLockMap* GetFileLockMap() { - static auto* file_lock_map = new FileLockMap(); - return file_lock_map; -} - -// File stream operations need an IOBuffer to hold the data. This class stores -// the data in a std::vector<uint8_t> to match what is used in the -// mojom::CdmFile API. -class CdmFileIOBuffer : public net::IOBuffer { - public: - // Create an empty buffer of size |size|. - explicit CdmFileIOBuffer(size_t size) : buffer_(size) { - data_ = reinterpret_cast<char*>(buffer_.data()); - } - - // Create a buffer that contains |data|. - explicit CdmFileIOBuffer(const std::vector<uint8_t>& data) : buffer_(data) { - data_ = reinterpret_cast<char*>(buffer_.data()); - } - - // Returns ownership of |buffer_| to the caller. - std::vector<uint8_t>&& TakeData() { return std::move(buffer_); } - - protected: - ~CdmFileIOBuffer() override { data_ = nullptr; } - - private: - std::vector<uint8_t> buffer_; -}; - } // namespace -// Read a file using FileStreamReader. Implemented as a separate class so that -// it can be run on the IO thread. -class CdmFileImpl::FileReader { - public: - // Returns whether the read operation succeeded or not. If |result| = true, - // then |data| is the contents of the file. - using ReadDoneCB = - base::OnceCallback<void(bool result, std::vector<uint8_t> data)>; - - FileReader() = default; - - FileReader(const FileReader&) = delete; - FileReader& operator=(const FileReader&) = delete; - - // Reads the contents of |file_url| and calls |callback| with the result - // (file contents on success, empty data on error). - void Read(scoped_refptr<storage::FileSystemContext> file_system_context, - const storage::FileSystemURL& file_url, - ReadDoneCB callback) { - DVLOG(3) << __func__ << " url: " << file_url.DebugString(); - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(!callback_); - DCHECK(!file_stream_reader_); - - callback_ = std::move(callback); - - file_stream_reader_ = file_system_context->CreateFileStreamReader( - file_url, 0, kMaxFileSizeBytes, base::Time()); - auto result = file_stream_reader_->GetLength( - base::BindOnce(&FileReader::OnGetLength, weak_factory_.GetWeakPtr())); - DVLOG(3) << __func__ << " GetLength(): " << result; - - // If GetLength() is running asynchronously, simply return. - if (result == net::ERR_IO_PENDING) - return; - - // GetLength() was synchronous, so pass the result on. - OnGetLength(result); - } - - private: - // Called when the size of the file to be read is known. Allocates a buffer - // large enough to hold the contents, then attempts to read the contents into - // the buffer. |result| will be the length of the file (if >= 0) or a net:: - // error on failure (if < 0). - void OnGetLength(int64_t result) { - DVLOG(3) << __func__ << " result: " << result; - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(callback_); - DCHECK(file_stream_reader_); - - // If the file doesn't exist, then pretend it is empty. - if (result == net::ERR_FILE_NOT_FOUND) { - std::move(callback_).Run(true, {}); - return; - } - - // Any other failure is an error. - if (result < 0) { - DLOG(WARNING) << __func__ - << " Unable to get file length. result = " << result; - std::move(callback_).Run(false, {}); - return; - } - - // Files are limited in size, so fail if file too big. - if (result > kMaxFileSizeBytes) { - DLOG(WARNING) << __func__ - << " Too much data to read. #bytes = " << result; - std::move(callback_).Run(false, {}); - return; - } - - // Read() sizes (provided and returned) are type int, so cast appropriately. - int bytes_to_read = base::checked_cast<int>(result); - auto buffer = base::MakeRefCounted<CdmFileIOBuffer>( - base::checked_cast<size_t>(bytes_to_read)); - - // Read the contents of the file into |buffer|. - result = file_stream_reader_->Read( - buffer.get(), bytes_to_read, - base::BindOnce(&FileReader::OnRead, weak_factory_.GetWeakPtr(), buffer, - bytes_to_read)); - DVLOG(3) << __func__ << " Read(): " << result; - - // If Read() is running asynchronously, simply return. - if (result == net::ERR_IO_PENDING) - return; - - // Read() was synchronous, so pass the result on. - OnRead(std::move(buffer), bytes_to_read, result); - } - - // Called when the file has been read and returns the result to the callback - // provided to Read(). |result| will be the number of bytes read (if >= 0) or - // a net:: error on failure (if < 0). - void OnRead(scoped_refptr<CdmFileIOBuffer> buffer, - int bytes_to_read, - int result) { - DVLOG(3) << __func__ << " Requested " << bytes_to_read << " bytes, got " - << result; - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(callback_); - DCHECK(file_stream_reader_); - - if (result != bytes_to_read) { - // Unable to read the contents of the file completely. - DLOG(WARNING) << "Failed to read file. Requested " << bytes_to_read - << " bytes, got " << result; - std::move(callback_).Run(false, {}); - return; - } - - // Successful read. Return the bytes read. - std::move(callback_).Run(true, std::move(buffer->TakeData())); - } - - // Called when the read operation is done. - ReadDoneCB callback_; - - // Used to read the stream. - std::unique_ptr<storage::FileStreamReader> file_stream_reader_; - - base::WeakPtrFactory<FileReader> weak_factory_{this}; -}; - -class CdmFileImpl::FileWriter { - public: - // Returns whether the write operation succeeded or not. - using WriteDoneCB = base::OnceCallback<void(bool)>; - - FileWriter() {} - - FileWriter(const FileWriter&) = delete; - FileWriter& operator=(const FileWriter&) = delete; - - // Writes |buffer| as the contents of |file_url| and calls |callback| with - // whether the write succeeded or not. - void Write(scoped_refptr<storage::FileSystemContext> file_system_context, - const storage::FileSystemURL& file_url, - scoped_refptr<net::IOBuffer> buffer, - int bytes_to_write, - WriteDoneCB callback) { - DVLOG(3) << __func__ << " url: " << file_url.DebugString(); - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - callback_ = std::move(callback); - - // Create a writer on |temp_file_name_|. This temp file will be renamed - // after a successful write. - file_stream_writer_ = - file_system_context->CreateFileStreamWriter(file_url, 0); - auto result = file_stream_writer_->Write( - buffer.get(), bytes_to_write, - base::BindOnce(&FileWriter::OnWrite, weak_factory_.GetWeakPtr(), buffer, - bytes_to_write)); - DVLOG(3) << __func__ << " Write(): " << result; - - // If Write() is running asynchronously, simply return. - if (result == net::ERR_IO_PENDING) - return; - - // Write() was synchronous, so pass the result on. - OnWrite(std::move(buffer), bytes_to_write, result); - } - - private: - // Called when the file has been written. |result| will be the number of bytes - // written (if >= 0) or a net:: error on failure (if < 0). - void OnWrite(scoped_refptr<net::IOBuffer> buffer, - int bytes_to_write, - int result) { - DVLOG(3) << __func__ << " Expected to write " << bytes_to_write - << " bytes, got " << result; - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (result != bytes_to_write) { - // Unable to write the file. - DLOG(WARNING) << "Failed to write file. Sent " << bytes_to_write - << " bytes, wrote " << result; - std::move(callback_).Run(false); - return; - } - - result = file_stream_writer_->Flush( - base::BindOnce(&FileWriter::OnFlush, weak_factory_.GetWeakPtr())); - DVLOG(3) << __func__ << " Flush(): " << result; - - // If Flush() is running asynchronously, simply return. - if (result == net::ERR_IO_PENDING) - return; - - // Flush() was synchronous, so pass the result on. - OnFlush(result); - } - - // Called when the file has been flushed. |result| is the net:: error code. - void OnFlush(int result) { - DVLOG(3) << __func__ << " Result: " << result; - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // We are done with |file_stream_writer_|. - file_stream_writer_.reset(); - - DLOG_IF(WARNING, result != net::OK) - << "Failed to flush file, result: " << result; - std::move(callback_).Run(result == net::OK); - } - - // Called when the write operation is done. - WriteDoneCB callback_; - - // Used to write the stream. - std::unique_ptr<storage::FileStreamWriter> file_stream_writer_; - - base::WeakPtrFactory<FileWriter> weak_factory_{this}; -}; - // static bool CdmFileImpl::IsValidName(const std::string& name) { // File names must only contain letters (A-Za-z), digits(0-9), or "._-", @@ -410,26 +75,6 @@ receiver_.Bind(std::move(pending_receiver)); receiver_.set_disconnect_handler(base::BindOnce( &CdmFileImpl::OnReceiverDisconnect, weak_factory_.GetWeakPtr())); - - // The MediaLicenseStorageHost handles file locking. - file_locked_ = true; -} - -CdmFileImpl::CdmFileImpl( - const std::string& file_name, - const url::Origin& origin, - const media::CdmType& cdm_type, - const std::string& file_system_root_uri, - scoped_refptr<storage::FileSystemContext> file_system_context) - : file_name_(file_name), - temp_file_name_(GetTempFileName(file_name_)), - origin_(origin), - cdm_type_(cdm_type), - file_system_root_uri_(file_system_root_uri), - file_system_context_(file_system_context) { - DVLOG(3) << __func__ << " " << file_name_; - DCHECK(IsValidName(file_name_)); - DCHECK(!base::FeatureList::IsEnabled(features::kMediaLicenseBackend)); } CdmFileImpl::~CdmFileImpl() { @@ -441,33 +86,12 @@ if (write_callback_) std::move(write_callback_).Run(Status::kFailure); - - if (file_locked_) - ReleaseFileLock(file_name_); -} - -bool CdmFileImpl::Initialize() { - DVLOG(3) << __func__ << " file: " << file_name_; - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(!file_locked_); - - // Grab the lock on |file_name_|. The lock will be held until this object is - // destructed. - if (!AcquireFileLock(file_name_)) { - DVLOG(2) << "File " << file_name_ << " is already in use."; - return false; - } - - // We have the lock on |file_name_|. |file_locked_| is set to simplify - // validation, and to help destruction not have to check. - file_locked_ = true; - return true; } void CdmFileImpl::Read(ReadCallback callback) { DVLOG(3) << __func__ << " file: " << file_name_; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); + DCHECK(host_); // Only 1 Read() or Write() is allowed at any time. if (read_callback_ || write_callback_) { @@ -479,39 +103,19 @@ read_callback_ = std::move(callback); start_time_ = base::TimeTicks::Now(); - if (host_) { - ReadUsingMediaLicenseStorageDelegate(); - return; - } - - // As reading is done on the IO thread, when it's done ReadDone() needs to be - // called back on this thread. - auto read_done_cb = media::BindToCurrentLoop( - base::BindOnce(&CdmFileImpl::ReadDone, weak_factory_.GetWeakPtr())); - - // Create the file reader that runs on the IO thread, and then call Read() on - // the IO thread. Use of base::Unretained() is OK as the reader is owned by - // |this|, and if |this| is destructed it will destroy the file reader on the - // IO thread. - file_reader_ = base::SequenceBound<FileReader>(GetIOThreadTaskRunner({})); - // TODO(dcheng): Migrate this to use Then()? - file_reader_.AsyncCall(&FileReader::Read) - .WithArgs(file_system_context_, CreateFileSystemURL(file_name_), - std::move(read_done_cb)); + host_->ReadFile( + cdm_type_, file_name_, + base::BindOnce(&CdmFileImpl::DidRead, weak_factory_.GetWeakPtr())); } -void CdmFileImpl::ReadDone(bool success, std::vector<uint8_t> data) { +void CdmFileImpl::DidRead(absl::optional<std::vector<uint8_t>> data) { DVLOG(3) << __func__ << " file: " << file_name_ - << ", success: " << (success ? "yes" : "no"); + << ", success: " << (data.has_value() ? "yes" : "no"); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(file_reader_); DCHECK(read_callback_); + DCHECK(host_); - // We are done with the reader, so destroy it. - file_reader_.Reset(); - - if (!success) { + if (!data.has_value()) { // Unable to read the contents of the file. std::move(read_callback_).Run(Status::kFailure, {}); return; @@ -519,14 +123,14 @@ // Only report reading time for successful reads. ReportFileOperationTimeUMA(kReadTimeUmaName); - std::move(read_callback_).Run(Status::kSuccess, std::move(data)); + std::move(read_callback_).Run(Status::kSuccess, std::move(data.value())); } void CdmFileImpl::Write(const std::vector<uint8_t>& data, WriteCallback callback) { DVLOG(3) << __func__ << " file: " << file_name_ << ", size: " << data.size(); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); + DCHECK(host_); // Only 1 Read() or Write() is allowed at any time. if (read_callback_ || write_callback_) { @@ -554,244 +158,19 @@ return; } - if (host_) { - WriteUsingMediaLicenseStorageDelegate(data); - return; - } - - // Copy |data| into a net::IOBuffer. - int bytes_to_write = base::checked_cast<int>(data.size()); - auto buffer = base::MakeRefCounted<CdmFileIOBuffer>(data); - - // FileStreamWriter only works on existing files. |temp_file_name_| should not - // exist, so create an empty one if necessary. - // We can not use AsyncFileUtil::CreateOrOpen() as it does not work with the - // incognito filesystem (http://crbug.com/958294). - auto url = CreateFileSystemURL(temp_file_name_); - auto* file_util = file_system_context_->GetAsyncFileUtil( - storage::kFileSystemTypePluginPrivate); - auto operation_context = - std::make_unique<storage::FileSystemOperationContext>( - file_system_context_.get()); - operation_context->set_allowed_bytes_growth(storage::QuotaManager::kNoLimit); - file_util->EnsureFileExists( - std::move(operation_context), url, - base::BindOnce(&CdmFileImpl::OnEnsureTempFileExists, - weak_factory_.GetWeakPtr(), std::move(buffer), - bytes_to_write)); -} - -void CdmFileImpl::OnEnsureTempFileExists(scoped_refptr<net::IOBuffer> buffer, - int bytes_to_write, - base::File::Error result, - bool created) { - DVLOG(3) << __func__ << " file: " << temp_file_name_ - << ", result: " << base::File::ErrorToString(result); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(write_callback_); - DCHECK(!file_writer_); - - if (result != base::File::FILE_OK) { - // Unable to create the file. - DLOG(WARNING) << "Failed to create temporary file, result: " - << base::File::ErrorToString(result); - std::move(write_callback_).Run(Status::kFailure); - return; - } - - // If the temp file has just been created, we know it is empty and can simply - // proceed with writing to it. However, if the file exists, truncate it in - // case it is longer than the number of bytes we want to write. - if (created) { - OnTempFileIsEmpty(std::move(buffer), bytes_to_write, result); - return; - } - - auto url = CreateFileSystemURL(temp_file_name_); - auto* file_util = file_system_context_->GetAsyncFileUtil( - storage::kFileSystemTypePluginPrivate); - auto operation_context = - std::make_unique<storage::FileSystemOperationContext>( - file_system_context_.get()); - operation_context->set_allowed_bytes_growth(storage::QuotaManager::kNoLimit); - file_util->Truncate(std::move(operation_context), url, 0, - base::BindOnce(&CdmFileImpl::OnTempFileIsEmpty, - weak_factory_.GetWeakPtr(), - std::move(buffer), bytes_to_write)); -} - -void CdmFileImpl::OnTempFileIsEmpty(scoped_refptr<net::IOBuffer> buffer, - int bytes_to_write, - base::File::Error result) { - DVLOG(3) << __func__ << " file: " << temp_file_name_ - << ", result: " << base::File::ErrorToString(result); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(write_callback_); - DCHECK(!file_writer_); - - if (result != base::File::FILE_OK) { - DLOG(WARNING) << "Failed to truncate temporary file, result: " - << base::File::ErrorToString(result); - std::move(write_callback_).Run(Status::kFailure); - return; - } - - // As writing is done on the IO thread, when it's done WriteDone() needs to be - // called on this thread. - auto write_done_cb = media::BindToCurrentLoop( - base::BindOnce(&CdmFileImpl::WriteDone, weak_factory_.GetWeakPtr())); - - // Create the file writer that runs on the IO thread, and then call Write() - // on the IO thread to write |buffer| into the temporary file. Use of - // base::Unretained() is OK as |file_writer_| is owned by |this|, and if - // |this| is destructed it will destroy |file_writer_| on the IO thread. - file_writer_ = base::SequenceBound<FileWriter>(GetIOThreadTaskRunner({})); - // TODO(dcheng): Migrate this to use Then()? - file_writer_.AsyncCall(&FileWriter::Write) - .WithArgs(file_system_context_, CreateFileSystemURL(temp_file_name_), - std::move(buffer), bytes_to_write, std::move(write_done_cb)); -} - -void CdmFileImpl::WriteDone(bool success) { - DVLOG(3) << __func__ << " file: " << file_name_ - << ", success: " << (success ? "yes" : "no"); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(file_writer_); - DCHECK(write_callback_); - - // We are done with |file_writer_|. - file_writer_.Reset(); - - if (!success) { - std::move(write_callback_).Run(Status::kFailure); - return; - } - - // Now rename |temp_file_name_| to |file_name_|. - storage::FileSystemURL src_file_url = CreateFileSystemURL(temp_file_name_); - storage::FileSystemURL dest_file_url = CreateFileSystemURL(file_name_); - storage::AsyncFileUtil* file_util = file_system_context_->GetAsyncFileUtil( - storage::kFileSystemTypePluginPrivate); - auto operation_context = - std::make_unique<storage::FileSystemOperationContext>( - file_system_context_.get()); - DVLOG(3) << "Renaming " << src_file_url.DebugString() << " to " - << dest_file_url.DebugString(); - file_util->MoveFileLocal( - std::move(operation_context), src_file_url, dest_file_url, - storage::FileSystemOperation::CopyOrMoveOptionSet(), - base::BindOnce(&CdmFileImpl::OnFileRenamed, weak_factory_.GetWeakPtr())); -} - -void CdmFileImpl::OnFileRenamed(base::File::Error move_result) { - DVLOG(3) << __func__ << " file: " << file_name_ - << ", result: " << base::File::ErrorToString(move_result); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(!file_writer_); - DCHECK(write_callback_); - - // Was the rename successful? - if (move_result != base::File::FILE_OK) { - DLOG(WARNING) << "Unable to rename file " << temp_file_name_ << " to " - << file_name_ - << ", error: " << base::File::ErrorToString(move_result); - std::move(write_callback_).Run(Status::kFailure); - return; - } - - // Only report writing time for successful writes. - ReportFileOperationTimeUMA(kWriteTimeUmaName); - std::move(write_callback_).Run(Status::kSuccess); -} - -void CdmFileImpl::DeleteFile() { - DVLOG(3) << __func__; - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(!file_writer_); - DCHECK(write_callback_); - - if (host_) { - DeleteUsingMediaLicenseStorageDelegate(); - return; - } - - storage::FileSystemURL file_url = CreateFileSystemURL(file_name_); - storage::AsyncFileUtil* file_util = file_system_context_->GetAsyncFileUtil( - storage::kFileSystemTypePluginPrivate); - auto operation_context = - std::make_unique<storage::FileSystemOperationContext>( - file_system_context_.get()); - - DVLOG(3) << "Deleting " << file_url.DebugString(); - file_util->DeleteFile( - std::move(operation_context), file_url, - base::BindOnce(&CdmFileImpl::OnFileDeleted, weak_factory_.GetWeakPtr())); -} - -void CdmFileImpl::OnFileDeleted(base::File::Error result) { - DVLOG(3) << __func__ << " file: " << file_name_ - << ", result: " << base::File::ErrorToString(result); - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(!file_writer_); - DCHECK(write_callback_); - - if (result != base::File::FILE_OK && - result != base::File::FILE_ERROR_NOT_FOUND) { - DLOG(WARNING) << "Unable to delete file " << file_name_ - << ", error: " << base::File::ErrorToString(result); - std::move(write_callback_).Run(Status::kFailure); - return; - } - - // Only report time for successful deletes. - ReportFileOperationTimeUMA(kDeleteTimeUmaName); - std::move(write_callback_).Run(Status::kSuccess); -} - -storage::FileSystemURL CdmFileImpl::CreateFileSystemURL( - const std::string& file_name) { - const GURL crack_url = GURL(file_system_root_uri_ + file_name); - // TODO(https://crbug.com/1231162): determine whether EME/CDM/plugin - // private file system will be partitioned and use the appropriate StorageKey - const blink::StorageKey crack_storage_key = - blink::StorageKey(url::Origin::Create(crack_url)); - return file_system_context_->CrackURL(crack_url, crack_storage_key); -} - -bool CdmFileImpl::AcquireFileLock(const std::string& file_name) { - if (host_) { - // The MediaLicenseStorageHost handles file locking and will not call the - // `Initialize()` method which acquires file locks. - NOTREACHED(); - return true; - } - - FileLockKey file_lock_key(origin_, cdm_type_, file_name); - return GetFileLockMap()->AcquireFileLock(file_lock_key); -} - -void CdmFileImpl::ReleaseFileLock(const std::string& file_name) { - if (host_) { - // The MediaLicenseStorageHost handles file locking. - return; - } - - FileLockKey file_lock_key(origin_, cdm_type_, file_name); - GetFileLockMap()->ReleaseFileLock(file_lock_key); + host_->WriteFile( + cdm_type_, file_name_, data, + base::BindOnce(&CdmFileImpl::DidWrite, weak_factory_.GetWeakPtr())); } void CdmFileImpl::ReportFileOperationTimeUMA(const std::string& uma_name) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(host_); + static const char kIncognito[] = ".Incognito"; static const char kNormal[] = ".Normal"; - bool is_incognito = - host_ ? host_->in_memory() : file_system_context_->is_incognito(); + bool is_incognito = host_->in_memory(); // This records the time taken to the base histogram as well as splitting it // out by incognito or normal mode. @@ -802,52 +181,9 @@ time_taken); } -void CdmFileImpl::ReadUsingMediaLicenseStorageDelegate() { +void CdmFileImpl::DidWrite(bool success) { + DVLOG(3) << __func__ << " file: " << file_name_; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - DCHECK(file_locked_); - DCHECK(read_callback_); - DCHECK(host_); - - host_->ReadFile( - cdm_type_, file_name_, - base::BindOnce(&CdmFileImpl::DidReadUsingMediaLicenseStorageDelegate, - weak_factory_.GetWeakPtr())); -} - -void CdmFileImpl::DidReadUsingMediaLicenseStorageDelegate( - absl::optional<std::vector<uint8_t>> data) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(read_callback_); - DCHECK(host_); - - if (!data.has_value()) { - std::move(read_callback_).Run(Status::kFailure, {}); - return; - } - - // Only report reading time for successful reads. - ReportFileOperationTimeUMA(kReadTimeUmaName); - std::move(read_callback_).Run(Status::kSuccess, std::move(data.value())); -} - -void CdmFileImpl::WriteUsingMediaLicenseStorageDelegate( - const std::vector<uint8_t>& data) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); - DCHECK(write_callback_); - DCHECK(host_); - - host_->WriteFile( - cdm_type_, file_name_, data, - base::BindOnce(&CdmFileImpl::DidWriteUsingMediaLicenseStorageDelegate, - weak_factory_.GetWeakPtr())); -} - -void CdmFileImpl::DidWriteUsingMediaLicenseStorageDelegate(bool success) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); DCHECK(write_callback_); DCHECK(host_); @@ -862,21 +198,22 @@ std::move(write_callback_).Run(Status::kSuccess); } -void CdmFileImpl::DeleteUsingMediaLicenseStorageDelegate() { +void CdmFileImpl::DeleteFile() { + DVLOG(3) << __func__; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); DCHECK(write_callback_); DCHECK(host_); + DVLOG(3) << "Deleting " << file_name_; + host_->DeleteFile( cdm_type_, file_name_, - base::BindOnce(&CdmFileImpl::DidDeleteUsingMediaLicenseStorageDelegate, - weak_factory_.GetWeakPtr())); + base::BindOnce(&CdmFileImpl::DidDeleteFile, weak_factory_.GetWeakPtr())); } -void CdmFileImpl::DidDeleteUsingMediaLicenseStorageDelegate(bool success) { +void CdmFileImpl::DidDeleteFile(bool success) { + DVLOG(3) << __func__ << " file: " << file_name_; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK(file_locked_); DCHECK(write_callback_); DCHECK(host_);
diff --git a/content/browser/media/cdm_file_impl.h b/content/browser/media/cdm_file_impl.h index d79faadd..1bdb852 100644 --- a/content/browser/media/cdm_file_impl.h +++ b/content/browser/media/cdm_file_impl.h
@@ -18,19 +18,11 @@ #include "media/cdm/cdm_type.h" #include "media/mojo/mojom/cdm_storage.mojom.h" #include "mojo/public/cpp/bindings/associated_receiver.h" -#include "storage/browser/file_system/async_file_util.h" -#include "url/origin.h" - -namespace storage { -class FileSystemContext; -class FileSystemURL; -} // namespace storage namespace content { class MediaLicenseStorageHost; -// This class implements the media::mojom::CdmFile interface. It uses the same -// mojo pipe as CdmStorageImpl, to enforce message dispatch order. +// This class implements the media::mojom::CdmFile interface. class CdmFileImpl final : public media::mojom::CdmFile { public: // Check whether |name| is valid as a usable file name. Returns true if it is, @@ -46,103 +38,39 @@ const std::string& file_name, mojo::PendingAssociatedReceiver<media::mojom::CdmFile> pending_receiver); - CdmFileImpl(const std::string& file_name, - const url::Origin& origin, - const media::CdmType& cdm_type, - const std::string& file_system_root_uri, - scoped_refptr<storage::FileSystemContext> file_system_context); - CdmFileImpl(const CdmFileImpl&) = delete; CdmFileImpl& operator=(const CdmFileImpl&) = delete; ~CdmFileImpl() final; - // Called to grab a lock on the file. Returns false if the file is in use by - // other CDMs or by the system, true otherwise. Note that |this| should not - // be used anymore if Initialize() fails. - bool Initialize(); - // media::mojom::CdmFile implementation. void Read(ReadCallback callback) final; void Write(const std::vector<uint8_t>& data, WriteCallback callback) final; private: - class FileReader; - class FileWriter; - - // Called when the file is read. If |success| is true, |data| is the contents - // of the file read. - void ReadDone(bool success, std::vector<uint8_t> data); - - // Called in sequence to write the file. |buffer| is the contents to be - // written to the file, |bytes_to_write| is the length. Uses |file_writer_|, - // which is cleared when no longer needed. |write_callback_| will always be - // called with the result. - void OnEnsureTempFileExists(scoped_refptr<net::IOBuffer> buffer, - int bytes_to_write, - base::File::Error result, - bool created); - void OnTempFileIsEmpty(scoped_refptr<net::IOBuffer> buffer, - int bytes_to_write, - base::File::Error result); - void WriteDone(bool success); - void OnFileRenamed(base::File::Error move_result); + void DidRead(absl::optional<std::vector<uint8_t>> data); + void DidWrite(bool success); // Deletes |file_name_| asynchronously. void DeleteFile(); - void OnFileDeleted(base::File::Error result); - - // Returns the FileSystemURL for the specified |file_name|. - storage::FileSystemURL CreateFileSystemURL(const std::string& file_name); - - // Helper methods to lock and unlock a file. - bool AcquireFileLock(const std::string& file_name); - void ReleaseFileLock(const std::string& file_name); + void DidDeleteFile(bool success); // Report operation time to UMA. void ReportFileOperationTimeUMA(const std::string& uma_name); - void ReadUsingMediaLicenseStorageDelegate(); - void DidReadUsingMediaLicenseStorageDelegate( - absl::optional<std::vector<uint8_t>> data); - void WriteUsingMediaLicenseStorageDelegate(const std::vector<uint8_t>& data); - void DidWriteUsingMediaLicenseStorageDelegate(bool success); - void DeleteUsingMediaLicenseStorageDelegate(); - void DidDeleteUsingMediaLicenseStorageDelegate(bool success); - void OnReceiverDisconnect(); - // This receiver is associated with the CdmStorage receiver which creates it. + // This receiver is associated with the MediaLicenseStorageHost which creates + // it. mojo::AssociatedReceiver<media::mojom::CdmFile> receiver_{this}; - // Names of the files this class represents. const std::string file_name_; - const std::string temp_file_name_; - - // TODO(crbug.com/1231162): Remove some of these fields and update this - // comment when we migrate off of the PluginPrivateFileSystem. - // Files are stored in the PluginPrivateFileSystem. The following are needed - // to access files. - const url::Origin origin_; const media::CdmType cdm_type_; - const std::string file_system_root_uri_; - scoped_refptr<storage::FileSystemContext> file_system_context_; - // Keep track of when the original file |file_name_| is locked. - // Initialize() can only be called if false and takes the lock (on success). - // Read() and Write() can only be called if true. - // Note that having a lock on |file_name| implies that |temp_file_name| is - // reserved for use by this object only, and an explicit lock on - // |temp_file_name| is not required. - bool file_locked_ = false; - - // Used when reading the file. |file_reader_| lives on the IO thread. + // Each of these callbacks is only valid while there is an in-progress read + // or write operation, respectively. ReadCallback read_callback_; - base::SequenceBound<FileReader> file_reader_; - - // Used when writing the file. |file_writer_| lives on the IO thread. WriteCallback write_callback_; - base::SequenceBound<FileWriter> file_writer_; // Time when the read or write operation starts. base::TimeTicks start_time_;
diff --git a/content/browser/media/cdm_storage_impl.cc b/content/browser/media/cdm_storage_impl.cc deleted file mode 100644 index 8257981..0000000 --- a/content/browser/media/cdm_storage_impl.cc +++ /dev/null
@@ -1,189 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/media/cdm_storage_impl.h" - -#include <map> -#include <memory> -#include <tuple> -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/logging.h" -#include "content/browser/media/cdm_file_impl.h" -#include "content/public/browser/child_process_security_policy.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/storage_partition.h" -#include "media/cdm/cdm_type.h" -#include "mojo/public/cpp/bindings/associated_remote.h" -#include "mojo/public/cpp/bindings/pending_associated_remote.h" -#include "storage/browser/file_system/file_system_context.h" -#include "storage/browser/file_system/file_system_operation_context.h" -#include "storage/browser/file_system/isolated_context.h" -#include "storage/common/file_system/file_system_types.h" -#include "storage/common/file_system/file_system_util.h" -#include "url/origin.h" - -// Currently this uses the PluginPrivateFileSystem as the previous CDMs ran -// as pepper plugins and we need to be able to access any existing files. -// TODO(crbug.com/1231162): Switch to using a separate file system once CDMs no -// longer run as pepper plugins. - -namespace content { - -// static -void CdmStorageImpl::Create( - RenderFrameHost* render_frame_host, - const media::CdmType& cdm_type, - mojo::PendingReceiver<media::mojom::CdmStorage> receiver) { - DVLOG(3) << __func__; - DCHECK(!render_frame_host->GetLastCommittedOrigin().opaque()) - << "Invalid origin specified for CdmStorageImpl::Create"; - - // Take a reference to the FileSystemContext. - scoped_refptr<storage::FileSystemContext> file_system_context; - StoragePartition* storage_partition = - render_frame_host->GetProcess()->GetStoragePartition(); - if (storage_partition) - file_system_context = storage_partition->GetFileSystemContext(); - - // The created object is bound to (and owned by) |receiver|. - new CdmStorageImpl(render_frame_host, cdm_type, - std::move(file_system_context), std::move(receiver)); -} - -CdmStorageImpl::CdmStorageImpl( - RenderFrameHost* render_frame_host, - const media::CdmType& cdm_type, - scoped_refptr<storage::FileSystemContext> file_system_context, - mojo::PendingReceiver<media::mojom::CdmStorage> receiver) - : DocumentService(render_frame_host, std::move(receiver)), - cdm_type_(cdm_type), - file_system_context_(std::move(file_system_context)), - child_process_id_(render_frame_host->GetProcess()->GetID()) {} - -CdmStorageImpl::~CdmStorageImpl() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); -} - -void CdmStorageImpl::Open(const std::string& file_name, OpenCallback callback) { - DVLOG(3) << __func__ << " file: " << file_name; - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - if (file_name.empty()) { - DVLOG(1) << "No file specified."; - std::move(callback).Run(Status::kFailure, mojo::NullAssociatedRemote()); - return; - } - - // The file system should only be opened once. If it has been attempted and - // failed, we can't create the CdmFile objects. - if (file_system_state_ == FileSystemState::kError) { - std::move(callback).Run(Status::kFailure, mojo::NullAssociatedRemote()); - return; - } - - // If the file system is already open, create and initialize the CdmFileImpl - // object. - if (file_system_state_ == FileSystemState::kOpened) { - CreateCdmFile(file_name, std::move(callback)); - return; - } - - // Save a file name and callback for when the file system is open. If the - // open is already in progress, nothing more to do until the existing - // OpenPluginPrivateFileSystem() call completes. - pending_open_calls_.emplace(pending_open_calls_.end(), file_name, - std::move(callback)); - if (file_system_state_ == FileSystemState::kOpening) - return; - - DCHECK_EQ(FileSystemState::kUnopened, file_system_state_); - file_system_state_ = FileSystemState::kOpening; - - std::string fsid = - storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath( - storage::kFileSystemTypePluginPrivate, - storage::kPluginPrivateRootName, base::FilePath()); - if (!storage::ValidateIsolatedFileSystemId(fsid)) { - DVLOG(1) << "Invalid file system ID."; - OnFileSystemOpened(base::File::FILE_ERROR_NOT_FOUND); - return; - } - - // Grant full access of isolated file system to child process. - ChildProcessSecurityPolicy::GetInstance()->GrantCreateReadWriteFileSystem( - child_process_id_, fsid); - - // Keep track of the URI for this instance of the PluginPrivateFileSystem. - file_system_root_uri_ = storage::GetIsolatedFileSystemRootURIString( - origin().GetURL(), fsid, storage::kPluginPrivateRootName); - - file_system_context_->OpenPluginPrivateFileSystem( - origin(), storage::kFileSystemTypePluginPrivate, fsid, - cdm_type_.legacy_file_system_id, - storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, - base::BindOnce(&CdmStorageImpl::OnFileSystemOpened, - weak_factory_.GetWeakPtr())); -} - -void CdmStorageImpl::OnFileSystemOpened(base::File::Error error) { - DVLOG(3) << __func__; - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK_EQ(FileSystemState::kOpening, file_system_state_); - - if (error != base::File::FILE_OK) { - file_system_state_ = FileSystemState::kError; - // All pending calls will fail. - for (auto& pending : pending_open_calls_) { - std::move(pending.second) - .Run(Status::kFailure, mojo::NullAssociatedRemote()); - } - pending_open_calls_.clear(); - return; - } - - // File system successfully opened, so create the CdmFileImpl object for - // all pending Open() calls. - file_system_state_ = FileSystemState::kOpened; - for (auto& pending : pending_open_calls_) { - CreateCdmFile(pending.first, std::move(pending.second)); - } - pending_open_calls_.clear(); -} - -void CdmStorageImpl::CreateCdmFile(const std::string& file_name, - OpenCallback callback) { - DVLOG(3) << __func__ << " file: " << file_name; - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - DCHECK_EQ(FileSystemState::kOpened, file_system_state_); - - // File system opened successfully, so create an CdmFileImpl object and - // initialize it (which only grabs the lock to prevent any other access to the - // file except through this object). - if (!CdmFileImpl::IsValidName(file_name)) { - std::move(callback).Run(Status::kFailure, mojo::NullAssociatedRemote()); - return; - } - - auto cdm_file_impl = std::make_unique<CdmFileImpl>( - file_name, origin(), cdm_type_, file_system_root_uri_, - file_system_context_); - - if (!cdm_file_impl->Initialize()) { - // Unable to initialize with the file requested. - std::move(callback).Run(Status::kInUse, mojo::NullAssociatedRemote()); - return; - } - - // File was opened successfully, so create the binding and return success. - mojo::PendingAssociatedRemote<media::mojom::CdmFile> cdm_file; - cdm_file_receivers_.Add(std::move(cdm_file_impl), - cdm_file.InitWithNewEndpointAndPassReceiver()); - std::move(callback).Run(Status::kSuccess, std::move(cdm_file)); -} - -} // namespace content
diff --git a/content/browser/media/cdm_storage_impl.h b/content/browser/media/cdm_storage_impl.h deleted file mode 100644 index 8975d5c2..0000000 --- a/content/browser/media/cdm_storage_impl.h +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_MEDIA_CDM_STORAGE_IMPL_H_ -#define CONTENT_BROWSER_MEDIA_CDM_STORAGE_IMPL_H_ - -#include <set> -#include <string> - -#include "base/callback_forward.h" -#include "base/files/file.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "content/common/content_export.h" -#include "content/public/browser/document_service.h" -#include "media/cdm/cdm_type.h" -#include "media/mojo/mojom/cdm_storage.mojom.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/unique_associated_receiver_set.h" - -namespace storage { -class FileSystemContext; -} - -namespace content { -class CdmFileImpl; -class RenderFrameHost; - -// This class implements the media::mojom::CdmStorage using the -// PluginPrivateFileSystem for backwards compatibility with CDMs running -// as a pepper plugin. -class CONTENT_EXPORT CdmStorageImpl final - : public content::DocumentService<media::mojom::CdmStorage> { - public: - // Create a CdmStorageImpl object for |cdm_type| and bind it to |request|. - static void Create(RenderFrameHost* render_frame_host, - const media::CdmType& cdm_type, - mojo::PendingReceiver<media::mojom::CdmStorage> receiver); - - CdmStorageImpl(const CdmStorageImpl&) = delete; - CdmStorageImpl& operator=(const CdmStorageImpl&) = delete; - - // media::mojom::CdmStorage implementation. - void Open(const std::string& file_name, OpenCallback callback) final; - - private: - // TODO(crbug.com/1231162): Consider reimagining this design once we migrate - // off of the PluginPrivateFileSystem. - // File system should only be opened once, so keep track if it has already - // been opened (or is in the process of opening). State is kError if an error - // happens while opening the file system. - enum class FileSystemState { kUnopened, kOpening, kOpened, kError }; - - CdmStorageImpl(RenderFrameHost* render_frame_host, - const media::CdmType& cdm_type, - scoped_refptr<storage::FileSystemContext> file_system_context, - mojo::PendingReceiver<media::mojom::CdmStorage> receiver); - ~CdmStorageImpl() final; - - // Called when the file system is opened. - void OnFileSystemOpened(base::File::Error error); - - // After the file system is opened, called to create a CdmFile object. - void CreateCdmFile(const std::string& file_name, OpenCallback callback); - - // Called after the CdmFileImpl object has opened the file. - void OnCdmFileInitialized(std::unique_ptr<CdmFileImpl> cdm_file_impl, - OpenCallback callback, - bool success); - - // TODO(crbug.com/1231162): Update this comment once we migrate off of the - // PluginPrivateFileSystem. CdmType contains a `legacy_file_system_id` used to - // access the PluginPrivateFileSystem, which will be removed once all data has - // been migrated. - // Files are stored in the PluginPrivateFileSystem, so keep track of the CDM - // file system ID in order to open the files in the correct context. - const media::CdmType cdm_type_; - // TODO(crbug.com/1231162): Remove this once we migrate off of the - // PluginPrivateFileSystem. - scoped_refptr<storage::FileSystemContext> file_system_context_; - - // TODO(crbug.com/1231162): Update this comment and consider removing this - // member once we migrate off of the PluginPrivateFileSystem. - // The PluginPrivateFileSystem only needs to be opened once. - FileSystemState file_system_state_ = FileSystemState::kUnopened; - - // As multiple calls to Open() could happen while the file system is being - // opened asynchronously, keep track of the requests so they can be - // processed once the file system is open. - using PendingOpenData = std::pair<std::string, OpenCallback>; - std::vector<PendingOpenData> pending_open_calls_; - - // TODO(crbug.com/1231162): Remove this once we migrate off of the - // PluginPrivateFileSystem. - // Once the PluginPrivateFileSystem is opened, keep track of the URI that - // refers to it. - std::string file_system_root_uri_; - - // This is the child process that will actually read and write the file(s) - // returned, and it needs permission to access the file(s). - const int child_process_id_; - - // Keep track of all media::mojom::CdmFile receivers, as each CdmFileImpl - // object keeps a reference to |this|. If |this| goes away unexpectedly, - // all remaining CdmFile receivers will be closed. - mojo::UniqueAssociatedReceiverSet<media::mojom::CdmFile> cdm_file_receivers_; - - base::WeakPtrFactory<CdmStorageImpl> weak_factory_{this}; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_MEDIA_CDM_STORAGE_IMPL_H_
diff --git a/content/browser/media/cdm_storage_impl_unittest.cc b/content/browser/media/cdm_storage_impl_unittest.cc deleted file mode 100644 index 9fb62b98..0000000 --- a/content/browser/media/cdm_storage_impl_unittest.cc +++ /dev/null
@@ -1,638 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/media/cdm_storage_impl.h" - -#include <memory> -#include <vector> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/files/file.h" -#include "base/logging.h" -#include "base/test/bind.h" -#include "base/test/test_future.h" -#include "base/test/with_feature_override.h" -#include "content/browser/media/media_license_manager.h" -#include "content/browser/storage_partition_impl.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/storage_partition.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/content_features.h" -#include "content/public/test/navigation_simulator.h" -#include "content/public/test/test_renderer_host.h" -#include "media/cdm/cdm_type.h" -#include "media/mojo/mojom/cdm_storage.mojom.h" -#include "mojo/public/cpp/bindings/associated_remote.h" -#include "mojo/public/cpp/bindings/pending_associated_remote.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/common/storage_key/storage_key.h" -#include "third_party/widevine/cdm/buildflags.h" -#include "url/gurl.h" -#include "url/origin.h" - -#if BUILDFLAG(ENABLE_WIDEVINE) -#include "third_party/widevine/cdm/widevine_cdm_common.h" -#endif // BUILDFLAG(ENABLE_WIDEVINE) - -using media::mojom::CdmFile; -using media::mojom::CdmStorage; - -namespace content { -using CdmFileId = MediaLicenseManager::CdmFileId; -using CdmFileIdAndContents = MediaLicenseManager::CdmFileIdAndContents; - -namespace { - -const media::CdmType kTestCdmType{base::Token{1234, 5678}, "test_file_system"}; -const media::CdmType kDifferentCdmType{base::Token{8765, 4321}, - "different_plugin"}; -const media::CdmType kUnrecognizedCdmType{base::Token{1111, 2222}, "imposter"}; - -const char kTestOrigin[] = "http://www.test.com"; - -const std::vector<MediaLicenseManager::CdmFileIdAndContents> kDefaultFiles{ - {{"file1", kTestCdmType}, {'r', 'a', 'n', 'd'}}, - {{"file2", kTestCdmType}, {'r', 'a', 'n', 'd', 'o'}}, - {{"file3", kTestCdmType}, {'r', 'a', 'n', 'd', 'o', 'm'}}, -}; - -// Helper functions to manipulate RenderFrameHosts. - -void SimulateNavigation(RenderFrameHost** rfh, const GURL& url) { - auto navigation_simulator = - NavigationSimulator::CreateRendererInitiated(url, *rfh); - navigation_simulator->Commit(); - *rfh = navigation_simulator->GetFinalRenderFrameHost(); -} - -} // namespace - -class CdmStorageTest : public base::test::WithFeatureOverride, - public RenderViewHostTestHarness { - public: - CdmStorageTest() - : base::test::WithFeatureOverride(features::kMediaLicenseBackend), - RenderViewHostTestHarness( - content::BrowserTaskEnvironment::REAL_IO_THREAD) {} - - protected: - void SetUp() final { - RenderViewHostTestHarness::SetUp(); - rfh_ = web_contents()->GetPrimaryMainFrame(); - RenderFrameHostTester::For(rfh_)->InitializeRenderFrameIfNeeded(); - SimulateNavigation(&rfh_, GURL(kTestOrigin)); - - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // Create the CdmStorageImpl object. - auto* media_license_manager = - static_cast<StoragePartitionImpl*>(rfh_->GetStoragePartition()) - ->GetMediaLicenseManager(); - DCHECK(media_license_manager); - media_license_manager->OpenCdmStorage( - MediaLicenseManager::BindingContext( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kTestCdmType), - cdm_storage_.BindNewPipeAndPassReceiver()); - } else { - // Create the CdmStorageImpl object. |cdm_storage_| will own the resulting - // object. - CdmStorageImpl::Create(rfh_, kTestCdmType, - cdm_storage_.BindNewPipeAndPassReceiver()); - } - } - - // Open the file |name|. Returns true if the file returned is valid, false - // otherwise. On success |cdm_file| is bound to the CdmFileImpl object. - bool Open(const std::string& name, - mojo::AssociatedRemote<CdmFile>& cdm_file) { - DVLOG(3) << __func__; - - base::test::TestFuture<CdmStorage::Status, - mojo::PendingAssociatedRemote<CdmFile>> - future; - cdm_storage_->Open(name, future.GetCallback()); - - CdmStorage::Status status = future.Get<0>(); - mojo::PendingAssociatedRemote<CdmFile> actual_file = - std::move(std::get<1>(future.Take())); - if (!actual_file) { - DCHECK_NE(status, CdmStorage::Status::kSuccess); - return false; - } - - // Open() returns a mojo::PendingAssociatedRemote<CdmFile>, so bind it to - // the mojo::AssociatedRemote<CdmFileAssociated> provided. - mojo::AssociatedRemote<CdmFile> cdm_file_remote; - cdm_file_remote.Bind(std::move(actual_file)); - cdm_file = std::move(cdm_file_remote); - - return status == CdmStorage::Status::kSuccess; - } - - // Reads the contents of the previously opened |cdm_file|. If successful, - // true is returned and |data| is updated with the contents of the file. - // If unable to read the file, false is returned. - bool Read(CdmFile* cdm_file, std::vector<uint8_t>& data) { - DVLOG(3) << __func__; - - base::test::TestFuture<CdmFile::Status, std::vector<uint8_t>> future; - cdm_file->Read( - future.GetCallback<CdmFile::Status, const std::vector<uint8_t>&>()); - - CdmFile::Status status = future.Get<0>(); - data = future.Get<1>(); - return status == CdmFile::Status::kSuccess; - } - - // Writes |data| to the previously opened |cdm_file|, replacing the contents - // of the file. Returns true if successful, false otherwise. - bool Write(CdmFile* cdm_file, const std::vector<uint8_t>& data) { - DVLOG(3) << __func__; - - base::test::TestFuture<CdmFile::Status> future; - cdm_file->Write(data, future.GetCallback()); - - CdmFile::Status status = future.Get(); - return status == CdmFile::Status::kSuccess; - } - - void WriteFiles(const std::vector<CdmFileIdAndContents>& files) { - // Write some data using the old backend. - for (const auto& file : files) { - mojo::AssociatedRemote<CdmFile> remote; - EXPECT_TRUE(Open(file.file.name, remote)); - ASSERT_TRUE(remote.is_bound()); - EXPECT_TRUE(Write(remote.get(), file.data)); - } - } - - void ReadFiles(const std::vector<CdmFileIdAndContents>& files) { - for (const auto& file : files) { - mojo::AssociatedRemote<CdmFile> remote; - EXPECT_TRUE(Open(file.file.name, remote)); - ASSERT_TRUE(remote.is_bound()); - std::vector<uint8_t> data_read; - EXPECT_TRUE(Read(remote.get(), data_read)); - EXPECT_EQ(file.data, data_read); - } - } - - void ExpectFilesEmpty(const std::vector<CdmFileIdAndContents>& files) { - for (const auto& file : files) { - mojo::AssociatedRemote<CdmFile> remote; - EXPECT_TRUE(Open(file.file.name, remote)); - ASSERT_TRUE(remote.is_bound()); - std::vector<uint8_t> data_read; - EXPECT_TRUE(Read(remote.get(), data_read)); - EXPECT_TRUE(data_read.empty()); - } - } - - void ResetAndBindToOldBackend(const blink::StorageKey& storage_key, - const media::CdmType& cdm_type) { - cdm_storage_.reset(); - - SimulateNavigation(&rfh_, storage_key.origin().GetURL()); - CdmStorageImpl::Create(rfh_, cdm_type, - cdm_storage_.BindNewPipeAndPassReceiver()); - } - - void ResetAndBindToNewBackend(const blink::StorageKey& storage_key, - const media::CdmType& cdm_type) { - cdm_storage_.reset(); - - SimulateNavigation(&rfh_, storage_key.origin().GetURL()); - media_license_manager()->OpenCdmStorage( - MediaLicenseManager::BindingContext(storage_key, cdm_type), - cdm_storage_.BindNewPipeAndPassReceiver()); - } - - MediaLicenseManager* media_license_manager() const { - auto* media_license_manager = - static_cast<StoragePartitionImpl*>(rfh_->GetStoragePartition()) - ->GetMediaLicenseManager(); - DCHECK(media_license_manager); - return media_license_manager; - } - - RenderFrameHost* rfh_ = nullptr; - mojo::Remote<CdmStorage> cdm_storage_; -}; - -// TODO(crbug.com/1231162): Make this a non-parameterized test suite once we no -// longer have to test against both backends. -INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(CdmStorageTest); - -TEST_P(CdmStorageTest, InvalidFileName) { - // Anything other than ASCII letter, digits, and -._ will fail. Add a - // Unicode character to the name. - const char kFileName[] = "openfile\u1234"; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_FALSE(Open(kFileName, cdm_file)); - ASSERT_FALSE(cdm_file.is_bound()); -} - -TEST_P(CdmStorageTest, InvalidFileNameEmpty) { - const char kFileName[] = ""; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_FALSE(Open(kFileName, cdm_file)); - ASSERT_FALSE(cdm_file.is_bound()); -} - -TEST_P(CdmStorageTest, InvalidFileNameStartWithUnderscore) { - const char kFileName[] = "_invalid"; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_FALSE(Open(kFileName, cdm_file)); - ASSERT_FALSE(cdm_file.is_bound()); -} - -TEST_P(CdmStorageTest, InvalidFileNameTooLong) { - // Limit is 256 characters, so try a file name with 257. - const std::string kFileName(257, 'a'); - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_FALSE(Open(kFileName, cdm_file)); - ASSERT_FALSE(cdm_file.is_bound()); -} - -TEST_P(CdmStorageTest, OpenFile) { - const char kFileName[] = "test_file_name"; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_TRUE(Open(kFileName, cdm_file)); - ASSERT_TRUE(cdm_file.is_bound()); -} - -TEST_P(CdmStorageTest, OpenFileLocked) { - const char kFileName[] = "test_file_name"; - mojo::AssociatedRemote<CdmFile> cdm_file1; - EXPECT_TRUE(Open(kFileName, cdm_file1)); - ASSERT_TRUE(cdm_file1.is_bound()); - - // Second attempt on the same file should fail as the file is locked. - mojo::AssociatedRemote<CdmFile> cdm_file2; - EXPECT_FALSE(Open(kFileName, cdm_file2)); - ASSERT_FALSE(cdm_file2.is_bound()); - - // Now close the first file and try again. It should be free now. - cdm_file1.reset(); - - mojo::AssociatedRemote<CdmFile> cdm_file3; - EXPECT_TRUE(Open(kFileName, cdm_file3)); - ASSERT_TRUE(cdm_file3.is_bound()); -} - -TEST_P(CdmStorageTest, MultipleFiles) { - const char kFileName1[] = "file1"; - mojo::AssociatedRemote<CdmFile> cdm_file1; - EXPECT_TRUE(Open(kFileName1, cdm_file1)); - ASSERT_TRUE(cdm_file1.is_bound()); - - const char kFileName2[] = "file2"; - mojo::AssociatedRemote<CdmFile> cdm_file2; - EXPECT_TRUE(Open(kFileName2, cdm_file2)); - ASSERT_TRUE(cdm_file2.is_bound()); - - const char kFileName3[] = "file3"; - mojo::AssociatedRemote<CdmFile> cdm_file3; - EXPECT_TRUE(Open(kFileName3, cdm_file3)); - ASSERT_TRUE(cdm_file3.is_bound()); -} - -TEST_P(CdmStorageTest, WriteThenReadFile) { - const char kFileName[] = "test_file_name"; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_TRUE(Open(kFileName, cdm_file)); - ASSERT_TRUE(cdm_file.is_bound()); - - // Write several bytes and read them back. - std::vector<uint8_t> kTestData = {'r', 'a', 'n', 'd', 'o', 'm'}; - EXPECT_TRUE(Write(cdm_file.get(), kTestData)); - - std::vector<uint8_t> data_read; - EXPECT_TRUE(Read(cdm_file.get(), data_read)); - EXPECT_EQ(kTestData, data_read); -} - -TEST_P(CdmStorageTest, ReadThenWriteEmptyFile) { - const char kFileName[] = "empty_file_name"; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_TRUE(Open(kFileName, cdm_file)); - ASSERT_TRUE(cdm_file.is_bound()); - - // New file should be empty. - std::vector<uint8_t> data_read; - EXPECT_TRUE(Read(cdm_file.get(), data_read)); - EXPECT_EQ(0u, data_read.size()); - - // Write nothing. - EXPECT_TRUE(Write(cdm_file.get(), std::vector<uint8_t>())); - - // Should still be empty. - EXPECT_TRUE(Read(cdm_file.get(), data_read)); - EXPECT_EQ(0u, data_read.size()); -} - -TEST_P(CdmStorageTest, ParallelRead) { - const char kFileName[] = "duplicate_read_file_name"; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_TRUE(Open(kFileName, cdm_file)); - ASSERT_TRUE(cdm_file.is_bound()); - - // Attempts to reads the contents of the previously opened |cdm_file| twice. - // We don't really care about the data, just that 1 read succeeds and the - // other fails. - base::test::TestFuture<CdmFile::Status, std::vector<uint8_t>> future1; - base::test::TestFuture<CdmFile::Status, std::vector<uint8_t>> future2; - - cdm_file->Read( - future1.GetCallback<CdmFile::Status, const std::vector<uint8_t>&>()); - cdm_file->Read( - future2.GetCallback<CdmFile::Status, const std::vector<uint8_t>&>()); - - EXPECT_TRUE(future1.Wait()); - EXPECT_TRUE(future2.Wait()); - - CdmFile::Status status1 = future1.Get<0>(); - CdmFile::Status status2 = future2.Get<0>(); - - // One call should succeed, one should fail. - EXPECT_TRUE((status1 == CdmFile::Status::kSuccess && - status2 == CdmFile::Status::kFailure) || - (status1 == CdmFile::Status::kFailure && - status2 == CdmFile::Status::kSuccess)) - << "status 1: " << status1 << ", status2: " << status2; -} - -TEST_P(CdmStorageTest, ParallelWrite) { - const char kFileName[] = "duplicate_write_file_name"; - mojo::AssociatedRemote<CdmFile> cdm_file; - EXPECT_TRUE(Open(kFileName, cdm_file)); - ASSERT_TRUE(cdm_file.is_bound()); - - // Attempts to write the contents of the previously opened |cdm_file| twice. - // We don't really care about the data, just that 1 write succeeds and the - // other fails. - base::test::TestFuture<CdmFile::Status> future1; - base::test::TestFuture<CdmFile::Status> future2; - - cdm_file->Write({1, 2, 3}, future1.GetCallback()); - cdm_file->Write({4, 5, 6}, future2.GetCallback()); - - EXPECT_TRUE(future1.Wait()); - EXPECT_TRUE(future2.Wait()); - - CdmFile::Status status1 = future1.Get(); - CdmFile::Status status2 = future2.Get(); - - // One call should succeed, one should fail. - EXPECT_TRUE((status1 == CdmFile::Status::kSuccess && - status2 == CdmFile::Status::kFailure) || - (status1 == CdmFile::Status::kFailure && - status2 == CdmFile::Status::kSuccess)) - << "status 1: " << status1 << ", status2: " << status2; -} - -TEST_P(CdmStorageTest, MigrateDataNone) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - - // If there's no data to migrate this should run gracefully and without error. - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); -} - -TEST_P(CdmStorageTest, MigrateDataBasic) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - // Write some data using the old backend. - WriteFiles(kDefaultFiles); - - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); - - // Read data using the new backend. - ReadFiles(kDefaultFiles); -} - -TEST_P(CdmStorageTest, MigrateDataAll) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - // Write some data using the old backend. - WriteFiles(kDefaultFiles); - - // Open a new backend using a different CDM type. The original data should - // still have been migrated. - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kDifferentCdmType); - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); - - // Can't read files from another CDM type. - ExpectFilesEmpty(kDefaultFiles); - - // Files from the original CDM type should exist without another migration. - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - ReadFiles(kDefaultFiles); -} - -TEST_P(CdmStorageTest, MigrateDataPluginDataDeleted) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - // Write some data using the old backend. - WriteFiles(kDefaultFiles); - - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); - - // Read data using the new backend. - ReadFiles(kDefaultFiles); - - ResetAndBindToOldBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - - // Data should have been removed from the old backend. - ExpectFilesEmpty(kDefaultFiles); -} - -TEST_P(CdmStorageTest, MigrateDataMultipleCdmTypes) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - // Write some data using the old backend. - WriteFiles(kDefaultFiles); - - // Write data to another CDM type from the same origin. - const std::vector<MediaLicenseManager::CdmFileIdAndContents> kDifferentFiles{ - {{"other0", kDifferentCdmType}, {'e', 'x', 'a', 'm'}}, - {{"other1", kDifferentCdmType}, {'e', 'x', 'a', 'm', 'p'}}, - {{"other2", kDifferentCdmType}, {'e', 'x', 'a', 'm', 'p', 'l'}}, - {{"other3", kDifferentCdmType}, {'e', 'x', 'a', 'm', 'p', 'l', 'e'}}, - }; - ResetAndBindToOldBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kDifferentCdmType); - WriteFiles(kDifferentFiles); - - // Ensure files from the first CDM type can be read by the new backend. - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); - - ReadFiles(kDefaultFiles); - - // Open storage for the other CDM type. All media licenses should have been - // migrated. - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kDifferentCdmType); - - ReadFiles(kDifferentFiles); -} - -TEST_P(CdmStorageTest, MigrateDataUnrecognizedCdmType) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - // Write some data using the old backend. - WriteFiles(kDefaultFiles); - - // Write data an unrecognized CDM type from the same origin. - const std::vector<CdmFileIdAndContents> kDifferentFiles{ - {{"other1", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o'}}, - {{"other2", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o', 'r'}}, - {{"other3", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o', 'r', 'e'}}, - {{"other4", kUnrecognizedCdmType}, {'i', 'g', 'n', 'o', 'r', 'e', 'd'}}, - }; - ResetAndBindToOldBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kUnrecognizedCdmType); - WriteFiles(kDifferentFiles); - - // Read data from the original CDM type using the new backend. - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); - ReadFiles(kDefaultFiles); - - // Open storage for the other CDM type. Media licenses for the unrecognized - // CDM type should NOT have been migrated. - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kUnrecognizedCdmType); - ExpectFilesEmpty(kDifferentFiles); - - // Despite not being migrated, the data should still have been removed from - // the old backend. - ResetAndBindToOldBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - ExpectFilesEmpty(kDefaultFiles); -} - -TEST_P(CdmStorageTest, MigrateDataMultipleOrigins) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - // Write some data using the old backend. - WriteFiles(kDefaultFiles); - - cdm_storage_.reset(); - - const blink::StorageKey kDifferentStorageKey = - blink::StorageKey::CreateFromStringForTesting("http://www.example.com"); - ResetAndBindToOldBackend(kDifferentStorageKey, kTestCdmType); - - const std::vector<CdmFileIdAndContents> kDifferentFiles{ - {{"dif_file1", kTestCdmType}, {'e', 'x', 'a', 'm'}}, - {{"dif_file2", kTestCdmType}, {'e', 'x', 'a', 'm', 'p'}}, - {{"dif_file3", kTestCdmType}, {'e', 'x', 'a', 'm', 'p', 'l'}}, - {{"dif_file4", kTestCdmType}, {'e', 'x', 'a', 'm', 'p', 'l', 'e'}}, - }; - WriteFiles(kDifferentFiles); - - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), kTestCdmType); - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); - - ReadFiles(kDefaultFiles); - - cdm_storage_.reset(); - - // Open storage for the other origin. All media licenses should have been - // migrated. - ResetAndBindToNewBackend(kDifferentStorageKey, kTestCdmType); - - ReadFiles(kDifferentFiles); -} - -#if BUILDFLAG(ENABLE_WIDEVINE) -TEST_P(CdmStorageTest, MigrateDataWidevine) { - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // No data to migrate if the flag is enabled. - return; - } - - ResetAndBindToOldBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kWidevineCdmType); - - const std::vector<CdmFileIdAndContents> kWidevineFiles{ - {{"wide_file1", kWidevineCdmType}, {'e', 'x', 'a', 'm'}}, - {{"wide_file2", kWidevineCdmType}, {'e', 'x', 'a', 'm', 'p'}}, - {{"wide_file3", kWidevineCdmType}, {'e', 'x', 'a', 'm', 'p', 'l'}}, - {{"wide_file4", kWidevineCdmType}, {'e', 'x', 'a', 'm', 'p', 'l', 'e'}}, - }; - - // Write some Widevine data using the old backend. - WriteFiles(kWidevineFiles); - - ResetAndBindToNewBackend( - blink::StorageKey::CreateFromStringForTesting(kTestOrigin), - kWidevineCdmType); - base::RunLoop loop; - media_license_manager()->MigrateMediaLicensesForTesting(loop.QuitClosure()); - loop.Run(); - - // Read data using the new backend. - ReadFiles(kWidevineFiles); -} -#endif // BUILDFLAG(ENABLE_WIDEVINE) - -} // namespace content
diff --git a/content/browser/media/media_interface_proxy.cc b/content/browser/media/media_interface_proxy.cc index 37ae0e3..fff49eb 100644 --- a/content/browser/media/media_interface_proxy.cc +++ b/content/browser/media/media_interface_proxy.cc
@@ -49,7 +49,6 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" -#include "content/browser/media/cdm_storage_impl.h" #include "content/browser/media/media_license_manager.h" #include "media/base/key_system_names.h" #include "media/mojo/mojom/cdm_service.mojom.h" @@ -169,24 +168,17 @@ if (cdm_type_.id.is_zero()) return; - // TODO(crbug.com/1231162): Make more test suites templated to test both - // backends. - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - MediaLicenseManager* media_license_manager = - static_cast<StoragePartitionImpl*>( - render_frame_host_->GetStoragePartition()) - ->GetMediaLicenseManager(); - DCHECK(media_license_manager); + MediaLicenseManager* media_license_manager = + static_cast<StoragePartitionImpl*>( + render_frame_host_->GetStoragePartition()) + ->GetMediaLicenseManager(); + DCHECK(media_license_manager); - auto storage_key = - static_cast<RenderFrameHostImpl*>(render_frame_host_)->storage_key(); - media_license_manager->OpenCdmStorage( - MediaLicenseManager::BindingContext(storage_key, cdm_type_), - std::move(receiver)); - } else { - CdmStorageImpl::Create(render_frame_host_, cdm_type_, - std::move(receiver)); - } + auto storage_key = + static_cast<RenderFrameHostImpl*>(render_frame_host_)->storage_key(); + media_license_manager->OpenCdmStorage( + MediaLicenseManager::BindingContext(storage_key, cdm_type_), + std::move(receiver)); #endif }
diff --git a/content/browser/media/media_license_manager.cc b/content/browser/media/media_license_manager.cc index 27b37d21..edeabe0 100644 --- a/content/browser/media/media_license_manager.cc +++ b/content/browser/media/media_license_manager.cc
@@ -8,56 +8,29 @@ #include <utility> #include <vector> -#include "base/barrier_callback.h" -#include "base/barrier_closure.h" #include "base/bind.h" #include "base/callback_forward.h" #include "base/containers/flat_map.h" -#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" -#include "base/notreached.h" #include "base/sequence_checker.h" -#include "base/strings/string_number_conversions.h" -#include "base/task/bind_post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" -#include "base/threading/sequence_bound.h" #include "base/threading/sequenced_task_runner_handle.h" #include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "components/services/storage/public/cpp/buckets/constants.h" #include "components/services/storage/public/cpp/constants.h" #include "content/browser/media/media_license_database.h" #include "content/browser/media/media_license_storage_host.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/common/cdm_info.h" -#include "content/public/common/content_features.h" #include "media/cdm/cdm_type.h" -#include "media/media_buildflags.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" #include "sql/database.h" -#include "storage/browser/file_system/file_stream_reader.h" -#include "storage/browser/file_system/file_system_context.h" -#include "storage/browser/file_system/file_system_url.h" -#include "storage/browser/file_system/isolated_context.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h" -#include "third_party/widevine/cdm/buildflags.h" // nogncheck #include "url/origin.h" -#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) -#include "content/public/common/cdm_info.h" -#endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) - -#if BUILDFLAG(ENABLE_WIDEVINE) -#include "third_party/widevine/cdm/widevine_cdm_common.h" // nogncheck -#endif // BUILDFLAG(ENABLE_WIDEVINE) - namespace content { namespace { @@ -80,189 +53,6 @@ }); } -// TODO(crbug.com/1231162): Yes, this code is ugly. It is only in place while we -// migrate to the new media license backend. -absl::optional<media::CdmType> GetCdmTypeFromFileSystemId( - const std::string& file_system_id) { - if (file_system_id == "application_x-ppapi-clearkey-cdm") { - // `kClearKeyCdmType` from media/cdm/cdm_paths.h - return media::CdmType{ - base::Token{0x3a2e0fadde4bd1b7ull, 0xcb90df3e240d1694ull}, - "application_x-ppapi-clearkey-cdm"}; - } -#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) - else if (file_system_id == "application_chromeos-cdm-factory-daemon") { - return kChromeOsCdmType; - } -#endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA) - -#if BUILDFLAG(ENABLE_WIDEVINE) - else if (file_system_id == "application_x-ppapi-widevine-cdm") { - return kWidevineCdmType; - } -#if BUILDFLAG(IS_WIN) - else if (file_system_id == "") { - return kMediaFoundationWidevineCdmType; - } -#endif // BUILDFLAG(IS_WIN) -#endif // BUILDFLAG(ENABLE_WIDEVINE) - else if (file_system_id == "test_file_system") { - // Used in migration tests in cdm_storage_impl_unittest.cc - return media::CdmType{base::Token{1234, 5678}, "test_file_system"}; - } else if (file_system_id == "different_plugin") { - // Used in migration tests in cdm_storage_impl_unittest.cc - return media::CdmType{base::Token{8765, 4321}, "different_plugin"}; - } - - // `file_system_id` doesn't match a known CDM type. - return absl::nullopt; -} - -base::flat_map<blink::StorageKey, std::vector<MediaLicenseManager::CdmFileId>> -GetMediaLicensesOnFileTaskRunner( - scoped_refptr<storage::FileSystemContext> context) { - DCHECK(context); - - storage::PluginPrivateFileSystemBackend* plugin_private_backend = - context->plugin_private_backend(); - - auto storage_keys = - plugin_private_backend->GetStorageKeysForTypeOnFileTaskRunner( - storage::kFileSystemTypePluginPrivate); - - if (storage_keys.empty()) - return {}; - - return base::MakeFlatMap<blink::StorageKey, - std::vector<MediaLicenseManager::CdmFileId>>( - storage_keys, /*comp=*/{}, - [&plugin_private_backend, &context](const auto& storage_key) { - std::vector<MediaLicenseManager::CdmFileId> cdm_files_for_storage_key; - auto cdm_files = plugin_private_backend - ->GetMediaLicenseFilesForOriginOnFileTaskRunner( - context.get(), storage_key.origin()); - for (const auto& cdm_file : cdm_files) { - auto maybe_cdm_type = - GetCdmTypeFromFileSystemId(cdm_file.legacy_file_system_id); - if (!maybe_cdm_type.has_value()) - continue; - - cdm_files_for_storage_key.emplace_back(cdm_file.name, - maybe_cdm_type.value()); - } - - return std::make_pair(storage_key, - std::move(cdm_files_for_storage_key)); - }); -} - -void DidReadFiles( - scoped_refptr<storage::FileSystemContext> context, - base::OnceCallback< - void(std::vector<MediaLicenseManager::CdmFileIdAndContents>)> callback, - const std::vector<MediaLicenseManager::CdmFileIdAndContents>& files) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // Don't bother migrating empty files. - std::vector<MediaLicenseManager::CdmFileIdAndContents> files_to_migrate; - base::ranges::for_each( - files, - [&files_to_migrate](MediaLicenseManager::CdmFileIdAndContents file) { - if (!file.data.empty()) - files_to_migrate.emplace_back(std::move(file)); - }); - - std::move(callback).Run(std::move(files_to_migrate)); -} - -void DidReadFile( - std::unique_ptr<storage::FileStreamReader> /*reader*/, - scoped_refptr<net::IOBufferWithSize> buffer, - MediaLicenseManager::CdmFileId file, - base::OnceCallback<void(MediaLicenseManager::CdmFileIdAndContents)> - callback, - int result) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (result != buffer->size()) { - std::move(callback).Run({file, {}}); - return; - } - - std::vector<uint8_t> data(buffer->data(), buffer->data() + buffer->size()); - std::move(callback).Run({file, std::move(data)}); -} - -void DidGetLength( - std::unique_ptr<storage::FileStreamReader> reader, - MediaLicenseManager::CdmFileId file, - base::OnceCallback<void(MediaLicenseManager::CdmFileIdAndContents)> - callback, - int64_t result) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // No need to Read() from `reader` if the file length is 0. - if (result <= 0) { - std::move(callback).Run({file, {}}); - return; - } - - auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(result); - auto* reader_ptr = reader.get(); - reader_ptr->Read(buffer.get(), buffer->size(), - base::BindOnce(&DidReadFile, std::move(reader), buffer, - std::move(file), std::move(callback))); -} - -void ReadFiles( - scoped_refptr<storage::FileSystemContext> context, - std::string file_system_root_uri, - std::vector<MediaLicenseManager::CdmFileId> files, - base::OnceCallback<void( - std::vector<MediaLicenseManager::CdmFileIdAndContents>)> callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - DCHECK(!files.empty()); - - // Kick off a number of read file operations and collect the results. - // Bind `context` to keep it alive while reading files. - auto* context_ptr = context.get(); - auto barrier = - base::BarrierCallback<MediaLicenseManager::CdmFileIdAndContents>( - files.size(), base::BindOnce(&DidReadFiles, std::move(context), - std::move(callback))); - - for (const auto& file : files) { - // Adapted from CdmFileImpl::CreateFileSystemURL(). - const GURL crack_url = GURL(file_system_root_uri + file.name); - const blink::StorageKey crack_storage_key = - blink::StorageKey(url::Origin::Create(crack_url)); - auto url = context_ptr->CrackURL(crack_url, crack_storage_key); - auto reader = context_ptr->CreateFileStreamReader( - url, 0, storage::kMaximumLength, base::Time()); - if (!reader) { - barrier.Run({file, {}}); - continue; - } - auto* reader_ptr = reader.get(); - auto result = reader_ptr->GetLength(base::BindOnce( - &DidGetLength, std::move(reader), std::move(file), barrier)); - // The GetLength() call is expected to run asynchronously. - DCHECK_EQ(result, net::ERR_IO_PENDING); - } -} - -void WriteFilesOnDbThread( - std::vector<MediaLicenseManager::CdmFileIdAndContents> files, - const base::FilePath& database_path) { - auto db = std::make_unique<MediaLicenseDatabase>(database_path); - - for (auto& file : files) { - db->OpenFile(file.file.cdm_type, file.file.name); - db->WriteFile(file.file.cdm_type, file.file.name, file.data); - } -} - } // namespace MediaLicenseManager::CdmFileId::CdmFileId(const std::string& name, @@ -280,12 +70,10 @@ MediaLicenseManager::CdmFileIdAndContents::~CdmFileIdAndContents() = default; MediaLicenseManager::MediaLicenseManager( - scoped_refptr<storage::FileSystemContext> file_system_context, bool in_memory, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) - : file_system_context_(std::move(file_system_context)), - db_runner_(CreateDatabaseTaskRunner()), + : db_runner_(CreateDatabaseTaskRunner()), in_memory_(in_memory), special_storage_policy_(std::move(special_storage_policy)), quota_manager_proxy_(std::move(quota_manager_proxy)), @@ -300,203 +88,10 @@ storage::QuotaClientType::kMediaLicense, {blink::mojom::StorageType::kTemporary}); } - - if (base::FeatureList::IsEnabled(features::kMediaLicenseBackend)) { - // Ensure the file system context is kept alive until we're done migrating - // media license data from the Plugin Private File System to this backend. - MigrateMediaLicenses( - base::BindOnce([](scoped_refptr<storage::FileSystemContext>) {}, - base::WrapRefCounted(context().get()))); - } } MediaLicenseManager::~MediaLicenseManager() = default; -void MediaLicenseManager::MigrateMediaLicenses(base::OnceClosure done_closure) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - DCHECK(plugin_private_data_migration_closure_.is_null()); - plugin_private_data_migration_closure_ = std::move(done_closure); - - context()->default_file_task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, base::BindOnce(&GetMediaLicensesOnFileTaskRunner, context()), - base::BindOnce(&MediaLicenseManager::DidGetMediaLicenses, - weak_factory_.GetWeakPtr())); -} - -void MediaLicenseManager::DidGetMediaLicenses( - base::flat_map<blink::StorageKey, std::vector<CdmFileId>> files_map) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!plugin_private_data_migration_closure_.is_null()); - - if (files_map.empty()) { - DidMigrateMediaLicenses(); - return; - } - - // Kick off migration process for each storage key. - base::RepeatingClosure barrier = base::BarrierClosure( - files_map.size(), - base::BindPostTask( - base::SequencedTaskRunnerHandle::Get(), - base::BindOnce(&MediaLicenseManager::DidMigrateMediaLicenses, - weak_factory_.GetWeakPtr()))); - - for (auto& storage_key_and_files : files_map) { - std::vector<CdmFileId> files = std::move(storage_key_and_files.second); - if (files.empty()) { - barrier.Run(); - continue; - } - const blink::StorageKey& storage_key = storage_key_and_files.first; - quota_manager_proxy()->UpdateOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(storage_key), - base::SequencedTaskRunnerHandle::Get(), - base::BindOnce(&MediaLicenseManager::OpenPluginFileSystemsForStorageKey, - weak_factory_.GetWeakPtr(), storage_key, - std::move(files), barrier)); - } -} - -void MediaLicenseManager::OpenPluginFileSystemsForStorageKey( - const blink::StorageKey& storage_key, - std::vector<CdmFileId> files, - base::OnceClosure done_migrating_storage_key_closure, - storage::QuotaErrorOr<storage::BucketInfo> result) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!plugin_private_data_migration_closure_.is_null()); - - if (!result.ok()) { - std::move(done_migrating_storage_key_closure).Run(); - return; - } - - // Organize files by plugin name. - base::flat_map<std::string, std::vector<CdmFileId>> files_by_plugin_name; - for (auto& file : files) { - files_by_plugin_name[file.cdm_type.legacy_file_system_id].emplace_back( - std::move(file)); - } - - auto barrier = base::BarrierCallback<std::vector<CdmFileIdAndContents>>( - files_by_plugin_name.size(), - base::BindOnce(&MediaLicenseManager::DidReadFilesForStorageKey, - weak_factory_.GetWeakPtr(), storage_key, - result->ToBucketLocator(), - std::move(done_migrating_storage_key_closure))); - - for (const auto& [plugin_name, files] : files_by_plugin_name) { - // Register and open a file system for this plugin type. - std::string fsid = - storage::IsolatedContext::GetInstance() - ->RegisterFileSystemForVirtualPath( - storage::kFileSystemTypePluginPrivate, - storage::kPluginPrivateRootName, base::FilePath()); - DCHECK(storage::ValidateIsolatedFileSystemId(fsid)); - - std::string file_system_root_uri = - storage::GetIsolatedFileSystemRootURIString( - storage_key.origin().GetURL(), fsid, - storage::kPluginPrivateRootName); - - context()->OpenPluginPrivateFileSystem( - storage_key.origin(), - storage::FileSystemType::kFileSystemTypePluginPrivate, fsid, - plugin_name, - storage::OpenFileSystemMode::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT, - base::BindOnce(&MediaLicenseManager::DidOpenPluginFileSystem, - weak_factory_.GetWeakPtr(), storage_key, - std::move(files), std::move(file_system_root_uri), - barrier)); - } -} - -void MediaLicenseManager::DidOpenPluginFileSystem( - const blink::StorageKey& storage_key, - std::vector<CdmFileId> files, - std::string file_system_root_uri, - base::OnceCallback<void(std::vector<CdmFileIdAndContents>)> callback, - base::File::Error error) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!plugin_private_data_migration_closure_.is_null()); - - if (error != base::File::FILE_OK) { - std::move(callback).Run({}); - return; - } - - auto wrapped_callback = base::BindPostTask( - base::SequencedTaskRunnerHandle::Get(), std::move(callback)); - GetIOThreadTaskRunner({})->PostTask( - FROM_HERE, - base::BindOnce(&ReadFiles, context(), std::move(file_system_root_uri), - std::move(files), std::move(wrapped_callback))); -} - -void MediaLicenseManager::DidReadFilesForStorageKey( - const blink::StorageKey& storage_key, - const storage::BucketLocator& bucket_locator, - base::OnceClosure done_migrating_storage_key_closure, - std::vector<std::vector<CdmFileIdAndContents>> collected_files) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!plugin_private_data_migration_closure_.is_null()); - - // Flatten collected files into one vector. - std::vector<CdmFileIdAndContents> files; - for (auto& file_list : collected_files) { - for (auto& file : file_list) { - // Empty files should have been stripped out. - DCHECK(!file.data.empty()); - files.emplace_back(std::move(file)); - } - } - - if (files.empty()) { - std::move(done_migrating_storage_key_closure).Run(); - return; - } - - db_runner()->PostTaskAndReply( - FROM_HERE, - base::BindOnce(&WriteFilesOnDbThread, std::move(files), - GetDatabasePath(bucket_locator)), - std::move(done_migrating_storage_key_closure)); -} - -void MediaLicenseManager::DidMigrateMediaLicenses() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!plugin_private_data_migration_closure_.is_null()); - - // Delete %profile/File System/Plugins since media license data is the only - // thing stored in the Plugin Private File System. - auto plugin_path = context()->plugin_private_backend()->base_path(); - - context()->default_file_task_runner()->PostTaskAndReply( - FROM_HERE, - base::BindOnce(base::IgnoreResult(&base::DeletePathRecursively), - plugin_path), - base::BindOnce(&MediaLicenseManager::DidClearPluginPrivateData, - weak_factory_.GetWeakPtr())); -} - -void MediaLicenseManager::DidClearPluginPrivateData() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!plugin_private_data_migration_closure_.is_null()); - - std::move(plugin_private_data_migration_closure_).Run(); - - // Now that data has been migrated, kick off binding the pending receivers. - for (const auto& receivers : pending_receivers_) { - const auto& storage_key = receivers.first; - // Get the default bucket for `storage_key`. - quota_manager_proxy()->UpdateOrCreateBucket( - storage::BucketInitParams::ForDefaultBucket(storage_key), - base::SequencedTaskRunnerHandle::Get(), - base::BindOnce(&MediaLicenseManager::DidGetBucket, - weak_factory_.GetWeakPtr(), storage_key)); - } -} - void MediaLicenseManager::OpenCdmStorage( const BindingContext& binding_context, mojo::PendingReceiver<media::mojom::CdmStorage> receiver) { @@ -512,12 +107,9 @@ auto& receiver_list = pending_receivers_[storage_key]; receiver_list.emplace_back(binding_context, std::move(receiver)); - if (receiver_list.size() > 1 || - !plugin_private_data_migration_closure_.is_null()) { + if (receiver_list.size() > 1) { // If a pending receiver for this storage key already existed, there is - // an in-flight `UpdateOrCreateBucket()` call for this storage key. If we're - // in the process of migrating data from the plugin private file system, - // pending receivers will be handled in `DidClearPluginPrivateData()`. + // an in-flight `UpdateOrCreateBucket()` call for this storage key. return; } @@ -535,15 +127,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto it = pending_receivers_.find(storage_key); - if (it == pending_receivers_.end()) { - // No receivers to bind. - // TODO(crbug.com/1231162): This case can only be hit - // when the migration code is kicked off after `OpenCdmStorage()` has - // already been called, since `OpenCdmStorage()` will not call - // `UpdateOrCreateBucket()` while there is an in-progress migration. Change - // this to a DCHECK once the migration logic is removed. - return; - } + DCHECK(it != pending_receivers_.end()); auto receivers_list = std::move(it->second); pending_receivers_.erase(it);
diff --git a/content/browser/media/media_license_manager.h b/content/browser/media/media_license_manager.h index bde6635..e90e90a 100644 --- a/content/browser/media/media_license_manager.h +++ b/content/browser/media/media_license_manager.h
@@ -19,7 +19,6 @@ #include "content/common/content_export.h" #include "media/cdm/cdm_type.h" #include "media/mojo/mojom/cdm_storage.mojom.h" -#include "storage/browser/file_system/file_system_context.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -72,7 +71,6 @@ }; MediaLicenseManager( - scoped_refptr<storage::FileSystemContext> file_system_context, bool in_memory, scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy, scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy); @@ -98,10 +96,6 @@ MediaLicenseStorageHost* host, base::PassKey<MediaLicenseStorageHost> pass_key); - void MigrateMediaLicensesForTesting(base::OnceClosure done_closure) { - MigrateMediaLicenses(std::move(done_closure)); - } - const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return quota_manager_proxy_; @@ -117,11 +111,6 @@ return in_memory_; } - const scoped_refptr<storage::FileSystemContext>& context() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return file_system_context_; - } - private: void DidGetBucket(const blink::StorageKey& storage_key, storage::QuotaErrorOr<storage::BucketInfo> result); @@ -130,37 +119,8 @@ storage::mojom::QuotaClient::DeleteBucketDataCallback callback, bool success); - // TODO(crbug.com/1231162): The following methods are used to migrate from the - // old backend to the new backend. Remove once the migration is complete. - void MigrateMediaLicenses(base::OnceClosure done_closure); - void DidGetMediaLicenses( - base::flat_map<blink::StorageKey, std::vector<CdmFileId>> files); - void OpenPluginFileSystemsForStorageKey( - const blink::StorageKey& storage_key, - std::vector<CdmFileId> files, - base::OnceClosure done_migrating_storage_key_closure, - storage::QuotaErrorOr<storage::BucketInfo> result); - void DidOpenPluginFileSystem( - const blink::StorageKey& storage_key, - std::vector<CdmFileId> files, - std::string file_system_root_uri, - base::OnceCallback<void(std::vector<CdmFileIdAndContents>)> callback, - base::File::Error result); - void DidReadFilesForStorageKey( - const blink::StorageKey& storage_key, - const storage::BucketLocator& bucket_locator, - base::OnceClosure done_migrating_storage_key_closure, - std::vector<std::vector<CdmFileIdAndContents>> collected_files); - void DidMigrateMediaLicenses(); - void DidClearPluginPrivateData(); - SEQUENCE_CHECKER(sequence_checker_); - // TODO(crbug.com/1231162): These members are only used to help migrate from - // the old backend to the new backend. Remove once the migration is complete. - const scoped_refptr<storage::FileSystemContext> file_system_context_; - base::OnceClosure plugin_private_data_migration_closure_; - // Task runner which all database operations are routed through. const scoped_refptr<base::SequencedTaskRunner> db_runner_;
diff --git a/content/browser/media/media_license_manager_unittest.cc b/content/browser/media/media_license_manager_unittest.cc index 8d58184..b16e1f9 100644 --- a/content/browser/media/media_license_manager_unittest.cc +++ b/content/browser/media/media_license_manager_unittest.cc
@@ -11,9 +11,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_refptr.h" -#include "base/strings/strcat.h" #include "base/strings/string_piece_forward.h" -#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "base/token.h" @@ -21,7 +19,6 @@ #include "components/services/storage/public/cpp/constants.h" #include "content/browser/media/media_license_quota_client.h" #include "content/public/browser/storage_partition.h" -#include "content/public/common/content_features.h" #include "media/cdm/cdm_type.h" #include "media/mojo/mojom/cdm_storage.mojom-forward.h" #include "mojo/public/cpp/bindings/associated_remote.h" @@ -44,22 +41,20 @@ class MediaLicenseManagerTest : public testing::Test { public: - MediaLicenseManagerTest() : feature_list_(features::kMediaLicenseBackend) {} + MediaLicenseManagerTest() : in_memory_(false) {} + explicit MediaLicenseManagerTest(bool in_memory) : in_memory_(in_memory) {} void SetUp() override { ASSERT_TRUE(profile_path_.CreateUniqueTempDir()); - ASSERT_TRUE(file_system_context_path_.CreateUniqueTempDir()); quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>( - /*is_incognito=*/false, profile_path_.GetPath(), + in_memory_, in_memory_ ? base::FilePath() : profile_path_.GetPath(), base::ThreadTaskRunnerHandle::Get().get(), /*special storage policy=*/nullptr); quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>( static_cast<storage::MockQuotaManager*>(quota_manager_.get()), base::ThreadTaskRunnerHandle::Get()); - file_system_context_ = storage::CreateFileSystemContextForTesting( - /*quota_manager_proxy=*/nullptr, file_system_context_path_.GetPath()); manager_ = std::make_unique<MediaLicenseManager>( - file_system_context_, file_system_context_->is_incognito(), + in_memory_, /*special storage policy=*/nullptr, quota_manager_proxy_); } @@ -129,16 +124,14 @@ } protected: + const bool in_memory_; + scoped_refptr<storage::MockQuotaManager> quota_manager_; scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; - scoped_refptr<storage::FileSystemContext> file_system_context_; - - base::test::ScopedFeatureList feature_list_; // This must be above MediaLicenseManager, to ensure that no file is accessed // when the temporary directory is deleted. base::ScopedTempDir profile_path_; - base::ScopedTempDir file_system_context_path_; base::test::TaskEnvironment task_environment_; std::unique_ptr<MediaLicenseManager> manager_; @@ -184,6 +177,9 @@ // not. EXPECT_FALSE(base::PathExists(database_file)); EXPECT_TRUE(base::DirectoryExists(database_file.DirName())); + + // Confirm that the file is now empty. + ExpectFileContents(cdm_file, ""); } TEST_F(MediaLicenseManagerTest, DeleteBucketDataClosedStorage) { @@ -273,6 +269,9 @@ EXPECT_FALSE(base::PathExists(database_file)); EXPECT_TRUE(base::DirectoryExists(database_file.DirName())); + // Confirm that the file is now empty. + ExpectFileContents(cdm_file, ""); + // Write some more data. This should succeed. Write(cdm_file, kTestData); @@ -306,27 +305,9 @@ } class MediaLicenseManagerIncognitoTest : public MediaLicenseManagerTest { - void SetUp() override { - // Still create this dir so the teardown will confirm it remains empty (on - // Windows, at least). - ASSERT_TRUE(profile_path_.CreateUniqueTempDir()); - ASSERT_TRUE(file_system_context_path_.CreateUniqueTempDir()); - - quota_manager_ = base::MakeRefCounted<storage::MockQuotaManager>( - /*is_incognito=*/true, /*profile_path=*/base::FilePath(), - base::ThreadTaskRunnerHandle::Get().get(), - /*special storage policy=*/nullptr); - quota_manager_proxy_ = base::MakeRefCounted<storage::MockQuotaManagerProxy>( - static_cast<storage::MockQuotaManager*>(quota_manager_.get()), - base::ThreadTaskRunnerHandle::Get()); - file_system_context_ = storage::CreateIncognitoFileSystemContextForTesting( - base::ThreadTaskRunnerHandle::Get(), - base::ThreadTaskRunnerHandle::Get(), /*quota_manager_proxy=*/nullptr, - file_system_context_path_.GetPath()); - manager_ = std::make_unique<MediaLicenseManager>( - file_system_context_, file_system_context_->is_incognito(), - /*special storage policy=*/nullptr, quota_manager_proxy_); - } + public: + MediaLicenseManagerIncognitoTest() + : MediaLicenseManagerTest(/*in_memory=*/true) {} }; TEST_F(MediaLicenseManagerIncognitoTest, DeleteBucketData) {
diff --git a/content/browser/media/media_license_storage_host_unittest.cc b/content/browser/media/media_license_storage_host_unittest.cc new file mode 100644 index 0000000..0653512 --- /dev/null +++ b/content/browser/media/media_license_storage_host_unittest.cc
@@ -0,0 +1,345 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <vector> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file.h" +#include "base/logging.h" +#include "base/test/bind.h" +#include "base/test/test_future.h" +#include "content/browser/media/media_license_manager.h" +#include "content/browser/storage_partition_impl.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/navigation_simulator.h" +#include "content/public/test/test_renderer_host.h" +#include "media/cdm/cdm_type.h" +#include "media/mojo/mojom/cdm_storage.mojom.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "mojo/public/cpp/bindings/pending_associated_remote.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" +#include "url/gurl.h" + +using media::mojom::CdmFile; +using media::mojom::CdmStorage; + +namespace content { +using CdmFileId = MediaLicenseManager::CdmFileId; +using CdmFileIdAndContents = MediaLicenseManager::CdmFileIdAndContents; + +namespace { + +const media::CdmType kTestCdmType{base::Token{1234, 5678}, "test_file_system"}; + +const char kTestOrigin[] = "http://www.test.com"; + +// Helper functions to manipulate RenderFrameHosts. + +void SimulateNavigation(RenderFrameHost** rfh, const GURL& url) { + auto navigation_simulator = + NavigationSimulator::CreateRendererInitiated(url, *rfh); + navigation_simulator->Commit(); + *rfh = navigation_simulator->GetFinalRenderFrameHost(); +} + +} // namespace + +class CdmStorageTest : public RenderViewHostTestHarness { + public: + CdmStorageTest() + : RenderViewHostTestHarness( + content::BrowserTaskEnvironment::REAL_IO_THREAD) {} + + protected: + void SetUp() final { + RenderViewHostTestHarness::SetUp(); + rfh_ = web_contents()->GetPrimaryMainFrame(); + RenderFrameHostTester::For(rfh_)->InitializeRenderFrameIfNeeded(); + SimulateNavigation(&rfh_, GURL(kTestOrigin)); + + auto* media_license_manager = + static_cast<StoragePartitionImpl*>(rfh_->GetStoragePartition()) + ->GetMediaLicenseManager(); + DCHECK(media_license_manager); + media_license_manager->OpenCdmStorage( + MediaLicenseManager::BindingContext( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin), + kTestCdmType), + cdm_storage_.BindNewPipeAndPassReceiver()); + } + + // Open the file |name|. Returns true if the file returned is valid, false + // otherwise. On success |cdm_file| is bound to the CdmFileImpl object. + bool Open(const std::string& name, + mojo::AssociatedRemote<CdmFile>& cdm_file) { + DVLOG(3) << __func__; + + base::test::TestFuture<CdmStorage::Status, + mojo::PendingAssociatedRemote<CdmFile>> + future; + cdm_storage_->Open(name, future.GetCallback()); + + CdmStorage::Status status = future.Get<0>(); + mojo::PendingAssociatedRemote<CdmFile> actual_file = + std::move(std::get<1>(future.Take())); + if (!actual_file) { + DCHECK_NE(status, CdmStorage::Status::kSuccess); + return false; + } + + // Open() returns a mojo::PendingAssociatedRemote<CdmFile>, so bind it to + // the mojo::AssociatedRemote<CdmFileAssociated> provided. + mojo::AssociatedRemote<CdmFile> cdm_file_remote; + cdm_file_remote.Bind(std::move(actual_file)); + cdm_file = std::move(cdm_file_remote); + + return status == CdmStorage::Status::kSuccess; + } + + // Reads the contents of the previously opened |cdm_file|. If successful, + // true is returned and |data| is updated with the contents of the file. + // If unable to read the file, false is returned. + bool Read(CdmFile* cdm_file, std::vector<uint8_t>& data) { + DVLOG(3) << __func__; + + base::test::TestFuture<CdmFile::Status, std::vector<uint8_t>> future; + cdm_file->Read( + future.GetCallback<CdmFile::Status, const std::vector<uint8_t>&>()); + + CdmFile::Status status = future.Get<0>(); + data = future.Get<1>(); + return status == CdmFile::Status::kSuccess; + } + + // Writes |data| to the previously opened |cdm_file|, replacing the contents + // of the file. Returns true if successful, false otherwise. + bool Write(CdmFile* cdm_file, const std::vector<uint8_t>& data) { + DVLOG(3) << __func__; + + base::test::TestFuture<CdmFile::Status> future; + cdm_file->Write(data, future.GetCallback()); + + CdmFile::Status status = future.Get(); + return status == CdmFile::Status::kSuccess; + } + + void WriteFiles(const std::vector<CdmFileIdAndContents>& files) { + // Write some data using the old backend. + for (const auto& file : files) { + mojo::AssociatedRemote<CdmFile> remote; + EXPECT_TRUE(Open(file.file.name, remote)); + ASSERT_TRUE(remote.is_bound()); + EXPECT_TRUE(Write(remote.get(), file.data)); + } + } + + void ReadFiles(const std::vector<CdmFileIdAndContents>& files) { + for (const auto& file : files) { + mojo::AssociatedRemote<CdmFile> remote; + EXPECT_TRUE(Open(file.file.name, remote)); + ASSERT_TRUE(remote.is_bound()); + std::vector<uint8_t> data_read; + EXPECT_TRUE(Read(remote.get(), data_read)); + EXPECT_EQ(file.data, data_read); + } + } + + void ExpectFilesEmpty(const std::vector<CdmFileIdAndContents>& files) { + for (const auto& file : files) { + mojo::AssociatedRemote<CdmFile> remote; + EXPECT_TRUE(Open(file.file.name, remote)); + ASSERT_TRUE(remote.is_bound()); + std::vector<uint8_t> data_read; + EXPECT_TRUE(Read(remote.get(), data_read)); + EXPECT_TRUE(data_read.empty()); + } + } + + MediaLicenseManager* media_license_manager() const { + auto* media_license_manager = + static_cast<StoragePartitionImpl*>(rfh_->GetStoragePartition()) + ->GetMediaLicenseManager(); + DCHECK(media_license_manager); + return media_license_manager; + } + + RenderFrameHost* rfh_ = nullptr; + mojo::Remote<CdmStorage> cdm_storage_; +}; + +TEST_F(CdmStorageTest, InvalidFileName) { + // Anything other than ASCII letter, digits, and -._ will fail. Add a + // Unicode character to the name. + const char kFileName[] = "openfile\u1234"; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_FALSE(Open(kFileName, cdm_file)); + ASSERT_FALSE(cdm_file.is_bound()); +} + +TEST_F(CdmStorageTest, InvalidFileNameEmpty) { + const char kFileName[] = ""; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_FALSE(Open(kFileName, cdm_file)); + ASSERT_FALSE(cdm_file.is_bound()); +} + +TEST_F(CdmStorageTest, InvalidFileNameStartWithUnderscore) { + const char kFileName[] = "_invalid"; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_FALSE(Open(kFileName, cdm_file)); + ASSERT_FALSE(cdm_file.is_bound()); +} + +TEST_F(CdmStorageTest, InvalidFileNameTooLong) { + // Limit is 256 characters, so try a file name with 257. + const std::string kFileName(257, 'a'); + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_FALSE(Open(kFileName, cdm_file)); + ASSERT_FALSE(cdm_file.is_bound()); +} + +TEST_F(CdmStorageTest, OpenFile) { + const char kFileName[] = "test_file_name"; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_TRUE(Open(kFileName, cdm_file)); + ASSERT_TRUE(cdm_file.is_bound()); +} + +TEST_F(CdmStorageTest, OpenFileLocked) { + const char kFileName[] = "test_file_name"; + mojo::AssociatedRemote<CdmFile> cdm_file1; + EXPECT_TRUE(Open(kFileName, cdm_file1)); + ASSERT_TRUE(cdm_file1.is_bound()); + + // Second attempt on the same file should fail as the file is locked. + mojo::AssociatedRemote<CdmFile> cdm_file2; + EXPECT_FALSE(Open(kFileName, cdm_file2)); + ASSERT_FALSE(cdm_file2.is_bound()); + + // Now close the first file and try again. It should be free now. + cdm_file1.reset(); + + mojo::AssociatedRemote<CdmFile> cdm_file3; + EXPECT_TRUE(Open(kFileName, cdm_file3)); + ASSERT_TRUE(cdm_file3.is_bound()); +} + +TEST_F(CdmStorageTest, MultipleFiles) { + const char kFileName1[] = "file1"; + mojo::AssociatedRemote<CdmFile> cdm_file1; + EXPECT_TRUE(Open(kFileName1, cdm_file1)); + ASSERT_TRUE(cdm_file1.is_bound()); + + const char kFileName2[] = "file2"; + mojo::AssociatedRemote<CdmFile> cdm_file2; + EXPECT_TRUE(Open(kFileName2, cdm_file2)); + ASSERT_TRUE(cdm_file2.is_bound()); + + const char kFileName3[] = "file3"; + mojo::AssociatedRemote<CdmFile> cdm_file3; + EXPECT_TRUE(Open(kFileName3, cdm_file3)); + ASSERT_TRUE(cdm_file3.is_bound()); +} + +TEST_F(CdmStorageTest, WriteThenReadFile) { + const char kFileName[] = "test_file_name"; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_TRUE(Open(kFileName, cdm_file)); + ASSERT_TRUE(cdm_file.is_bound()); + + // Write several bytes and read them back. + std::vector<uint8_t> kTestData = {'r', 'a', 'n', 'd', 'o', 'm'}; + EXPECT_TRUE(Write(cdm_file.get(), kTestData)); + + std::vector<uint8_t> data_read; + EXPECT_TRUE(Read(cdm_file.get(), data_read)); + EXPECT_EQ(kTestData, data_read); +} + +TEST_F(CdmStorageTest, ReadThenWriteEmptyFile) { + const char kFileName[] = "empty_file_name"; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_TRUE(Open(kFileName, cdm_file)); + ASSERT_TRUE(cdm_file.is_bound()); + + // New file should be empty. + std::vector<uint8_t> data_read; + EXPECT_TRUE(Read(cdm_file.get(), data_read)); + EXPECT_EQ(0u, data_read.size()); + + // Write nothing. + EXPECT_TRUE(Write(cdm_file.get(), std::vector<uint8_t>())); + + // Should still be empty. + EXPECT_TRUE(Read(cdm_file.get(), data_read)); + EXPECT_EQ(0u, data_read.size()); +} + +TEST_F(CdmStorageTest, ParallelRead) { + const char kFileName[] = "duplicate_read_file_name"; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_TRUE(Open(kFileName, cdm_file)); + ASSERT_TRUE(cdm_file.is_bound()); + + // Attempts to reads the contents of the previously opened |cdm_file| twice. + // We don't really care about the data, just that 1 read succeeds and the + // other fails. + base::test::TestFuture<CdmFile::Status, std::vector<uint8_t>> future1; + base::test::TestFuture<CdmFile::Status, std::vector<uint8_t>> future2; + + cdm_file->Read( + future1.GetCallback<CdmFile::Status, const std::vector<uint8_t>&>()); + cdm_file->Read( + future2.GetCallback<CdmFile::Status, const std::vector<uint8_t>&>()); + + EXPECT_TRUE(future1.Wait()); + EXPECT_TRUE(future2.Wait()); + + CdmFile::Status status1 = future1.Get<0>(); + CdmFile::Status status2 = future2.Get<0>(); + + // One call should succeed, one should fail. + EXPECT_TRUE((status1 == CdmFile::Status::kSuccess && + status2 == CdmFile::Status::kFailure) || + (status1 == CdmFile::Status::kFailure && + status2 == CdmFile::Status::kSuccess)) + << "status 1: " << status1 << ", status2: " << status2; +} + +TEST_F(CdmStorageTest, ParallelWrite) { + const char kFileName[] = "duplicate_write_file_name"; + mojo::AssociatedRemote<CdmFile> cdm_file; + EXPECT_TRUE(Open(kFileName, cdm_file)); + ASSERT_TRUE(cdm_file.is_bound()); + + // Attempts to write the contents of the previously opened |cdm_file| twice. + // We don't really care about the data, just that 1 write succeeds and the + // other fails. + base::test::TestFuture<CdmFile::Status> future1; + base::test::TestFuture<CdmFile::Status> future2; + + cdm_file->Write({1, 2, 3}, future1.GetCallback()); + cdm_file->Write({4, 5, 6}, future2.GetCallback()); + + EXPECT_TRUE(future1.Wait()); + EXPECT_TRUE(future2.Wait()); + + CdmFile::Status status1 = future1.Get(); + CdmFile::Status status2 = future2.Get(); + + // One call should succeed, one should fail. + EXPECT_TRUE((status1 == CdmFile::Status::kSuccess && + status2 == CdmFile::Status::kFailure) || + (status1 == CdmFile::Status::kFailure && + status2 == CdmFile::Status::kSuccess)) + << "status 1: " << status1 << ", status2: " << status2; +} + +} // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index cf7d850..6f0950e8 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3239,6 +3239,7 @@ switches::kEnableWebGLDeveloperExtensions, switches::kEnableWebGLDraftExtensions, switches::kEnableWebGLImageChromium, + switches::kEnableWebGPUDeveloperFeatures, switches::kFileUrlPathAlias, switches::kForceDeviceScaleFactor, switches::kForceDisplayColorProfile,
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index a34ad787..287f44b 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -1361,8 +1361,8 @@ #if BUILDFLAG(ENABLE_LIBRARY_CDMS) media_license_manager_ = std::make_unique<MediaLicenseManager>( - filesystem_context_, is_in_memory(), - browser_context_->GetSpecialStoragePolicy(), quota_manager_proxy); + is_in_memory(), browser_context_->GetSpecialStoragePolicy(), + quota_manager_proxy); #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) if (base::FeatureList::IsEnabled(blink::features::kSharedStorageAPI)) {
diff --git a/content/browser/webauth/client_data_json.cc b/content/browser/webauth/client_data_json.cc index 9c3e329b..c65d369b 100644 --- a/content/browser/webauth/client_data_json.cc +++ b/content/browser/webauth/client_data_json.cc
@@ -30,12 +30,11 @@ ret.push_back('"'); const char* const in_bytes = in.data(); - // ICU uses |int32_t| for lengths. - const int32_t length = base::checked_cast<int32_t>(in.size()); - int32_t offset = 0; + const size_t length = in.size(); + size_t offset = 0; while (offset < length) { - const int32_t prior_offset = offset; + const size_t prior_offset = offset; // Input strings must be valid UTF-8. base_icu::UChar32 codepoint; CHECK(base::ReadUnicodeCharacter(in_bytes, length, &offset, &codepoint));
diff --git a/content/child/dwrite_font_proxy/font_fallback_win.cc b/content/child/dwrite_font_proxy/font_fallback_win.cc index 4435749..de6d056 100644 --- a/content/child/dwrite_font_proxy/font_fallback_win.cc +++ b/content/child/dwrite_font_proxy/font_fallback_win.cc
@@ -97,10 +97,13 @@ locale = locale ? locale : L""; + size_t mapped_length_size_t = *mapped_length; if (GetCachedFont(text_chunk, base_family_name, locale, base_weight, - base_style, base_stretch, mapped_font, mapped_length)) { + base_style, base_stretch, mapped_font, + &mapped_length_size_t)) { DCHECK(*mapped_font); - DCHECK_GT(*mapped_length, 0u); + DCHECK_GT(mapped_length_size_t, 0u); + *mapped_length = base::checked_cast<UINT32>(mapped_length_size_t); LogFallbackResult(SUCCESS_CACHE); return S_OK; } @@ -172,7 +175,7 @@ DWRITE_FONT_STYLE base_style, DWRITE_FONT_STRETCH base_stretch, IDWriteFont** font, - uint32_t* mapped_length) { + size_t* mapped_length) { base::AutoLock guard(lock_); std::map<std::wstring, std::list<mswr::ComPtr<IDWriteFontFamily>>>::iterator it = fallback_family_cache_.find(MakeCacheKey(base_family_name, locale)); @@ -197,9 +200,9 @@ // different from |mapped_length| because ReadUnicodeCharacter can advance // |character_index| even if the character cannot be mapped (invalid // surrogate pair or font does not contain a matching glyph). - int32_t character_index = 0; - uint32_t length = 0; // How much of the text can actually be mapped. - while (static_cast<uint32_t>(character_index) < text.length()) { + size_t character_index = 0; + size_t length = 0; // How much of the text can actually be mapped. + while (character_index < text.length()) { BOOL exists = false; base_icu::UChar32 character = 0; if (!base::ReadUnicodeCharacter(text.c_str(), text.length(),
diff --git a/content/child/dwrite_font_proxy/font_fallback_win.h b/content/child/dwrite_font_proxy/font_fallback_win.h index f3778a13..6bc0230 100644 --- a/content/child/dwrite_font_proxy/font_fallback_win.h +++ b/content/child/dwrite_font_proxy/font_fallback_win.h
@@ -65,7 +65,7 @@ DWRITE_FONT_STYLE base_style, DWRITE_FONT_STRETCH base_stretch, IDWriteFont** mapped_font, - uint32_t* mapped_length) LOCKS_EXCLUDED(lock_); + size_t* mapped_length) LOCKS_EXCLUDED(lock_); void AddCachedFamily(Microsoft::WRL::ComPtr<IDWriteFontFamily> family, const wchar_t* base_family_name,
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index d8046d3..0b4c6c1 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -476,6 +476,8 @@ {wrf::EnableWebGLDraftExtensions, switches::kEnableWebGLDraftExtensions, true}, {wrf::EnableWebGPU, switches::kEnableUnsafeWebGPU, true}, + {wrf::EnableWebGPUDeveloperFeatures, + switches::kEnableWebGPUDeveloperFeatures, true}, {wrf::EnableDirectSockets, switches::kIsolatedAppOrigins, true}, }; for (const auto& mapping : switchToFeatureMapping) {
diff --git a/content/content_resources.grd b/content/content_resources.grd index 1a9f01e..21d50c1 100644 --- a/content/content_resources.grd +++ b/content/content_resources.grd
@@ -41,7 +41,7 @@ </if> <include name="IDR_UI_WINDOW_OPEN_DISPOSITION_MOJO_WEBUI_JS" file="${root_gen_dir}/mojom-webui/ui/base/mojom/window_open_disposition.mojom-webui.js" resource_path="mojo/ui/base/mojom/window_open_disposition.mojom-webui.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_UKM_INTERNALS_HTML" file="../components/ukm/debug/ukm_internals.html" type="BINDATA" /> - <include name="IDR_UKM_INTERNALS_JS" file="../components/ukm/debug/ukm_internals.js" preprocess="true" type="BINDATA" /> + <include name="IDR_UKM_INTERNALS_JS" file="${root_gen_dir}/components/ukm/debug/tsc/ukm_internals.js" use_base_dir="false" resource_path="ukm_internals.js" type="BINDATA" /> <include name="IDR_UKM_INTERNALS_CSS" file="../components/ukm/debug/ukm_internals.css" type="BINDATA" /> <if expr="chromeos_ash"> <include name="IDR_UNGUESSABLE_TOKEN_MOJO_HTML" file="${root_gen_dir}/mojo/public/mojom/base/unguessable_token.mojom.html" resource_path="mojo/mojo/public/mojom/base/unguessable_token.mojom.html" use_base_dir="false" type="BINDATA" />
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 155aba4e..fa5914f 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -553,11 +553,6 @@ #endif }; -// Use a custom backend to store media licenses in lieu of the -// Plugin Private File System. -const base::Feature kMediaLicenseBackend{"MediaLicenseBackend", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Allow cross-context transfer of MediaStreamTracks. const base::Feature kMediaStreamTrackTransfer{ "MediaStreamTrackTransfer", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 9663e85..163f6c0 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -145,7 +145,6 @@ }; CONTENT_EXPORT extern const base::FeatureParam<MBIMode> kMBIModeParam; CONTENT_EXPORT extern const base::Feature kMediaDevicesSystemMonitorCache; -CONTENT_EXPORT extern const base::Feature kMediaLicenseBackend; CONTENT_EXPORT extern const base::Feature kMediaStreamTrackTransfer; CONTENT_EXPORT extern const base::Feature kMojoDedicatedThread; CONTENT_EXPORT extern const base::Feature kMojoVideoCapture;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 78e1f80..86d4ad4 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -2791,9 +2791,9 @@ if (enable_library_cdms) { sources += [ - "../browser/media/cdm_storage_impl_unittest.cc", "../browser/media/key_system_support_impl_unittest.cc", "../browser/media/media_license_manager_unittest.cc", + "../browser/media/media_license_storage_host_unittest.cc", ] }
diff --git a/docs/ozone_overview.md b/docs/ozone_overview.md index 378dfdd..169e57bb 100644 --- a/docs/ozone_overview.md +++ b/docs/ozone_overview.md
@@ -354,6 +354,12 @@ Note: traditional TTYs are not the ideal browsing experience.<br/>  +### drm +Ash-chrome client implementation. + +### flatland / scenic +For fuchsia. + ## Communication There is a public mailing list:
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc index 542137d..2a2569b 100644 --- a/extensions/browser/updater/extension_downloader.cc +++ b/extensions/browser/updater/extension_downloader.cc
@@ -187,24 +187,23 @@ UpdateDetails::~UpdateDetails() = default; -ExtensionDownloader::ExtensionFetch::ExtensionFetch() - : credentials(CREDENTIALS_NONE) {} - ExtensionDownloader::ExtensionFetch::ExtensionFetch( - const std::string& id, + ExtensionDownloaderTask task, const GURL& url, const std::string& package_hash, const std::string& version, const std::set<int>& request_ids, const DownloadFetchPriority fetch_priority) - : id(id), + : id(task.id), url(url), package_hash(package_hash), version(version), request_ids(request_ids), fetch_priority(fetch_priority), credentials(CREDENTIALS_NONE), - oauth2_attempt_count(0) {} + oauth2_attempt_count(0) { + associated_tasks.emplace_back(std::move(task)); +} ExtensionDownloader::ExtensionFetch::~ExtensionFetch() = default; @@ -654,15 +653,16 @@ /*version not fetched*/ base::Version(), /*manifest_fetch_failed*/ true); if (cached_crx_path) { + const ExtensionId id = task.id; delegate_->OnExtensionDownloadStageChanged( - task.id, ExtensionDownloaderDelegate::Stage::FINISHED); + id, ExtensionDownloaderDelegate::Stage::FINISHED); auto extension_fetch_data(std::make_unique<ExtensionFetch>( - task.id, fetch_data->base_url(), /*hash not fetched*/ "", + std::move(task), fetch_data->base_url(), /*hash not fetched*/ "", /*version not fetched*/ "", fetch_data->request_ids(), fetch_data->fetch_priority())); NotifyDelegateDownloadFinished(std::move(extension_fetch_data), true, cached_crx_path.value(), false); - extensions_fetched_from_cache.insert(task.id); + extensions_fetched_from_cache.insert(id); } else { tasks_left.emplace_back(std::move(task)); } @@ -809,7 +809,7 @@ // which returns tasks back via its output arguments. DetermineUpdates(fetch_data->TakeAssociatedTasks(), *results, &to_update, &failures); - for (const auto& update : to_update) { + for (auto& update : to_update) { const std::string& extension_id = update.first.id; GURL crx_url = update.second->crx_url; @@ -820,7 +820,7 @@ } FetchUpdatedExtension( std::make_unique<ExtensionFetch>( - extension_id, crx_url, update.second->package_hash, + std::move(update.first), crx_url, update.second->package_hash, update.second->version, fetch_data->request_ids(), fetch_data->fetch_priority()), update.second->info); @@ -1090,6 +1090,10 @@ if (iter->id == fetch_data->id || iter->url == fetch_data->url) { delegate_->OnExtensionDownloadStageChanged( fetch_data->id, ExtensionDownloaderDelegate::Stage::QUEUED_FOR_CRX); + iter->associated_tasks.insert( + iter->associated_tasks.end(), + std::make_move_iterator(fetch_data->associated_tasks.begin()), + std::make_move_iterator(fetch_data->associated_tasks.end())); iter->request_ids.insert(fetch_data->request_ids.begin(), fetch_data->request_ids.end()); return; // already scheduled @@ -1100,6 +1104,10 @@ extensions_queue_.active_request()->url == fetch_data->url) { delegate_->OnExtensionDownloadStageChanged( fetch_data->id, ExtensionDownloaderDelegate::Stage::DOWNLOADING_CRX); + extensions_queue_.active_request()->associated_tasks.insert( + extensions_queue_.active_request()->associated_tasks.end(), + std::make_move_iterator(fetch_data->associated_tasks.begin()), + std::make_move_iterator(fetch_data->associated_tasks.end())); extensions_queue_.active_request()->request_ids.insert( fetch_data->request_ids.begin(), fetch_data->request_ids.end()); return;
diff --git a/extensions/browser/updater/extension_downloader.h b/extensions/browser/updater/extension_downloader.h index b77c260..10c9973 100644 --- a/extensions/browser/updater/extension_downloader.h +++ b/extensions/browser/updater/extension_downloader.h
@@ -176,8 +176,7 @@ // We need to keep track of some information associated with a url // when doing a fetch. struct ExtensionFetch { - ExtensionFetch(); - ExtensionFetch(const std::string& id, + ExtensionFetch(ExtensionDownloaderTask task, const GURL& url, const std::string& package_hash, const std::string& version, @@ -189,8 +188,11 @@ GURL url; std::string package_hash; base::Version version; + // TODO(b:235968596): Remove `request_ids` from this struct, as we have all + // data needed in the associated tasks. std::set<int> request_ids; DownloadFetchPriority fetch_priority; + std::vector<ExtensionDownloaderTask> associated_tasks; enum CredentialsMode { CREDENTIALS_NONE = 0,
diff --git a/fuchsia/base/BUILD.gn b/fuchsia/base/BUILD.gn index fd9d342..c43860b1 100644 --- a/fuchsia/base/BUILD.gn +++ b/fuchsia/base/BUILD.gn
@@ -13,6 +13,7 @@ ":cr_fuchsia_base_unittests__exec", "./test/*", "//chromecast/internal/*", + "//fuchsia_web/common/test/*", "//fuchsia_web/runners/*", "//fuchsia_web/webengine/*", ] @@ -31,16 +32,6 @@ ] } -static_library("run_all_integration_tests") { - testonly = true - visibility = [ - "//fuchsia_web/runners/*", - "//fuchsia_web/webengine/*", - ] - sources = [ "run_all_integration_tests.cc" ] - deps = [ "//base/test:test_support" ] -} - # Unit-tests for all //fuchsia/base utilities. test("cr_fuchsia_base_unittests") { sources = [ "agent_impl_unittest.cc" ] @@ -50,7 +41,7 @@ "//base:testfidl", "//base/test:run_all_unittests", "//base/test:test_support", - "//fuchsia/base/test:test_support", + "//fuchsia_web/common/test:test_support", "//testing/gmock", "//testing/gtest", "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp",
diff --git a/fuchsia/base/agent_impl_unittest.cc b/fuchsia/base/agent_impl_unittest.cc index 8577678..a2419cf 100644 --- a/fuchsia/base/agent_impl_unittest.cc +++ b/fuchsia/base/agent_impl_unittest.cc
@@ -11,7 +11,7 @@ #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "base/testfidl/cpp/fidl.h" -#include "fuchsia/base/test/fit_adapter.h" +#include "fuchsia_web/common/test/fit_adapter.h" #include "testing/gtest/include/gtest/gtest.h" namespace cr_fuchsia {
diff --git a/fuchsia/base/test/BUILD.gn b/fuchsia_web/common/test/BUILD.gn similarity index 65% rename from fuchsia/base/test/BUILD.gn rename to fuchsia_web/common/test/BUILD.gn index b988c2b9..468d7b8 100644 --- a/fuchsia/base/test/BUILD.gn +++ b/fuchsia_web/common/test/BUILD.gn
@@ -4,17 +4,18 @@ assert(is_fuchsia) +# Only allow use by WebEngine-related Fuchsia targets. +visibility = [ "//fuchsia_web/*" ] + source_set("test_support") { testonly = true + + # TODO(crbug.com/1081525): Remove once directory is deleted. + visibility += [ "//fuchsia/base/*" ] sources = [ - "context_provider_test_connector.cc", - "context_provider_test_connector.h", - "fake_component_context.cc", - "fake_component_context.h", "fit_adapter.h", "frame_test_util.cc", "frame_test_util.h", - "scoped_connection_checker.h", "test_devtools_list_fetcher.cc", "test_devtools_list_fetcher.h", "test_navigation_listener.cc", @@ -34,3 +35,14 @@ "//url", ] } + +static_library("run_all_integration_tests") { + testonly = true + visibility = [] + visibility += [ + "//fuchsia_web/runners/*", + "//fuchsia_web/webengine/*", + ] + sources = [ "run_all_integration_tests.cc" ] + deps = [ "//base/test:test_support" ] +}
diff --git a/fuchsia/base/test/DEPS b/fuchsia_web/common/test/DEPS similarity index 100% rename from fuchsia/base/test/DEPS rename to fuchsia_web/common/test/DEPS
diff --git a/fuchsia/base/test/fit_adapter.h b/fuchsia_web/common/test/fit_adapter.h similarity index 84% rename from fuchsia/base/test/fit_adapter.h rename to fuchsia_web/common/test/fit_adapter.h index f2e453f..3675f19 100644 --- a/fuchsia/base/test/fit_adapter.h +++ b/fuchsia_web/common/test/fit_adapter.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_FIT_ADAPTER_H_ -#define FUCHSIA_BASE_TEST_FIT_ADAPTER_H_ +#ifndef FUCHSIA_WEB_COMMON_TEST_FIT_ADAPTER_H_ +#define FUCHSIA_WEB_COMMON_TEST_FIT_ADAPTER_H_ #include <lib/fit/function.h> @@ -24,4 +24,4 @@ } // namespace cr_fuchsia -#endif // FUCHSIA_BASE_TEST_FIT_ADAPTER_H_ +#endif // FUCHSIA_WEB_COMMON_TEST_FIT_ADAPTER_H_
diff --git a/fuchsia/base/test/frame_test_util.cc b/fuchsia_web/common/test/frame_test_util.cc similarity index 93% rename from fuchsia/base/test/frame_test_util.cc rename to fuchsia_web/common/test/frame_test_util.cc index 2e934b6..b592f81 100644 --- a/fuchsia/base/test/frame_test_util.cc +++ b/fuchsia_web/common/test/frame_test_util.cc
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "fuchsia/base/test/frame_test_util.h" +#include "fuchsia_web/common/test/frame_test_util.h" #include "base/fuchsia/mem_buffer_util.h" #include "base/json/json_reader.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/test/test_future.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" namespace cr_fuchsia {
diff --git a/fuchsia/base/test/frame_test_util.h b/fuchsia_web/common/test/frame_test_util.h similarity index 91% rename from fuchsia/base/test/frame_test_util.h rename to fuchsia_web/common/test/frame_test_util.h index 6f6074a5..e270025 100644 --- a/fuchsia/base/test/frame_test_util.h +++ b/fuchsia_web/common/test/frame_test_util.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_FRAME_TEST_UTIL_H_ -#define FUCHSIA_BASE_TEST_FRAME_TEST_UTIL_H_ +#ifndef FUCHSIA_WEB_COMMON_TEST_FRAME_TEST_UTIL_H_ +#define FUCHSIA_WEB_COMMON_TEST_FRAME_TEST_UTIL_H_ #include <fuchsia/mem/cpp/fidl.h> #include <fuchsia/web/cpp/fidl.h> @@ -44,4 +44,4 @@ } // namespace cr_fuchsia -#endif // FUCHSIA_BASE_TEST_FRAME_TEST_UTIL_H_ +#endif // FUCHSIA_WEB_COMMON_TEST_FRAME_TEST_UTIL_H_
diff --git a/fuchsia/base/run_all_integration_tests.cc b/fuchsia_web/common/test/run_all_integration_tests.cc similarity index 100% rename from fuchsia/base/run_all_integration_tests.cc rename to fuchsia_web/common/test/run_all_integration_tests.cc
diff --git a/fuchsia/base/test/test_devtools_list_fetcher.cc b/fuchsia_web/common/test/test_devtools_list_fetcher.cc similarity index 95% rename from fuchsia/base/test/test_devtools_list_fetcher.cc rename to fuchsia_web/common/test/test_devtools_list_fetcher.cc index 03c1a7a..edaf97d 100644 --- a/fuchsia/base/test/test_devtools_list_fetcher.cc +++ b/fuchsia_web/common/test/test_devtools_list_fetcher.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "fuchsia/base/test/test_devtools_list_fetcher.h" +#include "fuchsia_web/common/test/test_devtools_list_fetcher.h" #include "base/callback.h" #include "base/json/json_reader.h"
diff --git a/fuchsia/base/test/test_devtools_list_fetcher.h b/fuchsia_web/common/test/test_devtools_list_fetcher.h similarity index 69% rename from fuchsia/base/test/test_devtools_list_fetcher.h rename to fuchsia_web/common/test/test_devtools_list_fetcher.h index 8bde0b9a..d908e36 100644 --- a/fuchsia/base/test/test_devtools_list_fetcher.h +++ b/fuchsia_web/common/test/test_devtools_list_fetcher.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_TEST_DEVTOOLS_LIST_FETCHER_H_ -#define FUCHSIA_BASE_TEST_TEST_DEVTOOLS_LIST_FETCHER_H_ +#ifndef FUCHSIA_WEB_COMMON_TEST_TEST_DEVTOOLS_LIST_FETCHER_H_ +#define FUCHSIA_WEB_COMMON_TEST_TEST_DEVTOOLS_LIST_FETCHER_H_ #include "base/values.h" @@ -15,4 +15,4 @@ } // namespace cr_fuchsia -#endif // FUCHSIA_BASE_TEST_TEST_DEVTOOLS_LIST_FETCHER_H_ +#endif // FUCHSIA_WEB_COMMON_TEST_TEST_DEVTOOLS_LIST_FETCHER_H_
diff --git a/fuchsia/base/test/test_navigation_listener.cc b/fuchsia_web/common/test/test_navigation_listener.cc similarity index 98% rename from fuchsia/base/test/test_navigation_listener.cc rename to fuchsia_web/common/test/test_navigation_listener.cc index b68c5b87..0ffcae9 100644 --- a/fuchsia/base/test/test_navigation_listener.cc +++ b/fuchsia_web/common/test/test_navigation_listener.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include <string> #include <utility>
diff --git a/fuchsia/base/test/test_navigation_listener.h b/fuchsia_web/common/test/test_navigation_listener.h similarity index 95% rename from fuchsia/base/test/test_navigation_listener.h rename to fuchsia_web/common/test/test_navigation_listener.h index beeb4ab7..bd41aae 100644 --- a/fuchsia/base/test/test_navigation_listener.h +++ b/fuchsia_web/common/test/test_navigation_listener.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_TEST_NAVIGATION_LISTENER_H_ -#define FUCHSIA_BASE_TEST_TEST_NAVIGATION_LISTENER_H_ +#ifndef FUCHSIA_WEB_COMMON_TEST_TEST_NAVIGATION_LISTENER_H_ +#define FUCHSIA_WEB_COMMON_TEST_TEST_NAVIGATION_LISTENER_H_ #include <fuchsia/web/cpp/fidl.h> #include <string> @@ -103,4 +103,4 @@ } // namespace cr_fuchsia -#endif // FUCHSIA_BASE_TEST_TEST_NAVIGATION_LISTENER_H_ +#endif // FUCHSIA_WEB_COMMON_TEST_TEST_NAVIGATION_LISTENER_H_
diff --git a/fuchsia/base/test/url_request_rewrite_test_util.cc b/fuchsia_web/common/test/url_request_rewrite_test_util.cc similarity index 97% rename from fuchsia/base/test/url_request_rewrite_test_util.cc rename to fuchsia_web/common/test/url_request_rewrite_test_util.cc index 45da5a55..be7ace2 100644 --- a/fuchsia/base/test/url_request_rewrite_test_util.cc +++ b/fuchsia_web/common/test/url_request_rewrite_test_util.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "fuchsia/base/test/url_request_rewrite_test_util.h" +#include "fuchsia_web/common/test/url_request_rewrite_test_util.h" #include "base/strings/string_piece.h" #include "fuchsia_web/common/string_util.h"
diff --git a/fuchsia/base/test/url_request_rewrite_test_util.h b/fuchsia_web/common/test/url_request_rewrite_test_util.h similarity index 84% rename from fuchsia/base/test/url_request_rewrite_test_util.h rename to fuchsia_web/common/test/url_request_rewrite_test_util.h index 8308c3c5..99b9d5f 100644 --- a/fuchsia/base/test/url_request_rewrite_test_util.h +++ b/fuchsia_web/common/test/url_request_rewrite_test_util.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_URL_REQUEST_REWRITE_TEST_UTIL_H_ -#define FUCHSIA_BASE_TEST_URL_REQUEST_REWRITE_TEST_UTIL_H_ +#ifndef FUCHSIA_WEB_COMMON_TEST_URL_REQUEST_REWRITE_TEST_UTIL_H_ +#define FUCHSIA_WEB_COMMON_TEST_URL_REQUEST_REWRITE_TEST_UTIL_H_ #include <fuchsia/web/cpp/fidl.h> @@ -35,4 +35,4 @@ } // namespace cr_fuchsia -#endif // FUCHSIA_BASE_TEST_URL_REQUEST_REWRITE_TEST_UTIL_H_ +#endif // FUCHSIA_WEB_COMMON_TEST_URL_REQUEST_REWRITE_TEST_UTIL_H_
diff --git a/fuchsia_web/runners/BUILD.gn b/fuchsia_web/runners/BUILD.gn index 9c2a423..9496f4c 100644 --- a/fuchsia_web/runners/BUILD.gn +++ b/fuchsia_web/runners/BUILD.gn
@@ -212,7 +212,7 @@ "//base", "//base/test:run_all_unittests", "//base/test:test_support", - "//fuchsia/base/test:test_support", + "//fuchsia_web/common/test:test_support", "//net:test_support", "//testing/gmock", "//testing/gtest", @@ -222,15 +222,19 @@ } test("cast_runner_integration_tests") { - sources = [ "cast/cast_runner_integration_test.cc" ] + sources = [ + "cast/cast_runner_integration_test.cc", + "cast/fake_component_context.cc", + "cast/fake_component_context.h", + ] data = [ "cast/testdata" ] deps = [ ":cast_runner_core", ":cast_runner_test_core", "//base/test:test_support", "//components/cast/message_port", - "//fuchsia/base:run_all_integration_tests", - "//fuchsia/base/test:test_support", + "//fuchsia_web/common/test:run_all_integration_tests", + "//fuchsia_web/common/test:test_support", "//media/fuchsia/audio:test_support", "//net:test_support", "//testing/gtest", @@ -274,7 +278,7 @@ "//components/cast/message_port:test_message_port_receiver", "//content/public/browser", "//content/test:test_support", - "//fuchsia/base/test:test_support", + "//fuchsia_web/common/test:test_support", "//fuchsia_web/webengine:browsertest_core", "//testing/gmock", "//testing/gtest", @@ -328,7 +332,7 @@ "//base/test:test_support", "//components/cast/message_port", "//fuchsia/base:modular", - "//fuchsia/base:run_all_integration_tests", + "//fuchsia_web/common/test:run_all_integration_tests", "//net:test_support", "//testing/gtest", "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sys",
diff --git a/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc b/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc index d9a3cc1..197477fa 100644 --- a/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc +++ b/fuchsia_web/runners/cast/api_bindings_client_browsertest.cc
@@ -13,9 +13,9 @@ #include "base/test/test_future.h" #include "components/cast/message_port/fuchsia/message_port_fuchsia.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/runners/cast/api_bindings_client.h" #include "fuchsia_web/runners/cast/create_web_message.h" #include "fuchsia_web/runners/cast/fake_api_bindings.h"
diff --git a/fuchsia_web/runners/cast/application_controller_impl_unittest.cc b/fuchsia_web/runners/cast/application_controller_impl_unittest.cc index 06280026..f7272a7 100644 --- a/fuchsia_web/runners/cast/application_controller_impl_unittest.cc +++ b/fuchsia_web/runners/cast/application_controller_impl_unittest.cc
@@ -11,7 +11,7 @@ #include "base/logging.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "fuchsia/base/test/fit_adapter.h" +#include "fuchsia_web/common/test/fit_adapter.h" #include "fuchsia_web/runners/cast/application_controller_impl.h" #include "fuchsia_web/runners/cast/fidl/fidl/chromium/cast/cpp/fidl.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/fuchsia_web/runners/cast/cast_runner_integration_test.cc b/fuchsia_web/runners/cast/cast_runner_integration_test.cc index bfcf102..9aa8072 100644 --- a/fuchsia_web/runners/cast/cast_runner_integration_test.cc +++ b/fuchsia_web/runners/cast/cast_runner_integration_test.cc
@@ -42,17 +42,16 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" #include "fuchsia/base/agent_impl.h" -#include "fuchsia/base/test/context_provider_test_connector.h" -#include "fuchsia/base/test/fake_component_context.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_devtools_list_fetcher.h" -#include "fuchsia/base/test/url_request_rewrite_test_util.h" #include "fuchsia_web/common/string_util.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_devtools_list_fetcher.h" +#include "fuchsia_web/common/test/url_request_rewrite_test_util.h" #include "fuchsia_web/runners/cast/cast_runner.h" #include "fuchsia_web/runners/cast/cast_runner_switches.h" #include "fuchsia_web/runners/cast/fake_api_bindings.h" #include "fuchsia_web/runners/cast/fake_application_config_manager.h" +#include "fuchsia_web/runners/cast/fake_component_context.h" #include "fuchsia_web/runners/cast/fidl/fidl/chromium/cast/cpp/fidl.h" #include "media/fuchsia/audio/fake_audio_device_enumerator.h" #include "net/test/embedded_test_server/default_handlers.h"
diff --git a/fuchsia/base/test/fake_component_context.cc b/fuchsia_web/runners/cast/fake_component_context.cc similarity index 96% rename from fuchsia/base/test/fake_component_context.cc rename to fuchsia_web/runners/cast/fake_component_context.cc index e3889df..bc7197a 100644 --- a/fuchsia/base/test/fake_component_context.cc +++ b/fuchsia_web/runners/cast/fake_component_context.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "fuchsia/base/test/fake_component_context.h" +#include "fuchsia_web/runners/cast/fake_component_context.h" #include <memory> #include <string>
diff --git a/fuchsia/base/test/fake_component_context.h b/fuchsia_web/runners/cast/fake_component_context.h similarity index 91% rename from fuchsia/base/test/fake_component_context.h rename to fuchsia_web/runners/cast/fake_component_context.h index 1c4fd8a..7ec95f0 100644 --- a/fuchsia/base/test/fake_component_context.h +++ b/fuchsia_web/runners/cast/fake_component_context.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_FAKE_COMPONENT_CONTEXT_H_ -#define FUCHSIA_BASE_TEST_FAKE_COMPONENT_CONTEXT_H_ +#ifndef FUCHSIA_WEB_RUNNERS_CAST_FAKE_COMPONENT_CONTEXT_H_ +#define FUCHSIA_WEB_RUNNERS_CAST_FAKE_COMPONENT_CONTEXT_H_ #include <fuchsia/modular/cpp/fidl_test_base.h> @@ -57,4 +57,4 @@ }; } // namespace cr_fuchsia -#endif // FUCHSIA_BASE_TEST_FAKE_COMPONENT_CONTEXT_H_ +#endif // FUCHSIA_WEB_RUNNERS_CAST_FAKE_COMPONENT_CONTEXT_H_
diff --git a/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc b/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc index 9d487d6..36d9a91 100644 --- a/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc +++ b/fuchsia_web/runners/cast/named_message_port_connector_fuchsia_browsertest.cc
@@ -10,9 +10,9 @@ #include "components/cast/message_port/fuchsia/message_port_fuchsia.h" #include "components/cast/message_port/test_message_port_receiver.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/runners/cast/create_web_message.h" #include "fuchsia_web/runners/cast/named_message_port_connector_fuchsia.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/BUILD.gn b/fuchsia_web/webengine/BUILD.gn index 4b966260..6833a163 100644 --- a/fuchsia_web/webengine/BUILD.gn +++ b/fuchsia_web/webengine/BUILD.gn
@@ -418,6 +418,7 @@ "test/frame_for_test.h", "test/scenic_test_helper.cc", "test/scenic_test_helper.h", + "test/scoped_connection_checker.h", "test/test_data.cc", "test/test_data.h", "test/web_engine_browser_test.cc", @@ -430,7 +431,7 @@ ":web_engine_core", "//content/public/browser", "//content/test:test_support", - "//fuchsia/base/test:test_support", + "//fuchsia_web/common/test:test_support", "//net:test_support", "//testing/gtest", "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web", @@ -494,8 +495,8 @@ "//components/version_info", "//content/public/browser", "//content/test:test_support", - "//fuchsia/base/test:test_support", "//fuchsia_web/common", + "//fuchsia_web/common/test:test_support", "//net:test_support", "//testing/gmock", "//testing/gtest", @@ -567,7 +568,7 @@ "//components/url_rewrite/common", "//components/url_rewrite/mojom", "//content/test:test_support", - "//fuchsia/base/test:test_support", + "//fuchsia_web/common/test:test_support", "//mojo/core/embedder", "//services/media_session/public/mojom", "//services/network:network_service", @@ -596,6 +597,8 @@ test("web_engine_integration_tests") { sources = [ + "test/context_provider_test_connector.cc", + "test/context_provider_test_connector.h", "test_debug_listener.cc", "test_debug_listener.h", "web_engine_debug_integration_test.cc", @@ -613,8 +616,8 @@ "//base", "//base:test_log_listener_safe", "//components/version_info", - "//fuchsia/base:run_all_integration_tests", - "//fuchsia/base/test:test_support", + "//fuchsia_web/common/test:run_all_integration_tests", + "//fuchsia_web/common/test:test_support", "//fuchsia_web/webinstance_host", "//media", "//media/fuchsia/audio:test_support",
diff --git a/fuchsia_web/webengine/browser/accessibility_bridge_browsertest.cc b/fuchsia_web/webengine/browser/accessibility_bridge_browsertest.cc index 1eba95da..844bcce 100644 --- a/fuchsia_web/webengine/browser/accessibility_bridge_browsertest.cc +++ b/fuchsia_web/webengine/browser/accessibility_bridge_browsertest.cc
@@ -11,8 +11,8 @@ #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/accessibility_bridge.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/fake_semantics_manager.h"
diff --git a/fuchsia_web/webengine/browser/accessibility_browsertest.cc b/fuchsia_web/webengine/browser/accessibility_browsertest.cc index 284d7d93..a531472 100644 --- a/fuchsia_web/webengine/browser/accessibility_browsertest.cc +++ b/fuchsia_web/webengine/browser/accessibility_browsertest.cc
@@ -13,8 +13,8 @@ #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/accessibility_bridge.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/fake_semantics_manager.h"
diff --git a/fuchsia_web/webengine/browser/autoplay_browsertest.cc b/fuchsia_web/webengine/browser/autoplay_browsertest.cc index 3144b3b..07d6d84e 100644 --- a/fuchsia_web/webengine/browser/autoplay_browsertest.cc +++ b/fuchsia_web/webengine/browser/autoplay_browsertest.cc
@@ -6,8 +6,8 @@ #include "base/files/file_path.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/frame_impl.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc index e825413..318faf8d 100644 --- a/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc +++ b/fuchsia_web/webengine/browser/cast_streaming_browsertest.cc
@@ -12,9 +12,9 @@ #include "components/cast/message_port/platform_message_port.h" #include "components/cast_streaming/browser/test/cast_streaming_test_sender.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/frame_impl.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/client_hints_browsertest.cc b/fuchsia_web/webengine/browser/client_hints_browsertest.cc index f5f611b..40b801f 100644 --- a/fuchsia_web/webengine/browser/client_hints_browsertest.cc +++ b/fuchsia_web/webengine/browser/client_hints_browsertest.cc
@@ -10,8 +10,8 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/frame_impl.h" #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
diff --git a/fuchsia_web/webengine/browser/content_directory_browsertest.cc b/fuchsia_web/webengine/browser/content_directory_browsertest.cc index 85a2a97..62559b3 100644 --- a/fuchsia_web/webengine/browser/content_directory_browsertest.cc +++ b/fuchsia_web/webengine/browser/content_directory_browsertest.cc
@@ -19,8 +19,8 @@ #include "base/threading/thread_restrictions.h" #include "content/public/test/browser_test.h" #include "content/public/test/content_test_suite_base.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/content_directory_loader_factory.h" #include "fuchsia_web/webengine/switches.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/context_impl_browsertest.cc b/fuchsia_web/webengine/browser/context_impl_browsertest.cc index bbea024e..c9189a3 100644 --- a/fuchsia_web/webengine/browser/context_impl_browsertest.cc +++ b/fuchsia_web/webengine/browser/context_impl_browsertest.cc
@@ -5,8 +5,8 @@ #include "base/command_line.h" #include "base/no_destructor.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/switches.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
diff --git a/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc b/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc index 481ff1a8..26ed8f26 100644 --- a/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc +++ b/fuchsia_web/webengine/browser/cookie_manager_impl_unittest.cc
@@ -13,7 +13,7 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "fuchsia/base/test/fit_adapter.h" +#include "fuchsia_web/common/test/fit_adapter.h" #include "fuchsia_web/webengine/browser/cookie_manager_impl.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/cookies/cookie_access_result.h"
diff --git a/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc b/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc index 0f7453d3..8ef18f0 100644 --- a/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc +++ b/fuchsia_web/webengine/browser/explicit_sites_filter_browsertest.cc
@@ -12,8 +12,8 @@ #include "components/safe_search_api/stub_url_checker.h" #include "components/safe_search_api/url_checker.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/frame_impl.h" #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h"
diff --git a/fuchsia_web/webengine/browser/favicon_browsertest.cc b/fuchsia_web/webengine/browser/favicon_browsertest.cc index aa5f692..4735b6f 100644 --- a/fuchsia_web/webengine/browser/favicon_browsertest.cc +++ b/fuchsia_web/webengine/browser/favicon_browsertest.cc
@@ -4,8 +4,8 @@ #include "base/fuchsia/mem_buffer_util.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/test_data.h" #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
diff --git a/fuchsia_web/webengine/browser/frame_host_impl_browsertest.cc b/fuchsia_web/webengine/browser/frame_host_impl_browsertest.cc index 1c9ff395..666c140 100644 --- a/fuchsia_web/webengine/browser/frame_host_impl_browsertest.cc +++ b/fuchsia_web/webengine/browser/frame_host_impl_browsertest.cc
@@ -5,7 +5,7 @@ #include <lib/sys/cpp/service_directory.h> #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/test/web_engine_browser_test.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/browser/frame_impl_browsertest.cc b/fuchsia_web/webengine/browser/frame_impl_browsertest.cc index f043bdc..ab9c026 100644 --- a/fuchsia_web/webengine/browser/frame_impl_browsertest.cc +++ b/fuchsia_web/webengine/browser/frame_impl_browsertest.cc
@@ -11,10 +11,10 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" #include "fuchsia_web/common/string_util.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/fake_semantics_manager.h" #include "fuchsia_web/webengine/browser/frame_impl.h"
diff --git a/fuchsia_web/webengine/browser/headless_browsertest.cc b/fuchsia_web/webengine/browser/headless_browsertest.cc index f5c13fb..9142f1d 100644 --- a/fuchsia_web/webengine/browser/headless_browsertest.cc +++ b/fuchsia_web/webengine/browser/headless_browsertest.cc
@@ -5,8 +5,8 @@ #include "base/auto_reset.h" #include "base/test/scoped_command_line.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/switches.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/test_data.h"
diff --git a/fuchsia_web/webengine/browser/input_browsertest.cc b/fuchsia_web/webengine/browser/input_browsertest.cc index ce93835..d449c4d 100644 --- a/fuchsia_web/webengine/browser/input_browsertest.cc +++ b/fuchsia_web/webengine/browser/input_browsertest.cc
@@ -11,13 +11,13 @@ #include "base/fuchsia/test_component_context_for_process.h" #include "base/test/scoped_feature_list.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/scoped_connection_checker.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/features.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/scenic_test_helper.h" +#include "fuchsia_web/webengine/test/scoped_connection_checker.h" #include "fuchsia_web/webengine/test/test_data.h" #include "fuchsia_web/webengine/test/web_engine_browser_test.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/browser/javascript_browsertest.cc b/fuchsia_web/webengine/browser/javascript_browsertest.cc index f58fd9a..fb45d3b 100644 --- a/fuchsia_web/webengine/browser/javascript_browsertest.cc +++ b/fuchsia_web/webengine/browser/javascript_browsertest.cc
@@ -4,8 +4,8 @@ #include "base/fuchsia/mem_buffer_util.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/media_browsertest.cc b/fuchsia_web/webengine/browser/media_browsertest.cc index b9e045d..09d587a0 100644 --- a/fuchsia_web/webengine/browser/media_browsertest.cc +++ b/fuchsia_web/webengine/browser/media_browsertest.cc
@@ -11,8 +11,8 @@ #include "base/fuchsia/test_component_context_for_process.h" #include "base/test/scoped_feature_list.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/features.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/test_data.h"
diff --git a/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc b/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc index 397c43b1..4b4b462 100644 --- a/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc +++ b/fuchsia_web/webengine/browser/navigation_policy_browsertest.cc
@@ -5,8 +5,8 @@ #include <fuchsia/web/cpp/fidl.h> #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/fake_navigation_policy_provider.h" #include "fuchsia_web/webengine/browser/frame_impl.h"
diff --git a/fuchsia_web/webengine/browser/permissions_browsertest.cc b/fuchsia_web/webengine/browser/permissions_browsertest.cc index 940d5e8..d22b096b 100644 --- a/fuchsia_web/webengine/browser/permissions_browsertest.cc +++ b/fuchsia_web/webengine/browser/permissions_browsertest.cc
@@ -7,8 +7,8 @@ #include "base/strings/stringprintf.h" #include "base/threading/scoped_blocking_call.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/test_data.h"
diff --git a/fuchsia_web/webengine/browser/popup_browsertest.cc b/fuchsia_web/webengine/browser/popup_browsertest.cc index 3c65687..0f294c52 100644 --- a/fuchsia_web/webengine/browser/popup_browsertest.cc +++ b/fuchsia_web/webengine/browser/popup_browsertest.cc
@@ -3,8 +3,8 @@ // found in the LICENSE file. #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/post_message_browsertest.cc b/fuchsia_web/webengine/browser/post_message_browsertest.cc index 066fa42..c98f07e2 100644 --- a/fuchsia_web/webengine/browser/post_message_browsertest.cc +++ b/fuchsia_web/webengine/browser/post_message_browsertest.cc
@@ -5,9 +5,9 @@ #include "base/fuchsia/mem_buffer_util.h" #include "base/test/test_future.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc b/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc index 9f3f1c0..074f918 100644 --- a/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc +++ b/fuchsia_web/webengine/browser/request_monitoring_browsertest.cc
@@ -3,10 +3,10 @@ // found in the LICENSE file. #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" -#include "fuchsia/base/test/url_request_rewrite_test_util.h" #include "fuchsia_web/common/string_util.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/url_request_rewrite_test_util.h" #include "fuchsia_web/webengine/browser/frame_impl_browser_test_base.h" #include "fuchsia_web/webengine/switches.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/theme_manager_browsertest.cc b/fuchsia_web/webengine/browser/theme_manager_browsertest.cc index 09fbbb28..f65c15e3 100644 --- a/fuchsia_web/webengine/browser/theme_manager_browsertest.cc +++ b/fuchsia_web/webengine/browser/theme_manager_browsertest.cc
@@ -11,8 +11,8 @@ #include "base/strings/stringprintf.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/frame_impl.h" #include "fuchsia_web/webengine/test/frame_for_test.h"
diff --git a/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc b/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc index 43f65491..daa0eb8 100644 --- a/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc +++ b/fuchsia_web/webengine/browser/url_request_invalidation_browsertest.cc
@@ -5,9 +5,9 @@ #include <fuchsia/web/cpp/fidl.h> #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_navigation_listener.h" -#include "fuchsia/base/test/url_request_rewrite_test_util.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/url_request_rewrite_test_util.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/web_engine_browser_test.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc b/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc index b4b294b..22ade085 100644 --- a/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc +++ b/fuchsia_web/webengine/browser/url_request_rewrite_type_converters_unittest.cc
@@ -8,7 +8,7 @@ #include "base/run_loop.h" #include "base/test/bind.h" -#include "fuchsia/base/test/url_request_rewrite_test_util.h" +#include "fuchsia_web/common/test/url_request_rewrite_test_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace {
diff --git a/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc b/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc index dc3fb23..7b97759 100644 --- a/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc +++ b/fuchsia_web/webengine/browser/virtual_keyboard_browsertest.cc
@@ -15,15 +15,15 @@ #include "base/strings/stringprintf.h" #include "base/test/scoped_feature_list.h" #include "content/public/test/browser_test.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/scoped_connection_checker.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/frame_impl.h" #include "fuchsia_web/webengine/browser/mock_virtual_keyboard.h" #include "fuchsia_web/webengine/features.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webengine/test/scenic_test_helper.h" +#include "fuchsia_web/webengine/test/scoped_connection_checker.h" #include "fuchsia_web/webengine/test/test_data.h" #include "fuchsia_web/webengine/test/web_engine_browser_test.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia/base/test/context_provider_test_connector.cc b/fuchsia_web/webengine/test/context_provider_test_connector.cc similarity index 97% rename from fuchsia/base/test/context_provider_test_connector.cc rename to fuchsia_web/webengine/test/context_provider_test_connector.cc index 1372ac38..9b49a60 100644 --- a/fuchsia/base/test/context_provider_test_connector.cc +++ b/fuchsia_web/webengine/test/context_provider_test_connector.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "fuchsia/base/test/context_provider_test_connector.h" +#include "fuchsia_web/webengine/test/context_provider_test_connector.h" #include <unistd.h>
diff --git a/fuchsia/base/test/context_provider_test_connector.h b/fuchsia_web/webengine/test/context_provider_test_connector.h similarity index 86% rename from fuchsia/base/test/context_provider_test_connector.h rename to fuchsia_web/webengine/test/context_provider_test_connector.h index a3e59f1..f956a91 100644 --- a/fuchsia/base/test/context_provider_test_connector.h +++ b/fuchsia_web/webengine/test/context_provider_test_connector.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_CONTEXT_PROVIDER_TEST_CONNECTOR_H_ -#define FUCHSIA_BASE_TEST_CONTEXT_PROVIDER_TEST_CONNECTOR_H_ +#ifndef FUCHSIA_WEB_WEBENGINE_TEST_CONTEXT_PROVIDER_TEST_CONNECTOR_H_ +#define FUCHSIA_WEB_WEBENGINE_TEST_CONTEXT_PROVIDER_TEST_CONNECTOR_H_ #include <fuchsia/sys/cpp/fidl.h> #include <fuchsia/web/cpp/fidl.h> @@ -34,4 +34,4 @@ base::CommandLine(base::CommandLine::NO_PROGRAM)); } // namespace cr_fuchsia -#endif // FUCHSIA_BASE_TEST_CONTEXT_PROVIDER_TEST_CONNECTOR_H_ +#endif // FUCHSIA_WEB_WEBENGINE_TEST_CONTEXT_PROVIDER_TEST_CONNECTOR_H_
diff --git a/fuchsia_web/webengine/test/frame_for_test.cc b/fuchsia_web/webengine/test/frame_for_test.cc index 9fd1a7a..e21ed99 100644 --- a/fuchsia_web/webengine/test/frame_for_test.cc +++ b/fuchsia_web/webengine/test/frame_for_test.cc
@@ -4,7 +4,7 @@ #include "fuchsia_web/webengine/test/frame_for_test.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" namespace cr_fuchsia {
diff --git a/fuchsia_web/webengine/test/scenic_test_helper.cc b/fuchsia_web/webengine/test/scenic_test_helper.cc index 8f90d36..60a6031 100644 --- a/fuchsia_web/webengine/test/scenic_test_helper.cc +++ b/fuchsia_web/webengine/test/scenic_test_helper.cc
@@ -10,7 +10,7 @@ #include "base/fuchsia/fuchsia_logging.h" #include "base/run_loop.h" #include "content/public/browser/render_widget_host_view.h" -#include "fuchsia/base/test/frame_test_util.h" +#include "fuchsia_web/common/test/frame_test_util.h" #include "fuchsia_web/webengine/browser/context_impl.h" #include "fuchsia_web/webengine/browser/frame_window_tree_host.h" #include "fuchsia_web/webengine/test/test_data.h"
diff --git a/fuchsia/base/test/scoped_connection_checker.h b/fuchsia_web/webengine/test/scoped_connection_checker.h similarity index 90% rename from fuchsia/base/test/scoped_connection_checker.h rename to fuchsia_web/webengine/test/scoped_connection_checker.h index cebc816..f69db0d 100644 --- a/fuchsia/base/test/scoped_connection_checker.h +++ b/fuchsia_web/webengine/test/scoped_connection_checker.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FUCHSIA_BASE_TEST_SCOPED_CONNECTION_CHECKER_H_ -#define FUCHSIA_BASE_TEST_SCOPED_CONNECTION_CHECKER_H_ +#ifndef FUCHSIA_WEB_WEBENGINE_TEST_SCOPED_CONNECTION_CHECKER_H_ +#define FUCHSIA_WEB_WEBENGINE_TEST_SCOPED_CONNECTION_CHECKER_H_ #include <lib/fdio/directory.h> #include <lib/vfs/cpp/service.h> @@ -55,4 +55,4 @@ template <typename Service> using EnsureConnectedChecker = ScopedConnectionCheckerBase<Service, true>; -#endif // FUCHSIA_BASE_TEST_SCOPED_CONNECTION_CHECKER_H_ +#endif // FUCHSIA_WEB_WEBENGINE_TEST_SCOPED_CONNECTION_CHECKER_H_
diff --git a/fuchsia_web/webengine/web_engine_debug_integration_test.cc b/fuchsia_web/webengine/web_engine_debug_integration_test.cc index 48f0c373..ef7eeeb 100644 --- a/fuchsia_web/webengine/web_engine_debug_integration_test.cc +++ b/fuchsia_web/webengine/web_engine_debug_integration_test.cc
@@ -13,11 +13,11 @@ #include "base/fuchsia/file_utils.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "fuchsia/base/test/context_provider_test_connector.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_devtools_list_fetcher.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_devtools_list_fetcher.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" +#include "fuchsia_web/webengine/test/context_provider_test_connector.h" #include "fuchsia_web/webengine/test_debug_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/web_engine_integration_logging_test.cc b/fuchsia_web/webengine/web_engine_integration_logging_test.cc index 5700760..de76d741 100644 --- a/fuchsia_web/webengine/web_engine_integration_logging_test.cc +++ b/fuchsia_web/webengine/web_engine_integration_logging_test.cc
@@ -13,8 +13,8 @@ #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/test/bind.h" -#include "fuchsia/base/test/context_provider_test_connector.h" -#include "fuchsia/base/test/frame_test_util.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/webengine/test/context_provider_test_connector.h" #include "fuchsia_web/webengine/web_engine_integration_test_base.h" namespace {
diff --git a/fuchsia_web/webengine/web_engine_integration_test.cc b/fuchsia_web/webengine/web_engine_integration_test.cc index da76f72..fd6ee50 100644 --- a/fuchsia_web/webengine/web_engine_integration_test.cc +++ b/fuchsia_web/webengine/web_engine_integration_test.cc
@@ -17,9 +17,9 @@ #include "base/test/test_future.h" #include "build/build_config.h" #include "components/version_info/version_info.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_devtools_list_fetcher.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_devtools_list_fetcher.h" #include "fuchsia_web/webengine/web_engine_integration_test_base.h" #include "media/base/media_switches.h" #include "media/fuchsia/audio/fake_audio_consumer.h"
diff --git a/fuchsia_web/webengine/web_engine_integration_test_base.cc b/fuchsia_web/webengine/web_engine_integration_test_base.cc index 2e28417f..d4d053b8 100644 --- a/fuchsia_web/webengine/web_engine_integration_test_base.cc +++ b/fuchsia_web/webengine/web_engine_integration_test_base.cc
@@ -13,8 +13,8 @@ #include "base/fuchsia/process_context.h" #include "base/path_service.h" #include "base/strings/string_piece.h" -#include "fuchsia/base/test/context_provider_test_connector.h" -#include "fuchsia/base/test/frame_test_util.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/webengine/test/context_provider_test_connector.h" #include "net/test/embedded_test_server/default_handlers.h" namespace {
diff --git a/fuchsia_web/webengine/web_engine_integration_test_base.h b/fuchsia_web/webengine/web_engine_integration_test_base.h index 6647631d..1e7a4ae 100644 --- a/fuchsia_web/webengine/web_engine_integration_test_base.h +++ b/fuchsia_web/webengine/web_engine_integration_test_base.h
@@ -16,7 +16,7 @@ #include "base/fuchsia/filtered_service_directory.h" #include "base/strings/string_piece_forward.h" #include "base/test/task_environment.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/fuchsia_web/webengine/web_instance_host_integration_test.cc b/fuchsia_web/webengine/web_instance_host_integration_test.cc index 17a7464..fd4284e 100644 --- a/fuchsia_web/webengine/web_instance_host_integration_test.cc +++ b/fuchsia_web/webengine/web_instance_host_integration_test.cc
@@ -14,10 +14,10 @@ #include "base/strings/string_piece_forward.h" #include "base/test/task_environment.h" #include "base/test/test_future.h" -#include "fuchsia/base/test/fit_adapter.h" -#include "fuchsia/base/test/frame_test_util.h" -#include "fuchsia/base/test/test_devtools_list_fetcher.h" -#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia_web/common/test/fit_adapter.h" +#include "fuchsia_web/common/test/frame_test_util.h" +#include "fuchsia_web/common/test/test_devtools_list_fetcher.h" +#include "fuchsia_web/common/test/test_navigation_listener.h" #include "fuchsia_web/webengine/test/frame_for_test.h" #include "fuchsia_web/webinstance_host/web_instance_host.h" #include "net/test/embedded_test_server/default_handlers.h"
diff --git a/gpu/config/gpu_switches.cc b/gpu/config/gpu_switches.cc index 17d91d4..0324a7c 100644 --- a/gpu/config/gpu_switches.cc +++ b/gpu/config/gpu_switches.cc
@@ -43,6 +43,11 @@ const char kEnableUnsafeWebGPU[] = "enable-unsafe-webgpu"; +// Enables WebGPU developer features which are not generally exposed to the web +// platform. +const char kEnableWebGPUDeveloperFeatures[] = + "enable-webgpu-developer-features"; + // Enable validation layers in Dawn backends. const char kEnableDawnBackendValidation[] = "enable-dawn-backend-validation";
diff --git a/gpu/config/gpu_switches.h b/gpu/config/gpu_switches.h index f4d43cd..0dc1a04a 100644 --- a/gpu/config/gpu_switches.h +++ b/gpu/config/gpu_switches.h
@@ -19,6 +19,7 @@ GPU_EXPORT extern const char kShaderDiskCacheSizeKB[]; GPU_EXPORT extern const char kDisableGpuProcessForDX12InfoCollection[]; GPU_EXPORT extern const char kEnableUnsafeWebGPU[]; +GPU_EXPORT extern const char kEnableWebGPUDeveloperFeatures[]; GPU_EXPORT extern const char kEnableDawnBackendValidation[]; GPU_EXPORT extern const char kUseWebGPUAdapter[]; GPU_EXPORT extern const char kEnableDawnFeatures[];
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index 7d07b3cd..41e7486d 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -1947,6 +1947,7 @@ } builders { name: "chromium/try/win_chromium_compile_dbg_ng" + cancel_stale: NO location_regexp: ".*" location_regexp_exclude: ".+/[+]/docs/.+" location_regexp_exclude: ".+/[+]/infra/config/.+"
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star index af47eca..7ff5d7a3 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.win.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.win.star
@@ -82,7 +82,11 @@ ), goma_jobs = goma.jobs.J150, main_list_view = "try", - tryjob = try_.job(), + tryjob = try_.job( + # TODO(crbug.com/1335555) Remove once cancelling doesn't wipe + # out builder cache + cancel_stale = False, + ), builderless = False, cores = 16, ssd = True,
diff --git a/ios/chrome/app/resources/BUILD.gn b/ios/chrome/app/resources/BUILD.gn index 53d876c..458b3ce 100644 --- a/ios/chrome/app/resources/BUILD.gn +++ b/ios/chrome/app/resources/BUILD.gn
@@ -29,6 +29,8 @@ "grit/ios_resources.h", "ios_resources.pak", ] + + deps = [ "//components/ukm/debug:build_ts" ] } group("packed_resources") {
diff --git a/ios/chrome/app/resources/ios_resources.grd b/ios/chrome/app/resources/ios_resources.grd index 3800f8ad..91624f44 100644 --- a/ios/chrome/app/resources/ios_resources.grd +++ b/ios/chrome/app/resources/ios_resources.grd
@@ -13,7 +13,7 @@ <include name="IDR_IOS_OMAHA_HTML" file="omaha/omaha.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_IOS_OMAHA_JS" file="omaha/omaha.js" type="BINDATA" /> <include name="IDR_IOS_UKM_INTERNALS_HTML" file="../../../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> - <include name="IDR_IOS_UKM_INTERNALS_JS" file="../../../../components/ukm/debug/ukm_internals.js" type="BINDATA" /> + <include name="IDR_IOS_UKM_INTERNALS_JS" file="${root_gen_dir}/components/ukm/debug/tsc/ukm_internals.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_IOS_TRANSLATE_INTERNALS_CSS" file="../../../../components/translate/translate_internals/translate_internals.css" type="BINDATA" /> <include name="IDR_IOS_TRANSLATE_INTERNALS_HTML" file="../../../../components/translate/translate_internals/translate_internals.html" type="BINDATA" /> <include name="IDR_IOS_TRANSLATE_INTERNALS_JS" file="../../../../components/translate/translate_internals/translate_internals.js" preprocess="true" type="BINDATA" />
diff --git a/ios/chrome/browser/sync/sync_service_factory_unittest.cc b/ios/chrome/browser/sync/sync_service_factory_unittest.cc index 644a9ec..55dd50c 100644 --- a/ios/chrome/browser/sync/sync_service_factory_unittest.cc +++ b/ios/chrome/browser/sync/sync_service_factory_unittest.cc
@@ -53,7 +53,7 @@ protected: // Returns the collection of default datatypes. syncer::ModelTypeSet DefaultDatatypes() { - static_assert(39 == syncer::GetNumModelTypes(), + static_assert(40 == syncer::GetNumModelTypes(), "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled).");
diff --git a/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm b/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm index eba2d79..d6a6fbd3 100644 --- a/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm +++ b/ios/chrome/browser/ui/default_promo/default_browser_promo_non_modal_scheduler.mm
@@ -37,7 +37,7 @@ const int64_t kShowPromoPostShareWaitTime = 1; // Number of times to show the promo to a user. -const int kPromoShownTimesLimit = 2; +const int kPromoShownTimesLimit = 3; // Timeout before the promo is dismissed. const double kPromoTimeout = 45;
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 1ce55b2..a97a23a 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 @@ -7776f31abf78d11b7350d5b31744300cfba5a2ab \ No newline at end of file +29d83827f1ce62ffa1d2b1338facee4e37e4326f \ 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 7bdb288d..a2f8bf6 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 @@ -98188e2515d1e375167883bd88154e4e6437703a \ No newline at end of file +d6d80d986cd86dc79a8d9eca8e8ed164170898d5 \ 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 9570e9b4..1110df9 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 @@ -443a1b06914c5b658a657fca986dc598aea86e87 \ No newline at end of file +3feb59b8cf1dfa10c8d41b76fae45f4bca0c4c64 \ 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 9816eed..dd069644 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 @@ -3f86dac1459635954bd1e4d2f20af844e66e6dcc \ No newline at end of file +26c43d93baa3b6a949bae43556aa87765dc235b7 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index e1c924a..17e5def 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -6ecf51009361a4779fe8bc09f0ff11e6acfa8ecc \ No newline at end of file +253a1275e663c8bb1eb4e2c83e909782556fbdad \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index eaf9926..81f5f3b 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -df9d5e658b048ae09fb1e9794b8c9982763d1399 \ No newline at end of file +cbd07fe889552cf5d33d0e0926802561b325a13f \ 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 e7424e3..bc4ba87 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 @@ -e6eb9295cf0298158b80aaa2b35419cdf9f2805e \ No newline at end of file +310b21e037a9da1bf152f9dc481a017f42ce71ea \ 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 18b241d..251b980 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 @@ -2ae51309119eb83d7eec7a086dc4fc5eda8588f4 \ No newline at end of file +2f0ad7b0a73049a41ead37659ae01f374a148817 \ 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 d13d47f..ae88bba 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 @@ -05c64536bde680a3cec23c08416479c38e99216b \ No newline at end of file +b34f34a98411d2d6bcf38dd9c65407b44c764159 \ 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 3fe28fb..6ff9541 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 @@ -92ebcb591c43b55551d76bc7d88631c8798d7f25 \ No newline at end of file +48f4b69a2b73fca5745be58a1a311414ee6829cc \ No newline at end of file
diff --git a/ios/web_view/internal/app/application_context.h b/ios/web_view/internal/app/application_context.h index ad319e0..379a33f 100644 --- a/ios/web_view/internal/app/application_context.h +++ b/ios/web_view/internal/app/application_context.h
@@ -85,6 +85,9 @@ // Gets the SafeBrowsingService. SafeBrowsingService* GetSafeBrowsingService(); + // Shuts down SafeBrowsingService if it was created. + void ShutdownSafeBrowsingServiceIfNecessary(); + private: friend class base::NoDestructor<ApplicationContext>;
diff --git a/ios/web_view/internal/app/application_context.mm b/ios/web_view/internal/app/application_context.mm index 6cea5c1628..58120b3 100644 --- a/ios/web_view/internal/app/application_context.mm +++ b/ios/web_view/internal/app/application_context.mm
@@ -232,4 +232,11 @@ return safe_browsing_service_.get(); } +void ApplicationContext::ShutdownSafeBrowsingServiceIfNecessary() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (safe_browsing_service_) { + safe_browsing_service_->ShutDown(); + } +} + } // namespace ios_web_view
diff --git a/ios/web_view/internal/web_view_web_main_parts.mm b/ios/web_view/internal/web_view_web_main_parts.mm index 534632d7..6a61190 100644 --- a/ios/web_view/internal/web_view_web_main_parts.mm +++ b/ios/web_view/internal/web_view_web_main_parts.mm
@@ -99,6 +99,8 @@ } void WebViewWebMainParts::PostMainMessageLoopRun() { + ApplicationContext::GetInstance()->ShutdownSafeBrowsingServiceIfNecessary(); + // CWVWebViewConfiguration must destroy its WebViewBrowserStates before the // threads are stopped by ApplicationContext. [CWVWebViewConfiguration shutDown];
diff --git a/media/base/video_frame_metadata.h b/media/base/video_frame_metadata.h index 26ea562..de5b134 100644 --- a/media/base/video_frame_metadata.h +++ b/media/base/video_frame_metadata.h
@@ -63,6 +63,10 @@ // If cropping was applied due to Region Capture to produce this frame, // then this reflects where the frame's contents originate from in the // original uncropped frame. + // + // NOTE: May also be nullopt if region capture is enabled but the capture rect + // is in a different coordinate space. For more info, see + // https://crbug.com/1327560. absl::optional<gfx::Rect> region_capture_rect; // Whenever cropTo() is called, Blink increments the crop_version and records
diff --git a/native_client_sdk/PRESUBMIT.py b/native_client_sdk/PRESUBMIT.py index 8788955..4c7cea13 100644 --- a/native_client_sdk/PRESUBMIT.py +++ b/native_client_sdk/PRESUBMIT.py
@@ -30,7 +30,8 @@ canned = input_api.canned_checks output.extend(canned.RunPylint(input_api, output_api, files_to_skip=files_to_skip, - disabled_warnings=disabled_warnings)) + disabled_warnings=disabled_warnings, + version='1.5')) return output
diff --git a/net/cert/internal/trust_store_win.cc b/net/cert/internal/trust_store_win.cc index c2d5ac0..b1649620 100644 --- a/net/cert/internal/trust_store_win.cc +++ b/net/cert/internal/trust_store_win.cc
@@ -154,6 +154,18 @@ CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, L"Disallowed"); + // Auto-sync all of the cert stores to get updates to the cert store. + // Auto-syncing on all_certs_store seems to work to resync the nested stores, + // although the docs at + // https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certcontrolstore + // are somewhat unclear. If and when root store changes are linked to clearing + // various caches, this should be replaced with CERT_STORE_CTRL_NOTIFY_CHANGE + // and CERT_STORE_CTRL_RESYNC. + if (!CertControlStore(all_certs_store.get(), 0, CERT_STORE_CTRL_AUTO_RESYNC, + 0)) { + PLOG(ERROR) << "Error enabling CERT_STORE_CTRL_AUTO_RESYNC"; + } + return base::WrapUnique(new TrustStoreWin( std::move(root_cert_store), std::move(intermediate_cert_store), std::move(disallowed_cert_store), std::move(all_certs_store)));
diff --git a/net/der/parse_values.cc b/net/der/parse_values.cc index aac0b25..caab98e 100644 --- a/net/der/parse_values.cc +++ b/net/der/parse_values.cc
@@ -450,7 +450,7 @@ memcpy(in_32bit.data(), in.UnsafeData(), in.Length()); for (const uint32_t c : in_32bit) { // UniversalString is UCS-4 in big-endian order. - uint32_t codepoint = base::NetToHost32(c); + auto codepoint = static_cast<base_icu::UChar32>(base::NetToHost32(c)); if (!CBU_IS_UNICODE_CHAR(codepoint)) return false; @@ -469,7 +469,7 @@ memcpy(in_16bit.data(), in.UnsafeData(), in.Length()); for (const uint16_t c : in_16bit) { // BMPString is UCS-2 in big-endian order. - uint32_t codepoint = base::NetToHost16(c); + base_icu::UChar32 codepoint = base::NetToHost16(c); // BMPString only supports codepoints in the Basic Multilingual Plane; // surrogates are not allowed. CBU_IS_UNICODE_CHAR excludes the surrogate
diff --git a/remoting/host/input_injector_x11.cc b/remoting/host/input_injector_x11.cc index a895fb9..b10a860 100644 --- a/remoting/host/input_injector_x11.cc +++ b/remoting/host/input_injector_x11.cc
@@ -352,7 +352,7 @@ pressed_keys_.clear(); const std::string text = event.text(); - for (int32_t index = 0; index < static_cast<int32_t>(text.size()); ++index) { + for (size_t index = 0; index < text.size(); ++index) { base_icu::UChar32 code_point; if (!base::ReadUnicodeCharacter(text.c_str(), text.size(), &index, &code_point)) {
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper.cc b/remoting/protocol/webrtc_video_encoder_wrapper.cc index 6fed61c..c50432b5 100644 --- a/remoting/protocol/webrtc_video_encoder_wrapper.cc +++ b/remoting/protocol/webrtc_video_encoder_wrapper.cc
@@ -302,14 +302,8 @@ encode_pending_ = true; - // Just in case the encoder runs the callback on an arbitrary thread, - // BindPostTask() is used here to trampoline onto the correct thread. - // This object is bound via a WeakPtr which must only be dereferenced - // on the current thread. - auto encode_callback = base::BindPostTask( - base::SequencedTaskRunnerHandle::Get(), - base::BindOnce(&WebrtcVideoEncoderWrapper::OnFrameEncoded, - weak_factory_.GetWeakPtr())); + auto encode_callback = base::BindOnce( + &WebrtcVideoEncoderWrapper::OnFrameEncoded, weak_factory_.GetWeakPtr()); encoder_->Encode(std::move(desktop_frame), frame_params, std::move(encode_callback)); return WEBRTC_VIDEO_CODEC_OK;
diff --git a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc index cd1cd4d..8f269e8 100644 --- a/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc +++ b/remoting/protocol/webrtc_video_encoder_wrapper_unittest.cc
@@ -165,9 +165,8 @@ class WebrtcVideoEncoderWrapperTest : public testing::Test { public: void SetUp() override { - mock_video_encoder_ = std::make_unique<NiceMock<MockVideoEncoder>>(); - // Configure the mock encoder's default behavior to mimic a real encoder. + mock_video_encoder_ = std::make_unique<NiceMock<MockVideoEncoder>>(); ON_CALL(*mock_video_encoder_, Encode) .WillByDefault([](std::unique_ptr<webrtc::DesktopFrame> frame, const WebrtcVideoEncoder::FrameParams& param, @@ -177,6 +176,27 @@ std::move(done).Run(WebrtcVideoEncoder::EncodeResult::SUCCEEDED, std::move(encoded_frame)); }); + + // Configure this mock encoder's behavior to mimic a real async encoder. + mock_video_encoder_async_ = std::make_unique<NiceMock<MockVideoEncoder>>(); + ON_CALL(*mock_video_encoder_async_, Encode) + .WillByDefault([this](std::unique_ptr<webrtc::DesktopFrame> frame, + const WebrtcVideoEncoder::FrameParams& param, + WebrtcVideoEncoder::EncodeCallback done) { + auto encoded_frame = + std::make_unique<WebrtcVideoEncoder::EncodedFrame>(); + encoded_frame->size = frame->size(); + encoded_frame->data.assign( + frame->size().width() * frame->size().height(), 'a'); + encoded_frame->key_frame = param.key_frame; + encoded_frame->quantizer = param.vpx_min_quantizer; + encoded_frame->codec = kVideoCodecVP9; + task_environment_.GetMainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(std::move(done), + WebrtcVideoEncoder::EncodeResult::SUCCEEDED, + std::move(encoded_frame))); + }); } std::unique_ptr<WebrtcVideoEncoderWrapper> InitEncoder(SdpVideoFormat sdp, @@ -205,6 +225,7 @@ NiceMock<MockVideoChannelStateObserver> observer_; MockEncodedImageCallback callback_; std::unique_ptr<NiceMock<MockVideoEncoder>> mock_video_encoder_; + std::unique_ptr<NiceMock<MockVideoEncoder>> mock_video_encoder_async_; }; TEST_F(WebrtcVideoEncoderWrapperTest, ReturnsVP8EncodedFrames) { @@ -257,7 +278,7 @@ PostQuitAndRun(); } -TEST_F(WebrtcVideoEncoderWrapperTest, FrameDroppedIfEncoderBusy) { +TEST_F(WebrtcVideoEncoderWrapperTest, FrameDroppedIfAsyncEncoderBusy) { EXPECT_CALL(callback_, OnEncodedImage(_, Field(&CodecSpecificInfo::codecType, kVideoCodecVP9))) .WillOnce(Return(kResultOk)); @@ -265,6 +286,7 @@ auto frame1 = MakeVideoFrame(); auto frame2 = MakeVideoFrame(); auto encoder = InitEncoder(GetVp9Format(), GetVp9Codec()); + encoder->SetEncoderForTest(std::move(mock_video_encoder_async_)); std::vector<VideoFrameType> frame_types{VideoFrameType::kVideoFrameKey}; encoder->Encode(frame1, &frame_types); encoder->Encode(frame2, &frame_types); @@ -278,13 +300,21 @@ InSequence s; // Encode frame1. - EXPECT_CALL(*mock_video_encoder_, Encode); + EXPECT_CALL(*mock_video_encoder_async_, Encode); + EXPECT_CALL( + callback_, + OnEncodedImage(_, Field(&CodecSpecificInfo::codecType, kVideoCodecVP9))) + .WillOnce(Return(kResultOk)); // Encode frame3. Its update-region should be the rectangle-union of frame2 // and frame3. auto combined_rect = DesktopRect::MakeLTRB(100, 200, 310, 410); - EXPECT_CALL(*mock_video_encoder_, + EXPECT_CALL(*mock_video_encoder_async_, Encode(Pointee(MatchesUpdateRect(combined_rect)), _, _)); + EXPECT_CALL( + callback_, + OnEncodedImage(_, Field(&CodecSpecificInfo::codecType, kVideoCodecVP9))) + .WillOnce(Return(kResultOk)); } auto frame1 = MakeVideoFrame(); @@ -296,7 +326,7 @@ .offset_x = 300, .offset_y = 400, .width = 10, .height = 10}); auto encoder = InitEncoder(GetVp9Format(), GetVp9Codec()); - encoder->SetEncoderForTest(std::move(mock_video_encoder_)); + encoder->SetEncoderForTest(std::move(mock_video_encoder_async_)); std::vector<VideoFrameType> frame_types{VideoFrameType::kVideoFrameKey}; // frame2 should be dropped since the encoder is busy. @@ -365,7 +395,8 @@ PostQuitAndRun(); } -TEST_F(WebrtcVideoEncoderWrapperTest, KeyFrameRequestRememberedIfEncoderBusy) { +TEST_F(WebrtcVideoEncoderWrapperTest, + KeyFrameRequestRememberedIfAsyncEncoderBusy) { // Three frames are used for this test: // Frame 1 kicks off the encoder. // Frame 2 is a key-frame request, which is dropped because frame 1 is still @@ -376,10 +407,10 @@ // // The end-result is that the encoder should see two key-frame requests (for // frames 1 and 3). - // Note that |mock_video_encoder_| does not produce any video frames. This - // means that no encoded frames are returned to WebRTC and so OnEncodedImage() - // is not EXPECT_CALL()ed by this test. - EXPECT_CALL(*mock_video_encoder_, Encode(_, IsKeyFrame(), _)).Times(2); + EXPECT_CALL(*mock_video_encoder_async_, Encode(_, IsKeyFrame(), _)).Times(2); + EXPECT_CALL(callback_, OnEncodedImage(_, _)) + .Times(2) + .WillRepeatedly(Return(kResultOk)); auto frame1 = MakeVideoFrame(); auto frame2 = MakeVideoFrame(); @@ -388,7 +419,7 @@ std::vector<VideoFrameType> frame_types2{VideoFrameType::kVideoFrameKey}; std::vector<VideoFrameType> frame_types3{VideoFrameType::kVideoFrameDelta}; auto encoder = InitEncoder(GetVp9Format(), GetVp9Codec()); - encoder->SetEncoderForTest(std::move(mock_video_encoder_)); + encoder->SetEncoderForTest(std::move(mock_video_encoder_async_)); encoder->Encode(frame1, &frame_types1); encoder->Encode(frame2, &frame_types2);
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc index 37c88296..26348b5e 100644 --- a/services/network/cookie_settings.cc +++ b/services/network/cookie_settings.cc
@@ -187,6 +187,51 @@ } } +bool CookieSettings::BlockDueToThirdPartyCookieBlockingSetting( + bool is_third_party_request, + const GURL& url, + const GURL& first_party_url, + ContentSetting cookie_setting) const { + if (block_third_party_cookies_ && is_third_party_request && + !base::Contains(third_party_cookies_allowed_schemes_, + first_party_url.scheme())) { + // See if a Storage Access permission grant can unblock. + if (const ContentSettingPatternSource* match = + FindMatchingSetting(url, first_party_url, storage_access_grants_); + match && match->GetContentSetting() == CONTENT_SETTING_ALLOW) { + FireStorageAccessHistogram(net::cookie_util::StorageAccessResult:: + ACCESS_ALLOWED_STORAGE_ACCESS_GRANT); + return false; + } + + FireStorageAccessHistogram( + net::cookie_util::StorageAccessResult::ACCESS_BLOCKED); + return true; + } + + // Cookies aren't blocked solely due to the third-party-cookie blocking + // setting, but they still may be blocked due to a global default. So we + // have to check what the setting is here. + FireStorageAccessHistogram( + cookie_setting == CONTENT_SETTING_BLOCK + ? net::cookie_util::StorageAccessResult::ACCESS_BLOCKED + : net::cookie_util::StorageAccessResult::ACCESS_ALLOWED); + + return false; +} + +CookieSettings::ThirdPartyBlockingOutcome +CookieSettings::GetThirdPartyBlockingScope(const GURL& first_party_url) const { + // If cookies are allowed for the first-party URL then we allow + // partitioned cross-site cookies. + if (const ContentSettingPatternSource* match = FindMatchingSetting( + first_party_url, first_party_url, content_settings_); + !match || match->GetContentSetting() == CONTENT_SETTING_ALLOW) { + return ThirdPartyBlockingOutcome::kPartitionedStateAllowed; + } + return ThirdPartyBlockingOutcome::kAllStateDisallowed; +} + CookieSettings::CookieSettingWithMetadata CookieSettings::GetCookieSettingWithMetadata( const GURL& url, @@ -204,66 +249,27 @@ ContentSetting cookie_setting = CONTENT_SETTING_ALLOW; ThirdPartyBlockingOutcome third_party_blocking_outcome = ThirdPartyBlockingOutcome::kIrrelevant; - if (block_third_party_cookies_ && is_third_party_request && - !base::Contains(third_party_cookies_allowed_schemes_, - first_party_url.scheme())) { - // We'll set `cookie_setting` to `CONTENT_SETTING_BLOCK` - // below iff there's no Storage Access permission grant - // that can allow access. - third_party_blocking_outcome = - ThirdPartyBlockingOutcome::kAllStateDisallowed; - } + bool found_explicit_setting = false; if (const ContentSettingPatternSource* match = FindMatchingSetting(url, first_party_url, content_settings_); match) { cookie_setting = match->GetContentSetting(); - if (cookie_setting == CONTENT_SETTING_BLOCK || IsExplicitSetting(*match)) { - third_party_blocking_outcome = ThirdPartyBlockingOutcome::kIrrelevant; - } + found_explicit_setting = IsExplicitSetting(*match); } - switch (third_party_blocking_outcome) { - case ThirdPartyBlockingOutcome::kAllStateDisallowed: - if (const ContentSettingPatternSource* match = - FindMatchingSetting(url, first_party_url, storage_access_grants_); - match && match->GetContentSetting() == CONTENT_SETTING_ALLOW) { - third_party_blocking_outcome = ThirdPartyBlockingOutcome::kIrrelevant; - FireStorageAccessHistogram(net::cookie_util::StorageAccessResult:: - ACCESS_ALLOWED_STORAGE_ACCESS_GRANT); - } else { - cookie_setting = CONTENT_SETTING_BLOCK; - FireStorageAccessHistogram( - net::cookie_util::StorageAccessResult::ACCESS_BLOCKED); - } - break; - case ThirdPartyBlockingOutcome::kIrrelevant: - // Cookies aren't blocked solely due to the third-party-cookie blocking - // setting, but they still may be blocked due to a global default. So we - // have to check what the setting is here. - FireStorageAccessHistogram( - cookie_setting == CONTENT_SETTING_BLOCK - ? net::cookie_util::StorageAccessResult::ACCESS_BLOCKED - : net::cookie_util::StorageAccessResult::ACCESS_ALLOWED); - break; - case ThirdPartyBlockingOutcome::kPartitionedStateAllowed: - NOTREACHED(); - break; - } - - if (third_party_blocking_outcome == - ThirdPartyBlockingOutcome::kAllStateDisallowed) { - // If the third-party cookie blocking setting is enabled and will block - // access to unpartitioned cookies, we check if the user has any content - // settings for the first-party URL as the primary pattern. If cookies are - // allowed for the first-party URL then we allow partitioned cross-site - // cookies. - if (const ContentSettingPatternSource* match = FindMatchingSetting( - first_party_url, first_party_url, content_settings_); - !match || match->GetContentSetting() == CONTENT_SETTING_ALLOW) { + if (cookie_setting != CONTENT_SETTING_BLOCK && !found_explicit_setting) { + if (BlockDueToThirdPartyCookieBlockingSetting( + is_third_party_request, url, first_party_url, cookie_setting)) { + cookie_setting = CONTENT_SETTING_BLOCK; third_party_blocking_outcome = - ThirdPartyBlockingOutcome::kPartitionedStateAllowed; + GetThirdPartyBlockingScope(first_party_url); } + } else { + FireStorageAccessHistogram( + cookie_setting == CONTENT_SETTING_BLOCK + ? net::cookie_util::StorageAccessResult::ACCESS_BLOCKED + : net::cookie_util::StorageAccessResult::ACCESS_ALLOWED); } return {cookie_setting, third_party_blocking_outcome};
diff --git a/services/network/cookie_settings.h b/services/network/cookie_settings.h index d23edcf..cefd5dc 100644 --- a/services/network/cookie_settings.h +++ b/services/network/cookie_settings.h
@@ -177,6 +177,23 @@ ThirdPartyBlockingOutcome third_party_blocking_outcome; }; + // Determines whether cookie access should be blocked due to the + // third-party-cookie-blocking setting and any relevant Storage Access + // permission grants. Does not distinguish between access to unpartitioned + // state and access to partitioned state. + bool BlockDueToThirdPartyCookieBlockingSetting( + bool is_third_party_request, + const GURL& url, + const GURL& first_party_url, + ContentSetting cookie_setting) const; + + // Determines the scope of third-party-cookie-blocking, i.e. whether it + // applies to all cookies or just unpartitioned cookies. Assumes that + // BlockDueToThirdpartyCookieBlockingSetting has been called and returned + // true. + ThirdPartyBlockingOutcome GetThirdPartyBlockingScope( + const GURL& first_party_url) const; + // Returns the cookie setting for the given request, along with metadata // associated with the lookup. Namely, whether the setting is due to // third-party cookie blocking settings or not.
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc index 3bc3344..f8e3798 100644 --- a/storage/browser/quota/quota_manager_impl.cc +++ b/storage/browser/quota/quota_manager_impl.cc
@@ -1256,7 +1256,8 @@ void QuotaManagerImpl::GetBucketsForStorageKey( const StorageKey& storage_key, blink::mojom::StorageType type, - base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback) { + base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback, + bool delete_expired) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(callback); EnsureDatabaseOpened(); @@ -1265,6 +1266,16 @@ std::move(callback).Run(QuotaError::kDatabaseError); return; } + + base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> reply; + if (delete_expired) { + reply = base::BindOnce(&QuotaManagerImpl::DidGetBucketsCheckExpiration, + weak_factory_.GetWeakPtr(), std::move(callback)); + } else { + reply = base::BindOnce(&QuotaManagerImpl::DidGetBuckets, + weak_factory_.GetWeakPtr(), std::move(callback)); + } + PostTaskAndReplyWithResultForDBThread( base::BindOnce( [](const StorageKey& storage_key, StorageType type, @@ -1273,8 +1284,7 @@ return database->GetBucketsForStorageKey(storage_key, type); }, storage_key, type), - base::BindOnce(&QuotaManagerImpl::DidGetBuckets, - weak_factory_.GetWeakPtr(), std::move(callback))); + std::move(reply)); } void QuotaManagerImpl::GetUsageInfo(GetUsageInfoCallback callback) { @@ -2956,6 +2966,48 @@ std::move(callback).Run(std::move(result)); } +void QuotaManagerImpl::DidGetBucketsCheckExpiration( + base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback, + QuotaErrorOr<std::set<BucketInfo>> result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(callback); + + DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); + + if (!result.ok()) { + std::move(callback).Run(std::move(result)); + return; + } + + std::set<BucketInfo> kept_buckets; + std::set<BucketInfo> buckets_to_delete; + for (const BucketInfo& bucket : result.value()) { + if (!bucket.expiration.is_null() && + bucket.expiration <= QuotaDatabase::GetNow()) { + buckets_to_delete.insert(bucket); + } else { + kept_buckets.insert(bucket); + } + } + + if (buckets_to_delete.empty()) { + std::move(callback).Run(kept_buckets); + return; + } + + base::RepeatingClosure barrier = + base::BarrierClosure(buckets_to_delete.size(), + base::BindOnce(std::move(callback), kept_buckets)); + for (const BucketInfo& bucket : buckets_to_delete) { + StatusCallback on_delete_done = + base::BindOnce([](base::RepeatingClosure barrier, + blink::mojom::QuotaStatusCode) { barrier.Run(); }, + barrier); + DeleteBucketDataInternal(bucket.ToBucketLocator(), AllQuotaClientTypes(), + std::move(on_delete_done)); + } +} + void QuotaManagerImpl::DidGetModifiedBetween( GetBucketsCallback callback, StorageType type,
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h index 0df957b0..19d3bf5 100644 --- a/storage/browser/quota/quota_manager_impl.h +++ b/storage/browser/quota/quota_manager_impl.h
@@ -245,11 +245,13 @@ base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback); // Retrieves all buckets for `storage_key` and `type` that are in the buckets - // table. Used for retrieving storage key usage data in the UsageTracker. + // table. When `delete_expired` is true, the expired buckets will be filtered + // out of the reply and also deleted from disk. void GetBucketsForStorageKey( const blink::StorageKey& storage_key, blink::mojom::StorageType type, - base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback); + base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback, + bool delete_expired = false); // Called by clients or webapps. Returns usage per host. void GetUsageInfo(GetUsageInfoCallback callback); @@ -715,6 +717,9 @@ void DidGetBuckets( base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback, QuotaErrorOr<std::set<BucketInfo>> result); + void DidGetBucketsCheckExpiration( + base::OnceCallback<void(QuotaErrorOr<std::set<BucketInfo>>)> callback, + QuotaErrorOr<std::set<BucketInfo>> result); void DidGetModifiedBetween(GetBucketsCallback callback, blink::mojom::StorageType type, QuotaErrorOr<std::set<BucketLocator>> result);
diff --git a/storage/browser/quota/quota_manager_proxy.cc b/storage/browser/quota/quota_manager_proxy.cc index b2168a4..099eb2f 100644 --- a/storage/browser/quota/quota_manager_proxy.cc +++ b/storage/browser/quota/quota_manager_proxy.cc
@@ -252,7 +252,7 @@ std::move(respond)); } -void QuotaManagerProxy::GetBucketsForStorageKey( +void QuotaManagerProxy::GetBucketsForStorageKeyDeleteExpired( const blink::StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner, @@ -263,8 +263,8 @@ if (!quota_manager_impl_task_runner_->RunsTasksInCurrentSequence()) { quota_manager_impl_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&QuotaManagerProxy::GetBucketsForStorageKey, this, - storage_key, type, std::move(callback_task_runner), + base::BindOnce(&QuotaManagerProxy::GetBucketsForStorageKeyDeleteExpired, + this, storage_key, type, std::move(callback_task_runner), std::move(callback))); return; } @@ -278,8 +278,8 @@ return; } - quota_manager_impl_->GetBucketsForStorageKey(storage_key, type, - std::move(respond)); + quota_manager_impl_->GetBucketsForStorageKey( + storage_key, type, std::move(respond), /*delete_expired=*/true); } void QuotaManagerProxy::GetBucketById(
diff --git a/storage/browser/quota/quota_manager_proxy.h b/storage/browser/quota/quota_manager_proxy.h index 6bb225dc..add2907 100644 --- a/storage/browser/quota/quota_manager_proxy.h +++ b/storage/browser/quota/quota_manager_proxy.h
@@ -146,8 +146,9 @@ base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback); // Retrieves all buckets for `storage_key` and `type` that are in the buckets - // table. - virtual void GetBucketsForStorageKey( + // table. Expired buckets will be filtered out of the reply and also deleted + // from disk. + virtual void GetBucketsForStorageKeyDeleteExpired( const blink::StorageKey& storage_key, blink::mojom::StorageType type, scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc index 28ca894..f9579cf 100644 --- a/storage/browser/quota/quota_manager_unittest.cc +++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -275,10 +275,11 @@ QuotaErrorOr<std::set<BucketInfo>> GetBucketsForStorageKey( const StorageKey& storage_key, - blink::mojom::StorageType storage_type) { + blink::mojom::StorageType storage_type, + bool delete_expired = false) { base::test::TestFuture<QuotaErrorOr<std::set<BucketInfo>>> future; - quota_manager_impl_->GetBucketsForStorageKey(storage_key, storage_type, - future.GetCallback()); + quota_manager_impl_->GetBucketsForStorageKey( + storage_key, storage_type, future.GetCallback(), delete_expired); return future.Take(); } @@ -1050,6 +1051,42 @@ EXPECT_THAT(buckets, testing::Contains(bucket_c)); } +TEST_F(QuotaManagerImplTest, GetBucketsForStorageKey_Expiration) { + StorageKey storage_key = ToStorageKey("http://a.com/"); + + auto clock = std::make_unique<base::SimpleTestClock>(); + QuotaDatabase::SetClockForTesting(clock.get()); + clock->SetNow(base::Time::Now()); + + BucketInitParams params(storage_key, "bucket_1"); + auto bucket = UpdateOrCreateBucket(params); + EXPECT_TRUE(bucket.ok()); + BucketInfo bucket_1 = bucket.value(); + + params.name = "bucket_2"; + params.expiration = clock->Now() + base::Days(1); + bucket = UpdateOrCreateBucket(params); + EXPECT_TRUE(bucket.ok()); + BucketInfo bucket_2 = bucket.value(); + + params.name = "bucket_3"; + bucket = UpdateOrCreateBucket(params); + EXPECT_TRUE(bucket.ok()); + BucketInfo bucket_3 = bucket.value(); + + clock->Advance(base::Days(2)); + + QuotaErrorOr<std::set<BucketInfo>> result = + GetBucketsForStorageKey(storage_key, kTemp, /*delete_expired=*/true); + EXPECT_TRUE(result.ok()); + + std::set<BucketInfo> buckets = result.value(); + ASSERT_EQ(1U, buckets.size()); + EXPECT_EQ(*buckets.begin(), bucket_1); + + QuotaDatabase::SetClockForTesting(nullptr); +} + TEST_F(QuotaManagerImplTest, GetUsageAndQuota_Simple) { static const ClientBucketData kData[] = { {"http://foo.com/", "logs", kTemp, 10},
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index d897b8e..db681e0d 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -1569,6 +1569,33 @@ "chromeos-octopus-chrome": { "additional_compile_targets": [ "chromiumos_preflight" + ], + "gtest_tests": [ + { + "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.base_unittests.filter" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_type": "octopus", + "os": "ChromeOS", + "pool": "chrome.tests" + } + ], + "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "base_unittests", + "test_id_prefix": "ninja://base:base_unittests/", + "trigger_script": { + "script": "//testing/trigger_scripts/chromeos_device_trigger.py" + } + } ] }, "chromeos-reven-chrome": {
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 5e98dd5..d4836adf 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -14796,7 +14796,8 @@ "name": "shard #${SHARD_INDEX} logcats" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "webview_trichrome_cts_tests", "test_id_prefix": "ninja://android_webview/test:webview_trichrome_cts_tests/", @@ -19684,7 +19685,8 @@ "name": "shard #${SHARD_INDEX} logcats" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "webview_trichrome_64_cts_tests", "test_id_prefix": "ninja://android_webview/test:webview_trichrome_64_cts_tests/", @@ -50492,7 +50494,8 @@ "name": "shard #${SHARD_INDEX} logcats" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "webview_trichrome_cts_tests", "test_id_prefix": "ninja://android_webview/test:webview_trichrome_cts_tests/",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 6a1b756..badeb40 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -494,6 +494,15 @@ 'hard_timeout': 1200, }, }, + 'win11-blink-rel': { + 'swarming': { + 'hard_timeout': 1200, + }, + 'args': [ + '--target', + 'Release_x64', + ], + }, 'win11-blink-rel-dummy': { 'swarming': { 'hard_timeout': 1200,
diff --git a/testing/buildbot/tryserver.blink.json b/testing/buildbot/tryserver.blink.json index c7ce8e8..8ca4d81 100644 --- a/testing/buildbot/tryserver.blink.json +++ b/testing/buildbot/tryserver.blink.json
@@ -143,5 +143,48 @@ "test_id_prefix": "ninja://:blink_web_tests/" } ] + }, + "win11-blink-rel": { + "isolated_scripts": [ + { + "args": [ + "--num-retries=3", + "--fuzzy-diff", + "--git-revision=${got_revision}", + "--target", + "Release_x64" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_web_tests", + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "blink_web_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Windows-11-22000" + } + ], + "hard_timeout": 1200, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://:blink_web_tests/" + } + ] } }
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 8bc5236..422ec84 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -463,6 +463,7 @@ 'WEBVIEW_TRICHROME_FULL_CTS_TESTS': { 'identifier': 'full_mode', 'swarming': { + 'shards': 2, 'cipd_packages': [ { 'cipd_package': 'chromium/android_webview/tools/cts_archive',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 9b56e1a..491a4049 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -153,11 +153,9 @@ 'additional_compile_targets': [ 'chromiumos_preflight', ], - # TODO(crbug.com/1293222): Restore after octopus capacity has been - # returned. - #'test_suites': { - # 'gtest_tests': 'chromeos_device_only_gtests', - #}, + 'test_suites': { + 'gtest_tests': 'chromeos_device_only_gtests', + }, 'swarming': { 'dimension_sets': [ { @@ -6397,6 +6395,17 @@ 'isolated_scripts': 'chromium_webkit_isolated_scripts', }, }, + 'win11-blink-rel': { + 'mixins': [ + 'win11', + ], + 'swarming': { + 'hard_timeout': 900, + }, + 'test_suites': { + 'isolated_scripts': 'chromium_webkit_isolated_scripts', + }, + }, }, }, {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index de80293f..f039a8f 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -4146,6 +4146,28 @@ ] } ], + "HTMLParamElementUrlSupport": [ + { + "platforms": [ + "android", + "android_webview", + "android_weblayer", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Disabled_20220615", + "disable_features": [ + "HTMLParamElementUrlSupport" + ] + } + ] + } + ], "HTTP2": [ { "platforms": [ @@ -5198,6 +5220,26 @@ ] } ], + "LocalFrameRootPrePostFCPMetrics": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "LocalFrameRootPrePostFCPMetrics" + ] + } + ] + } + ], "LocationBarModelOptimizations": [ { "platforms": [ @@ -8986,6 +9028,21 @@ ] } ], + "Vp9kSVCHWDecoding": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "Vp9kSVCHWDecoding" + ] + } + ] + } + ], "Vulkan": [ { "platforms": [
diff --git a/third_party/androidx/build.gradle.template b/third_party/androidx/build.gradle.template index cfa496e..4db4d85 100644 --- a/third_party/androidx/build.gradle.template +++ b/third_party/androidx/build.gradle.template
@@ -88,6 +88,7 @@ compile 'androidx.legacy:legacy-support-v4:1.0.0' // testCompile targets have test_only = true. + androidTestCompile 'androidx.fragment:fragment-testing:{{androidx_dependency_version}}' androidTestCompile 'androidx.test:core:1.4.0-rc01' androidTestCompile 'androidx.test:monitor:1.4.0-rc01' androidTestCompile 'androidx.test:rules:1.2.0'
diff --git a/third_party/androidx/fetch_all_androidx.py b/third_party/androidx/fetch_all_androidx.py index 09145619..b4390aa 100755 --- a/third_party/androidx/fetch_all_androidx.py +++ b/third_party/androidx/fetch_all_androidx.py
@@ -32,7 +32,9 @@ os.path.join(_ANDROIDX_PATH, '..', 'android_deps', 'fetch_all.py')) # URL to BUILD_INFO in latest androidx snapshot. -_ANDROIDX_LATEST_SNAPSHOT_BUILD_INFO_URL = 'https://androidx.dev/snapshots/latest/artifacts/BUILD_INFO' +#_ANDROIDX_LATEST_SNAPSHOT_BUILD_INFO_URL = 'https://androidx.dev/snapshots/latest/artifacts/BUILD_INFO' +# Force latest to be last known good snapshot 8722497. See https://crbug.com/1336778 +_ANDROIDX_LATEST_SNAPSHOT_BUILD_INFO_URL = 'https://androidx.dev/snapshots/builds/8722497/artifacts/BUILD_INFO' # Snapshot repository URL with {{version}} placeholder. _SNAPSHOT_REPOSITORY_URL = 'https://androidx.dev/snapshots/builds/{{version}}/artifacts/repository'
diff --git a/third_party/blink/PRESUBMIT.py b/third_party/blink/PRESUBMIT.py index dff8fd97..6d23f9ce 100644 --- a/third_party/blink/PRESUBMIT.py +++ b/third_party/blink/PRESUBMIT.py
@@ -142,8 +142,7 @@ for f in input_api.AffectedFiles(): file_path = f.LocalPath() # Filter out changes in web_tests/. - if ('web_tests' + input_api.os_path.sep in file_path - and 'TestExpectations' not in file_path): + if 'web_tests' + input_api.os_path.sep in file_path: continue if '/PRESUBMIT' in file_path: continue
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 4436d33..1f951b669 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -65,7 +65,7 @@ // Used as a binding for controlling the runtime enabled blink feature // "FixedElementsDontOverscroll". This is needed for experimentation. const base::Feature kFixedElementsDontOverscroll{ - "FixedElementsDontOverscroll", base::FEATURE_ENABLED_BY_DEFAULT}; + "FixedElementsDontOverscroll", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kGMSCoreEmoji{"GMSCoreEmoji", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -1532,6 +1532,9 @@ const base::Feature kEarlyExitOnNoopClassOrStyleChange{ "EarlyExitOnNoopClassOrStyleChange", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kLocalFrameRootPrePostFCPMetrics{ + "LocalFrameRootPrePostFCPMetrics", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kDisableArrayBufferSizeLimitsForTesting{ "DisableArrayBufferSizeLimitsForTesting", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 6880d88..d2525a1 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -778,6 +778,10 @@ BLINK_COMMON_EXPORT extern const base::Feature kEarlyExitOnNoopClassOrStyleChange; +// Enables correct PreFCP and PostFCP metrics for non-main local frame roots. +// See https://crbug.com/1330675. +BLINK_COMMON_EXPORT extern const base::Feature kLocalFrameRootPrePostFCPMetrics; + // TODO(https://crbug.com/1201109): temporary flag to disable new ArrayBuffer // size limits, so that tests can be written against code receiving these // buffers. Remove when the bindings code instituting these limits is removed.
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index da95562d..5c39eae 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -177,6 +177,7 @@ BLINK_PLATFORM_EXPORT static void EnableWebGLDraftExtensions(bool); BLINK_PLATFORM_EXPORT static void EnableWebGLImageChromium(bool); BLINK_PLATFORM_EXPORT static void EnableWebGPU(bool); + BLINK_PLATFORM_EXPORT static void EnableWebGPUDeveloperFeatures(bool); BLINK_PLATFORM_EXPORT static void EnableWebNfc(bool); BLINK_PLATFORM_EXPORT static void EnableWebOTPAssertionFeaturePolicy(bool); BLINK_PLATFORM_EXPORT static void EnableWebShare(bool);
diff --git a/third_party/blink/renderer/bindings/bindings.gni b/third_party/blink/renderer/bindings/bindings.gni index 79a1419..712e987 100644 --- a/third_party/blink/renderer/bindings/bindings.gni +++ b/third_party/blink/renderer/bindings/bindings.gni
@@ -24,6 +24,7 @@ "core/v8/custom/v8_custom_xpath_ns_resolver.cc", "core/v8/custom/v8_custom_xpath_ns_resolver.h", "core/v8/custom/v8_dev_tools_host_custom.cc", + "core/v8/custom/v8_element_custom.cc", "core/v8/custom/v8_html_all_collection_custom.cc", "core/v8/custom/v8_html_plugin_element_custom.cc", "core/v8/custom/v8_promise_rejection_event_custom.cc",
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc new file mode 100644 index 0000000..39154bdb --- /dev/null +++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc
@@ -0,0 +1,68 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/bindings/core/v8/v8_element.h" + +#include "base/metrics/histogram_macros.h" +#include "base/timer/elapsed_timer.h" +#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h" +#include "third_party/blink/renderer/bindings/core/v8/idl_types.h" +#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" +#include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "v8/include/v8.h" + +namespace blink { + +// TODO(https://crbug.com/1335986): Custom setter is needed to collect metrics, +// and can be removed once metrics are captured. +// static +void V8Element::InnerHTMLAttributeSetterCustom( + v8::Local<v8::Value> html_value, + const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Isolate* isolate = info.GetIsolate(); + const ExceptionState::ContextType exception_state_context_type = + ExceptionContext::Context::kAttributeSet; + const char* const class_like_name = "Element"; + const char* const property_name = "innerHTML"; + ExceptionState exception_state(isolate, exception_state_context_type, + class_like_name, property_name); + + // [CEReactions] + CEReactionsScope ce_reactions_scope; + + v8::Local<v8::Object> v8_receiver = info.This(); + Element* blink_receiver = V8Element::ToWrappableUnsafe(v8_receiver); + ExecutionContext* execution_context_of_document_tree = + bindings::ExecutionContextFromV8Wrappable(blink_receiver); + const bool is_high_resolution_timer = base::TimeTicks::IsHighResolution(); + base::ElapsedTimer timer; + auto&& html = NativeValueTraits< + IDLStringStringContextTrustedHTMLTreatNullAsEmptyString>:: + NativeValue(isolate, html_value, exception_state, + execution_context_of_document_tree); + if (is_high_resolution_timer) { + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + "Blink.SetInnerHtml.ConversionTime", timer.Elapsed(), + base::Microseconds(1), base::Seconds(1), 100); + } + if (UNLIKELY(exception_state.HadException())) { + return; + } + timer = base::ElapsedTimer(); + blink_receiver->setInnerHTML(html, exception_state); + if (is_high_resolution_timer) { + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + "Blink.SetInnerHtml.ExecutionTime", timer.Elapsed(), + base::Microseconds(1), base::Seconds(10), 100); + UMA_HISTOGRAM_COUNTS_1M("Blink.SetInnerHtml.StringLength", html.length()); + } + if (UNLIKELY(exception_state.HadException())) { + return; + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_custom_font_data.h b/third_party/blink/renderer/core/css/css_custom_font_data.h index 56ea0ae..37d259a 100644 --- a/third_party/blink/renderer/core/css/css_custom_font_data.h +++ b/third_party/blink/renderer/core/css/css_custom_font_data.h
@@ -71,15 +71,9 @@ // TODO(Oilpan): consider moving (Custom)FontFace hierarchy to the heap, // thereby making this reference a Member<>. -#if defined(USE_PARALLEL_TEXT_SHAPING) - CrossThreadWeakPersistent<CSSFontFaceSource> font_face_source_; - std::atomic<FallbackVisibility> fallback_visibility_; - mutable std::atomic<bool> is_loading_; -#else WeakPersistent<CSSFontFaceSource> font_face_source_; FallbackVisibility fallback_visibility_; mutable bool is_loading_; -#endif }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_font_face.cc b/third_party/blink/renderer/core/css/css_font_face.cc index 8df72fd2d..91a3bdb 100644 --- a/third_party/blink/renderer/core/css/css_font_face.cc +++ b/third_party/blink/renderer/core/css/css_font_face.cc
@@ -36,93 +36,63 @@ #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/platform/fonts/font_description.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" namespace blink { -CSSFontFace::CSSFontFace(FontFace* font_face, Vector<UnicodeRange>& ranges) - : ranges_(base::AdoptRef(new UnicodeRangeSet(ranges))), - font_face_(font_face) -#if defined(USE_PARALLEL_TEXT_SHAPING) - , - task_runner_(font_face->GetExecutionContext()->GetTaskRunner( - TaskType::kFontLoading)) -#endif -{ - DCHECK(font_face_); -} - void CSSFontFace::AddSource(CSSFontFaceSource* source) { - AutoLockForParallelTextShaping guard(sources_lock_); sources_.push_back(source); } void CSSFontFace::AddSegmentedFontFace( CSSSegmentedFontFace* segmented_font_face) { - DCHECK(IsContextThread()); DCHECK(!segmented_font_faces_.Contains(segmented_font_face)); segmented_font_faces_.insert(segmented_font_face); } void CSSFontFace::RemoveSegmentedFontFace( CSSSegmentedFontFace* segmented_font_face) { - DCHECK(IsContextThread()); DCHECK(segmented_font_faces_.Contains(segmented_font_face)); segmented_font_faces_.erase(segmented_font_face); } void CSSFontFace::DidBeginLoad() { - DCHECK(IsContextThread()); if (LoadStatus() == FontFace::kUnloaded) SetLoadStatus(FontFace::kLoading); } bool CSSFontFace::FontLoaded(CSSFontFaceSource* source) { - DCHECK(IsContextThread()); - if (source != FrontSource()) + if (!IsValid() || source != sources_.front()) return false; if (LoadStatus() == FontFace::kLoading) { if (source->IsValid()) { SetLoadStatus(FontFace::kLoaded); } else if (source->IsInFailurePeriod()) { - { - AutoLockForParallelTextShaping guard(sources_lock_); - sources_.clear(); - } + sources_.clear(); SetLoadStatus(FontFace::kError); } else { - { - AutoLockForParallelTextShaping guard(sources_lock_); - if (!sources_.IsEmpty() && source == sources_.front()) - sources_.pop_front(); - } + sources_.pop_front(); Load(); } } - for (const auto& segmented_font_face : segmented_font_faces_) + for (CSSSegmentedFontFace* segmented_font_face : segmented_font_faces_) segmented_font_face->FontFaceInvalidated(); return true; } void CSSFontFace::SetDisplay(FontDisplay value) { - for (auto& source : GetSources()) { + for (auto& source : sources_) { source->SetDisplay(value); } } size_t CSSFontFace::ApproximateBlankCharacterCount() const { - auto* const source = FrontSource(); - if (!source || !source->IsInBlockPeriod()) + if (sources_.IsEmpty() || !sources_.front()->IsInBlockPeriod()) return 0; size_t approximate_character_count_ = 0; - for (const auto& segmented_font_face : segmented_font_faces_) { + for (CSSSegmentedFontFace* segmented_font_face : segmented_font_faces_) { approximate_character_count_ += segmented_font_face->ApproximateCharacterCount(); } @@ -130,18 +100,16 @@ } bool CSSFontFace::FallbackVisibilityChanged(RemoteFontFaceSource* source) { - if (source != FrontSource()) + if (!IsValid() || source != sources_.front()) return false; - for (const auto& segmented_font_face : segmented_font_faces_) + for (CSSSegmentedFontFace* segmented_font_face : segmented_font_faces_) segmented_font_face->FontFaceInvalidated(); return true; } scoped_refptr<SimpleFontData> CSSFontFace::GetFontData( const FontDescription& font_description) { - AutoLockForParallelTextShaping guard(sources_lock_); - - if (sources_.IsEmpty()) + if (!IsValid()) return nullptr; // Apply the 'size-adjust' descriptor before font selection. @@ -174,107 +142,63 @@ } // The active source may already be loading or loaded. Adjust our // FontFace status accordingly. - UpdateLoadStatusForActiveSource(source); + if (LoadStatus() == FontFace::kUnloaded && + (source->IsLoading() || source->IsLoaded())) + SetLoadStatus(FontFace::kLoading); + if (LoadStatus() == FontFace::kLoading && source->IsLoaded()) + SetLoadStatus(FontFace::kLoaded); return result; } sources_.pop_front(); } // We ran out of source. Set the FontFace status to "error" and return. - UpdateLoadStatusForNoSource(); - return nullptr; -} - -void CSSFontFace::UpdateLoadStatusForActiveSource(CSSFontFaceSource* source) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (auto task_runner = GetCrossThreadTaskRunner()) { - PostCrossThreadTask( - *task_runner, FROM_HERE, - CrossThreadBindOnce(&CSSFontFace::UpdateLoadStatusForActiveSource, - WrapCrossThreadPersistent(this), - WrapCrossThreadPersistent(source))); - return; - } - if (!font_face_->GetExecutionContext()) - return; - DCHECK(IsContextThread()); -#endif - if (LoadStatus() == FontFace::kUnloaded && - (source->IsLoading() || source->IsLoaded())) - SetLoadStatus(FontFace::kLoading); - if (LoadStatus() == FontFace::kLoading && source->IsLoaded()) - SetLoadStatus(FontFace::kLoaded); -} - -void CSSFontFace::UpdateLoadStatusForNoSource() { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (auto task_runner = GetCrossThreadTaskRunner()) { - PostCrossThreadTask( - *task_runner, FROM_HERE, - CrossThreadBindOnce(&CSSFontFace::UpdateLoadStatusForNoSource, - WrapCrossThreadPersistent(this))); - return; - } - if (!font_face_->GetExecutionContext()) - return; - DCHECK(IsContextThread()); -#endif if (LoadStatus() == FontFace::kUnloaded) SetLoadStatus(FontFace::kLoading); if (LoadStatus() == FontFace::kLoading) SetLoadStatus(FontFace::kError); + return nullptr; } bool CSSFontFace::MaybeLoadFont(const FontDescription& font_description, - const StringView& text) { - DCHECK(IsContextThread()); + const String& text) { // This is a fast path of loading web font in style phase. For speed, this // only checks if the first character of the text is included in the font's // unicode range. If this font is needed by subsequent characters, load is // kicked off in layout phase. - const UChar32 character = text.length() ? text.CodepointAt(0) : 0; - if (!ranges_->Contains(character)) - return false; - if (LoadStatus() != FontFace::kUnloaded) + UChar32 character = text.CharacterStartingAt(0); + if (ranges_->Contains(character)) { + if (LoadStatus() == FontFace::kUnloaded) + Load(font_description); return true; - LoadInternal(font_description); - return true; + } + return false; } bool CSSFontFace::MaybeLoadFont(const FontDescription& font_description, const FontDataForRangeSet& range_set) { - if (ranges_ != range_set.Ranges()) - return false; - if (LoadStatus() != FontFace::kUnloaded) + if (ranges_ == range_set.Ranges()) { + if (LoadStatus() == FontFace::kUnloaded) { + Load(font_description); + } return true; - LoadInternal(font_description); - return true; + } + return false; } void CSSFontFace::Load() { - DCHECK(IsContextThread()); FontDescription font_description; FontFamily font_family; font_family.SetFamily(font_face_->family(), FontFamily::Type::kFamilyName); font_description.SetFamily(font_family); - LoadInternal(font_description); + Load(font_description); } -void CSSFontFace::LoadInternal(const FontDescription& font_description) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (auto task_runner = GetCrossThreadTaskRunner()) { - PostCrossThreadTask( - *task_runner, FROM_HERE, - CrossThreadBindOnce(&CSSFontFace::LoadInternal, - WrapCrossThreadPersistent(this), font_description)); - return; - } -#endif +void CSSFontFace::Load(const FontDescription& font_description) { if (LoadStatus() == FontFace::kUnloaded) SetLoadStatus(FontFace::kLoading); DCHECK_EQ(LoadStatus(), FontFace::kLoading); - AutoLockForParallelTextShaping guard(sources_lock_); while (!sources_.IsEmpty()) { Member<CSSFontFaceSource>& source = sources_.front(); if (source->IsValid()) { @@ -297,7 +221,6 @@ } void CSSFontFace::SetLoadStatus(FontFace::LoadStatusType new_status) { - DCHECK(IsContextThread()); DCHECK(font_face_); if (new_status == FontFace::kError) font_face_->SetError(); @@ -324,7 +247,7 @@ if (LoadStatus() == FontFace::kLoaded) return false; bool changed = false; - for (CSSFontFaceSource* source : GetSources()) { + for (CSSFontFaceSource* source : sources_) { if (source->UpdatePeriod()) changed = true; } @@ -332,36 +255,9 @@ } void CSSFontFace::Trace(Visitor* visitor) const { - { - AutoLockForParallelTextShaping guard(sources_lock_); - visitor->Trace(sources_); - } + visitor->Trace(segmented_font_faces_); + visitor->Trace(sources_); visitor->Trace(font_face_); } -bool CSSFontFace::IsContextThread() const { -#if defined(USE_PARALLEL_TEXT_SHAPING) - return font_face_->GetExecutionContext()->IsContextThread(); -#else - return true; -#endif -} - -#if defined(USE_PARALLEL_TEXT_SHAPING) -scoped_refptr<base::SequencedTaskRunner> CSSFontFace::GetCrossThreadTaskRunner() - const { - auto* const context = font_face_->GetExecutionContext(); - if (!context || context->IsContextThread()) - return nullptr; - return task_runner_; -} -#endif - -HeapVector<Member<CSSFontFaceSource>> CSSFontFace::GetSources() const { - AutoLockForParallelTextShaping guard(sources_lock_); - HeapVector<Member<CSSFontFaceSource>> sources; - CopyToVector(sources_, sources); - return sources; -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_font_face.h b/third_party/blink/renderer/core/css/css_font_face.h index cf9bd7d1..97924a85 100644 --- a/third_party/blink/renderer/core/css/css_font_face.h +++ b/third_party/blink/renderer/core/css/css_font_face.h
@@ -32,7 +32,6 @@ #include "third_party/blink/renderer/core/css/css_segmented_font_face.h" #include "third_party/blink/renderer/core/css/font_face.h" #include "third_party/blink/renderer/core/css/font_face_source.h" -#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h" #include "third_party/blink/renderer/platform/fonts/unicode_range_set.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h" @@ -49,17 +48,16 @@ class CORE_EXPORT CSSFontFace final : public GarbageCollected<CSSFontFace> { public: - CSSFontFace(FontFace* font_face, Vector<UnicodeRange>& ranges); + CSSFontFace(FontFace* font_face, Vector<UnicodeRange>& ranges) + : ranges_(base::AdoptRef(new UnicodeRangeSet(ranges))), + font_face_(font_face) { + DCHECK(font_face_); + } CSSFontFace(const CSSFontFace&) = delete; CSSFontFace& operator=(const CSSFontFace&) = delete; // Front source is the first successfully loaded source. - const CSSFontFaceSource* FrontSource() const LOCKS_EXCLUDED(sources_lock_) { - AutoLockForParallelTextShaping guard(sources_lock_); - return sources_.IsEmpty() ? nullptr : sources_.front(); - } - CSSFontFaceSource* FrontSource() LOCKS_EXCLUDED(sources_lock_) { - AutoLockForParallelTextShaping guard(sources_lock_); + const CSSFontFaceSource* FrontSource() const { return sources_.IsEmpty() ? nullptr : sources_.front(); } FontFace* GetFontFace() const { return font_face_; } @@ -69,57 +67,42 @@ void AddSegmentedFontFace(CSSSegmentedFontFace*); void RemoveSegmentedFontFace(CSSSegmentedFontFace*); - bool IsValid() const { return FrontSource(); } + bool IsValid() const { return !sources_.IsEmpty(); } size_t ApproximateBlankCharacterCount() const; - void AddSource(CSSFontFaceSource*) LOCKS_EXCLUDED(sources_lock_); + void AddSource(CSSFontFaceSource*); void SetDisplay(FontDisplay); void DidBeginLoad(); bool FontLoaded(CSSFontFaceSource*); bool FallbackVisibilityChanged(RemoteFontFaceSource*); - scoped_refptr<SimpleFontData> GetFontData(const FontDescription&) - LOCKS_EXCLUDED(sources_lock_); + scoped_refptr<SimpleFontData> GetFontData(const FontDescription&); FontFace::LoadStatusType LoadStatus() const { return font_face_->LoadStatus(); } - bool MaybeLoadFont(const FontDescription&, const StringView&); + bool MaybeLoadFont(const FontDescription&, const String&); bool MaybeLoadFont(const FontDescription&, const FontDataForRangeSet&); void Load(); + void Load(const FontDescription&); // Recalculate the font loading timeline period for the font face. // https://drafts.csswg.org/css-fonts-4/#font-display-timeline // Returns true if the display period is changed. bool UpdatePeriod(); - bool HadBlankText() { - if (auto* source = FrontSource()) - return source->HadBlankText(); - return false; - } + bool HadBlankText() { return IsValid() && sources_.front()->HadBlankText(); } void Trace(Visitor*) const; private: - HeapVector<Member<CSSFontFaceSource>> GetSources() const - LOCKS_EXCLUDED(sources_lock_); - bool IsContextThread() const; - void LoadInternal(const FontDescription&) LOCKS_EXCLUDED(sources_lock_); void SetLoadStatus(FontFace::LoadStatusType); - void UpdateLoadStatusForActiveSource(CSSFontFaceSource*); - void UpdateLoadStatusForNoSource(); scoped_refptr<UnicodeRangeSet> ranges_; - HashSet<scoped_refptr<CSSSegmentedFontFace>> segmented_font_faces_; - mutable LockForParallelTextShaping sources_lock_; - HeapDeque<Member<CSSFontFaceSource>> sources_ GUARDED_BY(sources_lock_); - const Member<FontFace> font_face_; -#if defined(USE_PARALLEL_TEXT_SHAPING) - scoped_refptr<base::SequencedTaskRunner> GetCrossThreadTaskRunner() const; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; -#endif + HeapHashSet<Member<CSSSegmentedFontFace>> segmented_font_faces_; + HeapDeque<Member<CSSFontFaceSource>> sources_; + Member<FontFace> font_face_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_font_selector.cc b/third_party/blink/renderer/core/css/css_font_selector.cc index fb149ec..c4cb3ff3f 100644 --- a/third_party/blink/renderer/core/css/css_font_selector.cc +++ b/third_party/blink/renderer/core/css/css_font_selector.cc
@@ -40,11 +40,7 @@ namespace blink { CSSFontSelector::CSSFontSelector(const TreeScope& tree_scope) - : CSSFontSelectorBase( - tree_scope.GetDocument().GetExecutionContext()->GetTaskRunner( - TaskType::kInternalDefault)), - tree_scope_(&tree_scope) { - DCHECK(tree_scope.GetDocument().GetExecutionContext()->IsContextThread()); + : tree_scope_(&tree_scope) { DCHECK(tree_scope.GetDocument().GetFrame()); generic_font_family_settings_ = tree_scope.GetDocument() .GetFrame() @@ -61,8 +57,7 @@ CSSFontSelector::~CSSFontSelector() = default; UseCounter* CSSFontSelector::GetUseCounter() const { - auto* const context = GetExecutionContext(); - return context && context->IsContextThread() ? context : nullptr; + return GetExecutionContext(); } void CSSFontSelector::RegisterForInvalidationCallbacks( @@ -129,7 +124,8 @@ } if (!font_family.FamilyIsGeneric()) { - if (auto face = font_face_cache_->Get(request_description, family_name)) { + if (CSSSegmentedFontFace* face = + font_face_cache_->Get(request_description, family_name)) { ReportWebFontFamily(family_name); return face->GetFontData(request_description); } @@ -152,7 +148,7 @@ FontCache::Get().GetFontData(request_description, settings_family_name); ReportFontLookupByUniqueOrFamilyName(settings_family_name, - request_description, font_data); + request_description, font_data.get()); return font_data; } @@ -169,10 +165,6 @@ return GetDocument().GetFontMatchingMetrics(); } -bool CSSFontSelector::IsAlive() const { - return tree_scope_; -} - void CSSFontSelector::Trace(Visitor* visitor) const { visitor->Trace(tree_scope_); visitor->Trace(clients_);
diff --git a/third_party/blink/renderer/core/css/css_font_selector.h b/third_party/blink/renderer/core/css/css_font_selector.h index c568a0e..74b7ee2 100644 --- a/third_party/blink/renderer/core/css/css_font_selector.h +++ b/third_party/blink/renderer/core/css/css_font_selector.h
@@ -82,7 +82,6 @@ void DispatchInvalidationCallbacks(FontInvalidationReason); // `CSSFontSelectorBase` overrides - bool IsAlive() const override; FontMatchingMetrics* GetFontMatchingMetrics() const override; UseCounter* GetUseCounter() const override;
diff --git a/third_party/blink/renderer/core/css/css_font_selector_base.cc b/third_party/blink/renderer/core/css/css_font_selector_base.cc index 2fa1fe9..aeec9b2 100644 --- a/third_party/blink/renderer/core/css/css_font_selector_base.cc +++ b/third_party/blink/renderer/core/css/css_font_selector_base.cc
@@ -16,58 +16,17 @@ namespace blink { -CSSFontSelectorBase::CSSFontSelectorBase( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) -#if defined(USE_PARALLEL_TEXT_SHAPING) - : task_runner_(task_runner) -#endif -{ - DCHECK(IsContextThread()); -} - void CSSFontSelectorBase::CountUse(WebFeature feature) const { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (IsContextThread()) - return UseCounter::Count(GetUseCounter(), feature); - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce(&CSSFontSelectorBase::CountUse, - WrapCrossThreadPersistent(this), feature)); -#endif + return UseCounter::Count(GetUseCounter(), feature); } AtomicString CSSFontSelectorBase::FamilyNameFromSettings( const FontDescription& font_description, const FontFamily& generic_family_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsContextThread()) { - if (IsWebkitBodyFamily(font_description)) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::CountUse, WrapCrossThreadPersistent(this), - WebFeature::kFontSelectorCSSFontFamilyWebKitPrefixBody)); - } - return FontSelector::FamilyNameFromSettings(generic_font_family_settings_, - font_description, - generic_family_name, nullptr); - } -#endif return FontSelector::FamilyNameFromSettings( generic_font_family_settings_, font_description, generic_family_name, GetUseCounter()); } - -bool CSSFontSelectorBase::IsContextThread() const { -#if defined(USE_PARALLEL_TEXT_SHAPING) - return task_runner_->RunsTasksInCurrentSequence(); -#else - return true; -#endif -} - bool CSSFontSelectorBase::IsPlatformFamilyMatchAvailable( const FontDescription& font_description, const FontFamily& passed_family) { @@ -81,19 +40,6 @@ void CSSFontSelectorBase::ReportEmojiSegmentGlyphCoverage( unsigned num_clusters, unsigned num_broken_clusters) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::ReportEmojiSegmentGlyphCoverage, - WrapCrossThreadPersistent(this), num_clusters, - num_broken_clusters)); - return; - } -#endif GetFontMatchingMetrics()->ReportEmojiSegmentGlyphCoverage( num_clusters, num_broken_clusters); } @@ -103,19 +49,6 @@ UScriptCode script, FontDescription::GenericFamilyType generic_family_type, const AtomicString& resulting_font_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::ReportFontFamilyLookupByGenericFamily, - WrapCrossThreadPersistent(this), generic_font_family_name, script, - generic_family_type, resulting_font_name)); - return; - } -#endif GetFontMatchingMetrics()->ReportFontFamilyLookupByGenericFamily( generic_font_family_name, script, generic_family_type, resulting_font_name); @@ -123,153 +56,56 @@ void CSSFontSelectorBase::ReportSuccessfulFontFamilyMatch( const AtomicString& font_family_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce(&CSSFontSelectorBase::ReportFailedFontFamilyMatch, - WrapCrossThreadPersistent(this), font_family_name)); - return; - } -#endif GetFontMatchingMetrics()->ReportSuccessfulFontFamilyMatch(font_family_name); } void CSSFontSelectorBase::ReportFailedFontFamilyMatch( const AtomicString& font_family_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce(&CSSFontSelectorBase::ReportFailedFontFamilyMatch, - WrapCrossThreadPersistent(this), font_family_name)); - return; - } -#endif GetFontMatchingMetrics()->ReportFailedFontFamilyMatch(font_family_name); } void CSSFontSelectorBase::ReportSuccessfulLocalFontMatch( const AtomicString& font_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::ReportSuccessfulLocalFontMatch, - WrapCrossThreadPersistent(this), font_name)); - return; - } -#endif GetFontMatchingMetrics()->ReportSuccessfulLocalFontMatch(font_name); } void CSSFontSelectorBase::ReportFailedLocalFontMatch( const AtomicString& font_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce(&CSSFontSelectorBase::ReportFailedLocalFontMatch, - WrapCrossThreadPersistent(this), font_name)); - return; - } -#endif GetFontMatchingMetrics()->ReportFailedLocalFontMatch(font_name); } void CSSFontSelectorBase::ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::ReportFontLookupByUniqueOrFamilyName, - WrapCrossThreadPersistent(this), name, font_description, - resulting_font_data)); - return; - } -#endif + SimpleFontData* resulting_font_data) { GetFontMatchingMetrics()->ReportFontLookupByUniqueOrFamilyName( - name, font_description, resulting_font_data.get()); + name, font_description, resulting_font_data); } void CSSFontSelectorBase::ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data, + SimpleFontData* resulting_font_data, bool is_loading_fallback) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::ReportFontLookupByUniqueNameOnly, - WrapCrossThreadPersistent(this), name, font_description, - resulting_font_data, is_loading_fallback)); - return; - } -#endif GetFontMatchingMetrics()->ReportFontLookupByUniqueNameOnly( - name, font_description, resulting_font_data.get(), is_loading_fallback); + name, font_description, resulting_font_data, is_loading_fallback); } void CSSFontSelectorBase::ReportFontLookupByFallbackCharacter( UChar32 fallback_character, FontFallbackPriority fallback_priority, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::ReportFontLookupByFallbackCharacter, - WrapCrossThreadPersistent(this), fallback_character, - fallback_priority, font_description, resulting_font_data)); - return; - } -#endif + SimpleFontData* resulting_font_data) { GetFontMatchingMetrics()->ReportFontLookupByFallbackCharacter( fallback_character, fallback_priority, font_description, - resulting_font_data.get()); + resulting_font_data); } void CSSFontSelectorBase::ReportLastResortFallbackFontLookup( const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce( - &CSSFontSelectorBase::ReportLastResortFallbackFontLookup, - WrapCrossThreadPersistent(this), font_description, - resulting_font_data)); - return; - } -#endif + SimpleFontData* resulting_font_data) { GetFontMatchingMetrics()->ReportLastResortFallbackFontLookup( - font_description, resulting_font_data.get()); + font_description, resulting_font_data); } void CSSFontSelectorBase::ReportNotDefGlyph() const { @@ -278,33 +114,11 @@ void CSSFontSelectorBase::ReportSystemFontFamily( const AtomicString& font_family_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce(&CSSFontSelectorBase::ReportSystemFontFamily, - WrapCrossThreadPersistent(this), font_family_name)); - return; - } -#endif GetFontMatchingMetrics()->ReportSystemFontFamily(font_family_name); } void CSSFontSelectorBase::ReportWebFontFamily( const AtomicString& font_family_name) { -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!IsAlive()) - return; - if (!IsContextThread()) { - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce(&CSSFontSelectorBase::ReportWebFontFamily, - WrapCrossThreadPersistent(this), font_family_name)); - return; - } -#endif GetFontMatchingMetrics()->ReportWebFontFamily(font_family_name); } @@ -313,7 +127,7 @@ const FontFamily& family, const String& text) { if (family.FamilyIsGeneric()) { - if (family.IsPrewarmed() || UNLIKELY(family.FamilyName().IsEmpty())) + if (family.IsPrewarmed()) return; family.SetIsPrewarmed(); // |FamilyNameFromSettings| has a visible impact on the load performance. @@ -321,13 +135,9 @@ // only when the |Font| is shared across elements, and therefore it can't // help when e.g., the font size is different, check once more if this // generic family is already prewarmed. - { - AutoLockForParallelTextShaping guard(prewarmed_generic_families_lock_); - const auto result = - prewarmed_generic_families_.insert(family.FamilyName()); - if (!result.is_new_entry) - return; - } + const auto result = prewarmed_generic_families_.insert(family.FamilyName()); + if (!result.is_new_entry) + return; const AtomicString& family_name = FamilyNameFromSettings(font_description, family); if (!family_name.IsEmpty()) @@ -335,13 +145,13 @@ return; } - if (auto face = + if (CSSSegmentedFontFace* face = font_face_cache_->Get(font_description, family.FamilyName())) { face->WillUseFontData(font_description, text); return; } - if (family.IsPrewarmed() || UNLIKELY(family.FamilyName().IsEmpty())) + if (family.IsPrewarmed()) return; family.SetIsPrewarmed(); FontCache::PrewarmFamily(family.FamilyName()); @@ -350,7 +160,8 @@ void CSSFontSelectorBase::WillUseRange(const FontDescription& font_description, const AtomicString& family, const FontDataForRangeSet& range_set) { - if (auto face = font_face_cache_->Get(font_description, family)) + if (CSSSegmentedFontFace* face = + font_face_cache_->Get(font_description, family)) face->WillUseRange(font_description, range_set); }
diff --git a/third_party/blink/renderer/core/css/css_font_selector_base.h b/third_party/blink/renderer/core/css/css_font_selector_base.h index 5c4047d0..00eea28 100644 --- a/third_party/blink/renderer/core/css/css_font_selector_base.h +++ b/third_party/blink/renderer/core/css/css_font_selector_base.h
@@ -9,7 +9,6 @@ #include "third_party/blink/renderer/core/css/font_face_cache.h" #include "third_party/blink/renderer/platform/fonts/font_selector.h" #include "third_party/blink/renderer/platform/fonts/generic_font_family_settings.h" -#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/wtf/forward.h" namespace blink { @@ -47,23 +46,23 @@ void ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) override; + SimpleFontData* resulting_font_data) override; void ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data, + SimpleFontData* resulting_font_data, bool is_loading_fallback = false) override; void ReportFontLookupByFallbackCharacter( UChar32 fallback_character, FontFallbackPriority fallback_priority, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) override; + SimpleFontData* resulting_font_data) override; void ReportLastResortFallbackFontLookup( const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) override; + SimpleFontData* resulting_font_data) override; void ReportFontFamilyLookupByGenericFamily( const AtomicString& generic_font_family_name, @@ -76,18 +75,9 @@ void ReportEmojiSegmentGlyphCoverage(unsigned num_clusters, unsigned num_broken_clusters) override; - bool IsContextThread() const override; - void Trace(Visitor*) const override; protected: - explicit CSSFontSelectorBase( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - - // TODO(crbug.com/383860): We should get rid of `IsAlive()` once lifetime - // issue of `CSSFontSelector` is solved. It will be alive after `TreeScope` - // is dead. - virtual bool IsAlive() const { return true; } virtual FontMatchingMetrics* GetFontMatchingMetrics() const = 0; virtual UseCounter* GetUseCounter() const = 0; @@ -99,12 +89,7 @@ Member<FontFaceCache> font_face_cache_; GenericFontFamilySettings generic_font_family_settings_; - LockForParallelTextShaping prewarmed_generic_families_lock_; - HashSet<AtomicString> prewarmed_generic_families_ - GUARDED_BY(prewarmed_generic_families_lock_); -#if defined(USE_PARALLEL_TEXT_SHAPING) - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; -#endif + HashSet<AtomicString> prewarmed_generic_families_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_segmented_font_face.cc b/third_party/blink/renderer/core/css/css_segmented_font_face.cc index b859dbe..eec016f9 100644 --- a/third_party/blink/renderer/core/css/css_segmented_font_face.cc +++ b/third_party/blink/renderer/core/css/css_segmented_font_face.cc
@@ -37,7 +37,6 @@ #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h" #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" -#include "third_party/blink/renderer/platform/heap/thread_state.h" // See comment below in CSSSegmentedFontFace::GetFontData - the cache from // CSSSegmentedFontFace (which represents a group of @font-face declarations @@ -52,23 +51,21 @@ namespace blink { // static -scoped_refptr<CSSSegmentedFontFace> CSSSegmentedFontFace::Create( +CSSSegmentedFontFace* CSSSegmentedFontFace::Create( FontSelectionCapabilities capabilities) { - return base::AdoptRef(new CSSSegmentedFontFace(capabilities)); + return MakeGarbageCollected<CSSSegmentedFontFace>(capabilities); } CSSSegmentedFontFace::CSSSegmentedFontFace( FontSelectionCapabilities font_selection_capabilities) : font_selection_capabilities_(font_selection_capabilities), font_data_table_(kFontDataTableMaxSize), - approximate_character_count_(0) { - DCHECK(ThreadState::Current()->GetIsolate()); -} + font_faces_(MakeGarbageCollected<FontFaceList>()), + approximate_character_count_(0) {} CSSSegmentedFontFace::~CSSSegmentedFontFace() = default; void CSSSegmentedFontFace::PruneTable() { - lock_.AssertAcquired(); // Make sure the glyph page tree prunes out all uses of this custom font. if (!font_data_table_.size()) return; @@ -77,9 +74,8 @@ } bool CSSSegmentedFontFace::IsValid() const { - lock_.AssertAcquired(); // Valid if at least one font face is valid. - return font_faces_.ForEachUntilTrue( + return font_faces_->ForEachUntilTrue( WTF::BindRepeating([](Member<FontFace> font_face) -> bool { if (font_face->CssFontFace()->IsValid()) return true; @@ -88,21 +84,18 @@ } void CSSSegmentedFontFace::FontFaceInvalidated() { - AutoLockForParallelTextShaping guard(lock_); PruneTable(); } void CSSSegmentedFontFace::AddFontFace(FontFace* font_face, bool css_connected) { - AutoLockForParallelTextShaping guard(lock_); PruneTable(); font_face->CssFontFace()->AddSegmentedFontFace(this); - font_faces_.Insert(font_face, css_connected); + font_faces_->Insert(font_face, css_connected); } void CSSSegmentedFontFace::RemoveFontFace(FontFace* font_face) { - AutoLockForParallelTextShaping guard(lock_); - if (!font_faces_.Erase(font_face)) + if (!font_faces_->Erase(font_face)) return; PruneTable(); @@ -111,7 +104,6 @@ scoped_refptr<FontData> CSSSegmentedFontFace::GetFontData( const FontDescription& font_description) { - AutoLockForParallelTextShaping guard(lock_); if (!IsValid()) return nullptr; @@ -152,7 +144,7 @@ font_selection_request.slope >= ItalicSlopeValue() && font_description.SyntheticItalicAllowed()); - font_faces_.ForEachReverse(WTF::BindRepeating( + font_faces_->ForEachReverse(WTF::BindRepeating( [](const FontDescription& requested_font_description, scoped_refptr<SegmentedFontData> created_font_data, Member<FontFace> font_face) { @@ -189,12 +181,10 @@ void CSSSegmentedFontFace::WillUseFontData( const FontDescription& font_description, - const StringView& text) { - // This function is called from main thread or worker thread. - AutoLockForParallelTextShaping guard(lock_); + const String& text) { approximate_character_count_ += text.length(); - font_faces_.ForEachReverseUntilTrue(WTF::BindRepeating( - [](const FontDescription& font_description, const StringView& text, + font_faces_->ForEachReverseUntilTrue(WTF::BindRepeating( + [](const FontDescription& font_description, const String& text, Member<FontFace> font_face) -> bool { if (font_face->LoadStatus() != FontFace::kUnloaded) return true; @@ -208,11 +198,10 @@ void CSSSegmentedFontFace::WillUseRange( const blink::FontDescription& font_description, const blink::FontDataForRangeSet& range_set) { - AutoLockForParallelTextShaping guard(lock_); // Iterating backwards since later defined unicode-range faces override // previously defined ones, according to the CSS3 fonts module. // https://drafts.csswg.org/css-fonts/#composite-fonts - font_faces_.ForEachReverseUntilTrue(WTF::BindRepeating( + font_faces_->ForEachReverseUntilTrue(WTF::BindRepeating( [](const blink::FontDescription& font_description, const blink::FontDataForRangeSet& range_set, Member<FontFace> font_face) -> bool { @@ -225,8 +214,7 @@ } bool CSSSegmentedFontFace::CheckFont(const String& text) const { - AutoLockForParallelTextShaping guard(lock_); - return font_faces_.ForEachUntilFalse(WTF::BindRepeating( + return font_faces_->ForEachUntilFalse(WTF::BindRepeating( [](const String& text, Member<FontFace> font_face) -> bool { if (font_face->LoadStatus() != FontFace::kLoaded && font_face->CssFontFace()->Ranges()->IntersectsWith(text)) @@ -238,10 +226,9 @@ void CSSSegmentedFontFace::Match(const String& text, HeapVector<Member<FontFace>>* faces) const { - AutoLockForParallelTextShaping guard(lock_); // WTF::BindRepeating requires WrapPersistent around |faces|, which is fine, // because the wrap's lifetime is contained to this function. - font_faces_.ForEach(WTF::BindRepeating( + font_faces_->ForEach(WTF::BindRepeating( [](const String& text, HeapVector<Member<FontFace>>* faces, Member<FontFace> font_face) { if (font_face->CssFontFace()->Ranges()->IntersectsWith(text)) @@ -251,7 +238,6 @@ } void CSSSegmentedFontFace::Trace(Visitor* visitor) const { - AutoLockForParallelTextShaping guard(lock_); visitor->Trace(font_faces_); }
diff --git a/third_party/blink/renderer/core/css/css_segmented_font_face.h b/third_party/blink/renderer/core/css/css_segmented_font_face.h index 019ef6f..f74aad11 100644 --- a/third_party/blink/renderer/core/css/css_segmented_font_face.h +++ b/third_party/blink/renderer/core/css/css_segmented_font_face.h
@@ -27,10 +27,8 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_SEGMENTED_FONT_FACE_H_ #include "base/callback.h" -#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/fonts/font_cache_key.h" #include "third_party/blink/renderer/platform/fonts/font_selection_types.h" -#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/fonts/segmented_font_data.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_linked_hash_set.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" @@ -38,7 +36,6 @@ #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/lru_cache.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -54,18 +51,8 @@ // Note however, |Insert| has to be instructed which sub-list to insert it to. // Iterating over the combined set, behaves as if all non-CSS-connected // FontFaces were stored after the CSS-connected ones. -class FontFaceList final { - DISALLOW_NEW(); - - // TODO(yosin): Once Oilpan allowed mixed thread heap, we should make - // |FontFaceList| as |HeapLinkedHashSet<T>|. - class FontFaceListPart : public LinkedHashSet<Member<FontFace>> { - public: - void Trace(Visitor* visitor) const { - for (auto& entry : *this) - visitor->Trace(*entry); - } - }; +class FontFaceList : public GarbageCollected<FontFaceList> { + using FontFaceListPart = HeapLinkedHashSet<Member<FontFace>>; public: bool IsEmpty() const; @@ -99,13 +86,12 @@ FontFaceListPart non_css_connected_face_; }; -// TODO(yosin): Once Oilpan allowed mixed thread heap, we should make -// |CSSSegmentedFontFace| as |GarbageCollected<T>|. -class CORE_EXPORT CSSSegmentedFontFace final - : public RefCountedWillBeThreadSafeForParallelTextShaping< - CSSSegmentedFontFace> { +class CSSSegmentedFontFace final + : public GarbageCollected<CSSSegmentedFontFace> { public: - static scoped_refptr<CSSSegmentedFontFace> Create(FontSelectionCapabilities); + static CSSSegmentedFontFace* Create(FontSelectionCapabilities); + + explicit CSSSegmentedFontFace(FontSelectionCapabilities); ~CSSSegmentedFontFace(); FontSelectionCapabilities GetFontSelectionCapabilities() const { @@ -114,25 +100,18 @@ // Called when status of a FontFace has changed (e.g. loaded or timed out) // so cached FontData must be discarded. - void FontFaceInvalidated() LOCKS_EXCLUDED(lock_); + void FontFaceInvalidated(); - void AddFontFace(FontFace*, bool css_connected) LOCKS_EXCLUDED(lock_); - void RemoveFontFace(FontFace*) LOCKS_EXCLUDED(lock_); - bool IsEmpty() const LOCKS_EXCLUDED(lock_) { - AutoLockForParallelTextShaping guard(lock_); - return font_faces_.IsEmpty(); - } + void AddFontFace(FontFace*, bool css_connected); + void RemoveFontFace(FontFace*); + bool IsEmpty() const { return font_faces_->IsEmpty(); } - scoped_refptr<FontData> GetFontData(const FontDescription&) - LOCKS_EXCLUDED(lock_); + scoped_refptr<FontData> GetFontData(const FontDescription&); - bool CheckFont(const String&) const LOCKS_EXCLUDED(lock_); - void Match(const String&, HeapVector<Member<FontFace>>*) const - LOCKS_EXCLUDED(lock_); - void WillUseFontData(const FontDescription&, const StringView& text) - LOCKS_EXCLUDED(lock_); - void WillUseRange(const FontDescription&, const blink::FontDataForRangeSet&) - LOCKS_EXCLUDED(lock_); + bool CheckFont(const String&) const; + void Match(const String&, HeapVector<Member<FontFace>>*) const; + void WillUseFontData(const FontDescription&, const String& text); + void WillUseRange(const FontDescription&, const blink::FontDataForRangeSet&); size_t ApproximateCharacterCount() const { return approximate_character_count_; } @@ -140,19 +119,16 @@ void Trace(Visitor*) const; private: - explicit CSSSegmentedFontFace(FontSelectionCapabilities); - - void PruneTable() EXCLUSIVE_LOCKS_REQUIRED(lock_); - bool IsValid() const EXCLUSIVE_LOCKS_REQUIRED(lock_); + void PruneTable(); + bool IsValid() const; FontSelectionCapabilities font_selection_capabilities_; - mutable LockForParallelTextShaping lock_; - WTF::LruCache<FontCacheKey, scoped_refptr<SegmentedFontData>> font_data_table_ - GUARDED_BY(lock_); + WTF::LruCache<FontCacheKey, scoped_refptr<SegmentedFontData>> + font_data_table_; // All non-CSS-connected FontFaces are stored after the CSS-connected ones. - FontFaceList font_faces_ GUARDED_BY(lock_); + Member<FontFaceList> font_faces_; // Approximate number of characters styled with this CSSSegmentedFontFace. // LayoutText::StyleDidChange() increments this on the first
diff --git a/third_party/blink/renderer/core/css/font_face.cc b/third_party/blink/renderer/core/css/font_face.cc index a8c4763..b4a0cc4b 100644 --- a/third_party/blink/renderer/core/css/font_face.cc +++ b/third_party/blink/renderer/core/css/font_face.cc
@@ -872,8 +872,7 @@ RemoteFontFaceSource* source = MakeGarbageCollected<RemoteFontFaceSource>( css_font_face_, font_selector, - CSSValueToFontDisplay(display_.Get()), - GetExecutionContext()->GetTaskRunner(TaskType::kFontLoading)); + CSSValueToFontDisplay(display_.Get())); item.Fetch(context, source); css_font_face_->AddSource(source); }
diff --git a/third_party/blink/renderer/core/css/font_face_cache.cc b/third_party/blink/renderer/core/css/font_face_cache.cc index 435fd72..068c9b0 100644 --- a/third_party/blink/renderer/core/css/font_face_cache.cc +++ b/third_party/blink/renderer/core/css/font_face_cache.cc
@@ -52,9 +52,9 @@ bool css_connected) { const auto result = map_.insert(font_face->family(), nullptr); if (result.is_new_entry) - result.stored_value->value = base::MakeRefCounted<CapabilitiesSet>(); + result.stored_value->value = MakeGarbageCollected<CapabilitiesSet>(); - scoped_refptr<CapabilitiesSet> family_faces = result.stored_value->value; + CapabilitiesSet* family_faces = result.stored_value->value; family_faces->AddFontFace(font_face, css_connected); } @@ -73,7 +73,6 @@ void FontFaceCache::FontSelectionQueryCache::Remove( const AtomicString& family) { - AutoLockForParallelTextShaping guard(lock_); map_.erase(family); } @@ -104,7 +103,7 @@ if (it == map_.end()) return false; - scoped_refptr<CapabilitiesSet> family_segmented_faces = it->value; + CapabilitiesSet* family_segmented_faces = it->value; if (family_segmented_faces->RemoveFontFace(font_face)) map_.erase(it); return true; @@ -127,7 +126,7 @@ if (it == map_.end()) return false; - scoped_refptr<CSSSegmentedFontFace> segmented_font_face = it->value; + CSSSegmentedFontFace* segmented_font_face = it->value; segmented_font_face->RemoveFontFace(font_face); if (!segmented_font_face->IsEmpty()) return false; @@ -156,7 +155,6 @@ } void FontFaceCache::FontSelectionQueryCache::Clear() { - AutoLockForParallelTextShaping guard(lock_); map_.clear(); } @@ -167,21 +165,21 @@ version_ = g_version.GetNext(); } -scoped_refptr<FontFaceCache::CapabilitiesSet> -FontFaceCache::SegmentedFacesByFamily::Find(const AtomicString& family) const { +FontFaceCache::CapabilitiesSet* FontFaceCache::SegmentedFacesByFamily::Find( + const AtomicString& family) const { const auto it = map_.find(family); if (it == map_.end() || it->value->IsEmpty()) return nullptr; return it->value; } -scoped_refptr<CSSSegmentedFontFace> FontFaceCache::Get( +CSSSegmentedFontFace* FontFaceCache::Get( const FontDescription& font_description, const AtomicString& family) { if (family.IsEmpty()) return nullptr; - scoped_refptr<CapabilitiesSet> family_faces = segmented_faces_.Find(family); + CapabilitiesSet* family_faces = segmented_faces_.Find(family); if (!family_faces) return nullptr; @@ -189,22 +187,19 @@ font_description.GetFontSelectionRequest(), family, family_faces); } -scoped_refptr<CSSSegmentedFontFace> -FontFaceCache::FontSelectionQueryCache::GetOrCreate( +CSSSegmentedFontFace* FontFaceCache::FontSelectionQueryCache::GetOrCreate( const FontSelectionRequest& request, const AtomicString& family, - scoped_refptr<CapabilitiesSet> family_faces) { - AutoLockForParallelTextShaping guard(lock_); + CapabilitiesSet* family_faces) { const auto result = map_.insert(family, nullptr); if (result.is_new_entry) { result.stored_value->value = - base::MakeRefCounted<FontSelectionQueryResult>(); + MakeGarbageCollected<FontSelectionQueryResult>(); } return result.stored_value->value->GetOrCreate(request, *family_faces); } -scoped_refptr<CSSSegmentedFontFace> -FontFaceCache::FontSelectionQueryResult::GetOrCreate( +CSSSegmentedFontFace* FontFaceCache::FontSelectionQueryResult::GetOrCreate( const FontSelectionRequest& request, const CapabilitiesSet& family_faces) { const auto face_entry = map_.insert(request, nullptr); @@ -227,7 +222,7 @@ all_faces_boundaries); for (const auto& item : family_faces) { const FontSelectionCapabilities& candidate_key = item.key; - scoped_refptr<CSSSegmentedFontFace> candidate_value = item.value; + CSSSegmentedFontFace* candidate_value = item.value; if (!face_entry.stored_value->value || font_selection_algorithm.IsBetterMatchForRequest( candidate_key, @@ -257,24 +252,19 @@ } void FontFaceCache::CapabilitiesSet::Trace(Visitor* visitor) const { - for (auto& entry : map_) - visitor->Trace(*entry.value); + visitor->Trace(map_); } void FontFaceCache::FontSelectionQueryCache::Trace(Visitor* visitor) const { - AutoLockForParallelTextShaping guard(lock_); - for (auto& entry : map_) - visitor->Trace(*entry.value); + visitor->Trace(map_); } void FontFaceCache::FontSelectionQueryResult::Trace(Visitor* visitor) const { - for (auto& entry : map_) - visitor->Trace(*entry.value); + visitor->Trace(map_); } void FontFaceCache::SegmentedFacesByFamily::Trace(Visitor* visitor) const { - for (auto& entry : map_) - visitor->Trace(*entry.value); + visitor->Trace(map_); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/font_face_cache.h b/third_party/blink/renderer/core/css/font_face_cache.h index f7f381a..927a5da 100644 --- a/third_party/blink/renderer/core/css/font_face_cache.h +++ b/third_party/blink/renderer/core/css/font_face_cache.h
@@ -32,13 +32,11 @@ #include "third_party/blink/renderer/core/css/font_face.h" #include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/platform/fonts/font_selection_types.h" -#include "third_party/blink/renderer/platform/fonts/lock_for_parallel_text_shaping.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/wtf/forward.h" #include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" #include "third_party/blink/renderer/platform/wtf/text/string_hash.h" -#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" namespace blink { @@ -60,8 +58,7 @@ // FIXME: It's sort of weird that add/remove uses StyleRuleFontFace* as key, // but this function uses FontDescription/family pair. - scoped_refptr<CSSSegmentedFontFace> Get(const FontDescription&, - const AtomicString& family); + CSSSegmentedFontFace* Get(const FontDescription&, const AtomicString& family); const HeapLinkedHashSet<Member<FontFace>>& CssConnectedFontFaces() const { return css_connected_font_faces_; @@ -83,11 +80,9 @@ // A second lookup table caches the previously received FontSelectionRequest // queries, which is: HeapHashMap <String, HeapHashMap<FontSelectionRequest, // CSSSegmentedFontFace>> - class CapabilitiesSet final - : public RefCountedWillBeThreadSafeForParallelTextShaping< - CapabilitiesSet> { + class CapabilitiesSet final : public GarbageCollected<CapabilitiesSet> { using Map = - HashMap<FontSelectionCapabilities, scoped_refptr<CSSSegmentedFontFace>>; + HeapHashMap<FontSelectionCapabilities, Member<CSSSegmentedFontFace>>; public: Map::const_iterator begin() const { return map_.begin(); } @@ -97,7 +92,7 @@ void AddFontFace(FontFace* font_face, bool css_connected); bool IsEmpty() const { return map_.IsEmpty(); } - // Returns true if associated `CSSSegmentedFontFace` is empty. + // Returns true if associated |CSSSegmentedFontFace| is empty. bool RemoveFontFace(FontFace* font_face); void Trace(Visitor*) const; @@ -106,19 +101,18 @@ Map map_; }; - // The map from `FontSelectionRequestKey` to `CSSSegmentedFontFace`. + // The map from |FontSelectionRequestKey| to |CSSSegmentedFontFace|. class FontSelectionQueryResult final - : public RefCountedWillBeThreadSafeForParallelTextShaping< - FontSelectionQueryResult> { - using Map = HashMap<FontSelectionRequestKey, - scoped_refptr<CSSSegmentedFontFace>, - FontSelectionRequestKeyHash, - WTF::SimpleClassHashTraits<FontSelectionRequestKey>>; + : public GarbageCollected<FontSelectionQueryResult> { + using Map = + HeapHashMap<FontSelectionRequestKey, + Member<CSSSegmentedFontFace>, + FontSelectionRequestKeyHash, + WTF::SimpleClassHashTraits<FontSelectionRequestKey>>; public: - scoped_refptr<CSSSegmentedFontFace> GetOrCreate( - const FontSelectionRequest& request, - const CapabilitiesSet& family_faces); + CSSSegmentedFontFace* GetOrCreate(const FontSelectionRequest& request, + const CapabilitiesSet& family_faces); void Trace(Visitor*) const; @@ -126,38 +120,36 @@ Map map_; }; - // The map from font family name to `FontSelectionQueryResult`. + // The map from font family name to |FontSelectionQueryResult|. class FontSelectionQueryCache final { - using Map = HashMap<String, - scoped_refptr<FontSelectionQueryResult>, - CaseFoldingHash>; + DISALLOW_NEW(); + + using Map = + HeapHashMap<String, Member<FontSelectionQueryResult>, CaseFoldingHash>; public: - void Clear() LOCKS_EXCLUDED(lock_); - scoped_refptr<CSSSegmentedFontFace> GetOrCreate( - const FontSelectionRequest& request, - const AtomicString& family, - scoped_refptr<CapabilitiesSet> family_faces) LOCKS_EXCLUDED(lock_); - void Remove(const AtomicString& family) LOCKS_EXCLUDED(lock_); + void Clear(); + CSSSegmentedFontFace* GetOrCreate(const FontSelectionRequest& request, + const AtomicString& family, + CapabilitiesSet* family_faces); + void Remove(const AtomicString& family); - void Trace(Visitor*) const LOCKS_EXCLUDED(lock_); + void Trace(Visitor*) const; private: - mutable LockForParallelTextShaping lock_; - Map map_ GUARDED_BY(lock_); + Map map_; }; - // The map from font family name to `CapabilitiesSet`. + // The map from font family name to |CapabilitiesSet|. class SegmentedFacesByFamily final { - using Map = - HashMap<String, scoped_refptr<CapabilitiesSet>, CaseFoldingHash>; + DISALLOW_NEW(); public: void AddFontFace(FontFace* font_face, bool css_connected); void Clear() { map_.clear(); } - scoped_refptr<CapabilitiesSet> Find(const AtomicString& family) const; + CapabilitiesSet* Find(const AtomicString& family) const; bool IsEmpty() const { return map_.IsEmpty(); } - // Returns true if `font_face` is removed from `map_`. + // Returns true if |font_face| is removed from |map_|. bool RemoveFontFace(FontFace* font_face); size_t GetNumSegmentedFacesForTesting() const; @@ -165,6 +157,8 @@ void Trace(Visitor*) const; private: + using Map = HeapHashMap<String, Member<CapabilitiesSet>, CaseFoldingHash>; + Map map_; };
diff --git a/third_party/blink/renderer/core/css/font_face_cache_test.cc b/third_party/blink/renderer/core/css/font_face_cache_test.cc index fec64cae..35b59b13 100644 --- a/third_party/blink/renderer/core/css/font_face_cache_test.cc +++ b/third_party/blink/renderer/core/css/font_face_cache_test.cc
@@ -146,7 +146,7 @@ const FontDescription& description_condensed = FontDescriptionForRequest( CondensedWidthValue(), NormalSlopeValue(), NormalWeightValue()); - scoped_refptr<CSSSegmentedFontFace> result = + CSSSegmentedFontFace* result = cache_->Get(description_condensed, kFontNameForTesting); ASSERT_TRUE(result); @@ -177,7 +177,7 @@ const FontDescription& description_bold = FontDescriptionForRequest( NormalWidthValue(), NormalSlopeValue(), BoldWeightValue()); - scoped_refptr<CSSSegmentedFontFace> result = + CSSSegmentedFontFace* result = cache_->Get(description_bold, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -272,7 +272,7 @@ } } for (FontDescription& test_description : test_descriptions) { - scoped_refptr<CSSSegmentedFontFace> result = + CSSSegmentedFontFace* result = cache_->Get(test_description, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -320,7 +320,7 @@ const FontDescription& description_bold = FontDescriptionForRequest( NormalWidthValue(), NormalSlopeValue(), BoldWeightValue()); - scoped_refptr<CSSSegmentedFontFace> result = + CSSSegmentedFontFace* result = cache_->Get(description_bold, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -372,7 +372,7 @@ const FontDescription& description_expanded = FontDescriptionForRequest( NormalWidthValue(), NormalSlopeValue(), test_weight); - scoped_refptr<CSSSegmentedFontFace> result = + CSSSegmentedFontFace* result = cache_->Get(description_expanded, kFontNameForTesting); ASSERT_TRUE(result); ASSERT_EQ(result->GetFontSelectionCapabilities().weight.minimum, @@ -429,7 +429,7 @@ const FontDescription& description_expanded = FontDescriptionForRequest( FontSelectionValue(105), NormalSlopeValue(), NormalWeightValue()); - scoped_refptr<CSSSegmentedFontFace> result = + CSSSegmentedFontFace* result = cache_->Get(description_expanded, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities = @@ -482,7 +482,7 @@ const FontDescription& description_italic = FontDescriptionForRequest( NormalWidthValue(), ItalicSlopeValue(), NormalWeightValue()); - scoped_refptr<CSSSegmentedFontFace> result = + CSSSegmentedFontFace* result = cache_->Get(description_italic, kFontNameForTesting); ASSERT_TRUE(result); FontSelectionCapabilities result_capabilities =
diff --git a/third_party/blink/renderer/core/css/font_face_set.cc b/third_party/blink/renderer/core/css/font_face_set.cc index 49d5433..f4e144d 100644 --- a/third_party/blink/renderer/core/css/font_face_set.cc +++ b/third_party/blink/renderer/core/css/font_face_set.cc
@@ -184,7 +184,7 @@ f = f->Next()) { if (f->FamilyIsGeneric()) continue; - auto segmented_font_face = + CSSSegmentedFontFace* segmented_font_face = font_face_cache->Get(font.GetFontDescription(), f->FamilyName()); if (segmented_font_face) segmented_font_face->Match(text, faces); @@ -220,7 +220,7 @@ f = f->Next()) { if (f->FamilyIsGeneric()) continue; - auto face = + CSSSegmentedFontFace* face = font_face_cache->Get(font.GetFontDescription(), f->FamilyName()); if (face) { if (!face->CheckFont(text))
diff --git a/third_party/blink/renderer/core/css/offscreen_font_selector.cc b/third_party/blink/renderer/core/css/offscreen_font_selector.cc index 7b7d462..fa1b592f 100644 --- a/third_party/blink/renderer/core/css/offscreen_font_selector.cc +++ b/third_party/blink/renderer/core/css/offscreen_font_selector.cc
@@ -12,8 +12,7 @@ namespace blink { OffscreenFontSelector::OffscreenFontSelector(WorkerGlobalScope* worker) - : CSSFontSelectorBase(worker->GetTaskRunner(TaskType::kInternalDefault)), - worker_(worker) { + : worker_(worker) { DCHECK(worker); font_face_cache_ = MakeGarbageCollected<FontFaceCache>(); FontCache::Get().AddClient(this); @@ -44,7 +43,8 @@ const FontDescription& font_description, const FontFamily& font_family) { const auto& family_name = font_family.FamilyName(); - if (auto face = font_face_cache_->Get(font_description, family_name)) { + if (CSSSegmentedFontFace* face = + font_face_cache_->Get(font_description, family_name)) { ReportWebFontFamily(family_name); return face->GetFontData(font_description); }
diff --git a/third_party/blink/renderer/core/css/remote_font_face_source.cc b/third_party/blink/renderer/core/css/remote_font_face_source.cc index cf944c61..11d1ef1 100644 --- a/third_party/blink/renderer/core/css/remote_font_face_source.cc +++ b/third_party/blink/renderer/core/css/remote_font_face_source.cc
@@ -28,10 +28,6 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h" #include "third_party/blink/renderer/platform/network/network_state_notifier.h" -#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" -#include "third_party/blink/renderer/platform/scheduler/public/thread.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h" -#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" namespace blink { @@ -137,16 +133,11 @@ return kSwapPeriod; } -RemoteFontFaceSource::RemoteFontFaceSource( - CSSFontFace* css_font_face, - FontSelector* font_selector, - FontDisplay display, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) +RemoteFontFaceSource::RemoteFontFaceSource(CSSFontFace* css_font_face, + FontSelector* font_selector, + FontDisplay display) : face_(css_font_face), font_selector_(font_selector), -#if defined(USE_PARALLEL_TEXT_SHAPING) - task_runner_(task_runner), -#endif // No need to report the violation here since the font is not loaded yet display_( GetFontDisplayWithDocumentPolicyCheck(display, @@ -185,7 +176,6 @@ ExecutionContext* execution_context = font_selector_->GetExecutionContext(); if (!execution_context) return; - DCHECK(execution_context->IsContextThread()); // Prevent promise rejection while shutting down the document. // See crbug.com/960290 auto* window = DynamicTo<LocalDOMWindow>(execution_context); @@ -382,29 +372,8 @@ } void RemoteFontFaceSource::BeginLoadIfNeeded() { - if (IsLoaded()) + if (IsLoaded() || !font_selector_->GetExecutionContext()) return; - ExecutionContext* const execution_context = - font_selector_->GetExecutionContext(); - if (!execution_context) - return; -#if defined(USE_PARALLEL_TEXT_SHAPING) - if (!execution_context->IsContextThread()) { - // Following tests reache here. - // * fast/css3-text/css3-text-decoration/text-decoration-skip-ink-links.html - // * fast/css3-text/css3-word-break/word-break-break-all-in-span.html - // * virtual/text-antialias/justify-vertical.html - // * virtual/text-antialias/line-break-8bit-after-16bit.html - // Note: |ExecutionContext::GetTaskRunner()| works only for context - // thread, so we ask main thread to handle |BeginLoadIfNeeded()|. - PostCrossThreadTask( - *task_runner_, FROM_HERE, - CrossThreadBindOnce(&RemoteFontFaceSource::BeginLoadIfNeeded, - WrapCrossThreadPersistent(this))); - return; - } -#endif - DCHECK(GetResource()); SetDisplay(face_->GetFontFace()->GetFontDisplay()); @@ -412,19 +381,20 @@ auto* font = To<FontResource>(GetResource()); if (font->StillNeedsLoad()) { if (font->IsLowPriorityLoadingAllowedForRemoteFont()) { - execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( - mojom::blink::ConsoleMessageSource::kIntervention, - mojom::blink::ConsoleMessageLevel::kInfo, - "Slow network is detected. See " - "https://www.chromestatus.com/feature/5636954674692096 for more " - "details. Fallback font will be used while loading: " + - font->Url().ElidedString())); + font_selector_->GetExecutionContext()->AddConsoleMessage( + MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kIntervention, + mojom::ConsoleMessageLevel::kInfo, + "Slow network is detected. See " + "https://www.chromestatus.com/feature/5636954674692096 for more " + "details. Fallback font will be used while loading: " + + font->Url().ElidedString())); // Set the loading priority to VeryLow only when all other clients agreed // that this font is not required for painting the text. font->DidChangePriority(ResourceLoadPriority::kVeryLow, 0); } - if (execution_context->Fetcher()->StartLoad(font)) + if (font_selector_->GetExecutionContext()->Fetcher()->StartLoad(font)) histograms_.LoadStarted(); } @@ -432,7 +402,9 @@ // Note that <link rel=preload> may have initiated loading without kicking // off the timers. font->StartLoadLimitTimersIfNecessary( - execution_context->GetTaskRunner(TaskType::kInternalLoading).get()); + font_selector_->GetExecutionContext() + ->GetTaskRunner(TaskType::kInternalLoading) + .get()); face_->DidBeginLoad(); }
diff --git a/third_party/blink/renderer/core/css/remote_font_face_source.h b/third_party/blink/renderer/core/css/remote_font_face_source.h index 6fe503d..7744db3 100644 --- a/third_party/blink/renderer/core/css/remote_font_face_source.h +++ b/third_party/blink/renderer/core/css/remote_font_face_source.h
@@ -23,10 +23,7 @@ public: enum Phase { kNoLimitExceeded, kShortLimitExceeded, kLongLimitExceeded }; - RemoteFontFaceSource(CSSFontFace*, - FontSelector*, - FontDisplay, - scoped_refptr<base::SingleThreadTaskRunner>); + RemoteFontFaceSource(CSSFontFace*, FontSelector*, FontDisplay); ~RemoteFontFaceSource() override; bool IsLoading() const override; @@ -151,11 +148,6 @@ Member<CSSFontFace> face_; Member<FontSelector> font_selector_; -#if defined(USE_PARALLEL_TEXT_SHAPING) - // Post `BeginLoadIfNeeded()` unless context thread. - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; -#endif - // |nullptr| if font is not loaded or failed to decode. scoped_refptr<FontCustomPlatformData> custom_font_data_; // |nullptr| if font is not loaded or failed to decode.
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 7e24486..3c569934 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -343,10 +343,10 @@ // There's only one font and it's bold and normal. EXPECT_EQ(1u, GetStyleEngine().GetFontSelector()->GetFontFaceCache() ->GetNumSegmentedFacesForTesting()); - scoped_refptr<CSSSegmentedFontFace> font_face = - GetStyleEngine().GetFontSelector()->GetFontFaceCache()->Get( - t4->GetComputedStyle()->GetFontDescription(), - AtomicString("Cool Font")); + CSSSegmentedFontFace* font_face = + GetStyleEngine().GetFontSelector()->GetFontFaceCache() + ->Get(t4->GetComputedStyle()->GetFontDescription(), + AtomicString("Cool Font")); EXPECT_TRUE(font_face); FontSelectionCapabilities capabilities = font_face->GetFontSelectionCapabilities();
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl index 07ac60d..56d58d2 100644 --- a/third_party/blink/renderer/core/dom/element.idl +++ b/third_party/blink/renderer/core/dom/element.idl
@@ -101,7 +101,9 @@ // TODO(mkwst): Write a spec for the `TrustedHTML` variants. // TODO(lyf): Change the type to `[TreatNullAs=xxx] HTMLString` after // https://crbug.com/1058762 has been fixed. - [CEReactions, RuntimeCallStatsCounter=ElementInnerHTML, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString innerHTML; + // TODO(https://crbug.com/1335986): Custom setter is needed to collect + // metrics, and can be removed once metrics are captured. + [Custom=Setter, CEReactions, RuntimeCallStatsCounter=ElementInnerHTML, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString innerHTML; [CEReactions, RaisesException=Setter] attribute [TreatNullAs=EmptyString, StringContext=TrustedHTML] DOMString outerHTML; [CEReactions, RaisesException] void insertAdjacentHTML(DOMString position, HTMLString text);
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc index 24cb711..23b64a1 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc
@@ -237,15 +237,8 @@ clock_ = clock; } -void LocalFrameUkmAggregator::DidReachFirstContentfulPaint( - bool are_painting_main_frame) { - DCHECK(fcp_state_ != kHavePassedFCP); - - if (!are_painting_main_frame) { - DCHECK(AllMetricsAreZero()); - return; - } - +void LocalFrameUkmAggregator::DidReachFirstContentfulPaint() { + DCHECK_NE(fcp_state_, kHavePassedFCP); fcp_state_ = kThisFrameReachedFCP; } @@ -626,20 +619,6 @@ record.reset(); } -bool LocalFrameUkmAggregator::AllMetricsAreZero() { - if (primary_metric_.interval_count != 0) - return false; - for (auto& record : absolute_metric_records_) { - if (record.interval_count != 0) { - return false; - } - if (record.main_frame_count != 0) { - return false; - } - } - return true; -} - void LocalFrameUkmAggregator::ChooseNextFrameForTest() { next_frame_sample_control_for_test_ = kMustChooseNextFrame; } @@ -648,4 +627,8 @@ next_frame_sample_control_for_test_ = kMustNotChooseNextFrame; } +bool LocalFrameUkmAggregator::IsBeforeFCPForTesting() const { + return fcp_state_ == kBeforeFCPSignal; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h index 7f5ce2c..399bb6e 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
@@ -310,9 +310,12 @@ // Inform the aggregator that we have reached First Contentful Paint. // The UKM event for the pre-FCP period will be recorded and UMA for - // aggregated contributions to FCP are reported if are_painting_main_frame - // is true. - void DidReachFirstContentfulPaint(bool are_painting_main_frame); + // aggregated contributions to FCP are reported. + // TODO(crbug.com/1330675): This is called for the main frame or local frame + // roots only, depending on features::kLocalFrameRootPrePostFCPMetrics. When + // the experiment finishes, we should let only local frame roots use this + // class. + void DidReachFirstContentfulPaint(); bool InMainFrameUpdate() { return in_main_frame_update_; } @@ -322,6 +325,8 @@ // RecordEndOfFrameMetrics. std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics(); + bool IsBeforeFCPForTesting() const; + private: struct AbsoluteMetricRecord { std::unique_ptr<CustomCountHistogram> pre_fcp_uma_counter; @@ -368,9 +373,6 @@ void ChooseNextFrameForTest(); void DoNotChooseNextFrameForTest(); - // Used to check that we record only for the MainFrame of a document. - bool AllMetricsAreZero(); - // The caller is the owner of the |clock|. The |clock| must outlive the // LocalFrameUkmAggregator. void SetTickClockForTesting(const base::TickClock* clock);
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc index e8e948f..5e7d6784 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc
@@ -6,12 +6,14 @@ #include "base/metrics/statistics_recorder.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/test/test_mock_time_task_runner.h" #include "cc/metrics/begin_main_frame_metrics.h" #include "components/ukm/test_ukm_recorder.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/metrics/document_update_reason.h" #include "third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_init.h" +#include "third_party/blink/renderer/core/paint/paint_timing.h" #include "third_party/blink/renderer/core/testing/intersection_observer_test_helper.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" @@ -159,7 +161,7 @@ for (int i = 0; i < LocalFrameUkmAggregator::kForcedStyleAndLayout; ++i) { auto timer = aggregator().GetScopedTimer(i); if (mark_fcp && i == static_cast<int>(LocalFrameUkmAggregator::kPaint)) - aggregator().DidReachFirstContentfulPaint(true); + aggregator().DidReachFirstContentfulPaint(); test_task_runner_->FastForwardBy( base::Milliseconds(millisecond_per_step)); } @@ -639,4 +641,34 @@ "Blink.IntersectionObservationJavascriptCount.UpdateTime.PreFCP"), 2); } + +static void TestLocalFrameRootPrePostFCPMetrics( + const LocalFrame& local_frame_root) { + ASSERT_FALSE(local_frame_root.IsMainFrame()); + ASSERT_TRUE(local_frame_root.IsLocalRoot()); + auto& ukm_aggregator = local_frame_root.View()->EnsureUkmAggregator(); + EXPECT_TRUE(ukm_aggregator.IsBeforeFCPForTesting()); + // Simulate the first contentful paint. + PaintTiming::From(*local_frame_root.GetDocument()).MarkFirstContentfulPaint(); + EXPECT_EQ( + base::FeatureList::IsEnabled(features::kLocalFrameRootPrePostFCPMetrics), + !ukm_aggregator.IsBeforeFCPForTesting()); +} + +TEST_F(LocalFrameUkmAggregatorSimTest, LocalFrameRootPrePostFCPMetrics) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kLocalFrameRootPrePostFCPMetrics); + InitializeRemote(); + TestLocalFrameRootPrePostFCPMetrics(*LocalFrameRoot().GetFrame()); +} + +TEST_F(LocalFrameUkmAggregatorSimTest, + LocalFrameRootPrePostFCPMetricsDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + features::kLocalFrameRootPrePostFCPMetrics); + InitializeRemote(); + TestLocalFrameRootPrePostFCPMetrics(*LocalFrameRoot().GetFrame()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 91c4dffb..a8a1f6f 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -4726,12 +4726,20 @@ } void LocalFrameView::OnFirstContentfulPaint() { - GetPage()->GetChromeClient().StopDeferringCommits( - *frame_, cc::PaintHoldingCommitTrigger::kFirstContentfulPaint); - const bool is_main_frame = frame_->IsMainFrame(); - if (frame_->GetDocument()->ShouldMarkFontPerformance()) - FontPerformance::MarkFirstContentfulPaint(); - EnsureUkmAggregator().DidReachFirstContentfulPaint(is_main_frame); + if (frame_->IsMainFrame()) { + // Restart commits that may have been deferred. + GetPage()->GetChromeClient().StopDeferringCommits( + *frame_, cc::PaintHoldingCommitTrigger::kFirstContentfulPaint); + if (frame_->GetDocument()->ShouldMarkFontPerformance()) + FontPerformance::MarkFirstContentfulPaint(); + } + + if (base::FeatureList::IsEnabled(features::kLocalFrameRootPrePostFCPMetrics) + ? frame_->IsLocalRoot() + : frame_->IsMainFrame()) { + // See crbug.com/1330675. + EnsureUkmAggregator().DidReachFirstContentfulPaint(); + } } void LocalFrameView::RegisterForLifecycleNotifications(
diff --git a/third_party/blink/renderer/core/html/html_object_element.cc b/third_party/blink/renderer/core/html/html_object_element.cc index f81729a..d659692c 100644 --- a/third_party/blink/renderer/core/html/html_object_element.cc +++ b/third_party/blink/renderer/core/html/html_object_element.cc
@@ -126,44 +126,41 @@ // serviceType! void HTMLObjectElement::ParametersForPlugin(PluginParameters& plugin_params) { HashSet<StringImpl*, CaseFoldingHash> unique_param_names; + if (RuntimeEnabledFeatures::HTMLParamElementUrlSupportEnabled()) { + // Scan the PARAM children and store their name/value pairs. + // Get the URL and type from the params if we don't already have them. + // Only scan <param> children if this functionality hasn't been disabled. + for (HTMLParamElement* p = Traversal<HTMLParamElement>::FirstChild(*this); + p; p = Traversal<HTMLParamElement>::NextSibling(*p)) { + String name = p->GetName(); + if (name.IsEmpty()) + continue; - if (!RuntimeEnabledFeatures::HTMLParamElementUrlSupportEnabled()) { - // The <param> element functionality has been deprecated/removed. - return; - } + unique_param_names.insert(name.Impl()); + plugin_params.AppendNameWithValue(p->GetName(), p->Value()); - // Scan the PARAM children and store their name/value pairs. - // Get the URL and type from the params if we don't already have them. - for (HTMLParamElement* p = Traversal<HTMLParamElement>::FirstChild(*this); p; - p = Traversal<HTMLParamElement>::NextSibling(*p)) { - String name = p->GetName(); - if (name.IsEmpty()) - continue; - - unique_param_names.insert(name.Impl()); - plugin_params.AppendNameWithValue(p->GetName(), p->Value()); - - // TODO(schenney): crbug.com/572908 url adjustment does not belong in this - // function. - // HTML5 says that an object resource's URL is specified by the object's - // data attribute, not by a param element with a name of "data". However, - // for compatibility, allow the resource's URL to be given by a param - // element with one of the common names if we know that resource points - // to a plugin. - if (url_.IsEmpty() && !EqualIgnoringASCIICase(name, "data") && - HTMLParamElement::IsURLParameter(name)) { - UseCounter::Count(GetDocument(), - WebFeature::kHTMLParamElementURLParameter); - // Use count this <param> usage, if it loads a PDF. - should_use_count_param_url_ = true; - SetUrl(StripLeadingAndTrailingHTMLSpaces(p->Value())); - } - // TODO(schenney): crbug.com/572908 serviceType calculation does not belong - // in this function. - if (service_type_.IsEmpty() && EqualIgnoringASCIICase(name, "type")) { - wtf_size_t pos = p->Value().Find(";"); - if (pos != kNotFound) - SetServiceType(p->Value().GetString().Left(pos)); + // TODO(schenney): crbug.com/572908 url adjustment does not belong in this + // function. + // HTML5 says that an object resource's URL is specified by the object's + // data attribute, not by a param element with a name of "data". However, + // for compatibility, allow the resource's URL to be given by a param + // element with one of the common names if we know that resource points + // to a plugin. + if (url_.IsEmpty() && !EqualIgnoringASCIICase(name, "data") && + HTMLParamElement::IsURLParameter(name)) { + UseCounter::Count(GetDocument(), + WebFeature::kHTMLParamElementURLParameter); + // Use count this <param> usage, if it loads a PDF. + should_use_count_param_url_ = true; + SetUrl(StripLeadingAndTrailingHTMLSpaces(p->Value())); + } + // TODO(schenney): crbug.com/572908 serviceType calculation does not + // belong in this function. + if (service_type_.IsEmpty() && EqualIgnoringASCIICase(name, "type")) { + wtf_size_t pos = p->Value().Find(";"); + if (pos != kNotFound) + SetServiceType(p->Value().GetString().Left(pos)); + } } } @@ -172,8 +169,11 @@ AttributeCollection attributes = Attributes(); for (const Attribute& attribute : attributes) { const AtomicString& name = attribute.GetName().LocalName(); - if (!unique_param_names.Contains(name.Impl())) + if (unique_param_names.Contains(name.Impl())) { + DCHECK(RuntimeEnabledFeatures::HTMLParamElementUrlSupportEnabled()); + } else { plugin_params.AppendAttribute(attribute); + } } // Some plugins don't understand the "data" attribute of the OBJECT tag (i.e.
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc index 3a69078..da7aba3 100644 --- a/third_party/blink/renderer/core/paint/box_painter_base.cc +++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -582,7 +582,8 @@ Image* image, const BackgroundImageGeometry& geometry, SkBlendMode op, - RespectImageOrientationEnum respect_orientation) { + RespectImageOrientationEnum respect_orientation, + bool image_may_be_lcp_candidate) { DCHECK(!geometry.TileSize().IsEmpty()); const gfx::RectF dest_rect(geometry.SnappedDestRect()); @@ -598,7 +599,8 @@ auto image_auto_dark_mode = ImageClassifierHelper::GetImageAutoDarkMode( *frame, style, dest_rect, *single_tile_src); context.DrawImage(image, Image::kSyncDecode, image_auto_dark_mode, - dest_rect, &*single_tile_src, op, respect_orientation); + dest_rect, &*single_tile_src, op, respect_orientation, + image_may_be_lcp_candidate); return; } @@ -644,7 +646,7 @@ // it into the snapped_dest_rect using phase from one_tile_rect and the // given repeat spacing. Note the phase is already scaled. context.DrawImageTiled(image, dest_rect, tiling_info, image_auto_dark_mode, - op, respect_orientation); + op, respect_orientation, image_may_be_lcp_candidate); } scoped_refptr<Image> GetBGColorPaintWorkletImage(const Document* document, @@ -705,7 +707,7 @@ return true; } -void DidDrawImage( +bool WillDrawImage( Node* node, const Image& image, const StyleImage& style_image, @@ -713,17 +715,19 @@ const gfx::RectF& image_rect) { Node* generating_node = GeneratingNode(node); if (!generating_node || !style_image.IsImageResource()) - return; + return false; const gfx::Rect enclosing_rect = gfx::ToEnclosingRect(image_rect); - PaintTimingDetector::NotifyBackgroundImagePaint( - *generating_node, image, To<StyleFetchedImage>(style_image), - current_paint_chunk_properties, enclosing_rect); + bool image_may_be_lcp_candidate = + PaintTimingDetector::NotifyBackgroundImagePaint( + *generating_node, image, To<StyleFetchedImage>(style_image), + current_paint_chunk_properties, enclosing_rect); LocalDOMWindow* window = node->GetDocument().domWindow(); DCHECK(window); ImageElementTiming::From(*window).NotifyBackgroundImagePainted( *generating_node, To<StyleFetchedImage>(style_image), current_paint_chunk_properties, enclosing_rect); + return image_may_be_lcp_candidate; } inline bool PaintFastBottomLayer(const Document* document, @@ -826,17 +830,19 @@ inspector_paint_image_event::Data, node, *info.image, gfx::RectF(image->Rect()), gfx::RectF(image_border.Rect())); + bool may_be_lcp_candidate = + WillDrawImage(node, *image, *info.image, + context.GetPaintController().CurrentPaintChunkProperties(), + image_border.Rect()); + auto image_auto_dark_mode = ImageClassifierHelper::GetImageAutoDarkMode( *document->GetFrame(), style, image_border.Rect(), src_rect); // Since there is no way for the developer to specify decode behavior, use // kSync by default. context.DrawImageRRect(image, Image::kSyncDecode, image_auto_dark_mode, image_border, src_rect, composite_op, - info.respect_image_orientation); + info.respect_image_orientation, may_be_lcp_candidate); - DidDrawImage(node, *image, *info.image, - context.GetPaintController().CurrentPaintChunkProperties(), - image_border.Rect()); return true; } @@ -955,11 +961,13 @@ TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", inspector_paint_image_event::Data, node, *info.image, gfx::RectF(image->Rect()), gfx::RectF(scrolled_paint_rect)); + bool may_be_lcp_candidate = WillDrawImage( + node, *image, *info.image, + context.GetPaintController().CurrentPaintChunkProperties(), + gfx::RectF(geometry.SnappedDestRect())); DrawTiledBackground(document->GetFrame(), context, style, image, geometry, - composite_op, info.respect_image_orientation); - DidDrawImage(node, *image, *info.image, - context.GetPaintController().CurrentPaintChunkProperties(), - gfx::RectF(geometry.SnappedDestRect())); + composite_op, info.respect_image_orientation, + may_be_lcp_candidate); } }
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc index 4d2708d..6c901ca 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -277,7 +277,7 @@ } } -void ImagePaintTimingDetector::RecordImage( +bool ImagePaintTimingDetector::RecordImage( const LayoutObject& object, const gfx::Size& intrinsic_size, const MediaTiming& media_timing, @@ -287,12 +287,12 @@ Node* node = object.GetNode(); if (!node) - return; + return false; // Before the image resource starts loading, <img> has no size info. We wait // until the size is known. if (image_border.IsEmpty()) - return; + return false; RecordId record_id = std::make_pair(&object, &media_timing); @@ -311,14 +311,14 @@ records_manager_.MaybeUpdateLargestIgnoredImage( record_id, rect_size, image_border, mapped_visual_rect); } - return; + return false; } if (records_manager_.IsRecordedImage(record_id)) { base::WeakPtr<ImageRecord> record = records_manager_.GetPendingImage(record_id); if (!record) - return; + return false; if (ShouldReportAnimatedImages() && media_timing.IsPaintedFirstFrame()) { added_entry_in_latest_frame_ |= records_manager_.OnFirstAnimatedFramePainted(record_id, frame_index_); @@ -334,8 +334,9 @@ visualizer->DumpImageDebuggingRect(object, mapped_visual_rect, media_timing); } + return true; } - return; + return false; } gfx::RectF mapped_visual_rect = @@ -352,7 +353,7 @@ bool added_pending = records_manager_.RecordFirstPaintAndReturnIsPending( record_id, rect_size, image_border, mapped_visual_rect, bpp); if (!added_pending) - return; + return false; if (ShouldReportAnimatedImages() && media_timing.IsPaintedFirstFrame()) { added_entry_in_latest_frame_ |= @@ -361,7 +362,9 @@ if (media_timing.IsSufficientContentLoadedForPaint()) { records_manager_.OnImageLoaded(record_id, frame_index_, style_image); added_entry_in_latest_frame_ = true; + return true; } + return false; } uint64_t ImagePaintTimingDetector::ComputeImageRectSize(
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h index da089d85..c281da5 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -243,8 +243,10 @@ // Record an image paint. This method covers both img and background image. In // the case of a normal img, the last parameter will be nullptr. This // parameter is needed only for the purposes of plumbing the correct loadTime - // value to the ImageRecord. - void RecordImage(const LayoutObject&, + // value to the ImageRecord. The method returns true if the image is a + // candidate for LargestContentfulPaint. That is, if the image is larger + // on screen than the current best candidate. + bool RecordImage(const LayoutObject&, const gfx::Size& intrinsic_size, const MediaTiming&, const PropertyTreeStateOrAlias& current_paint_properties,
diff --git a/third_party/blink/renderer/core/paint/image_painter.cc b/third_party/blink/renderer/core/paint/image_painter.cc index d041b4c..6d103200 100644 --- a/third_party/blink/renderer/core/paint/image_painter.cc +++ b/third_party/blink/renderer/core/paint/image_painter.cc
@@ -260,10 +260,10 @@ *layout_image_.GetFrame(), layout_image_.StyleRef(), gfx::RectF(pixel_snapped_dest_rect), src_rect); - context.DrawImage(image.get(), decode_mode, image_auto_dark_mode, - gfx::RectF(pixel_snapped_dest_rect), &src_rect, - SkBlendMode::kSrcOver, respect_orientation); - + // At this point we have all the necessary information to report paint + // timing data. Do so now in order to mark the resulting PaintImage as + // an LCP candidate. + bool image_may_be_lcp_candidate = false; if (ImageResourceContent* image_content = image_resource.CachedImage()) { if ((IsA<HTMLImageElement>(node) || IsA<HTMLVideoElement>(node)) && image_content->IsLoaded()) { @@ -274,11 +274,16 @@ context.GetPaintController().CurrentPaintChunkProperties(), pixel_snapped_dest_rect); } - PaintTimingDetector::NotifyImagePaint( + image_may_be_lcp_candidate = PaintTimingDetector::NotifyImagePaint( layout_image_, image->Size(), *image_content, context.GetPaintController().CurrentPaintChunkProperties(), pixel_snapped_dest_rect); } + + context.DrawImage(image.get(), decode_mode, image_auto_dark_mode, + gfx::RectF(pixel_snapped_dest_rect), &src_rect, + SkBlendMode::kSrcOver, respect_orientation, + image_may_be_lcp_candidate); } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_timing.cc b/third_party/blink/renderer/core/paint/paint_timing.cc index 0d6de59..d7db2e4 100644 --- a/third_party/blink/renderer/core/paint/paint_timing.cc +++ b/third_party/blink/renderer/core/paint/paint_timing.cc
@@ -251,13 +251,12 @@ first_contentful_paint_ = stamp; RegisterNotifyPresentationTime(PaintEvent::kFirstContentfulPaint); - // Restart commits that may have been deferred. LocalFrame* frame = GetFrame(); - if (!frame || !frame->IsMainFrame()) + if (!frame) return; frame->View()->OnFirstContentfulPaint(); - if (frame->GetFrameScheduler()) + if (frame->IsMainFrame() && frame->GetFrameScheduler()) frame->GetFrameScheduler()->OnFirstContentfulPaintInMainFrame(); NotifyPaintTimingChanged();
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/third_party/blink/renderer/core/paint/paint_timing_detector.cc index 36c51e3d..aa38d69f 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -113,7 +113,7 @@ } // static -void PaintTimingDetector::NotifyBackgroundImagePaint( +bool PaintTimingDetector::NotifyBackgroundImagePaint( const Node& node, const Image& image, const StyleFetchedImage& style_image, @@ -122,48 +122,49 @@ DCHECK(style_image.CachedImage()); LayoutObject* object = node.GetLayoutObject(); if (!object) - return; + return false; LocalFrameView* frame_view = object->GetFrameView(); if (!frame_view) - return; + return false; ImagePaintTimingDetector* detector = frame_view->GetPaintTimingDetector().GetImagePaintTimingDetector(); if (!detector) - return; + return false; if (!IsBackgroundImageContentful(*object, image)) - return; + return false; ImageResourceContent* cached_image = style_image.CachedImage(); DCHECK(cached_image); // TODO(yoav): |image| and |cached_image.GetImage()| are not the same here in // the case of SVGs. Figure out why and if we can remove this footgun. - detector->RecordImage(*object, image.Size(), *cached_image, - current_paint_chunk_properties, &style_image, - image_border); + return detector->RecordImage(*object, image.Size(), *cached_image, + current_paint_chunk_properties, &style_image, + image_border); } // static -void PaintTimingDetector::NotifyImagePaint( +bool PaintTimingDetector::NotifyImagePaint( const LayoutObject& object, const gfx::Size& intrinsic_size, const MediaTiming& media_timing, const PropertyTreeStateOrAlias& current_paint_chunk_properties, const gfx::Rect& image_border) { if (IgnorePaintTimingScope::ShouldIgnore()) - return; + return false; LocalFrameView* frame_view = object.GetFrameView(); if (!frame_view) - return; + return false; ImagePaintTimingDetector* detector = frame_view->GetPaintTimingDetector().GetImagePaintTimingDetector(); if (!detector) - return; + return false; - detector->RecordImage(object, intrinsic_size, media_timing, - current_paint_chunk_properties, nullptr, image_border); + return detector->RecordImage(object, intrinsic_size, media_timing, + current_paint_chunk_properties, nullptr, + image_border); } void PaintTimingDetector::NotifyImageFinished(const LayoutObject& object,
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.h b/third_party/blink/renderer/core/paint/paint_timing_detector.h index 2405d30..3ade99b9 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.h
@@ -123,13 +123,19 @@ public: PaintTimingDetector(LocalFrameView*); - static void NotifyBackgroundImagePaint( + // Returns true if the image might ultimately be a candidate for largest + // paint, otherwise false. When this method is called we do not know the + // largest status for certain, because we need to wait for presentation. + // Hence the "maybe" return value. + static bool NotifyBackgroundImagePaint( const Node&, const Image&, const StyleFetchedImage&, const PropertyTreeStateOrAlias& current_paint_chunk_properties, const gfx::Rect& image_border); - static void NotifyImagePaint( + // Returns true if the image is a candidate for largest paint, otherwise + // false. See the comment for NotifyBackgroundImagePaint(...). + static bool NotifyImagePaint( const LayoutObject&, const gfx::Size& intrinsic_size, const MediaTiming& media_timing,
diff --git a/third_party/blink/renderer/core/paint/svg_image_painter.cc b/third_party/blink/renderer/core/paint/svg_image_painter.cc index a73cccf..99644d1 100644 --- a/third_party/blink/renderer/core/paint/svg_image_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_image_painter.cc
@@ -85,6 +85,23 @@ dest_rect, src_rect); } + ImageResourceContent* image_content = image_resource.CachedImage(); + bool image_may_be_lcp_candidate = false; + if (image_content->IsLoaded()) { + LocalDOMWindow* window = layout_svg_image_.GetDocument().domWindow(); + DCHECK(window); + ImageElementTiming::From(*window).NotifyImagePainted( + layout_svg_image_, *image_content, + paint_info.context.GetPaintController().CurrentPaintChunkProperties(), + gfx::ToEnclosingRect(dest_rect)); + } + image_may_be_lcp_candidate = PaintTimingDetector::NotifyImagePaint( + layout_svg_image_, image->Size(), *image_content, + paint_info.context.GetPaintController().CurrentPaintChunkProperties(), + gfx::ToEnclosingRect(dest_rect)); + PaintTiming& timing = PaintTiming::From(layout_svg_image_.GetDocument()); + timing.MarkFirstContentfulPaint(); + ScopedInterpolationQuality interpolation_quality_scope( paint_info.context, layout_svg_image_.StyleRef().GetInterpolationQuality()); @@ -95,23 +112,7 @@ src_rect); paint_info.context.DrawImage(image.get(), decode_mode, image_auto_dark_mode, dest_rect, &src_rect, SkBlendMode::kSrcOver, - respect_orientation); - - ImageResourceContent* image_content = image_resource.CachedImage(); - if (image_content->IsLoaded()) { - LocalDOMWindow* window = layout_svg_image_.GetDocument().domWindow(); - DCHECK(window); - ImageElementTiming::From(*window).NotifyImagePainted( - layout_svg_image_, *image_content, - paint_info.context.GetPaintController().CurrentPaintChunkProperties(), - gfx::ToEnclosingRect(dest_rect)); - } - PaintTimingDetector::NotifyImagePaint( - layout_svg_image_, image->Size(), *image_content, - paint_info.context.GetPaintController().CurrentPaintChunkProperties(), - gfx::ToEnclosingRect(dest_rect)); - PaintTiming& timing = PaintTiming::From(layout_svg_image_.GetDocument()); - timing.MarkFirstContentfulPaint(); + respect_orientation, image_may_be_lcp_candidate); } gfx::SizeF SVGImagePainter::ComputeImageViewportSize() const {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc index f2f6de1..2f30ad4 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -98,6 +98,7 @@ device_ = String::Format("0x%08x", properties.deviceID); } description_ = properties.name; + driver_ = properties.driverDescription; WGPUSupportedLimits limits = {}; GetProcs().adapterGetLimits(handle_, &limits); @@ -238,11 +239,20 @@ } } - // TODO(dawn:1427): If unmask_hints are given ask the user for consent to - // expose more information and, if given, include device_ and description_ in - // the returned GPUAdapterInfo. - auto* adapter_info = - MakeGarbageCollected<GPUAdapterInfo>(vendor_, architecture_, "", ""); + GPUAdapterInfo* adapter_info; + if (RuntimeEnabledFeatures::WebGPUDeveloperFeaturesEnabled()) { + // If WebGPU developer features have been enabled then provide unmasked + // versions of all available adapter info values, including some that are + // only available when the flag is enabled. + adapter_info = MakeGarbageCollected<GPUAdapterInfo>( + vendor_, architecture_, device_, description_, driver_); + } else { + // TODO(dawn:1427): If unmask_hints are given ask the user for consent to + // expose more information and, if given, include device_ and description_ + // in the returned GPUAdapterInfo. + adapter_info = MakeGarbageCollected<GPUAdapterInfo>(vendor_, architecture_); + } + resolver->Resolve(adapter_info); return promise;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.h b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h index 983a644..19cd8e4b 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
@@ -73,6 +73,7 @@ String architecture_; String device_; String description_; + String driver_; static constexpr int kMaxAllowedConsoleWarnings = 50; int allowed_console_warnings_remaining_ = kMaxAllowedConsoleWarnings;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.cc index f4b92cd..97f9f77 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.cc
@@ -9,11 +9,13 @@ GPUAdapterInfo::GPUAdapterInfo(const String& vendor, const String& architecture, const String& device, - const String& description) + const String& description, + const String& driver) : vendor_(vendor), architecture_(architecture), device_(device), - description_(description) {} + description_(description), + driver_(driver) {} const String& GPUAdapterInfo::vendor() const { return vendor_; @@ -31,4 +33,8 @@ return description_; } +const String& GPUAdapterInfo::driver() const { + return driver_; +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.h b/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.h index 8eba07b..09f11be2 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.h
@@ -16,8 +16,9 @@ public: GPUAdapterInfo(const String& vendor, const String& architecture, - const String& device, - const String& description); + const String& device = String(), + const String& description = String(), + const String& driver = String()); GPUAdapterInfo(const GPUAdapterInfo&) = delete; GPUAdapterInfo& operator=(const GPUAdapterInfo&) = delete; @@ -27,12 +28,14 @@ const String& architecture() const; const String& device() const; const String& description() const; + const String& driver() const; private: String vendor_; String architecture_; String device_; String description_; + String driver_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.idl b/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.idl index b19383b96..de59c4a 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter_info.idl
@@ -12,4 +12,5 @@ readonly attribute DOMString architecture; readonly attribute DOMString device; readonly attribute DOMString description; + [RuntimeEnabled=WebGPUDeveloperFeatures] readonly attribute DOMString driver; };
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index a387e3e7..e7ca7c2e 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -409,6 +409,10 @@ RuntimeEnabledFeatures::SetWebGPUEnabled(enable); } +void WebRuntimeFeatures::EnableWebGPUDeveloperFeatures(bool enable) { + RuntimeEnabledFeatures::SetWebGPUDeveloperFeaturesEnabled(enable); +} + void WebRuntimeFeatures::EnableWebXR(bool enable) { RuntimeEnabledFeatures::SetWebXREnabled(enable); }
diff --git a/third_party/blink/renderer/platform/fonts/font_selector.cc b/third_party/blink/renderer/platform/fonts/font_selector.cc index 4d996e6..0df0d4f 100644 --- a/third_party/blink/renderer/platform/fonts/font_selector.cc +++ b/third_party/blink/renderer/platform/fonts/font_selector.cc
@@ -33,13 +33,10 @@ return g_empty_atom; if (IsWebkitBodyFamily(font_description)) { - // TODO(yosin): We should make |use_counter| available for font threads. - if (use_counter) { - // TODO(crbug.com/1065468): Remove this counter when it's no longer - // necessary. - UseCounter::Count(use_counter, - WebFeature::kFontSelectorCSSFontFamilyWebKitPrefixBody); - } + // TODO(crbug.com/1065468): Remove this counter when it's no longer + // necessary. + UseCounter::Count(use_counter, + WebFeature::kFontSelectorCSSFontFamilyWebKitPrefixBody); } else if (generic_family_name == font_family_names::kWebkitStandard && !generic_family.FamilyIsGeneric()) { // -webkit-standard is set internally only with a kGenericFamily type in
diff --git a/third_party/blink/renderer/platform/fonts/font_selector.h b/third_party/blink/renderer/platform/fonts/font_selector.h index da32354..fc2d7c85 100644 --- a/third_party/blink/renderer/platform/fonts/font_selector.h +++ b/third_party/blink/renderer/platform/fonts/font_selector.h
@@ -92,7 +92,7 @@ virtual void ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) = 0; + SimpleFontData* resulting_font_data) = 0; // Called whenever a page attempts to find a local font based on a name. This // only includes lookups where the name is allowed to match PostScript names @@ -100,7 +100,7 @@ virtual void ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data, + SimpleFontData* resulting_font_data, bool is_loading_fallback = false) = 0; // Called whenever a page attempts to find a local font based on a fallback @@ -109,12 +109,12 @@ UChar32 fallback_character, FontFallbackPriority fallback_priority, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) = 0; + SimpleFontData* resulting_font_data) = 0; // Called whenever a page attempts to find a last-resort font. virtual void ReportLastResortFallbackFontLookup( const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) = 0; + SimpleFontData* resulting_font_data) = 0; virtual void ReportNotDefGlyph() const = 0; @@ -137,8 +137,6 @@ const FontDescription&, const FontFamily& passed_family) = 0; - virtual bool IsContextThread() const = 0; - FontFallbackMap& GetFontFallbackMap(); void Trace(Visitor* visitor) const override;
diff --git a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc index 1e45dfc..53ea5f8 100644 --- a/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc +++ b/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -225,10 +225,13 @@ return; auto paint_image_decoding_mode = ToPaintImageDecodingMode(draw_options.decode_mode); - if (paint_image.decoding_mode() != paint_image_decoding_mode) { - paint_image = PaintImageBuilder::WithCopy(std::move(paint_image)) - .set_decoding_mode(paint_image_decoding_mode) - .TakePaintImage(); + if (paint_image.decoding_mode() != paint_image_decoding_mode || + paint_image.may_be_lcp_candidate() != draw_options.may_be_lcp_candidate) { + paint_image = + PaintImageBuilder::WithCopy(std::move(paint_image)) + .set_decoding_mode(paint_image_decoding_mode) + .set_may_be_lcp_candidate(draw_options.may_be_lcp_candidate) + .TakePaintImage(); } StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect, draw_options, paint_image);
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image.cc b/third_party/blink/renderer/platform/graphics/bitmap_image.cc index 46f42d7..bec446e 100644 --- a/third_party/blink/renderer/platform/graphics/bitmap_image.cc +++ b/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -263,9 +263,11 @@ auto paint_image_decoding_mode = ToPaintImageDecodingMode(draw_options.decode_mode); - if (image.decoding_mode() != paint_image_decoding_mode) { + if (image.decoding_mode() != paint_image_decoding_mode || + image.may_be_lcp_candidate() != draw_options.may_be_lcp_candidate) { image = PaintImageBuilder::WithCopy(std::move(image)) .set_decoding_mode(paint_image_decoding_mode) + .set_may_be_lcp_candidate(draw_options.may_be_lcp_candidate) .TakePaintImage(); }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc index 4d67711..848153b6 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -587,12 +587,6 @@ ids.overscroll_elasticity_transform = property_tree_manager.EnsureCompositorTransformNode( *properties.overscroll_elasticity_transform); - - if (RuntimeEnabledFeatures::FixedElementsDontOverscrollEnabled()) { - property_tree_manager.SetOverscrollTransformNodeId( - ids.overscroll_elasticity_transform); - property_tree_manager.SetFixedElementsDontOverscroll(true); - } } if (properties.overscroll_elasticity_effect) { ids.overscroll_elasticity_effect = @@ -616,6 +610,11 @@ } } + if (RuntimeEnabledFeatures::FixedElementsDontOverscrollEnabled()) { + property_tree_manager.SetOverscrollTransformNodeId( + ids.overscroll_elasticity_transform); + property_tree_manager.SetFixedElementsDontOverscroll(true); + } layer_tree_host->RegisterViewportPropertyIds(ids); } @@ -691,6 +690,10 @@ int effect_id = property_tree_manager.SwitchToEffectNodeWithSynthesizedClip( effect, clip, layer.draws_content()); + if (RuntimeEnabledFeatures::FixedElementsDontOverscrollEnabled() && + transform.RequiresCompositingForFixedToViewport()) + property_tree_manager.SetOverscrollClipNodeId(clip_id); + // We need additional bookkeeping for backdrop-filter mask. if (effect.RequiresCompositingForBackdropFilterMask() && effect.CcNodeId(g_s_property_tree_sequence_number) == effect_id) {
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc index 13c189bc..9926830 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -386,6 +386,10 @@ transform_tree_.set_overscroll_node_id(id); } +void PropertyTreeManager::SetOverscrollClipNodeId(const int id) { + clip_tree_.set_overscroll_node_id(id); +} + void PropertyTreeManager::SetFixedElementsDontOverscroll(const bool value) { transform_tree_.set_fixed_elements_dont_overscroll(value); }
diff --git a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h index 478d956a..1efabd8c 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h +++ b/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
@@ -115,6 +115,7 @@ // Used to offset the scroll translation during overscroll. void SetOverscrollTransformNodeId(const int id); + void SetOverscrollClipNodeId(const int id); void SetFixedElementsDontOverscroll(const bool value); // This function is expected to be invoked right before emitting each layer.
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index 63ce53a..8f967d93 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -751,7 +751,8 @@ const gfx::RectF& dest, const gfx::RectF* src_ptr, SkBlendMode op, - RespectImageOrientationEnum should_respect_image_orientation) { + RespectImageOrientationEnum should_respect_image_orientation, + bool image_may_be_lcp_candidate) { if (!image) return; @@ -764,7 +765,8 @@ DarkModeFilter* dark_mode_filter = GetDarkModeFilterForImage(auto_dark_mode); ImageDrawOptions draw_options( dark_mode_filter, sampling, should_respect_image_orientation, - Image::kClampImageToSourceRect, decode_mode, auto_dark_mode.enabled); + Image::kClampImageToSourceRect, decode_mode, auto_dark_mode.enabled, + image_may_be_lcp_candidate); image->Draw(canvas_, image_flags, dest, src, draw_options); paint_controller_.SetImagePainted(); @@ -777,13 +779,14 @@ const FloatRoundedRect& dest, const gfx::RectF& src_rect, SkBlendMode op, - RespectImageOrientationEnum respect_orientation) { + RespectImageOrientationEnum respect_orientation, + bool image_may_be_lcp_candidate) { if (!image) return; if (!dest.IsRounded()) { DrawImage(image, decode_mode, auto_dark_mode, dest.Rect(), &src_rect, op, - respect_orientation); + respect_orientation, image_may_be_lcp_candidate); return; } @@ -803,7 +806,8 @@ DarkModeFilter* dark_mode_filter = GetDarkModeFilterForImage(auto_dark_mode); ImageDrawOptions draw_options(dark_mode_filter, sampling, respect_orientation, Image::kClampImageToSourceRect, decode_mode, - auto_dark_mode.enabled); + auto_dark_mode.enabled, + image_may_be_lcp_candidate); bool use_shader = (visible_src == src_rect) && (respect_orientation == kDoNotRespectImageOrientation || @@ -865,7 +869,8 @@ const ImageTilingInfo& tiling_info, const ImageAutoDarkMode& auto_dark_mode, SkBlendMode op, - RespectImageOrientationEnum respect_orientation) { + RespectImageOrientationEnum respect_orientation, + bool image_may_be_lcp_candidate) { if (!image) return; @@ -875,7 +880,8 @@ DarkModeFilter* dark_mode_filter = GetDarkModeFilterForImage(auto_dark_mode); ImageDrawOptions draw_options(dark_mode_filter, sampling, respect_orientation, Image::kClampImageToSourceRect, - Image::kSyncDecode, auto_dark_mode.enabled); + Image::kSyncDecode, auto_dark_mode.enabled, + image_may_be_lcp_candidate); image->DrawPattern(*this, image_flags, dest_rect, tiling_info, draw_options); paint_controller_.SetImagePainted();
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.h b/third_party/blink/renderer/platform/graphics/graphics_context.h index 7804b25..329f05d 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.h +++ b/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -93,19 +93,22 @@ RespectImageOrientationEnum respect_orientation, Image::ImageClampingMode clamping_mode, Image::ImageDecodingMode decode_mode, - bool apply_dark_mode) + bool apply_dark_mode, + bool may_be_lcp_candidate) : dark_mode_filter(dark_mode_filter), sampling_options(sampling_options), respect_orientation(respect_orientation), clamping_mode(clamping_mode), decode_mode(decode_mode), - apply_dark_mode(apply_dark_mode) {} + apply_dark_mode(apply_dark_mode), + may_be_lcp_candidate(may_be_lcp_candidate) {} DarkModeFilter* dark_mode_filter = nullptr; SkSamplingOptions sampling_options; RespectImageOrientationEnum respect_orientation = kRespectImageOrientation; Image::ImageClampingMode clamping_mode = Image::kClampImageToSourceRect; Image::ImageDecodingMode decode_mode = Image::kSyncDecode; bool apply_dark_mode = false; + bool may_be_lcp_candidate = false; }; struct AutoDarkMode { @@ -319,20 +322,23 @@ const gfx::RectF& dest_rect, const gfx::RectF* src_rect = nullptr, SkBlendMode = SkBlendMode::kSrcOver, - RespectImageOrientationEnum = kRespectImageOrientation); + RespectImageOrientationEnum = kRespectImageOrientation, + bool image_may_be_lcp_candidate = false); void DrawImageRRect(Image*, Image::ImageDecodingMode, const ImageAutoDarkMode& auto_dark_mode, const FloatRoundedRect& dest, const gfx::RectF& src_rect, SkBlendMode = SkBlendMode::kSrcOver, - RespectImageOrientationEnum = kRespectImageOrientation); + RespectImageOrientationEnum = kRespectImageOrientation, + bool image_may_be_lcp_candidate = false); void DrawImageTiled(Image* image, const gfx::RectF& dest_rect, const ImageTilingInfo& tiling_info, const ImageAutoDarkMode& auto_dark_mode, SkBlendMode = SkBlendMode::kSrcOver, - RespectImageOrientationEnum = kRespectImageOrientation); + RespectImageOrientationEnum = kRespectImageOrientation, + bool image_may_be_lcp_candidate = false); // These methods write to the canvas. // Also drawLine(const gfx::Point& point1, const gfx::Point& point2) and
diff --git a/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc b/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc index 04b3e26c..cc546196 100644 --- a/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc +++ b/third_party/blink/renderer/platform/graphics/paint/cull_rect.cc
@@ -137,7 +137,11 @@ for (const auto* t = &destination.Transform(); t != &source.Transform(); t = t->UnaliasedParent()) { - DCHECK(t); + // TODO(wangxianzhu): This should be DCHECK(t), but for now we need to + // work around crbug.com/1262837 etc. Also see the TODO in + // FragmentData::LocalBorderBoxProperties(). + if (!t) + return false; if (t == &root.Transform()) { abnormal_hierarchy = true; break;
diff --git a/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc b/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc index 968d2bd..3fadffd8 100644 --- a/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc +++ b/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc
@@ -80,8 +80,14 @@ const gfx::RectF& src_rect, const ImageDrawOptions& draw_options) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + auto image = PaintImageForCurrentFrame(); + if (image.may_be_lcp_candidate() != draw_options.may_be_lcp_candidate) { + image = PaintImageBuilder::WithCopy(std::move(image)) + .set_may_be_lcp_candidate(draw_options.may_be_lcp_candidate) + .TakePaintImage(); + } StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect, draw_options, - PaintImageForCurrentFrame()); + image); } PaintImage UnacceleratedStaticBitmapImage::PaintImageForCurrentFrame() {
diff --git a/third_party/blink/renderer/platform/network/parsed_content_header_field_parameters.cc b/third_party/blink/renderer/platform/network/parsed_content_header_field_parameters.cc index fca608a..29705e5 100644 --- a/third_party/blink/renderer/platform/network/parsed_content_header_field_parameters.cc +++ b/third_party/blink/renderer/platform/network/parsed_content_header_field_parameters.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/platform/network/parsed_content_header_field_parameters.h" +#include "base/containers/adapters.h" #include "base/logging.h" #include "third_party/blink/renderer/platform/network/header_field_tokenizer.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" @@ -71,9 +72,9 @@ return String(); String lower_name = name.LowerASCII(); - for (auto i = rbegin(); i != rend(); ++i) { - if (i->name.LowerASCII() == lower_name) - return i->value; + for (const NameValue& param : base::Reversed(*this)) { + if (param.name.LowerASCII() == lower_name) + return param.value; } return String(); }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 9d0ce2d6..7e000f9 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1102,7 +1102,7 @@ }, { name: "FixedElementsDontOverscroll", - status: "stable", + status: "test", }, { name: "Fledge", @@ -2677,6 +2677,11 @@ origin_trial_feature_name: "WebGPU", }, { + // WebGPU developer features are deliberately not enabled by experimental + // web platform features. + name: "WebGPUDeveloperFeatures", + }, + { // Requires both WebGPU and --enable-experimental-web-platform-features name: "WebGPUImportTexture", status: "experimental",
diff --git a/third_party/blink/renderer/platform/testing/font_test_helpers.cc b/third_party/blink/renderer/platform/testing/font_test_helpers.cc index 46c4f45..8f7e6046 100644 --- a/third_party/blink/renderer/platform/testing/font_test_helpers.cc +++ b/third_party/blink/renderer/platform/testing/font_test_helpers.cc
@@ -68,25 +68,24 @@ void ReportFontLookupByUniqueOrFamilyName( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) override {} + SimpleFontData* resulting_font_data) override {} void ReportFontLookupByUniqueNameOnly( const AtomicString& name, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data, + SimpleFontData* resulting_font_data, bool is_loading_fallback = false) override {} void ReportFontLookupByFallbackCharacter( UChar32 hint, FontFallbackPriority fallback_priority, const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) override {} + SimpleFontData* resulting_font_data) override {} void ReportLastResortFallbackFontLookup( const FontDescription& font_description, - scoped_refptr<SimpleFontData> resulting_font_data) override {} + SimpleFontData* resulting_font_data) override {} void ReportNotDefGlyph() const override {} void ReportEmojiSegmentGlyphCoverage(unsigned, unsigned) override {} ExecutionContext* GetExecutionContext() const override { return nullptr; } FontFaceCache* GetFontFaceCache() override { return nullptr; } - bool IsContextThread() const override { return true; } void RegisterForInvalidationCallbacks(FontSelectorClient*) override {} void UnregisterForInvalidationCallbacks(FontSelectorClient*) override {}
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index e6f5913..2ce26e1 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -128,6 +128,9 @@ # //base/task/bind_post_task.h 'base::BindPostTask', + # //base/bind.h + 'base::IgnoreResult', + # //base/bits.h 'base::bits::.+',
diff --git a/third_party/blink/tools/blinkpy/style/checker.py b/third_party/blink/tools/blinkpy/style/checker.py index 1b25a305..20a313a 100644 --- a/third_party/blink/tools/blinkpy/style/checker.py +++ b/third_party/blink/tools/blinkpy/style/checker.py
@@ -41,7 +41,6 @@ from blinkpy.style.checkers.jsonchecker import JSONChecker from blinkpy.style.checkers.png import PNGChecker from blinkpy.style.checkers.python import PythonChecker -from blinkpy.style.checkers.test_expectations import TestExpectationsChecker from blinkpy.style.checkers.text import TextChecker from blinkpy.style.checkers.xcodeproj import XcodeProjectFileChecker from blinkpy.style.checkers.xml import XMLChecker @@ -196,7 +195,6 @@ # Take the union across all checkers. categories = CommonCategories.union(CppChecker.categories) categories = categories.union(JSONChecker.categories) - categories = categories.union(TestExpectationsChecker.categories) categories = categories.union(PNGChecker.categories) return categories @@ -360,14 +358,6 @@ """Return whether the given file should be skipped without a warning.""" if not self._file_type(file_path): # FileType.NONE. return True - # Since "web_tests" is in _SKIPPED_FILES_WITHOUT_WARNING, make - # an exception to prevent files like 'TestExpectations' from being skipped. - # - # FIXME: Figure out a good way to avoid having to add special logic - # for this special case. - basename = os.path.basename(file_path) - if basename == 'TestExpectations': - return False for skipped_file in _SKIPPED_FILES_WITHOUT_WARNING: if self._should_skip_file_path(file_path, skipped_file): return True @@ -399,8 +389,7 @@ return FileType.XCODEPROJ elif file_extension == _PNG_FILE_EXTENSION: return FileType.PNG - elif (file_extension in _TEXT_FILE_EXTENSIONS - or os.path.basename(file_path) == 'TestExpectations'): + elif (file_extension in _TEXT_FILE_EXTENSIONS): return FileType.TEXT else: return FileType.NONE @@ -425,12 +414,7 @@ elif file_type == FileType.PNG: checker = PNGChecker(file_path, handle_style_error) elif file_type == FileType.TEXT: - basename = os.path.basename(file_path) - if basename == 'TestExpectations': - checker = TestExpectationsChecker(file_path, - handle_style_error) - else: - checker = TextChecker(file_path, handle_style_error) + checker = TextChecker(file_path, handle_style_error) else: raise ValueError( 'Invalid file type "%(file_type)s": the only valid file types '
diff --git a/third_party/blink/tools/blinkpy/style/checker_unittest.py b/third_party/blink/tools/blinkpy/style/checker_unittest.py index ef55ac3..23d98b52 100644 --- a/third_party/blink/tools/blinkpy/style/checker_unittest.py +++ b/third_party/blink/tools/blinkpy/style/checker_unittest.py
@@ -263,14 +263,9 @@ def test_should_skip_without_warning__false(self): """Test should_skip_without_warning() for False return values.""" - paths = [ - 'foo.txt', - os.path.join('web_tests', 'TestExpectations'), - ] - - for path in paths: - self._assert_should_skip_without_warning( - path, is_checker_none=False, expected=False) + self._assert_should_skip_without_warning('foo.txt', + is_checker_none=False, + expected=False) class CheckerDispatcherCarriageReturnTest(unittest.TestCase):
diff --git a/third_party/blink/tools/blinkpy/style/checkers/test_expectations.py b/third_party/blink/tools/blinkpy/style/checkers/test_expectations.py deleted file mode 100644 index 48d4e546..0000000 --- a/third_party/blink/tools/blinkpy/style/checkers/test_expectations.py +++ /dev/null
@@ -1,73 +0,0 @@ -# Copyright (C) 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Checks WebKit style for test_expectations files.""" - -import logging - -from blinkpy.style.checkers.common import TabChecker -from blinkpy.common.host import Host -from blinkpy.web_tests.models.typ_types import TestExpectations - - -class TestExpectationsChecker(object): - """Processes TestExpectations lines for validating the syntax.""" - - categories = set(['test/expectations']) - - def __init__(self, file_path, handle_style_error, host=None): - self._file_path = file_path - self._handle_style_error = handle_style_error - self._tab_checker = TabChecker(file_path, handle_style_error) - - # FIXME: host should be a required parameter, not an optional one. - host = host or Host() - - self._port_obj = host.port_factory.get() - - # Suppress error messages of test_expectations module since they will be reported later. - log = logging.getLogger( - 'blinkpy.web_tests.layout_package.test_expectations') - log.setLevel(logging.CRITICAL) - - def check_test_expectations(self, expectations_str, tests=None): - expectations = TestExpectations() - ret, errors = expectations.parse_tagged_list(expectations_str) - if ret: - self._handle_style_error(message=errors) - - def check_tabs(self, lines): - self._tab_checker.check(lines) - - def check(self, lines): - expectations = '\n'.join(lines) - if self._port_obj: - self.check_test_expectations( - expectations_str=expectations, tests=None) - - # Warn tabs in lines as well - self.check_tabs(lines)
diff --git a/third_party/blink/tools/blinkpy/style/checkers/test_expectations_unittest.py b/third_party/blink/tools/blinkpy/style/checkers/test_expectations_unittest.py deleted file mode 100644 index 35a6131..0000000 --- a/third_party/blink/tools/blinkpy/style/checkers/test_expectations_unittest.py +++ /dev/null
@@ -1,121 +0,0 @@ -# Copyright (C) 2010 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import unittest - -from blinkpy.common.host_mock import MockHost -from blinkpy.style.checkers.test_expectations import TestExpectationsChecker - - -class ErrorCollector(object): - """An error handler class for unit tests.""" - - def __init__(self): - self._errors = [] - self.turned_off_filtering = False - - def turn_off_line_filtering(self): - self.turned_off_filtering = True - - def __call__(self, - lineno=0, - category='test/expectations', - confidence=100, - message=''): - self._errors.append('%s\n[%s] [%d]' % (message, category, confidence)) - return True - - def get_errors(self): - return ''.join(self._errors) - - def reset_errors(self): - self._errors = [] - self.turned_off_filtering = False - - -class TestExpectationsTestCase(unittest.TestCase): - """TestCase for test_expectations.py""" - - def setUp(self): - self._error_collector = ErrorCollector() - self._test_file = 'passes/text.html' - - def assert_lines_lint(self, lines, should_pass, expected_output=None): - self._error_collector.reset_errors() - - host = MockHost() - checker = TestExpectationsChecker( - 'test/TestExpectations', self._error_collector, host=host) - - # We should have a valid port, but override it with a test port so we - # can check the lines. - self.assertIsNotNone(checker._port_obj) - checker._port_obj = host.port_factory.get('test-mac-mac10.10') - checker.check_test_expectations( - expectations_str='\n'.join(lines), tests=[self._test_file]) - checker.check_tabs(lines) - if should_pass: - self.assertEqual('', self._error_collector.get_errors()) - elif expected_output: - self.assertEqual(expected_output, - self._error_collector.get_errors()) - else: - self.assertNotEquals('', self._error_collector.get_errors()) - - # Note that a patch might change a line that introduces errors elsewhere, but we - # don't want to lint the whole file (it can unfairly punish patches for pre-existing errors). - # We rely on a separate webkit_lint step on the bots to keep the whole file okay. - # FIXME: See https://bugs.webkit.org/show_bug.cgi?id=104712 . - self.assertFalse(self._error_collector.turned_off_filtering) - - def test_valid_expectations(self): - self.assert_lines_lint([ - '# tags: [ Mac ]\n' - '# results: [ Pass Failure ]\n' - 'crbug.com/1234 [ Mac ] passes/text.html [ Pass Failure ]' - ], - should_pass=True) - - def test_invalid_expectations(self): - self.assert_lines_lint(['Bug(me) passes/text.html [ Give Up]'], - should_pass=False) - - def test_tab(self): - self.assert_lines_lint( - [ - '# results: [ Pass ]\n' - '\tcrbug.com/b/1 passes/text.html [ Pass ]' - ], - should_pass=False, - expected_output='Line contains tab character.\n[whitespace/tab] [5]' - ) - - def test_missing_expectation_not_allowed(self): - self.assert_lines_lint( - ['crbug.com/1234 [ Mac ] passes/text.html [ Missing ]'], - should_pass=False)
diff --git a/third_party/blink/tools/blinkpy/style/main.py b/third_party/blink/tools/blinkpy/style/main.py index 80ac53c8..3addc55 100644 --- a/third_party/blink/tools/blinkpy/style/main.py +++ b/third_party/blink/tools/blinkpy/style/main.py
@@ -102,9 +102,12 @@ def _engage_awesome_stderr_hacks(self): # Change stderr to write with replacement characters so we don't die # if we try to print something containing non-ASCII characters. - stderr = codecs.StreamReaderWriter(sys.stderr, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), 'replace') + # We use sys.stderr.buffer in Python 3, since StreamReaderWriter writes + # bytes to the specified stream (this fix copied from cpplint.py). + stderr = codecs.StreamReaderWriter( + getattr(sys.stderr, 'buffer', sys.stderr), + codecs.getreader('utf8'), codecs.getwriter('utf8'), 'replace') + # Setting an "encoding" attribute on the stream is necessary to # prevent the logging module from raising an error. See # the checker.configure_logging() function for more information.
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index a70f443..5b7af635 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -1984,3 +1984,6 @@ # virtual test suite. wpt_internal/origin-agent-cluster-default/* [ Skip ] virtual/origin-agent-cluster-default/wpt_internal/origin-agent-cluster-default/* [ Pass ] + +# Skip manual tests, see crbug/1114920 +external/wpt/html/semantics/forms/the-input-element/disabled-click-picker-manual.html [ Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index e7ddf09..f46eaba 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1416,10 +1416,7 @@ # Comparing variable font rendering to static font rendering fails on systems that use FreeType for variable fonts crbug.com/1067242 [ Mac10.13 ] external/wpt/css/css-text-decor/text-underline-position-from-font-variable.html [ Failure ] -crbug.com/1067242 [ Mac10.13 ] external/wpt/css/css-text-decor/text-decoration-thickness-fixed.html [ Failure ] crbug.com/1067242 [ Mac10.13 ] external/wpt/css/css-text-decor/text-decoration-thickness-from-font-variable.html [ Failure ] -# Windows 10 bots are not on high enough a Windows version to render variable fonts in DirectWrite -crbug.com/1068947 [ Win ] external/wpt/css/css-text-decor/text-decoration-thickness-fixed.html [ Failure ] # Windows 10 bot upgrade now causes these failures on Windows-10-18363 crbug.com/1140324 [ Win11 ] external/wpt/css/css-text-decor/text-underline-offset-variable.html [ Failure ] crbug.com/1140324 [ Win10.20h2 ] external/wpt/css/css-text-decor/text-underline-offset-variable.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/reference/text-decoration-thickness-fixed-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/reference/text-decoration-thickness-fixed-ref.html index b155eb9c..88f7b46 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/reference/text-decoration-thickness-fixed-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/reference/text-decoration-thickness-fixed-ref.html
@@ -19,7 +19,7 @@ .test { text-underline-position: from-font; -font-size: 62px; +font-size: 64px; line-height: 1.8; } @@ -38,9 +38,9 @@ </head> <body> <p>Test passes if underlines are thin, thick, thin, thick in this order and match the reference rendering.</p> - <div class="test"><span class="thin_underline">aagaa</span></div> - <div class="test"><span class="thick_underline">aagaa</span></div> - <div class="test"><span class="thin_underline">aagaa</span></div> - <div class="test"><span class="thick_underline">aagaa</span></div> + <div class="test"><span class="thin_underline">aaGaa</span></div> + <div class="test"><span class="thick_underline">aaGaa</span></div> + <div class="test"><span class="thin_underline">aaGaa</span></div> + <div class="test"><span class="thick_underline">aaGaa</span></div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-thickness-fixed.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-thickness-fixed.html index 3437c430..07dab0b9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-thickness-fixed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-thickness-fixed.html
@@ -15,7 +15,7 @@ .test { text-underline-position: from-font; -font-size: 62px; +font-size: 64px; line-height: 1.8; } @@ -28,7 +28,7 @@ .thick_underline { font-family: underline-variable; text-decoration: underline; -text-decoration-thickness: 6.2px; +text-decoration-thickness: 6.4px; } .thin_underline_percent { @@ -46,9 +46,9 @@ </head> <body> <p>Test passes if underlines are thin, thick, thin, thick in this order and match the reference rendering.</p> - <div class="test"><span class="thin_underline">aagaa</span></div> - <div class="test"><span class="thick_underline">aagaa</span></div> - <div class="test"><span class="thin_underline_percent">aagaa</span></div> - <div class="test"><span class="thick_underline_percent">aagaa</span></div> + <div class="test"><span class="thin_underline">aaGaa</span></div> + <div class="test"><span class="thick_underline">aaGaa</span></div> + <div class="test"><span class="thin_underline_percent">aaGaa</span></div> + <div class="test"><span class="thick_underline_percent">aaGaa</span></div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-expected.html index 876eacc..03fe48a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for alpha. </p> <script> var canvas, ctx; @@ -22,4 +21,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-expected.html index bd0affb..5b54384a 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works when both alpha and filter are applied. </p> <script> var canvas, ctx; @@ -23,4 +22,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation-expected.html index bd9b5ae..8d84dcb7 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works with global alpha, filter, and global composite operation. </p> <script> var canvas, ctx; @@ -27,4 +26,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation.html index dd1af3d..6912d6a1 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-globalcompositeoperation.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-alpha-filter-globalcompositeoperation-expected.html"> <p class="desc"> Test to ensure beginlayer works with global alpha, filter, and global composite operation. </p> <script> var canvas, ctx; @@ -26,4 +26,3 @@ ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow-expected.html index bfdb26e..89c3f64 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for filter, alpha and shadow. </p> <script> var canvas, ctx; @@ -26,4 +25,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow.html index ae97240..9c4a6fc 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter-shadow.html
@@ -1,4 +1,5 @@ -<body> +<link rel="match" href="layers-alpha-filter-shadow-expected.html"> +<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-18000"> <p class="desc"> Test to ensure beginlayer works for filter, alpha and shadow. </p> <script> var canvas, ctx; @@ -27,4 +28,3 @@ ctx.endLayer(); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter.html index d45b1d5..7a895cf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-filter.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-alpha-filter-expected.html"> <p class="desc"> Test to ensure beginlayer works when both alpha and filter are applied. </p> <script> var canvas, ctx; @@ -22,4 +22,3 @@ ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow-expected.html index 89343e78..f29fb736 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for alpha and shadow. </p> <script> var canvas, ctx; @@ -25,4 +24,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow.html index bfe7241..e7d791d8 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha-shadow.html
@@ -1,4 +1,5 @@ -<body> +<link rel="match" href="layers-alpha-shadow-expected.html"> +<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-18000"> <p class="desc"> Test to ensure beginlayer works for alpha and shadow. </p> <script> var canvas, ctx; @@ -26,4 +27,3 @@ ctx.endLayer(); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha.html index fe871e7e..7be5bdb0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-alpha.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-alpha-expected.html"> <p class="desc"> Test to ensure beginlayer works for alpha. </p> <script> var canvas, ctx; @@ -23,4 +23,3 @@ ctx.endLayer(); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop-expected.html index e3c9571..7f4937ec 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> A test to make sure an unmatched endLayer is a no-op and has no effect on the code following it. </p> <script> var canvas, ctx; @@ -23,4 +22,3 @@ ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop.html index d9d6200..aae72cf 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-endlayer-noop.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-endlayer-noop-expected.html"> <p class="desc"> A test to make sure an unmatched endLayer is a no-op and has no effect on the code following it. </p> <script> var canvas, ctx; @@ -25,4 +25,3 @@ ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-expected.html index a65f52b..7fe4d2c 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for filter. </p> <script> var canvas, ctx; @@ -22,4 +21,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation-expected.html index 3e9fbee..0676d7e1 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for filter and global composition. </p> <script> var canvas, ctx; @@ -27,4 +26,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation.html index 51c79c8..03d04d09 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-globalcompositeoperation.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-filter-globalcompositeoperation-expected.html"> <p class="desc"> Test to ensure beginlayer works for filter and global composition. </p> <script> var canvas, ctx; @@ -26,4 +26,3 @@ ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow-expected.html index 85a5bea..5d141c3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for filter and shadow. </p> <script> var canvas, ctx; @@ -25,4 +24,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow.html index e4da5b8..31ce671 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter-shadow.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-filter-shadow-expected.html"> <p class="desc"> Test to ensure beginlayer works for filter and shadow. </p> <script> var canvas, ctx; @@ -26,4 +26,3 @@ ctx.endLayer(); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter.html index 9dbb09f6..c4d63cd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-filter.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-filter-expected.html"> <p class="desc"> Test to ensure beginlayer works for filter. </p> <script> var canvas, ctx; @@ -21,4 +21,3 @@ ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation-expected.html index 234c1f9e..d2d4317 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for globalCompositeOperation. </p> <script> var canvas, ctx; @@ -22,4 +21,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation.html index 20ce0ca..6d4fde3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-globalcompositeoperation.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-globalcompositeoperation-expected.html"> <p class="desc"> Test to ensure beginlayer works for globalCompositeOperation. </p> <script> var canvas, ctx; @@ -23,4 +23,3 @@ ctx.endLayer(); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer-expected.html index d6e06cd..cec5a54 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> A test to make sure a single endLayer with no beginLayer is a no-op. </p> <script> var canvas, ctx; @@ -17,4 +16,3 @@ ctx.fillStyle = 'rgba(0,255,0,1)'; ctx.fillRect(70,70,75,50); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer.html index e762c5f..f0584d3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-loneendlayer.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-loneendlayer-expected.html"> <p class="desc"> A test to make sure a single endLayer with no beginLayer is a no-op. </p> <script> var canvas, ctx; @@ -19,4 +19,3 @@ ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested-expected.html index c74f1e6..4647996 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested-expected.html
@@ -1,5 +1,3 @@ -<meta name=fuzzy content="maxDifference=0-5;totalPixels=0-100"> -<body> <script> var canvas, ctx; canvas = document.createElement("canvas"); @@ -34,4 +32,3 @@ ctx2.drawImage(canvas3,0,0); ctx.drawImage(canvas2,0,0); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested.html index b1bbdbe..fb52976 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-nested.html
@@ -1,5 +1,5 @@ -<meta name=fuzzy content="maxDifference=0-5;totalPixels=0-100"> -<body> +<link rel="match" href="layers-nested-expected.html"> +<meta name=fuzzy content="maxDifference=0-2; totalPixels=0-14000"> <script> var canvas, ctx; canvas = document.createElement("canvas"); @@ -32,4 +32,3 @@ ctx.endLayer(); ctx.endLayer(); </script> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle-expected.html index 6372dfe..f67a457 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test that ensure layers restores style values upon endLayer. </p> <script> var canvas, ctx; @@ -22,4 +21,3 @@ ctx.fillRect(70,70,75,50); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle.html index 9a20aa07..659b6c0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-restorestyle.html
@@ -1,4 +1,5 @@ -<body> +<link rel="match" href="layers-restorestyle-expected.html"> +<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-14000"> <p class="desc"> Test that ensure layers restores style values upon endLayer. </p> <script> var canvas, ctx; @@ -22,4 +23,3 @@ ctx.fillRect(70,70,75,50); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex-expected.html index 60fffec..eca81cd 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers. </p> <script> var canvas; @@ -32,4 +31,3 @@ ctx.drawImage(canvas2[i],i,i); } </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex.html index 586e1f0..66840bba 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-several-complex.html
@@ -1,4 +1,5 @@ -<body> +<link rel="match" href="layers-several-complex-expected.html"> +<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-19000"> <p class="desc"> Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers. </p> <script> var canvas, ctx; @@ -30,4 +31,3 @@ } </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow-expected.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow-expected.html index c58bc50..7696045 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow-expected.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow-expected.html
@@ -1,4 +1,3 @@ -<body> <p class="desc"> A test to make sure shadow works with layers. </p> <script> var canvas, ctx; @@ -24,4 +23,3 @@ ctx.drawImage(canvas2,0,0); </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow.html b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow.html index a605ef4..59768746 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/element/manual/layers/layers-shadow.html
@@ -1,4 +1,4 @@ -<body> +<link rel="match" href="layers-shadow-expected.html"> <p class="desc"> A test to make sure shadow works with layers. </p> <script> @@ -26,4 +26,3 @@ ctx.endLayer(); </script> -</body>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-code-blocked.html b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-code-blocked.html deleted file mode 100644 index e7ba845..0000000 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-code-blocked.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="resources/object-src-param.js"></script> -<meta http-equiv="Content-Security-Policy" content="object-src http://localhost:8080"> -</head> -<body> -This test passes if there is a console message saying the plugin was blocked. -<script> - appendObjectElement('code'); -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-movie-blocked.html b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-movie-blocked.html deleted file mode 100644 index e9f938c4..0000000 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-movie-blocked.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="resources/object-src-param.js"></script> -<meta http-equiv="Content-Security-Policy" content="object-src http://localhost:8080"> -</head> -<body> -This test passes if there is a console message saying the plugin was blocked. -<script> - appendObjectElement('movie'); -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-src-blocked.html b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-src-blocked.html deleted file mode 100644 index def6f517..0000000 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-src-blocked.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="resources/object-src-param.js"></script> -<meta http-equiv="Content-Security-Policy" content="object-src http://localhost:8080"> -</head> -<body> -This test passes if there is a console message saying the plugin was blocked. -<script> - appendObjectElement('src'); -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-url-blocked.html b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-url-blocked.html deleted file mode 100644 index d4e78d2..0000000 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-param-url-blocked.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="resources/object-src-param.js"></script> -<meta http-equiv="Content-Security-Policy" content="object-src http://localhost:8080"> -</head> -<body> -This test passes if there is a console message saying the plugin was blocked. -<script> - appendObjectElement('url'); -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/resources/object-src-param.js b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/resources/object-src-param.js deleted file mode 100644 index 812aadd..0000000 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/resources/object-src-param.js +++ /dev/null
@@ -1,29 +0,0 @@ -if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.waitUntilDone(); -} - -function appendObjectElement(type) { - window.onload = function () { - var o = document.createElement('object'); - o.setAttribute('type', 'application/x-blink-test-plugin'); - o.addEventListener('load', function () { - console.log('FAIL: The object should have been blocked.'); - if (window.testRunner) - testRunner.notifyDone(); - }); - o.addEventListener('error', function () { - console.log('PASS: Error occurred, so load was correctly blocked.'); - if (window.testRunner) - testRunner.notifyDone(); - }); - - var p = document.createElement('param'); - p.setAttribute('value', 'http://127.0.0.1:8080/plugins/resources/mock-plugin.pl?' + type); - p.setAttribute('name', type); - - o.appendChild(p); - - document.body.appendChild(o); - }; -}
diff --git a/third_party/blink/web_tests/wpt_internal/trust-tokens/README b/third_party/blink/web_tests/wpt_internal/trust-tokens/README deleted file mode 100644 index c243eaf..0000000 --- a/third_party/blink/web_tests/wpt_internal/trust-tokens/README +++ /dev/null
@@ -1,2 +0,0 @@ -This directory contains files for testing trust tokens with WPT using a Python -implementation of a trust token issuer.
diff --git a/third_party/blink/web_tests/wpt_internal/trust-tokens/README.md b/third_party/blink/web_tests/wpt_internal/trust-tokens/README.md new file mode 100644 index 0000000..a43f8fa --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/trust-tokens/README.md
@@ -0,0 +1,75 @@ +# Trust Token Tests + +## Table of Contents + +1. [Overview](#overview) +1. [General Guidelines](#general-guidelines) +1. [File Descriptions](#file-descriptions) +1. [Running Tests](#running-tests) + +## Overview + +The trust token WPTs in this directory are JavaScript tests that interact with a Python implementation of a trust token issuer. +[Python file handlers](https://web-platform-tests.org/writing-tests/python-handlers/index.html) implement the server-side logic for trust token issuance and redemption. +The supported issuer protocol is `TrustTokenV3VOPRF`. + +Please refer to the [trust token API explainer](https://github.com/WICG/trust-token-api) for details about the API. + +## General Guidelines + +- These tests are currently internal only. New tests should be added to `wpt_internal/trust-tokens/`. When trust tokens are implemented by other browser vendors, these files can be transitioned to `third_party/blink/web_tests/external/wpt/trust-tokens/` +- All tests should be [JavaScript tests](https://web-platform-tests.org/writing-tests/testharness.html) +- The key commitment and other arguments to the test runner are defined in `third_party/blink/web_tests/VirtualTestSuites`. The contents of the key commitment are as follows: +```json +{ + "https://web-platform.test:8444": { + "TrustTokenV3VOPRF": { + "protocol_version": "TrustTokenV3VOPRF", + "id": 1, + "batchsize": 1, + "keys": { + "0": { + "Y": "AAAAAASqh8oivosFN46xxx7zIK10bh07Younm5hZ90HgglQqOFUC8l2/VSlsOlReOHJ2CrfJ6CG1adnTkKJhZ0BtbSPWBwviQtdl64MWJc7sSg9HPvWfTjDigX5ihbzihG8V8aA=", + // The timestamp here is equivalent to + // Friday, December 31, 9999 11:59:59 PM GMT + "expiry": "253402300799000000" + } + } + } + } +} +``` + +## File Descriptions + +- `resources/hash_to_field.py` + - Helper module used to implement [hash-to-scalar](https://github.com/WICG/trust-token-api/blob/main/ISSUER_PROTOCOL.md#serializationhashing-1) +- `resources/trust_token_issuance.py` + - Python file handler for token issuance + - Generates a valid response including a DLEQ proof, which is verified by Chromium + - The response is stripped from the `Sec-Trust-Token` header by the browser and is not accessible to JavaScript +- `resources/trust_token_redemption.py` + - Python file handler for token redemption + - The redemption record in the response is an arbitrary byte string, and it is also stripped from the `Sec-Trust-Token` header by the browser +- `resources/trust_token_send_redemption_record.py` + - Python file handler for `send-redemption-record` requests + - Checks for the presence of the `Sec-Redemption-Record` header +- `resources/trust_token_voprf.py` + - Helper module that implements the server side of the issuer protocol +- `trust-token-api-e2e.https.html` + - JavaScript WPT that tests the browser's interaction with the issuer + - Tests `token-request`, `token-redemption`, and `send-redemption-record` + +## Running Tests + +The WPTs run as [virtual tests](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/web_tests/VirtualTestSuites). This enables the issuer's key commitment to be passed to Chromium via a command line argument. + +```bash +# Build web tests +autoninja -C out/Default blink_tests + +# Run a single test +third_party/blink/tools/run_web_tests.py -t Default virtual/trust-tokens/wpt_internal/trust-tokens/trust-token-api-e2e.https.html +``` + +See the [web tests doc](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/web_tests.md#running-the-tests) for more details on using the test runner.
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp index 69d69bf..440f1e93 100644 --- a/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp +++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/util.cpp
@@ -43,8 +43,8 @@ std::pair<char32_t, It> _utf8_decode(It it, It end) { assert(it != end); const char* src = &*it; - int32_t src_len = std::distance(it, end); - int32_t char_index = 0; + size_t src_len = static_cast<size_t>(std::distance(it, end)); + size_t char_index = 0; base_icu::UChar32 code_point_out; base::ReadUnicodeCharacter(src, src_len, &char_index, &code_point_out);
diff --git a/third_party/zxcvbn-cpp/patches/base_utf8.diff b/third_party/zxcvbn-cpp/patches/base_utf8.diff index c7a81c5b..d15bf4a8 100644 --- a/third_party/zxcvbn-cpp/patches/base_utf8.diff +++ b/third_party/zxcvbn-cpp/patches/base_utf8.diff
@@ -56,8 +56,8 @@ +std::pair<char32_t, It> _utf8_decode(It it, It end) { + assert(it != end); + const char* src = &*it; -+ int32_t src_len = std::distance(it, end); -+ int32_t char_index = 0; ++ size_t src_len = static_cast<size_t>(std::distance(it, end)); ++ size_t char_index = 0; + base_icu::UChar32 code_point_out; -bool utf8_valid(std::string::const_iterator start,
diff --git a/tools/android/native_lib_memory/PRESUBMIT.py b/tools/android/native_lib_memory/PRESUBMIT.py index 73f80c8..b5a8c19 100644 --- a/tools/android/native_lib_memory/PRESUBMIT.py +++ b/tools/android/native_lib_memory/PRESUBMIT.py
@@ -18,7 +18,8 @@ output.extend( input_api.canned_checks.RunPylint(input_api, output_api, - files_to_skip=files_to_skip)) + files_to_skip=files_to_skip, + version='1.5')) # These tests don't run on Windows and give verbose and cryptic failure # messages. if input_api.sys.platform != 'win32':
diff --git a/tools/browserbench-webdriver/browserbench.py b/tools/browserbench-webdriver/browserbench.py index a09c7f8..9c69670 100644 --- a/tools/browserbench-webdriver/browserbench.py +++ b/tools/browserbench-webdriver/browserbench.py
@@ -7,6 +7,7 @@ import json import logging +import platform import selenium import subprocess import sys @@ -170,6 +171,13 @@ logging.info('Script starting') + caffeinate_process = None + if platform.system() == 'Darwin': + logging.info('Starting caffeinate') + # Caffeinate ensures the machine is not sleeping/idle. + caffeinate_process = subprocess.Popen( + ['/usr/bin/caffeinate', '-uims', '-t', '300']) + parser = OptionParser() parser.add_option('-b', '--browser', @@ -235,6 +243,8 @@ else: logging.critical('Got exception running, retried too many times, ' 'giving up') + if caffeinate_process: + caffeinate_process.kill() raise e # When rerunning, first try killing the browser in hopes of state # resetting. @@ -242,6 +252,8 @@ logging.info('Test completed') self._ProduceOutput(measurements, extra_key_values) + if caffeinate_process: + caffeinate_process.kill() def AddExtraParserOptions(self, parser): pass
diff --git a/tools/checkperms/PRESUBMIT.py b/tools/checkperms/PRESUBMIT.py index 8f4efcb..f2a8640 100644 --- a/tools/checkperms/PRESUBMIT.py +++ b/tools/checkperms/PRESUBMIT.py
@@ -14,7 +14,8 @@ def CommonChecks(input_api, output_api): output = [] - output.extend(input_api.canned_checks.RunPylint(input_api, output_api)) + output.extend( + input_api.canned_checks.RunPylint(input_api, output_api, version='1.5')) # Run it like if it were a unit test. output.extend( input_api.canned_checks.RunUnitTests(input_api,
diff --git a/tools/code_coverage/create_js_source_maps/PRESUBMIT.py b/tools/code_coverage/create_js_source_maps/PRESUBMIT.py index c4d5f23..0cfee788 100644 --- a/tools/code_coverage/create_js_source_maps/PRESUBMIT.py +++ b/tools/code_coverage/create_js_source_maps/PRESUBMIT.py
@@ -11,7 +11,9 @@ def CheckLint(input_api, output_api): - results = input_api.canned_checks.RunPylint(input_api, output_api) + results = input_api.canned_checks.RunPylint(input_api, + output_api, + version='1.5') results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api, check_js=True)
diff --git a/tools/cygprofile/PRESUBMIT.py b/tools/cygprofile/PRESUBMIT.py index 8efde4c3..8c9edd7 100644 --- a/tools/cygprofile/PRESUBMIT.py +++ b/tools/cygprofile/PRESUBMIT.py
@@ -18,7 +18,8 @@ output.extend( input_api.canned_checks.RunPylint(input_api, output_api, - files_to_skip=files_to_skip)) + files_to_skip=files_to_skip, + version='1.5')) # These tests don't run on Windows and give verbose and cryptic failure # messages.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a5bb677b..65163031 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -13870,6 +13870,11 @@ <int value="3" label="CAPS Service started"/> </enum> +<enum name="CaptionBubbleErrorType"> + <int value="0" label="Generic"/> + <int value="1" label="Media foundation renderer unsupported"/> +</enum> + <enum name="CaptivePortalBlockingPageEvent"> <int value="0" label="SHOW_ALL"/> <int value="1" label="OPEN_LOGIN_PAGE"/> @@ -21217,6 +21222,8 @@ <int value="22" label="SMART_REPLACE_PHRASE"/> <int value="23" label="SMART_INSERT_BEFORE"/> <int value="24" label="SMART_SELECT_BTWN_INCL"/> + <int value="25" label="NAV_NEXT_SENT"/> + <int value="26" label="NAV_PREV_SENT"/> </enum> <enum name="CrosDictationToggleDictationMethod"> @@ -55363,6 +55370,7 @@ <int value="-1804411756" label="ClipboardSuggestionContentHidden:enabled"/> <int value="-1802559277" label="RunTasksByBatches:disabled"/> <int value="-1802502753" label="enable-manual-password-generation:enabled"/> + <int value="-1801515363" label="ThreadedPreloadScanner:enabled"/> <int value="-1799801575" label="CookieDeprecationMessages:enabled"/> <int value="-1798337879" label="enable-md-downloads"/> <int value="-1798258607" label="AdaptiveCharging:disabled"/> @@ -58320,6 +58328,7 @@ <int value="128323385" label="WebUIOmniboxPopup:enabled"/> <int value="129246815" label="AudioSettingsPage:disabled"/> <int value="129458360" label="LiteVideo:disabled"/> + <int value="130059719" label="ThreadedPreloadScanner:disabled"/> <int value="130939792" label="FilesJsModules:disabled"/> <int value="131881947" label="D3DVsync:enabled"/> <int value="132560299" @@ -58959,6 +58968,7 @@ <int value="549483647" label="EnableUnifiedMultiDeviceSettings:disabled"/> <int value="550378029" label="reset-app-list-install-state"/> <int value="550387510" label="NTPAssetDownloadSuggestions:disabled"/> + <int value="550411207" label="enable-webgpu-developer-features"/> <int value="550741462" label="WebAppBorderless:disabled"/> <int value="552317551" label="MediaAppHandlesPdf:disabled"/> <int value="552421509" label="AssistMultiWordExpanded:enabled"/> @@ -91791,6 +91801,7 @@ <int value="49" label="Autofill Wallet Offer"/> <int value="50" label="Workspace Desk"/> <int value="51" label="History"/> + <int value="52" label="Printers Authorization Servers"/> </enum> <enum name="SyncModelTypeStoreInitResult"> @@ -98087,6 +98098,7 @@ <int value="1804492839" label="Colors"/> <int value="1894705443" label="Leisure"/> <int value="1914850019" label="Heritage"/> + <int value="2026958207" label="LGBTQ Artists"/> <int value="2084467495" label="Dessert time"/> <int value="2094027636" label="Solid colors"/> </enum> @@ -98135,6 +98147,8 @@ <int value="-1971674273" label="Leisure - 18438465517979870047"/> <int value="-1953555516" label="Floral - 18439301194079738820"/> <int value="-1938230489" label="Element - 18440708087942279975"/> + <int value="-1934316364" label="LGBTQ Artists - 3223345251527860"/> + <int value="-1927352346" label="LGBTQ Artists - 18438382509191262182"/> <int value="-1916450445" label="Art - 18446537445211457907"/> <int value="-1910580223" label="Solid Colors - 18444350009783540737"/> <int value="-1890583571" label="Heritage - 8492875030461421"/> @@ -98182,6 +98196,7 @@ <int value="-1389216897" label="Landscapes - 3716322142862207"/> <int value="-1382225891" label="Landscapes - 7848789358209053"/> <int value="-1379111552" label="Heritage - 6939063748423040"/> + <int value="-1349646083" label="LGBTQ Artists - 18440020408432199933"/> <int value="-1346329828" label="Collage - 302823912809244"/> <int value="-1315221908" label="Cityscapes - 18438039904557157996"/> <int value="-1308168417" label="Solid Colors - 737212648320799"/> @@ -98229,10 +98244,14 @@ <int value="-755562342" label="Art - 18442108141089261722"/> <int value="-753216621" label="Colors - 6786829258511251"/> <int value="-732111196" label="Solid Colors - 6325085935558308"/> + <int value="-692767506" label="LGBTQ Artists - 18440369104598938862"/> <int value="-671868169" label="Art - 18441859488336321271"/> <int value="-663382773" label="Landscapes - 543123721000203"/> + <int value="-651763227" label="LGBTQ Artists - 18444260070132212197"/> <int value="-650608223" label="Composition - 1914403712172449"/> + <int value="-648909746" label="LGBTQ Artists - 18445559868972756046"/> <int value="-646744548" label="Togetherness - 4852535008654876"/> + <int value="-629215657" label="LGBTQ Artists - 8024729151532631"/> <int value="-628255755" label="Dessert Time - 18439774784268899317"/> <int value="-620910477" label="Cityscapes - 18441185517824223347"/> <int value="-610816140" label="Landscapes - 8626157735358324"/> @@ -98252,6 +98271,7 @@ <int value="-435188694" label="Art - 18444631610789694506"/> <int value="-387775828" label="Cityscapes - 18438479018645979820"/> <int value="-359510740" label="Solid Colors - 18440625901026823468"/> + <int value="-353243221" label="LGBTQ Artists - 18439187396226576299"/> <int value="-347674537" label="Heritage - 6951507300116567"/> <int value="-344702098" label="Landscapes - 18446494149217895278"/> <int value="-335909288" label="Art - 6686963096251992"/> @@ -98328,7 +98348,9 @@ <int value="519669485" label="Made by Canvas - 1162381878724333"/> <int value="519705872" label="Cityscapes - 5269745003271440"/> <int value="523171359" label="Landscapes - 456362273207839"/> + <int value="542400471" label="LGBTQ Artists - 8628186113138647"/> <int value="582571507" label="Cityscapes - 18437958065853126131"/> + <int value="602985801" label="LGBTQ Artists - 18442751988110251337"/> <int value="627281636" label="Cityscapes - 18443580607585029860"/> <int value="632498960" label="Element - 18442926110408911632"/> <int value="636241240" label="Imaginary - 18446507769540134232"/> @@ -98374,6 +98396,7 @@ <int value="1040676664" label="Landscapes - 858440449095480"/> <int value="1123537047" label="Composition - 18445642548865650839"/> <int value="1141632188" label="Cityscapes - 18443148044763131068"/> + <int value="1165024101" label="LGBTQ Artists - 91127486143333"/> <int value="1173629942" label="Colors - 6465464552401910"/> <int value="1192252038" label="Cityscapes - 6488081868804742"/> <int value="1206215167" label="Art - 18445129029773517311"/> @@ -98388,8 +98411,10 @@ <int value="1354190091" label="Landscapes - 8257179059965195"/> <int value="1358808705" label="Cityscapes - 18438573333579417217"/> <int value="1361171564" label="Collage - 18446268433212494956"/> + <int value="1398130163" label="LGBTQ Artists - 18438014764531959283"/> <int value="1404576511" label="Collage - 1050009239298815"/> <int value="1414735641" label="Solid Colors - 2615791116822297"/> + <int value="1446838327" label="LGBTQ Artists - 18441755303138361399"/> <int value="1447770551" label="Composition - 18441221902560868791"/> <int value="1456247150" label="Togetherness - 18444641211933036910"/> <int value="1457778021" label="Cityscapes - 18438203687318056293"/> @@ -98403,6 +98428,7 @@ <int value="1520811358" label="Colors - 273157145869662"/> <int value="1535000622" label="Imaginary - 1900923995439150"/> <int value="1551836957" label="Heritage - 990184787093277"/> + <int value="1559927711" label="LGBTQ Artists - 18441607573556337567"/> <int value="1561201240" label="Solid Colors - 18440201375495096920"/> <int value="1567507477" label="Art - 2184344624841749"/> <int value="1573305199" label="Collage - 18445466155008572271"/> @@ -98418,6 +98444,7 @@ <int value="1650555304" label="Cityscapes - 8018267505523112"/> <int value="1679563589" label="Colors - 3148839772756805"/> <int value="1693366509" label="Cityscapes - 18440922723974559981"/> + <int value="1694862057" label="LGBTQ Artists - 4207995903118057"/> <int value="1696499200" label="Collage - 8802726148212224"/> <int value="1697916989" label="Floral - 4641671638951997"/> <int value="1708825347" label="Leisure - 2442472300649219"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml index 4b601203..f314e4a 100644 --- a/tools/metrics/histograms/metadata/accessibility/histograms.xml +++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -1133,6 +1133,17 @@ </summary> </histogram> +<histogram name="Accessibility.LiveCaption.CaptionBubbleError" + enum="CaptionBubbleErrorType" expires_after="2023-06-13"> + <owner>abigailbklein@google.com</owner> + <owner>evliu@google.com</owner> + <owner>chrome-a11y-core@google.com</owner> + <summary> + Records when the caption bubble displays an error. This is logged once each + time the caption bubble model encounters an error. + </summary> +</histogram> + <histogram name="Accessibility.LiveCaption.Duration.CaptionBubble{Visibility}2" units="ms" expires_after="2022-07-26"> <owner>abigailbklein@google.com</owner> @@ -1230,7 +1241,7 @@ </summary> </histogram> -<histogram name="Accessibility.LiveCaption.Session" +<histogram name="Accessibility.LiveCaption.Session2" enum="LiveCaptionSessionEvent" expires_after="2022-11-27"> <owner>katie@chromium.org</owner> <owner>abigailbklein@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index 7733c09..fdb5993b 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -2292,6 +2292,44 @@ </summary> </histogram> +<histogram name="Blink.SetInnerHtml.ConversionTime" units="microseconds" + expires_after="2022-12-12"> + <owner>sky@chromium.org</owner> + <owner>swarm-team@chromium.org</owner> + <summary> + Time spent converting the v8 string to a blink string when Element.innerHTML + is set. + + This histogram does not record metrics on machines with low-resolution + clocks. + </summary> +</histogram> + +<histogram name="Blink.SetInnerHtml.ExecutionTime" units="microseconds" + expires_after="2022-12-12"> + <owner>sky@chromium.org</owner> + <owner>swarm-team@chromium.org</owner> + <summary> + Time spent processing html string supplied to Element.innerHTML. This + specifically captures the time in Element.SetInnerHTML. + + This histogram does not record metrics on machines with low-resolution + clocks. + </summary> +</histogram> + +<histogram name="Blink.SetInnerHtml.StringLength" units="length" + expires_after="2022-12-12"> + <owner>sky@chromium.org</owner> + <owner>swarm-team@chromium.org</owner> + <summary> + Length of the string supplied to Element.innerHTML. + + This histogram does not record metrics on machines with low-resolution + clocks. + </summary> +</histogram> + <histogram name="Blink.Sms.BackendAvailability" enum="WebOTPBackendAvailability" expires_after="2022-10-30"> <owner>yigu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml index be7b2591..db7fe69 100644 --- a/tools/metrics/histograms/metadata/sync/histograms.xml +++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -45,6 +45,8 @@ <variant name=".PASSWORD" summary="PASSWORD"/> <variant name=".PREFERENCE" summary="PREFERENCE"/> <variant name=".PRINTERS" summary="PRINTERS"/> + <variant name=".PRINTERS_AUTHORIZATION_SERVERS" + summary="PRINTERS_AUTHORIZATION_SERVERS"/> <variant name=".PRIORITY_PREFERENCE" summary="PRIORITY_PREFERENCE"/> <variant name=".PROXY_TABS" summary="PROXY_TABS"/> <variant name=".READING_LIST" summary="READING_LIST"/>
diff --git a/tools/perf/PRESUBMIT.py b/tools/perf/PRESUBMIT.py index 46c55b6..20d8140 100644 --- a/tools/perf/PRESUBMIT.py +++ b/tools/perf/PRESUBMIT.py
@@ -32,9 +32,14 @@ results.extend(_CheckWprShaFiles(input_api, output_api)) results.extend(_CheckShardMaps(input_api, output_api, block_on_failure)) results.extend(_CheckVersionsInSmokeTests(input_api, output_api)) - results.extend(input_api.RunTests(input_api.canned_checks.GetPylint( - input_api, output_api, extra_paths_list=_GetPathsToPrepend(input_api), - pylintrc='pylintrc'))) + results.extend( + input_api.RunTests( + input_api.canned_checks.GetPylint( + input_api, + output_api, + extra_paths_list=_GetPathsToPrepend(input_api), + pylintrc='pylintrc', + version='1.5'))) return results
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 9667b6b..a8eccb14 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,16 +5,16 @@ "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "5c26236044a135f11d8afc32a4e512aab2e8bb16", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/ddc88694c41b71562428bd08b168666c8d42eaf3/trace_processor_shell.exe" + "hash": "bc2c442fac332b89ad0f9ff5c244b64fec3c2b0c", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/6007fadd7cb1b558e89799b409d20529abb8c37f/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "43adeda14c6a325073dff3752e4b67bcf83862c8", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/74fabc35bb05d6d0795387df62cc30c81d517952/trace_processor_shell" + "hash": "37ad669f8e361ec25d649544e36abe883d11385d", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/6007fadd7cb1b558e89799b409d20529abb8c37f/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6", @@ -22,7 +22,7 @@ }, "linux": { "hash": "9e2523358d3118333a637c080edf185cb0613e4a", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/397f8c5e50d7d4d7106e69a8ac378dafc22b1334/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6007fadd7cb1b558e89799b409d20529abb8c37f/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index 908f508..fdf9741 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -1013,10 +1013,11 @@ return 0; std::u16string text = obj->GetHypertext(); - int32_t text_length = text.length(); + size_t text_length = text.length(); offset = obj->UnicodeToUTF16OffsetInText(offset); - int32_t limited_offset = base::clamp(offset, 0, text_length); + offset = std::max(offset, 0); + size_t limited_offset = std::min(static_cast<size_t>(offset), text_length); base_icu::UChar32 code_point; base::ReadUnicodeCharacter(text.c_str(), text_length + 1, &limited_offset, @@ -4343,8 +4344,8 @@ text_unicode_adjustments_.emplace(); std::u16string text = GetHypertext(); - int32_t text_length = text.size(); - for (int32_t i = 0; i < text_length; i++) { + size_t text_length = text.size(); + for (size_t i = 0; i < text_length; i++) { base_icu::UChar32 code_point; size_t original_i = i; base::ReadUnicodeCharacter(text.c_str(), text_length + 1, &i, &code_point);
diff --git a/ui/events/keycodes/dom/keycode_converter.cc b/ui/events/keycodes/dom/keycode_converter.cc index d0f8c2a..f5d61aa 100644 --- a/ui/events/keycodes/dom/keycode_converter.cc +++ b/ui/events/keycodes/dom/keycode_converter.cc
@@ -336,8 +336,8 @@ } // Otherwise, if the string contains a single Unicode character, // the key value is that character. - const auto key_length = static_cast<int32_t>(key.length()); - int32_t char_index = 0; + const size_t key_length = key.length(); + size_t char_index = 0; base_icu::UChar32 character; if (base::ReadUnicodeCharacter(key.data(), key_length, &char_index, &character) &&
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 43a0255..2fb16b9 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -471,13 +471,13 @@ js_library("directory_tree_naming_controller") { deps = [ ":directory_model", + "ui:dialogs", "ui:directory_tree", "//ui/file_manager/file_manager/common/js:api", "//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/externs:volume_info", "//ui/file_manager/file_manager/foreground/js:file_rename", "//ui/webui/resources/js:assert.m", - "//ui/webui/resources/js/cr/ui:dialogs.m", ] } @@ -757,6 +757,7 @@ "ui:directory_tree", "ui:drag_selector", "ui:list_container", + "ui:tree", "//ui/file_manager/file_manager/common/js:api", "//ui/file_manager/file_manager/common/js:file_type", "//ui/file_manager/file_manager/common/js:progress_center_common", @@ -773,7 +774,6 @@ "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr/ui:command.m", "//ui/webui/resources/js/cr/ui:list.m", - "//ui/webui/resources/js/cr/ui:tree", ] } @@ -1042,12 +1042,12 @@ ":directory_contents", ":directory_model", ":file_selection", + "ui:dialogs", "ui:list_container", "//ui/file_manager/file_manager/common/js:api", "//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/foreground/js:file_rename", "//ui/webui/resources/js:assert.m", - "//ui/webui/resources/js/cr/ui:dialogs.m", ] }
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js index e1eb28b..b006bfb 100644 --- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js +++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
@@ -5,7 +5,6 @@ import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; import {Command} from 'chrome://resources/js/cr/ui/command.m.js'; import {List} from 'chrome://resources/js/cr/ui/list.m.js'; -import {TreeItem} from 'chrome://resources/js/cr/ui/tree.js'; import {queryRequiredElement} from 'chrome://resources/js/util.m.js'; import {getDirectory, getDisallowedTransfers, startIOTask} from '../../common/js/api.js'; @@ -28,6 +27,7 @@ import {DirectoryItem, DirectoryTree} from './ui/directory_tree.js'; import {DragSelector} from './ui/drag_selector.js'; import {ListContainer} from './ui/list_container.js'; +import {TreeItem} from './ui/tree.js'; /** * Global (placed in the window object) variable name to hold internal
diff --git a/ui/file_manager/file_manager/foreground/js/naming_controller.js b/ui/file_manager/file_manager/foreground/js/naming_controller.js index 62400d3..b74ad25 100644 --- a/ui/file_manager/file_manager/foreground/js/naming_controller.js +++ b/ui/file_manager/file_manager/foreground/js/naming_controller.js
@@ -3,7 +3,6 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; -import {ConfirmDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js'; import {getFile} from '../../common/js/api.js'; import {strf, UserCanceledError, util} from '../../common/js/util.js'; @@ -13,6 +12,7 @@ import {DirectoryModel} from './directory_model.js'; import {renameEntry, validateEntryName, validateFileName} from './file_rename.js'; import {FileSelectionHandler} from './file_selection.js'; +import {ConfirmDialog} from './ui/dialogs.js'; import {FilesAlertDialog} from './ui/files_alert_dialog.js'; import {ListContainer} from './ui/list_container.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index be7a2b3..1043055 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -30,6 +30,7 @@ ":commandbutton", ":default_task_dialog", ":dialog_footer", + ":dialogs", ":directory_tree", ":drag_selector", ":file_grid", @@ -52,6 +53,7 @@ ":progress_center_panel", ":providers_menu", ":search_box", + ":tree", ] } @@ -80,6 +82,7 @@ ":commandbutton", ":default_task_dialog", ":dialog_footer", + ":dialogs", ":directory_tree", ":drag_selector", ":file_grid", @@ -102,6 +105,7 @@ ":progress_center_panel", ":providers_menu", ":search_box", + ":tree", "table:table", "table:table_column", "table:table_column_model", @@ -199,8 +203,12 @@ ] } +js_library("dialogs") { +} + js_library("directory_tree") { deps = [ + ":tree", "//ui/file_manager/file_manager/common/js:file_type", "//ui/file_manager/file_manager/common/js:metrics", "//ui/file_manager/file_manager/common/js:util", @@ -219,7 +227,6 @@ "//ui/webui/resources/js/cr/ui:command.m", "//ui/webui/resources/js/cr/ui:context_menu_handler.m", "//ui/webui/resources/js/cr/ui:menu.m", - "//ui/webui/resources/js/cr/ui:tree", ] visibility += [ "//ui/file_manager/file_manager/externs:command_handler_deps" ] @@ -294,9 +301,9 @@ js_library("file_manager_dialog_base") { deps = [ + ":dialogs", "//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/common/js:xfm", - "//ui/webui/resources/js/cr/ui:dialogs.m", ] } @@ -318,6 +325,7 @@ ":combobutton", ":default_task_dialog", ":dialog_footer", + ":dialogs", ":directory_tree", ":file_grid", ":file_table", @@ -347,7 +355,6 @@ "//ui/webui/resources/js:util.m", "//ui/webui/resources/js/cr:ui.m", "//ui/webui/resources/js/cr/ui:context_menu_handler.m", - "//ui/webui/resources/js/cr/ui:dialogs.m", "//ui/webui/resources/js/cr/ui:menu.m", "//ui/webui/resources/js/cr/ui:menu_item.m", "//ui/webui/resources/js/cr/ui:splitter", @@ -456,8 +463,8 @@ js_library("files_alert_dialog") { deps = [ + ":dialogs", "//ui/file_manager/file_manager/common/js:util", - "//ui/webui/resources/js/cr/ui:dialogs.m", ] } @@ -465,8 +472,8 @@ js_library("files_confirm_dialog") { deps = [ + ":dialogs", "//ui/file_manager/file_manager/common/js:util", - "//ui/webui/resources/js/cr/ui:dialogs.m", ] } @@ -507,8 +514,8 @@ js_library("import_crostini_image_dialog") { deps = [ + ":dialogs", "//ui/file_manager/file_manager/common/js:util", - "//ui/webui/resources/js/cr/ui:dialogs.m", ] } @@ -615,6 +622,14 @@ externs_list = [ "//ui/file_manager/file_manager/externs/search_item.js" ] } +js_library("tree") { + deps = [ + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:cr.m", + "//ui/webui/resources/js/cr:ui.m", + ] +} + js_library("autocomplete_list") { deps = [ "//ui/webui/resources/js:cr.m",
diff --git a/ui/webui/resources/js/cr/ui/dialogs.js b/ui/file_manager/file_manager/foreground/js/ui/dialogs.js similarity index 95% rename from ui/webui/resources/js/cr/ui/dialogs.js rename to ui/file_manager/file_manager/foreground/js/ui/dialogs.js index 4ae3b36..68745270 100644 --- a/ui/webui/resources/js/cr/ui/dialogs.js +++ b/ui/file_manager/file_manager/foreground/js/ui/dialogs.js
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// #import {isRTL} from 'chrome://resources/js/util.m.js' +import {isRTL} from 'chrome://resources/js/util.m.js'; -cr.define('cr.ui.dialogs', function() { /** * @constructor */ - /* #export */ function BaseDialog(parentNode) { + export function BaseDialog(parentNode) { this.parentNode_ = parentNode; this.document_ = parentNode.ownerDocument; @@ -356,9 +355,9 @@ /** * AlertDialog contains just a message and an ok button. * @constructor - * @extends {cr.ui.dialogs.BaseDialog} + * @extends {BaseDialog} */ - /* #export */ function AlertDialog(parentNode) { + export function AlertDialog(parentNode) { BaseDialog.call(this, parentNode); this.cancelButton.style.display = 'none'; } @@ -378,19 +377,11 @@ /** * ConfirmDialog contains a message, an ok button, and a cancel button. * @constructor - * @extends {cr.ui.dialogs.BaseDialog} + * @extends {BaseDialog} */ - /* #export */ function ConfirmDialog(parentNode) { + export function ConfirmDialog(parentNode) { BaseDialog.call(this, parentNode); } ConfirmDialog.prototype = {__proto__: BaseDialog.prototype}; - // #cr_define_end - console.warn('crbug/1173575, non-JS module files deprecated.'); - return { - BaseDialog: BaseDialog, - AlertDialog: AlertDialog, - ConfirmDialog: ConfirmDialog, - }; -});
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js index 8117195..9c55553 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -7,7 +7,6 @@ import {Command} from 'chrome://resources/js/cr/ui/command.m.js'; import {contextMenuHandler} from 'chrome://resources/js/cr/ui/context_menu_handler.m.js'; import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js'; -import {Tree, TreeItem} from 'chrome://resources/js/cr/ui/tree.js'; import {FileType} from '../../../common/js/file_type.js'; import {metrics} from '../../../common/js/metrics.js'; @@ -23,6 +22,8 @@ import {MetadataModel} from '../metadata/metadata_model.js'; import {NavigationListModel, NavigationModelAndroidAppItem, NavigationModelFakeItem, NavigationModelItem, NavigationModelItemType, NavigationModelShortcutItem, NavigationModelVolumeItem, NavigationSection} from '../navigation_list_model.js'; +import {Tree, TreeItem} from './tree.js'; + // Namespace const directorytree = {};
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js index b5d1d1e..0db9f99 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_dialog_base.js
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {BaseDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js'; - import {util} from '../../../common/js/util.js'; import {xfm} from '../../../common/js/xfm.js'; +import {BaseDialog} from './dialogs.js'; + /** * This class is an extended class, to manage the status of the dialogs. */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index 22379ef..682b736 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -5,7 +5,6 @@ import {assertInstanceof} from 'chrome://resources/js/assert.m.js'; import {decorate, define as crUiDefine} from 'chrome://resources/js/cr/ui.m.js'; import {contextMenuHandler} from 'chrome://resources/js/cr/ui/context_menu_handler.m.js'; -import {BaseDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js'; import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js'; import {MenuItem} from 'chrome://resources/js/cr/ui/menu_item.m.js'; import {Splitter} from 'chrome://resources/js/cr/ui/splitter.js'; @@ -29,6 +28,7 @@ import {ComboButton} from './combobutton.js'; import {DefaultTaskDialog} from './default_task_dialog.js'; import {DialogFooter} from './dialog_footer.js'; +import {BaseDialog} from './dialogs.js'; import {DirectoryTree} from './directory_tree.js'; import {FileGrid} from './file_grid.js'; import {FileTable} from './file_table.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/files_alert_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/files_alert_dialog.js index b73d586..8e43cc8 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/files_alert_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/files_alert_dialog.js
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {AlertDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js'; - import {util} from '../../../common/js/util.js'; +import {AlertDialog} from './dialogs.js'; + /** * Alert dialog. */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js index 41a82556..d0376804 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/files_confirm_dialog.js
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {ConfirmDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js'; - import {util} from '../../../common/js/util.js'; +import {ConfirmDialog} from './dialogs.js'; + /** * Confirm dialog. */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js index 3d852191..4ce8d273 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js
@@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {ConfirmDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js'; - import {str, util} from '../../../common/js/util.js'; +import {ConfirmDialog} from './dialogs.js'; + + /** * ImportCrostiniImageDialog is used as the handler for .tini files.
diff --git a/ui/webui/resources/js/cr/ui/tree.js b/ui/file_manager/file_manager/foreground/js/ui/tree.js similarity index 95% rename from ui/webui/resources/js/cr/ui/tree.js rename to ui/file_manager/file_manager/foreground/js/ui/tree.js index 446adff..1dca296 100644 --- a/ui/webui/resources/js/cr/ui/tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/tree.js
@@ -2,16 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// NOTE: This file depends on ui.js (or the autogenerated ui.m.js module -// version). These files and all files that depend on them are deprecated, and -// should only be used by legacy UIs that have not yet been updated to new -// patterns. Use Web Components in any new code. - // clang-format off -import {assert, assertInstanceof} from '../../assert.m.js'; -import {dispatchSimpleEvent, getPropertyDescriptor, isMac, PropertyKind} from '../../cr.m.js'; -import {getTrustedHTML} from '../../static_types.js'; -import {define as crUiDefine, limitInputWidth} from '../ui.m.js'; +import {assert, assertInstanceof} from 'chrome://resources/js/assert.m.js'; +import {dispatchSimpleEvent, getPropertyDescriptor, PropertyKind} from 'chrome://resources/js/cr.m.js'; +import {getTrustedHTML} from 'chrome://resources/js/static_types.js'; +import {define as crUiDefine, limitInputWidth} from 'chrome://resources/js/cr/ui.m.js'; // clang-format on /** @@ -202,7 +197,7 @@ case 'ArrowLeft': case 'ArrowRight': // Don't let back/forward keyboard shortcuts be used. - if (!isMac && e.altKey || isMac && e.metaKey) { + if (e.altKey) { break; } @@ -659,9 +654,9 @@ } input.addEventListener('keydown', handleKeydown); - input.addEventListener('blur', (function() { - this.editing = false; - }).bind(this)); + input.addEventListener('blur', () => { + this.editing = false; + }); // Make sure that double clicks do not expand and collapse the tree // item.
diff --git a/ui/file_manager/file_names.gni b/ui/file_manager/file_names.gni index febc286..b4e76ef 100644 --- a/ui/file_manager/file_names.gni +++ b/ui/file_manager/file_names.gni
@@ -221,6 +221,7 @@ "file_manager/foreground/js/ui/commandbutton.js", "file_manager/foreground/js/ui/default_task_dialog.js", "file_manager/foreground/js/ui/dialog_footer.js", + "file_manager/foreground/js/ui/dialogs.js", "file_manager/foreground/js/ui/directory_tree.js", "file_manager/foreground/js/ui/drag_selector.js", "file_manager/foreground/js/ui/file_grid.js", @@ -250,6 +251,7 @@ "file_manager/foreground/js/ui/table/table_header.js", "file_manager/foreground/js/ui/table/table_list.js", "file_manager/foreground/js/ui/table/table_splitter.js", + "file_manager/foreground/js/ui/tree.js", ] # END: static_js_files.
diff --git a/ui/file_manager/tsconfig_base.json b/ui/file_manager/tsconfig_base.json index f79e3053..9844915 100644 --- a/ui/file_manager/tsconfig_base.json +++ b/ui/file_manager/tsconfig_base.json
@@ -2,6 +2,12 @@ "extends": "../../tools/typescript/tsconfig_base.json", "compilerOptions": { "allowJs": true, - "importsNotUsedAsValues": "preserve" + "importsNotUsedAsValues": "preserve", + "typeRoots": [ + "../../third_party/node/node_modules/@types" + ], + "types": [ + "trusted-types" + ] } }
diff --git a/ui/ozone/platform/README b/ui/ozone/platform/README index cc91d3b7..70ca9c1 100644 --- a/ui/ozone/platform/README +++ b/ui/ozone/platform/README
@@ -1,2 +1,4 @@ This directory contains implementations of platforms. Each platform implements the interfaces from ui/ozone/public for the rest of chromium. + +See docs/ozone_overview.md for details.
diff --git a/ui/shell_dialogs/execute_select_file_win.cc b/ui/shell_dialogs/execute_select_file_win.cc index 063d4c7c..162dbc3 100644 --- a/ui/shell_dialogs/execute_select_file_win.cc +++ b/ui/shell_dialogs/execute_select_file_win.cc
@@ -10,6 +10,7 @@ #include "base/callback.h" #include "base/files/file.h" #include "base/files/file_util.h" +#include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "base/win/com_init_util.h" #include "base/win/registry.h" @@ -50,7 +51,7 @@ default_folder = default_path; } else { default_folder = default_path.DirName(); - default_file_name = default_path.BaseName(); + default_file_name = GetSanitizedFileName(default_path.BaseName()); } // Do not fail the file dialog operation if the specified folder is invalid. @@ -371,6 +372,33 @@ return return_value; } +base::FilePath GetSanitizedFileName(const base::FilePath& file_name) { + base::StringTokenizerT<std::wstring, std::wstring::const_iterator> t( + file_name.value(), L"%"); + t.set_options(base::StringTokenizer::RETURN_EMPTY_TOKENS); + std::wstring result; + bool token_valid = t.GetNext(); + while (token_valid) { + // Append substring before the first "%". + result.append(t.token()); + // Done if we are reaching the end delimiter, + if (!t.GetNext()) { + break; + } + std::wstring string_after_first_percent = t.token(); + token_valid = t.GetNext(); + // If there are no other "%", append the string after + // the first "%". Otherwise, remove the string between + // the "%" and continue handing the remaining string. + if (!token_valid) { + result.append(L"%"); + result.append(string_after_first_percent); + break; + } + } + return base::FilePath(result); +} + void ExecuteSelectFile( SelectFileDialog::Type type, const std::u16string& title,
diff --git a/ui/shell_dialogs/execute_select_file_win.h b/ui/shell_dialogs/execute_select_file_win.h index dc808af3..8fa96906 100644 --- a/ui/shell_dialogs/execute_select_file_win.h +++ b/ui/shell_dialogs/execute_select_file_win.h
@@ -26,6 +26,12 @@ const std::wstring& filter_selected, const std::wstring& suggested_ext); +// Given a file name, return the sanitized version by removing substrings that +// are embedded in double '%' characters as those are reserved for environment +// variables. Implementation detail exported for unit tests. +SHELL_DIALOGS_EXPORT base::FilePath GetSanitizedFileName( + const base::FilePath& file_name); + // Describes a filter for a file dialog. struct FileFilterSpec { // A human readable description of this filter. E.g. "HTML Files."
diff --git a/ui/shell_dialogs/execute_select_file_win_unittest.cc b/ui/shell_dialogs/execute_select_file_win_unittest.cc index df5e8a8..b6c604f 100644 --- a/ui/shell_dialogs/execute_select_file_win_unittest.cc +++ b/ui/shell_dialogs/execute_select_file_win_unittest.cc
@@ -50,3 +50,38 @@ test_cases[i].suggested_ext)); } } + +TEST(ShellDialogsWin, GetSanitizedFileName) { + struct GetSanitizedFileNameTestCase { + const wchar_t* filename; + const wchar_t* sanitized_filename; + } test_cases[] = { + {L"", L""}, + {L"a.txt", L"a.txt"}, + + // Only 1 "%" in file name. + {L"%", L"%"}, + {L"%.txt", L"%.txt"}, + {L"ab%c.txt", L"ab%c.txt"}, + {L"abc.t%", L"abc.t%"}, + + // 2 "%" in file name. + {L"%%", L""}, + {L"%c%", L""}, + {L"%c%d", L"d"}, + {L"d%c%.txt", L"d.txt"}, + {L"ab%c.t%", L"ab"}, + {L"abc.%t%", L"abc."}, + + // More than 2 "%" in file name. + {L"%ab%c%.txt", L"c%.txt"}, + {L"%abc%.%txt%", L"."}, + {L"%ab%c%.%txt%", L"ctxt%"}, + }; + + for (size_t i = 0; i < std::size(test_cases); ++i) { + SCOPED_TRACE(base::StringPrintf("i=%zu", i)); + EXPECT_EQ(base::FilePath(test_cases[i].sanitized_filename), + ui::GetSanitizedFileName(base::FilePath(test_cases[i].filename))); + } +}
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index 8c979f96..33c5c7d 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn
@@ -206,7 +206,6 @@ "cr_components/chromeos/smb_shares/add_smb_share_dialog.d.ts", "cr_components/chromeos/smb_shares/smb_browser_proxy.d.ts", "js/cr/ui/context_menu_handler.m.d.ts", - "js/cr/ui/dialogs.m.d.ts", "js/cr/ui/grid.m.d.ts", "js/cr/ui/list.m.d.ts", "js/cr/ui/menu_button.m.d.ts", @@ -290,7 +289,6 @@ "js/cr/ui/position_util.m.js", "js/cr/ui/splitter.js", "js/cr/ui/store_client.js", - "js/cr/ui/tree.js", ] } } @@ -299,6 +297,10 @@ generate_definitions_js_files += [ "js/cr/ui/focus_without_ink.m.js" ] } +if (is_ios) { + generate_definitions_js_files += [ "js/ios/web_ui.js" ] +} + ts_library("library") { root_dir = preprocessed_folder out_dir = preprocessed_folder @@ -306,6 +308,7 @@ tsconfig_base = "tsconfig_base.json" in_files = [ + "cr_elements/cr_splitter/cr_splitter.ts", "cr_elements/cr_tab_box/cr_tab_box.ts", "cr_elements/cr_tab_box/cr_tab_box.html.ts", "cr_elements/cr_tree/cr_tree.ts", @@ -351,7 +354,6 @@ "cr_elements/cr_search_field/cr_search_field.ts", "cr_elements/cr_slider/cr_slider.html.ts", "cr_elements/cr_slider/cr_slider.ts", - "cr_elements/cr_splitter/cr_splitter.ts", "cr_elements/cr_tabs/cr_tabs.html.ts", "cr_elements/cr_tabs/cr_tabs.ts", "cr_elements/cr_toast/cr_toast_manager.html.ts",
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn index 9a0313f6..617cf46 100644 --- a/ui/webui/resources/cr_elements/BUILD.gn +++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -79,6 +79,7 @@ in_folder = "." out_folder = preprocess_folder in_files = [ + "cr_splitter/cr_splitter.ts", "cr_tab_box/cr_tab_box.ts", "cr_tree/cr_tree_base.ts", "cr_tree/cr_tree_item.ts", @@ -99,7 +100,6 @@ "cr_search_field/cr_search_field_mixin.ts", "cr_search_field/cr_search_field.ts", "cr_slider/cr_slider.ts", - "cr_splitter/cr_splitter.ts", "cr_tabs/cr_tabs.ts", "cr_toast/cr_toast_manager.ts", "cr_toast/cr_toast.ts",
diff --git a/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.ts b/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.ts index 7b2ae6ab..b1785b4 100644 --- a/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.ts +++ b/ui/webui/resources/cr_elements/cr_splitter/cr_splitter.ts
@@ -3,41 +3,28 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert_ts.js'; -import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -export class CrSplitterElement extends PolymerElement { +export class CrSplitterElement extends HTMLElement { static get is() { return 'cr-splitter'; } - static get template() { - return null; - } - - static get properties() { - return { - resizeNextElement: Boolean, - }; - } - private handlers_: Map<string, (e: any) => void>|null = null; private startX_: number = 0; private startWidth_: number = -1; resizeNextElement: boolean = false; - override ready() { - super.ready(); + constructor() { + super(); this.addEventListener('mousedown', e => this.onMouseDown_(e)); this.addEventListener('touchstart', e => this.onTouchStart_(e)); } - override connectedCallback() { - super.connectedCallback(); + connectedCallback() { this.handlers_ = new Map(); } - override disconnectedCallback() { - super.disconnectedCallback(); + disconnectedCallback() { this.removeAllHandlers_(); this.handlers_ = null; }
diff --git a/ui/webui/resources/css/BUILD.gn b/ui/webui/resources/css/BUILD.gn index 3801cb7..985218e 100644 --- a/ui/webui/resources/css/BUILD.gn +++ b/ui/webui/resources/css/BUILD.gn
@@ -36,7 +36,6 @@ "text_defaults.css", "text_defaults_md.css", "throbber.css", - "tree.css", "widgets.css", ]
diff --git a/ui/webui/resources/css/tree.css b/ui/webui/resources/css/tree.css deleted file mode 100644 index d0f7939c..0000000 --- a/ui/webui/resources/css/tree.css +++ /dev/null
@@ -1,185 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -tree { - display: block; - outline: none; - overflow: auto; -} - -.tree-item > .tree-row { - align-items: center; - background-color: rgba(255, 255, 255, 0); - border: 1px solid rgba(255, 255, 255, 0); /* transparent white */ - border-radius: 2px; - color: black; - cursor: default; - display: flex; - line-height: 28px; - padding: 0 3px; - position: relative; - user-select: none; - white-space: nowrap; -} - -.expand-icon { - background: url(../images/tree_triangle.svg) no-repeat center center; - background-size: 8px 5.5px; - height: 16px; - min-width: 16px; - opacity: .6; - transform: rotate(-90deg); - transition: all 150ms; - width: 16px; -} - -html[dir=rtl] .expand-icon { - transform: rotate(90deg); -} - -.tree-item[expanded] > .tree-row > .expand-icon { - background-image: url(../images/tree_triangle.svg); - opacity: .5; - transform: rotate(0); -} - -.tree-row .expand-icon { - visibility: hidden; -} - -.tree-row[may-have-children] .expand-icon { - visibility: visible; -} - -.tree-row[has-children=false] .expand-icon { - visibility: hidden; -} - -.tree-row:hover { - background-color: hsl(214, 91%, 97%); - border-color: hsl(214, 91%, 85%); - z-index: 1; -} - -/* WebKit has a bug with attribute selectors so we apply selected to the tree - * row as well. https://bugs.webkit.org/show_bug.cgi?id=12519. */ -.tree-row[selected] { - background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.8), - rgba(255,255,255,0)); -} - -.tree-row[selected] { - background-color: hsl(0, 0%, 90%); - border-color: hsl(0, 0%, 85%); - z-index: 2; -} - -.tree-row[selected]:hover, -tree:focus .tree-row[selected] { - background-color: hsl(214, 91%, 89%); - border-color: rgb(125, 162, 206); -} - -.tree-children[expanded] { - display: block; -} - -.tree-children { - display: none; -} - -.tree-item > .tree-row > * { - box-sizing: border-box; - display: inline-block; -} - -.tree-label-icon { - background-position: 0 50%; - background-repeat: no-repeat; - height: 20px; - min-width: 20px; - width: 20px; -} - -.tree-label { - white-space: pre; -} - -.tree-label-icon, -.tree-row[may-have-children] > .tree-label-icon { - background-image: url(chrome://theme/IDR_FOLDER_CLOSED); -} - -<if expr="is_macosx or is_ios"> -@media (prefers-color-scheme: dark) { - .tree-label-icon, - .tree-row[may-have-children] > .tree-label-icon { - background-image: url(chrome://theme/IDR_FOLDER_CLOSED_WHITE); - } -} -</if> - -<if expr="not is_macosx and not is_ios"> -.tree-item[expanded] > .tree-row > .tree-label-icon { - background-image: url(chrome://theme/IDR_FOLDER_OPEN); -} -</if> - -html[dir=rtl] .tree-label-icon, -html[dir=rtl] .tree-row[may-have-children] > .tree-label-icon, -html[dir=rtl] .tree-item[expanded] > .tree-row > .tree-label-icon { - transform: scaleX(-1); -} - -tree[icon-visibility=hidden] .tree-label-icon { - display: none; -} - -tree[icon-visibility=parent] .tree-label-icon, -tree[icon-visibility=parent] .tree-row[has-children=false] > .tree-label-icon { - background-image: none; -} - -/* We need to ensure that even empty labels take up space */ -.tree-label:empty::after { - content: ' '; - white-space: pre; -} - -.tree-rename > .tree-row > .tree-label { - -webkit-user-modify: read-write-plaintext-only; - background: white; - color: black; - outline: 1px solid black; - user-select: auto; -} - -.tree-item[editing] input { - /* Do not inherit the line-height */ - font-family: inherit; - font-size: inherit; - font-weight: inherit; - margin: -2px -8px -2px -3px; -<if expr="not is_macosx and not is_ios"> - outline: none; -</if> - padding: 1px 7px 1px 1px; -} - -html[dir=rtl] .tree-item[editing] input { - margin: -2px -3px -2px -8px; - padding: 1px 1px 1px 7px; -} - -@media(forced-colors) { - .tree-row[selected], - .tree-row:hover, - .tree-row[selected]:hover, - tree:focus .tree-row[selected] { - background-color: Highlight; - background-image: none; - color: HighlightText; - forced-color-adjust: none; - } -}
diff --git a/ui/webui/resources/js/cr.gni b/ui/webui/resources/js/cr.gni index 1a20b8a..7fb7ae5 100644 --- a/ui/webui/resources/js/cr.gni +++ b/ui/webui/resources/js/cr.gni
@@ -10,9 +10,6 @@ "cr.ui.Command|Command", "cr.ui.contextMenuHandler|contextMenuHandler", "cr.ui.decorate|decorate", - "cr.ui.dialogs.BaseDialog|BaseDialog", - "cr.ui.dialogs.AlertDialog|AlertDialog", - "cr.ui.dialogs.ConfirmDialog|ConfirmDialog", "cr.ui.Action|Action", "cr.ui.AnchorType|AnchorType", "cr.ui.ArrayDataModel|ArrayDataModel", @@ -35,8 +32,5 @@ "cr.ui.Size|Size", "cr.ui.Splitter|Splitter", "cr.ui.StoreObserver|StoreObserver", - "cr.ui.Tab|Tab", - "cr.ui.Tree|Tree", - "cr.ui.TreeItem|TreeItem", "cr.ui.VirtualFocusRow|VirtualFocusRow", ]
diff --git a/ui/webui/resources/js/cr/ui/BUILD.gn b/ui/webui/resources/js/cr/ui/BUILD.gn index 4114d43..672dbf7 100644 --- a/ui/webui/resources/js/cr/ui/BUILD.gn +++ b/ui/webui/resources/js/cr/ui/BUILD.gn
@@ -41,7 +41,6 @@ "focus_outline_manager.js", "splitter.js", "store.js", - "tree.js", ] if (is_chromeos_ash) { @@ -49,7 +48,6 @@ "array_data_model.js", "command.js", "context_menu_handler.js", - "dialogs.js", "focus_manager.js", "focus_row.js", "focus_row_behavior.js", @@ -101,7 +99,6 @@ if (is_chromeos_ash) { in_files += [ - "dialogs.m.js", "grid.m.js", "list_single_selection_model.m.js", ] @@ -121,7 +118,6 @@ ":array_data_model", ":command", ":context_menu_handler", - ":dialogs", ":focus_manager", ":focus_outline_manager", ":focus_row", @@ -172,13 +168,6 @@ ] } -js_library("dialogs") { - deps = [ - "../..:cr", - "../..:util", - ] -} - js_library("focus_manager") { deps = [ "../..:cr" ] } @@ -295,7 +284,6 @@ "array_data_model.js", "command.js", "context_menu_handler.js", - "dialogs.js", "focus_outline_manager.js", "focus_row.js", "focus_row_behavior.js", @@ -321,7 +309,6 @@ ":array_data_model.m", ":command.m", ":context_menu_handler.m", - ":dialogs.m", ":drag_wrapper", ":focus_grid", ":focus_outline_manager.m", @@ -342,7 +329,6 @@ ":splitter", ":store", ":store_client", - ":tree", ] } @@ -387,11 +373,6 @@ extra_deps = [ ":modulize" ] } -js_library("dialogs.m") { - sources = [ "$root_gen_dir/ui/webui/resources/js/cr/ui/dialogs.m.js" ] - extra_deps = [ ":modulize" ] -} - js_library("drag_wrapper") { } @@ -566,11 +547,3 @@ "../..:assert.m", ] } - -js_library("tree") { - deps = [ - "../:ui.m", - "../..:assert.m", - "../..:cr.m", - ] -}
diff --git a/ui/webui/resources/js/cr/ui/dialogs.m.d.ts b/ui/webui/resources/js/cr/ui/dialogs.m.d.ts deleted file mode 100644 index b78a1d5..0000000 --- a/ui/webui/resources/js/cr/ui/dialogs.m.d.ts +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2022 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -export class BaseDialog { - constructor(parentNode: any); - setOkLabel(label: string): void; - setCancelLabel(label: string): void; - setInitialFocusOnCancel(): void; - show( - message: string, onOk?: Function|undefined, onCancel?: Function|undefined, - onShow?: Function|undefined): void; - showHtml( - title: string, message: string, onOk?: Function|undefined, - onCancel?: Function|undefined, onShow?: Function|undefined): void; - showWithTitle( - title: string, message: string, onOk?: Function|undefined, - onCancel?: Function|undefined, onShow?: Function|undefined): void; - hide(onHide?: Function|undefined): void; - - /* eslint-disable @typescript-eslint/naming-convention */ - OK_LABEL: string; - CANCEL_LABEL: string; - ANIMATE_STABLE_DURATION: number; - /* eslint-enable @typescript-eslint/naming-convention */ -} - -export class AlertDialog extends BaseDialog { - constructor(parentNode: any); - show(message: any, onOk?: Function|undefined, onShow?: Function|undefined): - any; -} - -export class ConfirmDialog extends BaseDialog { - constructor(parentNode: any); -}
diff --git a/url/url_canon_etc.cc b/url/url_canon_etc.cc index 851926da..53b71ea 100644 --- a/url/url_canon_etc.cc +++ b/url/url_canon_etc.cc
@@ -101,7 +101,7 @@ const Component& scheme, CanonOutput* output, Component* out_scheme) { - if (scheme.len <= 0) { + if (!scheme.is_nonempty()) { // Scheme is unspecified or empty, convert to empty by appending a colon. *out_scheme = Component(output->length(), 0); output->push_back(':'); @@ -117,12 +117,13 @@ // FindAndCompareScheme, which could cause some security checks on // schemes to be incorrect. bool success = true; - int end = scheme.end(); - for (int i = scheme.begin; i < end; i++) { + size_t begin = static_cast<size_t>(scheme.begin); + size_t end = static_cast<size_t>(scheme.end()); + for (size_t i = begin; i < end; i++) { UCHAR ch = static_cast<UCHAR>(spec[i]); char replacement = 0; if (ch < 0x80) { - if (i == scheme.begin) { + if (i == begin) { // Need to do a special check for the first letter of the scheme. if (IsSchemeFirstChar(static_cast<unsigned char>(ch))) replacement = kSchemeCanonical[ch]; @@ -179,8 +180,9 @@ out_username->begin = output->length(); if (username.len > 0) { // This will escape characters not valid for the username. - AppendStringOfType(&username_spec[username.begin], username.len, - CHAR_USERINFO, output); + AppendStringOfType(&username_spec[username.begin], + static_cast<size_t>(username.len), CHAR_USERINFO, + output); } out_username->len = output->length() - out_username->begin; @@ -189,8 +191,9 @@ if (password.len > 0) { output->push_back(':'); out_password->begin = output->length(); - AppendStringOfType(&password_spec[password.begin], password.len, - CHAR_USERINFO, output); + AppendStringOfType(&password_spec[password.begin], + static_cast<size_t>(password.len), CHAR_USERINFO, + output); out_password->len = output->length() - out_password->begin; } else { *out_password = Component(); @@ -223,7 +226,8 @@ // what the error was, and mark the URL as invalid by returning false. output->push_back(':'); out_port->begin = output->length(); - AppendInvalidNarrowString(spec, port.begin, port.end(), output); + AppendInvalidNarrowString(spec, static_cast<size_t>(port.begin), + static_cast<size_t>(port.end()), output); out_port->len = output->length() - out_port->begin; return false; } @@ -285,7 +289,7 @@ const Component& ref, CanonOutput* output, Component* out_ref) { - if (ref.len < 0) { + if (!ref.is_valid()) { // Common case of no ref. *out_ref = Component(); return; @@ -297,8 +301,8 @@ out_ref->begin = output->length(); // Now iterate through all the characters, converting to UTF-8 and validating. - int end = ref.end(); - for (int i = ref.begin; i < end; i++) { + size_t end = static_cast<size_t>(ref.end()); + for (size_t i = static_cast<size_t>(ref.begin); i < end; i++) { UCHAR current_char = static_cast<UCHAR>(spec[i]); if (current_char < 0x80) { if (kShouldEscapeCharInFragment[current_char])
diff --git a/url/url_canon_host.cc b/url/url_canon_host.cc index c2cd9d1..5f7bf71 100644 --- a/url/url_canon_host.cc +++ b/url/url_canon_host.cc
@@ -123,15 +123,15 @@ // |*has_non_ascii| flag. // // The return value indicates if the output is a potentially valid host name. -template<typename INCHAR, typename OUTCHAR> +template <typename INCHAR, typename OUTCHAR> bool DoSimpleHost(const INCHAR* host, - int host_len, + size_t host_len, CanonOutputT<OUTCHAR>* output, bool* has_non_ascii) { *has_non_ascii = false; bool success = true; - for (int i = 0; i < host_len; ++i) { + for (size_t i = 0; i < host_len; ++i) { unsigned int source = host[i]; if (source == '%') { // Unescape first, if possible. @@ -175,7 +175,7 @@ } // Canonicalizes a host that requires IDN conversion. Returns true on success -bool DoIDNHost(const char16_t* src, int src_len, CanonOutput* output) { +bool DoIDNHost(const char16_t* src, size_t src_len, CanonOutput* output) { int original_output_len = output->length(); // So we can rewind below. // We need to escape URL before doing IDN conversion, since punicode strings @@ -202,8 +202,8 @@ // unescaping. Although we unescaped everything before this function call, if // somebody does %00 as fullwidth, ICU will convert this to ASCII. bool success = DoSimpleHost(wide_output.data(), - wide_output.length(), - output, &has_non_ascii); + static_cast<size_t>(wide_output.length()), output, + &has_non_ascii); if (has_non_ascii) { // ICU generated something that DoSimpleHost didn't think looked like // ASCII. This is quite rare, but ICU might convert some characters to @@ -220,7 +220,8 @@ // ASCII isn't strictly necessary, but DoSimpleHost handles this case // anyway so we handle it/ output->set_length(original_output_len); - AppendInvalidNarrowString(wide_output.data(), 0, wide_output.length(), + AppendInvalidNarrowString(wide_output.data(), 0, + static_cast<size_t>(wide_output.length()), output); return false; } @@ -230,8 +231,11 @@ // 8-bit convert host to its ASCII version: this converts the UTF-8 input to // UTF-16. The has_escaped flag should be set if the input string requires // unescaping. -bool DoComplexHost(const char* host, int host_len, - bool has_non_ascii, bool has_escaped, CanonOutput* output) { +bool DoComplexHost(const char* host, + size_t host_len, + bool has_non_ascii, + bool has_escaped, + CanonOutput* output) { // Save the current position in the output. We may write stuff and rewind it // below, so we need to know where to rewind to. int begin_length = output->length(); @@ -239,7 +243,7 @@ // Points to the UTF-8 data we want to convert. This will either be the // input or the unescaped version written to |*output| if necessary. const char* utf8_source; - int utf8_source_len; + size_t utf8_source_len; bool are_all_escaped_valid = true; if (has_escaped) { // Unescape before converting to UTF-16 for IDN. We write this into the @@ -264,7 +268,7 @@ // Save the pointer into the data was just converted (it may be appended to // other data in the output buffer). utf8_source = &output->data()[begin_length]; - utf8_source_len = output->length() - begin_length; + utf8_source_len = static_cast<size_t>(output->length() - begin_length); } else { // We don't need to unescape, use input for IDNization later. (We know the // input has non-ASCII, or the simple version would have been called @@ -280,17 +284,18 @@ if (!ConvertUTF8ToUTF16(utf8_source, utf8_source_len, &utf16)) { // In this error case, the input may or may not be the output. StackBuffer utf8; - for (int i = 0; i < utf8_source_len; i++) + for (size_t i = 0; i < utf8_source_len; i++) utf8.push_back(utf8_source[i]); output->set_length(begin_length); - AppendInvalidNarrowString(utf8.data(), 0, utf8.length(), output); + AppendInvalidNarrowString(utf8.data(), 0, + static_cast<size_t>(utf8.length()), output); return false; } output->set_length(begin_length); // This will call DoSimpleHost which will do normal ASCII canonicalization // and also check for IP addresses in the outpt. - return DoIDNHost(utf16.data(), utf16.length(), output) && + return DoIDNHost(utf16.data(), static_cast<size_t>(utf16.length()), output) && are_all_escaped_valid; } @@ -298,7 +303,7 @@ // the backend, so we just pass through. The has_escaped flag should be set if // the input string requires unescaping. bool DoComplexHost(const char16_t* host, - int host_len, + size_t host_len, bool has_non_ascii, bool has_escaped, CanonOutput* output) { @@ -319,8 +324,8 @@ // Once we convert to UTF-8, we can use the 8-bit version of the complex // host handling code above. - return DoComplexHost(utf8.data(), utf8.length(), has_non_ascii, - has_escaped, output); + return DoComplexHost(utf8.data(), static_cast<size_t>(utf8.length()), + has_non_ascii, has_escaped, output); } // No unescaping necessary, we can safely pass the input to ICU. This @@ -334,16 +339,18 @@ bool DoHostSubstring(const CHAR* spec, const Component& host, CanonOutput* output) { + DCHECK(host.is_valid()); + bool has_non_ascii, has_escaped; ScanHostname<CHAR, UCHAR>(spec, host, &has_non_ascii, &has_escaped); if (has_non_ascii || has_escaped) { - return DoComplexHost(&spec[host.begin], host.len, has_non_ascii, - has_escaped, output); + return DoComplexHost(&spec[host.begin], static_cast<size_t>(host.len), + has_non_ascii, has_escaped, output); } - const bool success = - DoSimpleHost(&spec[host.begin], host.len, output, &has_non_ascii); + const bool success = DoSimpleHost( + &spec[host.begin], static_cast<size_t>(host.len), output, &has_non_ascii); DCHECK(!has_non_ascii); return success; } @@ -353,7 +360,7 @@ const Component& host, CanonOutput* output, CanonHostInfo* host_info) { - if (host.len <= 0) { + if (!host.is_nonempty()) { // Empty hosts don't need anything. host_info->family = CanonHostInfo::NEUTRAL; host_info->out_host = Component();
diff --git a/url/url_canon_internal.cc b/url/url_canon_internal.cc index 48a1e74b1..192feb9 100644 --- a/url/url_canon_internal.cc +++ b/url/url_canon_internal.cc
@@ -11,17 +11,19 @@ #include <cstdio> #include <string> +#include "base/numerics/safe_conversions.h" #include "base/strings/utf_string_conversion_utils.h" namespace url { namespace { -template<typename CHAR, typename UCHAR> -void DoAppendStringOfType(const CHAR* source, int length, +template <typename CHAR, typename UCHAR> +void DoAppendStringOfType(const CHAR* source, + size_t length, SharedCharTypes type, CanonOutput* output) { - for (int i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) { if (static_cast<UCHAR>(source[i]) >= 0x80) { // ReadChar will fill the code point with kUnicodeReplacementCharacter // when the input is invalid, which is what we want. @@ -41,10 +43,12 @@ // This function assumes the input values are all contained in 8-bit, // although it allows any type. Returns true if input is valid, false if not. -template<typename CHAR, typename UCHAR> -void DoAppendInvalidNarrowString(const CHAR* spec, int begin, int end, +template <typename CHAR, typename UCHAR> +void DoAppendInvalidNarrowString(const CHAR* spec, + size_t begin, + size_t end, CanonOutput* output) { - for (int i = begin; i < end; i++) { + for (size_t i = begin; i < end; i++) { UCHAR uch = static_cast<UCHAR>(spec[i]); if (uch >= 0x80) { // Handle UTF-8/16 encodings. This call will correctly handle the error @@ -98,7 +102,8 @@ // Convert to UTF-8. dest_component->begin = utf8_buffer->length(); success = ConvertUTF16ToUTF8(&override_source[override_component.begin], - override_component.len, utf8_buffer); + static_cast<size_t>(override_component.len), + utf8_buffer); dest_component->len = utf8_buffer->length() - dest_component->begin; } } @@ -235,26 +240,24 @@ const base_icu::UChar32 kUnicodeReplacementCharacter = 0xfffd; -void AppendStringOfType(const char* source, int length, +void AppendStringOfType(const char* source, + size_t length, SharedCharTypes type, CanonOutput* output) { DoAppendStringOfType<char, unsigned char>(source, length, type, output); } void AppendStringOfType(const char16_t* source, - int length, + size_t length, SharedCharTypes type, CanonOutput* output) { DoAppendStringOfType<char16_t, char16_t>(source, length, type, output); } bool ReadUTFChar(const char* str, - int* begin, - int length, + size_t* begin, + size_t length, base_icu::UChar32* code_point_out) { - // This depends on ints and int32s being the same thing. If they're not, it - // will fail to compile. - // TODO(mmenke): This should probably be fixed. if (!base::ReadUnicodeCharacter(str, length, begin, code_point_out) || !base::IsValidCharacter(*code_point_out)) { *code_point_out = kUnicodeReplacementCharacter; @@ -264,12 +267,9 @@ } bool ReadUTFChar(const char16_t* str, - int* begin, - int length, + size_t* begin, + size_t length, base_icu::UChar32* code_point_out) { - // This depends on ints and int32s being the same thing. If they're not, it - // will fail to compile. - // TODO(mmenke): This should probably be fixed. if (!base::ReadUnicodeCharacter(str, length, begin, code_point_out) || !base::IsValidCharacter(*code_point_out)) { *code_point_out = kUnicodeReplacementCharacter; @@ -278,23 +278,25 @@ return true; } -void AppendInvalidNarrowString(const char* spec, int begin, int end, +void AppendInvalidNarrowString(const char* spec, + size_t begin, + size_t end, CanonOutput* output) { DoAppendInvalidNarrowString<char, unsigned char>(spec, begin, end, output); } void AppendInvalidNarrowString(const char16_t* spec, - int begin, - int end, + size_t begin, + size_t end, CanonOutput* output) { DoAppendInvalidNarrowString<char16_t, char16_t>(spec, begin, end, output); } bool ConvertUTF16ToUTF8(const char16_t* input, - int input_len, + size_t input_len, CanonOutput* output) { bool success = true; - for (int i = 0; i < input_len; i++) { + for (size_t i = 0; i < input_len; i++) { base_icu::UChar32 code_point; success &= ReadUTFChar(input, &i, input_len, &code_point); AppendUTF8Value(code_point, output); @@ -303,10 +305,10 @@ } bool ConvertUTF8ToUTF16(const char* input, - int input_len, + size_t input_len, CanonOutputT<char16_t>* output) { bool success = true; - for (int i = 0; i < input_len; i++) { + for (size_t i = 0; i < input_len; i++) { base_icu::UChar32 code_point; success &= ReadUTFChar(input, &i, input_len, &code_point); AppendUTF16Value(code_point, output);
diff --git a/url/url_canon_internal.h b/url/url_canon_internal.h index def4636..ec5b61cb4 100644 --- a/url/url_canon_internal.h +++ b/url/url_canon_internal.h
@@ -77,11 +77,12 @@ // Appends the given string to the output, escaping characters that do not // match the given |type| in SharedCharTypes. -void AppendStringOfType(const char* source, int length, +void AppendStringOfType(const char* source, + size_t length, SharedCharTypes type, CanonOutput* output); void AppendStringOfType(const char16_t* source, - int length, + size_t length, SharedCharTypes type, CanonOutput* output); @@ -107,8 +108,8 @@ // Indicates if the given character is a dot or dot equivalent, returning the // number of characters taken by it. This will be one for a literal dot, 3 for // an escaped dot. If the character is not a dot, this will return 0. -template<typename CHAR> -inline int IsDot(const CHAR* spec, int offset, int end) { +template <typename CHAR> +inline size_t IsDot(const CHAR* spec, size_t offset, size_t end) { if (spec[offset] == '.') { return 1; } else if (spec[offset] == '%' && offset + 3 <= end && @@ -154,8 +155,8 @@ // (for a single-byte ASCII character, it will not be changed). COMPONENT_EXPORT(URL) bool ReadUTFChar(const char* str, - int* begin, - int length, + size_t* begin, + size_t length, base_icu::UChar32* code_point_out); // Generic To-UTF-8 converter. This will call the given append method for each @@ -231,8 +232,8 @@ // (for a single-16-bit-word character, it will not be changed). COMPONENT_EXPORT(URL) bool ReadUTFChar(const char16_t* str, - int* begin, - int length, + size_t* begin, + size_t length, base_icu::UChar32* code_point_out); // Equivalent to U16_APPEND_UNSAFE in ICU but uses our output method. @@ -268,8 +269,8 @@ // Assumes that ch[begin] is within range in the array, but does not assume // that any following characters are. inline bool AppendUTF8EscapedChar(const char16_t* str, - int* begin, - int length, + size_t* begin, + size_t length, CanonOutput* output) { // UTF-16 input. ReadUTFChar will handle invalid characters for us and give // us the kUnicodeReplacementCharacter, so we don't have to do special @@ -281,7 +282,9 @@ } // Handles UTF-8 input. See the wide version above for usage. -inline bool AppendUTF8EscapedChar(const char* str, int* begin, int length, +inline bool AppendUTF8EscapedChar(const char* str, + size_t* begin, + size_t length, CanonOutput* output) { // ReadUTF8Char will handle invalid characters for us and give us the // kUnicodeReplacementCharacter, so we don't have to do special checking @@ -308,8 +311,10 @@ return c <= 255; } -template<typename CHAR> -inline bool DecodeEscaped(const CHAR* spec, int* begin, int end, +template <typename CHAR> +inline bool DecodeEscaped(const CHAR* spec, + size_t* begin, + size_t end, unsigned char* unescaped_value) { if (*begin + 3 > end || !Is8BitChar(spec[*begin + 1]) || !Is8BitChar(spec[*begin + 2])) { @@ -338,11 +343,13 @@ // This is used in error cases to append invalid output so that it looks // approximately correct. Non-error cases should not call this function since // the escaping rules are not guaranteed! -void AppendInvalidNarrowString(const char* spec, int begin, int end, +void AppendInvalidNarrowString(const char* spec, + size_t begin, + size_t end, CanonOutput* output); void AppendInvalidNarrowString(const char16_t* spec, - int begin, - int end, + size_t begin, + size_t end, CanonOutput* output); // Misc canonicalization helpers ---------------------------------------------- @@ -357,11 +364,11 @@ // normal. COMPONENT_EXPORT(URL) bool ConvertUTF16ToUTF8(const char16_t* input, - int input_len, + size_t input_len, CanonOutput* output); COMPONENT_EXPORT(URL) bool ConvertUTF8ToUTF16(const char* input, - int input_len, + size_t input_len, CanonOutputT<char16_t>* output); // Converts from UTF-16 to 8-bit using the character set converter. If the
diff --git a/url/url_canon_mailtourl.cc b/url/url_canon_mailtourl.cc index f4fe2b4e..ff62bea5 100644 --- a/url/url_canon_mailtourl.cc +++ b/url/url_canon_mailtourl.cc
@@ -57,8 +57,8 @@ // Copy the path using path URL's more lax escaping rules. // We convert to UTF-8 and escape non-ASCII, but leave most // ASCII characters alone. - int end = parsed.path.end(); - for (int i = parsed.path.begin; i < end; ++i) { + size_t end = static_cast<size_t>(parsed.path.end()); + for (size_t i = static_cast<size_t>(parsed.path.begin); i < end; ++i) { UCHAR uch = static_cast<UCHAR>(source.path[i]); if (ShouldEncodeMailboxCharacter<UCHAR>(uch)) success &= AppendUTF8EscapedChar(source.path, &i, end, output);
diff --git a/url/url_canon_path.cc b/url/url_canon_path.cc index d6fb64b..f50e107 100644 --- a/url/url_canon_path.cc +++ b/url/url_canon_path.cc
@@ -101,9 +101,11 @@ // If the input is "../foo", |after_dot| = 1, |end| = 6, and // at the end, |*consumed_len| = 2 for the "./" this function consumed. The // original dot length should be handled by the caller. -template<typename CHAR> -DotDisposition ClassifyAfterDot(const CHAR* spec, int after_dot, - int end, int* consumed_len) { +template <typename CHAR> +DotDisposition ClassifyAfterDot(const CHAR* spec, + size_t after_dot, + size_t end, + size_t* consumed_len) { if (after_dot == end) { // Single dot at the end. *consumed_len = 0; @@ -115,9 +117,9 @@ return DIRECTORY_CUR; } - int second_dot_len = IsDot(spec, after_dot, end); + size_t second_dot_len = IsDot(spec, after_dot, end); if (second_dot_len) { - int after_second_dot = after_dot + second_dot_len; + size_t after_second_dot = after_dot + second_dot_len; if (after_second_dot == end) { // Double dot at the end. *consumed_len = second_dot_len; @@ -193,10 +195,10 @@ // ends with a '%' followed by one or two characters, and the '%' is the one // pointed to by |last_invalid_percent_index|. The last character in the string // was just unescaped. -template<typename CHAR> +template <typename CHAR> void CheckForNestedEscapes(const CHAR* spec, - int next_input_index, - int input_len, + size_t next_input_index, + size_t input_len, int last_invalid_percent_index, CanonOutput* output) { const int length = output->length(); @@ -218,9 +220,10 @@ } // Now output ends like "%cc". Try to unescape this. - int begin = last_invalid_percent_index; + size_t begin = static_cast<size_t>(last_invalid_percent_index); unsigned char temp; - if (DecodeEscaped(output->data(), &begin, output->length(), &temp)) { + if (DecodeEscaped(output->data(), &begin, + static_cast<size_t>(output->length()), &temp)) { // New escape sequence found. Overwrite the characters following the '%' // with "25", and push_back() the one or two characters that were following // the '%' when we were called. @@ -252,7 +255,10 @@ const Component& path, int path_begin_in_output, CanonOutput* output) { - int end = path.end(); + if (!path.is_nonempty()) + return true; + + size_t end = static_cast<size_t>(path.end()); // We use this variable to minimize the amount of work done when unescaping -- // we'll only call CheckForNestedEscapes() when this points at one of the last @@ -260,7 +266,7 @@ int last_invalid_percent_index = INT_MIN; bool success = true; - for (int i = path.begin; i < end; i++) { + for (size_t i = static_cast<size_t>(path.begin); i < end; i++) { DCHECK_LT(last_invalid_percent_index, output->length()); UCHAR uch = static_cast<UCHAR>(spec[i]); if (sizeof(CHAR) > 1 && uch >= 0x80) { @@ -276,7 +282,7 @@ unsigned char flags = kPathCharLookup[out_ch]; if (flags & SPECIAL) { // Needs special handling of some sort. - int dotlen; + size_t dotlen; if ((dotlen = IsDot(spec, i, end)) > 0) { // See if this dot was preceded by a slash in the output. // @@ -287,7 +293,7 @@ if (output->length() > path_begin_in_output && output->at(output->length() - 1) == '/') { // Slash followed by a dot, check to see if this is means relative - int consumed_len; + size_t consumed_len; switch (ClassifyAfterDot<CHAR>(spec, i + dotlen, end, &consumed_len)) { case NOT_A_DIRECTORY:
diff --git a/url/url_canon_pathurl.cc b/url/url_canon_pathurl.cc index e726cfb..d8d65f33 100644 --- a/url/url_canon_pathurl.cc +++ b/url/url_canon_pathurl.cc
@@ -32,8 +32,8 @@ // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state // https://url.spec.whatwg.org/#c0-control-percent-encode-set new_component->begin = output->length(); - int end = component.end(); - for (int i = component.begin; i < end; i++) { + size_t end = static_cast<size_t>(component.end()); + for (size_t i = static_cast<size_t>(component.begin); i < end; i++) { UCHAR uch = static_cast<UCHAR>(source[i]); if (uch < 0x20 || uch > 0x7E) AppendUTF8EscapedChar(source, &i, end, output);
diff --git a/url/url_canon_query.cc b/url/url_canon_query.cc index b3a1118..d23b45f 100644 --- a/url/url_canon_query.cc +++ b/url/url_canon_query.cc
@@ -72,10 +72,12 @@ const Component& query, CharsetConverter* converter, CanonOutput* output) { + DCHECK(query.is_valid()); // This function will replace any misencoded values with the invalid // character. This is what we want so we don't have to check for error. RawCanonOutputW<1024> utf16; - ConvertUTF8ToUTF16(&spec[query.begin], query.len, &utf16); + ConvertUTF8ToUTF16(&spec[query.begin], static_cast<size_t>(query.len), + &utf16); converter->ConvertFromUTF16(utf16.data(), utf16.length(), output); } @@ -86,7 +88,9 @@ const Component& query, CharsetConverter* converter, CanonOutput* output) { - converter->ConvertFromUTF16(&spec[query.begin], query.len, output); + DCHECK(query.is_valid()); + converter->ConvertFromUTF16(&spec[query.begin], + static_cast<size_t>(query.len), output); } template<typename CHAR, typename UCHAR> @@ -109,7 +113,8 @@ } else { // No converter, do our own UTF-8 conversion. - AppendStringOfType(&spec[query.begin], query.len, CHAR_QUERY, output); + AppendStringOfType(&spec[query.begin], static_cast<size_t>(query.len), + CHAR_QUERY, output); } } }
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc index f6ac9d4..96aa55a 100644 --- a/url/url_canon_unittest.cc +++ b/url/url_canon_unittest.cc
@@ -173,9 +173,9 @@ out_str.clear(); StdStringCanonOutput output(&out_str); - int input_len = static_cast<int>(strlen(utf_cases[i].input8)); + size_t input_len = strlen(utf_cases[i].input8); bool success = true; - for (int ch = 0; ch < input_len; ch++) { + for (size_t ch = 0; ch < input_len; ch++) { success &= AppendUTF8EscapedChar(utf_cases[i].input8, &ch, input_len, &output); } @@ -189,9 +189,9 @@ std::u16string input_str( test_utils::TruncateWStringToUTF16(utf_cases[i].input16)); - int input_len = static_cast<int>(input_str.length()); + size_t input_len = input_str.length(); bool success = true; - for (int ch = 0; ch < input_len; ch++) { + for (size_t ch = 0; ch < input_len; ch++) { success &= AppendUTF8EscapedChar(input_str.c_str(), &ch, input_len, &output); }
diff --git a/url/url_util.cc b/url/url_util.cc index 1f0de84..cd8e2e1 100644 --- a/url/url_util.cc +++ b/url/url_util.cc
@@ -811,11 +811,15 @@ int length, DecodeURLMode mode, CanonOutputW* output) { + if (length <= 0) + return; + STACK_UNINITIALIZED RawCanonOutputT<char> unescaped_chars; - for (int i = 0; i < length; i++) { + size_t length_size_t = static_cast<size_t>(length); + for (size_t i = 0; i < length_size_t; i++) { if (input[i] == '%') { unsigned char ch; - if (DecodeEscaped(input, &i, length, &ch)) { + if (DecodeEscaped(input, &i, length_size_t, &ch)) { unescaped_chars.push_back(ch); } else { // Invalid escape sequence, copy the percent literal. @@ -830,18 +834,20 @@ int output_initial_length = output->length(); // Convert that 8-bit to UTF-16. It's not clear IE does this at all to // JavaScript URLs, but Firefox and Safari do. - for (int i = 0; i < unescaped_chars.length(); i++) { - unsigned char uch = static_cast<unsigned char>(unescaped_chars.at(i)); + size_t unescaped_length = static_cast<size_t>(unescaped_chars.length()); + for (size_t i = 0; i < unescaped_length; i++) { + unsigned char uch = + static_cast<unsigned char>(unescaped_chars.at(static_cast<int>(i))); if (uch < 0x80) { // Non-UTF-8, just append directly output->push_back(uch); } else { // next_ch will point to the last character of the decoded // character. - int next_character = i; + size_t next_character = i; base_icu::UChar32 code_point; - if (ReadUTFChar(unescaped_chars.data(), &next_character, - unescaped_chars.length(), &code_point)) { + if (ReadUTFChar(unescaped_chars.data(), &next_character, unescaped_length, + &code_point)) { // Valid UTF-8 character, convert to UTF-16. AppendUTF16Value(code_point, output); i = next_character;