diff --git a/DEPS b/DEPS index 818351d..24c7aa6 100644 --- a/DEPS +++ b/DEPS
@@ -308,19 +308,19 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': '29258ca44e62a5796cd874022d3dc89c8e39b69c', + 'src_internal_revision': '2f414f9eacfd0f8796e5eb675076cc7fb49c6954', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '292f17ed8a19f7f18c386a691001148f503c9611', + 'skia_revision': 'a673ab63fccc0d194dcd3d0414aeaf2f53920a9e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'b53eb026438b102249f055de1af5d8aff5bb0779', + 'v8_revision': '45524bc2f627d7733ed31196b8c1eb7d7db391e7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '75c8ef1c6371b2922a6cab9687b9a53fe6674ffc', + 'angle_revision': 'd334a6f265750b754868d6c3ebeaa84a527a33b0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -383,11 +383,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'fa6a888a12fcdba798061eb6680cabc8e1573a42', + 'catapult_revision': '56ba67e870f9511d59155a9d8f40ff4afdea73d7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': 'd1a16c439233c3c7199fcc3f0507b1d012611ab9', + 'chromium_variations_revision': 'bc7922fea2a34cdd9f5b704b95cae57b3779fcbd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -427,7 +427,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'f5abb823f98d0ab55b31b63453d46188b7f9e5a3', + 'dawn_revision': '2ed7112412452a0104c1a7dc68748549d385392b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -471,7 +471,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'cros_components_revision': 'caaac730221dc9e0a461e7eedcae4a35a46696bd', + 'cros_components_revision': '62c84c45907dd68c94ad119532653edffed86e5c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -827,12 +827,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '8933ab5bda635e80ec163376cf2410af186083a0', + '2932c1090e4c5fa9b48dd9ba530f6c353ef6d99e', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '05de69cbec5c294245bfb96d9be826065c05e6eb', + 'url': Var('chromium_git') + '/website.git' + '@' + '986765e7d5353a13f3927a616ac4b19ed46753c8', }, 'src/ios/third_party/earl_grey2/src': { @@ -989,7 +989,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'FWqUT5IoVM8psEVxMdqcw7C2u3EfgoZddhNc6JEJQdkC', + 'version': 'IER7pfMyPXflJkWOifaNaUEXSj2gI2JkwPEsjw3QrjwC', }, ], 'condition': 'checkout_android', @@ -1199,7 +1199,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'af26c1dfaae2f3c632d88bf9bd78526866afe180', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '00915b68748cc78969f6269b78ddaae0a120e993', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1850,7 +1850,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '98673cc24786be6c10dd8908e0b0b4ed27625c6a', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'a8c47276cb6d3188db8b5a4ba77abd07797c0071', + Var('webrtc_git') + '/src.git' + '@' + '2825f0a7bbd08f8ee466291d7ee7a77fa7838e03', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -4096,7 +4096,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '68317323902aff53eb3ea1e381f48e9249f0f516', + '688972f572b29fa2d33f7cd37601e05e50d8fea8', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java b/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java index 52305dc..147b204 100644 --- a/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java +++ b/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java
@@ -14,6 +14,7 @@ import android.os.RemoteException; import android.os.SystemClock; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import org.jni_zero.CalledByNative; @@ -31,6 +32,8 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.task.PostTask; +import org.chromium.base.task.TaskTraits; import org.chromium.components.variations.LoadSeedResult; import java.io.File; @@ -110,7 +113,7 @@ private static long sCachedSeedFreshness; private static long sCachedAppSeedFreshness; - private SeedLoadAndUpdateRunnable mRunnable; + private FutureTask<SeedLoadResult> mLoadTask; private SeedServerCallback mSeedServerCallback = new SeedServerCallback(); private static void recordLoadSeedResult(@LoadSeedResult int result) { @@ -225,95 +228,110 @@ } } - // Loads our local copy of the seed, if any, and then renames our local copy and/or requests a - // new seed, if necessary. - private class SeedLoadAndUpdateRunnable implements Runnable { - // mLoadTask will set these to indicate what additional work to do after mLoadTask finishes: - // - mFoundNewSeed: Is a "new" seed file present? (If so, it should be renamed to an "old" - // seed, replacing any existing "old" seed.) - // - mNeedNewSeed: Should we request a new seed from the service? - // - mCurrentSeedDate: The "date" field of our local seed, converted to milliseconds since - // epoch, or Long.MIN_VALUE if we have no seed. This value originates from the server. - // - mSeedFileTime: The time, in milliseconds since the UNIX epoch, our local copy of the - // seed was last written to disk as measured by the device's clock. - private boolean mFoundNewSeed; - private boolean mNeedNewSeed; - private long mCurrentSeedDate = Long.MIN_VALUE; - private long mSeedFileTime; + /** Result of loading the local copy of the seed. */ + private static class SeedLoadResult { + /** Whether the seed was loaded successfully. */ + final boolean mLoadedSeed; - private FutureTask<Boolean> mLoadTask = - new FutureTask<>( - () -> { - File newSeedFile = VariationsUtils.getNewSeedFile(); - File oldSeedFile = VariationsUtils.getSeedFile(); + /** + * The "date" field of our local seed, converted to milliseconds since epoch, or + * Long.MIN_VALUE if we have no seed. This value originates from the server. + */ + final long mCurrentSeedDate; - // First check for a new seed. - boolean loadedSeed = false; - if (parseAndSaveSeedFile(newSeedFile)) { - loadedSeed = true; - mSeedFileTime = newSeedFile.lastModified(); + /** + * The time, in milliseconds since the UNIX epoch, our local copy of the seed was last + * written to disk as measured by the device's clock. + */ + final long mSeedFileTime; - // If a valid new seed was found, make a note to replace the old - // seed with the new seed. (Don't do it now, to avoid delaying - // FutureTask.get().) - mFoundNewSeed = true; - } else if (parseAndSaveSeedFile( - oldSeedFile)) { // If no new seed, check for an old one. - loadedSeed = true; - mSeedFileTime = oldSeedFile.lastModified(); - } + private SeedLoadResult(boolean loadedSeed, long mCurrentSeedDate, long seedFileTime) { + this.mLoadedSeed = loadedSeed; + this.mCurrentSeedDate = mCurrentSeedDate; + this.mSeedFileTime = seedFileTime; + } + } - // Make a note to request a new seed if necessary. (Don't request it - // now, to avoid delaying FutureTask.get().) - if (!loadedSeed || isSeedExpired(mSeedFileTime)) { - mNeedNewSeed = true; + /** + * Load the current variations seed file. + * + * <p>This method should be posted to a background thread to ensure that other initialization + * work can happen concurrently. + */ + @NonNull + private SeedLoadResult loadSeedFile() { + File newSeedFile = VariationsUtils.getNewSeedFile(); + File oldSeedFile = VariationsUtils.getSeedFile(); + long currentSeedDate = Long.MIN_VALUE; + long seedFileTime = 0; + boolean loadedSeed = false; + boolean foundNewSeed = false; + // First check for a new seed. + if (parseAndSaveSeedFile(newSeedFile)) { + loadedSeed = true; + seedFileTime = newSeedFile.lastModified(); - // Rate-limit the requests. - if (shouldThrottleRequests(getCurrentTimeMillis())) { - mNeedNewSeed = false; - } - } - - // Save the date field of whatever seed was loaded, if any. - if (loadedSeed) { - mCurrentSeedDate = VariationsSeedLoaderJni.get().getSavedSeedDate(); - } - return loadedSeed; - }); - - @Override - public void run() { - mLoadTask.run(); - // The loaded seed is now available via get(). The following steps won't block startup. - - if (mFoundNewSeed) { - // The move happens synchronously. It's not possible for the service to still be - // writing to this file when we move it, because mFoundNewSeed means we already read - // the seed and found it to be complete. Therefore the service must have already - // finished writing. - VariationsUtils.replaceOldWithNewSeed(); - } - - if (mNeedNewSeed) { - // The new seed will arrive asynchronously; the new seed file is written by the - // service, and may complete after this app process has died. - requestSeedFromService(mCurrentSeedDate); - VariationsUtils.updateStampTime(); - } - - onBackgroundWorkFinished(); + // If a valid new seed was found, make a note to replace the old + // seed with the new seed. (Don't do it now, to avoid delaying + // FutureTask.get().) + foundNewSeed = true; + } else if (parseAndSaveSeedFile(oldSeedFile)) { + // If no new seed, check for an old one. + loadedSeed = true; + seedFileTime = oldSeedFile.lastModified(); } - public boolean get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - boolean success = mLoadTask.get(timeout, unit); - maybeRecordSeedFileTime(mSeedFileTime); - return success; + // Make a note to request a new seed if necessary. (Don't request it + // now, to avoid delaying FutureTask.get().) + boolean needNewSeed = false; + if (!loadedSeed || isSeedExpired(seedFileTime)) { + // Rate-limit the requests. + needNewSeed = !shouldThrottleRequests(getCurrentTimeMillis()); } - public long getLoadedSeedDate() { - return mCurrentSeedDate; + // Save the date field of whatever seed was loaded, if any. + if (loadedSeed) { + currentSeedDate = VariationsSeedLoaderJni.get().getSavedSeedDate(); } + + // Schedule a task to update the seed files from the service. + updateSeedFileAndRequestNewFromServiceOnBackgroundThread( + foundNewSeed, needNewSeed, currentSeedDate); + + return new SeedLoadResult(loadedSeed, currentSeedDate, seedFileTime); + } + + /** + * Post a task to replace the old seed with a new one and request an update. + * + * @param foundNewSeed Is a "new" seed file present? (If so, it should be renamed to an "old" + * seed, replacing any existing "old" seed.) + * @param needNewSeed Should we request a new seed from the service? + * @param seedFileTime timestamp of the current seed file. + */ + private void updateSeedFileAndRequestNewFromServiceOnBackgroundThread( + boolean foundNewSeed, boolean needNewSeed, long seedFileTime) { + // This work is not time critical. + PostTask.postTask( + TaskTraits.BEST_EFFORT_MAY_BLOCK, + () -> { + if (foundNewSeed) { + // The move happens synchronously. It's not possible for the service to + // still be writing to this file when we move it, because foundNewSeed means + // we already read the seed and found it to be complete. Therefore the + // service must have already finished writing. + VariationsUtils.replaceOldWithNewSeed(); + } + + if (needNewSeed) { + // The new seed will arrive asynchronously; the new seed file is written by + // the service, and may complete after this app process has died. + requestSeedFromService(seedFileTime); + VariationsUtils.updateStampTime(); + } + + onBackgroundWorkFinished(); + }); } // Connects to VariationsSeedServer service. Sends a file descriptor for our local copy of the @@ -440,8 +458,10 @@ // Begin asynchronously loading the variations seed. ContextUtils.getApplicationContext() and // AwBrowserProcess.getWebViewPackageName() must be ready to use before calling this. public void startVariationsInit() { - mRunnable = new SeedLoadAndUpdateRunnable(); - (new Thread(mRunnable)).start(); + mLoadTask = new FutureTask<>(this::loadSeedFile); + // The Runnable task must be scheduled with high priority to start the FutureTask as soon as + // possible since that task is blocking WebView startup. + PostTask.postTask(TaskTraits.USER_BLOCKING_MAY_BLOCK, mLoadTask); } // Block on loading the seed with a timeout. Then if a seed was successfully loaded, initialize @@ -450,9 +470,12 @@ long start = SystemClock.elapsedRealtime(); try { try { - boolean gotSeed = mRunnable.get(getSeedLoadTimeoutMillis(), TimeUnit.MILLISECONDS); + SeedLoadResult loadResult = + mLoadTask.get(getSeedLoadTimeoutMillis(), TimeUnit.MILLISECONDS); + maybeRecordSeedFileTime(loadResult.mSeedFileTime); + boolean gotSeed = loadResult.mLoadedSeed; // Log the seed age to help with debugging. - long seedDate = mRunnable.getLoadedSeedDate(); + long seedDate = loadResult.mCurrentSeedDate; if (gotSeed && seedDate > 0) { long seedAge = TimeUnit.MILLISECONDS.toSeconds(new Date().getTime() - seedDate); // Changes to the log message below must be accompanied with changes to WebView
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java index ba653dd..e698b76 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -727,14 +727,15 @@ } /** - * This test is verifying that a user interacting with a form after reloading a webpage - * triggers a new autofill session rather than continuing a session that was started before the - * reload. This is necessary to ensure that autofill is properly triggered in this case (see + * This test is verifying that a user interacting with a form after reloading a webpage triggers + * a new autofill session rather than continuing a session that was started before the reload. + * This is necessary to ensure that autofill is properly triggered in this case (see * crbug.com/1117563 for details). */ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testAutofillTriggersAfterReload() throws Throwable { int cnt = 0; @@ -848,6 +849,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testCommit() throws Throwable { loadHTML( """ @@ -886,7 +888,9 @@ executeJavaScriptAndWaitForResult("document.getElementById('formid').submit();"); waitForCallbackAndVerifyTypes( cnt, - new Integer[] {AUTOFILL_VALUE_CHANGED, AUTOFILL_VALUE_CHANGED, AUTOFILL_COMMIT}); + new Integer[] { + AUTOFILL_VALUE_CHANGED, AUTOFILL_VALUE_CHANGED, AUTOFILL_COMMIT, AUTOFILL_CANCEL + }); ArrayList<Pair<Integer, AutofillValue>> values = getChangedValues(); assertEquals(2, values.size()); assertEquals("a", values.get(0).second.getTextValue()); @@ -957,7 +961,9 @@ @Test @SmallTest @Feature({"AndroidWebView"}) - @CommandLineFlags.Add({"enable-features=AutofillAcrossIframes"}) + @CommandLineFlags.Add({ + "enable-features=AutofillAcrossIframes, AndroidAutofillCancelSessionOnNavigation" + }) public void testCrossFrameCommit() throws Throwable { // The only reason we use a <form> inside the iframe is that this makes it easiest to // trigger a form submission in that frame. @@ -1276,12 +1282,13 @@ } /** - * This test is verifying that a navigation occurring while there is a probably-submitted - * form will trigger commit of the current autofill session. + * This test is verifying that a navigation occurring while there is a probably-submitted form + * will trigger commit of the current autofill session. */ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testNavigationAfterProbableSubmitResultsInSessionCommit() throws Throwable { int cnt = 0; loadHTML( @@ -1583,6 +1590,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserSelectSuggestionUserChangeFormFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1616,6 +1624,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserSelectSuggestionUserChangeFormNoFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1648,6 +1657,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMASessionMetricsRecordedOnAwContentsDestruction() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1682,6 +1692,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserSelectNotSuggestionUserChangeFormNoFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1714,6 +1725,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserNotSelectSuggestionUserChangeFormFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1746,6 +1758,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMANoSuggestionUserChangeFormNoFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1775,6 +1788,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMANoSuggestionUserChangeFormFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1806,6 +1820,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserSelectSuggestionUserNotChangeFormFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1838,6 +1853,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserSelectSuggestionUserNotChangeFormNoFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1868,6 +1884,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserNotSelectSuggestionUserNotChangeFormNoFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1897,6 +1914,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAUserNotSelectSuggestionUserNotChangeFormFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1928,6 +1946,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMANoSuggestionUserNotChangeFormNoFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -1956,6 +1975,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMANoSuggestionUserNotChangeFormFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -2133,6 +2153,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAFormSubmissionProbablyFormSubmitted() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -2159,6 +2180,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAFormSubmissionFrameDetached() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -2218,6 +2240,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAFormSubmissionSameDocumentNavigation() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -2276,6 +2299,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testUMAFormSubmissionXHRSucceeded() throws Throwable { var histograms = TestThreadUtils.runOnUiThreadBlocking( @@ -3243,6 +3267,7 @@ @Test @SmallTest @Feature({"AndroidWebView"}) + @CommandLineFlags.Add({"enable-features=AndroidAutofillCancelSessionOnNavigation"}) public void testFrameDetachedOnFormSubmission() throws Throwable { final String subFrame = """
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 6d42ec3..063ee9d3 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2996,6 +2996,7 @@ "//ash/keyboard/ui", "//ash/login/resources:resources_grit", "//ash/public/cpp/ambient/proto", + "//ash/public/mojom:hid_preserving_bluetooth_state_controller", "//ash/quick_pair", "//ash/quick_pair/companion_app", "//ash/quick_pair/feature_status_tracker", @@ -4111,6 +4112,7 @@ "//ash/public/cpp/external_arc:unit_tests", "//ash/public/cpp/holding_space:test_support", "//ash/public/mojom", + "//ash/public/mojom:hid_preserving_bluetooth_state_controller", "//ash/quick_pair:unit_tests", "//ash/resources/vector_icons", "//ash/shortcut_viewer:unit_tests",
diff --git a/ash/public/mojom/BUILD.gn b/ash/public/mojom/BUILD.gn index 03b0dd4..715d4db 100644 --- a/ash/public/mojom/BUILD.gn +++ b/ash/public/mojom/BUILD.gn
@@ -12,7 +12,6 @@ sources = [ "assistant_volume_control.mojom", - "hid_preserving_bluetooth_state_controller.mojom", "tray_action.mojom", ] @@ -40,6 +39,12 @@ export_header = "ash/public/cpp/ash_public_export.h" } +mojom("hid_preserving_bluetooth_state_controller") { + sources = [ "hid_preserving_bluetooth_state_controller.mojom" ] + public_deps = [ "//mojo/public/mojom/base" ] + webui_module_path = "chrome://resources/ash/common/" +} + # This is a separate target so that downstream WebUI targets can take # advantage of JS module Mojom files, without having to generate WebUI Mojom # files for all dependencies (and their dependencies) in //ash/public/mojom.
diff --git a/ash/webui/common/resources/BUILD.gn b/ash/webui/common/resources/BUILD.gn index 74eb0d53..8ecc446 100644 --- a/ash/webui/common/resources/BUILD.gn +++ b/ash/webui/common/resources/BUILD.gn
@@ -133,6 +133,7 @@ "bluetooth/bluetooth_types.ts", "bluetooth/bluetooth_utils.ts", "bluetooth/cros_bluetooth_config.ts", + "bluetooth/hid_preserving_bluetooth_state_controller.ts", "connectivity/mojo_connectivity_provider.ts", "hotspot/cros_hotspot_config.ts", "hotspot/fake_hotspot_config.ts", @@ -145,6 +146,7 @@ ] mojo_files_ts = [ + "bluetooth/hid_preserving_bluetooth_state_controller.mojom-webui.ts", "connectivity/passpoint.mojom-webui.ts", "hotspot/cros_hotspot_config.mojom-webui.ts", "shortcut_input_ui/accelerator_actions.mojom-webui.ts", @@ -251,6 +253,7 @@ ":generate_definitions", ":preprocess", ":preprocess_ts", + "bluetooth:copy_mojo_files", "connectivity:copy_mojo_files", "hotspot:copy_mojo_files", "shortcut_input_ui:copy_mojo_files",
diff --git a/ash/webui/common/resources/bluetooth/BUILD.gn b/ash/webui/common/resources/bluetooth/BUILD.gn new file mode 100644 index 0000000..3fa7576 --- /dev/null +++ b/ash/webui/common/resources/bluetooth/BUILD.gn
@@ -0,0 +1,13 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chromeos/ui_mode.gni") + +assert(is_chromeos_ash, "This module is Chrome OS only.") + +copy("copy_mojo_files") { + deps = [ "//ash/public/mojom:hid_preserving_bluetooth_state_controller_ts__generator" ] + sources = [ "$root_gen_dir/ash/public/mojom/hid_preserving_bluetooth_state_controller.mojom-webui.ts" ] + outputs = [ "$root_gen_dir/ash/webui/common/resources/preprocessed/bluetooth/{{source_file_part}}" ] +}
diff --git a/ash/webui/common/resources/bluetooth/hid_preserving_bluetooth_state_controller.ts b/ash/webui/common/resources/bluetooth/hid_preserving_bluetooth_state_controller.ts new file mode 100644 index 0000000..b527662b --- /dev/null +++ b/ash/webui/common/resources/bluetooth/hid_preserving_bluetooth_state_controller.ts
@@ -0,0 +1,31 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {HidPreservingBluetoothStateController, HidPreservingBluetoothStateControllerInterface} from './hid_preserving_bluetooth_state_controller.mojom-webui.js'; + +/** + * @fileoverview + * Wrapper for HidPreservingBluetoothStateController that provides the ability + * to inject a fake HidPreservingBluetoothStateController implementation for + * tests. + */ + +let hidPreservingController: HidPreservingBluetoothStateControllerInterface| + undefined; + +export function setHidPreservingControllerForTesting( + testHidPreservingController?: + HidPreservingBluetoothStateControllerInterface): void { + hidPreservingController = testHidPreservingController; +} + +export function getHidPreservingController(): + HidPreservingBluetoothStateControllerInterface { + if (hidPreservingController) { + return hidPreservingController; + } + + hidPreservingController = HidPreservingBluetoothStateController.getRemote(); + return hidPreservingController; +}
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc b/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc index 0e85768..47036a30 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc +++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc
@@ -55,11 +55,11 @@ bool may_dangle, uintptr_t address) { PA_CHECK(owner_id); - const std::pair<uintptr_t, size_t> slot_and_size = + const auto slot_and_size = partition_alloc::PartitionAllocGetSlotStartAndSizeInBRPPool(address); const uintptr_t slot_count = reinterpret_cast<uintptr_t>( partition_alloc::PartitionRoot::RefCountPointerFromSlotStartAndSize( - slot_and_size.first, slot_and_size.second)); + slot_and_size.slot_start, slot_and_size.size)); const std::lock_guard guard(GetStorageMutex()); GetStorage().insert({owner_id, Info(slot_count, may_dangle)}); @@ -85,12 +85,12 @@ std::vector<std::array<const void*, 32>> InstanceTracer::GetStackTracesForAddressForTest(const void* address) { - const std::pair<uintptr_t, size_t> slot_and_size = + const auto slot_and_size = partition_alloc::PartitionAllocGetSlotStartAndSizeInBRPPool( reinterpret_cast<uintptr_t>(address)); const uintptr_t slot_count = reinterpret_cast<uintptr_t>( partition_alloc::PartitionRoot::RefCountPointerFromSlotStartAndSize( - slot_and_size.first, slot_and_size.second)); + slot_and_size.slot_start, slot_and_size.size)); return GetStackTracesForDanglingRefs(slot_count); }
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h b/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h index ffcce586..73e7164 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h +++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h
@@ -86,7 +86,7 @@ return ++counter_; } - static std::atomic<uint64_t> counter_; + PA_COMPONENT_EXPORT(RAW_PTR) static std::atomic<uint64_t> counter_; // 0 is treated as 'ownerless'. It is used as a sentinel for constexpr // raw_ptrs or other places where owner tracking doesn't make sense.
diff --git a/build/config/siso/PRESUBMIT.py b/build/config/siso/PRESUBMIT.py index 4099f0b..9a0f786 100644 --- a/build/config/siso/PRESUBMIT.py +++ b/build/config/siso/PRESUBMIT.py
@@ -16,9 +16,6 @@ "Missing 'Cq-Include-Trybots:' field required for Siso config changes" "\nPlease add the following fields to run Siso tryjobs.\n\n" "Cq-Include-Trybots: luci.chromium.try:fuchsia-binary-size-siso\n" - "Cq-Include-Trybots: luci.chromium.try:ios-simulator-siso\n" "Cq-Include-Trybots: luci.chromium.try:linux_chromium_asan_siso_rel_ng\n" - "Cq-Include-Trybots: luci.chromium.try:linux_chromium_compile_siso_dbg_ng\n" - "Cq-Include-Trybots: luci.chromium.try:mac-siso-rel\n" ) return [output_api.PresubmitPromptWarning(message)]
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc index f23983a..31d92ea 100644 --- a/cc/raster/one_copy_raster_buffer_provider.cc +++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -446,6 +446,10 @@ ri->BeginQueryEXT(query_target, staging_buffer->query_id); } + uint32_t texture_target = + shared_image->GetTextureTarget(gfx::BufferUsage::SCANOUT); + CHECK_EQ(texture_target, mailbox_texture_target); + // Clear to ensure the resource is fully initialized and BeginAccess succeeds. if (needs_clear) { int clear_bytes_per_row = viz::ResourceSizes::UncheckedWidthInBytes<int>( @@ -457,9 +461,9 @@ // SkBitmap.cpp doesn't yet have an interface for SkColor4fs // https://bugs.chromium.org/p/skia/issues/detail?id=13329 bitmap.eraseColor(raster_source->background_color().toSkColor()); - ri->WritePixels( - shared_image->mailbox(), /*dst_x_offset=*/0, /*dst_y_offset=*/0, - /*dst_plane_index=*/0, mailbox_texture_target, bitmap.pixmap()); + ri->WritePixels(shared_image->mailbox(), /*dst_x_offset=*/0, + /*dst_y_offset=*/0, + /*dst_plane_index=*/0, texture_target, bitmap.pixmap()); } } @@ -478,7 +482,7 @@ ri->CopySharedImage( staging_buffer->client_shared_image->mailbox(), shared_image->mailbox(), - mailbox_texture_target, 0, y, 0, y, rect_to_copy.width(), rows_to_copy, + texture_target, 0, y, 0, y, rect_to_copy.width(), rows_to_copy, false /* unpack_flip_y */, false /* unpack_premultiply_alpha */); y += rows_to_copy;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditor.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditor.java index ac0187c..36b7fbf 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditor.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditor.java
@@ -6,7 +6,14 @@ import android.content.Context; +import org.chromium.base.ValueChangedCallback; +import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabModelFilter; +import org.chromium.chrome.browser.tabmodel.TabModelObserver; +import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; +import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilterObserver; import org.chromium.chrome.tab_ui.R; import org.chromium.ui.modelutil.PropertyModel; @@ -17,9 +24,72 @@ */ public abstract class TabGroupTitleEditor { private final Context mContext; + private final ObservableSupplier<TabModelFilter> mCurrentTabModelFilterSupplier; + private final TabModelObserver mTabModelObserver; + private final TabGroupModelFilterObserver mFilterObserver; + private final ValueChangedCallback<TabModelFilter> mCurrentTabModelFilterObserver = + new ValueChangedCallback<>(this::onTabModelFilterChanged); - public TabGroupTitleEditor(Context context) { + public TabGroupTitleEditor( + Context context, ObservableSupplier<TabModelFilter> tabModelFilterSupplier) { mContext = context; + mCurrentTabModelFilterSupplier = tabModelFilterSupplier; + + mTabModelObserver = + new TabModelObserver() { + @Override + public void tabClosureCommitted(Tab tab) { + var filter = (TabGroupModelFilter) mCurrentTabModelFilterSupplier.get(); + int rootId = tab.getRootId(); + Tab groupTab = filter.getGroupLastShownTab(rootId); + if (groupTab == null || !filter.isTabInTabGroup(groupTab)) { + deleteTabGroupTitle(rootId); + } + } + }; + + mFilterObserver = + new TabGroupModelFilterObserver() { + @Override + public void willMergeTabToGroup(Tab movedTab, int newRootId) { + String sourceGroupTitle = getTabGroupTitle(movedTab.getRootId()); + String targetGroupTitle = getTabGroupTitle(newRootId); + if (sourceGroupTitle == null) return; + // If the target group has no title but the source group has a title, + // handover the stored title to the group after merge. + if (targetGroupTitle == null) { + storeTabGroupTitle(newRootId, sourceGroupTitle); + } + } + + @Override + public void willMoveTabOutOfGroup(Tab movedTab, int newRootId) { + int rootId = movedTab.getRootId(); + String title = getTabGroupTitle(rootId); + if (title == null) return; + // If the group size is 2, i.e. the group becomes a single tab after + // ungroup, delete the stored title. When tab groups of size 1 are supported + // this behavior is no longer valid. + var filter = (TabGroupModelFilter) mCurrentTabModelFilterSupplier.get(); + int sizeThreshold = + ChromeFeatureList.sAndroidTabGroupStableIds.isEnabled() ? 1 : 2; + boolean shouldDeleteTitle = + filter.getRelatedTabCountForRootId(rootId) <= sizeThreshold; + if (shouldDeleteTitle) { + deleteTabGroupTitle(rootId); + return; + } + // If the root tab in group is moved out, re-assign the title to the new + // root tab in group. + if (rootId != newRootId) { + deleteTabGroupTitle(rootId); + storeTabGroupTitle(newRootId, title); + } + } + }; + + mCurrentTabModelFilterObserver.onResult( + mCurrentTabModelFilterSupplier.addObserver(mCurrentTabModelFilterObserver)); } /** @@ -76,4 +146,28 @@ * @return The stored title of the related group. */ protected abstract String getTabGroupTitle(int tabRootId); + + /** Destroy any members that needs clean up. */ + public void destroy() { + removeTabModelFilterObservers(mCurrentTabModelFilterSupplier.get()); + mCurrentTabModelFilterSupplier.removeObserver(mCurrentTabModelFilterObserver); + } + + private void onTabModelFilterChanged(TabModelFilter newFilter, TabModelFilter oldFilter) { + removeTabModelFilterObservers(oldFilter); + + if (newFilter != null) { + TabGroupModelFilter newGroupFilter = (TabGroupModelFilter) newFilter; + newGroupFilter.addObserver(mTabModelObserver); + newGroupFilter.addTabGroupObserver(mFilterObserver); + } + } + + private void removeTabModelFilterObservers(TabModelFilter filter) { + if (filter != null) { + TabGroupModelFilter groupFilter = (TabGroupModelFilter) filter; + groupFilter.removeObserver(mTabModelObserver); + groupFilter.removeTabGroupObserver(mFilterObserver); + } + } }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManager.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManager.java deleted file mode 100644 index 731fd25..0000000 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManager.java +++ /dev/null
@@ -1,165 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.tasks.tab_management; - -import androidx.annotation.NonNull; - -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider; -import org.chromium.chrome.browser.tabmodel.TabModelObserver; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupColorUtils; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilterObserver; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupTitleUtils; -import org.chromium.components.tab_groups.TabGroupColorId; - -/** - * Manages observers that monitor for updates to tab group visual aspects such as colors and titles. - */ -public class TabGroupVisualDataManager { - private static final int INVALID_COLOR_ID = -1; - - private final TabModelSelector mTabModelSelector; - private TabModelObserver mTabModelObserver; - private TabGroupModelFilterObserver mFilterObserver; - - public TabGroupVisualDataManager(@NonNull TabModelSelector tabModelSelector) { - assert tabModelSelector.isTabStateInitialized(); - mTabModelSelector = tabModelSelector; - - TabModelFilterProvider tabModelFilterProvider = - mTabModelSelector.getTabModelFilterProvider(); - - mTabModelObserver = - new TabModelObserver() { - @Override - public void tabClosureCommitted(Tab tab) { - TabGroupModelFilter filter = - (TabGroupModelFilter) - tabModelFilterProvider.getTabModelFilter(tab.isIncognito()); - int rootId = tab.getRootId(); - Tab groupTab = filter.getGroupLastShownTab(rootId); - if (groupTab == null || !filter.isTabInTabGroup(groupTab)) { - TabGroupTitleUtils.deleteTabGroupTitle(rootId); - - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - TabGroupColorUtils.deleteTabGroupColor(rootId); - } - } - } - }; - - mFilterObserver = - new TabGroupModelFilterObserver() { - @Override - public void didCreateNewGroup(int newRootId, TabGroupModelFilter filter) { - // TODO(b/41490324): Store a default color as none will exist, but this - // should be enforced later on with the intro of TabGroupCreationDialog. - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - final @TabGroupColorId int colorId = - TabGroupColorUtils.getNextSuggestedColorId(filter); - TabGroupColorUtils.storeTabGroupColor(newRootId, colorId); - } - } - - @Override - public void willMergeTabToGroup(Tab movedTab, int newRootId) { - String sourceGroupTitle = - TabGroupTitleUtils.getTabGroupTitle(movedTab.getRootId()); - String targetGroupTitle = TabGroupTitleUtils.getTabGroupTitle(newRootId); - // If the target group has no title but the source group has a title, - // handover the stored title to the group after merge. - if (sourceGroupTitle != null && targetGroupTitle == null) { - TabGroupTitleUtils.storeTabGroupTitle(newRootId, sourceGroupTitle); - } - - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - int sourceGroupColor = - TabGroupColorUtils.getTabGroupColor(movedTab.getRootId()); - int targetGroupColor = TabGroupColorUtils.getTabGroupColor(newRootId); - // If the target group has no color but the source group has a color, - // handover the stored color to the group after merge. - if (sourceGroupColor != INVALID_COLOR_ID - && targetGroupColor == INVALID_COLOR_ID) { - TabGroupColorUtils.storeTabGroupColor(newRootId, sourceGroupColor); - } - } - } - - @Override - public void willMoveTabOutOfGroup(Tab movedTab, int newRootId) { - int rootId = movedTab.getRootId(); - String title = TabGroupTitleUtils.getTabGroupTitle(rootId); - - // If the group size is 2, i.e. the group becomes a single tab after - // ungroup, delete the stored visual data. When tab groups of size 1 are - // supported this behavior is no longer valid. - TabGroupModelFilter filter = - (TabGroupModelFilter) - tabModelFilterProvider.getTabModelFilter( - movedTab.isIncognito()); - int sizeThreshold = - ChromeFeatureList.sAndroidTabGroupStableIds.isEnabled() ? 1 : 2; - boolean shouldDeleteVisualData = - filter.getRelatedTabCountForRootId(rootId) <= sizeThreshold; - if (shouldDeleteVisualData) { - if (title != null) { - TabGroupTitleUtils.deleteTabGroupTitle(rootId); - } - - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - TabGroupColorUtils.deleteTabGroupColor(rootId); - } - - return; - } - // If the root tab in group is moved out, re-assign the visual data to the - // new root tab in group. - if (rootId != newRootId) { - if (title != null) { - TabGroupTitleUtils.deleteTabGroupTitle(rootId); - TabGroupTitleUtils.storeTabGroupTitle(newRootId, title); - } - - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - int colorId = TabGroupColorUtils.getTabGroupColor(rootId); - assert colorId != INVALID_COLOR_ID; - - TabGroupColorUtils.deleteTabGroupColor(rootId); - TabGroupColorUtils.storeTabGroupColor(newRootId, colorId); - } - } - } - }; - - tabModelFilterProvider.addTabModelFilterObserver(mTabModelObserver); - - ((TabGroupModelFilter) tabModelFilterProvider.getTabModelFilter(false)) - .addTabGroupObserver(mFilterObserver); - ((TabGroupModelFilter) tabModelFilterProvider.getTabModelFilter(true)) - .addTabGroupObserver(mFilterObserver); - } - - /** Destroy any members that need clean up. */ - public void destroy() { - TabModelFilterProvider tabModelFilterProvider = - mTabModelSelector.getTabModelFilterProvider(); - - if (mTabModelObserver != null) { - tabModelFilterProvider.removeTabModelFilterObserver(mTabModelObserver); - mTabModelObserver = null; - } - - if (mFilterObserver != null) { - ((TabGroupModelFilter) tabModelFilterProvider.getTabModelFilter(false)) - .removeTabGroupObserver(mFilterObserver); - ((TabGroupModelFilter) tabModelFilterProvider.getTabModelFilter(true)) - .removeTabGroupObserver(mFilterObserver); - mFilterObserver = null; - } - } -}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index a7ad1a3..b925b2e0 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -1137,7 +1137,7 @@ mCurrentTabModelFilterSupplier.addObserver(mOnTabModelFilterChanged)); mTabGroupTitleEditor = - new TabGroupTitleEditor(mContext) { + new TabGroupTitleEditor(mContext, mCurrentTabModelFilterSupplier) { @Override protected void updateTabGroupTitle(Tab tab, String title) { // Only update title in PropertyModel for tab switcher. @@ -1689,6 +1689,9 @@ if (mComponentCallbacks != null) { mContext.unregisterComponentCallbacks(mComponentCallbacks); } + if (mTabGroupTitleEditor != null) { + mTabGroupTitleEditor.destroy(); + } unregisterOnScrolledListener(); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java index 04150a53..6d5600b1 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java
@@ -11,7 +11,6 @@ import org.chromium.base.Token; import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabCreationState; import org.chromium.chrome.browser.tab.TabLaunchType; @@ -19,7 +18,6 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupColorUtils; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilterObserver; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupTitleUtils; @@ -35,8 +33,6 @@ * and shows a undo snackbar. */ public class UndoGroupSnackbarController implements SnackbarManager.SnackbarController { - private static final int INVALID_COLOR_ID = -1; - private final Context mContext; private final TabModelSelector mTabModelSelector; private final SnackbarManager mSnackbarManager; @@ -50,21 +46,18 @@ public final int tabOriginalRootId; public final @Nullable Token tabOriginalTabGroupId; public final String destinationGroupTitle; - public final int destinationGroupColorId; TabUndoInfo( Tab tab, int tabIndex, int rootId, @Nullable Token tabGroupId, - String destinationGroupTitle, - int destinationGroupColorId) { + String destinationGroupTitle) { this.tab = tab; this.tabOriginalIndex = tabIndex; this.tabOriginalRootId = rootId; this.tabOriginalTabGroupId = tabGroupId; this.destinationGroupTitle = destinationGroupTitle; - this.destinationGroupColorId = destinationGroupColorId; } } @@ -88,8 +81,7 @@ List<Integer> tabOriginalIndex, List<Integer> originalRootId, List<Token> originalTabGroupId, - String destinationGroupTitle, - int destinationGroupColorId) { + String destinationGroupTitle) { assert tabs.size() == tabOriginalIndex.size(); List<TabUndoInfo> tabUndoInfo = new ArrayList<>(); @@ -101,12 +93,7 @@ tabUndoInfo.add( new TabUndoInfo( - tab, - index, - rootId, - tabGroupId, - destinationGroupTitle, - destinationGroupColorId)); + tab, index, rootId, tabGroupId, destinationGroupTitle)); } showUndoGroupSnackbar(tabUndoInfo); } @@ -196,16 +183,11 @@ @Override public void onDismissNoAction(Object actionData) { - // Delete the original tab group titles and colors of the merging tabs once the merge is - // committed. + // Delete the original tab group titles of the merging tabs once the merge is committed. for (TabUndoInfo info : (List<TabUndoInfo>) actionData) { if (info.tab.getRootId() == info.tabOriginalRootId) continue; TabGroupTitleUtils.deleteTabGroupTitle(info.tabOriginalRootId); - - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - TabGroupColorUtils.deleteTabGroupColor(info.tabOriginalRootId); - } } } @@ -225,17 +207,6 @@ TabGroupTitleUtils.deleteTabGroupTitle(data.get(0).tab.getRootId()); } - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - // If the destination rootID previously did not have a color id associated with it since - // it was either created from a new tab group or was originally a single tab before - // merge, delete that color id on undo. This check deletes the group color for that - // destination rootID, as all tabs still currently share that ID before the undo - // operation is performed. - if (data.get(0).destinationGroupColorId == INVALID_COLOR_ID) { - TabGroupColorUtils.deleteTabGroupColor(data.get(0).tab.getRootId()); - } - } - for (int i = data.size() - 1; i >= 0; i--) { TabUndoInfo info = data.get(i); tabGroupModelFilter.undoGroupedTab(
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java index 472e081..5bea146 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -110,7 +110,6 @@ import org.chromium.chrome.browser.tab.TabUtils; import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupColorUtils; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; import org.chromium.chrome.browser.tasks.tab_groups.TabGroupTitleUtils; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; @@ -169,8 +168,6 @@ private static final String TEST_URL = "/chrome/test/data/android/google.html"; - private static final int INVALID_COLOR_ID = -1; - // Tests need animation on. @ClassRule public static DisableAnimationsTestRule sEnableAnimationsRule = @@ -1867,7 +1864,6 @@ @Test @MediumTest @UseMethodParameter(RefactorTestParams.class) - @EnableFeatures({ChromeFeatureList.TAB_GROUP_PARITY_ANDROID}) public void testUndoGroupMergeInTabSwitcher_TabToTab(boolean isStartSurfaceRefactorEnabled) { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); SnackbarManager snackbarManager = mActivityTestRule.getActivity().getSnackbarManager(); @@ -1875,40 +1871,22 @@ enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 2); - // Get the next suggested color id. - int nextSuggestedColorId = - TabGroupColorUtils.getNextSuggestedColorId( - (TabGroupModelFilter) - cta.getTabModelSelectorSupplier() - .get() - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - // Create a tab group. mergeAllNormalTabsToAGroup(cta); assertTrue( snackbarManager.getCurrentSnackbarForTesting().getController() instanceof UndoGroupSnackbarController); - // Assert that the suggested default color was set. - TabModel normalTabModel = cta.getTabModelSelectorSupplier().get().getModel(false); - int tabGroupRootId = normalTabModel.getTabAt(0).getRootId(); - assertEquals(nextSuggestedColorId, TabGroupColorUtils.getTabGroupColor(tabGroupRootId)); - // Undo merge in tab switcher. verifyTabSwitcherCardCount(cta, 1); assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo); verifyTabSwitcherCardCount(cta, 2); - - // Assert the color is no longer set for that group. - assertEquals(INVALID_COLOR_ID, TabGroupColorUtils.getTabGroupColor(tabGroupRootId)); } @Test @MediumTest @UseMethodParameter(RefactorTestParams.class) - @EnableFeatures({ChromeFeatureList.TAB_GROUP_PARITY_ANDROID}) public void testUndoGroupMergeInTabSwitcher_TabToGroupAdjacent( boolean isStartSurfaceRefactorEnabled) { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); @@ -1917,15 +1895,6 @@ enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 3); - // Get the next suggested color id. - int nextSuggestedColorId = - TabGroupColorUtils.getNextSuggestedColorId( - (TabGroupModelFilter) - cta.getTabModelSelectorSupplier() - .get() - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - // Merge first two tabs into a group. TabModel normalTabModel = cta.getTabModelSelector().getModel(false); List<Tab> tabGroup = @@ -1943,22 +1912,12 @@ instanceof UndoGroupSnackbarController); assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); - // Assert default color was set properly. - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(0).getRootId())); - // Merge tab group of 2 at first index with the 3rd tab. mergeAllNormalTabsToAGroup(cta); assertTrue( snackbarManager.getCurrentSnackbarForTesting().getController() instanceof UndoGroupSnackbarController); - // Assert the default color is still the tab group color - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(0).getRootId())); - // Undo merge in tab switcher. verifyTabSwitcherCardCount(cta, 1); assertEquals("3", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); @@ -1973,21 +1932,12 @@ assertNull( TabGroupTitleUtils.getTabGroupTitle( normalTabModel.getTabAt(2).getRootId())); - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor( - normalTabModel.getTabAt(1).getRootId())); - assertEquals( - INVALID_COLOR_ID, - TabGroupColorUtils.getTabGroupColor( - normalTabModel.getTabAt(2).getRootId())); }); } @Test @MediumTest @UseMethodParameter(RefactorTestParams.class) - @EnableFeatures({ChromeFeatureList.TAB_GROUP_PARITY_ANDROID}) public void testUndoGroupMergeInTabSwitcher_GroupToGroupNonAdjacent( boolean isStartSurfaceRefactorEnabled) { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); @@ -1996,15 +1946,6 @@ enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 5); - // Get the next suggested color id. - int nextSuggestedColorId1 = - TabGroupColorUtils.getNextSuggestedColorId( - (TabGroupModelFilter) - cta.getTabModelSelectorSupplier() - .get() - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - // Merge last two tabs into a group. TabModel normalTabModel = cta.getTabModelSelector().getModel(false); List<Tab> tabGroup = @@ -2017,20 +1958,6 @@ instanceof UndoGroupSnackbarController); assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); - // Assert default color 1 was set properly. - assertEquals( - nextSuggestedColorId1, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(4).getRootId())); - - // Get the next suggested color id. - int nextSuggestedColorId2 = - TabGroupColorUtils.getNextSuggestedColorId( - (TabGroupModelFilter) - cta.getTabModelSelectorSupplier() - .get() - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - // Merge first two tabs into a group. List<Tab> tabGroup2 = new ArrayList<>( @@ -2049,11 +1976,6 @@ instanceof UndoGroupSnackbarController); assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); - // Assert default color 2 was set properly. - assertEquals( - nextSuggestedColorId2, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(1).getRootId())); - // Merge the two tab groups into a group. List<Tab> tabGroup3 = new ArrayList<>( @@ -2063,11 +1985,6 @@ snackbarManager.getCurrentSnackbarForTesting().getController() instanceof UndoGroupSnackbarController); - // Assert default color 2 was set as the overall merged group color. - assertEquals( - nextSuggestedColorId2, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(3).getRootId())); - // Undo merge in tab switcher. verifyTabSwitcherCardCount(cta, 2); assertEquals("4", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); @@ -2083,21 +2000,12 @@ "Bar", TabGroupTitleUtils.getTabGroupTitle( normalTabModel.getTabAt(0).getRootId())); - assertEquals( - nextSuggestedColorId1, - TabGroupColorUtils.getTabGroupColor( - normalTabModel.getTabAt(4).getRootId())); - assertEquals( - nextSuggestedColorId2, - TabGroupColorUtils.getTabGroupColor( - normalTabModel.getTabAt(0).getRootId())); }); } @Test @MediumTest @UseMethodParameter(RefactorTestParams.class) - @EnableFeatures({ChromeFeatureList.TAB_GROUP_PARITY_ANDROID}) public void testUndoGroupMergeInTabSwitcher_PostMergeGroupTitleCommit( boolean isStartSurfaceRefactorEnabled) { final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); @@ -2106,15 +2014,6 @@ enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 3); - // Get the next suggested color id. - int nextSuggestedColorId = - TabGroupColorUtils.getNextSuggestedColorId( - (TabGroupModelFilter) - cta.getTabModelSelectorSupplier() - .get() - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - // Merge first two tabs into a group. TabModel normalTabModel = cta.getTabModelSelector().getModel(false); List<Tab> tabGroup = @@ -2135,22 +2034,12 @@ instanceof UndoGroupSnackbarController); assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); - // Assert default color was set properly. - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(1).getRootId())); - // Merge tab group of 2 at first index with the 3rd tab. mergeAllNormalTabsToAGroup(cta); assertTrue( snackbarManager.getCurrentSnackbarForTesting().getController() instanceof UndoGroupSnackbarController); - // Assert default color was set properly for the overall merged group. - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(2).getRootId())); - // Check that the old group title was handed over when the group merge is committed // and no longer exists. TestThreadUtils.runOnUiThreadBlocking(() -> snackbarManager.dismissAllSnackbars()); @@ -2162,130 +2051,6 @@ TabGroupTitleUtils.getTabGroupTitle( normalTabModel.getTabAt(0).getRootId())); }); - - // Assert color still exists post snackbar dismissal. - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(1).getRootId())); - } - - @Test - @MediumTest - @UseMethodParameter(RefactorTestParams.class) - @EnableFeatures({ChromeFeatureList.TAB_GROUP_PARITY_ANDROID}) - public void testUndoClosure_UndoGroupClosure(boolean isStartSurfaceRefactorEnabled) { - ChromeTabbedActivity cta = mActivityTestRule.getActivity(); - SnackbarManager snackbarManager = mActivityTestRule.getActivity().getSnackbarManager(); - createTabs(cta, false, 2); - - enterTabSwitcher(cta); - verifyTabSwitcherCardCount(cta, 2); - assertNull(snackbarManager.getCurrentSnackbarForTesting()); - - // Get the next suggested color id. - int nextSuggestedColorId = - TabGroupColorUtils.getNextSuggestedColorId( - (TabGroupModelFilter) - cta.getTabModelSelectorSupplier() - .get() - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - - // Merge first two tabs into a group. - TabModel normalTabModel = cta.getTabModelSelector().getModel(false); - List<Tab> tabGroup = - new ArrayList<>( - Arrays.asList(normalTabModel.getTabAt(0), normalTabModel.getTabAt(1))); - createTabGroup(cta, false, tabGroup); - verifyTabSwitcherCardCount(cta, 1); - assertTrue( - snackbarManager.getCurrentSnackbarForTesting().getController() - instanceof UndoGroupSnackbarController); - assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); - - // Assert default color was set properly. - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(1).getRootId())); - TestThreadUtils.runOnUiThreadBlocking(() -> snackbarManager.dismissAllSnackbars()); - - // Temporarily save the rootID to check during closure. - int groupRootId = normalTabModel.getTabAt(1).getRootId(); - - closeFirstTabInTabSwitcher(cta); - assertTrue( - snackbarManager.getCurrentSnackbarForTesting().getController() - instanceof UndoBarController); - verifyTabSwitcherCardCount(cta, 0); - - // Assert default color still persists. - assertEquals(nextSuggestedColorId, TabGroupColorUtils.getTabGroupColor(groupRootId)); - - CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo); - verifyTabSwitcherCardCount(cta, 1); - - // Assert default color still persists. - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(1).getRootId())); - } - - @Test - @MediumTest - @UseMethodParameter(RefactorTestParams.class) - @EnableFeatures({ChromeFeatureList.TAB_GROUP_PARITY_ANDROID}) - public void testUndoClosure_AcceptGroupClosure(boolean isStartSurfaceRefactorEnabled) { - ChromeTabbedActivity cta = mActivityTestRule.getActivity(); - SnackbarManager snackbarManager = mActivityTestRule.getActivity().getSnackbarManager(); - createTabs(cta, false, 2); - - enterTabSwitcher(cta); - verifyTabSwitcherCardCount(cta, 2); - assertNull(snackbarManager.getCurrentSnackbarForTesting()); - - // Get the next suggested color id. - int nextSuggestedColorId = - TabGroupColorUtils.getNextSuggestedColorId( - (TabGroupModelFilter) - cta.getTabModelSelectorSupplier() - .get() - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - - // Merge first two tabs into a group. - TabModel normalTabModel = cta.getTabModelSelector().getModel(false); - List<Tab> tabGroup = - new ArrayList<>( - Arrays.asList(normalTabModel.getTabAt(0), normalTabModel.getTabAt(1))); - createTabGroup(cta, false, tabGroup); - verifyTabSwitcherCardCount(cta, 1); - assertTrue( - snackbarManager.getCurrentSnackbarForTesting().getController() - instanceof UndoGroupSnackbarController); - assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting()); - - // Assert default color was set properly. - assertEquals( - nextSuggestedColorId, - TabGroupColorUtils.getTabGroupColor(normalTabModel.getTabAt(1).getRootId())); - TestThreadUtils.runOnUiThreadBlocking(() -> snackbarManager.dismissAllSnackbars()); - - // Temporarily save the rootID to check during closure. - int groupRootId = normalTabModel.getTabAt(1).getRootId(); - - closeFirstTabInTabSwitcher(cta); - assertTrue( - snackbarManager.getCurrentSnackbarForTesting().getController() - instanceof UndoBarController); - verifyTabSwitcherCardCount(cta, 0); - - // Assert default color still persists. - assertEquals(nextSuggestedColorId, TabGroupColorUtils.getTabGroupColor(groupRootId)); - - TestThreadUtils.runOnUiThreadBlocking(() -> snackbarManager.dismissAllSnackbars()); - - // Assert default color is cleared. - assertEquals(INVALID_COLOR_ID, TabGroupColorUtils.getTabGroupColor(groupRootId)); } @Test
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditorUnitTest.java index f77e09c58..77f61d2e 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditorUnitTest.java
@@ -4,42 +4,108 @@ package org.chromium.chrome.browser.tasks.tab_management; +import static androidx.test.espresso.matcher.ViewMatchers.assertThat; +import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import androidx.annotation.Nullable; + +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.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; +import org.chromium.base.Token; +import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Features; +import org.chromium.base.test.util.Features.DisableFeatures; +import org.chromium.base.test.util.Features.EnableFeatures; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabModel; +import org.chromium.chrome.browser.tabmodel.TabModelFilter; +import org.chromium.chrome.browser.tabmodel.TabModelObserver; +import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; +import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilterObserver; import org.chromium.chrome.tab_ui.R; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; /** Tests for {@link TabGroupTitleEditor}. */ @SuppressWarnings({"ArraysAsListWithZeroOrOneArgument", "ResultOfMethodCallIgnored"}) @RunWith(BaseRobolectricTestRunner.class) +@EnableFeatures(ChromeFeatureList.ANDROID_TAB_GROUP_STABLE_IDS) public class TabGroupTitleEditorUnitTest { @Rule public TestRule mProcessor = new Features.JUnitProcessor(); + private static final String TAB1_TITLE = "Tab1"; + private static final String TAB2_TITLE = "Tab2"; + private static final String TAB3_TITLE = "Tab3"; + private static final String TAB4_TITLE = "Tab4"; + private static final String CUSTOMIZED_TITLE1 = "Some cool tabs"; + private static final String CUSTOMIZED_TITLE2 = "Other cool tabs"; + private static final int TAB1_ID = 456; + private static final int TAB2_ID = 789; + private static final int TAB3_ID = 123; + private static final int TAB4_ID = 357; + private static final Token GROUP_1_ID = new Token(1L, 2L); + private static final Token GROUP_2_ID = new Token(2L, 3L); + + @Mock TabModel mTabModel; + @Mock TabGroupModelFilter mTabGroupModelFilter; + @Mock TabModel mIncognitoTabModel; + @Mock TabGroupModelFilter mIncognitoTabGroupModelFilter; + @Captor ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor; + @Captor ArgumentCaptor<TabGroupModelFilterObserver> mTabGroupModelFilterObserverCaptor; + + private final ObservableSupplierImpl<TabModelFilter> mTabModelFilterSupplier = + new ObservableSupplierImpl<>(); + private Tab mTab1; + private Tab mTab2; + private Tab mTab3; + private Tab mTab4; private Map<String, String> mStorage; private TabGroupTitleEditor mTabGroupTitleEditor; @Before public void setUp() { + MockitoAnnotations.initMocks(this); + mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID, TAB1_TITLE); + mTab2 = TabUiUnitTestUtils.prepareTab(TAB2_ID, TAB2_TITLE); + mTab3 = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); + mTab4 = TabUiUnitTestUtils.prepareTab(TAB4_ID, TAB4_TITLE); + doReturn(mTabModel).when(mTabGroupModelFilter).getTabModel(); + doReturn(mIncognitoTabModel).when(mIncognitoTabGroupModelFilter).getTabModel(); + mTabModelFilterSupplier.set(mTabGroupModelFilter); + doNothing().when(mTabGroupModelFilter).addObserver(mTabModelObserverCaptor.capture()); + doNothing() + .when(mTabGroupModelFilter) + .addTabGroupObserver(mTabGroupModelFilterObserverCaptor.capture()); + mTabGroupTitleEditor = - new TabGroupTitleEditor(RuntimeEnvironment.application) { + new TabGroupTitleEditor(RuntimeEnvironment.application, mTabModelFilterSupplier) { @Override protected void updateTabGroupTitle(Tab tab, String title) {} @@ -59,6 +125,226 @@ } }; mStorage = new HashMap<>(); + assertTrue(mTabModelFilterSupplier.hasObservers()); + } + + @After + public void tearDown() { + mTabGroupTitleEditor.destroy(); + assertFalse(mTabModelFilterSupplier.hasObservers()); + } + + @Test + public void testChangeModels() { + verify(mTabGroupModelFilter).addObserver(any()); + verify(mTabGroupModelFilter).addTabGroupObserver(any()); + mTabModelFilterSupplier.set(mIncognitoTabGroupModelFilter); + verify(mIncognitoTabGroupModelFilter).addObserver(any()); + verify(mIncognitoTabGroupModelFilter).addTabGroupObserver(any()); + verify(mTabGroupModelFilter).removeObserver(any()); + verify(mTabGroupModelFilter).removeTabGroupObserver(any()); + } + + @Test + public void tabClosureCommitted_RootTab_NotDeleteStoredTitle() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + assertThat(mStorage.size(), equalTo(1)); + + // Mock that tab1, tab2, new tab are in the same group and group root id is TAB1_ID. + Tab newTab = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); + List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, newTab)); + createTabGroup(tabs, TAB1_ID, GROUP_1_ID); + + // Mock that the root tab of the group, tab1, is closed. + List<Tab> groupAfterClosure = new ArrayList<>(Arrays.asList(mTab2, newTab)); + when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)) + .thenReturn(groupAfterClosure.size()); + mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab1); + + assertThat(mStorage.size(), equalTo(1)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB1_ID), equalTo(CUSTOMIZED_TITLE1)); + } + + @Test + public void tabClosureCommitted_NotRootTab_NotDeleteStoredTitle() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + + // Mock that tab1, tab2, new tab are in the same group and group root id is TAB1_ID. + Tab newTab = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); + List<Tab> groupBeforeClosure = new ArrayList<>(Arrays.asList(mTab1, mTab2, newTab)); + createTabGroup(groupBeforeClosure, TAB1_ID, GROUP_1_ID); + + // Mock that tab2 is closed and tab2 is not the root tab. + List<Tab> groupAfterClosure = new ArrayList<>(Arrays.asList(mTab1, newTab)); + when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)) + .thenReturn(groupAfterClosure.size()); + mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab2); + + assertThat(mStorage.size(), equalTo(1)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB1_ID), equalTo(CUSTOMIZED_TITLE1)); + } + + @Test + @DisableFeatures(ChromeFeatureList.ANDROID_TAB_GROUP_STABLE_IDS) + public void tabClosureCommitted_DeleteStoredTitle_GroupSize1NotSupported() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + assertThat(mStorage.size(), equalTo(1)); + + // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. + List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); + createTabGroup(tabs, TAB1_ID, GROUP_1_ID); + + // Mock that tab1 is closed and the group becomes a single tab. + when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)).thenReturn(1); + when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(false); + when(mTabGroupModelFilter.isTabInTabGroup(mTab2)).thenReturn(false); + mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab2); + + // The stored title should be deleted. + assertThat(mStorage.size(), equalTo(0)); + } + + @Test + public void tabClosureCommitted_DeleteStoredTitle_GroupSize1Supported() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + assertThat(mStorage.size(), equalTo(1)); + + // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. + List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); + createTabGroup(tabs, TAB1_ID, GROUP_1_ID); + + // Mock that tab1 is closed and the group becomes a single tab. + when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)).thenReturn(1); + when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(true); + when(mTabGroupModelFilter.isTabInTabGroup(mTab2)).thenReturn(false); + mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab2); + + // The stored title should not be deleted. + assertThat(mStorage.size(), equalTo(1)); + + when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(false); + mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab1); + + // The stored title should be deleted. + assertThat(mStorage.size(), equalTo(0)); + } + + @Test + public void tabMergeIntoGroup_NotDeleteStoredTitle() { + // Mock that we have two stored titles with reference to root ID of tab1 and tab3. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + mTabGroupTitleEditor.storeTabGroupTitle(TAB3_ID, CUSTOMIZED_TITLE2); + assertThat(mStorage.size(), equalTo(2)); + + // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID; tab3 and tab4 + // are in the same group and group root id is TAB3_ID. + List<Tab> group1 = new ArrayList<>(Arrays.asList(mTab1, mTab2)); + createTabGroup(group1, TAB1_ID, GROUP_1_ID); + List<Tab> group2 = new ArrayList<>(Arrays.asList(mTab3, mTab4)); + createTabGroup(group2, TAB3_ID, GROUP_2_ID); + + mTabGroupModelFilterObserverCaptor.getValue().willMergeTabToGroup(mTab1, TAB3_ID); + + // The title of the source group will not be deleted until the merge is committed, after + // SnackbarController#onDismissNoAction is called for the UndoGroupSnackbarController. + assertThat(mStorage.size(), equalTo(2)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB1_ID), equalTo(CUSTOMIZED_TITLE1)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB3_ID), equalTo(CUSTOMIZED_TITLE2)); + } + + @Test + public void tabMergeIntoGroup_HandOverStoredTitle() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + assertThat(mStorage.size(), equalTo(1)); + + // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID; tab3 and tab4 + // are in the same group and group root id is TAB3_ID. + List<Tab> group1 = new ArrayList<>(Arrays.asList(mTab1, mTab2)); + createTabGroup(group1, TAB1_ID, GROUP_1_ID); + List<Tab> group2 = new ArrayList<>(Arrays.asList(mTab3, mTab4)); + createTabGroup(group2, TAB3_ID, GROUP_2_ID); + + mTabGroupModelFilterObserverCaptor.getValue().willMergeTabToGroup(mTab1, TAB3_ID); + + // The stored title should be assigned to the new root id. The title of the source group + // will not be deleted until the merge is committed, after + // SnackbarController#onDismissNoAction is called for the UndoGroupSnackbarController. + assertThat(mStorage.size(), equalTo(2)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB1_ID), equalTo(CUSTOMIZED_TITLE1)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB3_ID), equalTo(CUSTOMIZED_TITLE1)); + } + + @Test + @DisableFeatures(ChromeFeatureList.ANDROID_TAB_GROUP_STABLE_IDS) + public void tabMoveOutOfGroup_DeleteStoredTitle_GroupSize1NotSupported() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + assertThat(mStorage.size(), equalTo(1)); + + // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. + List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); + createTabGroup(tabs, TAB1_ID, GROUP_1_ID); + + // Mock that we are going to ungroup tab1, and the group becomes a single tab after ungroup. + mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab1, TAB2_ID); + + // The stored title should be deleted. + assertThat(mStorage.size(), equalTo(0)); + } + + @Test + public void tabMoveOutOfGroup_DeleteStoredTitle_GroupSize1Supported() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + assertThat(mStorage.size(), equalTo(1)); + + // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. + List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); + createTabGroup(tabs, TAB1_ID, GROUP_1_ID); + + // Mock that we are going to ungroup tab1, and the group becomes a single tab after ungroup. + mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab1, TAB2_ID); + when(mTabGroupModelFilter.getGroupLastShownTab(TAB1_ID)).thenReturn(mTab1); + when(mTabGroupModelFilter.getGroupLastShownTab(TAB2_ID)).thenReturn(mTab2); + when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)).thenReturn(1); + when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB2_ID)).thenReturn(1); + when(mTab1.getRootId()).thenReturn(TAB1_ID); + when(mTab1.getTabGroupId()).thenReturn(null); + when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(false); + when(mTab2.getRootId()).thenReturn(TAB2_ID); + + // The stored title should not be deleted. + assertThat(mStorage.size(), equalTo(1)); + + mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab2, TAB2_ID); + + // The stored title should be deleted. + assertThat(mStorage.size(), equalTo(0)); + } + + @Test + public void tabMoveOutOfGroup_HandOverStoredTitle() { + // Mock that we have a stored title stored with reference to root ID of tab1. + mTabGroupTitleEditor.storeTabGroupTitle(TAB1_ID, CUSTOMIZED_TITLE1); + + // Mock that tab1, tab2 and newTab are in the same group and group root id is TAB1_ID. + Tab newTab = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); + List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, newTab)); + createTabGroup(tabs, TAB1_ID, GROUP_1_ID); + + // Mock that we are going to ungroup tab1, and the group is still a group after ungroup with + // root id become TAB2_ID. + mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab1, TAB2_ID); + + // The stored title should be assigned to the new root id. + assertThat(mStorage.size(), equalTo(1)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB1_ID), equalTo(null)); + assertThat(mTabGroupTitleEditor.getTabGroupTitle(TAB2_ID), equalTo(CUSTOMIZED_TITLE1)); } @Test @@ -87,4 +373,15 @@ assertFalse(mTabGroupTitleEditor.isDefaultTitle(fourTabsTitle, 3)); assertFalse(mTabGroupTitleEditor.isDefaultTitle("Foo", fourTabsCount)); } + + private void createTabGroup(List<Tab> tabs, int rootId, @Nullable Token groupId) { + Tab lastTab = tabs.isEmpty() ? null : tabs.get(0); + when(mTabGroupModelFilter.getGroupLastShownTab(rootId)).thenReturn(lastTab); + when(mTabGroupModelFilter.getRelatedTabCountForRootId(rootId)).thenReturn(tabs.size()); + for (Tab tab : tabs) { + when(mTabGroupModelFilter.isTabInTabGroup(tab)).thenReturn(tabs.size() != 1); + when(tab.getRootId()).thenReturn(rootId); + when(tab.getTabGroupId()).thenReturn(groupId); + } + } }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManagerUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManagerUnitTest.java deleted file mode 100644 index 91095c4e..0000000 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManagerUnitTest.java +++ /dev/null
@@ -1,440 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.tasks.tab_management; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.annotation.Nullable; -import androidx.collection.ArraySet; - -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.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import org.chromium.base.ContextUtils; -import org.chromium.base.Token; -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Features; -import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider; -import org.chromium.chrome.browser.tabmodel.TabModelObserver; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilterObserver; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -/** Tests for {@link TabGroupVisualDataManager}. */ -@SuppressWarnings({"ArraysAsListWithZeroOrOneArgument", "ResultOfMethodCallIgnored"}) -@RunWith(BaseRobolectricTestRunner.class) -@EnableFeatures({ - ChromeFeatureList.ANDROID_TAB_GROUP_STABLE_IDS, - ChromeFeatureList.TAB_GROUP_PARITY_ANDROID -}) -public class TabGroupVisualDataManagerUnitTest { - @Rule public TestRule mProcessor = new Features.JUnitProcessor(); - - private static final String TAB_GROUP_TITLES_FILE_NAME = "tab_group_titles"; - private static final String TAB_GROUP_COLORS_FILE_NAME = "tab_group_colors"; - - private static final String TAB1_TITLE = "Tab1"; - private static final String TAB2_TITLE = "Tab2"; - private static final String TAB3_TITLE = "Tab3"; - private static final String TAB4_TITLE = "Tab4"; - private static final String CUSTOMIZED_TITLE1 = "Some cool tabs"; - private static final String CUSTOMIZED_TITLE2 = "Other cool tabs"; - private static final int COLOR1_ID = 0; - private static final int COLOR2_ID = 1; - private static final int INVALID_COLOR_ID = -1; - private static final int TAB1_ID = 456; - private static final int TAB2_ID = 789; - private static final int TAB3_ID = 123; - private static final int TAB4_ID = 357; - private static final Token GROUP_1_ID = new Token(1L, 2L); - private static final Token GROUP_2_ID = new Token(2L, 3L); - - @Mock private Context mContext; - @Mock private TabGroupModelFilter mTabGroupModelFilter; - @Mock private TabGroupModelFilter mIncognitoTabGroupModelFilter; - @Mock private TabModelSelector mTabModelSelector; - @Mock private TabModelFilterProvider mTabModelFilterProvider; - @Mock private SharedPreferences mSharedPreferencesTitle; - @Mock private SharedPreferences.Editor mEditorTitle; - @Mock private SharedPreferences.Editor mPutStringEditorTitle; - @Mock private SharedPreferences.Editor mRemoveEditorTitle; - @Mock private SharedPreferences mSharedPreferencesColor; - @Mock private SharedPreferences.Editor mEditorColor; - @Mock private SharedPreferences.Editor mPutIntEditorColor; - @Mock private SharedPreferences.Editor mRemoveEditorColor; - @Captor private ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor; - @Captor private ArgumentCaptor<TabGroupModelFilterObserver> mTabGroupModelFilterObserverCaptor; - - @Captor - private ArgumentCaptor<TabGroupModelFilterObserver> mIncognitoTabGroupModelFilterObserverCaptor; - - private Tab mTab1; - private Tab mTab2; - private Tab mTab3; - private Tab mTab4; - private TabGroupVisualDataManager mTabGroupVisualDataManager; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mTab1 = TabUiUnitTestUtils.prepareTab(TAB1_ID, TAB1_TITLE); - mTab2 = TabUiUnitTestUtils.prepareTab(TAB2_ID, TAB2_TITLE); - mTab3 = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); - mTab4 = TabUiUnitTestUtils.prepareTab(TAB4_ID, TAB4_TITLE); - - doReturn(true).when(mTabModelSelector).isTabStateInitialized(); - doReturn(mTabModelFilterProvider).when(mTabModelSelector).getTabModelFilterProvider(); - doReturn(mTabGroupModelFilter).when(mTabModelFilterProvider).getCurrentTabModelFilter(); - doReturn(mTabGroupModelFilter).when(mTabModelFilterProvider).getTabModelFilter(false); - doReturn(mIncognitoTabGroupModelFilter) - .when(mTabModelFilterProvider) - .getTabModelFilter(true); - - doNothing() - .when(mTabModelFilterProvider) - .addTabModelFilterObserver(mTabModelObserverCaptor.capture()); - doNothing() - .when(mTabGroupModelFilter) - .addTabGroupObserver(mTabGroupModelFilterObserverCaptor.capture()); - doNothing() - .when(mIncognitoTabGroupModelFilter) - .addTabGroupObserver(mIncognitoTabGroupModelFilterObserverCaptor.capture()); - - mTabGroupVisualDataManager = new TabGroupVisualDataManager(mTabModelSelector); - - doReturn(mSharedPreferencesTitle) - .when(mContext) - .getSharedPreferences(TAB_GROUP_TITLES_FILE_NAME, Context.MODE_PRIVATE); - doReturn(mEditorTitle).when(mSharedPreferencesTitle).edit(); - doReturn(mRemoveEditorTitle).when(mEditorTitle).remove(any(String.class)); - doReturn(mPutStringEditorTitle) - .when(mEditorTitle) - .putString(any(String.class), any(String.class)); - - doReturn(mSharedPreferencesColor) - .when(mContext) - .getSharedPreferences(TAB_GROUP_COLORS_FILE_NAME, Context.MODE_PRIVATE); - doReturn(mEditorColor).when(mSharedPreferencesColor).edit(); - doReturn(mRemoveEditorColor).when(mEditorColor).remove(any(String.class)); - doReturn(mPutIntEditorColor) - .when(mEditorColor) - .putInt(any(String.class), any(Integer.class)); - - ContextUtils.initApplicationContextForTests(mContext); - } - - @After - public void tearDown() { - mTabGroupVisualDataManager.destroy(); - } - - @Test - public void tabClosureCommitted_RootTab_NotDeleteStoredTitle() { - // Assume that CUSTOMIZED_TITLE1 and COLOR1_ID are associated with the tab group. - // Mock that tab1, tab2, new tab are in the same group and group root id is TAB1_ID. - Tab newTab = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); - List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, newTab)); - createTabGroup(tabs, TAB1_ID, GROUP_1_ID); - - // Mock that the root tab of the group, tab1, is closed. - mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab1); - - // Verify that the title and color were not deleted. - verify(mEditorTitle, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle, never()).apply(); - verify(mEditorColor, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor, never()).apply(); - } - - @Test - public void tabClosureCommitted_NotRootTab_NotDeleteStoredTitle() { - // Assume that CUSTOMIZED_TITLE1 and COLOR1_ID are associated with the tab group. - // Mock that tab1, tab2, new tab are in the same group and group root id is TAB1_ID. - Tab newTab = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); - List<Tab> groupBeforeClosure = new ArrayList<>(Arrays.asList(mTab1, mTab2, newTab)); - createTabGroup(groupBeforeClosure, TAB1_ID, GROUP_1_ID); - - // Mock that tab2 is closed and tab2 is not the root tab. - mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab2); - - // Verify that the title and color were not deleted. - verify(mEditorTitle, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle, never()).apply(); - verify(mEditorColor, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor, never()).apply(); - } - - @Test - @DisableFeatures(ChromeFeatureList.ANDROID_TAB_GROUP_STABLE_IDS) - public void tabClosureCommitted_DeleteStoredTitle_GroupSize1NotSupported() { - // Assume that CUSTOMIZED_TITLE1 and COLOR1_ID are associated with the tab group. - // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. - List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); - createTabGroup(tabs, TAB1_ID, GROUP_1_ID); - - // Mock that tab1 is closed and the group becomes a single tab. - when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)).thenReturn(1); - when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(false); - when(mTabGroupModelFilter.isTabInTabGroup(mTab2)).thenReturn(false); - mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab2); - - // Verify that the title and color were deleted. - verify(mEditorTitle).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle).apply(); - verify(mEditorColor).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor).apply(); - } - - @Test - public void tabClosureCommitted_DeleteStoredTitle_GroupSize1Supported() { - // Assume that CUSTOMIZED_TITLE1 and COLOR1_ID are associated with the tab group. - // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. - List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); - createTabGroup(tabs, TAB1_ID, GROUP_1_ID); - - // Mock that tab1 is closed and the group becomes a single tab. - when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)).thenReturn(1); - when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(true); - when(mTabGroupModelFilter.isTabInTabGroup(mTab2)).thenReturn(false); - mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab2); - - // Verify that the title and color were not deleted. - verify(mEditorTitle, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle, never()).apply(); - verify(mEditorColor, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor, never()).apply(); - - when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(false); - mTabModelObserverCaptor.getValue().tabClosureCommitted(mTab1); - - // Verify that the title and color were deleted. - verify(mEditorTitle).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle).apply(); - verify(mEditorColor).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor).apply(); - } - - // TODO(b/41490324): Remove this test when introducing TabGroupCreationDialog logic. - @Test - public void didCreateNewGroup_StoreColor() { - // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. - // None of the tab groups have colors associated with them. - List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); - createTabGroup(tabs, TAB1_ID, GROUP_1_ID); - - // Create roodId set and mock that it has no color stored. - Set<Integer> rootIdsSet = new ArraySet<>(); - rootIdsSet.add(TAB1_ID); - when(mTabGroupModelFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB1_ID), INVALID_COLOR_ID)) - .thenReturn(INVALID_COLOR_ID); - - mTabGroupModelFilterObserverCaptor - .getValue() - .didCreateNewGroup(TAB1_ID, mTabGroupModelFilter); - - // Verify that a default color was stored. - verify(mEditorColor).putInt(eq(String.valueOf(TAB1_ID)), eq(COLOR1_ID)); - verify(mPutIntEditorColor).apply(); - } - - @Test - public void tabMergeIntoGroup_NotDeleteStoredTitle() { - // Mock that TITLE1, TITLE2 and COLOR1_ID, COLOR2_ID are associated with the groups. - when(mSharedPreferencesTitle.getString(String.valueOf(TAB1_ID), null)) - .thenReturn(CUSTOMIZED_TITLE1); - when(mSharedPreferencesTitle.getString(String.valueOf(TAB3_ID), null)) - .thenReturn(CUSTOMIZED_TITLE2); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB1_ID), INVALID_COLOR_ID)) - .thenReturn(COLOR1_ID); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB3_ID), INVALID_COLOR_ID)) - .thenReturn(COLOR2_ID); - - // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID; tab3 and tab4 - // are in the same group and group root id is TAB3_ID. - List<Tab> group1 = new ArrayList<>(Arrays.asList(mTab1, mTab2)); - createTabGroup(group1, TAB1_ID, GROUP_1_ID); - List<Tab> group2 = new ArrayList<>(Arrays.asList(mTab3, mTab4)); - createTabGroup(group2, TAB3_ID, GROUP_2_ID); - - mTabGroupModelFilterObserverCaptor.getValue().willMergeTabToGroup(mTab1, TAB3_ID); - - // The title of the source group will not be deleted until the merge is committed, after - // SnackbarController#onDismissNoAction is called for the UndoGroupSnackbarController. - verify(mEditorTitle, never()).putString(eq(String.valueOf(TAB3_ID)), eq(CUSTOMIZED_TITLE1)); - verify(mRemoveEditorTitle, never()).apply(); - verify(mEditorColor, never()).putInt(eq(String.valueOf(TAB3_ID)), eq(COLOR1_ID)); - verify(mRemoveEditorColor, never()).apply(); - } - - @Test - public void tabMergeIntoGroup_HandOverStoredTitle() { - // Mock that TITLE1 and COLOR1_ID are associated with the group of TAB1_ID. - when(mSharedPreferencesTitle.getString(String.valueOf(TAB1_ID), null)) - .thenReturn(CUSTOMIZED_TITLE1); - when(mSharedPreferencesTitle.getString(String.valueOf(TAB3_ID), null)).thenReturn(null); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB1_ID), INVALID_COLOR_ID)) - .thenReturn(COLOR1_ID); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB3_ID), INVALID_COLOR_ID)) - .thenReturn(INVALID_COLOR_ID); - - // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID; tab3 and tab4 - // are in the same group and group root id is TAB3_ID. - List<Tab> group1 = new ArrayList<>(Arrays.asList(mTab1, mTab2)); - createTabGroup(group1, TAB1_ID, GROUP_1_ID); - List<Tab> group2 = new ArrayList<>(Arrays.asList(mTab3, mTab4)); - createTabGroup(group2, TAB3_ID, GROUP_2_ID); - - mTabGroupModelFilterObserverCaptor.getValue().willMergeTabToGroup(mTab1, TAB3_ID); - - // The stored title should be assigned to the new root id. The title of the source group - // will not be deleted until the merge is committed, after - // SnackbarController#onDismissNoAction is called for the UndoGroupSnackbarController. - verify(mEditorTitle).putString(eq(String.valueOf(TAB3_ID)), eq(CUSTOMIZED_TITLE1)); - verify(mPutStringEditorTitle).apply(); - verify(mEditorColor).putInt(eq(String.valueOf(TAB3_ID)), eq(COLOR1_ID)); - verify(mPutIntEditorColor).apply(); - } - - @Test - @DisableFeatures(ChromeFeatureList.ANDROID_TAB_GROUP_STABLE_IDS) - public void tabMoveOutOfGroup_DeleteStoredTitle_GroupSize1NotSupported() { - // Mock that TITLE1 and COLOR1_ID are associated with the group of TAB1_ID. - when(mSharedPreferencesTitle.getString(String.valueOf(TAB1_ID), null)) - .thenReturn(CUSTOMIZED_TITLE1); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB1_ID), INVALID_COLOR_ID)) - .thenReturn(COLOR1_ID); - - // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. - List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); - createTabGroup(tabs, TAB1_ID, GROUP_1_ID); - - // Mock that we are going to ungroup tab1, and the group becomes a single tab after ungroup. - mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab1, TAB2_ID); - - // Verify that the title and color were deleted. - verify(mEditorTitle).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle).apply(); - verify(mEditorColor).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor).apply(); - } - - @Test - public void tabMoveOutOfGroup_DeleteStoredTitle_GroupSize1Supported() { - // Mock that TITLE1 and COLOR1_ID are associated with the group of TAB1_ID. - when(mSharedPreferencesTitle.getString(String.valueOf(TAB1_ID), null)) - .thenReturn(CUSTOMIZED_TITLE1); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB1_ID), INVALID_COLOR_ID)) - .thenReturn(COLOR1_ID); - - // Mock that tab1 and tab2 are in the same group and group root id is TAB1_ID. - List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2)); - createTabGroup(tabs, TAB1_ID, GROUP_1_ID); - - // Mock that we are going to ungroup tab1, and the group becomes a single tab after ungroup. - when(mTabGroupModelFilter.getGroupLastShownTab(TAB1_ID)).thenReturn(mTab1); - when(mTabGroupModelFilter.getGroupLastShownTab(TAB2_ID)).thenReturn(mTab2); - when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)).thenReturn(2); - when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB2_ID)).thenReturn(2); - when(mTab1.getRootId()).thenReturn(TAB1_ID); - when(mTab1.getTabGroupId()).thenReturn(null); - when(mTabGroupModelFilter.isTabInTabGroup(mTab1)).thenReturn(false); - when(mTab2.getRootId()).thenReturn(TAB2_ID); - - // Mock the situation that the root tab is not the tab being moved out. - mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab1, TAB1_ID); - - // Verify that the title and color were not deleted. - verify(mEditorTitle, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle, never()).apply(); - verify(mEditorColor, never()).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor, never()).apply(); - - // Mock that TITLE1 and COLOR1_ID are associated with the group of TAB1_ID. - when(mSharedPreferencesTitle.getString(String.valueOf(TAB2_ID), null)) - .thenReturn(CUSTOMIZED_TITLE1); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB2_ID), INVALID_COLOR_ID)) - .thenReturn(COLOR1_ID); - - // Mock that we are going to ungroup the last tab in a size 1 tab group, and it is the root - // tab. - when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB1_ID)).thenReturn(1); - when(mTabGroupModelFilter.getRelatedTabCountForRootId(TAB2_ID)).thenReturn(1); - - mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab2, TAB1_ID); - - // Verify that the title and color were deleted. - verify(mEditorTitle).remove(eq(String.valueOf(TAB2_ID))); - verify(mRemoveEditorTitle).apply(); - verify(mEditorColor).remove(eq(String.valueOf(TAB2_ID))); - verify(mRemoveEditorColor).apply(); - } - - @Test - public void tabMoveOutOfGroup_HandOverStoredTitle() { - // Mock that TITLE1 and COLOR1_ID are associated with the group of TAB1_ID. - when(mSharedPreferencesTitle.getString(String.valueOf(TAB1_ID), null)) - .thenReturn(CUSTOMIZED_TITLE1); - when(mSharedPreferencesColor.getInt(String.valueOf(TAB1_ID), INVALID_COLOR_ID)) - .thenReturn(COLOR1_ID); - - // Mock that tab1, tab2 and newTab are in the same group and group root id is TAB1_ID. - Tab newTab = TabUiUnitTestUtils.prepareTab(TAB3_ID, TAB3_TITLE); - List<Tab> tabs = new ArrayList<>(Arrays.asList(mTab1, mTab2, newTab)); - createTabGroup(tabs, TAB1_ID, GROUP_1_ID); - - // Mock that we are going to ungroup tab1, and the group is still a group after ungroup with - // root id become TAB2_ID. - mTabGroupModelFilterObserverCaptor.getValue().willMoveTabOutOfGroup(mTab1, TAB2_ID); - - // The stored title should be assigned to the new root id. - verify(mEditorTitle).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorTitle).apply(); - verify(mEditorTitle).putString(eq(String.valueOf(TAB2_ID)), eq(CUSTOMIZED_TITLE1)); - verify(mPutStringEditorTitle).apply(); - verify(mEditorColor).remove(eq(String.valueOf(TAB1_ID))); - verify(mRemoveEditorColor).apply(); - verify(mEditorColor).putInt(eq(String.valueOf(TAB2_ID)), eq(COLOR1_ID)); - verify(mPutIntEditorColor).apply(); - } - - private void createTabGroup(List<Tab> tabs, int rootId, @Nullable Token groupId) { - Tab lastTab = tabs.isEmpty() ? null : tabs.get(0); - when(mTabGroupModelFilter.getGroupLastShownTab(rootId)).thenReturn(lastTab); - when(mTabGroupModelFilter.getRelatedTabCountForRootId(rootId)).thenReturn(tabs.size()); - for (Tab tab : tabs) { - when(mTabGroupModelFilter.isTabInTabGroup(tab)).thenReturn(tabs.size() != 1); - when(tab.getRootId()).thenReturn(rootId); - when(tab.getTabGroupId()).thenReturn(groupId); - } - } -}
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index bb719bc..57666c0 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -1130,7 +1130,7 @@ mMediator.initWithNative(mProfile); // mTabModelObserverCaptor captures on every initWithNative call. - verify(mTabGroupModelFilter, times(2)).addObserver(mTabModelObserverCaptor.capture()); + verify(mTabGroupModelFilter, times(4)).addObserver(mTabModelObserverCaptor.capture()); initAndAssertAllProperties(); ThumbnailFetcher tab1Fetcher = mModel.get(0).model.get(TabProperties.THUMBNAIL_FETCHER); @@ -3204,11 +3204,11 @@ @Test public void testChangingTabModelFilters() { mCurrentTabModelFilterSupplier.set(mIncognitoTabGroupModelFilter); - // Once for the Mediator. - verify(mTabGroupModelFilter).removeObserver(any()); - verify(mTabGroupModelFilter).removeTabGroupObserver(any()); - verify(mIncognitoTabGroupModelFilter).addObserver(any()); - verify(mIncognitoTabGroupModelFilter).addTabGroupObserver(any()); + // Once for the Mediator and once for the TabGroupTitleEditor. + verify(mTabGroupModelFilter, times(2)).removeObserver(any()); + verify(mTabGroupModelFilter, times(2)).removeTabGroupObserver(any()); + verify(mIncognitoTabGroupModelFilter, times(2)).addObserver(any()); + verify(mIncognitoTabGroupModelFilter, times(2)).addTabGroupObserver(any()); } @Test @@ -3566,10 +3566,10 @@ mMediator.initWithNative(mProfile); assertThat( - mTabModelObserverCaptor.getAllValues().size(), equalTo(tabModelObserverCount + 1)); + mTabModelObserverCaptor.getAllValues().size(), equalTo(tabModelObserverCount + 2)); assertThat( mTabGroupModelFilterObserverCaptor.getAllValues().size(), - equalTo(tabGroupModelFilterObserverCount + 1)); + equalTo(tabGroupModelFilterObserverCount + 2)); mMediatorTabModelObserver = mTabModelObserverCaptor.getAllValues().get(tabModelObserverCount);
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 28472d07..33102dd 100644 --- a/chrome/android/features/tab_ui/tab_management_java_sources.gni +++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -14,7 +14,6 @@ "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ColorPickerUtils.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/RecyclerViewPosition.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUi.java", - "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManager.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListFaviconProvider.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java", @@ -204,7 +203,6 @@ "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupCreationTextInputLayoutTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupTitleEditorUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java", - "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupVisualDataManagerUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderUnitTest.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListEditorActionUnitTestHelper.java", "//chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListEditorBookmarkActionUnitTest.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java index e6d5688..33893cd7 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java
@@ -10,7 +10,6 @@ import org.chromium.base.ResettersForTesting; import org.chromium.chrome.browser.preferences.Pref; -import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabHidingType; @@ -144,7 +143,7 @@ private PrefService getPrefService() { if (sPrefServiceForTesting != null) return sPrefServiceForTesting; - return UserPrefs.get(ProfileManager.getLastUsedRegularProfile()); + return UserPrefs.get(mTab.getProfile()); } static void setPrefServiceForTesting(PrefService prefServiceForTesting) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 083de24..97b8366 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -209,11 +209,8 @@ import org.chromium.chrome.browser.tasks.ReturnToChromeUtil; import org.chromium.chrome.browser.tasks.ReturnToChromeUtil.ReturnToChromeBackPressHandler; import org.chromium.chrome.browser.tasks.TasksUma; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupColorUtils; -import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; import org.chromium.chrome.browser.tasks.tab_management.CloseAllTabsDialog; import org.chromium.chrome.browser.tasks.tab_management.TabGroupUi; -import org.chromium.chrome.browser.tasks.tab_management.TabGroupVisualDataManager; import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegateProvider; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; @@ -501,9 +498,6 @@ RecordUserAction.record("MobileNewTabOpened"); }; - // Manager for tab group visual data lifecycle updates. - private TabGroupVisualDataManager mTabGroupVisualDataManager; - /** * This class is used to warm up the chrome split ClassLoader. See SplitChromeApplication for * more info @@ -680,14 +674,6 @@ mTabModelOrchestrator.onNativeLibraryReady(getTabContentManager()); - TabModelUtils.runOnTabStateInitialized( - mTabModelSelector, - (tabModelSelector) -> { - assert tabModelSelector != null; - mTabGroupVisualDataManager = - new TabGroupVisualDataManager(tabModelSelector); - }); - // For saving non-incognito tab closures for Recent Tabs. mHistoricalTabModelObserver = new HistoricalTabModelObserver(mTabModelSelector.getModel(false)); @@ -2315,20 +2301,6 @@ this::getSnackbarManager, dialogVisibilitySupplier); - if (ChromeFeatureList.sTabGroupParityAndroid.isEnabled()) { - TabModelUtils.runOnTabStateInitialized( - getTabModelSelectorSupplier().get(), - (tabModelSelectorReturn) -> { - TabGroupColorUtils.assignTabGroupColorsIfApplicable( - (TabGroupModelFilter) - tabModelSelectorReturn - .getTabModelFilterProvider() - .getCurrentTabModelFilter()); - }); - } else { - PostTask.postTask(TaskTraits.UI_DEFAULT, TabGroupColorUtils::clearTabGroupColorInfo); - } - mInactivityTracker = new ChromeInactivityTracker( ChromePreferenceKeys.TABBED_ACTIVITY_LAST_BACKGROUNDED_TIME_MS_PREF); @@ -3614,11 +3586,6 @@ if (mHubProvider != null) mHubProvider.destroy(); - if (mTabGroupVisualDataManager != null) { - mTabGroupVisualDataManager.destroy(); - mTabGroupVisualDataManager = null; - } - super.onDestroyInternal(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentAdvanced.java b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentAdvanced.java index b524568..164efcb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentAdvanced.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentAdvanced.java
@@ -35,9 +35,6 @@ if (nonGoogleSearchHistoryTextPref != null) { getPreferenceScreen().removePreference(nonGoogleSearchHistoryTextPref); } - // TODO(https://crbug.com/1334920): Change after follow up discussion with privacy team. - Preference signOutOfChromeTextPref = - findPreference(ClearBrowsingDataFragment.PREF_SIGN_OUT_OF_CHROME_TEXT); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LegacyIncognitoDescriptionView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LegacyIncognitoDescriptionView.java index ae81fb2..073a827 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LegacyIncognitoDescriptionView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LegacyIncognitoDescriptionView.java
@@ -22,6 +22,7 @@ import android.widget.TextView; import androidx.annotation.IdRes; +import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.appcompat.widget.SwitchCompat; @@ -30,6 +31,7 @@ import org.chromium.ui.base.ViewUtils; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; +import org.chromium.ui.text.SpanApplier.SpanInfo; import org.chromium.ui.widget.ChromeBulletSpan; /** The view to describle incognito mode. */ @@ -145,8 +147,13 @@ */ private void populateBulletpoints(@IdRes int element, @StringRes int content) { TextView view = (TextView) findViewById(element); - String text = getContext().getResources().getString(content); + SpannableString spannedText = getSpannedBulletText(getContext(), content); + view.setText(spannedText); + } + @NonNull + static SpannableString getSpannedBulletText(Context context, @StringRes int content) { + String text = context.getResources().getString(content); // Some translations don't have a line break between list entries. text = text.replaceAll("([^\n ]) *(<li>|</?ul>)", "$1\n$2"); @@ -165,24 +172,31 @@ text = text.replaceFirst(" *<li>([^<]*)</li>", "<li2>$1</li2>"); text = text.replaceFirst(" *<li>([^<]*)</li>\n", "<li3>$1</li3>"); + String error = + "Format error. Locale: " + + context.getResources().getConfiguration().getLocales() + + " \nstring: " + + context.getResources().getString(content); + assert text.contains("<li1>") : error; + assert text.contains("<li2>") : error; + assert text.contains("<li3>") : error; + // Remove the <ul></ul> tags which serve no purpose here, including the whitespace around // them. text = text.replaceAll(" *</?ul>\\n?", ""); - view.setText( + SpannableString spannedText = SpanApplier.applySpans( text, - new SpanApplier.SpanInfo( + new SpanInfo( "<em>", "</em>", new ForegroundColorSpan( - getContext().getColor(R.color.incognito_emphasis))), - new SpanApplier.SpanInfo( - "<li1>", "</li1>", new ChromeBulletSpan(getContext())), - new SpanApplier.SpanInfo( - "<li2>", "</li2>", new ChromeBulletSpan(getContext())), - new SpanApplier.SpanInfo( - "<li3>", "</li3>", new ChromeBulletSpan(getContext())))); + context.getColor(R.color.incognito_emphasis))), + new SpanInfo("<li1>", "</li1>", new ChromeBulletSpan(context)), + new SpanInfo("<li2>", "</li2>", new ChromeBulletSpan(context)), + new SpanInfo("<li3>", "</li3>", new ChromeBulletSpan(context))); + return spannedText; } /** Adjusts the paddings, margins, and the orientation of bulletpoints. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionView.java index c8609cf..97f0a42 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionView.java
@@ -21,6 +21,7 @@ import android.widget.TextView; import androidx.annotation.IdRes; +import androidx.annotation.NonNull; import androidx.annotation.StringRes; import androidx.appcompat.widget.LinearLayoutCompat; import androidx.appcompat.widget.SwitchCompat; @@ -29,6 +30,7 @@ import org.chromium.components.content_settings.CookieControlsEnforcement; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; +import org.chromium.ui.text.SpanApplier.SpanInfo; import org.chromium.ui.widget.ChromeBulletSpan; /** The view to describe revamped incognito mode. */ @@ -135,8 +137,14 @@ * Populates |element| with |content|. */ private void populateDescriptions(@IdRes int element, @StringRes int content) { - TextView view = (TextView) findViewById(element); - String text = getContext().getResources().getString(content); + TextView view = findViewById(element); + SpannableString spannableString = getSpannedBulletText(getContext(), content); + view.setText(spannableString); + } + + @NonNull + static SpannableString getSpannedBulletText(Context context, int content) { + String text = context.getResources().getString(content); // Format the bulletpoints: // - Disambiguate the <li></li> spans for SpanApplier. @@ -146,19 +154,26 @@ text = text.replaceFirst(" *<li>([^<]*)</li>", "<li2>$1</li2>"); text = text.replaceFirst(" *<li>([^<]*)</li>\n", "<li3>$1</li3>"); + String error = + "Format error. Locale: " + + context.getResources().getConfiguration().getLocales() + + " \nstring: " + + context.getResources().getString(content); + assert text.contains("<li1>") : error; + assert text.contains("<li2>") : error; + assert text.contains("<li3>") : error; + // Remove the <ul></ul> tags which serve no purpose here, including the whitespace around // them. text = text.replaceAll(" *</?ul>\\n?", ""); - view.setText( + SpannableString spannableString = SpanApplier.applySpans( text, - new SpanApplier.SpanInfo( - "<li1>", "</li1>", new ChromeBulletSpan(getContext())), - new SpanApplier.SpanInfo( - "<li2>", "</li2>", new ChromeBulletSpan(getContext())), - new SpanApplier.SpanInfo( - "<li3>", "</li3>", new ChromeBulletSpan(getContext())))); + new SpanInfo("<li1>", "</li1>", new ChromeBulletSpan(context)), + new SpanInfo("<li2>", "</li2>", new ChromeBulletSpan(context)), + new SpanInfo("<li3>", "</li3>", new ChromeBulletSpan(context))); + return spannableString; } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java index 63577805..b266e2a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivitySigninAndSyncTest.java
@@ -75,7 +75,6 @@ import org.chromium.components.signin.base.AccountCapabilities; import org.chromium.components.signin.identitymanager.ConsentLevel; import org.chromium.components.signin.identitymanager.IdentityManager; -import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.components.signin.test.util.AccountCapabilitiesBuilder; import org.chromium.components.signin.test.util.FakeAccountManagerFacade; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -181,9 +180,6 @@ @Restriction({DeviceRestriction.RESTRICTION_TYPE_NON_AUTO}) @Features.EnableFeatures(ChromeFeatureList.REPLACE_SYNC_PROMOS_WITH_SIGN_IN_PROMOS) public void continueButtonClickShowsHistorySyncPage() { - HistogramWatcher histogramWatcher = - HistogramWatcher.newSingleRecordWatcher( - "Signin.HistorySyncOptIn.Started", SigninAccessPoint.START_PAGE); mAccountManagerTestRule.addAccount(TEST_EMAIL); launchFirstRunActivityAndWaitForNativeInitialization(); waitUntilCurrentPageIs(SigninFirstRunFragment.class); @@ -191,7 +187,6 @@ clickButton(R.id.signin_fre_continue_button); - histogramWatcher.assertExpected(); waitUntilCurrentPageIs(HistorySyncFirstRunFragment.class); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageTest.java index 998e3862..73fc33a6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPageTest.java
@@ -17,6 +17,10 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.not; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; + import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.filters.SmallTest; @@ -26,9 +30,11 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.LocaleUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Features.DisableFeatures; +import org.chromium.chrome.browser.ProductConfig; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.preferences.Pref; @@ -43,6 +49,8 @@ import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import java.util.Locale; + /** Integration tests for IncognitoNewTabPage. */ @RunWith(ChromeJUnit4ClassRunner.class) @Batch(Batch.PER_CLASS) @@ -161,4 +169,26 @@ onView(withId(R.id.tracking_protection_card)) .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); } + + private Context createContextForLocale(Context context, String languageTag) { + Locale locale = LocaleUtils.forLanguageTag(languageTag); + Resources res = context.getResources(); + Configuration config = res.getConfiguration(); + config.setLocale(locale); + return context.createConfigurationContext(config); + } + + /** Test the ntp text formatting for all locales. */ + @Test + @SmallTest + public void testDescriptionLanguages() throws Exception { + var context = sActivityTestRule.getActivity().getApplicationContext(); + for (String languageTag : ProductConfig.LOCALES) { + var localeContext = createContextForLocale(context, languageTag); + LegacyIncognitoDescriptionView.getSpannedBulletText( + localeContext, R.string.new_tab_otr_not_saved); + LegacyIncognitoDescriptionView.getSpannedBulletText( + localeContext, R.string.new_tab_otr_visible); + } + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoNewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoNewTabPageTest.java index b04f709..83452b1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoNewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoNewTabPageTest.java
@@ -17,6 +17,10 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.not; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; + import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.filters.SmallTest; @@ -26,10 +30,12 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.LocaleUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.base.test.util.Features.EnableFeatures; +import org.chromium.chrome.browser.ProductConfig; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.preferences.Pref; @@ -44,6 +50,8 @@ import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import java.util.Locale; + /** Integration tests for IncognitoNewTabPage. */ @RunWith(ChromeJUnit4ClassRunner.class) @Batch(Batch.PER_CLASS) @@ -160,4 +168,30 @@ onView(withId(R.id.revamped_tracking_protection_card)) .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))); } + + private Context createContextForLocale(Context context, String languageTag) { + Locale locale = LocaleUtils.forLanguageTag(languageTag); + Resources res = context.getResources(); + Configuration config = res.getConfiguration(); + config.setLocale(locale); + return context.createConfigurationContext(config); + } + + /** Test the ntp text formatting for all locales. */ + @Test + @SmallTest + public void testDescriptionLanguages() throws Exception { + var context = sActivityTestRule.getActivity().getApplicationContext(); + for (String languageTag : ProductConfig.LOCALES) { + // TODO(crbug.com/326858789): These languages have pending suggestions in TC. + // Remove these checks when the suggestions are added. + if (languageTag.equals("pt-BR")) continue; + if (languageTag.equals("sk")) continue; + var localeContext = createContextForLocale(context, languageTag); + RevampedIncognitoDescriptionView.getSpannedBulletText( + localeContext, R.string.revamped_incognito_ntp_does_description); + RevampedIncognitoDescriptionView.getSpannedBulletText( + localeContext, R.string.revamped_incognito_ntp_does_not_description); + } + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java index 1014749e..ba18c85 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java
@@ -74,9 +74,9 @@ private static final String CHILD_ACCOUNT_NAME = AccountManagerTestRule.generateChildEmail("account@gmail.com"); - public SyncTestRule mSyncTestRule = new SyncTestRule(); + private final SyncTestRule mSyncTestRule = new SyncTestRule(); - public final SettingsActivityTestRule<AccountManagementFragment> mSettingsActivityTestRule = + private final SettingsActivityTestRule<AccountManagementFragment> mSettingsActivityTestRule = new SettingsActivityTestRule<>(AccountManagementFragment.class); // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsWithFakeSyncServiceImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsWithFakeSyncServiceImplTest.java index c05d6cf..2b8f0bd 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsWithFakeSyncServiceImplTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsWithFakeSyncServiceImplTest.java
@@ -30,7 +30,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class ManageSyncSettingsWithFakeSyncServiceImplTest { - @Rule + @Rule(order = 0) public SyncTestRule mSyncTestRule = new SyncTestRule() { @Override @@ -39,7 +39,10 @@ } }; - @Rule + // SettingsActivity has to be finished before the outer ChromeTabbedActivity can be finished, + // otherwise trying to finish ChromeTabbedActivity won't work (SyncTestRule extends + // ChromeTabbedActivityTestRule). + @Rule(order = 1) public SettingsActivityTestRule<ManageSyncSettings> mSettingsActivityTestRule = new SettingsActivityTestRule<>(ManageSyncSettings.class);
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0a4e8bb5..05eb872 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -11099,6 +11099,11 @@ FEATURE_VALUE_TYPE( autofill::features::kAutofillEnableCardBenefitsForCapitalOne)}, + {"autofill-enable-card-benefits-sync", + flag_descriptions::kAutofillEnableCardBenefitsSyncName, + flag_descriptions::kAutofillEnableCardBenefitsSyncDescription, kOsAll, + FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableCardBenefitsSync)}, + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 1b1023e..9c15336 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -3608,6 +3608,7 @@ "//ash/public/cpp/external_arc", "//ash/public/mojom", "//ash/public/mojom:accelerator_info", + "//ash/public/mojom:hid_preserving_bluetooth_state_controller", "//ash/quick_pair/common", "//ash/webui/camera_app_ui", "//ash/webui/common/mojom:sea_pen",
diff --git a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_session.cc b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_session.cc index 8bd0e5d..fc37235 100644 --- a/chrome/browser/ash/arc/screen_capture/arc_screen_capture_session.cc +++ b/chrome/browser/ash/arc/screen_capture/arc_screen_capture_session.cc
@@ -228,15 +228,11 @@ auto client_shared_image = sii->CreateSharedImage( {si_format, size_, gfx::ColorSpace(), // NOTE: This SI will be used as the destination of a copy of the desktop - // texture via the raster interface. Hence, it needs RASTER_WRITE usage - // as well as GLES2_WRITE usage for the case where the raster interface - // is going over GLES2. - // TODO(crbug.com/1508447): Remove GLES2_WRITE usage once the browser - // main thread using the RasterDecoder implementation has definitively - // landed. - gpu::SHARED_IMAGE_USAGE_RASTER_WRITE | - gpu::SHARED_IMAGE_USAGE_GLES2_WRITE, - "ArcScreenCapture"}, + // texture via the raster interface. Hence, it needs RASTER_WRITE usage. + // Note that as the browser process raster interface uses + // RasterImplementation (and not RasterImplementationGLES) as its + // implementation, GLES2_WRITE usage is not needed. + gpu::SHARED_IMAGE_USAGE_RASTER_WRITE, "ArcScreenCapture"}, std::move(handle)); CHECK(client_shared_image); ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc index 18c00a4..b566f2c 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_impl.cc
@@ -618,7 +618,9 @@ if (!user_is_local) { SetInitialUserImage(); is_random_image_set_ = true; - DownloadProfileImage(); + // We should download the user image in this case, but at this moment the + // user Profile instance is not yet ready. The actual downloading will be + // handled in UserProfileCreated(). } } else { // Although UserImage.LoggedIn3 is an enumerated histogram, we intentionally @@ -1030,10 +1032,10 @@ bool UserImageManagerImpl::IsCustomizationSelectorsPrefEnabled() const { const user_manager::User* user = GetUser(); - content::BrowserContext* browser_context = - BrowserContextHelper::Get()->GetBrowserContextByUser(user); - Profile* profile = Profile::FromBrowserContext(browser_context); - return user_image::prefs::IsCustomizationSelectorsPrefEnabled(profile); + // When this method is called, user Profile must be initialized already. + auto* prefs = user->GetProfilePrefs(); + CHECK(prefs); + return user_image::prefs::IsCustomizationSelectorsPrefEnabled(prefs); } } // namespace ash
diff --git a/chrome/browser/ash/login/users/avatar/user_image_prefs.cc b/chrome/browser/ash/login/users/avatar/user_image_prefs.cc index 61f756e..e456a8d 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_prefs.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_prefs.cc
@@ -4,8 +4,6 @@ #include "chrome/browser/ash/login/users/avatar/user_image_prefs.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -18,9 +16,8 @@ registry->RegisterBooleanPref(kUserAvatarCustomizationSelectorsEnabled, true); } -bool IsCustomizationSelectorsPrefEnabled(Profile* profile) { - PrefService* pref_service = profile->GetPrefs(); - return pref_service->GetBoolean( +bool IsCustomizationSelectorsPrefEnabled(const PrefService* prefs) { + return prefs->GetBoolean( user_image::prefs::kUserAvatarCustomizationSelectorsEnabled); }
diff --git a/chrome/browser/ash/login/users/avatar/user_image_prefs.h b/chrome/browser/ash/login/users/avatar/user_image_prefs.h index ec58423..eb1c8360 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_prefs.h +++ b/chrome/browser/ash/login/users/avatar/user_image_prefs.h
@@ -5,9 +5,8 @@ #ifndef CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_PREFS_H_ #define CHROME_BROWSER_ASH_LOGIN_USERS_AVATAR_USER_IMAGE_PREFS_H_ -#include "chrome/browser/profiles/profile.h" - class PrefRegistrySimple; +class PrefService; namespace ash::user_image::prefs { @@ -19,7 +18,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry); // Returns boolean value of the kUserAvatarCustomizationSelectorsEnabled pref. -bool IsCustomizationSelectorsPrefEnabled(Profile* profile); +bool IsCustomizationSelectorsPrefEnabled(const PrefService* pref_service); } // namespace ash::user_image::prefs
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc index 4019c04..dce52db 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_impl.cc +++ b/chrome/browser/ash/login/users/chrome_user_manager_impl.cc
@@ -745,10 +745,6 @@ MaybeStartBluetoothLogging(account_id); - // TODO(b/278643115): Move this into UserManagerBase::NotifyOnLogin. - for (auto& observer : observer_list_) { - observer.OnUserLoggedIn(*active_user_); - } WallpaperControllerClientImpl::Get()->ShowUserWallpaper(account_id); // Make sure that new data is persisted to Local State. @@ -760,11 +756,6 @@ const user_manager::UserType user_type) { DCHECK_CURRENTLY_ON(BrowserThread::UI); UserManagerBase::RegularUserLoggedInAsEphemeral(account_id, user_type); - - // TODO(b/278643115): Move this into UserManagerBase::NotifyOnLogin. - for (auto& observer : observer_list_) { - observer.OnUserLoggedIn(*active_user_); - } WallpaperControllerClientImpl::Get()->ShowUserWallpaper(account_id); } @@ -784,11 +775,6 @@ SetIsCurrentUserNew(true); active_user_ = user; - // TODO(b/278643115): Move this into UserManagerBase::NotifyOnLogin. - for (auto& observer : observer_list_) { - observer.OnUserLoggedIn(*active_user_); - } - // For public account, it's possible that the user-policy controlled wallpaper // was fetched/cleared at the login screen (while for a regular user it was // always fetched/cleared inside a user session), in the case the user-policy
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc index 490bbb4..cedf3ac0 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl.cc
@@ -405,7 +405,8 @@ } bool PersonalizationAppUserProviderImpl::IsCustomizationSelectorsPrefEnabled() { - return user_image::prefs::IsCustomizationSelectorsPrefEnabled(profile_); + return user_image::prefs::IsCustomizationSelectorsPrefEnabled( + profile_->GetPrefs()); } void PersonalizationAppUserProviderImpl::UpdateUserImageObserver(
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc index db5bc04..b03308f9 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc
@@ -63,19 +63,6 @@ constexpr char kFakeTestName[] = "Fake Name"; constexpr char kTestGaiaId[] = "1234567890"; -void AddAndLoginUser(const AccountId& account_id, - const std::string& display_name) { - ash::FakeChromeUserManager* user_manager = - static_cast<ash::FakeChromeUserManager*>( - user_manager::UserManager::Get()); - - user_manager->AddUser(account_id); - user_manager->SaveUserDisplayName(account_id, - base::UTF8ToUTF16(display_name)); - user_manager->LoginUser(account_id); - user_manager->SwitchActiveUser(account_id); -} - mojo_base::BigBuffer FakeEncodedPngBuffer() { return mojo_base::BigBuffer({0, 1}); } @@ -170,9 +157,7 @@ class PersonalizationAppUserProviderImplTest : public testing::Test { public: - PersonalizationAppUserProviderImplTest() - : scoped_user_manager_(std::make_unique<ash::FakeChromeUserManager>()), - profile_manager_(TestingBrowserProcess::GetGlobal()) {} + PersonalizationAppUserProviderImplTest() = default; PersonalizationAppUserProviderImplTest( const PersonalizationAppUserProviderImplTest&) = delete; PersonalizationAppUserProviderImplTest& operator=( @@ -183,11 +168,22 @@ // testing::Test: void SetUp() override { UserImageManagerImpl::SkipDefaultUserImageDownloadForTesting(); - ASSERT_TRUE(profile_manager_.SetUp()); + + // Add a User then log in. + const AccountId account_id = + AccountId::FromUserEmailGaiaId(kFakeTestEmail, kTestGaiaId); + user_manager_->AddUser(account_id); + user_manager_->SaveUserDisplayName( + account_id, base::UTF8ToUTF16(std::string(kFakeTestName))); + user_manager_->UserLoggedIn( + account_id, + user_manager::FakeUserManager::GetFakeUsernameHash(account_id), + /*browser_restart=*/false, /*is_child=*/false); + + // Create a profile and set it as User profile. profile_ = profile_manager_.CreateTestingProfile(kFakeTestEmail); - AddAndLoginUser(AccountId::FromUserEmailGaiaId(kFakeTestEmail, kTestGaiaId), - kFakeTestName); + user_manager_->OnUserProfileCreated(account_id, profile_->GetPrefs()); web_contents_ = content::WebContents::Create( content::WebContents::CreateParams(profile_)); @@ -202,6 +198,11 @@ user_provider_remote_.BindNewPipeAndPassReceiver()); } + void TearDown() override { + user_manager_->OnUserProfileWillBeDestroyed( + AccountId::FromUserEmailGaiaId(kFakeTestEmail, kTestGaiaId)); + } + TestingProfile* profile() { return profile_; } content::TestWebUI* web_ui() { return &web_ui_; } @@ -229,11 +230,6 @@ GetAccountId(profile_))); } - ash::FakeChromeUserManager* GetFakeUserManager() { - return static_cast<ash::FakeChromeUserManager*>( - user_manager::UserManager::Get()); - } - void SetUserImageObserver() { user_provider_remote_->SetUserImageObserver( test_user_image_observer_.pending_remote()); @@ -276,10 +272,10 @@ private: base::test::ScopedFeatureList scoped_feature_list_; content::BrowserTaskEnvironment task_environment_; - user_manager::ScopedUserManager scoped_user_manager_; - UserImageManagerRegistry user_image_manager_registry_{ - user_manager::UserManager::Get()}; - TestingProfileManager profile_manager_; + user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> + user_manager_{std::make_unique<ash::FakeChromeUserManager>()}; + UserImageManagerRegistry user_image_manager_registry_{user_manager_.Get()}; + TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()}; data_decoder::test::InProcessDataDecoder data_decoder_; content::TestWebUI web_ui_; std::unique_ptr<content::WebContents> web_contents_;
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 44a658a..26e16fd 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -249,6 +249,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_features.h" +#include "ash/public/mojom/hid_preserving_bluetooth_state_controller.mojom.h" #include "ash/webui/camera_app_ui/camera_app_helper.mojom.h" #include "ash/webui/camera_app_ui/camera_app_ui.h" #include "ash/webui/color_internals/color_internals_ui.h" @@ -1300,6 +1301,14 @@ ntp::tab_resumption::mojom::PageHandler, NewTabPageUI>(map); } +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (ash::features::IsBluetoothDisconnectWarningEnabled()) { + RegisterWebUIControllerInterfaceBinder< + ash::mojom::HidPreservingBluetoothStateController, + ash::settings::OSSettingsUI>(map); + } +#endif // defined(IS_CHROMEOS_ASH) + RegisterWebUIControllerInterfaceBinder< reading_list::mojom::PageHandlerFactory, ReadingListUI>(map); RegisterWebUIControllerInterfaceBinder<
diff --git a/chrome/browser/chromeos/mahi/mahi_tab_helper.cc b/chrome/browser/chromeos/mahi/mahi_tab_helper.cc index a694330c..8e35a7f 100644 --- a/chrome/browser/chromeos/mahi/mahi_tab_helper.cc +++ b/chrome/browser/chromeos/mahi/mahi_tab_helper.cc
@@ -42,8 +42,6 @@ if (ShouldSkip()) { return; } - MahiWebContentsManager::Get()->OnFocusChanged(web_contents()); - // Only fire an event if the web content has finished document loading. // Otherwise, it would be handled by // `DocumentOnLoadCompletedInPrimaryMainFrame`.
diff --git a/chrome/browser/chromeos/mahi/mahi_tab_helper_unittest.cc b/chrome/browser/chromeos/mahi/mahi_tab_helper_unittest.cc index d9c8dd8f..212e8a0 100644 --- a/chrome/browser/chromeos/mahi/mahi_tab_helper_unittest.cc +++ b/chrome/browser/chromeos/mahi/mahi_tab_helper_unittest.cc
@@ -85,7 +85,6 @@ EXPECT_NE(nullptr, MahiTabHelper::FromWebContents(web_contents2)); // Switch back to a previous loaded tab. - EXPECT_CALL(mock_mahi_web_contents_manager_, OnFocusChanged(_)).Times(1); EXPECT_CALL(mock_mahi_web_contents_manager_, OnFocusedPageLoadComplete(_)) .Times(1); // Change active tab with `browser()->tab_strip_model()->ActivateTabAt()` or
diff --git a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc index 24222946..a73a2a6 100644 --- a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc +++ b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.cc
@@ -54,29 +54,21 @@ is_initialized_ = true; } -void MahiWebContentsManager::OnFocusChanged( - content::WebContents* web_contents) { - // Creates a new focused web content state. - focused_web_content_state_ = - WebContentState(web_contents->GetVisibleURL(), web_contents->GetTitle()); - - client_->OnFocusedPageChanged(focused_web_content_state_); -} - void MahiWebContentsManager::OnFocusedPageLoadComplete( content::WebContents* web_contents) { - if (focused_web_content_state_.url != web_contents->GetVisibleURL()) { - LOG(ERROR) << "MahiBrowser:: Focused page does not match."; - return; - } + // Creates a new focused web content state, and fires `OnFocusedPageChanged()` + // event immediately so that `MahiManager` knows the focused page has changed. + focused_web_content_state_ = WebContentState( + web_contents->GetLastCommittedURL(), web_contents->GetTitle()); + client_->OnFocusedPageChanged(focused_web_content_state_); + // Requests the a11y tree snapshot. content::RenderFrameHost* render_frame_host = web_contents->GetPrimaryMainFrame(); if (render_frame_host) { focused_web_content_state_.ukm_source_id = render_frame_host->GetPageUkmSourceId(); } - web_contents->RequestAXTreeSnapshot( base::BindOnce(&MahiWebContentsManager::OnGetSnapshot, weak_pointer_factory_.GetWeakPtr(),
diff --git a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h index 1d74902a..d769e0f 100644 --- a/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h +++ b/chrome/browser/chromeos/mahi/mahi_web_contents_manager.h
@@ -47,10 +47,6 @@ void Initialize(); - // Called when the focused tab changed. - // Virtual so we can override in tests. - virtual void OnFocusChanged(content::WebContents* web_contents); - // Called when the focused tab finish loading. // Virtual so we can override in tests. virtual void OnFocusedPageLoadComplete(content::WebContents* web_contents);
diff --git a/chrome/browser/chromeos/mahi/mahi_web_contents_manager_browsertest.cc b/chrome/browser/chromeos/mahi/mahi_web_contents_manager_browsertest.cc index 6e48a39..5bea90bd 100644 --- a/chrome/browser/chromeos/mahi/mahi_web_contents_manager_browsertest.cc +++ b/chrome/browser/chromeos/mahi/mahi_web_contents_manager_browsertest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/chromeos/mahi/test/scoped_mahi_web_contents_manager_for_testing.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/crosapi/mojom/mahi.mojom.h" #include "chromeos/lacros/lacros_service.h" @@ -88,6 +89,10 @@ // Simulates opening a new tab with url. void CreateWebContent() { + // Simulates chrome open. + ASSERT_TRUE( + ui_test_utils::NavigateToURL(browser(), GURL("chrome://newtab/"))); + // Then navigates to the target page. EXPECT_TRUE(AddTabAtIndex(0, GURL(kUrl), ui::PAGE_TRANSITION_TYPED)); }
diff --git a/chrome/browser/chromeos/mahi/test/mock_mahi_web_contents_manager.h b/chrome/browser/chromeos/mahi/test/mock_mahi_web_contents_manager.h index 8456b24..2aec4b8 100644 --- a/chrome/browser/chromeos/mahi/test/mock_mahi_web_contents_manager.h +++ b/chrome/browser/chromeos/mahi/test/mock_mahi_web_contents_manager.h
@@ -15,7 +15,6 @@ MockMahiWebContentsManager(); ~MockMahiWebContentsManager() override; - MOCK_METHOD1(OnFocusChanged, void(content::WebContents*)); MOCK_METHOD1(OnFocusedPageLoadComplete, void(content::WebContents*)); };
diff --git a/chrome/browser/compose/chrome_compose_client.cc b/chrome/browser/compose/chrome_compose_client.cc index 684159a..686d86ee 100644 --- a/chrome/browser/compose/chrome_compose_client.cc +++ b/chrome/browser/compose/chrome_compose_client.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/compose/chrome_compose_client.h" #include <memory> +#include <optional> #include <string> #include <utility> @@ -33,7 +34,10 @@ #include "chrome/common/pref_names.h" #include "components/autofill/content/browser/content_autofill_client.h" #include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/content/browser/content_autofill_driver_factory.h" +#include "components/autofill/core/common/aliases.h" #include "components/autofill/core/common/form_field_data.h" +#include "components/autofill/core/common/unique_ids.h" #include "components/compose/core/browser/compose_features.h" #include "components/compose/core/browser/compose_manager_impl.h" #include "components/compose/core/browser/compose_metrics.h" @@ -441,12 +445,34 @@ if (!active_compose_ids_.has_value()) { return; } - if (auto* autofill_client = - autofill::ContentAutofillClient::FromWebContents(&GetWebContents())) { - autofill_client->ShowComposeFadingPopup( - /*form_id=*/active_compose_ids_->second, - /*field_id=*/active_compose_ids_->first); + + autofill::AutofillDriver* driver = + autofill::ContentAutofillDriverFactory::FromWebContents(&GetWebContents()) + ->DriverForFrame(GetWebContents().GetPrimaryMainFrame()); + if (!driver) { + return; } + // AutofillDriver forwards ExtractForm to the AutofillDriverRouter which can + // find the correct driver to use for the form. + driver->ExtractForm( + /*form=*/active_compose_ids_->second, /*response_handler=*/base::BindOnce( + [](autofill::FieldGlobalId trigger_field, + autofill::AutofillDriver* host_frame_driver, + const std::optional<autofill::FormData>& form) { + if (!form) { + return; + } + CHECK(host_frame_driver); + const autofill::FormFieldData* form_field = + form->FindFieldByGlobalId(trigger_field); + if (form_field != nullptr) { + host_frame_driver->GetAutofillManager().OnAskForValuesToFill( + *form, *form_field, form_field->bounds, + autofill::AutofillSuggestionTriggerSource:: + kComposeDialogLostFocus); + } + }, + /*field_id=*/active_compose_ids_->first)); } ComposeSession* ChromeComposeClient::GetSessionForActiveComposeField() {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 51216ab..71c878b 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -595,6 +595,11 @@ "expiry_milestone": 130 }, { + "name": "autofill-enable-card-benefits-sync", + "owners": [ "alexandertekle@chromium.org", "yishuil@google.com" ], + "expiry_milestone": 130 + }, + { "name": "autofill-enable-card-product-name", "owners": [ "vishwasuppoor@chromium.org", "siyua@chromium.org", "alexandertekle@chromium.org" ], "expiry_milestone": 125
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index ddd69a8..785631e 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -482,6 +482,12 @@ "When enabled, card benefits offered by Capital One will be shown in " "Autofill suggestions."; +const char kAutofillEnableCardBenefitsSyncName[] = + "Enable syncing card benefits"; +const char kAutofillEnableCardBenefitsSyncDescription[] = + "When enabled, card benefits offered by issuers will be synced from the " + "Payments server."; + const char kAutofillEnableCardProductNameName[] = "Enable showing card product name"; const char kAutofillEnableCardProductNameDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 97267e4..4a6f517 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -289,6 +289,9 @@ extern const char kAutofillEnableCardBenefitsForCapitalOneName[]; extern const char kAutofillEnableCardBenefitsForCapitalOneDescription[]; +extern const char kAutofillEnableCardBenefitsSyncName[]; +extern const char kAutofillEnableCardBenefitsSyncDescription[]; + extern const char kAutofillEnableCardProductNameName[]; extern const char kAutofillEnableCardProductNameDescription[];
diff --git a/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc b/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc index 2865125e..255fc8e 100644 --- a/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc +++ b/chrome/browser/optimization_guide/page_content_annotations_service_browsertest.cc
@@ -917,7 +917,6 @@ {features::kPageContentAnnotations, {{"write_to_history_service", "false"}, {"annotate_visit_batch_size", "2"}}}, - {features::kPageEntitiesPageContentAnnotations, {}}, {features::kPageVisibilityPageContentAnnotations, {}}}, /*disabled_features=*/{}); }
diff --git a/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.cc b/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.cc index 8af4387..36a17e6 100644 --- a/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.cc +++ b/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.cc
@@ -308,9 +308,10 @@ void BuiltInBackendToAndroidBackendMigrator::RunMigrationForLocalUsers() { auto barrier_callback = base::BarrierCallback<BackendAndLoginsResults>( - 2, base::BindOnce(&BuiltInBackendToAndroidBackendMigrator:: - MigratePasswordsBetweenAndroidAndBuiltInBackends, - weak_ptr_factory_.GetWeakPtr())); + 2, + base::BindOnce(&BuiltInBackendToAndroidBackendMigrator:: + MigrateLocalPasswordsBetweenAndroidAndBuiltInBackends, + weak_ptr_factory_.GetWeakPtr())); auto bind_backend_to_logins = [](PasswordStoreBackend* backend, LoginsResultOrError result) { @@ -346,7 +347,7 @@ } void BuiltInBackendToAndroidBackendMigrator:: - MigratePasswordsBetweenAndroidAndBuiltInBackends( + MigrateLocalPasswordsBetweenAndroidAndBuiltInBackends( std::vector<BackendAndLoginsResults> results) { DCHECK(metrics_reporter_); DCHECK_EQ(2u, results.size()); @@ -364,29 +365,20 @@ (results[0].backend == android_backend_) ? results[0].GetLogins() : results[1].GetLogins(); - if (!HasMigratedToTheAndroidBackend(prefs_)) { - MergeAndroidBackendAndBuiltInBackend(std::move(built_in_backend_logins), - std::move(android_logins)); - } else { - MirrorAndroidBackendToBuiltInBackend(std::move(built_in_backend_logins), - std::move(android_logins)); - } + MergeBuiltInBackendIntoAndroidBackend(std::move(built_in_backend_logins), + std::move(android_logins)); } void BuiltInBackendToAndroidBackendMigrator:: - MergeAndroidBackendAndBuiltInBackend( + MergeBuiltInBackendIntoAndroidBackend( PasswordFormPtrFlatSet built_in_backend_logins, PasswordFormPtrFlatSet android_logins) { - // For a form |F|, there are three cases to handle: + // For a form |F|, there are 2 cases to handle: // 1. If |F| exists only in the |built_in_backend_|, then |F| should be added // to the |android_backend_|. - // 2. If |F| exists only in the |android_backend_|, then |F| should be added - // to the |built_in_backend_|. - // 3. If |F| exists in both |built_in_backend_| and |android_backend_|, then - // both versions should be merged by accepting the most recently created - // one*, and update either |built_in_backend_| and |android_backend_| - // accordingly. - // * it should happen only if password values differs between backends. + // 2. If |F| already exists in both |android_backend_|, then + // the most recent version of |F| will be kept in |android_backend_|. + // TODO (b/321217242): No changes to |built_in_backend_| should be done. // Callbacks are chained like in a stack way by passing 'callback_chain' as a // completion for the next operation. At the end, update pref to mark @@ -425,6 +417,7 @@ weak_ptr_factory_.GetWeakPtr(), android_backend_, *login, std::move(callbacks_chain)); } else { + // TODO (b/321217242): No changes to |built_in_backend_| should be done. callbacks_chain = base::BindOnce( &BuiltInBackendToAndroidBackendMigrator::UpdateLoginInBackend, weak_ptr_factory_.GetWeakPtr(), built_in_backend_, *android_login, @@ -432,75 +425,7 @@ } } - // At this point, we have processed all passwords from the |built_in_backend_| - // In addition, we also have processed all passwords from the - // |android_backend_| which exist in the |built_in_backend_|. What's remaining - // is to process passwords from |android_backend_| that don't exist in the - // |built_in_backend_|. - for (auto* const android_login : android_logins) { - if (built_in_backend_logins.contains(android_login)) { - continue; - } - - // Add to the |built_in_backend_| any passwords from the |android_backend_| - // that doesn't exist in the |built_in_backend_|. - callbacks_chain = base::BindOnce( - &BuiltInBackendToAndroidBackendMigrator::AddLoginToBackend, - weak_ptr_factory_.GetWeakPtr(), built_in_backend_, *android_login, - std::move(callbacks_chain)); - } - - std::move(callbacks_chain).Run(); -} - -void BuiltInBackendToAndroidBackendMigrator:: - MirrorAndroidBackendToBuiltInBackend( - PasswordFormPtrFlatSet built_in_backend_logins, - PasswordFormPtrFlatSet android_logins) { - // For a form |F|, there are three cases to handle: - // 1. If |F| exists only in the |built_in_backend_|, then |F| should be - // removed from the |built_in_backend_|. - // 2. |F| exists only in the |android_backend_|, then |F| should be added to - // the |built_in_backend_|. - // 3. |F| exists in both |built_in_backend_| and |android_backend_|, then - // version from |built_in_backend_| should be updated with version from the - // |android_backend_|. - - // Callbacks are chained like in a stack way by passing 'callback_chain' as a - // completion for the next operation. - base::OnceClosure callbacks_chain = - base::BindOnce(&BuiltInBackendToAndroidBackendMigrator::MigrationFinished, - weak_ptr_factory_.GetWeakPtr(), /*is_success=*/true); - - for (auto* const login : built_in_backend_logins) { - auto android_login_iter = android_logins.find(login); - - if (android_login_iter == android_logins.end()) { - // Password from the |built_in_backend_| doesn't exist in the - // |android_backend_|. - callbacks_chain = base::BindOnce( - &BuiltInBackendToAndroidBackendMigrator::RemoveLoginFromBackend, - weak_ptr_factory_.GetWeakPtr(), built_in_backend_, *login, - std::move(callbacks_chain)); - continue; - } - - // Password from the |built_in_backend_| exists in the |android_backend_|. - auto* const android_login = (*android_login_iter); - - if (login->password_value == android_login->password_value) { - // Passwords are identical, nothing else to do. - continue; - } - - // Passwords aren't identical, update the built-in version to match the - // Android version. - callbacks_chain = base::BindOnce( - &BuiltInBackendToAndroidBackendMigrator::UpdateLoginInBackend, - weak_ptr_factory_.GetWeakPtr(), built_in_backend_, *android_login, - std::move(callbacks_chain)); - } - + // TODO (b/321217242): Remove this. // At this point, we have processed all passwords from the |built_in_backend_| // In addition, we also have processed all passwords from the // |android_backend_| which exist in the |built_in_backend_|. What's remaining @@ -587,18 +512,31 @@ kRequiredMigrationVersion); // Reenroll previously evicted user into the experiment if the migration has // succeeded. - if (migration_in_progress_type_ == MigrationType::kReenrollmentAttempt) { - prefs_->ClearPref(password_manager::prefs:: - kUnenrolledFromGoogleMobileServicesDueToErrors); - prefs_->ClearPref( - password_manager::prefs:: - kUnenrolledFromGoogleMobileServicesAfterApiErrorCode); - prefs_->SetInteger( - prefs::kTimesReenrolledToGoogleMobileServices, - prefs_->GetInteger(prefs::kTimesReenrolledToGoogleMobileServices) + - 1); - prefs_->SetInteger(prefs::kTimesAttemptedToReenrollToGoogleMobileServices, - 0); + switch (migration_in_progress_type_) { + case MigrationType::kReenrollmentAttempt: + prefs_->ClearPref(password_manager::prefs:: + kUnenrolledFromGoogleMobileServicesDueToErrors); + prefs_->ClearPref( + password_manager::prefs:: + kUnenrolledFromGoogleMobileServicesAfterApiErrorCode); + prefs_->SetInteger( + prefs::kTimesReenrolledToGoogleMobileServices, + prefs_->GetInteger(prefs::kTimesReenrolledToGoogleMobileServices) + + 1); + prefs_->SetInteger( + prefs::kTimesAttemptedToReenrollToGoogleMobileServices, 0); + break; + case MigrationType::kForLocalUsers: + prefs_->SetInteger( + prefs::kPasswordsUseUPMLocalAndSeparateStores, + static_cast<int>(password_manager::prefs:: + UseUpmLocalAndSeparateStoresState::kOn)); + break; + case MigrationType::kNone: + case MigrationType::kInitialForSyncUsers: + case MigrationType::kNonSyncableToAndroidBackend: + case MigrationType::kNonSyncableToBuiltInBackend: + break; } }
diff --git a/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.h b/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.h index baee1b6..388fcc22 100644 --- a/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.h +++ b/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator.h
@@ -102,24 +102,18 @@ // to perform initial & rolling migration for local users. void RunMigrationForLocalUsers(); - // Migrates password between |built_in_backend_| and |android_backend_|. - // |result| consists of passwords from the |built_in_backend_| let's call them - // |A| and passwords from the |android_backend_| - |B|. If initial migration - // needed this function will update both backends with |A|U|B| otherwise it - // will replace passwords from the |built_in_backend_| with |B|. - void MigratePasswordsBetweenAndroidAndBuiltInBackends( + // Migrates password from the profile store |built_in_backend_| to the Gms + // core local store |android_backend_|. |result| consists of passwords from + // the |built_in_backend_| let's call them |A|. If the password from |A| is + // already present in |android_backend_|, then the latest version of the + // credential is adopted by |android_backend_|. + void MigrateLocalPasswordsBetweenAndroidAndBuiltInBackends( std::vector<BackendAndLoginsResults> result); // Updates both |built_in_backend_| and |android_backend_| such that both // contain the same set of passwords without deleting any password. In // addition, it marks the initial migration as completed. - void MergeAndroidBackendAndBuiltInBackend( - PasswordFormPtrFlatSet built_in_backend_logins, - PasswordFormPtrFlatSet android_logins); - - // Updates |built_in_backend_| such that it contains the same set of passwords - // as in |android_backend_|. - void MirrorAndroidBackendToBuiltInBackend( + void MergeBuiltInBackendIntoAndroidBackend( PasswordFormPtrFlatSet built_in_backend_logins, PasswordFormPtrFlatSet android_logins);
diff --git a/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator_unittest.cc b/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator_unittest.cc index a260f082..e5cab2e 100644 --- a/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator_unittest.cc +++ b/chrome/browser/password_manager/android/built_in_backend_to_android_backend_migrator_unittest.cc
@@ -24,6 +24,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using password_manager::prefs::kPasswordsUseUPMLocalAndSeparateStores; +using password_manager::prefs::UseUpmLocalAndSeparateStoresState; using ::testing::ElementsAre; using ::testing::ElementsAreArray; using ::testing::Eq; @@ -163,7 +165,7 @@ } TEST_F(BuiltInBackendToAndroidBackendMigratorTest, - AllPrefsAreUpdatedWhenMigrationIsNeeded_SyncOff) { + AllPrefsAreUpdatedAfterLocalPasswordsMigration) { Init(); prefs()->SetInteger( @@ -178,8 +180,8 @@ /*should_attempt_upm_reenrollment=*/false); RunUntilIdle(); - EXPECT_EQ(1, prefs()->GetInteger( - prefs::kCurrentMigrationVersionToGoogleMobileServices)); + EXPECT_EQ(static_cast<int>(UseUpmLocalAndSeparateStoresState::kOn), + prefs()->GetInteger(kPasswordsUseUPMLocalAndSeparateStores)); EXPECT_EQ( base::Time::Now().InSecondsFSinceUnixEpoch(), prefs()->GetDouble(password_manager::prefs::kTimeOfLastMigrationAttempt)); @@ -926,9 +928,12 @@ migrator()->StartMigrationIfNecessary( /*should_attempt_upm_reenrollment=*/false); - // Migration version is still 0 since migration didn't complete. - EXPECT_EQ(0, prefs()->GetInteger( - prefs::kCurrentMigrationVersionToGoogleMobileServices)); + // Local migration should still be pending since it didn' t complete + // successfully. + EXPECT_EQ(static_cast<int>( + UseUpmLocalAndSeparateStoresState::kOffAndMigrationPending), + prefs()->GetInteger(kPasswordsUseUPMLocalAndSeparateStores)); + RunUntilIdle(); }
diff --git a/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.cc b/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.cc index 7bd3437b..36371a53 100644 --- a/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.cc +++ b/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.cc
@@ -328,6 +328,16 @@ migrator_->OnSyncServiceInitialized(sync_service); } +void LegacyPasswordStoreBackendMigrationDecorator:: + RecordAddLoginAsyncCalledFromTheStore() { + active_backend_->RecordAddLoginAsyncCalledFromTheStore(); +} + +void LegacyPasswordStoreBackendMigrationDecorator:: + RecordUpdateLoginAsyncCalledFromTheStore() { + active_backend_->RecordUpdateLoginAsyncCalledFromTheStore(); +} + base::WeakPtr<PasswordStoreBackend> LegacyPasswordStoreBackendMigrationDecorator::AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr();
diff --git a/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.h b/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.h index 913e05a..2d54ead5 100644 --- a/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.h +++ b/chrome/browser/password_manager/android/legacy_password_store_backend_migration_decorator.h
@@ -132,6 +132,8 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegate() override; void OnSyncServiceInitialized(syncer::SyncService* sync_service) override; + void RecordAddLoginAsyncCalledFromTheStore() override; + void RecordUpdateLoginAsyncCalledFromTheStore() override; base::WeakPtr<PasswordStoreBackend> AsWeakPtr() override; // Starts migration process.
diff --git a/chrome/browser/password_manager/android/password_store_android_account_backend.cc b/chrome/browser/password_manager/android/password_store_android_account_backend.cc index 9e8b80c..f5b55f2 100644 --- a/chrome/browser/password_manager/android/password_store_android_account_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_account_backend.cc
@@ -411,6 +411,20 @@ } void PasswordStoreAndroidAccountBackend:: + RecordAddLoginAsyncCalledFromTheStore() { + base::UmaHistogramBoolean( + "PasswordManager.PasswordStore.AccountBackend.AddLoginCalledOnStore", + true); +} + +void PasswordStoreAndroidAccountBackend:: + RecordUpdateLoginAsyncCalledFromTheStore() { + base::UmaHistogramBoolean( + "PasswordManager.PasswordStore.AccountBackend.UpdateLoginCalledOnStore", + true); +} + +void PasswordStoreAndroidAccountBackend:: InjectAffiliationAndBrandingInformation( LoginsOrErrorReply callback, LoginsResultOrError forms_or_error) {
diff --git a/chrome/browser/password_manager/android/password_store_android_account_backend.h b/chrome/browser/password_manager/android/password_store_android_account_backend.h index 3735b52..c5e769d 100644 --- a/chrome/browser/password_manager/android/password_store_android_account_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_account_backend.h
@@ -82,6 +82,8 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegate() override; void OnSyncServiceInitialized(syncer::SyncService* sync_service) override; + void RecordAddLoginAsyncCalledFromTheStore() override; + void RecordUpdateLoginAsyncCalledFromTheStore() override; SmartBubbleStatsStore* GetSmartBubbleStatsStore() override; base::WeakPtr<PasswordStoreBackend> AsWeakPtr() override;
diff --git a/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc b/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc index 38266a90..0084370 100644 --- a/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc +++ b/chrome/browser/password_manager/android/password_store_android_account_backend_unittest.cc
@@ -2092,6 +2092,24 @@ RunUntilIdle(); } +TEST_F(PasswordStoreAndroidAccountBackendTest, RecordPasswordStoreMetrics) { + base::HistogramTester histogram_tester; + backend().InitBackend( + /*affiliated_match_helper=*/nullptr, + PasswordStoreAndroidAccountBackend::RemoteChangesReceived(), + base::NullCallback(), base::DoNothing()); + + backend().RecordAddLoginAsyncCalledFromTheStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.AccountBackend.AddLoginCalledOnStore", + true, 1); + + backend().RecordUpdateLoginAsyncCalledFromTheStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.AccountBackend.UpdateLoginCalledOnStore", + true, 1); +} + // Test suite to verify there is no unenrollment for most of the errors except // Passphrase. Each backend operation is checked by a separate test. class PasswordStoreAndroidAccountBackendWithoutUnenrollmentTest
diff --git a/chrome/browser/password_manager/android/password_store_android_local_backend.cc b/chrome/browser/password_manager/android/password_store_android_local_backend.cc index ec3541cf..7407951 100644 --- a/chrome/browser/password_manager/android/password_store_android_local_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_local_backend.cc
@@ -153,6 +153,18 @@ void PasswordStoreAndroidLocalBackend::OnSyncServiceInitialized( syncer::SyncService* sync_service) {} +void PasswordStoreAndroidLocalBackend::RecordAddLoginAsyncCalledFromTheStore() { + base::UmaHistogramBoolean( + "PasswordManager.PasswordStore.LocalBackend.AddLoginCalledOnStore", true); +} + +void PasswordStoreAndroidLocalBackend:: + RecordUpdateLoginAsyncCalledFromTheStore() { + base::UmaHistogramBoolean( + "PasswordManager.PasswordStore.LocalBackend.UpdateLoginCalledOnStore", + true); +} + SmartBubbleStatsStore* PasswordStoreAndroidLocalBackend::GetSmartBubbleStatsStore() { return nullptr;
diff --git a/chrome/browser/password_manager/android/password_store_android_local_backend.h b/chrome/browser/password_manager/android/password_store_android_local_backend.h index c964b5ff..f684521 100644 --- a/chrome/browser/password_manager/android/password_store_android_local_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_local_backend.h
@@ -75,6 +75,8 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegate() override; void OnSyncServiceInitialized(syncer::SyncService* sync_service) override; + void RecordAddLoginAsyncCalledFromTheStore() override; + void RecordUpdateLoginAsyncCalledFromTheStore() override; SmartBubbleStatsStore* GetSmartBubbleStatsStore() override; base::WeakPtr<PasswordStoreBackend> AsWeakPtr() override;
diff --git a/chrome/browser/password_manager/android/password_store_android_local_backend_unittest.cc b/chrome/browser/password_manager/android/password_store_android_local_backend_unittest.cc index 9052fdee..48af33d 100644 --- a/chrome/browser/password_manager/android/password_store_android_local_backend_unittest.cc +++ b/chrome/browser/password_manager/android/password_store_android_local_backend_unittest.cc
@@ -7,6 +7,7 @@ #include <jni.h> #include <cstdint> +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "chrome/browser/password_manager/android/fake_password_manager_lifecycle_helper.h" @@ -365,6 +366,24 @@ prefs::kUnenrolledFromGoogleMobileServicesDueToErrors)); } +TEST_F(PasswordStoreAndroidLocalBackendTest, RecordPasswordStoreMetrics) { + base::HistogramTester histogram_tester; + backend().InitBackend( + /*affiliated_match_helper=*/nullptr, + PasswordStoreAndroidLocalBackend::RemoteChangesReceived(), + base::NullCallback(), base::DoNothing()); + + backend().RecordAddLoginAsyncCalledFromTheStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.LocalBackend.AddLoginCalledOnStore", true, + 1); + + backend().RecordUpdateLoginAsyncCalledFromTheStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.LocalBackend.UpdateLoginCalledOnStore", + true, 1); +} + class PasswordStoreAndroidLocalBackendRetriesTest : public PasswordStoreAndroidLocalBackendTest, public testing::WithParamInterface<AndroidBackendAPIErrorCode> {};
diff --git a/chrome/browser/password_manager/android/password_store_proxy_backend.cc b/chrome/browser/password_manager/android/password_store_proxy_backend.cc index 56b3bfa3..506594e 100644 --- a/chrome/browser/password_manager/android/password_store_proxy_backend.cc +++ b/chrome/browser/password_manager/android/password_store_proxy_backend.cc
@@ -306,6 +306,14 @@ android_backend_->OnSyncServiceInitialized(sync_service); } +void PasswordStoreProxyBackend::RecordAddLoginAsyncCalledFromTheStore() { + main_backend()->RecordAddLoginAsyncCalledFromTheStore(); +} + +void PasswordStoreProxyBackend::RecordUpdateLoginAsyncCalledFromTheStore() { + main_backend()->RecordUpdateLoginAsyncCalledFromTheStore(); +} + base::WeakPtr<PasswordStoreBackend> PasswordStoreProxyBackend::AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
diff --git a/chrome/browser/password_manager/android/password_store_proxy_backend.h b/chrome/browser/password_manager/android/password_store_proxy_backend.h index 61ce9fc..4713b30b 100644 --- a/chrome/browser/password_manager/android/password_store_proxy_backend.h +++ b/chrome/browser/password_manager/android/password_store_proxy_backend.h
@@ -88,6 +88,8 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegate() override; void OnSyncServiceInitialized(syncer::SyncService* sync_service) override; + void RecordAddLoginAsyncCalledFromTheStore() override; + void RecordUpdateLoginAsyncCalledFromTheStore() override; base::WeakPtr<PasswordStoreBackend> AsWeakPtr() override; void OnSyncShutdown(syncer::SyncService* sync_service) override;
diff --git a/chrome/browser/resources/ash/settings/BUILD.gn b/chrome/browser/resources/ash/settings/BUILD.gn index 81ffac8..b5b73ff 100644 --- a/chrome/browser/resources/ash/settings/BUILD.gn +++ b/chrome/browser/resources/ash/settings/BUILD.gn
@@ -571,12 +571,14 @@ optimize_webui_excludes = [ "chrome://resources/cr_components/app_management/app_management.mojom-webui.js", "chrome://resources/ash/common/bluetooth/cros_bluetooth_config.js", + "chrome://resources/ash/common/bluetooth/hid_preserving_bluetooth_state_controller.js", "chrome://resources/ash/common/cellular_setup/mojo_interface_provider.js", "chrome://resources/ash/common/connectivity/mojo_connectivity_provider.js", "chrome://resources/ash/common/connectivity/passpoint.mojom-webui.js", "chrome://resources/ash/common/hotspot/cros_hotspot_config.js", "chrome://resources/ash/common/hotspot/cros_hotspot_config.mojom-webui.js", "chrome://resources/ash/common/network/mojo_interface_provider.js", + "chrome://resources/mojo/ash/public/mojom/hid_preserving_bluetooth_state_controller.mojom-webui.js", "chrome://resources/mojo/chromeos/ash/services/cellular_setup/public/mojom/cellular_setup.mojom-webui.js", "chrome://resources/mojo/chromeos/ash/services/cellular_setup/public/mojom/esim_manager.mojom-webui.js", "chrome://resources/mojo/chromeos/ash/services/auth_factor_config/public/mojom/auth_factor_config.mojom-webui.js",
diff --git a/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_devices_subpage.ts b/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_devices_subpage.ts index 64bf89d..bf70d99a 100644 --- a/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_devices_subpage.ts +++ b/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_devices_subpage.ts
@@ -13,10 +13,11 @@ import {BluetoothUiSurface, recordBluetoothUiSurfaceMetrics} from 'chrome://resources/ash/common/bluetooth/bluetooth_metrics_utils.js'; import {getBluetoothConfig} from 'chrome://resources/ash/common/bluetooth/cros_bluetooth_config.js'; -import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js'; +import {getHidPreservingController} from 'chrome://resources/ash/common/bluetooth/hid_preserving_bluetooth_state_controller.js'; import {getInstance as getAnnouncerInstance} from 'chrome://resources/ash/common/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {WebUiListenerMixin} from 'chrome://resources/ash/common/cr_elements/web_ui_listener_mixin.js'; +import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {BluetoothSystemProperties, BluetoothSystemState, DeviceConnectionState, PairedBluetoothDeviceProperties} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -92,6 +93,14 @@ type: Array, value: [], }, + + isBluetoothDisconnectWarningEnabled_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('bluetoothDisconnectWarningFlag'); + }, + readOnly: true, + }, }; } @@ -103,6 +112,7 @@ private lastSelectedDeviceId_: string|null; private savedDevicesSublabel_: string; private unconnectedDevices_: PairedBluetoothDeviceProperties[]; + private isBluetoothDisconnectWarningEnabled_: boolean; constructor() { super(); @@ -216,11 +226,18 @@ if (oldValue === undefined) { return; } + // If the toggle value changed but the toggle is disabled, the change came // from CrosBluetoothConfig, not the user. Don't attempt to update the // enabled state. if (!this.isToggleDisabled_()) { - getBluetoothConfig().setBluetoothEnabledState(this.isBluetoothToggleOn_); + if (this.isBluetoothDisconnectWarningEnabled_) { + getHidPreservingController().tryToSetBluetoothEnabledState( + this.isBluetoothToggleOn_); + } else { + getBluetoothConfig().setBluetoothEnabledState( + this.isBluetoothToggleOn_); + } } this.announceBluetoothStateChange_(); }
diff --git a/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_summary.ts b/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_summary.ts index 3523bbac..25c3c42a 100644 --- a/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_summary.ts +++ b/chrome/browser/resources/ash/settings/os_bluetooth_page/os_bluetooth_summary.ts
@@ -14,6 +14,7 @@ import {getDeviceNameUnsafe} from 'chrome://resources/ash/common/bluetooth/bluetooth_utils.js'; import {getBluetoothConfig} from 'chrome://resources/ash/common/bluetooth/cros_bluetooth_config.js'; +import {getHidPreservingController} from 'chrome://resources/ash/common/bluetooth/hid_preserving_bluetooth_state_controller.js'; import {getInstance as getAnnouncerInstance} from 'chrome://resources/ash/common/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; @@ -91,6 +92,14 @@ }, readOnly: true, }, + + isBluetoothDisconnectWarningEnabled_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('bluetoothDisconnectWarningFlag'); + }, + readOnly: true, + }, }; } @@ -101,6 +110,7 @@ private isBluetoothToggleOn_: boolean; private isSecondaryUser_: boolean; private primaryUserEmail_: string; + private isBluetoothDisconnectWarningEnabled_: boolean; constructor() { super(); @@ -150,7 +160,13 @@ if (this.isToggleDisabled_()) { return; } - getBluetoothConfig().setBluetoothEnabledState(this.isBluetoothToggleOn_); + + if (this.isBluetoothDisconnectWarningEnabled_) { + getHidPreservingController().tryToSetBluetoothEnabledState( + this.isBluetoothToggleOn_); + } else { + getBluetoothConfig().setBluetoothEnabledState(this.isBluetoothToggleOn_); + } } private isToggleDisabled_(): boolean {
diff --git a/chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.html b/chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.html index 20275a2..07f091f 100644 --- a/chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.html +++ b/chrome/browser/resources/chromeos/login/screens/osauth/fingerprint_setup.html
@@ -73,8 +73,7 @@ [[i18nDynamic(locale, 'setupFingerprintScanTryAgain')]] </div> <div slot="content" class="flex layout vertical center center-justified"> - <fingerprint-progress id="arc" dynamic="[[isDynamicColor]]" - autoplay> + <fingerprint-progress id="arc" dynamic="[[isDynamicColor]]"> </fingerprint-progress> </div> <div slot="bottom-buttons">
diff --git a/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc b/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc index de6e1d48..03a3e73 100644 --- a/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc +++ b/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc
@@ -3,13 +3,10 @@ // found in the LICENSE file. #include <memory> -#include <string_view> #include "base/callback_list.h" #include "base/check_deref.h" #include "base/files/file_path.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_future.h" @@ -26,41 +23,30 @@ #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/sessions/session_restore_test_helper.h" #include "chrome/browser/sessions/session_service_factory.h" -#include "chrome/browser/sessions/session_service_test_helper.h" -#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/profiles/profile_picker.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" -#include "chrome/browser/web_applications/test/web_app_test_utils.h" #include "chrome/browser/web_applications/web_app_install_info.h" -#include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/chrome_constants.h" -#include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/ui_test_utils.h" #include "components/keep_alive_registry/keep_alive_types.h" #include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/search_engines/choice_made_location.h" #include "components/search_engines/default_search_manager.h" #include "components/search_engines/prepopulated_engines.h" #include "components/search_engines/search_engine_choice_utils.h" -#include "components/search_engines/search_engine_utils.h" #include "components/search_engines/search_engines_pref_names.h" #include "components/search_engines/search_engines_switches.h" #include "components/search_engines/search_engines_test_util.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_prepopulate_data.h" #include "components/search_engines/template_url_service.h" -#include "components/signin/public/base/signin_switches.h" #include "components/version_info/version_info.h" #include "components/webapps/common/web_app_id.h" #include "content/public/browser/browser_context.h" @@ -71,18 +57,12 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/window_open_disposition.h" -#include "url/url_constants.h" - -// TODO(b/280753754): Convert these tests to interactive ui tests. using testing::_; using EntryPoint = SearchEngineChoiceDialogService::EntryPoint; namespace { -constexpr char kCustomSearchEngineDomain[] = "bar.com"; -constexpr char16_t kCustomSearchEngineKeyword[] = u"bar.com"; - // Class that mocks `SearchEngineChoiceDialogService`. class MockSearchEngineChoiceDialogService : public SearchEngineChoiceDialogService { @@ -136,23 +116,6 @@ unsigned int number_of_browsers_with_dialogs_open_ = 0; }; -void SetUserSelectedDefaultSearchProvider( - TemplateURLService* template_url_service) { - TemplateURLData data; - data.SetShortName(kCustomSearchEngineKeyword); - data.SetKeyword(kCustomSearchEngineKeyword); - data.SetURL(base::StringPrintf("https://%s/url?bar={searchTerms}", - kCustomSearchEngineDomain)); - data.new_tab_url = - base::StringPrintf("https://%s/newtab", kCustomSearchEngineDomain); - data.alternate_urls.push_back(base::StringPrintf( - "https://%s/alt#quux={searchTerms}", kCustomSearchEngineDomain)); - - TemplateURL* template_url = - template_url_service->Add(std::make_unique<TemplateURL>(data)); - template_url_service->SetUserSelectedDefaultSearchProvider(template_url); -} - webapps::AppId InstallPWA(Profile* profile, const GURL& start_url) { auto web_app_info = std::make_unique<web_app::WebAppInstallInfo>(); web_app_info->start_url = start_url; @@ -626,33 +589,6 @@ } #endif -// This test is disabled because we currently don't want to show the dialog for -// users who have custom search engines. -// TODO(b/302687046): Modify the test based on the decision towards custom -// search engines. -IN_PROC_BROWSER_TEST_F(SearchEngineChoiceDialogBrowserTest, - DISABLED_ChooseCustomDefaultSearchProvider) { - TemplateURLService* template_url_service = - TemplateURLServiceFactory::GetForProfile(browser()->profile()); - SetUserSelectedDefaultSearchProvider(template_url_service); - auto* search_engine_choice_dialog_service = - static_cast<MockSearchEngineChoiceDialogService*>( - SearchEngineChoiceDialogServiceFactory::GetForProfile( - browser()->profile())); - - // Navigate to a URL to display the dialog. - ASSERT_TRUE(ui_test_utils::NavigateToURLWithDisposition( - browser(), GURL(kCustomSearchEngineDomain), - WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - - search_engine_choice_dialog_service->NotifyChoiceMade( - /*prepopulate_id=*/0, EntryPoint::kDialog); - const TemplateURL* default_search_provider = - template_url_service->GetDefaultSearchProvider(); - EXPECT_EQ(default_search_provider->short_name(), kCustomSearchEngineKeyword); -} - IN_PROC_BROWSER_TEST_F(SearchEngineChoiceDialogBrowserTest, DialogDoesNotShowWithExtensionEnabledThatOverridesDSE) { Profile* profile = browser()->profile();
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index 74c81a8..d2ae46c 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -2211,7 +2211,8 @@ // Test that when closing a profile with multiple browsers, all browsers are // restored when the profile is reopened. -IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoreAllBrowsers) { +// TODO(http://b/327325665) Enable this test after resolving issue. +IN_PROC_BROWSER_TEST_F(SessionRestoreTest, DISABLED_RestoreAllBrowsers) { // Create two profiles with two browsers each. Browser* first_profile_browser_one = browser(); ui_test_utils::BrowserChangeObserver new_browser_observer(
diff --git a/chrome/browser/tab_group/BUILD.gn b/chrome/browser/tab_group/BUILD.gn index 22788aeb..a4d40cf0 100644 --- a/chrome/browser/tab_group/BUILD.gn +++ b/chrome/browser/tab_group/BUILD.gn
@@ -9,7 +9,6 @@ android_library("java") { sources = [ "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroup.java", - "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtils.java", "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java", "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterObserver.java", "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupTitleUtils.java", @@ -21,15 +20,12 @@ "//chrome/browser/flags:java", "//chrome/browser/tab:java", "//chrome/browser/tabmodel:java", - "//components/tab_groups:tab_groups_java", "//third_party/androidx:androidx_annotation_annotation_java", - "//third_party/androidx:androidx_collection_collection_java", ] } robolectric_library("junit") { sources = [ - "junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtilsUnitTest.java", "junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java", "junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupTitleUtilsUnitTest.java", ] @@ -45,7 +41,6 @@ "//chrome/test/android:chrome_java_unit_test_support", "//third_party/android_deps:espresso_java", "//third_party/androidx:androidx_annotation_annotation_java", - "//third_party/androidx:androidx_collection_collection_java", "//third_party/hamcrest:hamcrest_core_java", "//third_party/jni_zero:jni_zero_java", "//third_party/junit",
diff --git a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtils.java b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtils.java deleted file mode 100644 index 0457d57..0000000 --- a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtils.java +++ /dev/null
@@ -1,169 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.tasks.tab_groups; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.collection.ArrayMap; - -import org.chromium.base.ContextUtils; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.components.tab_groups.TabGroupColorId; - -import java.util.Map; -import java.util.Set; - -/** Helper class to handle tab group color related utilities. */ -public class TabGroupColorUtils { - private static final String TAB_GROUP_COLORS_FILE_NAME = "tab_group_colors"; - private static final String MIGRATION_CHECK = "migration_check"; - private static final int INVALID_COLOR_ID = -1; - private static final int MIGRATION_NOT_DONE = 0; - private static final int MIGRATION_DONE = 1; - - /** - * This method stores tab group colors with reference to {@code tabRootId}. - * - * @param tabRootId The tab root ID which is used as a reference to store group colors. - * @param color The tab group color {@link TabGroupColorId} to store. - */ - public static void storeTabGroupColor(int tabRootId, int color) { - assert tabRootId != Tab.INVALID_TAB_ID; - getSharedPreferences().edit().putInt(String.valueOf(tabRootId), color).apply(); - } - - /** - * This method deletes a specific stored tab group color with reference to {@code tabRootId}. - * - * @param tabRootId The tab root ID whose related tab group color will be deleted. - */ - public static void deleteTabGroupColor(int tabRootId) { - assert tabRootId != Tab.INVALID_TAB_ID; - getSharedPreferences().edit().remove(String.valueOf(tabRootId)).apply(); - } - - /** - * This method fetches tab group colors for the related tab group root ID. - * - * @param tabRootId The tab root ID whose related tab group color will be fetched. - * @return The stored color of the target tab group, default value is -1 (INVALID_COLOR_ID). - */ - public static int getTabGroupColor(int tabRootId) { - assert tabRootId != Tab.INVALID_TAB_ID; - return getSharedPreferences().getInt(String.valueOf(tabRootId), INVALID_COLOR_ID); - } - - /** - * This method assigns a color to all tab groups which do not have an assigned tab color at - * startup. If a migration for all existing tabs has already been performed, skip this logic. - * - * @param tabGroupModelFilter The {@TabGroupModelFilter} that governs the current tab groups. - */ - public static void assignTabGroupColorsIfApplicable(TabGroupModelFilter tabGroupModelFilter) { - // TODO(b/41490324): Consider removing the migration logic when tab group colors are - // launched. There may be an argument to keep this around in case the color info is somehow - // lost between startups, in which case this will at least set some default colors up. In - // theory, once the migrations have been applied to everyone there won't be a need for this. - // - // If the migration is already done, skip the below logic. - if (getSharedPreferences().getInt(MIGRATION_CHECK, MIGRATION_NOT_DONE) == MIGRATION_DONE) { - return; - } - - Map<Integer, Integer> currentColorCountMap = getCurrentColorCountMap(tabGroupModelFilter); - Set<Integer> rootIds = tabGroupModelFilter.getAllTabGroupRootIds(); - - // Assign a color to all tab groups that don't have a color. - for (Integer rootId : rootIds) { - int colorId = getTabGroupColor(rootId); - - // Retrieve the next suggested colorId if the current tab group does not have a color. - if (colorId == INVALID_COLOR_ID) { - int suggestedColorId = getNextSuggestedColorId(currentColorCountMap); - storeTabGroupColor(rootId, suggestedColorId); - currentColorCountMap.put( - suggestedColorId, currentColorCountMap.get(suggestedColorId) + 1); - } - } - - // Mark that the initial migration of tab colors is complete. - getSharedPreferences().edit().putInt(MIGRATION_CHECK, MIGRATION_DONE).apply(); - } - - /** - * This method returns the next suggested colorId to be assigned to a tab group if that tab - * group has no color assigned to it. This algorithm uses a key-value map to store all usage - * counts of the current list of colors in other tab groups. It will select the least used color - * that appears first in the color list. The suggested color value should be a color id of type - * {@link TabGroupColorId}. - * - * @param tabGroupModelFilter The {@link TabGroupModelFilter} that governs all tab groups. - */ - public static int getNextSuggestedColorId(TabGroupModelFilter tabGroupModelFilter) { - // Generate the currentColorCountMap. - Map<Integer, Integer> currentColorCountMap = getCurrentColorCountMap(tabGroupModelFilter); - return getNextSuggestedColorId(currentColorCountMap); - } - - /** - * This method removes the shared preference file. TODO(b/41490324): Consider removing this when - * the feature is launched. - */ - public static void clearTabGroupColorInfo() { - ContextUtils.getApplicationContext().deleteSharedPreferences(TAB_GROUP_COLORS_FILE_NAME); - } - - private static SharedPreferences getSharedPreferences() { - return ContextUtils.getApplicationContext() - .getSharedPreferences(TAB_GROUP_COLORS_FILE_NAME, Context.MODE_PRIVATE); - } - - /** Get a map that indicates the current usage count of each tab group color. */ - private static Map<Integer, Integer> getCurrentColorCountMap( - TabGroupModelFilter tabGroupModelFilter) { - int colorListSize = TabGroupColorId.NUM_ENTRIES; - Map<Integer, Integer> colorCountMap = new ArrayMap<>(colorListSize); - for (int i = 0; i < colorListSize; i++) { - colorCountMap.put(i, 0); - } - - Set<Integer> rootIds = tabGroupModelFilter.getAllTabGroupRootIds(); - - // Filter all tab groups for ones that already have a color assigned. - for (Integer rootId : rootIds) { - int colorId = getTabGroupColor(rootId); - - // If the tab group has a color stored on shared prefs, increment the colorId map count. - if (colorId != INVALID_COLOR_ID) { - colorCountMap.put(colorId, colorCountMap.get(colorId) + 1); - } - } - - return colorCountMap; - } - - /** Impl of getNextSuggestedColorId which assumes a currentColorCountMap has been created. */ - private static int getNextSuggestedColorId(Map<Integer, Integer> currentColorCountMap) { - int colorId = Integer.MAX_VALUE; - int colorCount = Integer.MAX_VALUE; - - for (Map.Entry<Integer, Integer> entry : currentColorCountMap.entrySet()) { - if (entry.getValue() < colorCount) { - colorCount = entry.getValue(); - colorId = entry.getKey(); - } else if (entry.getValue() == colorCount) { - if (entry.getKey() < colorId) { - colorId = entry.getKey(); - } - } - } - - // Assert that the current color count map exists and sets a valid colorId on loop - // iteration, otherwise default to an invalid colorId. - assert colorId != Integer.MAX_VALUE; - return colorId != Integer.MAX_VALUE ? colorId : INVALID_COLOR_ID; - } -}
diff --git a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java index f8ac830..6688c35 100644 --- a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java +++ b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java
@@ -9,7 +9,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import androidx.collection.ArraySet; import org.chromium.base.MathUtils; import org.chromium.base.ObserverList; @@ -43,8 +42,6 @@ * https://crbug.com/1523745. */ public class TabGroupModelFilter extends TabModelFilter { - private static final int INVALID_COLOR_ID = -1; - private ObserverList<TabGroupModelFilterObserver> mGroupFilterObserver = new ObserverList<>(); private Map<Integer, Integer> mRootIdToGroupIndexMap = new HashMap<>(); private Map<Integer, TabGroup> mRootIdToGroupMap = new HashMap<>(); @@ -139,8 +136,7 @@ Collections.singletonList(index), Collections.singletonList(tab.getRootId()), Collections.singletonList(null), - null, - INVALID_COLOR_ID); + null); } } } @@ -189,7 +185,6 @@ List<Integer> originalRootIds = new ArrayList<>(); List<Token> originalTabGroupIds = new ArrayList<>(); String destinationGroupTitle = TabGroupTitleUtils.getTabGroupTitle(destinationRootId); - int destinationGroupColorId = TabGroupColorUtils.getTabGroupColor(destinationRootId); boolean didCreateNewGroup = !isTabInTabGroup(sourceTab) && !isTabInTabGroup(destinationTab); @@ -244,8 +239,7 @@ originalIndexes, originalRootIds, originalTabGroupIds, - destinationGroupTitle, - destinationGroupColorId); + destinationGroupTitle); } } } @@ -298,7 +292,6 @@ } int destinationIndexInTabModel = getTabModelDestinationIndex(destinationTab); String destinationGroupTitle = TabGroupTitleUtils.getTabGroupTitle(destinationRootId); - int destinationGroupColorId = TabGroupColorUtils.getTabGroupColor(destinationRootId); for (int i = 0; i < tabs.size(); i++) { Tab tab = tabs.get(i); @@ -362,8 +355,7 @@ originalIndexes, originalRootIds, originalTabGroupIds, - destinationGroupTitle, - destinationGroupColorId); + destinationGroupTitle); } } } @@ -1029,20 +1021,6 @@ super.didMoveTab(tab, newIndex, curIndex); } - /** Get all tab group root ids that are associated with tab groups greater than size 1. */ - public Set<Integer> getAllTabGroupRootIds() { - Set<Integer> uniqueTabGroupRootIds = new ArraySet<>(); - TabList tabList = getTabModel(); - - for (int i = 0; i < tabList.getCount(); i++) { - Tab tab = tabList.getTabAt(i); - if (isTabInTabGroup(tab)) { - uniqueTabGroupRootIds.add(tab.getRootId()); - } - } - return uniqueTabGroupRootIds; - } - private boolean isMoveTabOutOfGroup(Tab movedTab) { return !mRootIdToGroupMap.containsKey(movedTab.getRootId()); }
diff --git a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterObserver.java b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterObserver.java index 6fec905..b6ac970 100644 --- a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterObserver.java +++ b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterObserver.java
@@ -73,15 +73,13 @@ * @param tabOriginalRootId The original root id for each modified tab. * @param tabOriginalTabGroupId The original tab group id for each modified tab. * @param destinationGroupTitle The original destination group title. - * @param destinationGroupColorId The original destination group color id. */ default void didCreateGroup( List<Tab> tabs, List<Integer> tabOriginalIndex, List<Integer> tabOriginalRootId, List<Token> tabOriginalTabGroupId, - String destinationGroupTitle, - int destinationGroupColorId) {} + String destinationGroupTitle) {} /** * This method is called after a new tab group is created, either through drag and drop, the tab
diff --git a/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtilsUnitTest.java b/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtilsUnitTest.java deleted file mode 100644 index cfda4da..0000000 --- a/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupColorUtilsUnitTest.java +++ /dev/null
@@ -1,273 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.tasks.tab_groups; - -import static androidx.test.espresso.matcher.ViewMatchers.assertThat; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.content.SharedPreferences; - -import androidx.collection.ArraySet; - -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.annotation.Config; - -import org.chromium.base.ContextUtils; -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Features; - -import java.util.Set; - -/** Tests for {@link TabGroupColorUtils}. */ -@RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE) -public class TabGroupColorUtilsUnitTest { - @Rule public TestRule mProcessor = new Features.JUnitProcessor(); - - private static final String TAB_GROUP_COLORS_FILE_NAME = "tab_group_colors"; - private static final String MIGRATION_CHECK = "migration_check"; - private static final int INVALID_COLOR_ID = -1; - private static final int MIGRATION_DONE = 1; - - private static final int ROOT_ID_1 = 123; - private static final int ROOT_ID_2 = 456; - private static final int ROOT_ID_3 = 789; - private static final int ROOT_ID_4 = 147; - private static final int ROOT_ID_5 = 258; - private static final int ROOT_ID_6 = 369; - private static final int ROOT_ID_7 = 159; - private static final int ROOT_ID_8 = 160; - private static final int ROOT_ID_9 = 161; - private static final int ROOT_ID_10 = 162; - private static final int COLOR_1 = 0; - private static final int COLOR_2 = 1; - private static final int COLOR_3 = 2; - private static final int COLOR_4 = 3; - private static final int COLOR_5 = 4; - private static final int COLOR_6 = 5; - private static final int COLOR_7 = 6; - private static final int COLOR_8 = 7; - private static final int COLOR_9 = 8; - - @Mock Context mContext; - @Mock TabGroupModelFilter mFilter; - @Mock SharedPreferences mSharedPreferences; - @Mock SharedPreferences.Editor mEditor; - @Mock SharedPreferences.Editor mPutIntEditor; - @Mock SharedPreferences.Editor mRemoveEditor; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - doReturn(mSharedPreferences) - .when(mContext) - .getSharedPreferences(TAB_GROUP_COLORS_FILE_NAME, Context.MODE_PRIVATE); - doReturn(mEditor).when(mSharedPreferences).edit(); - doReturn(mRemoveEditor).when(mEditor).remove(any(String.class)); - doReturn(mPutIntEditor).when(mEditor).putInt(any(String.class), any(Integer.class)); - ContextUtils.initApplicationContextForTests(mContext); - } - - @Test - public void testDeleteTabGroupColor() { - TabGroupColorUtils.deleteTabGroupColor(ROOT_ID_1); - - verify(mEditor).remove(eq(String.valueOf(ROOT_ID_1))); - verify(mRemoveEditor).apply(); - } - - @Test - public void testGetTabGroupColor() { - // Mock that we have a stored tab group color with reference to ROOT_ID. - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_1), INVALID_COLOR_ID)) - .thenReturn(COLOR_1); - - assertThat(TabGroupColorUtils.getTabGroupColor(ROOT_ID_1), equalTo(COLOR_1)); - } - - @Test - public void testStoreTabGroupColor() { - TabGroupColorUtils.storeTabGroupColor(ROOT_ID_1, COLOR_1); - - verify(mEditor).putInt(eq(String.valueOf(ROOT_ID_1)), eq(COLOR_1)); - verify(mPutIntEditor).apply(); - } - - @Test - public void testAssignDefaultTabGroupColors() { - Set<Integer> rootIdsSet = new ArraySet<>(); - rootIdsSet.add(ROOT_ID_1); - rootIdsSet.add(ROOT_ID_2); - rootIdsSet.add(ROOT_ID_3); - - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - // Mock that there is no stored tab group color for these root ids. - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_1), INVALID_COLOR_ID)) - .thenReturn(INVALID_COLOR_ID); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_2), INVALID_COLOR_ID)) - .thenReturn(INVALID_COLOR_ID); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_3), INVALID_COLOR_ID)) - .thenReturn(INVALID_COLOR_ID); - - TabGroupColorUtils.assignTabGroupColorsIfApplicable(mFilter); - - // Test the scenario where no tab groups have colors so the first colors in order are - // assigned. - verify(mEditor).putInt(eq(String.valueOf(ROOT_ID_1)), eq(COLOR_1)); - verify(mEditor).putInt(eq(String.valueOf(ROOT_ID_2)), eq(COLOR_2)); - verify(mEditor).putInt(eq(String.valueOf(ROOT_ID_3)), eq(COLOR_3)); - verify(mEditor).putInt(eq(MIGRATION_CHECK), eq(MIGRATION_DONE)); - verify(mPutIntEditor, times(4)).apply(); - } - - @Test - public void testNextSuggestedColorFirstAndThird() { - Set<Integer> rootIdsSet = new ArraySet<>(); - rootIdsSet.add(ROOT_ID_1); - rootIdsSet.add(ROOT_ID_2); - - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - // Mock that the first and third colors already exist. - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_1), INVALID_COLOR_ID)) - .thenReturn(COLOR_1); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_2), INVALID_COLOR_ID)) - .thenReturn(COLOR_3); - - assertEquals(COLOR_2, TabGroupColorUtils.getNextSuggestedColorId(mFilter)); - } - - @Test - public void testNextSuggestedColorDoubleFirstAndSecond() { - Set<Integer> rootIdsSet = new ArraySet<>(); - rootIdsSet.add(ROOT_ID_1); - rootIdsSet.add(ROOT_ID_2); - rootIdsSet.add(ROOT_ID_3); - - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - // Mock that the first and second colors already exist. - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_1), INVALID_COLOR_ID)) - .thenReturn(COLOR_1); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_2), INVALID_COLOR_ID)) - .thenReturn(COLOR_1); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_3), INVALID_COLOR_ID)) - .thenReturn(COLOR_2); - - assertEquals(COLOR_3, TabGroupColorUtils.getNextSuggestedColorId(mFilter)); - } - - @Test - public void testNextSuggestedColorSecondColor() { - Set<Integer> rootIdsSet = new ArraySet<>(); - rootIdsSet.add(ROOT_ID_1); - - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - // Mock that only the second color already exists. - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_1), INVALID_COLOR_ID)) - .thenReturn(COLOR_2); - - assertEquals(COLOR_1, TabGroupColorUtils.getNextSuggestedColorId(mFilter)); - } - - @Test - public void testNextSuggestedColorAllColorsUsed() { - Set<Integer> rootIdsSet = new ArraySet<>(); - rootIdsSet.add(ROOT_ID_1); - rootIdsSet.add(ROOT_ID_2); - rootIdsSet.add(ROOT_ID_3); - rootIdsSet.add(ROOT_ID_4); - rootIdsSet.add(ROOT_ID_5); - rootIdsSet.add(ROOT_ID_6); - rootIdsSet.add(ROOT_ID_7); - rootIdsSet.add(ROOT_ID_8); - rootIdsSet.add(ROOT_ID_9); - - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - // Mock that all colors are used. - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_1), INVALID_COLOR_ID)) - .thenReturn(COLOR_1); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_2), INVALID_COLOR_ID)) - .thenReturn(COLOR_2); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_3), INVALID_COLOR_ID)) - .thenReturn(COLOR_3); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_4), INVALID_COLOR_ID)) - .thenReturn(COLOR_4); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_5), INVALID_COLOR_ID)) - .thenReturn(COLOR_5); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_6), INVALID_COLOR_ID)) - .thenReturn(COLOR_6); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_7), INVALID_COLOR_ID)) - .thenReturn(COLOR_7); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_8), INVALID_COLOR_ID)) - .thenReturn(COLOR_8); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_9), INVALID_COLOR_ID)) - .thenReturn(COLOR_9); - - assertEquals(COLOR_1, TabGroupColorUtils.getNextSuggestedColorId(mFilter)); - } - - @Test - public void testNextSuggestedColorContinuousSuggestion() { - Set<Integer> rootIdsSet = new ArraySet<>(); - rootIdsSet.add(ROOT_ID_1); - rootIdsSet.add(ROOT_ID_2); - rootIdsSet.add(ROOT_ID_3); - rootIdsSet.add(ROOT_ID_4); - rootIdsSet.add(ROOT_ID_5); - rootIdsSet.add(ROOT_ID_6); - rootIdsSet.add(ROOT_ID_7); - rootIdsSet.add(ROOT_ID_8); - - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - // Mock that all colors are used except for COLOR_8. - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_1), INVALID_COLOR_ID)) - .thenReturn(COLOR_1); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_2), INVALID_COLOR_ID)) - .thenReturn(COLOR_2); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_3), INVALID_COLOR_ID)) - .thenReturn(COLOR_3); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_4), INVALID_COLOR_ID)) - .thenReturn(COLOR_4); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_5), INVALID_COLOR_ID)) - .thenReturn(COLOR_5); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_6), INVALID_COLOR_ID)) - .thenReturn(COLOR_6); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_7), INVALID_COLOR_ID)) - .thenReturn(COLOR_7); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_8), INVALID_COLOR_ID)) - .thenReturn(COLOR_9); - - assertEquals(COLOR_8, TabGroupColorUtils.getNextSuggestedColorId(mFilter)); - - // Mock that subsequent addition of the missing color directs the suggestion to COLOR_1. - rootIdsSet.add(ROOT_ID_9); - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_9), INVALID_COLOR_ID)) - .thenReturn(COLOR_8); - assertEquals(COLOR_1, TabGroupColorUtils.getNextSuggestedColorId(mFilter)); - - // Mock that subsequent addition of the first color directs the suggestion to COLOR_2. - rootIdsSet.add(ROOT_ID_10); - when(mFilter.getAllTabGroupRootIds()).thenReturn(rootIdsSet); - when(mSharedPreferences.getInt(String.valueOf(ROOT_ID_10), INVALID_COLOR_ID)) - .thenReturn(COLOR_1); - assertEquals(COLOR_2, TabGroupColorUtils.getNextSuggestedColorId(mFilter)); - } -}
diff --git a/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java b/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java index fd96105..af846e8f 100644 --- a/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java +++ b/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java
@@ -30,7 +30,6 @@ import android.content.SharedPreferences; import androidx.annotation.Nullable; -import androidx.collection.ArraySet; import org.junit.Before; import org.junit.Rule; @@ -64,7 +63,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Set; /** Tests for {@link TabGroupModelFilter}. */ @SuppressWarnings("ResultOfMethodCallIgnored") @@ -110,10 +108,6 @@ private static final String TAB_GROUP_TITLES_FILE_NAME = "tab_group_titles"; private static final String TAB_TITLE = "Tab"; - private static final String TAB_GROUP_COLORS_FILE_NAME = "tab_group_colors"; - private static final int INVALID_COLOR_ID = -1; - private static final int COLOR_ID = 0; - @Rule public TestRule mProcessor = new Features.JUnitProcessor(); @Rule public JniMocker mJniMocker = new JniMocker(); @@ -126,9 +120,7 @@ @Mock Context mContext; - @Mock SharedPreferences mSharedPreferencesTitle; - - @Mock SharedPreferences mSharedPreferencesColor; + @Mock SharedPreferences mSharedPreferences; @Captor ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor; @@ -328,15 +320,11 @@ assertTrue(mTabGroupModelFilter.isTabModelRestored()); } - doReturn(mSharedPreferencesTitle) + doReturn(mSharedPreferences) .when(mContext) .getSharedPreferences(TAB_GROUP_TITLES_FILE_NAME, Context.MODE_PRIVATE); - doReturn(mSharedPreferencesColor) - .when(mContext) - .getSharedPreferences(TAB_GROUP_COLORS_FILE_NAME, Context.MODE_PRIVATE); ContextUtils.initApplicationContextForTests(mContext); - when(mSharedPreferencesTitle.getString(anyString(), any())).thenReturn(TAB_TITLE); - when(mSharedPreferencesColor.getInt(anyString(), anyInt())).thenReturn(COLOR_ID); + when(mSharedPreferences.getString(anyString(), any())).thenReturn(TAB_TITLE); } @Before @@ -797,8 +785,7 @@ Collections.singletonList(0), Collections.singletonList(mTab1.getRootId()), Collections.singletonList(null), - null, - INVALID_COLOR_ID); + null); assertTrue(mTabGroupModelFilter.isTabInTabGroup(mTab1)); mTabGroupModelFilter.moveTabOutOfGroup(TAB1_ID); @@ -1345,7 +1332,7 @@ .didCreateNewGroup(mTab4.getRootId(), mTabGroupModelFilter); verify(mTabGroupModelFilterObserver).didMergeTabToGroup(mTab4, mTab4.getId()); verify(mTabGroupModelFilterObserver, never()) - .didCreateGroup(any(), any(), any(), any(), any(), anyInt()); + .didCreateGroup(any(), any(), any(), any(), any()); assertThat(mTab4.getTabGroupId(), equalTo(tabGroupId)); @@ -1605,8 +1592,7 @@ originalIndexes, originalRootIds, originalTabGroupIds, - TAB_TITLE, - COLOR_ID); + TAB_TITLE); assertArrayEquals( mTabGroupModelFilter.getRelatedTabList(mTab2.getId()).toArray(), expectedGroup.toArray()); @@ -1649,8 +1635,7 @@ originalIndexes, originalRootIds, originalTabGroupIds, - TAB_TITLE, - COLOR_ID); + TAB_TITLE); assertArrayEquals( mTabGroupModelFilter.getRelatedTabList(mTab2.getId()).toArray(), expectedGroup.toArray()); @@ -1686,8 +1671,7 @@ originalIndexes, originalRootIds, originalTabGroupIds, - TAB_TITLE, - COLOR_ID); + TAB_TITLE); assertArrayEquals( mTabGroupModelFilter.getRelatedTabList(mTab1.getId()).toArray(), expectedGroup.toArray()); @@ -1705,7 +1689,7 @@ verify(mTabGroupModelFilterObserver) .didCreateNewGroup(mTab4.getRootId(), mTabGroupModelFilter); verify(mTabGroupModelFilterObserver, never()) - .didCreateGroup(any(), any(), any(), any(), any(), anyInt()); + .didCreateGroup(any(), any(), any(), any(), any()); assertEquals(mTab1.getTabGroupId(), tabGroupId); assertEquals(mTab4.getTabGroupId(), tabGroupId); @@ -1781,15 +1765,4 @@ assertTrue(mTabGroupModelFilter.tabGroupExistsForRootId(mTab3.getRootId())); assertTrue(mTabGroupModelFilter.tabGroupExistsForRootId(mTab5.getRootId())); } - - @Test - public void testGetAllTabGroupRootIds() { - // With the given setup, mTab2 and mTab3 are in a group and mTab5 and mTab6 are in another - // group. - Set<Integer> rootIds = new ArraySet<>(); - rootIds.add(mTab2.getRootId()); - rootIds.add(mTab5.getRootId()); - - assertEquals(rootIds, mTabGroupModelFilter.getAllTabGroupRootIds()); - } }
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc index 92816d7..953a1743 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
@@ -120,8 +120,7 @@ // Complete = contains number, expiration date and name on card. // Valid = unexpired with valid number format. std::vector<CreditCard> cards_to_suggest = - AutofillSuggestionGenerator(manager_->client(), - *manager_->client().GetPersonalDataManager()) + AutofillSuggestionGenerator(manager_->client()) .GetTouchToFillCardsToSuggest(); return cards_to_suggest.empty() ? DryRunResult(TriggerOutcome::kNoValidCards, {})
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 38bfecb..ee653b0 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3667,6 +3667,7 @@ "//ash/public/cpp/app_list/vector_icons", "//ash/public/cpp/resources:ash_public_unscaled_resources", "//ash/public/mojom", + "//ash/public/mojom:hid_preserving_bluetooth_state_controller", "//ash/quick_pair/common", "//ash/quick_pair/keyed_service", "//ash/quick_pair/proto:fastpair_proto",
diff --git a/chrome/browser/ui/ash/birch/birch_file_suggest_provider.cc b/chrome/browser/ui/ash/birch/birch_file_suggest_provider.cc index bdd8137..62a0735 100644 --- a/chrome/browser/ui/ash/birch/birch_file_suggest_provider.cc +++ b/chrome/browser/ui/ash/birch/birch_file_suggest_provider.cc
@@ -44,7 +44,7 @@ void BirchFileSuggestProvider::OnSuggestedFileDataUpdated( const std::optional<std::vector<FileSuggestData>>& suggest_results) { - if (!Shell::Get()->HasInstance()) { + if (!Shell::HasInstance()) { return; } if (!suggest_results) {
diff --git a/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc b/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc index 9a32312..308ca27 100644 --- a/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc +++ b/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc
@@ -76,6 +76,9 @@ if (IsLacrosAppId(params.app_id)) { out_properties_container.SetProperty( aura::client::kAppType, static_cast<int>(ash::AppType::LACROS)); + // Make sure Lacros is treated as opaque for occlusion tracking purposes. + out_properties_container.SetProperty( + chromeos::kWindowManagerManagesOpacityKey, true); // Lacros is trusted not to abuse window activation, so grant it a // non-expiring permission to activate. out_properties_container.SetProperty(
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc index 6e3ac6dd..744c5f55 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -34,6 +34,7 @@ #include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/browser/ui/suggestion.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/compose/core/browser/config.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/feature_engagement/public/tracker.h" #include "components/strings/grit/components_strings.h" @@ -162,7 +163,9 @@ // Currently, this is only relevant for Compose. .hide_on_text_field_change = IsRootPopup() && suggestions.size() == 1 && - suggestions[0].popup_item_id == PopupItemId::kCompose}; + GetFillingProductFromPopupItemId(suggestions[0].popup_item_id) == + FillingProduct::kCompose}; + AutofillPopupHideHelper::HidingCallback hiding_callback = base::BindRepeating( &AutofillPopupControllerImpl::Hide, base::Unretained(this)); AutofillPopupHideHelper::PictureInPictureDetectionCallback @@ -232,6 +235,17 @@ key_press_observer_.Reset(); key_press_observer_.Observe(web_contents_->GetFocusedFrame()); + if (suggestions_.size() == 1 && + suggestions_[0].popup_item_id == + PopupItemId::kComposeSavedStateNotification) { + const compose::Config& config = compose::GetComposeConfig(); + fading_popup_timer_.Start( + FROM_HERE, + base::Milliseconds(config.saved_state_timeout_milliseconds), + base::BindOnce(&AutofillPopupControllerImpl::Hide, GetWeakPtr(), + PopupHidingReason::kFadeTimerExpired)); + } + delegate_->OnPopupShown(); } }
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h index 7223aed..73d3c32 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -12,6 +12,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "base/timer/timer.h" #include "chrome/browser/ui/autofill/autofill_popup_controller.h" #include "chrome/browser/ui/autofill/autofill_popup_hide_helper.h" #include "chrome/browser/ui/autofill/next_idle_time_ticks.h" @@ -268,6 +269,9 @@ password_manager::metrics_util::PasswordMigrationWarningTriggers)> show_pwd_migration_warning_callback_; + // Timer to close a fading popup. + base::OneShotTimer fading_popup_timer_; + // Whether the popup should ignore mouse observed outside check. bool should_ignore_mouse_observed_outside_item_bounds_check_ = false;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc index cba369c2..6e998792 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl_unittest.cc
@@ -1236,6 +1236,24 @@ client().popup_controller(manager()).AcceptSuggestion( 0, base::TimeTicks::Now() + base::Milliseconds(500)); } + +// When a suggestion is accepted, the popup is hidden inside +// `delegate->DidAcceptSuggestion()`. On Android, some code is still being +// executed after hiding. This test makes sure no use-after-free, null pointer +// dereferencing or other memory violations occur. +TEST_F(AutofillPopupControllerImplTest, AcceptSuggestionIsMemorySafe) { + ShowSuggestions(manager(), {PopupItemId::kPasswordEntry}); + task_environment()->FastForwardBy(base::Milliseconds(500)); + + EXPECT_CALL(manager().external_delegate(), DidAcceptSuggestion) + .WillOnce([this]() { + client().popup_controller(manager()).Hide( + PopupHidingReason::kAcceptSuggestion); + }); + client().popup_controller(manager()).AcceptSuggestion(/*index=*/0, + base::TimeTicks::Now()); +} + #endif // BUILDFLAG(IS_ANDROID) #if !BUILDFLAG(IS_ANDROID) @@ -1621,6 +1639,25 @@ Hide(PopupHidingReason::kTabGone)); } +// Tests that Compose saved state notification popup gets hidden after 2 +// seconds, but not after 1 second. +TEST_F(AutofillPopupControllerImplTestHidingLogic, + TimedHideComposeSavedStateNotification) { + ShowSuggestions(manager(), {PopupItemId::kComposeSavedStateNotification}); + test::GenerateTestAutofillPopup(&manager().external_delegate()); + ::testing::MockFunction<void()> check; + { + ::testing::InSequence s; + EXPECT_CALL(check, Call); + EXPECT_CALL(client().popup_controller(manager()), + Hide(PopupHidingReason::kFadeTimerExpired)); + } + task_environment()->FastForwardBy(base::Seconds(1)); + check.Call(); + task_environment()->FastForwardBy(base::Seconds(1)); + Mock::VerifyAndClearExpectations(&client().popup_controller(manager())); +} + #if !BUILDFLAG(IS_ANDROID) // Tests that if the popup is shown in the *main frame*, changing the zoom hides // the popup.
diff --git a/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc b/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc index 035ba83..4401cc0 100644 --- a/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc +++ b/chrome/browser/ui/views/autofill/popup/popup_view_utils.cc
@@ -556,6 +556,7 @@ case PopupItemId::kAddressFieldByFieldFilling: case PopupItemId::kAutocompleteEntry: case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: case PopupItemId::kCreateNewPlusAddress: case PopupItemId::kCreditCardEntry: case PopupItemId::kCreditCardFieldByFieldFilling: @@ -602,6 +603,7 @@ case PopupItemId::kAutofillOptions: case PopupItemId::kClearForm: case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: case PopupItemId::kCreateNewPlusAddress: case PopupItemId::kDatalistEntry: case PopupItemId::kDevtoolsTestAddressEntry:
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 39567f5..62071a61 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -26,6 +26,7 @@ #include "base/strings/string_number_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/test/bind.h" +#include "base/test/run_until.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -4265,15 +4266,32 @@ namespace { +// Calls `SetBounds` on a browser window, and waits for the bounds to be set +// server-side. +// +// NOTE: This function assumes that the server will respect our choice of +// bounds. For example, if we place the window outside the edge of the screen, +// the server will modify its bounds - in that case this function will fail. + +// NOTE: This function also assumes that the window's bounds were never +// previously set to `bounds`. If they were previously set to be `bounds`, then +// to another value, then back to `bounds`, it may grab the latched state for +// the first setting, instead of the last one. void SetBoundsSync(BrowserWindow* window, const gfx::Rect& bounds) { window->SetBounds(bounds); #if BUILDFLAG(IS_CHROMEOS_LACROS) - // Wait for a Wayland roundtrip to ensure all side effects have been - // processed. auto* host = static_cast<aura::WindowTreeHostPlatform*>( window->GetNativeWindow()->GetHost()); auto* wayland_extension = ui::GetWaylandExtension(*host->platform_window()); + + // Wait until the server has processed all currently issued requests. + wayland_extension->RoundTripQueue(); + + // Wait for latched state to reflect the bounds change. + ASSERT_TRUE(base::test::RunUntil([&]() { + return wayland_extension->GetLatchedState().bounds_dip == bounds; + })); wayland_extension->RoundTripQueue(); #endif }
diff --git a/chrome/browser/ui/webui/ash/DEPS b/chrome/browser/ui/webui/ash/DEPS index 7880df5..efa25fb5 100644 --- a/chrome/browser/ui/webui/ash/DEPS +++ b/chrome/browser/ui/webui/ash/DEPS
@@ -1,5 +1,5 @@ include_rules = [ - "+ash/system/diagnostics", + "+ash/system", "+ash/test", # Ash depends on views, so allow code in ui/webui/ash to depend on ui/views.
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc index cbe1a60..720f30a 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_open_metrics.cc
@@ -58,8 +58,8 @@ } // Returns true when `task_result` represents the cloud open/upload flow ending -// before the setup has completed. -bool DidEndWithoutSetUp(OfficeTaskResult task_result) { +// before calling CloudOpenTask::OpenOrMoveFiles(). +bool DidEndBeforeCallingOpenOrMoveFiles(OfficeTaskResult task_result) { switch (task_result) { case OfficeTaskResult::kFallbackQuickOffice: case OfficeTaskResult::kFallbackOther: @@ -181,8 +181,9 @@ // Task result should always be logged. ExpectLogged(task_result); if (task_result.logged()) { - if (DidEndWithoutSetUp(task_result.value)) { - // The cloud open/upload flow was exited before the setup completed. + if (DidEndBeforeCallingOpenOrMoveFiles(task_result.value)) { + // The cloud open/upload flow was exited before calling + // CloudOpenTask::OpenOrMoveFiles(). ExpectNotLogged(transfer_required); ExpectNotLogged(source_volume); ExpectNotLogged(upload_result); @@ -240,8 +241,7 @@ } } } else { - // The cloud open/upload flow was not exited at the Fallback Dialog or - // Setup flow. + // CloudOpenTask::OpenOrMoveFiles() was called. ExpectLogged(source_volume); ExpectLogged(transfer_required); if (DidEndAtMoveConfirmation(task_result.value)) {
diff --git a/chrome/browser/ui/webui/ash/settings/os_settings_ui.cc b/chrome/browser/ui/webui/ash/settings/os_settings_ui.cc index 8c02814..5ee65543 100644 --- a/chrome/browser/ui/webui/ash/settings/os_settings_ui.cc +++ b/chrome/browser/ui/webui/ash/settings/os_settings_ui.cc
@@ -13,6 +13,8 @@ #include "ash/public/cpp/esim_manager.h" #include "ash/public/cpp/hotspot_config_service.h" #include "ash/public/cpp/network_config_service.h" +#include "ash/public/mojom/hid_preserving_bluetooth_state_controller.mojom.h" +#include "ash/system/bluetooth/hid_preserving_controller/hid_preserving_bluetooth_state_service.h" #include "ash/webui/common/trusted_types_util.h" #include "ash/webui/personalization_app/search/search.mojom.h" #include "ash/webui/personalization_app/search/search_handler.h" @@ -391,6 +393,13 @@ ash::GetPasspointService(std::move(receiver)); } +void OSSettingsUI::BindInterface( + mojo::PendingReceiver<ash::mojom::HidPreservingBluetoothStateController> + receiver) { + DCHECK(features::IsBluetoothDisconnectWarningEnabled()); + GetHidPreservingBluetoothStateControllerService(std::move(receiver)); +} + WEB_UI_CONTROLLER_TYPE_IMPL(OSSettingsUI) } // namespace ash::settings
diff --git a/chrome/browser/ui/webui/ash/settings/os_settings_ui.h b/chrome/browser/ui/webui/ash/settings/os_settings_ui.h index 879c9b5c..c319456 100644 --- a/chrome/browser/ui/webui/ash/settings/os_settings_ui.h +++ b/chrome/browser/ui/webui/ash/settings/os_settings_ui.h
@@ -7,6 +7,7 @@ #include <memory> +#include "ash/public/mojom/hid_preserving_bluetooth_state_controller.mojom-forward.h" #include "ash/webui/common/mojom/shortcut_input_provider.mojom.h" #include "ash/webui/personalization_app/search/search.mojom-forward.h" #include "base/time/time.h" @@ -209,6 +210,11 @@ mojo::PendingReceiver<chromeos::connectivity::mojom::PasspointService> receiver); + // Binds HidPreservingBluetoothStateController service. + void BindInterface( + mojo::PendingReceiver<ash::mojom::HidPreservingBluetoothStateController> + receiver); + private: base::TimeTicks time_when_opened_;
diff --git a/chrome/browser/ui/webui/ash/settings/pages/bluetooth/bluetooth_section.cc b/chrome/browser/ui/webui/ash/settings/pages/bluetooth/bluetooth_section.cc index 9eb5089..f8350e4 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/bluetooth/bluetooth_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/bluetooth/bluetooth_section.cc
@@ -334,6 +334,8 @@ "bluetoothRevampHatsSurveyFlag", base::FeatureList::IsEnabled( ::features::kHappinessTrackingSystemBluetoothRevamp)); + html_source->AddBoolean("bluetoothDisconnectWarningFlag", + features::IsBluetoothDisconnectWarningEnabled()); bluetooth::AddLoadTimeData(html_source); }
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 7136fa2..33cfe10 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -516,8 +516,6 @@ if (is_chromeos) { sources += [ - "preinstalled_web_apps/app_mall.cc", - "preinstalled_web_apps/app_mall.h", "preinstalled_web_apps/calculator.cc", "preinstalled_web_apps/calculator.h", "preinstalled_web_apps/google_calendar.cc", @@ -529,9 +527,6 @@ "preinstalled_web_apps/messages_dogfood.cc", "preinstalled_web_apps/messages_dogfood.h", ] - - # TODO(b/327080071): Remove when app_mall.cc moves to an online preload. - deps += [ "//ash/webui/resources:help_app_resources" ] } deps += [ "//chrome/browser/resources:preinstalled_web_apps_resources" ]
diff --git a/chrome/browser/web_applications/preinstalled_app_install_features.cc b/chrome/browser/web_applications/preinstalled_app_install_features.cc index 0ab7d630f..eacf58fc 100644 --- a/chrome/browser/web_applications/preinstalled_app_install_features.cc +++ b/chrome/browser/web_applications/preinstalled_app_install_features.cc
@@ -27,11 +27,7 @@ // After a feature flag has been shipped and should be cleaned up, move it into // kShippedPreinstalledAppInstallFeatures to ensure any external installation // configs that reference it continue to see it as enabled. -constexpr const base::Feature* kPreinstalledAppInstallFeatures[] = { -#if BUILDFLAG(IS_CHROMEOS) - &chromeos::features::kCrosMall, -#endif -}; +constexpr const base::Feature* kPreinstalledAppInstallFeatures[] = {}; constexpr const base::StringPiece kShippedPreinstalledAppInstallFeatures[] = { // Enables installing the PWA version of the chrome os calculator instead of
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/app_mall.cc b/chrome/browser/web_applications/preinstalled_web_apps/app_mall.cc deleted file mode 100644 index 516f6eb..0000000 --- a/chrome/browser/web_applications/preinstalled_web_apps/app_mall.cc +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/web_applications/preinstalled_web_apps/app_mall.h" - -#include <memory> - -#include "ash/webui/grit/ash_help_app_resources.h" -#include "base/functional/bind.h" -#include "chrome/browser/web_applications/external_install_options.h" -#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h" -#include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_app_definition_utils.h" -#include "chrome/browser/web_applications/web_app_install_info.h" -#include "chrome/grit/preinstalled_web_apps_resources.h" -#include "chromeos/constants/chromeos_features.h" - -namespace web_app { - -ExternalInstallOptions GetConfigForAppMall() { - ExternalInstallOptions options( - /*install_url=*/GURL("https://discover.apps.chrome/"), - /*user_display_mode=*/mojom::UserDisplayMode::kStandalone, - /*install_source=*/ExternalInstallSource::kExternalDefault); - - options.user_type_allowlist = {"unmanaged"}; - options.gate_on_feature = chromeos::features::kCrosMall.name; - - options.load_and_await_service_worker_registration = false; - options.only_use_app_info_factory = false; - - // This App Info Factory is temporary, to help with prototyping. - // TODO(b/327080071): Remove. - options.app_info_factory = base::BindRepeating([]() { - auto info = std::make_unique<WebAppInstallInfo>(); - info->title = u"Get Apps and Games"; - info->start_url = GURL("https://discover.apps.chrome/"); - info->manifest_id = GURL("https://discover.apps.chrome/"); - info->display_mode = DisplayMode::kStandalone; - info->icon_bitmaps.any = LoadBundledIcons({IDR_HELP_APP_ICON_192}); - return info; - }); - - return options; -} - -} // namespace web_app
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/app_mall.h b/chrome/browser/web_applications/preinstalled_web_apps/app_mall.h deleted file mode 100644 index 57bfb03..0000000 --- a/chrome/browser/web_applications/preinstalled_web_apps/app_mall.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APPS_APP_MALL_H_ -#define CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APPS_APP_MALL_H_ - -#include "chrome/browser/web_applications/external_install_options.h" - -namespace web_app { - -ExternalInstallOptions GetConfigForAppMall(); - -} // namespace web_app - -#endif // CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APPS_APP_MALL_H_
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc index c7fa851..a52d0445 100644 --- a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc +++ b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
@@ -27,7 +27,6 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/web_applications/preinstalled_web_apps/app_mall.h" #include "chrome/browser/web_applications/preinstalled_web_apps/calculator.h" #include "chrome/browser/web_applications/preinstalled_web_apps/google_calendar.h" #include "chrome/browser/web_applications/preinstalled_web_apps/google_chat.h" @@ -79,7 +78,6 @@ GetConfigForGoogleSlides(is_standalone_tabbed), GetConfigForYouTube(), #if BUILDFLAG(IS_CHROMEOS) - GetConfigForAppMall(), GetConfigForCalculator(), GetConfigForGoogleCalendar(), GetConfigForGoogleChat(),
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index d69a18b..f4b6a1f 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1709085465-1b31e75863d31368ea1253012d8a50b2fd94bf2c-842e05709146e9f1f464a54ee26b6cfbff637842.profdata +chrome-mac-arm-main-1709114309-4e1d4e7a54bd1cd9fc6cfa9cf07bfa83d2212272-ca25f4d1951c7e00bb917b0ec497a6dd15e23d1e.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 18222ea3..3d40aa5 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1709068917-71b5bd73b41e803a656d237e4bcac6bb00847539-85c5580ab27b10a745b6c26c32c5037db19eafb3.profdata +chrome-mac-main-1709078324-cc180c331af1d14ee0a29ac0afdd23a11ba75ec8-a6f948e7126bcb0d99e93a2347d3c9fa647adfa6.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index b3eacbf..62c8aa6 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1709067589-24f546de9ffb88744f74658b2c780cd636573bfb-334ae2d16d79edf5c5bfd85f19dd053a35d14563.profdata +chrome-win32-main-1709088945-331015ee82336bad565dcf95dc6bb6eac951e2e6-8534b16a5d8ba9e9daa035fb37c665751dcd6773.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 5848b7c..0a63572 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1709078324-b8ad9a77978ec4c0a398ef4325f45da4fddf7270-a6f948e7126bcb0d99e93a2347d3c9fa647adfa6.profdata +chrome-win64-main-1709088945-3e3566cc2ee6314b15d185051ac7d7c75c259f8a-8534b16a5d8ba9e9daa035fb37c665751dcd6773.profdata
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index 7bf7cc06..48b2397 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -2530,6 +2530,31 @@ base::RunLoop().RunUntilIdle(); } +// Tests that the popup is suppressed when the user selects address or payments +// fallback even when the triggering field that is classified as password. +TEST_F(PasswordAutofillAgentTest, + NoPopupOnPasswordFieldWhereAddressOrPaymentsManualFallbackWasSelected) { + SimulateOnFillPasswordForm(fill_data_); + // This call is necessary to setup the autofill agent appropriate for the + // user selection; simulates the menu actually popping up. + SimulatePointClick(gfx::Point(1, 1)); + + // No popup when using address/payment manual fallback. + EXPECT_CALL(fake_driver_, ShowPasswordSuggestions).Times(0); + autofill_agent_->TriggerSuggestions( + form_util::GetFieldRendererId(username_element_), + AutofillSuggestionTriggerSource::kManualFallbackAddress); + autofill_agent_->TriggerSuggestions( + form_util::GetFieldRendererId(username_element_), + AutofillSuggestionTriggerSource::kManualFallbackPayments); + + // However popup is shown otherwise. + EXPECT_CALL(fake_driver_, ShowPasswordSuggestions); + autofill_agent_->TriggerSuggestions( + form_util::GetFieldRendererId(username_element_), + AutofillSuggestionTriggerSource::kTextFieldDidChange); +} + TEST_F(PasswordAutofillAgentTest, NoPopupOnPasswordFieldWithoutSuggestionsByDefault) { ClearUsernameAndPasswordFieldValues(); @@ -2539,7 +2564,6 @@ // what informs the agent whether it should show the popup even without // suggestions. In this test, that call hasn't happened yet, so the popup // should NOT show up without suggestions. - SimulateElementClick(kPasswordName); EXPECT_CALL(fake_driver_, ShowPasswordSuggestions).Times(0);
diff --git a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn index 85278b69..a8249cbd 100644 --- a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn +++ b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
@@ -28,6 +28,7 @@ "bluetooth/fake_bluetooth_config.ts", "bluetooth/fake_bluetooth_discovery_delegate.ts", "bluetooth/fake_device_pairing_handler.ts", + "bluetooth/fake_hid_preserving_bluetooth_state_controller.ts", "cellular_setup/activation_code_page_test.ts", "cellular_setup/base_page_test.ts", "cellular_setup/button_bar_test.ts",
diff --git a/chrome/test/data/webui/cr_components/chromeos/bluetooth/fake_hid_preserving_bluetooth_state_controller.ts b/chrome/test/data/webui/cr_components/chromeos/bluetooth/fake_hid_preserving_bluetooth_state_controller.ts new file mode 100644 index 0000000..b76a815 --- /dev/null +++ b/chrome/test/data/webui/cr_components/chromeos/bluetooth/fake_hid_preserving_bluetooth_state_controller.ts
@@ -0,0 +1,59 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import type {HidPreservingBluetoothStateControllerInterface} from 'chrome://resources/ash/common/bluetooth/hid_preserving_bluetooth_state_controller.mojom-webui.js'; +import type {CrosBluetoothConfigInterface} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js'; + +import {assertTrue} from '../../../chromeos/chai_assert.js'; + +/** + * @fileoverview Fake implementation of HidPreservingBluetoothStateController + * for testing. + */ + +export class FakeHidPreservingBluetoothStateController implements + HidPreservingBluetoothStateControllerInterface { + bluetoothConfig: CrosBluetoothConfigInterface|undefined; + shouldShowWarningDialog: boolean = false; + pendingBluetoothEnabledRequest: boolean = false; + dialogShownCount: number = 0; + + setBluetoothConfigForTesting(testBluetoothConfig?: + CrosBluetoothConfigInterface): void { + this.bluetoothConfig = testBluetoothConfig; + } + + tryToSetBluetoothEnabledState(enabled: boolean) { + if (this.shouldShowWarningDialog && !enabled) { + this.dialogShownCount++; + this.pendingBluetoothEnabledRequest = enabled; + return; + } + + this.setBluetoothEnabledState(enabled); + } + + setShouldShowWarningDialog(shouldShowWarningDialog: boolean) { + this.shouldShowWarningDialog = shouldShowWarningDialog; + } + + completeShowDialog(showDialogResult: boolean) { + assertTrue(this.shouldShowWarningDialog); + + if (!showDialogResult) { + return; + } + + this.setBluetoothEnabledState(this.pendingBluetoothEnabledRequest); + } + + setBluetoothEnabledState(enabled: boolean) { + assertTrue(!!this.bluetoothConfig); + this.bluetoothConfig!.setBluetoothEnabledState(enabled); + } + + getDialogShownCount(): number { + return this.dialogShownCount; + } +}
diff --git a/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_test.ts b/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_test.ts index 0ce24ff..3cf61a5 100644 --- a/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_test.ts
@@ -7,12 +7,14 @@ import {SettingsBluetoothDevicesSubpageElement, SettingsPairedBluetoothListElement} from 'chrome://os-settings/lazy_load.js'; import {CrToggleElement, OsBluetoothDevicesSubpageBrowserProxyImpl, Router, routes, settingMojom, SettingsToggleButtonElement} from 'chrome://os-settings/os_settings.js'; import {setBluetoothConfigForTesting} from 'chrome://resources/ash/common/bluetooth/cros_bluetooth_config.js'; +import {setHidPreservingControllerForTesting} from 'chrome://resources/ash/common/bluetooth/hid_preserving_bluetooth_state_controller.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {getDeepActiveElement} from 'chrome://resources/js/util.js'; import {BluetoothSystemProperties, BluetoothSystemState, DeviceConnectionState, SystemPropertiesObserverInterface} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertEquals, assertFalse, assertGT, assertNotEquals, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {createDefaultBluetoothDevice, FakeBluetoothConfig} from 'chrome://webui-test/cr_components/chromeos/bluetooth/fake_bluetooth_config.js'; +import {FakeHidPreservingBluetoothStateController} from 'chrome://webui-test/cr_components/chromeos/bluetooth/fake_hid_preserving_bluetooth_state_controller.js'; import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; @@ -23,6 +25,7 @@ let bluetoothDevicesSubpage: SettingsBluetoothDevicesSubpageElement; let propertiesObserver: SystemPropertiesObserverInterface; let browserProxy: TestOsBluetoothDevicesSubpageBrowserProxy; + let hidPreservingController: FakeHidPreservingBluetoothStateController; suiteSetup(() => { browserProxy = new TestOsBluetoothDevicesSubpageBrowserProxy(); @@ -42,7 +45,18 @@ Router.getInstance().resetRouteForTesting(); }); - async function init(urlParams?: URLSearchParams): Promise<void> { + async function init( + isBluetoothDisconnectWarningEnabled: boolean = false, + urlParams?: URLSearchParams): Promise<void> { + if (isBluetoothDisconnectWarningEnabled) { + loadTimeData.overrideValues({'bluetoothDisconnectWarningFlag': true}); + hidPreservingController = new FakeHidPreservingBluetoothStateController(); + hidPreservingController.setBluetoothConfigForTesting(bluetoothConfig); + setHidPreservingControllerForTesting(hidPreservingController); + } else { + loadTimeData.overrideValues({'bluetoothDisconnectWarningFlag': false}); + } + bluetoothDevicesSubpage = document.createElement('os-settings-bluetooth-devices-subpage'); setFastPairPrefEnabled(true); @@ -429,7 +443,7 @@ flush(); const params = new URLSearchParams(); params.append('settingId', settingMojom.Setting.kBluetoothOnOff.toString()); - await init(params); + await init(false, params); const deepLinkElement = bluetoothDevicesSubpage.shadowRoot!.querySelector( '#enableBluetoothToggle'); @@ -445,7 +459,7 @@ flush(); const params = new URLSearchParams(); params.append('settingId', settingMojom.Setting.kFastPairOnOff.toString()); - await init(params); + await init(false, params); const fastPairToggle = bluetoothDevicesSubpage.shadowRoot!.querySelector( '#enableFastPairToggle'); @@ -506,4 +520,78 @@ '.device-lists-separator'); assertGT(sepLines.length, 1); }); + + test('Toggle Bluetooth with bluetoothDisconnectWarningFlag on', async () => { + bluetoothConfig.setSystemState(BluetoothSystemState.kDisabled); + await flushTasks(); + await init(/* isBluetoothDisconnectWarningEnabled= */ true); + + const enableBluetoothToggle = + bluetoothDevicesSubpage.shadowRoot!.querySelector<CrToggleElement>( + '#enableBluetoothToggle'); + assertTrue(!!enableBluetoothToggle); + assertFalse(enableBluetoothToggle.checked); + + const enableBluetooth = async () => { + assertTrue( + bluetoothDevicesSubpage.systemProperties.systemState === + BluetoothSystemState.kDisabled); + + // Simulate clicking toggle. + enableBluetoothToggle.click(); + await flushTasks(); + + // Toggle should be on since systemState is enabling. + assertTrue( + bluetoothDevicesSubpage.systemProperties.systemState === + BluetoothSystemState.kEnabling); + + // Mock operation success. + bluetoothConfig.completeSetBluetoothEnabledState(/*success=*/ true); + await flushTasks(); + assertTrue( + bluetoothDevicesSubpage.systemProperties.systemState === + BluetoothSystemState.kEnabled); + }; + + await enableBluetooth(); + assertEquals(hidPreservingController.getDialogShownCount(), 0); + + // Disable bluetooth and simulate showing dialog, with user electing + // to continue disabling Bluetooth. + hidPreservingController.setShouldShowWarningDialog(true); + enableBluetoothToggle.click(); + await flushTasks(); + + assertEquals(hidPreservingController.getDialogShownCount(), 1); + assertTrue( + bluetoothDevicesSubpage.systemProperties.systemState === + BluetoothSystemState.kEnabled); + hidPreservingController.completeShowDialog(true); + await flushTasks(); + + assertTrue( + bluetoothDevicesSubpage.systemProperties.systemState === + BluetoothSystemState.kDisabling); + bluetoothConfig.completeSetBluetoothEnabledState(/*success=*/ true); + await flushTasks(); + await enableBluetooth(); + assertEquals(hidPreservingController.getDialogShownCount(), 1); + + // Disable Bluetooth and simulate showing dialog with user selecting + // to keep current bluetooth state. + enableBluetoothToggle.click(); + await flushTasks(); + + assertEquals(hidPreservingController.getDialogShownCount(), 2); + assertTrue( + bluetoothDevicesSubpage.systemProperties.systemState === + BluetoothSystemState.kEnabled); + hidPreservingController.completeShowDialog(false); + + await flushTasks(); + assertTrue( + bluetoothDevicesSubpage.systemProperties.systemState === + BluetoothSystemState.kEnabled); + }); });
diff --git a/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_summary_test.ts b/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_summary_test.ts index d4f2036..ff9c69e 100644 --- a/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_summary_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_bluetooth_page/os_bluetooth_summary_test.ts
@@ -3,15 +3,18 @@ // found in the LICENSE file. import 'chrome://os-settings/os_settings.js'; +import 'chrome://os-settings/lazy_load.js'; import {CrToggleElement, IronIconElement, OsBluetoothDevicesSubpageBrowserProxyImpl, Router, routes, SettingsBluetoothSummaryElement} from 'chrome://os-settings/os_settings.js'; import {setBluetoothConfigForTesting} from 'chrome://resources/ash/common/bluetooth/cros_bluetooth_config.js'; +import {setHidPreservingControllerForTesting} from 'chrome://resources/ash/common/bluetooth/hid_preserving_bluetooth_state_controller.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {mojoString16ToString} from 'chrome://resources/js/mojo_type_util.js'; import {BluetoothSystemProperties, BluetoothSystemState, DeviceConnectionState, SystemPropertiesObserverInterface} from 'chrome://resources/mojo/chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-webui.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertEquals, assertFalse, assertNotEquals, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {createDefaultBluetoothDevice, FakeBluetoothConfig} from 'chrome://webui-test/cr_components/chromeos/bluetooth/fake_bluetooth_config.js'; +import {FakeHidPreservingBluetoothStateController} from 'chrome://webui-test/cr_components/chromeos/bluetooth/fake_hid_preserving_bluetooth_state_controller.js'; import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; @@ -22,6 +25,7 @@ let bluetoothSummary: SettingsBluetoothSummaryElement; let propertiesObserver: SystemPropertiesObserverInterface; let browserProxy: TestOsBluetoothDevicesSubpageBrowserProxy; + let hidPreservingController: FakeHidPreservingBluetoothStateController; setup(() => { bluetoothConfig = new FakeBluetoothConfig(); @@ -34,7 +38,16 @@ Router.getInstance().resetRouteForTesting(); }); - function init(): void { + async function init(isBluetoothDisconnectWarningEnabled: boolean = false) { + if (isBluetoothDisconnectWarningEnabled) { + loadTimeData.overrideValues({'bluetoothDisconnectWarningFlag': true}); + hidPreservingController = new FakeHidPreservingBluetoothStateController(); + hidPreservingController.setBluetoothConfigForTesting(bluetoothConfig); + setHidPreservingControllerForTesting(hidPreservingController); + } else { + loadTimeData.overrideValues({'bluetoothDisconnectWarningFlag': false}); + } + browserProxy = new TestOsBluetoothDevicesSubpageBrowserProxy(); OsBluetoothDevicesSubpageBrowserProxyImpl.setInstanceForTesting( browserProxy); @@ -53,8 +66,82 @@ bluetoothConfig.observeSystemProperties(propertiesObserver); } + test('Toggle Bluetooth with bluetoothDisconnectWarningFlag on', async () => { + await flushTasks(); + await init(/* isBluetoothDisconnectWarningEnabled= */ true); + bluetoothConfig.setSystemState(BluetoothSystemState.kDisabled); + await flushTasks(); + + const enableBluetoothToggle = + bluetoothSummary.shadowRoot!.querySelector<CrToggleElement>( + '#enableBluetoothToggle'); + assertTrue(!!enableBluetoothToggle); + + const enableBluetooth = async () => { + assertTrue( + bluetoothSummary.systemProperties.systemState === + BluetoothSystemState.kDisabled); + + // Simulate clicking toggle. + enableBluetoothToggle.click(); + await flushTasks(); + + // Toggle should be on since systemState is enabling. + assertTrue( + bluetoothSummary.systemProperties.systemState === + BluetoothSystemState.kEnabling); + + // Mock operation success. + bluetoothConfig.completeSetBluetoothEnabledState(/*success=*/ true); + await flushTasks(); + assertTrue( + bluetoothSummary.systemProperties.systemState === + BluetoothSystemState.kEnabled); + }; + + await enableBluetooth(); + assertEquals(hidPreservingController.getDialogShownCount(), 0); + + // Disable bluetooth and simulate showing dialog, with user electing + // to continue disabling Bluetooth. + hidPreservingController.setShouldShowWarningDialog(true); + enableBluetoothToggle.click(); + await flushTasks(); + + assertEquals(hidPreservingController.getDialogShownCount(), 1); + assertTrue( + bluetoothSummary.systemProperties.systemState === + BluetoothSystemState.kEnabled); + hidPreservingController.completeShowDialog(true); + await flushTasks(); + + assertTrue( + bluetoothSummary.systemProperties.systemState === + BluetoothSystemState.kDisabling); + bluetoothConfig.completeSetBluetoothEnabledState(/*success=*/ true); + await flushTasks(); + await enableBluetooth(); + assertEquals(hidPreservingController.getDialogShownCount(), 1); + + // Disable Bluetooth and simulate showing dialog with user selecting + // to keep current bluetooth state. + enableBluetoothToggle.click(); + await flushTasks(); + + assertEquals(hidPreservingController.getDialogShownCount(), 2); + assertTrue( + bluetoothSummary.systemProperties.systemState === + BluetoothSystemState.kEnabled); + hidPreservingController.completeShowDialog(false); + + await flushTasks(); + assertTrue( + bluetoothSummary.systemProperties.systemState === + BluetoothSystemState.kEnabled); + }); + test('Button is focused after returning from devices subpage', async () => { - init(); + await init(); bluetoothConfig.setBluetoothEnabledState(/*enabled=*/ true); await flushTasks(); const iconButton = @@ -81,9 +168,9 @@ }); test('Toggle button creation and a11y', async () => { + await init(); bluetoothConfig.setSystemState(BluetoothSystemState.kEnabled); await flushTasks(); - init(); let a11yMessagesEventPromise = eventToPromise('cr-a11y-announcer-messages-sent', document.body); @@ -107,7 +194,9 @@ }); test('Toggle button states', async () => { - init(); + await init(); + bluetoothConfig.setSystemState(BluetoothSystemState.kDisabled); + await flushTasks(); assertEquals(0, browserProxy.getShowBluetoothRevampHatsSurveyCount()); const getPairNewDeviceBtn = () => @@ -175,7 +264,10 @@ }); test('UI states test', async () => { - init(); + await init(); + + bluetoothConfig.setSystemState(BluetoothSystemState.kDisabled); + await flushTasks(); // Simulate device state is disabled. const bluetoothSecondaryLabel = @@ -290,7 +382,7 @@ }); test('start-pairing is fired on pairNewDeviceBtn click', async () => { - init(); + await init(); bluetoothConfig.setBluetoothEnabledState(/*enabled=*/ true); await flushTasks(); @@ -317,7 +409,7 @@ isSecondaryUser: true, primaryUserEmail, }); - init(); + await init(); bluetoothConfig.setBluetoothEnabledState(/*enabled=*/ true); await flushTasks(); @@ -339,8 +431,8 @@ bluetoothSummarySecondaryText.textContent?.trim()); }); - test('Route to summary page', () => { - init(); + test('Route to summary page', async () => { + await init(); assertEquals(0, browserProxy.getShowBluetoothRevampHatsSurveyCount()); Router.getInstance().navigateTo(routes.BLUETOOTH); assertEquals(
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index 3d8864f..d0331d6 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -73,10 +73,6 @@ "CrosComponents", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables an app to discover and install other apps. This flag will be enabled -// with Finch. -BASE_FEATURE(kCrosMall, "CrosMall", base::FEATURE_DISABLED_BY_DEFAULT); - // Enables the behaviour difference between web apps and browser created // shortcut backed by the web app system on Chrome OS. BASE_FEATURE(kCrosShortstand,
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index 9909949..94b9cad 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -39,7 +39,6 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kCrosAppsBackgroundEventHandling); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kCrosComponents); -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kCrosMall); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kCrosShortstand); COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
diff --git a/clank b/clank index 8933ab5..2932c10 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 8933ab5bda635e80ec163376cf2410af186083a0 +Subproject commit 2932c1090e4c5fa9b48dd9ba530f6c353ef6d99e
diff --git a/components/autofill/content/browser/content_autofill_client.cc b/components/autofill/content/browser/content_autofill_client.cc index d86c553a..94b2676 100644 --- a/components/autofill/content/browser/content_autofill_client.cc +++ b/components/autofill/content/browser/content_autofill_client.cc
@@ -17,11 +17,6 @@ return &autofill_driver_factory_; } -void ContentAutofillClient::ShowComposeFadingPopup(FormGlobalId form_id, - FieldGlobalId field_id) { - // TODO(b/303500278): Complete fading popup implementation. -} - WEB_CONTENTS_USER_DATA_KEY_IMPL(ContentAutofillClient); } // namespace autofill
diff --git a/components/autofill/content/browser/content_autofill_client.h b/components/autofill/content/browser/content_autofill_client.h index 14907aa..19e4272 100644 --- a/components/autofill/content/browser/content_autofill_client.h +++ b/components/autofill/content/browser/content_autofill_client.h
@@ -41,9 +41,6 @@ base::PassKey<ContentAutofillDriverFactory> pass_key, const mojo::AssociatedRemote<mojom::AutofillAgent>& agent) = 0; - // Shows the compose fading popup for the given autofill field. - void ShowComposeFadingPopup(FormGlobalId form_id, FieldGlobalId field_id); - private: friend class content::WebContentsUserData<ContentAutofillClient>;
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 054af0e..00679048 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -33,6 +33,7 @@ #include "components/autofill/content/renderer/suggestion_properties.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_features.h" +#include "components/autofill/core/common/autofill_util.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_data_predictions.h" #include "components/autofill/core/common/form_field_data.h" @@ -949,7 +950,11 @@ } last_queried_element_ = FieldRef(element); - if (form_util::IsAutofillableInputElement(input_element)) { + const bool is_address_or_payments_manual_fallback = + IsAddressAutofillManuallyTriggered(trigger_source) || + IsPaymentsAutofillManuallyTriggered(trigger_source); + if (!is_address_or_payments_manual_fallback && + form_util::IsAutofillableInputElement(input_element)) { if (password_generation_agent_ && password_generation_agent_->ShowPasswordGenerationSuggestions( input_element)) { @@ -964,16 +969,17 @@ } // Password field elements should only have suggestions shown by the password - // autofill agent. - // The /*disable presubmit*/ comment below is used to disable a presubmit - // script that ensures that only IsPasswordFieldForAutofill() is used in this - // code (it has to appear between the function name and the parenthesis to not - // match a regex). In this specific case we are actually interested in whether - // the field is currently a password field, not whether it has ever been a - // password field. + // autofill agent. Unless an address or payments manual fallback option is + // chosen. The /*disable presubmit*/ comment below is used to disable a + // presubmit script that ensures that only IsPasswordFieldForAutofill() is + // used in this code (it has to appear between the function name and the + // parenthesis to not match a regex). In this specific case we are actually + // interested in whether the field is currently a password field, not whether + // it has ever been a password field. if (!input_element.IsNull() && input_element.IsPasswordField /*disable presubmit*/ () && - !config_.query_password_suggestions) { + !config_.query_password_suggestions && + !is_address_or_payments_manual_fallback) { return; }
diff --git a/components/autofill/content/renderer/suggestion_properties.cc b/components/autofill/content/renderer/suggestion_properties.cc index e90cb78..b79ccdf 100644 --- a/components/autofill/content/renderer/suggestion_properties.cc +++ b/components/autofill/content/renderer/suggestion_properties.cc
@@ -24,6 +24,7 @@ case AutofillSuggestionTriggerSource::kManualFallbackPasswords: case AutofillSuggestionTriggerSource:: kShowPromptAfterDialogClosedNonManualFallback: + case AutofillSuggestionTriggerSource::kComposeDialogLostFocus: case AutofillSuggestionTriggerSource::kTextareaFocusedWithoutClick: case AutofillSuggestionTriggerSource::kContentEditableClicked: return true; @@ -46,6 +47,7 @@ switch (trigger_source) { case AutofillSuggestionTriggerSource::kTextareaFocusedWithoutClick: case AutofillSuggestionTriggerSource::kContentEditableClicked: + case AutofillSuggestionTriggerSource::kComposeDialogLostFocus: return true; case AutofillSuggestionTriggerSource::kFormControlElementClicked: case AutofillSuggestionTriggerSource::kManualFallbackAddress: @@ -80,6 +82,7 @@ case AutofillSuggestionTriggerSource::kManualFallbackPasswords: case AutofillSuggestionTriggerSource:: kShowPromptAfterDialogClosedNonManualFallback: + case AutofillSuggestionTriggerSource::kComposeDialogLostFocus: return false; // `kShowCardsFromAccount`, `kPasswordManager`, `kAndroidWebView` and `kiOS` // are not used in the renderer code. As such, suggestion properties don't @@ -112,6 +115,7 @@ case AutofillSuggestionTriggerSource::kManualFallbackPasswords: case AutofillSuggestionTriggerSource:: kShowPromptAfterDialogClosedNonManualFallback: + case AutofillSuggestionTriggerSource::kComposeDialogLostFocus: return false; // `kShowCardsFromAccount`, `kPasswordManager`, `kAndroidWebView` and `kiOS` // are not used in the renderer code. As such, suggestion properties don't
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 8d125b58..631cfd2 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -536,6 +536,9 @@ "ui/payments/card_unmask_prompt_options.h", "ui/payments/card_unmask_prompt_view.h", "ui/payments/payments_bubble_closed_reasons.h", + "ui/payments/payments_window_user_consent_dialog_controller.h", + "ui/payments/payments_window_user_consent_dialog_controller_impl.cc", + "ui/payments/payments_window_user_consent_dialog_controller_impl.h", "ui/payments/save_card_and_virtual_card_enroll_confirmation_ui_params.cc", "ui/payments/save_card_and_virtual_card_enroll_confirmation_ui_params.h", "ui/payments/virtual_card_enroll_bubble_controller.h", @@ -1200,6 +1203,7 @@ "ui/payments/bubble_show_options_unittest.cc", "ui/payments/card_unmask_otp_input_dialog_controller_impl_unittest.cc", "ui/payments/card_unmask_prompt_controller_impl_unittest.cc", + "ui/payments/payments_window_user_consent_dialog_controller_impl_unittest.cc", "ui/payments/save_card_and_virtual_card_enroll_confirmation_ui_params_unittest.cc", "ui/payments/virtual_card_enroll_ui_model_unittest.cc", "ui/region_combobox_model_unittest.cc",
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc index 4da49714..4c133c2 100644 --- a/components/autofill/core/browser/autofill_external_delegate.cc +++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -88,6 +88,7 @@ case AutofillSuggestionTriggerSource::kiOS: case AutofillSuggestionTriggerSource:: kShowPromptAfterDialogClosedNonManualFallback: + case AutofillSuggestionTriggerSource::kComposeDialogLostFocus: // On Android, no popup exists. Instead, the keyboard accessory is used. #if BUILDFLAG(IS_ANDROID) return AutofillTriggerSource::kKeyboardAccessory; @@ -162,6 +163,7 @@ case PopupItemId::kAutofillOptions: case PopupItemId::kClearForm: case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: case PopupItemId::kCreateNewPlusAddress: case PopupItemId::kDatalistEntry: case PopupItemId::kDeleteAddressProfile: @@ -429,6 +431,7 @@ case PopupItemId::kDeleteAddressProfile: case PopupItemId::kAutofillOptions: case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: case PopupItemId::kDatalistEntry: case PopupItemId::kShowAccountCards: case PopupItemId::kInsecureContextPaymentDisabledMessage: @@ -675,6 +678,7 @@ break; } case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: if (AutofillComposeDelegate* delegate = manager_->client().GetComposeDelegate()) { delegate->OpenCompose( @@ -816,6 +820,7 @@ case PopupItemId::kPasswordAccountStorageReSignin: case PopupItemId::kPasswordAccountStorageEmpty: case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: case PopupItemId::kDatalistEntry: case PopupItemId::kMerchantPromoCodeEntry: case PopupItemId::kSeePromoCodeDetails:
diff --git a/components/autofill/core/browser/autofill_optimization_guide.cc b/components/autofill/core/browser/autofill_optimization_guide.cc index 9beeda2..7df2b06 100644 --- a/components/autofill/core/browser/autofill_optimization_guide.cc +++ b/components/autofill/core/browser/autofill_optimization_guide.cc
@@ -237,9 +237,9 @@ bool AutofillOptimizationGuide::ShouldBlockFormFieldSuggestion( const GURL& url, - const CreditCard* card) const { + const CreditCard& card) const { if (auto optimization_type = - GetVcnMerchantOptOutOptimizationTypeForCard(*card); + GetVcnMerchantOptOutOptimizationTypeForCard(card); optimization_type != optimization_guide::proto::TYPE_UNSPECIFIED) { optimization_guide::OptimizationGuideDecision decision = decider_->CanApplyOptimization(url, optimization_type,
diff --git a/components/autofill/core/browser/autofill_optimization_guide.h b/components/autofill/core/browser/autofill_optimization_guide.h index 973bc6d0..a2b53e0 100644 --- a/components/autofill/core/browser/autofill_optimization_guide.h +++ b/components/autofill/core/browser/autofill_optimization_guide.h
@@ -68,7 +68,7 @@ // This function relies on the optimization guide decider that corresponds to // the network of `card`. virtual bool ShouldBlockFormFieldSuggestion(const GURL& url, - const CreditCard* card) const; + const CreditCard& card) const; private: // Raw pointer to a decider which is owned by the decider's factory.
diff --git a/components/autofill/core/browser/autofill_optimization_guide_unittest.cc b/components/autofill/core/browser/autofill_optimization_guide_unittest.cc index 9be36d3..836b4c8 100644 --- a/components/autofill/core/browser/autofill_optimization_guide_unittest.cc +++ b/components/autofill/core/browser/autofill_optimization_guide_unittest.cc
@@ -345,7 +345,7 @@ optimization_guide::OptimizationGuideDecision::kFalse)); EXPECT_TRUE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion( - url, &virtual_card)); + url, virtual_card)); } // Test that if the URL is not blocklisted, we do not block a virtual card @@ -368,7 +368,7 @@ optimization_guide::OptimizationGuideDecision::kTrue)); EXPECT_FALSE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion( - url, &virtual_card)); + url, virtual_card)); } // Test that we do not block virtual card suggestions in the VCN merchant @@ -391,7 +391,7 @@ .Times(0); EXPECT_FALSE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion( - url, &virtual_card)); + url, virtual_card)); } // Test that we do not block the virtual card suggestion from being shown in the @@ -416,7 +416,7 @@ .Times(0); EXPECT_FALSE(autofill_optimization_guide_->ShouldBlockFormFieldSuggestion( - url, &virtual_card)); + url, virtual_card)); } // Test that the Amex category-benefit optimization types are registered when we
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.cc b/components/autofill/core/browser/autofill_suggestion_generator.cc index cc75eb8..a27611f0 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator.cc
@@ -1171,9 +1171,8 @@ } // namespace AutofillSuggestionGenerator::AutofillSuggestionGenerator( - AutofillClient& autofill_client, - PersonalDataManager& personal_data) - : autofill_client_(autofill_client), personal_data_(personal_data) {} + AutofillClient& autofill_client) + : autofill_client_(autofill_client) {} AutofillSuggestionGenerator::~AutofillSuggestionGenerator() = default; @@ -1190,7 +1189,7 @@ // available profiles should be shown. Selecting a suggestion overwrites the // triggering field's value. for (const AutofillProfile* profile : - personal_data_->GetProfilesToSuggest()) { + personal_data().GetProfilesToSuggest()) { profiles_to_suggest.push_back(profile); } } else { @@ -1256,7 +1255,7 @@ // Get the profiles to suggest, which are already sorted. std::vector<AutofillProfile*> sorted_profiles = - personal_data_->GetProfilesToSuggest(); + personal_data().GetProfilesToSuggest(); // When suggesting with no prefix to match, suppress disused address // suggestions as well as those based on invalid profile data. @@ -1271,7 +1270,7 @@ field_contents, field_contents_canon, field_is_autofilled); - const AutofillProfileComparator comparator(personal_data_->app_locale()); + const AutofillProfileComparator comparator(personal_data().app_locale()); // Don't show two suggestions if one is a subset of the other. // Duplicates across sources are resolved in favour of `kAccount` profiles. std::vector<raw_ptr<const AutofillProfile, VectorExperimental>> @@ -1291,7 +1290,7 @@ uint64_t trigger_field_max_length, const std::set<std::string>& previously_hidden_profiles_guid) { std::vector<Suggestion> suggestions; - std::string app_locale = personal_data_->app_locale(); + std::string app_locale = personal_data().app_locale(); // This will be used to check if suggestions should be supported with icons. const bool contains_profile_related_fields = @@ -1381,7 +1380,7 @@ // Add devtools test addresses suggestion if it exists. A suggestion will // exist if devtools is open and therefore test addresses were set. if (std::optional<Suggestion> test_addresses_suggestion = - GetSuggestionForTestAddresses(personal_data_->test_addresses(), + GetSuggestionForTestAddresses(personal_data().test_addresses(), app_locale)) { suggestions.insert(suggestions.begin(), std::move(*test_addresses_suggestion)); @@ -1403,7 +1402,7 @@ std::vector<std::u16string> suggestion_main_text; for (const AutofillProfile* profile : matched_profiles) { suggestion_main_text.push_back(GetProfileSuggestionMainText( - *profile, personal_data_->app_locale(), trigger_field_type)); + *profile, personal_data().app_locale(), trigger_field_type)); } std::vector<raw_ptr<const AutofillProfile, VectorExperimental>> @@ -1413,7 +1412,7 @@ // very useful for the user). for (size_t a = 0; a < matched_profiles.size() && - unique_matched_profiles.size() < kMaxUniqueSuggestedProfilesCount; + unique_matched_profiles.size() < kMaxDeduplicatedProfilesForSuggestion; ++a) { bool include = true; const AutofillProfile* profile_a = matched_profiles[a]; @@ -1469,7 +1468,7 @@ bool field_is_autofilled) { std::vector<const AutofillProfile*> matched_profiles; for (const AutofillProfile* profile : profiles) { - if (matched_profiles.size() == kMaxSuggestedProfilesCount) { + if (matched_profiles.size() == kMaxPrefixMatchedProfilesForSuggestion) { break; } // Don't offer to fill the exact same value again. If detailed suggestions @@ -1484,7 +1483,7 @@ } #endif // BUILDFLAG(IS_ANDROID) std::u16string main_text = GetProfileSuggestionMainText( - *profile, personal_data_->app_locale(), trigger_field_type); + *profile, personal_data().app_locale(), trigger_field_type); // Discard profiles that do not have a value for the trigger field. if (main_text.empty()) { continue; @@ -1518,7 +1517,7 @@ Suggestion& suggestion) const { const FieldTypeGroup trigger_field_type_group = GroupTypeOfFieldType(trigger_field_type); - const std::string app_locale = personal_data_->app_locale(); + const std::string app_locale = personal_data().app_locale(); AddNameChildSuggestions(trigger_field_type_group, profile, app_locale, suggestion); AddAddressChildSuggestions(trigger_field_type_group, profile, app_locale, @@ -1543,7 +1542,7 @@ // Manual fallback entries are shown for all non credit card fields. const bool is_manual_fallback_for_non_credit_card_field = GroupTypeOfFieldType(trigger_field_type) != FieldTypeGroup::kCreditCard; - const std::string& app_locale = personal_data_->app_locale(); + const std::string& app_locale = personal_data().app_locale(); std::map<std::string, AutofillOfferData*> card_linked_offers_map = GetCardLinkedOffers(*autofill_client_); @@ -1761,17 +1760,13 @@ // static std::vector<CreditCard> AutofillSuggestionGenerator::GetOrderedCardsToSuggest( bool suppress_disused_cards) { - std::map<std::string, AutofillOfferData*> card_linked_offers_map = - GetCardLinkedOffers(*autofill_client_); - - const PersonalDataManager& personal_data = - CHECK_DEREF(autofill_client_->GetPersonalDataManager()); std::vector<CreditCard*> available_cards = - personal_data.GetCreditCardsToSuggest(); - + personal_data().GetCreditCardsToSuggest(); // If a card has available card linked offers on the last committed url, rank // it to the top. - if (!card_linked_offers_map.empty()) { + if (std::map<std::string, AutofillOfferData*> card_linked_offers_map = + GetCardLinkedOffers(*autofill_client_); + !card_linked_offers_map.empty()) { base::ranges::stable_sort( available_cards, [&card_linked_offers_map](const CreditCard* a, const CreditCard* b) { @@ -1779,7 +1774,6 @@ !base::Contains(card_linked_offers_map, b->guid()); }); } - // Suppress disused credit cards when triggered from an empty field. if (suppress_disused_cards) { const base::Time min_last_used = @@ -1788,7 +1782,6 @@ RemoveExpiredLocalCreditCardsNotUsedSinceTimestamp(min_last_used, available_cards); } - std::vector<CreditCard> cards_to_suggest; cards_to_suggest.reserve(available_cards.size()); for (const CreditCard* card : available_cards) { @@ -1911,7 +1904,7 @@ } // Either the card a) has no nickname or b) is a server card and we would // prefer to use the nickname of a local card. - std::vector<CreditCard*> candidates = personal_data_->GetCreditCards(); + std::vector<CreditCard*> candidates = personal_data().GetCreditCards(); for (CreditCard* candidate : candidates) { if (candidate->guid() != card.guid() && candidate->MatchingCardDetails(card) && @@ -1925,25 +1918,26 @@ bool AutofillSuggestionGenerator::ShouldShowVirtualCardOption( const CreditCard* candidate_card) const { + const CreditCard* candidate_server_card = nullptr; switch (candidate_card->record_type()) { case CreditCard::RecordType::kLocalCard: - candidate_card = - personal_data_->GetServerCardForLocalCard(candidate_card); - - // If we could not find a matching server duplicate, return false. - if (!candidate_card) { - return false; - } - ABSL_FALLTHROUGH_INTENDED; + candidate_server_card = + personal_data().GetServerCardForLocalCard(candidate_card); + break; case CreditCard::RecordType::kMaskedServerCard: - return ShouldShowVirtualCardOptionForServerCard(candidate_card); + candidate_server_card = candidate_card; + break; case CreditCard::RecordType::kFullServerCard: - return false; + break; case CreditCard::RecordType::kVirtualCard: // Should not happen since virtual card is not persisted. - NOTREACHED(); - return false; + NOTREACHED_NORETURN(); } + if (!candidate_server_card) { + return false; + } + candidate_card = candidate_server_card; + return ShouldShowVirtualCardOptionForServerCard(*candidate_server_card); } // TODO(crbug.com/1346331): Separate logic for desktop, Android dropdown, and @@ -2028,7 +2022,7 @@ void AutofillSuggestionGenerator::AddPaymentsGranularFillingChildSuggestions( const CreditCard& credit_card, Suggestion& suggestion) const { - const std::string& app_locale = personal_data_->app_locale(); + const std::string& app_locale = personal_data().app_locale(); bool has_content_above = AddCreditCardNameChildSuggestion(credit_card, app_locale, suggestion); @@ -2073,7 +2067,7 @@ #endif } else { main_text = - credit_card.GetInfo(trigger_field_type, personal_data_->app_locale()); + credit_card.GetInfo(trigger_field_type, personal_data().app_locale()); } return {Suggestion::Text(main_text, Suggestion::Text::IsPrimary(true), @@ -2089,7 +2083,7 @@ const CreditCard& credit_card, FieldType trigger_field_type, const url::Origin& origin) const { - const std::string& app_locale = personal_data_->app_locale(); + const std::string& app_locale = personal_data().app_locale(); // If the focused field is a card number field. if (trigger_field_type == CREDIT_CARD_NUMBER) { @@ -2159,7 +2153,7 @@ const url::Origin& origin) const { // Benefits are only displayed for app locale set to U.S. English. if (!base::FeatureList::IsEnabled(features::kAutofillEnableCardBenefits) || - personal_data_->app_locale() != "en-US") { + personal_data().app_locale() != "en-US") { return std::nullopt; } CreditCardBenefitBase::LinkedCardInstrumentId benefit_instrument_id( @@ -2167,7 +2161,7 @@ // 1. Check merchant benefit. std::optional<CreditCardMerchantBenefit> merchant_benefit = - personal_data_->GetMerchantBenefitByInstrumentIdAndOrigin( + personal_data().GetMerchantBenefitByInstrumentIdAndOrigin( benefit_instrument_id, origin); if (merchant_benefit && merchant_benefit->IsActiveBenefit()) { return GetBenefitTextWithTermsAppended( @@ -2182,7 +2176,7 @@ if (category_benefit_type != CreditCardCategoryBenefit::BenefitCategory::kUnknownBenefitCategory) { std::optional<CreditCardCategoryBenefit> category_benefit = - personal_data_->GetCategoryBenefitByInstrumentIdAndCategory( + personal_data().GetCategoryBenefitByInstrumentIdAndCategory( benefit_instrument_id, category_benefit_type); if (category_benefit && category_benefit->IsActiveBenefit()) { return GetBenefitTextWithTermsAppended( @@ -2192,7 +2186,7 @@ // 3. Check flat rate benefit. std::optional<CreditCardFlatRateBenefit> flat_rate_benefit = - personal_data_->GetFlatRateBenefitByInstrumentId(benefit_instrument_id); + personal_data().GetFlatRateBenefitByInstrumentId(benefit_instrument_id); if (flat_rate_benefit && flat_rate_benefit->IsActiveBenefit()) { return GetBenefitTextWithTermsAppended( flat_rate_benefit->benefit_description()); @@ -2209,7 +2203,7 @@ const url::Origin& origin) const { if (credit_card.record_type() == CreditCard::RecordType::kLocalCard) { const CreditCard* server_duplicate_card = - personal_data_->GetServerCardForLocalCard(&credit_card); + personal_data().GetServerCardForLocalCard(&credit_card); DCHECK(server_duplicate_card); suggestion.payload = Suggestion::Guid(server_duplicate_card->guid()); } @@ -2285,7 +2279,7 @@ Suggestion& suggestion, const CreditCard& credit_card, bool virtual_card_option) const { - const GURL card_art_url = personal_data_->GetCardArtURL(credit_card); + const GURL card_art_url = personal_data().GetCardArtURL(credit_card); if (card_art_url.is_empty() || !card_art_url.is_valid()) return; @@ -2306,7 +2300,7 @@ suggestion.custom_icon_url = card_art_url; #else gfx::Image* image = - personal_data_->GetCreditCardArtImageForUrl(card_art_url); + personal_data().GetCreditCardArtImageForUrl(card_art_url); if (image) { suggestion.custom_icon = *image; } @@ -2365,16 +2359,13 @@ } bool AutofillSuggestionGenerator::ShouldShowVirtualCardOptionForServerCard( - const CreditCard* card) const { - CHECK(card); - + const CreditCard& card) const { // If the card is not enrolled into virtual cards, we should not show a // virtual card suggestion for it. - if (card->virtual_card_enrollment_state() != + if (card.virtual_card_enrollment_state() != CreditCard::VirtualCardEnrollmentState::kEnrolled) { return false; } - // We should not show a suggestion for this card if the autofill // optimization guide returns that this suggestion should be blocked. if (auto* autofill_optimization_guide = @@ -2384,7 +2375,6 @@ card); return !blocked; } - // No conditions to prevent displaying a virtual card suggestion were // found, so return true. return true;
diff --git a/components/autofill/core/browser/autofill_suggestion_generator.h b/components/autofill/core/browser/autofill_suggestion_generator.h index 1c5664e6..7116783 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator.h +++ b/components/autofill/core/browser/autofill_suggestion_generator.h
@@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/check_deref.h" #include "base/containers/flat_map.h" #include "base/memory/raw_ptr.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" @@ -38,17 +39,7 @@ // address profile Autofill. class AutofillSuggestionGenerator { public: - // As of November 2018, displaying 10 suggestions cover at least 99% of the - // indices clicked by our users. The suggestions will also refine as they - // type. - static constexpr size_t kMaxUniqueSuggestedProfilesCount = 10; - - // As of November 2018, 50 profiles should be more than enough to cover at - // least 99% of all times the dropdown is shown. - static constexpr size_t kMaxSuggestedProfilesCount = 50; - - AutofillSuggestionGenerator(AutofillClient& autofill_client, - PersonalDataManager& personal_data); + explicit AutofillSuggestionGenerator(AutofillClient& autofill_client); ~AutofillSuggestionGenerator(); AutofillSuggestionGenerator(const AutofillSuggestionGenerator&) = delete; AutofillSuggestionGenerator& operator=(const AutofillSuggestionGenerator&) = @@ -134,10 +125,6 @@ // one copy has a nickname, take that. std::u16string GetDisplayNicknameForCreditCard(const CreditCard& card) const; - // Helper function to decide whether to show the virtual card option for - // `candidate_card`. - bool ShouldShowVirtualCardOption(const CreditCard* candidate_card) const; - private: friend class AutofillSuggestionGeneratorTestApi; @@ -186,9 +173,9 @@ // Dedupes the given profiles based on if one is a subset of the other for // suggestions represented by `field_types`. The function returns at most - // `kMaxUniqueSuggestedProfilesCount` profiles. `field_types` stores all of - // the FieldTypes relevant for the current suggestions, including that - // of the field on which the user is currently focused. + // `kMaxDeduplicatedProfilesForSuggestion` profiles. `field_types` stores all + // of the FieldTypes relevant for the current suggestions, including that of + // the field on which the user is currently focused. std::vector<raw_ptr<const AutofillProfile, VectorExperimental>> DeduplicatedProfilesForSuggestions( const std::vector<const AutofillProfile*>& matched_profiles, @@ -198,7 +185,7 @@ // Matches based on prefix search, and limits number of profiles. // Returns the top matching profiles based on prefix search. At most - // `kMaxSuggestedProfilesCount` are returned. + // `kMaxPrefixMatchedProfilesForSuggestion` are returned. std::vector<const AutofillProfile*> GetPrefixMatchedProfiles( const std::vector<AutofillProfile*>& profiles, FieldType trigger_field_type, @@ -283,16 +270,23 @@ bool is_autofilled, bool with_gpay_logo) const; + // Helper function to decide whether to show the virtual card option for + // `candidate_card`. + // TODO(b/326950201): Pass the argument by reference. + bool ShouldShowVirtualCardOption(const CreditCard* candidate_card) const; + // Returns true if we should show a virtual card option for the server card // `card`, false otherwise. - bool ShouldShowVirtualCardOptionForServerCard(const CreditCard* card) const; + bool ShouldShowVirtualCardOptionForServerCard(const CreditCard& card) const; + + const PersonalDataManager& personal_data() const { + // The PDM outlives the ASG, hence this is safe. + return *autofill_client_->GetPersonalDataManager(); + } // autofill_client_ and the generator are both one per tab, and have the same // lifecycle. base::raw_ref<AutofillClient> autofill_client_; - - // personal_data_ should outlive the generator. - base::raw_ref<PersonalDataManager> personal_data_; }; } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_test_api.h b/components/autofill/core/browser/autofill_suggestion_generator_test_api.h index 42485474..ddee2b2 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator_test_api.h +++ b/components/autofill/core/browser/autofill_suggestion_generator_test_api.h
@@ -55,6 +55,11 @@ card_linked_offer_available, origin); } + // TODO(b/326950201): Remove and use GetOrderedCardsToSuggest instead. + bool ShouldShowVirtualCardOption(const CreditCard* candidate_card) { + return suggestion_generator_->ShouldShowVirtualCardOption(candidate_card); + } + private: raw_ref<AutofillSuggestionGenerator> suggestion_generator_; };
diff --git a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc index 526ea458..6ea4aa8 100644 --- a/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc +++ b/components/autofill/core/browser/autofill_suggestion_generator_unittest.cc
@@ -185,8 +185,8 @@ /*strike_database=*/nullptr, /*image_fetcher=*/nullptr, /*shared_storage_handler=*/nullptr); - suggestion_generator_ = std::make_unique<AutofillSuggestionGenerator>( - autofill_client_, personal_data()); + suggestion_generator_ = + std::make_unique<AutofillSuggestionGenerator>(autofill_client_); autofill_client_.set_autofill_offer_manager( std::make_unique<AutofillOfferManager>( &personal_data(), @@ -344,9 +344,7 @@ // Therefore, we keep only the 10 first suggested profiles. TEST_F(AutofillSuggestionGeneratorTest, GetProfilesToSuggest_SuggestionsLimit) { std::vector<AutofillProfile> profiles; - for (size_t i = 0; - i < 2 * AutofillSuggestionGenerator::kMaxUniqueSuggestedProfilesCount; - i++) { + for (size_t i = 0; i < 2 * kMaxDeduplicatedProfilesForSuggestion; i++) { AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); test::SetProfileInfo(&profile, base::StringPrintf("Marion%zu", i).c_str(), "Mitchell", "Morrison", "johnwayne@me.xyz", "Fox", @@ -361,18 +359,16 @@ test_api(suggestion_generator()) .GetProfilesToSuggest(NAME_FIRST, u"Ma", false, {}); - ASSERT_EQ(2 * AutofillSuggestionGenerator::kMaxUniqueSuggestedProfilesCount, + ASSERT_EQ(2 * kMaxDeduplicatedProfilesForSuggestion, personal_data().GetProfiles().size()); - ASSERT_EQ(AutofillSuggestionGenerator::kMaxUniqueSuggestedProfilesCount, - suggested_profiles.size()); + ASSERT_EQ(kMaxDeduplicatedProfilesForSuggestion, suggested_profiles.size()); } // Deduping takes noticeable time when there are more than 50 profiles. // Therefore, keep only the 50 first pre-dedupe matching profiles. TEST_F(AutofillSuggestionGeneratorTest, GetProfilesToSuggest_ProfilesLimit) { std::vector<AutofillProfile> profiles; - for (size_t i = 0; - i < AutofillSuggestionGenerator::kMaxSuggestedProfilesCount; i++) { + for (size_t i = 0; i < kMaxPrefixMatchedProfilesForSuggestion; i++) { AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); test::SetProfileInfo( @@ -405,7 +401,7 @@ test_api(suggestion_generator()) .GetProfilesToSuggest(NAME_FIRST, u"Ma", false, {}); - ASSERT_EQ(AutofillSuggestionGenerator::kMaxSuggestedProfilesCount + 1, + ASSERT_EQ(kMaxPrefixMatchedProfilesForSuggestion + 1, personal_data().GetProfiles().size()); ASSERT_EQ(1U, suggested_profiles.size()); EXPECT_EQ(suggested_profiles.front()->GetRawInfo(NAME_FIRST), @@ -652,14 +648,11 @@ // Test the limit of number of deduplicated profiles. TEST_F(AutofillSuggestionGeneratorTest, GetProfilesToSuggest_DedupeLimit) { std::vector<AutofillProfile> profiles; - for (size_t i = 0; - i < AutofillSuggestionGenerator::kMaxUniqueSuggestedProfilesCount + 1; - i++) { + for (size_t i = 0; i < kMaxDeduplicatedProfilesForSuggestion + 1; i++) { AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); profile.SetRawInfo(NAME_FULL, base::UTF8ToUTF16(base::StringPrintf("Bob %zu Doe", i))); - profile.set_use_count( - AutofillSuggestionGenerator::kMaxUniqueSuggestedProfilesCount + 10 - i); + profile.set_use_count(kMaxDeduplicatedProfilesForSuggestion + 10 - i); profiles.push_back(profile); personal_data().AddProfile(profile); } @@ -670,8 +663,7 @@ .GetProfilesToSuggest(NAME_FULL, u"", /*field_is_autofilled=*/false, {NAME_FULL}); - ASSERT_EQ(AutofillSuggestionGenerator::kMaxUniqueSuggestedProfilesCount, - profiles_to_suggest.size()); + ASSERT_EQ(kMaxDeduplicatedProfilesForSuggestion, profiles_to_suggest.size()); // All profiles are different. for (size_t i = 0; i < profiles_to_suggest.size(); i++) { @@ -2813,8 +2805,10 @@ CreateLocalCard(/*guid=*/"00000000-0000-0000-0000-000000000002"); // If all prerequisites are met, it should return true. - EXPECT_TRUE(suggestion_generator().ShouldShowVirtualCardOption(&server_card)); - EXPECT_TRUE(suggestion_generator().ShouldShowVirtualCardOption(&local_card)); + EXPECT_TRUE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&server_card)); + EXPECT_TRUE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&local_card)); } // Test that the virtual card option is shown when the autofill optimization @@ -2834,8 +2828,10 @@ CreateLocalCard(/*guid=*/"00000000-0000-0000-0000-000000000002"); // If all prerequisites are met, it should return true. - EXPECT_TRUE(suggestion_generator().ShouldShowVirtualCardOption(&server_card)); - EXPECT_TRUE(suggestion_generator().ShouldShowVirtualCardOption(&local_card)); + EXPECT_TRUE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&server_card)); + EXPECT_TRUE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&local_card)); } // Test that the virtual card option is not shown if the merchant is opted-out @@ -2859,9 +2855,10 @@ ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(optimization_guide), ShouldBlockFormFieldSuggestion) .WillByDefault(testing::Return(true)); - EXPECT_FALSE( - suggestion_generator().ShouldShowVirtualCardOption(&server_card)); - EXPECT_FALSE(suggestion_generator().ShouldShowVirtualCardOption(&local_card)); + EXPECT_FALSE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&server_card)); + EXPECT_FALSE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&local_card)); } // Test that the virtual card option is not shown if the server card we might be @@ -2881,9 +2878,10 @@ // For server card not enrolled, both local and server card should return // false. - EXPECT_FALSE( - suggestion_generator().ShouldShowVirtualCardOption(&server_card)); - EXPECT_FALSE(suggestion_generator().ShouldShowVirtualCardOption(&local_card)); + EXPECT_FALSE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&server_card)); + EXPECT_FALSE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&local_card)); } // Test that the virtual card option is not shown for a local card with no @@ -2895,7 +2893,8 @@ CreateLocalCard(/*guid=*/"00000000-0000-0000-0000-000000000002"); // The local card does not have a server duplicate, should return false. - EXPECT_FALSE(suggestion_generator().ShouldShowVirtualCardOption(&local_card)); + EXPECT_FALSE(test_api(suggestion_generator()) + .ShouldShowVirtualCardOption(&local_card)); } TEST_F(AutofillSuggestionGeneratorTest, GetLocalIbanSuggestions) {
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index b98f1d2..104ea13 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -266,6 +266,7 @@ case PopupItemId::kAutofillOptions: case PopupItemId::kClearForm: case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: case PopupItemId::kCreateNewPlusAddress: case PopupItemId::kCreditCardEntry: case PopupItemId::kDatalistEntry: @@ -437,6 +438,31 @@ return random_value_per_session < kSamplingRate; } +// Returns true if the source is only relevant for Compose. +bool IsTriggerSourceOnlyRelevantForCompose( + AutofillSuggestionTriggerSource source) { + switch (source) { + case AutofillSuggestionTriggerSource::kTextareaFocusedWithoutClick: + case AutofillSuggestionTriggerSource::kComposeDialogLostFocus: + return true; + case AutofillSuggestionTriggerSource::kUnspecified: + case AutofillSuggestionTriggerSource::kFormControlElementClicked: + case AutofillSuggestionTriggerSource::kContentEditableClicked: + case AutofillSuggestionTriggerSource::kTextFieldDidChange: + case AutofillSuggestionTriggerSource::kTextFieldDidReceiveKeyDown: + case AutofillSuggestionTriggerSource::kOpenTextDataListChooser: + case AutofillSuggestionTriggerSource::kShowCardsFromAccount: + case AutofillSuggestionTriggerSource::kPasswordManager: + case AutofillSuggestionTriggerSource::kiOS: + case AutofillSuggestionTriggerSource::kManualFallbackAddress: + case AutofillSuggestionTriggerSource::kManualFallbackPayments: + case AutofillSuggestionTriggerSource::kManualFallbackPasswords: + case AutofillSuggestionTriggerSource:: + kShowPromptAfterDialogClosedNonManualFallback: + return false; + } +} + } // namespace BrowserAutofillManager::BrowserAutofillManager(AutofillDriver* driver, @@ -445,9 +471,8 @@ : AutofillManager(driver, client), external_delegate_(std::make_unique<AutofillExternalDelegate>(this)), app_locale_(app_locale), - suggestion_generator_(std::make_unique<AutofillSuggestionGenerator>( - *client, - *client->GetPersonalDataManager())), + suggestion_generator_( + std::make_unique<AutofillSuggestionGenerator>(*client)), form_filler_( std::make_unique<FormFiller>(*this, log_manager(), app_locale)) { address_form_event_logger_ = @@ -1054,7 +1079,7 @@ (field.form_control_type == FormControlType::kTextArea || field.form_control_type == FormControlType::kContentEditable)) { if (std::optional<Suggestion> maybe_compose_suggestion = - MaybeGetComposeSuggestion(field)) { + MaybeGetComposeSuggestion(field, trigger_source)) { suggestions.push_back(*std::move(maybe_compose_suggestion)); } } @@ -2337,10 +2362,8 @@ DCHECK(suggestions); DCHECK(context); - // This trigger source is only relevant for Compose, for which suggestions - // are not populated here. - if (trigger_source == - AutofillSuggestionTriggerSource::kTextareaFocusedWithoutClick) { + // Compose suggestions are not populated in this method. + if (IsTriggerSourceOnlyRelevantForCompose(trigger_source)) { return; } @@ -2664,19 +2687,25 @@ } std::optional<Suggestion> BrowserAutofillManager::MaybeGetComposeSuggestion( - const FormFieldData& field) { + const FormFieldData& field, + AutofillSuggestionTriggerSource trigger_source) { AutofillComposeDelegate* compose_delegate = client().GetComposeDelegate(); if (!compose_delegate || !compose_delegate->ShouldOfferComposePopup(field)) { return std::nullopt; } std::u16string suggestion_text; std::u16string label_text; + PopupItemId popup_item_id = PopupItemId::kCompose; if (compose_delegate->HasSavedState(field.global_id())) { // The nudge text indicates that the user can resume where they left off in // the Compose dialog. suggestion_text = l10n_util::GetStringUTF16(IDS_COMPOSE_SUGGESTION_SAVED_TEXT); label_text = l10n_util::GetStringUTF16(IDS_COMPOSE_SUGGESTION_SAVED_LABEL); + if (trigger_source == + AutofillSuggestionTriggerSource::kComposeDialogLostFocus) { + popup_item_id = PopupItemId::kComposeSavedStateNotification; + } } else { // Text for a new Compose session. suggestion_text = @@ -2685,7 +2714,7 @@ } Suggestion suggestion(std::move(suggestion_text)); suggestion.labels = {{Suggestion::Text(std::move(label_text))}}; - suggestion.popup_item_id = PopupItemId::kCompose; + suggestion.popup_item_id = popup_item_id; suggestion.icon = Suggestion::Icon::kPenSpark; return suggestion; }
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h index afa16cf3..6cd345dd 100644 --- a/components/autofill/core/browser/browser_autofill_manager.h +++ b/components/autofill/core/browser/browser_autofill_manager.h
@@ -531,9 +531,10 @@ bool ShouldUploadUkm(const FormStructure& form_structure); // Returns a compose suggestion if the compose service is available for - // `field`. + // `field` and `trigger_source`. std::optional<Suggestion> MaybeGetComposeSuggestion( - const FormFieldData& field); + const FormFieldData& field, + AutofillSuggestionTriggerSource trigger_source); // Delegates to perform external processing (display, selection) on // our behalf.
diff --git a/components/autofill/core/browser/data_model/phone_number.h b/components/autofill/core/browser/data_model/phone_number.h index b78ac1b..9694cf8 100644 --- a/components/autofill/core/browser/data_model/phone_number.h +++ b/components/autofill/core/browser/data_model/phone_number.h
@@ -18,6 +18,35 @@ class AutofillProfile; // A form group that stores phone number information. +// +// The behavior of PhoneNumber is quite complex because of different +// representations of phone numbers (national and international formats) and the +// number of field types. See components/autofill/core/browser/field_types.h for +// an introduction to the semantic field types. +// +// The PhoneNumber/PhoneImportAndGetTest.TestSettingAndParsing unittests may be +// best to see the exact behavior of learning phone numbers from submitted forms +// and filling phone numbers into new forms. +// +// If no country code is submitted (as a separate PHONE_HOME_COUNTRY_CODE field +// or as part of a PHONE_HOME_WHOLE_NUMBER or PHONE_HOME_CITY_AND_NUMBER) at +// form submission time, no attempt is made to save one. As a consequence, we +// cannot fill country code fields nor international phone number fields with +// the country code. See b/322330285. +// +// Phone numbers of form submissions are validated by libphonenumber for +// plausibility before getting saved (in the context of the country, which is +// the first of 1) country in the form, 2) country of GeoIP, 3) country of +// locale). Phone numbers from form submissions are stored in a formatted way +// unless they were submitted in a PHONE_HOME_WHOLE_NUMBER field and already +// contained formatting characters (whitespaces, parentheses, slashes, hyphens, +// ...). +// +// At filling time, the stored number is interpreted and, if successful, the +// relevant pieces are returned. The values used for filling consist only of +// [+0123456789]. Whitespaces, parentheses, slashes, hyphens, ... are stripped. +// International numbers filled as PHONE_HOME_WHOLE_NUMBER start with a + in all +// countries but the US, where the + is dropped. class PhoneNumber : public FormGroup { public: explicit PhoneNumber(const AutofillProfile* profile);
diff --git a/components/autofill/core/browser/data_model/phone_number_unittest.cc b/components/autofill/core/browser/data_model/phone_number_unittest.cc index 7fc4ab4..3eeebd9 100644 --- a/components/autofill/core/browser/data_model/phone_number_unittest.cc +++ b/components/autofill/core/browser/data_model/phone_number_unittest.cc
@@ -38,6 +38,7 @@ const std::u16string& country, bool trunk_types_enabled, const std::vector<MatchingTypesTestCase>& tests) { + SCOPED_TRACE(::testing::Message() << "number: " << number); base::test::ScopedFeatureList trunk_types; trunk_types.InitWithFeatureState( features::kAutofillEnableSupportForPhoneNumberTrunkTypes, @@ -49,6 +50,7 @@ // `kLocale` is irrelevant, because `profile` has country information. phone_number.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), number, kLocale); for (const MatchingTypesTestCase& test : tests) { + SCOPED_TRACE(::testing::Message() << "test.input: " << test.input); FieldTypeSet matching_types; phone_number.GetMatchingTypes(test.input, kLocale, &matching_types); EXPECT_EQ(matching_types, test.expected_types); @@ -75,6 +77,75 @@ {u"2345", {}}, {u"6502345678", {PHONE_HOME_CITY_AND_NUMBER}}, {u"(650)2345678", {PHONE_HOME_CITY_AND_NUMBER}}}); + // Set phone number so city_code = 650, number = 2345678. + MatchingTypesTest(u"650 234-5678", u"US", + /*trunk_types_enabled=*/false, + {{std::u16string(), {EMPTY_TYPE}}, + {u"1", {}}, + {u"16", {}}, + {u"165", {}}, + {u"1650", {}}, + {u"16502", {}}, + {u"165023", {}}, + {u"1650234", {}}, + // The international number is not recognized. + {u"16502345678", {}}, + {u"650", {PHONE_HOME_CITY_CODE}}, + {u"2345678", {PHONE_HOME_NUMBER}}, + {u"234", {PHONE_HOME_NUMBER_PREFIX}}, + {u"5678", {PHONE_HOME_NUMBER_SUFFIX}}, + {u"2345", {}}, + {u"6502345678", {PHONE_HOME_CITY_AND_NUMBER}}, + {u"(650)2345678", {PHONE_HOME_CITY_AND_NUMBER}}}); +} + +TEST(PhoneNumberTest, Matcher_TrunkTypes) { + // The following tests the same numbers as above but with trunk_types_enabled + // = true; + + // Set phone number so country_code == 1, city_code = 650, number = 2345678. + MatchingTypesTest( + u"1 [650] 234-5678", u"US", + /*trunk_types_enabled=*/true, + {{u"1", {PHONE_HOME_COUNTRY_CODE}}, + {u"+1", {PHONE_HOME_COUNTRY_CODE}}, + {u"(+1) United States", {PHONE_HOME_COUNTRY_CODE}}, + {u"US (+1)", {PHONE_HOME_COUNTRY_CODE}}, + {u"16502345678", {PHONE_HOME_WHOLE_NUMBER}}, + // The following has a different expectation if + // trunk_types_enabled = true + {u"650", {PHONE_HOME_CITY_CODE, PHONE_HOME_CITY_CODE_WITH_TRUNK_PREFIX}}, + {u"2345678", {PHONE_HOME_NUMBER}}, + {u"234", {PHONE_HOME_NUMBER_PREFIX}}, + {u"5678", {PHONE_HOME_NUMBER_SUFFIX}}, + // The following two have different expectations if + // trunk_types_enabled = true. + {u"6502345678", + {PHONE_HOME_CITY_AND_NUMBER, + PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}, + {u"(650)2345678", + {PHONE_HOME_CITY_AND_NUMBER, + PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}}); + // Set phone number so city_code = 650, number = 2345678. + MatchingTypesTest( + u"650 234-5678", u"US", + /*trunk_types_enabled=*/true, + {{u"1", {}}, + {u"+1", {}}, + {u"(+1) United States", {}}, + {u"US (+1)", {}}, + // The international number is not recognized. + {u"16502345678", {}}, + {u"650", {PHONE_HOME_CITY_CODE, PHONE_HOME_CITY_CODE_WITH_TRUNK_PREFIX}}, + {u"2345678", {PHONE_HOME_NUMBER}}, + {u"234", {PHONE_HOME_NUMBER_PREFIX}}, + {u"5678", {PHONE_HOME_NUMBER_SUFFIX}}, + {u"6502345678", + {PHONE_HOME_CITY_AND_NUMBER, + PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}, + {u"(650)2345678", + {PHONE_HOME_CITY_AND_NUMBER, + PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}}); } TEST(PhoneNumberTest, Matcher_DisambiguateWholeNumber) { @@ -88,34 +159,106 @@ PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}}); } -// Verify that the derived types of German numbers are correct. -TEST(PhoneNumberTest, Matcher_DE) { - MatchingTypesTest(u"+491741234567", u"DE", +// Tests that the |PHONE_HOME_COUNTRY_CODE| should not be added to the set of +// matching types. +TEST(PhoneNumberTest, CountryCodeNotInMatchingTypes) { + MatchingTypesTest(u"1 [650] 234-5678", u"US", /*trunk_types_enabled=*/false, - {{u"+491741234567", {PHONE_HOME_WHOLE_NUMBER}}, - {u"01741234567", {PHONE_HOME_CITY_AND_NUMBER}}, - {u"1234567", {PHONE_HOME_NUMBER}}, - {u"174", {PHONE_HOME_CITY_CODE}}}); + {{u"01", {}}, + {u"+16502", {}}, + {u"11", {}}, + {u"211", {}}, + {u"0001", {}}, + {u"++1", {}}, + {u"+1abc2", {}}, + {u"001abc2", {}}, + {u"01", {}}}); } -TEST(PhoneNumberTest, Matcher_TrunkTypes) { - MatchingTypesTest( - u"1 [650] 234-5678", u"US", - /*trunk_types_enabled=*/true, - {{u"650", {PHONE_HOME_CITY_CODE, PHONE_HOME_CITY_CODE_WITH_TRUNK_PREFIX}}, - {u"6502345678", - {PHONE_HOME_CITY_AND_NUMBER, - PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}}); +// Verify that the derived types of German numbers are correct. +TEST(PhoneNumberTest, Matcher_DE) { + // Crowdsourcing is broken. A number of cases are very surprising. + MatchingTypesTest(u"+491741234567", u"DE", + /*trunk_types_enabled=*/false, + { + {u"49", {PHONE_HOME_COUNTRY_CODE}}, + {u"+49", {PHONE_HOME_COUNTRY_CODE}}, + {u"0049", {PHONE_HOME_COUNTRY_CODE}}, + {u"(+49) DE", {PHONE_HOME_COUNTRY_CODE}}, + {u"(0049) DE", {PHONE_HOME_COUNTRY_CODE}}, + {u"174", {PHONE_HOME_CITY_CODE}}, + // TODO(crbug.com/40220393): This should match + // PHONE_HOME_CITY_CODE! + {u"0174", {}}, + {u"1234567", {PHONE_HOME_NUMBER}}, + // TODO(crbug.com/40220393): This should match + // PHONE_HOME_CITY_AND_NUMBER! + {u"1741234567", {}}, + {u"01741234567", {PHONE_HOME_CITY_AND_NUMBER}}, + {u"(0174)1234567", {PHONE_HOME_CITY_AND_NUMBER}}, + {u"0174 1234567", {PHONE_HOME_CITY_AND_NUMBER}}, + {u"+491741234567", {PHONE_HOME_WHOLE_NUMBER}}, + {u"00491741234567", {PHONE_HOME_WHOLE_NUMBER}}, + {u"004901741234567", {PHONE_HOME_WHOLE_NUMBER}}, + }); + MatchingTypesTest(u"0174 1234567", u"DE", + /*trunk_types_enabled=*/false, + { + {u"49", {}}, + {u"+49", {}}, + {u"0049", {}}, + {u"(+49) DE", {}}, + {u"(0049) DE", {}}, + {u"174", {PHONE_HOME_CITY_CODE}}, + {u"0174", {}}, + {u"1234567", {PHONE_HOME_NUMBER}}, + {u"01741234567", {PHONE_HOME_CITY_AND_NUMBER}}, + {u"(0174)1234567", {PHONE_HOME_CITY_AND_NUMBER}}, + {u"0174 1234567", {PHONE_HOME_CITY_AND_NUMBER}}, + // The international phone number is unknown. + {u"+491741234567", {}}, + {u"00491741234567", {}}, + {u"004901741234567", {}}, + }); } TEST(PhoneNumberTest, Matcher_TrunkTypes_DE) { MatchingTypesTest( u"+491741234567", u"DE", /*trunk_types_enabled=*/true, - {{u"174", {PHONE_HOME_CITY_CODE}}, - {u"0174", {PHONE_HOME_CITY_CODE_WITH_TRUNK_PREFIX}}, - {u"1741234567", {PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}, - {u"01741234567", {PHONE_HOME_CITY_AND_NUMBER}}}); + { + {u"49", {PHONE_HOME_COUNTRY_CODE}}, + {u"+49", {PHONE_HOME_COUNTRY_CODE}}, + {u"0049", {PHONE_HOME_COUNTRY_CODE}}, + {u"174", {PHONE_HOME_CITY_CODE}}, + {u"0174", {PHONE_HOME_CITY_CODE_WITH_TRUNK_PREFIX}}, + {u"1234567", {PHONE_HOME_NUMBER}}, + {u"1741234567", {PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX}}, + {u"01741234567", {PHONE_HOME_CITY_AND_NUMBER}}, + {u"+491741234567", {PHONE_HOME_WHOLE_NUMBER}}, + {u"00491741234567", {PHONE_HOME_WHOLE_NUMBER}}, + {u"004901741234567", {PHONE_HOME_WHOLE_NUMBER}}, + }); + MatchingTypesTest(u"0174 1234567", u"DE", + /*trunk_types_enabled=*/true, + { + {u"49", {}}, + {u"+49", {}}, + {u"0049", {}}, + {u"174", {PHONE_HOME_CITY_CODE}}, + {u"0174", {PHONE_HOME_CITY_CODE_WITH_TRUNK_PREFIX}}, + {u"1234567", {PHONE_HOME_NUMBER}}, + // TODO(crbug.com/40220393): Should this really vote for + // PHONE_HOME_WHOLE_NUMBER? + {u"1741234567", + {PHONE_HOME_CITY_AND_NUMBER_WITHOUT_TRUNK_PREFIX, + PHONE_HOME_WHOLE_NUMBER}}, + {u"01741234567", {PHONE_HOME_CITY_AND_NUMBER}}, + // The international phone number is unknown. + {u"+491741234567", {}}, + {u"00491741234567", {}}, + {u"004901741234567", {}}, + }); } // Verify that `PhoneNumber::SetInfo()` correctly formats the incoming number. @@ -239,53 +382,25 @@ } TEST(PhoneNumberTest, PhoneCombineHelper) { + // PhoneCombineHelper is largely covered via PhoneImportAndGetTest. This + // just tests some remaining edge cases: + + // Check that `SetInfo` fails for an address country (rather than a + // phone country): AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US"); - PhoneNumber::PhoneCombineHelper number1; EXPECT_FALSE(number1.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), u"1")); - EXPECT_TRUE(number1.SetInfo(AutofillType(PHONE_HOME_COUNTRY_CODE), u"1")); - EXPECT_TRUE(number1.SetInfo(AutofillType(PHONE_HOME_CITY_CODE), u"650")); - EXPECT_TRUE(number1.SetInfo(AutofillType(PHONE_HOME_NUMBER), u"2345678")); - std::u16string parsed_phone; - EXPECT_TRUE(number1.ParseNumber(profile, kLocale, &parsed_phone)); - // International format as it has a country code. - EXPECT_EQ(u"1 650-234-5678", parsed_phone); - - PhoneNumber::PhoneCombineHelper number3; - EXPECT_TRUE(number3.SetInfo(AutofillType(PHONE_HOME_CITY_CODE), u"650")); - EXPECT_TRUE(number3.SetInfo(AutofillType(PHONE_HOME_NUMBER), u"2345680")); - EXPECT_TRUE(number3.ParseNumber(profile, kLocale, &parsed_phone)); - // National format as it does not have a country code. - EXPECT_EQ(u"(650) 234-5680", parsed_phone); - - PhoneNumber::PhoneCombineHelper number4; - EXPECT_TRUE(number4.SetInfo(AutofillType(PHONE_HOME_CITY_CODE), - u"123")); // Incorrect city code. - EXPECT_TRUE(number4.SetInfo(AutofillType(PHONE_HOME_NUMBER), u"2345680")); - EXPECT_TRUE(number4.ParseNumber(profile, kLocale, &parsed_phone)); - EXPECT_EQ(u"1232345680", parsed_phone); - - PhoneNumber::PhoneCombineHelper number5; - EXPECT_TRUE( - number5.SetInfo(AutofillType(PHONE_HOME_CITY_AND_NUMBER), u"6502345681")); - EXPECT_TRUE(number5.ParseNumber(profile, kLocale, &parsed_phone)); - EXPECT_EQ(u"(650) 234-5681", parsed_phone); - - PhoneNumber::PhoneCombineHelper number6; - EXPECT_TRUE(number6.SetInfo(AutofillType(PHONE_HOME_CITY_CODE), u"650")); - EXPECT_TRUE(number6.SetInfo(AutofillType(PHONE_HOME_NUMBER_PREFIX), u"234")); - EXPECT_TRUE(number6.SetInfo(AutofillType(PHONE_HOME_NUMBER_SUFFIX), u"5682")); - EXPECT_TRUE(number6.ParseNumber(profile, kLocale, &parsed_phone)); - EXPECT_EQ(u"(650) 234-5682", parsed_phone); // Ensure parsing is possible when falling back to detecting the country code // based on the app locale. - PhoneNumber::PhoneCombineHelper number7; - EXPECT_TRUE(number7.SetInfo(AutofillType(PHONE_HOME_CITY_CODE), u"650")); - EXPECT_TRUE(number7.SetInfo(AutofillType(PHONE_HOME_NUMBER_PREFIX), u"234")); - EXPECT_TRUE(number7.SetInfo(AutofillType(PHONE_HOME_NUMBER_SUFFIX), u"5682")); - EXPECT_TRUE(number7.ParseNumber( + std::u16string parsed_phone; + PhoneNumber::PhoneCombineHelper number2; + EXPECT_TRUE(number2.SetInfo(AutofillType(PHONE_HOME_CITY_CODE), u"650")); + EXPECT_TRUE(number2.SetInfo(AutofillType(PHONE_HOME_NUMBER_PREFIX), u"234")); + EXPECT_TRUE(number2.SetInfo(AutofillType(PHONE_HOME_NUMBER_SUFFIX), u"5682")); + EXPECT_TRUE(number2.ParseNumber( + // No country code is specified here: AutofillProfile(i18n_model_definition::kLegacyHierarchyCountryCode), kLocale, &parsed_phone)); EXPECT_EQ(u"(650) 234-5682", parsed_phone); @@ -450,71 +565,433 @@ EXPECT_TRUE(phone.GetInfo(PHONE_HOME_EXTENSION, locale).empty()); } -// Tests whether the |PHONE_HOME_COUNTRY_CODE| is added to the set of matching -// types. -TEST(PhoneNumberTest, CountryCodeInMatchingTypes) { +// The PhoneImportAndGetTest testcases simulate the steps of observing a phone +// number submission on a website (possibly spread over multiple fields) which +// is imported into an address profile, and retrieving the values that would be +// filled into a website. +// Importing a phone number actually happens in +// FormDataImporter::SetPhoneNumber, which is out of scope for this test but so +// small that we replicate it in the test. +struct PhoneImportAndGetTestCase { + struct FieldTypeAndValue { + FieldType field_type; + std::u16string value; + }; + + // Field type / field value pairs that represent the values a user submits + // on a form. + std::vector<FieldTypeAndValue> observed_fields; + // The default region assumed for parsing. In real executions this is derived + // from the form, a GeoIP or the locale. + std::u16string default_country; + // The value that is persisted on disk, shown in save prompts and on + // chrome://settings/addresses (the "raw value"). + std::u16string expected_stored_number; + + // The values we expect to get at filling time + std::vector<FieldTypeAndValue> expected_values; +}; + +class PhoneImportAndGetTest + : public ::testing::TestWithParam<PhoneImportAndGetTestCase> {}; + +TEST_P(PhoneImportAndGetTest, TestSettingAndParsing) { + const PhoneImportAndGetTestCase& test = GetParam(); + + SCOPED_TRACE(::testing::Message() << [&] { + std::ostringstream result; + result << "observed_fields:\n"; + for (const auto& [field_type, value] : test.observed_fields) { + result << FieldTypeToStringView(field_type) << ": " << value << "\n"; + } + result << "default_country: " << test.default_country << "\n"; + result << "expected_stored_number: " << test.expected_stored_number << "\n"; + return result.str(); + }()); + AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US"); - // Set the phone number such that country_code == 1, city_code = 650, - // number = 2345678. - std::u16string phone(u"1 [650] 234-5678"); - PhoneNumber phone_number(&profile); - phone_number.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), phone, "US"); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, test.default_country); - std::vector<const char*> test_cases = {"+1", "1", "(+1) United States", - "US (+1)"}; - - for (size_t i = 0; i < test_cases.size(); i++) { - SCOPED_TRACE(testing::Message() << "i(US) = " << i); - - FieldTypeSet matching_types; - phone_number.GetMatchingTypes(ASCIIToUTF16(test_cases[i]), "US", - &matching_types); - - EXPECT_THAT(matching_types, testing::ElementsAre(PHONE_HOME_COUNTRY_CODE)); + // The locale currently plays no role in the test because the profile contains + // a country. This just stays here to be as close as possible to actual user + // experiences. + std::string faked_app_locale; + if (test.default_country == u"DE") { + faked_app_locale = "de_DE"; + } else if (test.default_country == u"US") { + faked_app_locale = "en_US"; + } else { + ASSERT_TRUE(false); } - profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"DE"); - std::u16string de_phone(u"+49 0151 6679586"); - PhoneNumber phone_number_de(&profile); - constexpr char kLocaleDE[] = "de_DE"; - phone_number_de.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), de_phone, - kLocaleDE); + // Gather all data in the PhoneCombineHelper. + PhoneNumber::PhoneCombineHelper number; + for (const auto& [field_type, value] : test.observed_fields) { + EXPECT_TRUE(number.SetInfo(AutofillType(field_type), value)); + } - test_cases = {"49", "+49", "(+49) DE", "(0049) DE", "0049"}; - for (size_t i = 0; i < test_cases.size(); i++) { - SCOPED_TRACE(testing::Message() << "i(DE) = " << i); + // Step 1 of 2 in FormDataImporter::SetPhoneNumber: parsing the number + std::u16string parsed_phone; + ASSERT_TRUE(number.ParseNumber(profile, faked_app_locale, &parsed_phone)); - FieldTypeSet matching_types; - phone_number_de.GetMatchingTypes(ASCIIToUTF16(test_cases[i]), kLocaleDE, - &matching_types); + // Step 2 of 2 in FormDataImporter::SetPhoneNumber: persisting the number + EXPECT_TRUE(profile.SetInfoWithVerificationStatus( + PHONE_HOME_WHOLE_NUMBER, parsed_phone, faked_app_locale, + VerificationStatus::kObserved)); - EXPECT_THAT(matching_types, testing::ElementsAre(PHONE_HOME_COUNTRY_CODE)); + // Verify that the raw value stored is as expected. + EXPECT_EQ(test.expected_stored_number, + profile.GetRawInfo(PHONE_HOME_WHOLE_NUMBER)); + + // Verify the values that would be filled on webforms. + for (const auto& [field_type, expected_value] : test.expected_values) { + SCOPED_TRACE(::testing::Message() + << "GetInfo(" << FieldTypeToStringView(field_type) << ")"); + EXPECT_EQ(expected_value, profile.GetInfo(field_type, faked_app_locale)); } } -// Tests that the |PHONE_HOME_COUNTRY_CODE| should not be added to the set of -// matching types. -TEST(PhoneNumberTest, CountryCodeNotInMatchingTypes) { - AutofillProfile profile(i18n_model_definition::kLegacyHierarchyCountryCode); - profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US"); - // Set phone number so country_code == 1, city_code = 650, number = 2345678. - std::u16string phone(u"1 [650] 234-5678"); - PhoneNumber phone_number(&profile); - phone_number.SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), phone, kLocale); +INSTANTIATE_TEST_SUITE_P( + PhoneNumber, + PhoneImportAndGetTest, + testing::Values( + // If a country code is set, the number is stored in international + // format. + PhoneImportAndGetTestCase{ + // The values a user submits on a form. + .observed_fields = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345678"}}, + // The country of the address profile and also the locale used for + // the test. + .default_country = u"US", + // What's stored on disk. + .expected_stored_number = u"1 650-234-5678", + // What's returned from GetInfo for filling. + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345678"}, + // GetInfo strips special symbols and + // whitespaces. + {PHONE_HOME_WHOLE_NUMBER, u"16502345678"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345678"}}}, + // If a number is given as city code and local number but does not have + // a country code, the phone number is stored in national format. The + // country code is not inferred. + // This is not ideal (see b/322330285) because we cannot fill country + // codes for such a number, nor can we fill a phone number in + // international format. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345680"}}, + .default_country = u"US", + .expected_stored_number = u"(650) 234-5680", + .expected_values = {{// No country code was set. + PHONE_HOME_COUNTRY_CODE, u""}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345680"}, + // Whole number is in national format because no + // country code was set. + {PHONE_HOME_WHOLE_NUMBER, u"6502345680"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345680"}}}, + // If the city code is incorrect, the phone number cannot be interpreted + // and is just stored as a sequence of digits. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_CODE, u"123"}, + {PHONE_HOME_NUMBER, u"2345680"}}, + .default_country = u"US", + .expected_stored_number = u"1232345680", + .expected_values = {{// No country code was set. + PHONE_HOME_COUNTRY_CODE, u""}, + {PHONE_HOME_CITY_CODE, u""}, + // Because the areacode is invalid the entire + // number is interpreted as a local number and + // also returned for PHONE_HOME_WHOLE_NUMBER and + // PHONE_HOME_CITY_AND_NUMBER. + {PHONE_HOME_NUMBER, u"1232345680"}, + {PHONE_HOME_WHOLE_NUMBER, u"1232345680"}, + {PHONE_HOME_CITY_AND_NUMBER, u"1232345680"}}}, + // If the phone number is submitted as PHONE_HOME_CITY_AND_NUMBER, + // the persisted internal value is a formatted national number. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"6502345681"}}, + .default_country = u"US", + .expected_stored_number = u"(650) 234-5681", + // .expected_values were already covered for this format above. + }, - std::vector<const char*> test_cases = { - "01", "+16502", "11", "211", "0001", "++1", "+1abc2", "001abc2", "01"}; + // If the phone number is submitted as city code, number and prefix, + // the persisted internal value is a formatted national number. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER_PREFIX, u"234"}, + {PHONE_HOME_NUMBER_SUFFIX, u"5682"}}, + .default_country = u"US", + .expected_stored_number = u"(650) 234-5682", + // .expected_values were already covered for this format above. + }, - for (size_t i = 0; i < test_cases.size(); i++) { - SCOPED_TRACE(testing::Message() << "i = " << i); + // If the phone number is submitted as a PHONE_HOME_CITY_AND_NUMBER in + // international format (with or without a +), it is stored as a + // formatted international number. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"+16502345681"}}, + .default_country = u"US", + .expected_stored_number = u"1 650-234-5681", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345681"}, + {PHONE_HOME_WHOLE_NUMBER, u"16502345681"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345681"}}}, + PhoneImportAndGetTestCase{ + // Same number as above but without a leading +. + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"16502345681"}}, + .default_country = u"US", + .expected_stored_number = u"1 650-234-5681", + // Same expectations as above. + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345681"}, + {PHONE_HOME_WHOLE_NUMBER, u"16502345681"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345681"}}}, - FieldTypeSet matching_types; - phone_number.GetMatchingTypes(ASCIIToUTF16(test_cases[i]), kLocale, - &matching_types); + // If the phone number is submitted as a PHONE_HOME_WHOLE_NUMBER in + // international format (with or without a +) and the user DID NOT + // add formatting characters (space, parentheses), the values are + // formatted. + // The values filled on websites are the same as if the number was + // stored as a PHONE_HOME_CITY_AND_NUMBER. + PhoneImportAndGetTestCase{ + // This time using PHONE_HOME_WHOLE_NUMBER: + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"+16502345681"}}, + .default_country = u"US", + // The + from the input is reflected here: + .expected_stored_number = u"1 650-234-5681", + // Same expectations as above. + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345681"}, + {PHONE_HOME_WHOLE_NUMBER, u"16502345681"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345681"}}}, + PhoneImportAndGetTestCase{ + // Same number as above but without a leading +. + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"16502345681"}}, + .default_country = u"US", + // The lack of a + is refelected here: + .expected_stored_number = u"1 650-234-5681", + // Same expectations as above. + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345681"}, + {PHONE_HOME_WHOLE_NUMBER, u"16502345681"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345681"}}}, - EXPECT_THAT(matching_types, testing::IsEmpty()); - } -} + // If, however, the user has provided formatting, this is preserved for + // PHONE_HOME_WHOLE_NUMBER. Note the broken whitespacing in the number. + PhoneImportAndGetTestCase{ + // This time using PHONE_HOME_WHOLE_NUMBER: + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"+1 65 02 345681"}}, + .default_country = u"US", + // The + from the input is reflected here: + .expected_stored_number = u"+1 65 02 345681", + // Same expectations as above. + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345681"}, + {PHONE_HOME_WHOLE_NUMBER, u"16502345681"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345681"}}}, + PhoneImportAndGetTestCase{ + // Same number as above but without a leading +. + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"1 65 02 345681"}}, + .default_country = u"US", + // The lack of a + is refelected here: + .expected_stored_number = u"1 65 02 345681", + // Same expectations as above. + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"1"}, + {PHONE_HOME_CITY_CODE, u"650"}, + {PHONE_HOME_NUMBER, u"2345681"}, + {PHONE_HOME_WHOLE_NUMBER, u"16502345681"}, + {PHONE_HOME_CITY_AND_NUMBER, u"6502345681"}}}, + + // The following tests document the behavior on a field that is + // classified as a PHONE_HOME_CITY_AND_NUMBER field. + + // Phone number is correctly filled in national format -> data is + // stored in national format. Whitespaces in the input are ignored. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"089 12 34 567"}}, + .default_country = u"DE", + .expected_stored_number = u"089 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u""}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"0891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + // While we expected a PHONE_HOME_CITY_AND_NUMBER, the user entered an + // international format (+49). The number is interpreted and stored in + // international format. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"+49891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"+49 89 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"49"}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + // In Germany international numbers start with + + // (different from US where the + is dropped). + {PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + // While we expected a PHONE_HOME_CITY_AND_NUMBER, the user entered an + // international format (+49) and made the mistake of not skipping the + // 0. The number is interpreted and stored in international format. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"+490891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"+49 89 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"49"}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + // In Germany international numbers start with + + // (different from US where the + is dropped). + {PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + // Phone number is filled in international format with 00 CC -> number + // is stored in international format. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"0049891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"+49 89 1234567", + // .expected_values were already covered for this format above. + }, + // Phone number is filled in international format but the user did not + // enter the + or 00 (e.g. because the website put the + before the + // input field). -> The number is still stored in international format. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"49891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"+49 89 1234567", + // .expected_values were already covered for this format above. + }, + // Phone number is filled in national format but the user did not enter + // the leading 0 (e.g. because the field was preceded by a country code + // selector that was not recognized). -> The number is still interpreted + // correctly and stored in national format. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"089 1234567", + // .expected_values were already covered for this format above. + }, + + // The following tests document the behavior on a field that is + // classified as a PHONE_HOME_WHOLE_NUMBER field (the input values are + // the same as above). Note how in all cases the raw input value is + // stored on disk. We still do a good job at guessing the correct values + // at filling because the number is parsed at filling time. + + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"0891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"089 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u""}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"0891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"+49 89 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"49"}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"+490891234567"}}, + .default_country = u"DE", + + .expected_stored_number = u"+49 89 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"49"}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"0049891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"+49 89 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"49"}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"49891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"+49 89 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"49"}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"891234567"}}, + .default_country = u"DE", + .expected_stored_number = u"089 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u""}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"0891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + + // What happens in case a US profile has a DE number? + + // For a proper international phone number, everything works as + // expected. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"+49891234567"}}, + .default_country = u"US", + .expected_stored_number = u"+49 89 1234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u"49"}, + {PHONE_HOME_CITY_CODE, u"89"}, + {PHONE_HOME_NUMBER, u"1234567"}, + // Unlike an international US number, this one + // is prefixed by a +. + {PHONE_HOME_WHOLE_NUMBER, u"+49891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + + // The German national number "08912345678" entered in a + // PHONE_HOME_CITY_AND_NUMBER or PHONE_HOME_WHOLE_NUMBER field would not + // be stored because it consists of 11 digits, more than US phone + // numbers allow. We don't have a test case because the number does not + // get stored. + + // The national German number "0891234567" (10 digits) is also invalid + // in the US, but can still be reproduced as a PHONE_HOME_NUMBER, + // PHONE_HOME_WHOLE_NUMBER and PHONE_HOME_CITY_AND_NUMBER. + // PHONE_HOME_CITY_CODE cannot be returned. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}, + .default_country = u"US", + .expected_stored_number = u"0891234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u""}, + {PHONE_HOME_CITY_CODE, u""}, + {PHONE_HOME_NUMBER, u"0891234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"0891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}}, + + // If an invalid 10 digit number is stored from a + // PHONE_HOME_WHOLE_NUMBER, it behaves like a + // PHONE_HOME_CITY_AND_NUMBER. + PhoneImportAndGetTestCase{ + .observed_fields = {{PHONE_HOME_WHOLE_NUMBER, u"0891234567"}}, + .default_country = u"US", + .expected_stored_number = u"0891234567", + .expected_values = {{PHONE_HOME_COUNTRY_CODE, u""}, + {PHONE_HOME_CITY_CODE, u""}, + {PHONE_HOME_NUMBER, u"0891234567"}, + {PHONE_HOME_WHOLE_NUMBER, u"0891234567"}, + {PHONE_HOME_CITY_AND_NUMBER, u"0891234567"}}})); } // namespace autofill
diff --git a/components/autofill/core/browser/filling_product.cc b/components/autofill/core/browser/filling_product.cc index 8b6b17e9..1a51566 100644 --- a/components/autofill/core/browser/filling_product.cc +++ b/components/autofill/core/browser/filling_product.cc
@@ -6,6 +6,7 @@ #include "base/notreached.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" namespace autofill { @@ -75,6 +76,7 @@ case PopupItemId::kViewPasswordDetails: return FillingProduct::kPassword; case PopupItemId::kCompose: + case PopupItemId::kComposeSavedStateNotification: return FillingProduct::kCompose; case PopupItemId::kCreateNewPlusAddress: case PopupItemId::kFillExistingPlusAddress:
diff --git a/components/autofill/core/browser/metrics/address_rewriter_in_profile_subset_metrics_unittest.cc b/components/autofill/core/browser/metrics/address_rewriter_in_profile_subset_metrics_unittest.cc index 5dcee19..9d49a2b 100644 --- a/components/autofill/core/browser/metrics/address_rewriter_in_profile_subset_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/address_rewriter_in_profile_subset_metrics_unittest.cc
@@ -65,8 +65,7 @@ AutofillSuggestionTriggerSource::kFormControlElementClicked); base::HistogramTester histogram_tester; - AutofillSuggestionGenerator suggestion_generator(*autofill_client_, - personal_data()); + AutofillSuggestionGenerator suggestion_generator(*autofill_client_); std::vector<Suggestion> suggestions = suggestion_generator.GetSuggestionsForProfiles( {NAME_FULL, ADDRESS_HOME_LINE1}, FormFieldData(), NAME_FULL,
diff --git a/components/autofill/core/browser/metrics/autofill_metrics.cc b/components/autofill/core/browser/metrics/autofill_metrics.cc index 90b864f4..96ac076 100644 --- a/components/autofill/core/browser/metrics/autofill_metrics.cc +++ b/components/autofill/core/browser/metrics/autofill_metrics.cc
@@ -1190,19 +1190,29 @@ void AutofillMetrics::LogEmailFieldPredictionMetrics( const AutofillField& field) { - // If the field has no email prediction, there is no need to record the - // metric. - if (field.Type().GetStorableType() != EMAIL_ADDRESS || field.value.empty()) { + // If the field has no value, there is no need to record any of the metrics. + if (field.value.empty()) { return; } - EmailPredictionConfusionMatrix prediction = - IsValidEmailAddress(field.value) - ? EmailPredictionConfusionMatrix::kTruePositive - : EmailPredictionConfusionMatrix::kFalsePositive; - base::UmaHistogramEnumeration("Autofill.EmailPredictionCorrectness.Precision", - prediction); - // TODO(b/324108545): Introduce recall metric. + bool is_valid_email = IsValidEmailAddress(field.value); + bool is_email_prediction = field.Type().GetStorableType() == EMAIL_ADDRESS; + + if (is_email_prediction) { + EmailPredictionConfusionMatrix prediction_precision = + is_valid_email ? EmailPredictionConfusionMatrix::kTruePositive + : EmailPredictionConfusionMatrix::kFalsePositive; + base::UmaHistogramEnumeration( + "Autofill.EmailPredictionCorrectness.Precision", prediction_precision); + } + + if (is_valid_email) { + EmailPredictionConfusionMatrix prediction_recall = + is_email_prediction ? EmailPredictionConfusionMatrix::kTruePositive + : EmailPredictionConfusionMatrix::kFalseNegative; + base::UmaHistogramEnumeration("Autofill.EmailPredictionCorrectness.Recall", + prediction_recall); + } } // static
diff --git a/components/autofill/core/browser/metrics/quality_metrics_unittest.cc b/components/autofill/core/browser/metrics/quality_metrics_unittest.cc index 5518793..a07738c 100644 --- a/components/autofill/core/browser/metrics/quality_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/quality_metrics_unittest.cc
@@ -975,6 +975,59 @@ } } +// Tests that recall metric is recorded for email field predictions. +TEST_F(QualityMetricsTest, EmailPredictionCorrectnessRecallMetric) { + FormData form = CreateForm( + {CreateTestFormField("Name", "name", "Elvis Aaron Presley", + FormControlType::kInputText), + CreateTestFormField("Address", "address", "3734 Elvis Presley Blvd.", + FormControlType::kInputText), + CreateTestFormField("Email", "email", "buddy@gmail.com", + FormControlType::kInputText)}); + + std::vector<FieldType> field_types = {NAME_FULL, ADDRESS_HOME_LINE1, + EMAIL_ADDRESS}; + autofill_manager().AddSeenForm(form, field_types); + + std::string precision_histogram = + "Autofill.EmailPredictionCorrectness.Recall"; + + // Check that the metric records true positive. + { + base::HistogramTester histogram_tester; + FillTestProfile(form); + SubmitForm(form); + + EXPECT_THAT( + histogram_tester.GetAllSamples(precision_histogram), + BucketsAre(Bucket(EmailPredictionConfusionMatrix::kTruePositive, 1))); + } + + // Check that the metric records false negative. (The predicted type is not + // email). + { + base::HistogramTester histogram_tester; + autofill_manager().ClearFormStructures(); + // Wrong field type predicted (i.e. not email). + field_types[2] = COMPANY_NAME; + autofill_manager().AddSeenForm(form, field_types); + FillTestProfile(form); + SubmitForm(form); + + EXPECT_THAT( + histogram_tester.GetAllSamples(precision_histogram), + BucketsAre(Bucket(EmailPredictionConfusionMatrix::kFalseNegative, 1))); + } + // Check that the metric is not recorded for empty values. + { + base::HistogramTester histogram_tester; + form.fields[2].value = u""; + FillTestProfile(form); + SubmitForm(form); + histogram_tester.ExpectTotalCount(precision_histogram, 0); + } +} + } // namespace autofill_metrics } // namespace autofill
diff --git a/components/autofill/core/browser/mock_autofill_optimization_guide.h b/components/autofill/core/browser/mock_autofill_optimization_guide.h index ed5fed0..48bbce1 100644 --- a/components/autofill/core/browser/mock_autofill_optimization_guide.h +++ b/components/autofill/core/browser/mock_autofill_optimization_guide.h
@@ -29,7 +29,7 @@ (const override)); MOCK_METHOD(bool, ShouldBlockFormFieldSuggestion, - (const GURL&, const CreditCard*), + (const GURL&, const CreditCard&), (const override)); MOCK_METHOD(CreditCardCategoryBenefit::BenefitCategory, AttemptToGetEligibleCreditCardBenefitCategory,
diff --git a/components/autofill/core/browser/payments_data_manager.cc b/components/autofill/core/browser/payments_data_manager.cc index aa9cd1e..10d3d8f 100644 --- a/components/autofill/core/browser/payments_data_manager.cc +++ b/components/autofill/core/browser/payments_data_manager.cc
@@ -465,14 +465,14 @@ template <typename T> std::optional<T> PaymentsDataManager::GetCreditCardBenefitByInstrumentId( CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - base::FunctionRef<bool(T&)> filter) { + base::FunctionRef<bool(const T&)> filter) const { if (!pdm_->IsAutofillWalletImportEnabled() || !pdm_->IsAutofillPaymentMethodsEnabled()) { return std::nullopt; } base::Time now = AutofillClock::Now(); - for (CreditCardBenefit& benefit : credit_card_benefits_) { - if (auto* b = absl::get_if<T>(&benefit); + for (const CreditCardBenefit& benefit : credit_card_benefits_) { + if (const auto* b = absl::get_if<T>(&benefit); b && b->linked_card_instrument_id() == instrument_id && b->start_time() <= now && now < b->expiry_time() && filter(*b)) { return *b; @@ -483,7 +483,7 @@ std::optional<CreditCardFlatRateBenefit> PaymentsDataManager::GetFlatRateBenefitByInstrumentId( - const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id) { + const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id) const { return GetCreditCardBenefitByInstrumentId<CreditCardFlatRateBenefit>( instrument_id); } @@ -491,9 +491,9 @@ std::optional<CreditCardCategoryBenefit> PaymentsDataManager::GetCategoryBenefitByInstrumentIdAndCategory( const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - const CreditCardCategoryBenefit::BenefitCategory benefit_category) { + const CreditCardCategoryBenefit::BenefitCategory benefit_category) const { return GetCreditCardBenefitByInstrumentId<CreditCardCategoryBenefit>( - instrument_id, [&benefit_category](CreditCardCategoryBenefit& b) { + instrument_id, [&benefit_category](const CreditCardCategoryBenefit& b) { return b.benefit_category() == benefit_category; }); } @@ -501,9 +501,9 @@ std::optional<CreditCardMerchantBenefit> PaymentsDataManager::GetMerchantBenefitByInstrumentIdAndOrigin( const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - const url::Origin& merchant_origin) { + const url::Origin& merchant_origin) const { return GetCreditCardBenefitByInstrumentId<CreditCardMerchantBenefit>( - instrument_id, [&merchant_origin](CreditCardMerchantBenefit& b) { + instrument_id, [&merchant_origin](const CreditCardMerchantBenefit& b) { return b.merchant_domains().contains(merchant_origin); }); }
diff --git a/components/autofill/core/browser/payments_data_manager.h b/components/autofill/core/browser/payments_data_manager.h index 750b2ff0..affcf91 100644 --- a/components/autofill/core/browser/payments_data_manager.h +++ b/components/autofill/core/browser/payments_data_manager.h
@@ -88,7 +88,7 @@ // Return the first valid flat rate benefit linked with the card with the // specific `instrument_id`. std::optional<CreditCardFlatRateBenefit> GetFlatRateBenefitByInstrumentId( - CreditCardBenefitBase::LinkedCardInstrumentId instrument_id); + CreditCardBenefitBase::LinkedCardInstrumentId instrument_id) const; // Return the first valid category benefit for the specific // `benefit_category` and linked with the card with the specific @@ -96,7 +96,7 @@ std::optional<CreditCardCategoryBenefit> GetCategoryBenefitByInstrumentIdAndCategory( CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - CreditCardCategoryBenefit::BenefitCategory benefit_category); + CreditCardCategoryBenefit::BenefitCategory benefit_category) const; // Return the first valid merchant benefit for the specific // `merchant_origin` and linked with the card with the specific @@ -104,7 +104,7 @@ std::optional<CreditCardMerchantBenefit> GetMerchantBenefitByInstrumentIdAndOrigin( CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - const url::Origin& merchant_origin); + const url::Origin& merchant_origin) const; // Returns just LOCAL_CARD cards. virtual std::vector<CreditCard*> GetLocalCreditCards() const; @@ -340,7 +340,9 @@ template <typename T> std::optional<T> GetCreditCardBenefitByInstrumentId( CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - base::FunctionRef<bool(T&)> filter = [](T&) { return true; }); + base::FunctionRef<bool(const T&)> filter = [](const T&) { + return true; + }) const; // Decides which database type to use for server and local cards. std::unique_ptr<PaymentsDatabaseHelper> database_helper_;
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 69a45fb..29012ff6 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -601,7 +601,7 @@ std::optional<CreditCardFlatRateBenefit> PersonalDataManager::GetFlatRateBenefitByInstrumentId( - const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id) { + const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id) const { return payments_data_manager_->GetFlatRateBenefitByInstrumentId( instrument_id); } @@ -609,7 +609,7 @@ std::optional<CreditCardCategoryBenefit> PersonalDataManager::GetCategoryBenefitByInstrumentIdAndCategory( const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - const CreditCardCategoryBenefit::BenefitCategory benefit_category) { + const CreditCardCategoryBenefit::BenefitCategory benefit_category) const { return payments_data_manager_->GetCategoryBenefitByInstrumentIdAndCategory( instrument_id, benefit_category); } @@ -617,7 +617,7 @@ std::optional<CreditCardMerchantBenefit> PersonalDataManager::GetMerchantBenefitByInstrumentIdAndOrigin( const CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - const url::Origin& merchant_origin) { + const url::Origin& merchant_origin) const { return payments_data_manager_->GetMerchantBenefitByInstrumentIdAndOrigin( instrument_id, merchant_origin); }
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index f32d6b5..3eb6b8e 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -361,7 +361,7 @@ // Return the first valid flat rate benefit linked with the card with the // specific `instrument_id`. std::optional<CreditCardFlatRateBenefit> GetFlatRateBenefitByInstrumentId( - CreditCardBenefitBase::LinkedCardInstrumentId instrument_id); + CreditCardBenefitBase::LinkedCardInstrumentId instrument_id) const; // Return the first valid category benefit for the specific // `benefit_category` and linked with the card with the specific @@ -369,7 +369,7 @@ std::optional<CreditCardCategoryBenefit> GetCategoryBenefitByInstrumentIdAndCategory( CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - CreditCardCategoryBenefit::BenefitCategory benefit_category); + CreditCardCategoryBenefit::BenefitCategory benefit_category) const; // Return the first valid merchant benefit for the specific // `merchant_origin` and linked with the card with the specific @@ -377,7 +377,7 @@ std::optional<CreditCardMerchantBenefit> GetMerchantBenefitByInstrumentIdAndOrigin( CreditCardBenefitBase::LinkedCardInstrumentId instrument_id, - const url::Origin& merchant_origin); + const url::Origin& merchant_origin) const; // Add the credit-card-linked benefit to local cache for tests. This does // not affect data in the real database.
diff --git a/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller.h b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller.h new file mode 100644 index 0000000..34cbd8d --- /dev/null +++ b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller.h
@@ -0,0 +1,35 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_CONTROLLER_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_CONTROLLER_H_ + +#include <string> + +namespace autofill::payments { + +// Interface for the controller that handles functionality related to the user +// consent dialog in a payments window pop-up flow. +class PaymentsWindowUserConsentDialogController { + public: + virtual ~PaymentsWindowUserConsentDialogController() = default; + + // Triggers the callback that continues the payments window pop-up flow. + virtual void OnOkButtonClicked() = 0; + + // Returns the title of the payments window pop-up user consent dialog to be + // displayed to the user. + virtual std::u16string GetWindowTitle() const = 0; + + // Returns the description of the payments window pop-up user consent dialog + // to be displayed to the user. + virtual std::u16string GetDialogDescription() const = 0; + + // Returns the label for the accept button. + virtual std::u16string GetOkButtonLabel() const = 0; +}; + +} // namespace autofill::payments + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_CONTROLLER_H_
diff --git a/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.cc b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.cc new file mode 100644 index 0000000..5331d48 --- /dev/null +++ b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.cc
@@ -0,0 +1,43 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.h" + +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" + +namespace autofill::payments { + +PaymentsWindowUserConsentDialogControllerImpl:: + PaymentsWindowUserConsentDialogControllerImpl( + base::OnceClosure accept_callback) + : accept_callback_(std::move(accept_callback)) {} + +PaymentsWindowUserConsentDialogControllerImpl:: + ~PaymentsWindowUserConsentDialogControllerImpl() = default; + +void PaymentsWindowUserConsentDialogControllerImpl::OnOkButtonClicked() { + CHECK(accept_callback_); + std::move(accept_callback_).Run(); +} + +std::u16string PaymentsWindowUserConsentDialogControllerImpl::GetWindowTitle() + const { + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_TITLE_VCN_3DS); +} + +std::u16string +PaymentsWindowUserConsentDialogControllerImpl::GetDialogDescription() const { + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_DESCRIPTION_VCN_3DS); +} + +std::u16string PaymentsWindowUserConsentDialogControllerImpl::GetOkButtonLabel() + const { + return l10n_util::GetStringUTF16( + IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_OK_BUTTON_LABEL_VCN_3DS); +} + +} // namespace autofill::payments
diff --git a/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.h b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.h new file mode 100644 index 0000000..67cc49a --- /dev/null +++ b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.h
@@ -0,0 +1,42 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_CONTROLLER_IMPL_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_CONTROLLER_IMPL_H_ + +#include "components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller.h" + +#include <string> + +#include "base/functional/callback.h" +#include "base/functional/callback_forward.h" + +namespace autofill::payments { + +class PaymentsWindowUserConsentDialogControllerImpl + : public PaymentsWindowUserConsentDialogController { + public: + explicit PaymentsWindowUserConsentDialogControllerImpl( + base::OnceClosure accept_callback); + PaymentsWindowUserConsentDialogControllerImpl( + const PaymentsWindowUserConsentDialogControllerImpl&) = delete; + PaymentsWindowUserConsentDialogControllerImpl& operator=( + const PaymentsWindowUserConsentDialogControllerImpl&) = delete; + ~PaymentsWindowUserConsentDialogControllerImpl() override; + + // PaymentsWindowUserConsentDialogController: + void OnOkButtonClicked() override; + std::u16string GetWindowTitle() const override; + std::u16string GetDialogDescription() const override; + std::u16string GetOkButtonLabel() const override; + + private: + // Dialog acceptance callback. Set when `ShowDialog()` is triggered, and run + // when `OnOkButtonClicked()` is called. + base::OnceClosure accept_callback_; +}; + +} // namespace autofill::payments + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_CONTROLLER_IMPL_H_
diff --git a/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl_unittest.cc b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl_unittest.cc new file mode 100644 index 0000000..dab8312 --- /dev/null +++ b/components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl_unittest.cc
@@ -0,0 +1,62 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/ui/payments/payments_window_user_consent_dialog_controller_impl.h" + +#include <string> + +#include "base/functional/callback_forward.h" +#include "base/test/mock_callback.h" +#include "components/strings/grit/components_strings.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" + +namespace autofill::payments { + +class PaymentsWindowUserConsentDialogControllerImplTest : public testing::Test { + public: + PaymentsWindowUserConsentDialogControllerImplTest() { + controller_ = + std::make_unique<PaymentsWindowUserConsentDialogControllerImpl>( + accept_callback_.Get()); + } + + ~PaymentsWindowUserConsentDialogControllerImplTest() override = default; + + PaymentsWindowUserConsentDialogControllerImpl* controller() { + return controller_.get(); + } + + protected: + base::MockOnceClosure accept_callback_; + + private: + std::unique_ptr<PaymentsWindowUserConsentDialogControllerImpl> controller_; +}; + +// Tests that the correct strings are returned for the dialog. +TEST_F(PaymentsWindowUserConsentDialogControllerImplTest, + CorrectStringsAreReturned) { + EXPECT_EQ( + controller()->GetWindowTitle(), + l10n_util::GetStringUTF16( + IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_TITLE_VCN_3DS)); + EXPECT_EQ( + controller()->GetDialogDescription(), + l10n_util::GetStringUTF16( + IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_DESCRIPTION_VCN_3DS)); + EXPECT_EQ( + controller()->GetOkButtonLabel(), + l10n_util::GetStringUTF16( + IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_OK_BUTTON_LABEL_VCN_3DS)); +} + +// Tests that the accept callback is triggered when the dialog is accepted. +TEST_F(PaymentsWindowUserConsentDialogControllerImplTest, + AcceptCallbackTriggeredOnDialogAcceptance) { + EXPECT_CALL(accept_callback_, Run); + controller()->OnOkButtonClicked(); +} + +} // namespace autofill::payments
diff --git a/components/autofill/core/browser/ui/popup_hiding_reasons.h b/components/autofill/core/browser/ui/popup_hiding_reasons.h index aed312e..462f5f2 100644 --- a/components/autofill/core/browser/ui/popup_hiding_reasons.h +++ b/components/autofill/core/browser/ui/popup_hiding_reasons.h
@@ -74,7 +74,11 @@ // Compose-related // popups, which close in response to user edits of the focused field. kFieldValueChanged = 25, - kMaxValue = kFieldValueChanged + // When a Compose popup loses focus, another autofill popup is shown for + // a few seconds on a timer then the popup is closed. Currently, this event + // is only used for Compose. + kFadeTimerExpired = 26, + kMaxValue = kFadeTimerExpired }; } // namespace autofill
diff --git a/components/autofill/core/browser/ui/popup_item_ids.h b/components/autofill/core/browser/ui/popup_item_ids.h index ab30fbf..c8290b5 100644 --- a/components/autofill/core/browser/ui/popup_item_ids.h +++ b/components/autofill/core/browser/ui/popup_item_ids.h
@@ -44,6 +44,7 @@ // Compose suggestions. kCompose, + kComposeSavedStateNotification, // Datalist suggestions. kDatalistEntry,
diff --git a/components/autofill/core/common/autofill_constants.h b/components/autofill/core/common/autofill_constants.h index 792e2c0..750305ac 100644 --- a/components/autofill/core/common/autofill_constants.h +++ b/components/autofill/core/common/autofill_constants.h
@@ -108,6 +108,16 @@ inline constexpr size_t kCreditCardTypeValueFormFillingLimit = 19; inline constexpr size_t kStateTypeValueFormFillingLimit = 1000; +// Limits the number of profiles from the list of matching profiles for +// suggestions that Autofill will keep after deduplication. Remaining profiles +// will be dropped. +inline constexpr size_t kMaxDeduplicatedProfilesForSuggestion = 10; + +// Limits the number of profiles from the list of stored profiles that Autofill +// will keep after prefix matching with a field's contents to show as +// suggestions. Remaining profiles will be dropped. +inline constexpr size_t kMaxPrefixMatchedProfilesForSuggestion = 50; + } // namespace autofill #endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_CONSTANTS_H_
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc index 7176646..7663740 100644 --- a/components/autofill/core/common/autofill_payments_features.cc +++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -62,6 +62,12 @@ "AutofillEnableCardBenefitsForCapitalOne", base::FEATURE_DISABLED_BY_DEFAULT); +// When enabled, card benefits offered by issuers will be synced from the +// Payments server. +BASE_FEATURE(kAutofillEnableCardBenefitsSync, + "AutofillEnableCardBenefitsSync", + base::FEATURE_DISABLED_BY_DEFAULT); + // When enabled, card product name (instead of issuer network) will be shown in // Payments Autofill UI. BASE_FEATURE(kAutofillEnableCardProductName,
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h index c57c639..640080a 100644 --- a/components/autofill/core/common/autofill_payments_features.h +++ b/components/autofill/core/common/autofill_payments_features.h
@@ -19,6 +19,7 @@ BASE_DECLARE_FEATURE(kAutofillEnableCardBenefits); BASE_DECLARE_FEATURE(kAutofillEnableCardBenefitsForAmericanExpress); BASE_DECLARE_FEATURE(kAutofillEnableCardBenefitsForCapitalOne); +BASE_DECLARE_FEATURE(kAutofillEnableCardBenefitsSync); BASE_DECLARE_FEATURE(kAutofillEnableCardProductName); BASE_DECLARE_FEATURE(kAutofillEnableCvcStorageAndFilling); BASE_DECLARE_FEATURE(kAutofillEnableFIDOProgressDialog);
diff --git a/components/autofill/core/common/mojom/autofill_types.mojom b/components/autofill/core/common/mojom/autofill_types.mojom index 59f5a22..586068f0 100644 --- a/components/autofill/core/common/mojom/autofill_types.mojom +++ b/components/autofill/core/common/mojom/autofill_types.mojom
@@ -620,4 +620,7 @@ // is used only if the suggestions were triggered manually via the Chrome // context menu. kShowPromptAfterDialogClosedNonManualFallback, + // The compose saved state notification is triggered when the compose dialog + // loses focus and is closed. + kComposeDialogLostFocus, };
diff --git a/components/autofill_payments_strings.grdp b/components/autofill_payments_strings.grdp index 0be4fe127..577df57 100644 --- a/components/autofill_payments_strings.grdp +++ b/components/autofill_payments_strings.grdp
@@ -929,6 +929,15 @@ <message name="IDS_AUTOFILL_CARD_UNMASK_OTP_INPUT_DIALOG_ENTER_CORRECT_CODE_LABEL" desc="This text is shown after an OTP is already sent, when the user enters an incorrect OTP code. It directs the user to enter the correct code that was sent to them."> Enter correct code </message> + <message name="IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_TITLE_VCN_3DS" desc="This text is shown as the title for the user consent dialog for VCN 3DS. If the user accepts the dialog, Chrome will open a pop-up and initiate the VCN 3DS flow."> + Your bank wants to verify it's you + </message> + <message name="IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_DESCRIPTION_VCN_3DS" desc="This text is shown as the description for the user consent dialog for VCN 3DS. If the user accepts the dialog, Chrome will open a pop-up and initiate the VCN 3DS flow."> + When you continue you'll be taken to your bank's website. After you verify, you'll automatically be returned to finish your purchase. + </message> + <message name="IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_OK_BUTTON_LABEL_VCN_3DS" desc="This text is shown as the accept button label for the user consent dialog for VCN 3DS. If the user accepts the dialog, Chrome will open a pop-up and initiate the VCN 3DS flow."> + Continue + </message> <!-- Credit card benefits-related strings --> <message name="IDS_AUTOFILL_CREDIT_CARD_BENEFIT_TEXT_FOR_SUGGESTIONS" desc="benefit text string shown in suggestion dropdown indicating that the credit card has an applicable benefit for this purchase with `terms apply` appended.">
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_DESCRIPTION_VCN_3DS.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_DESCRIPTION_VCN_3DS.png.sha1 new file mode 100644 index 0000000..e62ec37 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_DESCRIPTION_VCN_3DS.png.sha1
@@ -0,0 +1 @@ +c44b962e2fc0b65be1bdca2862746058e8b11d8f \ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_OK_BUTTON_LABEL_VCN_3DS.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_OK_BUTTON_LABEL_VCN_3DS.png.sha1 new file mode 100644 index 0000000..e62ec37 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_OK_BUTTON_LABEL_VCN_3DS.png.sha1
@@ -0,0 +1 @@ +c44b962e2fc0b65be1bdca2862746058e8b11d8f \ No newline at end of file
diff --git a/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_TITLE_VCN_3DS.png.sha1 b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_TITLE_VCN_3DS.png.sha1 new file mode 100644 index 0000000..e62ec37 --- /dev/null +++ b/components/autofill_payments_strings_grdp/IDS_AUTOFILL_PAYMENTS_WINDOW_USER_CONSENT_DIALOG_TITLE_VCN_3DS.png.sha1
@@ -0,0 +1 @@ +c44b962e2fc0b65be1bdca2862746058e8b11d8f \ No newline at end of file
diff --git a/components/bookmarks/browser/bookmark_model.h b/components/bookmarks/browser/bookmark_model.h index cc0baa7..dd3d544 100644 --- a/components/bookmarks/browser/bookmark_model.h +++ b/components/bookmarks/browser/bookmark_model.h
@@ -71,12 +71,11 @@ // You should NOT directly create a BookmarkModel, instead go through the // BookmarkModelFactory. // -// Marked final to prevent unintended subclassing. // `MoveToOtherModelWithNewNodeIdsAndUuids` affects two instances, and assumes // that both instances are `BookmarkModel`, not some subclasses. -class BookmarkModel final : public CoreBookmarkModel, - public BookmarkUndoProvider, - public base::SupportsUserData { +class BookmarkModel : public CoreBookmarkModel, + public BookmarkUndoProvider, + public base::SupportsUserData { public: // `client` must not be null. explicit BookmarkModel(std::unique_ptr<BookmarkClient> client);
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index 89776a6..847f693d 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -1172,23 +1172,8 @@ return; } - bool frame_type_changed = frame_type_ != frame_type; - - // aura-shell's set_frame, when used with xdg-shell, works iff the frame type - // or frame colors were specified before firsrt buffer commit. If these are - // not specified, the widget's layer is set to 'NOT_DRAWN' and the frame can't - // be drawn. `ClientControlledShellSurface` is not affected. - if (frame_type_changed && widget_ && - widget_->GetNativeWindow()->layer()->type() == ui::LAYER_NOT_DRAWN) { - if (frame_type != SurfaceFrameType::NONE && - frame_type != SurfaceFrameType::SHADOW) { - DLOG(FATAL) - << "A shell surface with NOT_DRAWN layer can't support visible frame"; - return; - } - } bool frame_was_disabled = !frame_enabled(); - + bool frame_type_changed = frame_type_ != frame_type; frame_type_ = frame_type; switch (frame_type) { case SurfaceFrameType::NONE: @@ -2110,25 +2095,6 @@ UpdateShadowRoundedCorners(); } - - if (window->layer()->type() == ui::LAYER_NOT_DRAWN) { - DCHECK(!window->GetProperty(chromeos::kWindowManagerManagesOpacityKey)); - - // Snapped window should not be opaque because it can be drag-resized, in - // which case the widget's window can be exposed while waiting for - // configure_ack + commit. - bool window_is_opaque = widget_->IsFullscreen() || widget_->IsMaximized(); - window->SetTransparent(!window_is_opaque); - if (root_surface()->FillsBoundsOpaquely()) { - // Manually control occlusion, but do not make the window - // opaque as the host window may not be at the same size unless the - // window state is either in fullscreen or maximized. - window->SetOpaqueRegionsForOcclusion( - {gfx::Rect(window->bounds().size())}); - } else { - window->SetOpaqueRegionsForOcclusion({}); - } - } } void ShellSurfaceBase::UpdateShadowRoundedCorners() {
diff --git a/components/exo/shell_surface_base.h b/components/exo/shell_surface_base.h index ca1dabbc..1a46a72 100644 --- a/components/exo/shell_surface_base.h +++ b/components/exo/shell_surface_base.h
@@ -382,8 +382,6 @@ bool IsReady() const; protected: - bool has_frame_colors() const { return has_frame_colors_; } - // Creates the |widget_| for |surface_|. |show_state| is the initial state // of the widget (e.g. maximized). void CreateShellSurfaceWidget(ui::WindowShowState show_state);
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc index 6812604b..77cea774 100644 --- a/components/exo/shell_surface_unittest.cc +++ b/components/exo/shell_surface_unittest.cc
@@ -78,8 +78,6 @@ namespace exo { -const gfx::BufferFormat kOpaqueFormat = gfx::BufferFormat::RGBX_8888; - using ShellSurfaceTest = test::ExoTestBase; namespace { @@ -1398,9 +1396,8 @@ TEST_F(ShellSurfaceTest, SetMinimumSize) { constexpr gfx::Size kBufferSize(64, 64); - auto shell_surface = test::ShellSurfaceBuilder(kBufferSize) - .SetFrameColors(SK_ColorWHITE, SK_ColorWHITE) - .BuildShellSurface(); + auto shell_surface = + test::ShellSurfaceBuilder(kBufferSize).BuildShellSurface(); auto* surface = shell_surface->root_surface(); constexpr gfx::Size kSizes[] = {{50, 50}, {100, 50}}; @@ -2576,15 +2573,15 @@ TEST_F(ShellSurfaceTest, CaptionWithPopup) { constexpr gfx::Size kBufferSize(256, 256); - auto shell_surface = test::ShellSurfaceBuilder(kBufferSize) - .SetRootBufferFormat(kOpaqueFormat) - .SetFrame(SurfaceFrameType::NORMAL) - .BuildShellSurface(); + auto shell_surface = + test::ShellSurfaceBuilder(kBufferSize).BuildShellSurface(); auto* surface = shell_surface->root_surface(); - shell_surface->GetWidget()->SetBounds(gfx::Rect(0, 0, 256, 288)); + + shell_surface->GetWidget()->SetBounds(gfx::Rect(0, 0, 256, 256)); + shell_surface->OnSetFrame(SurfaceFrameType::NORMAL); auto popup_buffer = std::make_unique<Buffer>( - exo_test_helper()->CreateGpuMemoryBuffer(kBufferSize, kOpaqueFormat)); + exo_test_helper()->CreateGpuMemoryBuffer(kBufferSize)); auto popup_surface = std::make_unique<Surface>(); popup_surface->Attach(popup_buffer.get()); std::unique_ptr<ShellSurface> popup_shell_surface(CreatePopupShellSurface( @@ -2621,10 +2618,9 @@ TEST_F(ShellSurfaceTest, SkipImeProcessingPropagateToSurface) { std::unique_ptr<ShellSurface> shell_surface = - test::ShellSurfaceBuilder({256, 256}) - .SetFrame(SurfaceFrameType::NORMAL) - .BuildShellSurface(); + test::ShellSurfaceBuilder({256, 256}).BuildShellSurface(); shell_surface->GetWidget()->SetBounds(gfx::Rect(0, 0, 256, 256)); + shell_surface->OnSetFrame(SurfaceFrameType::NORMAL); aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); ASSERT_FALSE(window->GetProperty(aura::client::kSkipImeProcessing)); @@ -3326,11 +3322,11 @@ } TEST_F(ShellSurfaceTest, OverlayOverlapsFrame) { - auto shell_surface = test::ShellSurfaceBuilder({100, 100}) - .SetFrame(SurfaceFrameType::NORMAL) - .BuildShellSurface(); + auto shell_surface = + test::ShellSurfaceBuilder({100, 100}).BuildShellSurface(); shell_surface->GetWidget()->GetNativeWindow()->SetProperty( aura::client::kSkipImeProcessing, true); + shell_surface->OnSetFrame(SurfaceFrameType::NORMAL); EXPECT_FALSE(shell_surface->HasOverlay()); @@ -3363,11 +3359,11 @@ } TEST_F(ShellSurfaceTest, OverlayCanResize) { - auto shell_surface = test::ShellSurfaceBuilder({100, 100}) - .SetFrame(SurfaceFrameType::NORMAL) - .BuildShellSurface(); + auto shell_surface = + test::ShellSurfaceBuilder({100, 100}).BuildShellSurface(); shell_surface->GetWidget()->GetNativeWindow()->SetProperty( aura::client::kSkipImeProcessing, true); + shell_surface->OnSetFrame(SurfaceFrameType::NORMAL); EXPECT_FALSE(shell_surface->HasOverlay()); { @@ -4069,10 +4065,9 @@ // when the surface commits. TEST_F(ShellSurfaceTest, SetShapeUpdatesAndUnsetsCorrectlyAfterCommit) { std::unique_ptr<ShellSurface> shell_surface = - test::ShellSurfaceBuilder({64, 64}) - .SetFrame(SurfaceFrameType::SHADOW) - .BuildShellSurface(); + test::ShellSurfaceBuilder({64, 64}).BuildShellSurface(); shell_surface->OnSetServerStartResize(); + shell_surface->OnSetFrame(SurfaceFrameType::SHADOW); shell_surface->root_surface()->Commit(); const views::Widget* widget = shell_surface->GetWidget(); ASSERT_TRUE(widget); @@ -4121,11 +4116,9 @@ // SetShape() is not supported for windows with the frame enabled. TEST_F(ShellSurfaceTest, SetShapeWithFrameNotSupported) { std::unique_ptr<ShellSurface> shell_surface = - test::ShellSurfaceBuilder({64, 64}) - .SetFrame(SurfaceFrameType::NORMAL) - .BuildShellSurface(); - + test::ShellSurfaceBuilder({64, 64}).BuildShellSurface(); shell_surface->OnSetServerStartResize(); + shell_surface->OnSetFrame(SurfaceFrameType::NORMAL); shell_surface->root_surface()->Commit(); const views::Widget* widget = shell_surface->GetWidget(); ASSERT_TRUE(widget); @@ -4313,10 +4306,11 @@ std::unique_ptr<ShellSurface> shell_surface = test::ShellSurfaceBuilder({256, 256}) .SetOrigin({20, 20}) - .SetFrame(SurfaceFrameType::NORMAL) .BuildShellSurface(); + auto* surface = shell_surface->root_surface(); // Enabling a normal frame makes `GetClientViewBounds().origin()` return // (0, 32), which makes the host window not align with any pixel boundary. + surface->SetFrame(SurfaceFrameType::NORMAL); shell_surface->root_surface()->SetSurfaceHierarchyContentBoundsForTest( gfx::Rect(-20, -20, 256, 256)); EXPECT_TRUE(shell_surface->OnPreWidgetCommit()); @@ -4550,57 +4544,37 @@ EXPECT_EQ(kNewOrigin + gfx::Vector2d(0, kVerticalOffset), client_origin); } -// Tests the unnecessary occlusion events are fired when opaque buffer and no -// frame are used. TEST_F(ShellSurfaceTest, DisplayScaleChangeDoesNotSendOcclusionUpdates) { std::unique_ptr<ShellSurface> shell_surface1 = - test::ShellSurfaceBuilder({256, 256}) - .SetRootBufferFormat(kOpaqueFormat) - .BuildShellSurface(); + test::ShellSurfaceBuilder({256, 256}).BuildShellSurface(); std::unique_ptr<ShellSurface> shell_surface2 = - test::ShellSurfaceBuilder({256, 256}) - .SetRootBufferFormat(kOpaqueFormat) - .BuildShellSurface(); - auto* surface1 = shell_surface1->root_surface(); - auto* surface2 = shell_surface2->root_surface(); - auto* window1 = shell_surface1->GetWidget()->GetNativeWindow(); - auto* window2 = shell_surface2->GetWidget()->GetNativeWindow(); + test::ShellSurfaceBuilder({256, 256}).BuildShellSurface(); - // xdg-shell without a frame type will use NOT_DRAWN layer type and - // should control the opacity by themselves. - EXPECT_EQ(ui::LAYER_NOT_DRAWN, window1->layer()->type()); - EXPECT_FALSE(window1->GetProperty(chromeos::kWindowManagerManagesOpacityKey)); - EXPECT_EQ(ui::LAYER_NOT_DRAWN, window2->layer()->type()); - EXPECT_FALSE(window2->GetProperty(chromeos::kWindowManagerManagesOpacityKey)); + shell_surface1->GetWidget()->GetNativeWindow()->SetProperty( + chromeos::kWindowManagerManagesOpacityKey, true); + shell_surface2->GetWidget()->GetNativeWindow()->SetProperty( + chromeos::kWindowManagerManagesOpacityKey, true); - const std::vector<gfx::Rect> kNormalOpaqueRegion{gfx::Rect(256, 256)}; - - // Normal window should have custom opacity regions. - EXPECT_TRUE(window1->GetTransparent()); - EXPECT_TRUE(window2->GetTransparent()); - EXPECT_EQ(kNormalOpaqueRegion, window1->opaque_regions_for_occlusion()); - EXPECT_EQ(kNormalOpaqueRegion, window2->opaque_regions_for_occlusion()); - - // Test Maximzied State + // Do state change after setting kWindowManagerManagesOpacityKey so it + // applies properly. shell_surface1->Maximize(); shell_surface2->Maximize(); - EXPECT_FALSE(window1->GetTransparent()); - EXPECT_FALSE(window2->GetTransparent()); - const std::vector<gfx::Rect> kMaximizedOpaqueRegion{gfx::Rect(800, 552)}; - EXPECT_EQ(kMaximizedOpaqueRegion, window1->opaque_regions_for_occlusion()); - EXPECT_EQ(kMaximizedOpaqueRegion, window2->opaque_regions_for_occlusion()); + auto* surface1 = shell_surface1->root_surface(); + auto* surface2 = shell_surface2->root_surface(); // Update root surfaces (this happens asynchronously normally) and set // occlusion tracking. surface1->SetOcclusionTracking(true); auto surface1_buffer = - exo_test_helper()->CreateBuffer(shell_surface1.get(), kOpaqueFormat); + std::make_unique<Buffer>(exo_test_helper()->CreateGpuMemoryBuffer( + shell_surface1->GetWidget()->GetWindowBoundsInScreen().size())); surface1->Attach(surface1_buffer.get()); surface1->Commit(); surface2->SetOcclusionTracking(true); auto surface2_buffer = - exo_test_helper()->CreateBuffer(shell_surface2.get(), kOpaqueFormat); + std::make_unique<Buffer>(exo_test_helper()->CreateGpuMemoryBuffer( + shell_surface2->GetWidget()->GetWindowBoundsInScreen().size())); surface2->Attach(surface2_buffer.get()); surface2->Commit(); @@ -4621,103 +4595,31 @@ EXPECT_EQ(0, observer2.num_occlusion_state_changes()); display_manager->ZoomDisplay(display_id, /*up=*/true); - // Update root surfaces (this happens asynchronously normally). - { - auto surface1_buffer_zoom = - exo_test_helper()->CreateBuffer(shell_surface1.get(), kOpaqueFormat); - surface1->Attach(surface1_buffer_zoom.get()); - surface1->Commit(); - auto surface2_buffer_zoom = - exo_test_helper()->CreateBuffer(shell_surface2.get(), kOpaqueFormat); - surface2->Attach(surface2_buffer_zoom.get()); - surface2->Commit(); - } + EXPECT_EQ(0, observer1.num_occlusion_state_changes()); EXPECT_EQ(0, observer2.num_occlusion_state_changes()); + // Update root surfaces (this happens asynchronously normally). + auto surface1_buffer_zoom = + std::make_unique<Buffer>(exo_test_helper()->CreateGpuMemoryBuffer( + shell_surface1->GetWidget()->GetWindowBoundsInScreen().size())); + surface1->Attach(surface1_buffer_zoom.get()); + surface1->Commit(); + auto surface2_buffer_zoom = + std::make_unique<Buffer>(exo_test_helper()->CreateGpuMemoryBuffer( + shell_surface2->GetWidget()->GetWindowBoundsInScreen().size())); + surface2->Attach(surface2_buffer_zoom.get()); + surface2->Commit(); + display_manager->ZoomDisplay(display_id, /*up=*/false); - { - auto surface1_buffer_zoom = - exo_test_helper()->CreateBuffer(shell_surface1.get(), kOpaqueFormat); - surface1->Attach(surface1_buffer_zoom.get()); - surface1->Commit(); - auto surface2_buffer_zoom = - exo_test_helper()->CreateBuffer(shell_surface2.get(), kOpaqueFormat); - surface2->Attach(surface2_buffer_zoom.get()); - surface2->Commit(); - } + // Should not get any occlusion changes - requires occlusion tracking clip // to the root window and that the shelf occlude what is below it, too. EXPECT_EQ(0, observer1.num_occlusion_state_changes()); EXPECT_EQ(0, observer2.num_occlusion_state_changes()); - // Test Snapped State - ash::WindowSnapWMEvent snap_event(ash::WM_EVENT_SNAP_PRIMARY); - ash::WindowState* window_state1 = ash::WindowState::Get(window1); - ash::WindowState* window_state2 = ash::WindowState::Get(window2); - - window_state1->OnWMEvent(&snap_event); - window_state2->OnWMEvent(&snap_event); - EXPECT_EQ(0, observer1.num_occlusion_state_changes()); - EXPECT_EQ(0, observer2.num_occlusion_state_changes()); - - EXPECT_TRUE(window1->GetTransparent()); - EXPECT_TRUE(window2->GetTransparent()); - - const std::vector<gfx::Rect> kSnappedOpaqueRegion{gfx::Rect(400, 552)}; - EXPECT_EQ(kSnappedOpaqueRegion, window1->opaque_regions_for_occlusion()); - EXPECT_EQ(kSnappedOpaqueRegion, window2->opaque_regions_for_occlusion()); - { - auto snapped_buffer1 = - exo_test_helper()->CreateBuffer(shell_surface1.get(), kOpaqueFormat); - surface1->Attach(snapped_buffer1.get()); - surface1->Commit(); - - auto snapped_buffer2 = - exo_test_helper()->CreateBuffer(shell_surface2.get(), kOpaqueFormat); - surface2->Attach(snapped_buffer2.get()); - surface2->Commit(); - } - EXPECT_EQ(0, observer1.num_occlusion_state_changes()); - EXPECT_EQ(0, observer2.num_occlusion_state_changes()); - - display_manager->ZoomDisplay(display_id, /*up=*/true); - { - auto snapped_buffer1 = - exo_test_helper()->CreateBuffer(shell_surface1.get(), kOpaqueFormat); - surface1->Attach(snapped_buffer1.get()); - surface1->Commit(); - - auto snapped_buffer2 = - exo_test_helper()->CreateBuffer(shell_surface2.get(), kOpaqueFormat); - surface2->Attach(snapped_buffer2.get()); - surface2->Commit(); - } - EXPECT_EQ(0, observer1.num_occlusion_state_changes()); - EXPECT_EQ(0, observer2.num_occlusion_state_changes()); - - display_manager->ZoomDisplay(display_id, /*up=*/false); - { - auto snapped_buffer1 = - exo_test_helper()->CreateBuffer(shell_surface1.get(), kOpaqueFormat); - surface1->Attach(snapped_buffer1.get()); - surface1->Commit(); - - auto snapped_buffer2 = - exo_test_helper()->CreateBuffer(shell_surface2.get(), kOpaqueFormat); - surface2->Attach(snapped_buffer2.get()); - surface2->Commit(); - } - EXPECT_EQ(0, observer1.num_occlusion_state_changes()); - EXPECT_EQ(0, observer2.num_occlusion_state_changes()); - - // Make sure the occlusion tracking is working. - surface2->RemoveSurfaceObserver(&observer2); - shell_surface2.reset(); - - EXPECT_EQ(1, observer1.num_occlusion_state_changes()); - surface1->RemoveSurfaceObserver(&observer1); + surface2->RemoveSurfaceObserver(&observer2); } TEST_F(ShellSurfaceTest, GetWidgetHitTestMask) {
diff --git a/components/exo/test/exo_test_helper.cc b/components/exo/test/exo_test_helper.cc index 1f953c8..a0284a25 100644 --- a/components/exo/test/exo_test_helper.cc +++ b/components/exo/test/exo_test_helper.cc
@@ -142,13 +142,6 @@ gpu::kNullSurfaceHandle, nullptr); } -std::unique_ptr<Buffer> ExoTestHelper::CreateBuffer( - ShellSurfaceBase* shell_surface, - gfx::BufferFormat format) { - return std::make_unique<Buffer>(CreateGpuMemoryBuffer( - shell_surface->GetWidget()->GetWindowBoundsInScreen().size(), format)); -} - std::unique_ptr<InputMethodSurface> ExoTestHelper::CreateInputMethodSurface( Surface* surface, InputMethodSurfaceManager* surface_manager,
diff --git a/components/exo/test/exo_test_helper.h b/components/exo/test/exo_test_helper.h index 8a1622b..51097ef 100644 --- a/components/exo/test/exo_test_helper.h +++ b/components/exo/test/exo_test_helper.h
@@ -26,7 +26,6 @@ class Surface; class ToastSurface; class ToastSurfaceManager; -class Buffer; namespace test { @@ -77,12 +76,6 @@ const gfx::Size& size, gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888); - // Creates an exo::Buffer that has the size of the given - // shell surface. - std::unique_ptr<Buffer> CreateBuffer( - ShellSurfaceBase* shell_surface, - gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888); - std::unique_ptr<ClientControlledShellSurface> CreateClientControlledShellSurface(Surface* surface, bool is_modal = false,
diff --git a/components/exo/test/shell_surface_builder.cc b/components/exo/test/shell_surface_builder.cc index f7337ac..d5e22a5 100644 --- a/components/exo/test/shell_surface_builder.cc +++ b/components/exo/test/shell_surface_builder.cc
@@ -202,14 +202,6 @@ return *this; } -ShellSurfaceBuilder& ShellSurfaceBuilder::SetFrameColors(SkColor active, - SkColor inactive) { - DCHECK(!built_); - active_frame_color_ = active; - inactive_frame_color_ = inactive; - return *this; -} - ShellSurfaceBuilder& ShellSurfaceBuilder::SetApplicationId( const std::string& application_id) { DCHECK(!built_); @@ -342,7 +334,7 @@ auto holder = std::make_unique<Holder>(); holder->AddRootSurface(root_buffer_size_, root_buffer_format_); - auto shell_surface = std::make_unique<XdgShellSurface>( + auto shell_surface = std::make_unique<ShellSurface>( holder->root_surface, origin_, can_minimize_, GetContainer()); if (!configure_callback_.is_null()) { @@ -513,11 +505,6 @@ shell_surface->root_surface()->SetFrame(type_.value()); } - if (active_frame_color_.has_value()) { - shell_surface->root_surface()->SetFrameColors( - active_frame_color_.value(), inactive_frame_color_.value()); - } - if (system_modal_) { shell_surface->SetSystemModal(true); }
diff --git a/components/exo/test/shell_surface_builder.h b/components/exo/test/shell_surface_builder.h index d5948d9..ef8134d 100644 --- a/components/exo/test/shell_surface_builder.h +++ b/components/exo/test/shell_surface_builder.h
@@ -53,7 +53,6 @@ ShellSurfaceBuilder& SetGeometry(const gfx::Rect& geometry); ShellSurfaceBuilder& SetInputRegion(const cc::Region& region); ShellSurfaceBuilder& SetFrame(SurfaceFrameType type); - ShellSurfaceBuilder& SetFrameColors(SkColor active, SkColor inactive); ShellSurfaceBuilder& SetApplicationId(const std::string& application_id); ShellSurfaceBuilder& SetDisableMovement(); ShellSurfaceBuilder& SetCentered(); @@ -99,15 +98,11 @@ std::optional<gfx::BufferFormat> root_buffer_format_ = gfx::BufferFormat::RGBA_8888; gfx::Point origin_; - std::optional<gfx::Size> max_size_; std::optional<gfx::Size> min_size_; std::optional<gfx::Rect> geometry_; std::optional<cc::Region> input_region_; std::optional<SurfaceFrameType> type_; - std::optional<SkColor> active_frame_color_; - std::optional<SkColor> inactive_frame_color_; - raw_ptr<SecurityDelegate> security_delegate_ = nullptr; ash::AppType app_type_ = ash::AppType::NON_APP; std::string application_id_;
diff --git a/components/exo/ui_lock_controller_unittest.cc b/components/exo/ui_lock_controller_unittest.cc index b66574ee..439782ce 100644 --- a/components/exo/ui_lock_controller_unittest.cc +++ b/components/exo/ui_lock_controller_unittest.cc
@@ -197,7 +197,7 @@ }; TEST_F(UILockControllerTest, HoldingEscapeExitsFullscreen) { - std::unique_ptr<ShellSurface> test_surface = BuildSurface(600, 400); + std::unique_ptr<ShellSurface> test_surface = BuildSurface(1024, 768); test_surface->SetUseImmersiveForFullscreen(false); test_surface->SetFullscreen(true, display::kInvalidDisplayId); test_surface->surface_for_testing()->Commit();
diff --git a/components/exo/wayland/protocol/aura-shell.xml b/components/exo/wayland/protocol/aura-shell.xml index 33988ff..70b533ca 100644 --- a/components/exo/wayland/protocol/aura-shell.xml +++ b/components/exo/wayland/protocol/aura-shell.xml
@@ -241,9 +241,7 @@ <request name="set_frame_colors" since="3"> <description summary="set the frame colors of this surface"> - Set the frame colors. This must be set before the initial - commit first, otherwise the subsequent request may not be - fulfilled. + Set the frame colors. </description> <arg name="active_color" type="uint" summary="32 bit ARGB color value, not premultiplied"/> <arg name="inactive_color" type="uint" summary="32 bit ARGB color value, not premultiplied"/> @@ -987,10 +985,8 @@ <request name="set_decoration" since="35"> <description summary="request a decoration for surface"> Clients are allowed to request a particular decoration for a - zaura_toplevel. The server is not required to honor this - request. See decoration_type for available options. This must - be set before the initial commit first, otherwise the - subsequent request may not be fulfilled. Available since M105. + zaura_toplevel. The server is not required to honor this request. See + decoration_type for available options. Available since M105. </description> <arg name="type" type="uint" summary="the new frame type"/> </request>
diff --git a/components/exo/xdg_shell_surface.cc b/components/exo/xdg_shell_surface.cc index dba2bb2..a40079f 100644 --- a/components/exo/xdg_shell_surface.cc +++ b/components/exo/xdg_shell_surface.cc
@@ -32,12 +32,8 @@ // window property. bool auto_maximize_enabled = params->init_properties_container.GetProperty( chromeos::kAutoMaximizeXdgShellEnabled); - if (auto_maximize_enabled && ShouldAutoMaximize()) { + if (auto_maximize_enabled && ShouldAutoMaximize()) params->show_state = ui::SHOW_STATE_MAXIMIZED; - } - if (!frame_enabled() && !has_frame_colors()) { - params->layer_type = ui::LAYER_NOT_DRAWN; - } } bool XdgShellSurface::ShouldAutoMaximize() {
diff --git a/components/optimization_guide/content/browser/page_content_annotations_model_manager.h b/components/optimization_guide/content/browser/page_content_annotations_model_manager.h index 8b037c8..959dcc4 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_model_manager.h +++ b/components/optimization_guide/content/browser/page_content_annotations_model_manager.h
@@ -73,13 +73,6 @@ kComplete = 3, }; - // Set up the machinery for execution of the page entities model. This should - // only be run at construction. Runs |callback(true)| when the model executor - // has a model file or |callback(false)| if the model executor is not - // available. - void SetUpPageEntitiesModel(OptimizationGuideModelProvider* model_provider, - base::OnceCallback<void(bool)> callback); - // Set up the machinery for execution of the page visibility model. This // should only be run at construction. void SetUpPageVisibilityModel(
diff --git a/components/optimization_guide/core/optimization_guide_constants.cc b/components/optimization_guide/core/optimization_guide_constants.cc index 4ef5190b..8cfde9e 100644 --- a/components/optimization_guide/core/optimization_guide_constants.cc +++ b/components/optimization_guide/core/optimization_guide_constants.cc
@@ -39,9 +39,6 @@ const base::FilePath::CharType kOptimizationGuideModelStoreDirPrefix[] = FILE_PATH_LITERAL("optimization_guide_model_store"); -const base::FilePath::CharType kPageEntitiesMetadataStore[] = - FILE_PATH_LITERAL("page_content_annotations_page_entities_metadata_store"); - const base::FilePath::CharType kSpModelFile[] = FILE_PATH_LITERAL("spm.model"); const base::FilePath::CharType kModelFile[] = FILE_PATH_LITERAL("model.pb");
diff --git a/components/optimization_guide/core/optimization_guide_constants.h b/components/optimization_guide/core/optimization_guide_constants.h index 484b81b0..370a2d0 100644 --- a/components/optimization_guide/core/optimization_guide_constants.h +++ b/components/optimization_guide/core/optimization_guide_constants.h
@@ -60,10 +60,6 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) extern const base::FilePath::CharType kOptimizationGuideModelStoreDirPrefix[]; -// The folder where the page entities metadata store will be stored on disk. -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -extern const base::FilePath::CharType kPageEntitiesMetadataStore[]; - // Files expected to be in the on device model bundle. COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) extern const base::FilePath::CharType kSpModelFile[];
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index fa1d0aa..cb6a629 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -169,30 +169,10 @@ BASE_FEATURE(kRemotePageMetadata, "RemotePageMetadata", enabled_by_default_desktop_only); - -// Enables the page entities model to be annotated on every page load. -BASE_FEATURE(kPageEntitiesPageContentAnnotations, - "PageEntitiesPageContentAnnotations", - base::FEATURE_DISABLED_BY_DEFAULT); // Enables the page visibility model to be annotated on every page load. BASE_FEATURE(kPageVisibilityPageContentAnnotations, "PageVisibilityPageContentAnnotations", base::FEATURE_ENABLED_BY_DEFAULT); -// Enables the text embedding model to be annotated on every page load. -BASE_FEATURE(kTextEmbeddingPageContentAnnotations, - "TextEmbeddingPageContentAnnotations", - base::FEATURE_DISABLED_BY_DEFAULT); - -// This feature flag does not allow for the entities model to load the name and -// prefix filters. -BASE_FEATURE(kPageEntitiesModelBypassFilters, - "PageEntitiesModelBypassFilters", - base::FEATURE_ENABLED_BY_DEFAULT); - -// This feature flag enables resetting the entities model on shutdown. -BASE_FEATURE(kPageEntitiesModelResetOnShutdown, - "PageEntitiesModelResetOnShutdown", - base::FEATURE_DISABLED_BY_DEFAULT); // Enables push notification of hints. BASE_FEATURE(kPushNotifications, @@ -689,12 +669,6 @@ return kContentAnnotationsExtractRelatedSearchesParam.Get(); } -bool ShouldExecutePageEntitiesModelOnPageContent(const std::string& locale) { - return base::FeatureList::IsEnabled(kPageEntitiesPageContentAnnotations) && - IsSupportedLocaleForFeature(locale, - kPageEntitiesPageContentAnnotations); -} - bool ShouldExecutePageVisibilityModelOnPageContent(const std::string& locale) { return base::FeatureList::IsEnabled(kPageVisibilityPageContentAnnotations) && IsSupportedLocaleForFeature(locale, @@ -702,13 +676,6 @@ /*default_value=*/"en"); } -bool ShouldExecuteTextEmbeddingModelOnPageContent(const std::string& locale) { - return (base::FeatureList::IsEnabled(kTextEmbeddingPageContentAnnotations) || - TextEmbeddingBatchAnnotationsEnabled()) && - IsSupportedLocaleForFeature(locale, - kTextEmbeddingPageContentAnnotations); -} - bool RemotePageMetadataEnabled(const std::string& locale, const std::string& country_code) { return base::FeatureList::IsEnabled(kRemotePageMetadata) &&
diff --git a/components/optimization_guide/core/optimization_guide_features.h b/components/optimization_guide/core/optimization_guide_features.h index adc473f..87526fe 100644 --- a/components/optimization_guide/core/optimization_guide_features.h +++ b/components/optimization_guide/core/optimization_guide_features.h
@@ -43,16 +43,8 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kPageContentAnnotations); COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -BASE_DECLARE_FEATURE(kPageEntitiesPageContentAnnotations); -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -BASE_DECLARE_FEATURE(kPageEntitiesModelBypassFilters); -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -BASE_DECLARE_FEATURE(kPageEntitiesModelResetOnShutdown); -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kPageVisibilityPageContentAnnotations); COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -BASE_DECLARE_FEATURE(kTextEmbeddingPageContentAnnotations); -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kPageTextExtraction); COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kPushNotifications); @@ -61,8 +53,6 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kPageVisibilityBatchAnnotations); COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -BASE_DECLARE_FEATURE(kTextEmbeddingBatchAnnotations); -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kPageContentAnnotationsValidation); COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kPreventLongRunningPredictionModels); @@ -81,8 +71,6 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kOptimizationGuidePersonalizedFetching); COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -BASE_DECLARE_FEATURE(kQueryInMemoryTextEmbeddings); -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kOptimizationGuidePredictionModelKillswitch); COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) BASE_DECLARE_FEATURE(kOptimizationGuideModelExecution); @@ -373,11 +361,6 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) bool ShouldExecutePageVisibilityModelOnPageContent(const std::string& locale); -// Returns whether the text embedding model should be executed on page content -// for a user using |locale| as their browser language. -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -bool ShouldExecuteTextEmbeddingModelOnPageContent(const std::string& locale); - // Returns whether page metadata should be retrieved from the remote // Optimization Guide service. COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) @@ -412,10 +395,6 @@ COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) bool PageVisibilityBatchAnnotationsEnabled(); -// Returns if Text Embedding Batch Annotations are enabled. -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -bool TextEmbeddingBatchAnnotationsEnabled(); - // The number of visits batch before running the page content annotation // models. A size of 1 is equivalent to annotating one page load at time // immediately after requested. @@ -460,10 +439,6 @@ bool ShouldPersistSalientImageMetadata(const std::string& locale, const std::string& country_code); -// Returns whether to query text embeddings coming from history service. -COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) -bool ShouldQueryEmbeddings(); - // Whether logging of model quality is enabled. COMPONENT_EXPORT(OPTIMIZATION_GUIDE_FEATURES) bool IsModelQualityLoggingEnabled();
diff --git a/components/optimization_guide/core/optimization_guide_features_unittest.cc b/components/optimization_guide/core/optimization_guide_features_unittest.cc index 13f9ed3..88fde758 100644 --- a/components/optimization_guide/core/optimization_guide_features_unittest.cc +++ b/components/optimization_guide/core/optimization_guide_features_unittest.cc
@@ -74,26 +74,6 @@ EXPECT_EQ(.2, features::NoiseProbabilityForRAPPORMetrics()); } -TEST(OptimizationGuideFeaturesTest, - ShouldExecutePageEntitiesModelOnPageContentDisabled) { - base::test::ScopedFeatureList scoped_feature_list; - - scoped_feature_list.InitAndDisableFeature( - features::kPageEntitiesPageContentAnnotations); - - EXPECT_FALSE(features::ShouldExecutePageEntitiesModelOnPageContent("en-US")); -} - -TEST(OptimizationGuideFeaturesTest, - ShouldExecutePageEntitiesModelOnPageContentEmptyAllowlist) { - base::test::ScopedFeatureList scoped_feature_list; - - scoped_feature_list.InitAndEnableFeature( - features::kPageEntitiesPageContentAnnotations); - - EXPECT_TRUE(features::ShouldExecutePageEntitiesModelOnPageContent("en-US")); -} - TEST(OptimizationGuideFeaturesTest, ModelQualityLoggingDefault) { base::test::ScopedFeatureList scoped_feature_list; @@ -153,19 +133,6 @@ } TEST(OptimizationGuideFeaturesTest, - ShouldExecutePageEntitiesModelOnPageContentWithAllowlist) { - base::test::ScopedFeatureList scoped_feature_list; - - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kPageEntitiesPageContentAnnotations, - {{"supported_locales", "en,zh-TW"}}); - - EXPECT_TRUE(features::ShouldExecutePageEntitiesModelOnPageContent("en-US")); - EXPECT_FALSE(features::ShouldExecutePageEntitiesModelOnPageContent("")); - EXPECT_FALSE(features::ShouldExecutePageEntitiesModelOnPageContent("zh-CN")); -} - -TEST(OptimizationGuideFeaturesTest, ShouldExecutePageVisibilityModelOnPageContentDisabled) { base::test::ScopedFeatureList scoped_feature_list;
diff --git a/components/optimization_guide/core/prediction_manager.cc b/components/optimization_guide/core/prediction_manager.cc index 20a42e1f..4dc29de 100644 --- a/components/optimization_guide/core/prediction_manager.cc +++ b/components/optimization_guide/core/prediction_manager.cc
@@ -125,10 +125,6 @@ model_metadata.type_url() == "type.googleapis.com/" "google.internal.chrome.optimizationguide.v1." - "PageEntitiesModelMetadata" || - model_metadata.type_url() == - "type.googleapis.com/" - "google.internal.chrome.optimizationguide.v1." "PageTopicsModelMetadata" || model_metadata.type_url() == "type.googleapis.com/"
diff --git a/components/optimization_guide/core/prediction_manager_unittest.cc b/components/optimization_guide/core/prediction_manager_unittest.cc index 1a3f1f3..298f4ca0 100644 --- a/components/optimization_guide/core/prediction_manager_unittest.cc +++ b/components/optimization_guide/core/prediction_manager_unittest.cc
@@ -683,7 +683,7 @@ proto::Any model_metadata; model_metadata.set_type_url( "type.googleapis.com/" - "google.internal.chrome.optimizationguide.v1.PageEntitiesModelMetadata"); + "google.internal.chrome.optimizationguide.v1.PageTopicsModelMetadata"); prediction_model_fetcher()->SetExpectedModelMetadataForOptimizationTarget( proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, model_metadata); histogram_tester.ExpectTotalCount( @@ -853,7 +853,7 @@ optimization_guide::proto::Any metadata; metadata.set_type_url( "type.googleapis.com/" - "google.internal.chrome.optimizationguide.v1.PageEntitiesModelMetadata"); + "google.internal.chrome.optimizationguide.v1.PageTopicsModelMetadata"); std::string encoded_metadata; metadata.SerializeToString(&encoded_metadata); encoded_metadata = base::Base64Encode(encoded_metadata); @@ -870,7 +870,7 @@ proto::Any model_metadata; model_metadata.set_type_url( "type.googleapis.com/" - "google.internal.chrome.optimizationguide.v1.PageEntitiesModelMetadata"); + "google.internal.chrome.optimizationguide.v1.PageTopicsModelMetadata"); prediction_model_fetcher()->SetExpectedModelMetadataForOptimizationTarget( proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, model_metadata); @@ -897,7 +897,7 @@ ->GetModelMetadata() ->type_url(), "type.googleapis.com/" - "google.internal.chrome.optimizationguide.v1.PageEntitiesModelMetadata"); + "google.internal.chrome.optimizationguide.v1.PageTopicsModelMetadata"); EXPECT_EQ(observer .last_received_model_for_target( proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD)
diff --git a/components/optimization_guide/proto/BUILD.gn b/components/optimization_guide/proto/BUILD.gn index 76fd3832..82b1812 100644 --- a/components/optimization_guide/proto/BUILD.gn +++ b/components/optimization_guide/proto/BUILD.gn
@@ -32,7 +32,6 @@ "on_device_base_model_metadata.proto", "on_device_tail_suggest_model_metadata.proto", "page_entities_metadata.proto", - "page_entities_model_metadata.proto", "page_topics_model_metadata.proto", "page_topics_override_list.proto", "push_notification.proto",
diff --git a/components/optimization_guide/proto/page_entities_model_metadata.proto b/components/optimization_guide/proto/page_entities_model_metadata.proto deleted file mode 100644 index 00a9271..0000000 --- a/components/optimization_guide/proto/page_entities_model_metadata.proto +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -syntax = "proto2"; - -option optimize_for = LITE_RUNTIME; -option java_package = "org.chromium.components.optimization_guide.proto"; -option java_outer_classname = "PageEntitiesModelMetadataProto"; - -package optimization_guide.proto; - -message PageEntitiesModelMetadata { - // The maximum model format feature flag that is supported. - // - // If sent from the server, this is the maximum model format feature flag the - // returned model supports. If sent from the client, this is the maximum - // model format feature flag the client knows how to evaluate. - optional int32 max_model_format_feature_flag = 1; - - // The slices to load into the entity annotator. - // - // Will only be populated by the server. - repeated string slice = 2; -} \ No newline at end of file
diff --git a/components/password_manager/core/browser/password_store/fake_password_store_backend.cc b/components/password_manager/core/browser/password_store/fake_password_store_backend.cc index 5520d90..2edd2673 100644 --- a/components/password_manager/core/browser/password_store/fake_password_store_backend.cc +++ b/components/password_manager/core/browser/password_store/fake_password_store_backend.cc
@@ -222,6 +222,10 @@ NOTIMPLEMENTED(); } +void FakePasswordStoreBackend::RecordAddLoginAsyncCalledFromTheStore() {} + +void FakePasswordStoreBackend::RecordUpdateLoginAsyncCalledFromTheStore() {} + base::WeakPtr<PasswordStoreBackend> FakePasswordStoreBackend::AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
diff --git a/components/password_manager/core/browser/password_store/fake_password_store_backend.h b/components/password_manager/core/browser/password_store/fake_password_store_backend.h index 866fcc69..8672039 100644 --- a/components/password_manager/core/browser/password_store/fake_password_store_backend.h +++ b/components/password_manager/core/browser/password_store/fake_password_store_backend.h
@@ -98,6 +98,8 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegate() override; void OnSyncServiceInitialized(syncer::SyncService* sync_service) override; + void RecordAddLoginAsyncCalledFromTheStore() override; + void RecordUpdateLoginAsyncCalledFromTheStore() override; base::WeakPtr<PasswordStoreBackend> AsWeakPtr() override; // Returns the task runner. Defaults to
diff --git a/components/password_manager/core/browser/password_store/mock_password_store_backend.h b/components/password_manager/core/browser/password_store/mock_password_store_backend.h index 0ee5193..cfa7083 100644 --- a/components/password_manager/core/browser/password_store/mock_password_store_backend.h +++ b/components/password_manager/core/browser/password_store/mock_password_store_backend.h
@@ -98,6 +98,8 @@ OnSyncServiceInitialized, (syncer::SyncService*), (override)); + MOCK_METHOD(void, RecordAddLoginAsyncCalledFromTheStore, (), (override)); + MOCK_METHOD(void, RecordUpdateLoginAsyncCalledFromTheStore, (), (override)); base::WeakPtr<PasswordStoreBackend> AsWeakPtr() override;
diff --git a/components/password_manager/core/browser/password_store/password_store.cc b/components/password_manager/core/browser/password_store/password_store.cc index 1ebc0d37..ae4e976 100644 --- a/components/password_manager/core/browser/password_store/password_store.cc +++ b/components/password_manager/core/browser/password_store/password_store.cc
@@ -116,6 +116,7 @@ CHECK(!form.blocked_by_user || (form.username_value.empty() && form.password_value.empty())); backend_->AddLoginAsync(form, barrier_callback); + backend_->RecordAddLoginAsyncCalledFromTheStore(); } } @@ -143,6 +144,7 @@ CHECK(!form.blocked_by_user || (form.username_value.empty() && form.password_value.empty())); backend_->UpdateLoginAsync(form, barrier_callback); + backend_->RecordUpdateLoginAsyncCalledFromTheStore(); } } @@ -181,6 +183,7 @@ backend_->RemoveLoginAsync(old_primary_key, barrier_callback); backend_->AddLoginAsync(new_form_with_correct_password_issues, barrier_callback); + backend_->RecordAddLoginAsyncCalledFromTheStore(); } void PasswordStore::RemoveLogin(const PasswordForm& form) {
diff --git a/components/password_manager/core/browser/password_store/password_store_backend.h b/components/password_manager/core/browser/password_store/password_store_backend.h index 34d9269..f21048a 100644 --- a/components/password_manager/core/browser/password_store/password_store_backend.h +++ b/components/password_manager/core/browser/password_store/password_store_backend.h
@@ -154,6 +154,14 @@ // Propagates sync initialization event. virtual void OnSyncServiceInitialized(syncer::SyncService* sync_service) = 0; + // Records calls to the `AddLoginAsync()` from the password store. + // TODO: crbug.com/327126704 - Remove this method after UPM is launched. + virtual void RecordAddLoginAsyncCalledFromTheStore() = 0; + + // Records calls to the `UpdateLoginAsync()` from the password store. + // TODO: crbug.com/327126704 - Remove this method after UPM is launched. + virtual void RecordUpdateLoginAsyncCalledFromTheStore() = 0; + // Get a WeakPtr to the instance. virtual base::WeakPtr<PasswordStoreBackend> AsWeakPtr() = 0; };
diff --git a/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc b/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc index 7fd65ad..90490d4 100644 --- a/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc +++ b/components/password_manager/core/browser/password_store/password_store_built_in_backend.cc
@@ -296,6 +296,18 @@ void PasswordStoreBuiltInBackend::OnSyncServiceInitialized( syncer::SyncService* sync_service) {} +void PasswordStoreBuiltInBackend::RecordAddLoginAsyncCalledFromTheStore() { + base::UmaHistogramBoolean( + "PasswordManager.PasswordStore.BuiltInBackend.AddLoginCalledOnStore", + true); +} + +void PasswordStoreBuiltInBackend::RecordUpdateLoginAsyncCalledFromTheStore() { + base::UmaHistogramBoolean( + "PasswordManager.PasswordStore.BuiltInBackend.UpdateLoginCalledOnStore", + true); +} + base::WeakPtr<PasswordStoreBackend> PasswordStoreBuiltInBackend::AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
diff --git a/components/password_manager/core/browser/password_store/password_store_built_in_backend.h b/components/password_manager/core/browser/password_store/password_store_built_in_backend.h index 68eb8f21..5ba36b4 100644 --- a/components/password_manager/core/browser/password_store/password_store_built_in_backend.h +++ b/components/password_manager/core/browser/password_store/password_store_built_in_backend.h
@@ -87,6 +87,8 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegate() override; void OnSyncServiceInitialized(syncer::SyncService* sync_service) override; + void RecordAddLoginAsyncCalledFromTheStore() override; + void RecordUpdateLoginAsyncCalledFromTheStore() override; base::WeakPtr<PasswordStoreBackend> AsWeakPtr() override; // SmartBubbleStatsStore:
diff --git a/components/password_manager/core/browser/password_store/password_store_unittest.cc b/components/password_manager/core/browser/password_store/password_store_unittest.cc index c38b1c8..96587ae2 100644 --- a/components/password_manager/core/browser/password_store/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store/password_store_unittest.cc
@@ -232,6 +232,7 @@ } TEST_F(PasswordStoreTest, UpdateLoginPrimaryKeyFields) { + base::HistogramTester histogram_tester; /* clang-format off */ static const PasswordFormData kTestCredentials[] = { // The old credential. @@ -277,6 +278,9 @@ old_primary_key.password_element = old_form->password_element; store->UpdateLoginWithPrimaryKey(*new_form, old_primary_key); WaitForPasswordStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.BuiltInBackend.AddLoginCalledOnStore", + true, 2); testing::Mock::VerifyAndClearExpectations(&mock_observer); MockPasswordStoreConsumer mock_consumer; @@ -296,6 +300,7 @@ } TEST_F(PasswordStoreTest, AddLogins) { + base::HistogramTester histogram_tester; std::vector<PasswordForm> all_credentials; all_credentials.push_back(*FillPasswordFormWithData( CreateTestPasswordFormDataByOrigin(kTestWebRealm1))); @@ -311,6 +316,9 @@ EXPECT_CALL(mock_observer, OnLoginsChanged(_, testing::SizeIs(2u))); store->AddLogins({all_credentials[0], all_credentials[1]}); WaitForPasswordStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.BuiltInBackend.AddLoginCalledOnStore", + true, all_credentials.size()); testing::Mock::VerifyAndClearExpectations(&mock_observer); @@ -329,6 +337,8 @@ } TEST_F(PasswordStoreTest, UpdateLogins) { + base::HistogramTester histogram_tester; + PasswordFormData form_data_1 = CreateTestPasswordFormDataByOrigin(kTestWebRealm1); PasswordFormData form_data_2 = @@ -343,6 +353,9 @@ store->AddLogins(all_credentials); WaitForPasswordStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.BuiltInBackend.AddLoginCalledOnStore", + true, all_credentials.size()); form_data_1.password_value = u"new_password1"; form_data_2.password_value = u"new_password2"; @@ -361,6 +374,9 @@ EXPECT_CALL(mock_observer, OnLoginsChanged(_, testing::SizeIs(2u))); store->UpdateLogins(updated_credentials); WaitForPasswordStore(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.PasswordStore.BuiltInBackend.UpdateLoginCalledOnStore", + true, all_credentials.size()); testing::Mock::VerifyAndClearExpectations(&mock_observer);
diff --git a/components/sync/engine/debug_info_event_listener.cc b/components/sync/engine/debug_info_event_listener.cc index 432f6c774..e80ce305 100644 --- a/components/sync/engine/debug_info_event_listener.cc +++ b/components/sync/engine/debug_info_event_listener.cc
@@ -38,11 +38,6 @@ sync_completed_event_info->mutable_caller_info()->set_notifications_enabled( snapshot.notifications_enabled()); - // Fill the legacy GetUpdatesSource field. This is not used anymore, but it's - // a required field so we still have to fill it with something. - sync_completed_event_info->mutable_caller_info()->set_source( - sync_pb::GetUpdatesCallerInfo::UNKNOWN); - AddEventToQueue(event_info); }
diff --git a/components/sync/engine/get_updates_delegate.cc b/components/sync/engine/get_updates_delegate.cc index 3a99bdee..323327a 100644 --- a/components/sync/engine/get_updates_delegate.cc +++ b/components/sync/engine/get_updates_delegate.cc
@@ -24,11 +24,6 @@ // This function assumes the progress markers have already been populated. void NormalGetUpdatesDelegate::HelpPopulateGuMessage( sync_pb::GetUpdatesMessage* get_updates) const { - // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. It's not - // used anymore, but |source| is a required field so we have to set it anyway. - get_updates->mutable_caller_info()->set_source( - sync_pb::GetUpdatesCallerInfo::UNKNOWN); - // Set the origin. get_updates->set_get_updates_origin(sync_pb::SyncEnums::GU_TRIGGER); get_updates->set_is_retry(nudge_tracker_->IsRetryRequired()); @@ -72,11 +67,6 @@ void ConfigureGetUpdatesDelegate::HelpPopulateGuMessage( sync_pb::GetUpdatesMessage* get_updates) const { - // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. It's not - // used anymore, but |source| is a required field so we have to set it anyway. - get_updates->mutable_caller_info()->set_source( - sync_pb::GetUpdatesCallerInfo::UNKNOWN); - get_updates->set_get_updates_origin(origin_); } @@ -98,11 +88,6 @@ void PollGetUpdatesDelegate::HelpPopulateGuMessage( sync_pb::GetUpdatesMessage* get_updates) const { - // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information. It's not - // used anymore, but |source| is a required field so we have to set it anyway. - get_updates->mutable_caller_info()->set_source( - sync_pb::GetUpdatesCallerInfo::UNKNOWN); - get_updates->set_get_updates_origin(sync_pb::SyncEnums::PERIODIC); }
diff --git a/components/sync/engine/get_updates_processor_unittest.cc b/components/sync/engine/get_updates_processor_unittest.cc index 0c3cda9..3984621 100644 --- a/components/sync/engine/get_updates_processor_unittest.cc +++ b/components/sync/engine/get_updates_processor_unittest.cc
@@ -115,8 +115,6 @@ processor->PrepareGetUpdates(enabled_types(), &message); const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates(); - EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, - gu_msg.caller_info().source()); EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin()); for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) { ModelType type = GetModelTypeFromSpecificsFieldNumber( @@ -160,8 +158,6 @@ processor->PrepareGetUpdates(enabled_types(), &message); const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates(); - EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, - gu_msg.caller_info().source()); EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin()); EXPECT_EQ(1, autofill_handler->GetPrepareGetUpdatesCount()); @@ -231,8 +227,6 @@ processor->PrepareGetUpdates(enabled_types(), &message); const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates(); - EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, - gu_msg.caller_info().source()); EXPECT_EQ(sync_pb::SyncEnums::GU_TRIGGER, gu_msg.get_updates_origin()); for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) { ModelType type = GetModelTypeFromSpecificsFieldNumber( @@ -264,8 +258,6 @@ const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates(); EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION, gu_msg.get_updates_origin()); - EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, - gu_msg.caller_info().source()); ModelTypeSet progress_types; for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) { @@ -285,8 +277,6 @@ const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates(); EXPECT_EQ(sync_pb::SyncEnums::PERIODIC, gu_msg.get_updates_origin()); - EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, - gu_msg.caller_info().source()); ModelTypeSet progress_types; for (int i = 0; i < gu_msg.from_progress_marker_size(); ++i) { @@ -315,8 +305,6 @@ const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates(); EXPECT_EQ(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin()); - EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, - gu_msg.caller_info().source()); EXPECT_TRUE(gu_msg.is_retry()); ModelTypeSet progress_types; @@ -349,8 +337,6 @@ const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates(); EXPECT_NE(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin()); - EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::UNKNOWN, - gu_msg.caller_info().source()); EXPECT_TRUE(gu_msg.is_retry()); }
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc index d169803b..725c1eb8 100644 --- a/components/user_manager/user_manager_base.cc +++ b/components/user_manager/user_manager_base.cc
@@ -1185,7 +1185,9 @@ DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence()); DCHECK(active_user_); - // TODO(b/278643115): Call Observer::OnUserLoggedIn() from here. + for (auto& observer : observer_list_) { + observer.OnUserLoggedIn(*active_user_); + } NotifyActiveUserChanged(active_user_); NotifyLoginStateUpdated();
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 958ef92e..e02e4e7 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2240,11 +2240,10 @@ "webauth/client_data_json.h", "webauth/webauth_request_security_checker.cc", "webauth/webauth_request_security_checker.h", - "webid/digital_credentials/digital_identity_provider.cc", - "webid/digital_credentials/digital_identity_provider.h", + "webid/digital_credentials/digital_identity_provider_utils.cc", + "webid/digital_credentials/digital_identity_provider_utils.h", "webid/digital_credentials/digital_identity_request_impl.cc", "webid/digital_credentials/digital_identity_request_impl.h", - "webid/digital_credentials/digital_identity_types.h", "webid/fake_identity_request_dialog_controller.cc", "webid/fake_identity_request_dialog_controller.h", "webid/fedcm_metrics.cc", @@ -3478,9 +3477,6 @@ java_cpp_enum("client_data_json_generated_enum") { sources = [ "webauth/client_data_json.h" ] } - java_cpp_enum("digital_identity_enum") { - sources = [ "webid/digital_credentials/digital_identity_types.h" ] - } } if (is_mac) {
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc index ffb56f7..c572f55 100644 --- a/content/browser/cross_origin_opener_policy_browsertest.cc +++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -7527,14 +7527,9 @@ // Smoke test for the case where a proxy for a given subframe is created before // other subframe proxies, that might be below it in the indexed order. -// TODO(1495328): Failing on Mac bots -#if BUILDFLAG(IS_MAC) -#define MAYBE_SubframesProxiesInWrongOrderSmokeTest DISABLED_SubframesProxiesInWrongOrderSmokeTest -#else -#define MAYBE_SubframesProxiesInWrongOrderSmokeTest SubframesProxiesInWrongOrderSmokeTest -#endif +// TODO(1495328,40269878): Failing on bots in multiple platforms IN_PROC_BROWSER_TEST_P(CoopRestrictPropertiesProxiesBrowserTest, - MAYBE_SubframesProxiesInWrongOrderSmokeTest) { + DISABLED_SubframesProxiesInWrongOrderSmokeTest) { GURL coop_rp_page(https_server()->GetURL( "a.test", "/set-header"
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index 87c5ae5..7f6b738 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -1628,6 +1628,8 @@ return Page::BackForwardCacheNotRestoredReasonEnum::LiveMediaStreamTrack; case WebSchedulerTrackedFeature::kUnloadHandler: return Page::BackForwardCacheNotRestoredReasonEnum::UnloadHandler; + case WebSchedulerTrackedFeature::kParserAborted: + return Page::BackForwardCacheNotRestoredReasonEnum::ParserAborted; } } @@ -1828,6 +1830,7 @@ case WebSchedulerTrackedFeature::kSmartCard: case WebSchedulerTrackedFeature::kLiveMediaStreamTrack: case WebSchedulerTrackedFeature::kUnloadHandler: + case WebSchedulerTrackedFeature::kParserAborted: return Page::BackForwardCacheNotRestoredReasonTypeEnum::PageSupportNeeded; case WebSchedulerTrackedFeature::kPortal: case WebSchedulerTrackedFeature::kWebNfc:
diff --git a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc index 7a193205..acac86e 100644 --- a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc +++ b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
@@ -475,8 +475,6 @@ return "not-main-frame"; case Reason::kRelatedActiveContentsExist: return "related-active-contents"; - case Reason::kHTTPStatusNotOK: - return "http-status-not-ok"; case Reason::kSchemeNotHTTPOrHTTPS: return "not-http-https-scheme"; case Reason::kLoading: @@ -510,6 +508,7 @@ case Reason::kNoResponseHead: return "no-response-head"; case Reason::kErrorDocument: + case Reason::kHTTPStatusNotOK: return "navigation-failure"; case Reason::kUnloadHandlerExistsInMainFrame: case Reason::kUnloadHandlerExistsInSubFrame:
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc index 6e6615e9..58defc71 100644 --- a/content/browser/renderer_host/back_forward_cache_impl.cc +++ b/content/browser/renderer_host/back_forward_cache_impl.cc
@@ -209,7 +209,8 @@ WebSchedulerTrackedFeature::kWebShare, WebSchedulerTrackedFeature::kWebSocket, WebSchedulerTrackedFeature::kWebTransport, - WebSchedulerTrackedFeature::kWebXR}; + WebSchedulerTrackedFeature::kWebXR, + WebSchedulerTrackedFeature::kParserAborted}; } WebSchedulerTrackedFeatures GetInjectionWebSchedulerTrackedFeatures() { return {WebSchedulerTrackedFeature::kInjectedJavascript,
diff --git a/content/browser/webid/digital_credentials/digital_identity_provider_android.cc b/content/browser/webid/digital_credentials/digital_identity_provider_android.cc index e042315..7d530ee 100644 --- a/content/browser/webid/digital_credentials/digital_identity_provider_android.cc +++ b/content/browser/webid/digital_credentials/digital_identity_provider_android.cc
@@ -10,7 +10,6 @@ #include "base/android/jni_string.h" #include "base/json/json_writer.h" #include "base/values.h" -#include "content/browser/webid/digital_credentials/digital_identity_types.h" #include "content/public/android/content_jni_headers/DigitalIdentityProvider_jni.h" #include "content/public/browser/web_contents.h" #include "ui/android/window_android.h" @@ -67,7 +66,7 @@ ConvertJavaStringToUTF8(env, j_digital_identity); std::move(callback_).Run( digital_identity, - static_cast<digital_identity::RequestStatusForMetrics>( + static_cast<DigitalIdentityProvider::RequestStatusForMetrics>( status_for_metrics)); } }
diff --git a/content/browser/webid/digital_credentials/digital_identity_provider_android.h b/content/browser/webid/digital_credentials/digital_identity_provider_android.h index 815cf2b7..2aa1e49 100644 --- a/content/browser/webid/digital_credentials/digital_identity_provider_android.h +++ b/content/browser/webid/digital_credentials/digital_identity_provider_android.h
@@ -8,8 +8,8 @@ #include "base/android/scoped_java_ref.h" #include "base/functional/callback.h" #include "base/values.h" -#include "content/browser/webid/digital_credentials/digital_identity_provider.h" #include "content/common/content_export.h" +#include "content/public/browser/digital_identity_provider.h" #include "third_party/blink/public/mojom/webid/digital_identity_request.mojom.h" #include "url/origin.h"
diff --git a/content/browser/webid/digital_credentials/digital_identity_provider.cc b/content/browser/webid/digital_credentials/digital_identity_provider_utils.cc similarity index 69% rename from content/browser/webid/digital_credentials/digital_identity_provider.cc rename to content/browser/webid/digital_credentials/digital_identity_provider_utils.cc index 950b1169..43e1fb0 100644 --- a/content/browser/webid/digital_credentials/digital_identity_provider.cc +++ b/content/browser/webid/digital_credentials/digital_identity_provider_utils.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 "content/browser/webid/digital_credentials/digital_identity_provider.h" +#include "content/browser/webid/digital_credentials/digital_identity_provider_utils.h" #include "build/build_config.h" @@ -12,11 +12,7 @@ namespace content { -DigitalIdentityProvider::DigitalIdentityProvider() = default; -DigitalIdentityProvider::~DigitalIdentityProvider() = default; - -// static -std::unique_ptr<DigitalIdentityProvider> DigitalIdentityProvider::Create() { +std::unique_ptr<DigitalIdentityProvider> CreateDigitalIdentityProvider() { #if BUILDFLAG(IS_ANDROID) return std::make_unique<DigitalIdentityProviderAndroid>(); #else
diff --git a/content/browser/webid/digital_credentials/digital_identity_provider_utils.h b/content/browser/webid/digital_credentials/digital_identity_provider_utils.h new file mode 100644 index 0000000..cc5b81a --- /dev/null +++ b/content/browser/webid/digital_credentials/digital_identity_provider_utils.h
@@ -0,0 +1,20 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_PROVIDER_UTILS_H_ +#define CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_PROVIDER_UTILS_H_ + +#include <memory> + +#include "content/common/content_export.h" +#include "content/public/browser/digital_identity_provider.h" + +namespace content { + +CONTENT_EXPORT std::unique_ptr<DigitalIdentityProvider> +CreateDigitalIdentityProvider(); + +} // namespace content + +#endif // CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_PROVIDER_UTILS_H_
diff --git a/content/browser/webid/digital_credentials/digital_identity_request_impl.cc b/content/browser/webid/digital_credentials/digital_identity_request_impl.cc index 1a9487e..8f0a7c4 100644 --- a/content/browser/webid/digital_credentials/digital_identity_request_impl.cc +++ b/content/browser/webid/digital_credentials/digital_identity_request_impl.cc
@@ -8,17 +8,18 @@ #include "base/metrics/histogram_functions.h" #include "base/values.h" #include "content/browser/renderer_host/render_frame_host_impl.h" -#include "content/browser/webid/digital_credentials/digital_identity_provider.h" -#include "content/browser/webid/digital_credentials/digital_identity_types.h" +#include "content/browser/webid/digital_credentials/digital_identity_provider_utils.h" #include "content/browser/webid/flags.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/digital_identity_provider.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h" using base::Value; using blink::mojom::RequestDigitalIdentityStatus; -using content::digital_identity::RequestStatusForMetrics; +using RequestStatusForMetrics = + content::DigitalIdentityProvider::RequestStatusForMetrics; namespace content { @@ -171,7 +172,7 @@ GetContentClient()->browser()->CreateDigitalIdentityProvider(); if (!provider) { - return DigitalIdentityProvider::Create(); + return CreateDigitalIdentityProvider(); } return provider; }
diff --git a/content/browser/webid/digital_credentials/digital_identity_request_impl.h b/content/browser/webid/digital_credentials/digital_identity_request_impl.h index 068da97..997efab 100644 --- a/content/browser/webid/digital_credentials/digital_identity_request_impl.h +++ b/content/browser/webid/digital_credentials/digital_identity_request_impl.h
@@ -10,8 +10,8 @@ #include <vector> #include "base/memory/weak_ptr.h" -#include "content/browser/webid/digital_credentials/digital_identity_types.h" #include "content/common/content_export.h" +#include "content/public/browser/digital_identity_provider.h" #include "content/public/browser/document_service.h" #include "third_party/blink/public/mojom/webid/digital_identity_request.mojom.h" #include "url/gurl.h" @@ -56,12 +56,12 @@ // `status_for_metrics`. void CompleteRequest( const std::string& response, - digital_identity::RequestStatusForMetrics status_for_metrics); + DigitalIdentityProvider::RequestStatusForMetrics status_for_metrics); void CompleteRequestWithStatus( blink::mojom::RequestDigitalIdentityStatus status, const std::string& response, - digital_identity::RequestStatusForMetrics status_for_metrics); + DigitalIdentityProvider::RequestStatusForMetrics status_for_metrics); std::unique_ptr<DigitalIdentityProvider> CreateProvider();
diff --git a/content/browser/webid/digital_credentials/digital_identity_types.h b/content/browser/webid/digital_credentials/digital_identity_types.h deleted file mode 100644 index f4bf9bea..0000000 --- a/content/browser/webid/digital_credentials/digital_identity_types.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_TYPES_H_ -#define CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_TYPES_H_ - -namespace content::digital_identity { - -// Do not reorder or change the values because the enum values are being -// recorded in metrics. -// A Java counterpart will be generated for this enum. -// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.webid -// GENERATED_JAVA_CLASS_NAME_OVERRIDE: DigitalIdentityRequestStatusForMetrics -enum class RequestStatusForMetrics { - kSuccess = 0, - kErrorOther = 1, - kErrorNoCredential = 2, - kErrorUserDeclined = 3, - kErrorAborted = 4, - kMaxValue = kErrorAborted, -}; - -} // namespace content::digital_identity - -#endif // CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_TYPES_H_
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index 944c8247a..1e255b1 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -741,6 +741,9 @@ /*is_disabled=*/idp_get_params_ptrs.size() > 1); } + had_transient_user_activation_ = + render_frame_host().HasTransientUserActivation(); + if (HasPendingRequest()) { RpMode pending_request_rp_mode = GetPageData(&render_frame_host()) ->PendingWebIdentityRequest() @@ -748,7 +751,7 @@ bool can_replace_pending_request = IsFedCmButtonModeEnabled() && idp_get_params_ptrs[0]->mode == RpMode::kButton && - render_frame_host().HasTransientUserActivation() && + had_transient_user_activation_ && pending_request_rp_mode != RpMode::kButton; // TODO(crbug.com/326587232): We should add metrics to capture @@ -777,6 +780,10 @@ /*token_status=*/std::nullopt, /*token_error=*/std::nullopt, /*should_delay_callback=*/false); + + // This was reset to false during CleanUp when replacing a widget flow + // from the same frame so we need to change it back to true. + had_transient_user_activation_ = true; } bool intercept = false; @@ -797,7 +804,7 @@ if (IsFedCmButtonModeEnabled() && idp_get_params_ptrs[0]->mode == blink::mojom::RpMode::kButton) { rp_mode_ = RpMode::kButton; - if (!render_frame_host().HasTransientUserActivation()) { + if (!had_transient_user_activation_) { // TODO(crbug.com/1487270): use a more specific error. CompleteRequestWithError(FederatedAuthRequestResult::kError, TokenStatus::kUnhandledRequest, @@ -912,7 +919,7 @@ mojo::ReportBadMessage("FedCM button mode is not enabled."); return; } - if (!render_frame_host().HasTransientUserActivation()) { + if (!had_transient_user_activation_) { // TODO(crbug.com/1487270): use a more specific error. CompleteRequestWithError(FederatedAuthRequestResult::kError, TokenStatus::kUnhandledRequest, @@ -1188,21 +1195,9 @@ FedCmIdpSigninStatusMode::ENABLED) { // If the user is logged out and we are in a button-mode, allow the user // to sign-in to the IdP and return early. - // TODO(https://crbug.com/1490611): handle the "unknown" status and button - // flows. - if (IsFedCmButtonModeEnabled() && - idp_info->rp_mode == blink::mojom::RpMode::kButton && - idp_info->metadata.idp_login_url.is_valid()) { - // We fail sooner before, but just to double check, we assert that - // we are inside a user gesture here again. - CHECK(render_frame_host().HasTransientUserActivation()); - // TODO(crbug.com/1487270): we should probably make idp_login_url - // optional instead of empty. - LoginToIdP(/*can_append_hints=*/false, identity_provider_config_url, - idp_info->metadata.idp_login_url); - // TODO(https://crbug.com/1487268): handle the button flow and the - // Multi IdP API (what should happen if you are logged in to some - // IdPs but not to others). + if (rp_mode_ == blink::mojom::RpMode::kButton) { + MaybeShowButtonModeModalDialog(identity_provider_config_url, + idp_info->metadata.idp_login_url); return; } // Do not send metrics for IDP where the user is not signed-in in order @@ -1214,7 +1209,7 @@ std::move(idp_info), FederatedAuthRequestResult::kErrorNotSignedInWithIdp, TokenStatus::kNotSignedInWithIdp, - /*should_delay_callback=*/rp_mode_ == RpMode::kWidget); + /*should_delay_callback=*/true); continue; } @@ -1637,6 +1632,11 @@ if (!old_idp_signin_status.has_value() || signin_status_mode == FedCmIdpSigninStatusMode::METRICS_ONLY) { + if (rp_mode_ == blink::mojom::RpMode::kButton) { + MaybeShowButtonModeModalDialog(idp_info->provider->config->config_url, + idp_info->metadata.idp_login_url); + return; + } OnFetchDataForIdpFailed(std::move(idp_info), result, token_status, /*should_delay_callback=*/true); return; @@ -2471,6 +2471,7 @@ token_error_ = std::nullopt; dialog_type_ = kNone; identity_selection_type_ = kExplicit; + had_transient_user_activation_ = false; rp_mode_ = RpMode::kWidget; } @@ -2836,6 +2837,27 @@ ShowModalDialog(idp_config_url, login_url); } +void FederatedAuthRequestImpl::MaybeShowButtonModeModalDialog( + const GURL& idp_config_url, + const GURL& idp_login_url) { + if (IsFedCmMultipleIdentityProvidersEnabled() && idp_infos_.size() > 1) { + // TODO(https://crbug.com/1487268): handle the button flow and the + // Multi IdP API (what should happen if you are logged in to some + // IdPs but not to others). + // TODO(crbug.com/326987150): This is temporary so we should degrade + // gracefully. + return; + } + + // We fail sooner before, but just to double check, we assert that + // we are inside a user gesture here again. + CHECK(had_transient_user_activation_); + // TODO(crbug.com/1487270): we should probably make idp_login_url + // optional instead of empty. + LoginToIdP(/*can_append_hints=*/false, idp_config_url, idp_login_url); + return; +} + void FederatedAuthRequestImpl::PreventSilentAccess( PreventSilentAccessCallback callback) { SetRequiresUserMediation(true);
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h index bddca4e..58acfc77 100644 --- a/content/browser/webid/federated_auth_request_impl.h +++ b/content/browser/webid/federated_auth_request_impl.h
@@ -377,6 +377,9 @@ const GURL& idp_config_url, GURL login_url); + void MaybeShowButtonModeModalDialog(const GURL& idp_config_url, + const GURL& idp_login_url); + void CompleteDisconnectRequest(DisconnectCallback callback, blink::mojom::DisconnectStatus status); @@ -511,6 +514,14 @@ // Wallets or multi-IDP are not counted. int num_requests_{0}; + // The button flow requires user activation to be kicked off. We'd also need + // this information along the way. e.g. showing pop-up window when accounts + // fetch is failed. However, the function `HasTransientUserActivation` may + // return false at that time because the network requests may be very slow + // such that the previous user gesture is expired. Therefore we store the + // information to use it during the entire the button flow. + bool had_transient_user_activation_{false}; + base::WeakPtrFactory<FederatedAuthRequestImpl> weak_ptr_factory_{this}; };
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index 1d6d571..cee8da3 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -5285,6 +5285,38 @@ EXPECT_FALSE(DidFetch(FetchedEndpoint::ACCOUNTS)); } +TEST_F(FederatedAuthRequestImplTest, ButtonFlowWithUnknownLoginStatus) { + base::test::ScopedFeatureList list; + list.InitAndEnableFeature(features::kFedCmButtonMode); + + url::Origin kIdpOrigin = OriginFromString(kProviderUrlFull); + MockConfiguration configuration = kConfigurationValid; + configuration.idp_info[kProviderUrlFull].accounts_response.parse_status = + ParseStatus::kInvalidResponseError; + + // Check that the LoginStatus is "unknown". + EXPECT_EQ(test_permission_delegate_->idp_signin_statuses_.count(kIdpOrigin), + 0u); + + auto dialog_controller = + std::make_unique<TestDialogController>(configuration); + base::WeakPtr<TestDialogController> weak_dialog_controller = + dialog_controller->AsWeakPtr(); + SetDialogController(std::move(dialog_controller)); + + // Check that the pop-up window is displayed. + EXPECT_CALL(*weak_dialog_controller, ShowModalDialog(_, _)) + .WillOnce(Return(nullptr)); + + RequestParameters parameters = kDefaultRequestParameters; + parameters.rp_mode = blink::mojom::RpMode::kButton; + + static_cast<TestRenderFrameHost*>(web_contents()->GetPrimaryMainFrame()) + ->SimulateUserActivation(); + + RunAuthDontWaitForCallback(parameters, configuration); +} + TEST_F(FederatedAuthRequestImplTest, CloseModalDialogView) { #if BUILDFLAG(IS_ANDROID) auto dialog_controller =
diff --git a/content/browser/webid/test/mock_digital_identity_provider.h b/content/browser/webid/test/mock_digital_identity_provider.h index 721f8ce..2b65a15 100644 --- a/content/browser/webid/test/mock_digital_identity_provider.h +++ b/content/browser/webid/test/mock_digital_identity_provider.h
@@ -6,7 +6,7 @@ #define CONTENT_BROWSER_WEBID_TEST_MOCK_DIGITAL_IDENTITY_PROVIDER_H_ #include "base/values.h" -#include "content/browser/webid/digital_credentials/digital_identity_provider.h" +#include "content/public/browser/digital_identity_provider.h" #include "testing/gmock/include/gmock/gmock.h" namespace content {
diff --git a/content/browser/webid/test/webid_test_content_browser_client.cc b/content/browser/webid/test/webid_test_content_browser_client.cc index e54d1e4..3ffef1a 100644 --- a/content/browser/webid/test/webid_test_content_browser_client.cc +++ b/content/browser/webid/test/webid_test_content_browser_client.cc
@@ -4,8 +4,8 @@ #include "content/browser/webid/test/webid_test_content_browser_client.h" -#include "content/browser/webid/digital_credentials/digital_identity_provider.h" #include "content/browser/webid/test/mock_modal_dialog_view_delegate.h" +#include "content/public/browser/digital_identity_provider.h" namespace content {
diff --git a/content/browser/webid/webid_browsertest.cc b/content/browser/webid/webid_browsertest.cc index 0238055..0d571919 100644 --- a/content/browser/webid/webid_browsertest.cc +++ b/content/browser/webid/webid_browsertest.cc
@@ -19,7 +19,6 @@ #include "base/test/values_test_util.h" #include "base/values.h" #include "components/network_session_configurator/common/network_switches.h" -#include "content/browser/webid/digital_credentials/digital_identity_types.h" #include "content/browser/webid/fake_identity_request_dialog_controller.h" #include "content/browser/webid/identity_registry.h" #include "content/browser/webid/test/mock_digital_identity_provider.h" @@ -980,7 +979,7 @@ [](DigitalIdentityProvider::DigitalIdentityCallback callback) { std::move(callback).Run( "test-mdoc", - digital_identity::RequestStatusForMetrics::kSuccess); + DigitalIdentityProvider::RequestStatusForMetrics::kSuccess); })); EXPECT_EQ("test-mdoc", RunDigitalIdentityValidRequest(shell())); @@ -1023,7 +1022,7 @@ [](DigitalIdentityProvider::DigitalIdentityCallback callback) { std::move(callback).Run( "test-mdoc", - digital_identity::RequestStatusForMetrics::kSuccess); + DigitalIdentityProvider::RequestStatusForMetrics::kSuccess); })); std::string script = R"( @@ -1072,7 +1071,7 @@ ExtractJsError(RunDigitalIdentityValidRequest(shell()))); std::move(callback).Run( "test-mdoc", - digital_identity::RequestStatusForMetrics::kSuccess); + DigitalIdentityProvider::RequestStatusForMetrics::kSuccess); })); EXPECT_EQ("test-mdoc", RunDigitalIdentityValidRequest(shell())); @@ -1092,8 +1091,8 @@ .WillOnce(WithArg<3>( [&](DigitalIdentityProvider::DigitalIdentityCallback callback) { std::move(callback).Run( - "test-mdoc", - digital_identity::RequestStatusForMetrics::kErrorUserDeclined); + "test-mdoc", DigitalIdentityProvider::RequestStatusForMetrics:: + kErrorUserDeclined); })); EXPECT_EQ("NetworkError: Error retrieving a token.", @@ -1135,14 +1134,14 @@ [](DigitalIdentityProvider::DigitalIdentityCallback callback) { std::move(callback).Run( "test-mdoc", - digital_identity::RequestStatusForMetrics::kSuccess); + DigitalIdentityProvider::RequestStatusForMetrics::kSuccess); })); RunDigitalIdentityValidRequest(shell()); histogram_tester.ExpectUniqueSample( "Blink.DigitalIdentityRequest.Status", - digital_identity::RequestStatusForMetrics::kSuccess, 1); + DigitalIdentityProvider::RequestStatusForMetrics::kSuccess, 1); } // Verify that the Authz parameters are passed to the id assertion endpoint.
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 0907075..aad121ad 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -207,10 +207,10 @@ ":content_jni_headers", ":is_ready_to_pay_service_aidl", "//content/browser:client_data_json_generated_enum", - "//content/browser:digital_identity_enum", "//content/browser/accessibility:content_browser_accessibility_java_enums_srcjar", "//content/browser/sms:sms_provider_gms_backend_enum", "//content/public/browser:bluetooth_chooser_event_javagen", + "//content/public/browser:digital_identity_enum", "//ui/touch_selection:ui_touch_handle_orientation_srcjar", "//ui/touch_selection:ui_touch_selection_enums_srcjar", ]
diff --git a/content/public/android/java/src/org/chromium/content/browser/webid/DigitalIdentityProvider.java b/content/public/android/java/src/org/chromium/content/browser/webid/DigitalIdentityProvider.java index 316f884..a854282b 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webid/DigitalIdentityProvider.java +++ b/content/public/android/java/src/org/chromium/content/browser/webid/DigitalIdentityProvider.java
@@ -15,6 +15,7 @@ import org.jni_zero.NativeMethods; import org.chromium.base.ResettersForTesting; +import org.chromium.content_public.browser.webid.DigitalIdentityRequestStatusForMetrics; import org.chromium.ui.base.WindowAndroid; /** Class for issuing request to the Identity Credentials Manager in GMS core. */
diff --git a/content/public/android/junit/src/org/chromium/content/browser/webid/DigitalIdentityProviderTest.java b/content/public/android/junit/src/org/chromium/content/browser/webid/DigitalIdentityProviderTest.java index 2669880..f6c108d 100644 --- a/content/public/android/junit/src/org/chromium/content/browser/webid/DigitalIdentityProviderTest.java +++ b/content/public/android/junit/src/org/chromium/content/browser/webid/DigitalIdentityProviderTest.java
@@ -13,6 +13,7 @@ import org.robolectric.annotation.Config; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.content_public.browser.webid.DigitalIdentityRequestStatusForMetrics; /** Tests for {@link DigitalIdentityProvider} */ @RunWith(BaseRobolectricTestRunner.class)
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 4e8dab1..f94f088 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -153,6 +153,8 @@ "devtools_manager_delegate.h", "devtools_network_transaction_factory.h", "devtools_socket_factory.h", + "digital_identity_provider.cc", + "digital_identity_provider.h", "dips_delegate.cc", "dips_delegate.h", "disallow_activation_reason.h", @@ -735,6 +737,9 @@ java_cpp_enum("bluetooth_chooser_event_javagen") { sources = [ "bluetooth_chooser.h" ] } + java_cpp_enum("digital_identity_enum") { + sources = [ "digital_identity_provider.h" ] + } } proto_library("proto") {
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 09a9bb0..f7fe84d6 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -20,13 +20,13 @@ #include "build/build_config.h" #include "build/buildflag.h" #include "build/chromeos_buildflags.h" -#include "content/browser/webid/digital_credentials/digital_identity_provider.h" #include "content/public/browser/anchor_element_preconnect_delegate.h" #include "content/public/browser/authenticator_request_client_delegate.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_main_parts.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/devtools_manager_delegate.h" +#include "content/public/browser/digital_identity_provider.h" #include "content/public/browser/dips_delegate.h" #include "content/public/browser/identity_request_dialog_controller.h" #include "content/public/browser/legacy_tech_cookie_issue_details.h"
diff --git a/content/public/browser/digital_identity_provider.cc b/content/public/browser/digital_identity_provider.cc new file mode 100644 index 0000000..40e5a85 --- /dev/null +++ b/content/public/browser/digital_identity_provider.cc
@@ -0,0 +1,12 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/browser/digital_identity_provider.h" + +namespace content { + +DigitalIdentityProvider::DigitalIdentityProvider() = default; +DigitalIdentityProvider::~DigitalIdentityProvider() = default; + +} // namespace content
diff --git a/content/browser/webid/digital_credentials/digital_identity_provider.h b/content/public/browser/digital_identity_provider.h similarity index 62% rename from content/browser/webid/digital_credentials/digital_identity_provider.h rename to content/public/browser/digital_identity_provider.h index 3d96f940..c969adc 100644 --- a/content/browser/webid/digital_credentials/digital_identity_provider.h +++ b/content/public/browser/digital_identity_provider.h
@@ -2,14 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_PROVIDER_H_ -#define CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_PROVIDER_H_ +#ifndef CONTENT_PUBLIC_BROWSER_DIGITAL_IDENTITY_PROVIDER_H_ +#define CONTENT_PUBLIC_BROWSER_DIGITAL_IDENTITY_PROVIDER_H_ #include <memory> #include "base/functional/callback.h" #include "base/values.h" -#include "content/browser/webid/digital_credentials/digital_identity_types.h" #include "content/common/content_export.h" #include "content/public/browser/web_contents.h" #include "url/origin.h" @@ -24,16 +23,28 @@ // and mobile. class CONTENT_EXPORT DigitalIdentityProvider { public: + // Do not reorder or change the values because the enum values are being + // recorded in metrics. + // A Java counterpart will be generated for this enum. + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.browser.webid + // GENERATED_JAVA_CLASS_NAME_OVERRIDE: DigitalIdentityRequestStatusForMetrics + enum class RequestStatusForMetrics { + kSuccess = 0, + kErrorOther = 1, + kErrorNoCredential = 2, + kErrorUserDeclined = 3, + kErrorAborted = 4, + kMaxValue = kErrorAborted, + }; + virtual ~DigitalIdentityProvider(); DigitalIdentityProvider(const DigitalIdentityProvider&) = delete; DigitalIdentityProvider& operator=(const DigitalIdentityProvider&) = delete; - static std::unique_ptr<DigitalIdentityProvider> Create(); - using DigitalIdentityCallback = base::OnceCallback<void( const std::string&, - digital_identity::RequestStatusForMetrics status_for_metrics)>; + RequestStatusForMetrics status_for_metrics)>; virtual void Request(WebContents* web_contents, const url::Origin& origin, const base::Value::Dict& request, @@ -45,4 +56,4 @@ } // namespace content -#endif // CONTENT_BROWSER_WEBID_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_PROVIDER_H_ +#endif // CONTENT_PUBLIC_BROWSER_DIGITAL_IDENTITY_PROVIDER_H_
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist index 078faf6..f43a5778 100644 --- a/content/test/content_test_bundle_data.filelist +++ b/content/test/content_test_bundle_data.filelist
@@ -6355,6 +6355,7 @@ data/gpu/pixel_webgl_premultiplied_alpha_false.html data/gpu/pixel_webgl_preserved_after_tab_switch.html data/gpu/pixel_webgl_read_pixels_tab_switch.html +data/gpu/pixel_webgl_resized_canvas.html data/gpu/pixel_webgl_sad_canvas.html data/gpu/pixel_webgl_util.js data/gpu/pixel_webgl_webcodecs_breakoutbox_displays_frame.html
diff --git a/content/test/data/gpu/pixel_webgl_resized_canvas.html b/content/test/data/gpu/pixel_webgl_resized_canvas.html new file mode 100644 index 0000000..fd8adc6 --- /dev/null +++ b/content/test/data/gpu/pixel_webgl_resized_canvas.html
@@ -0,0 +1,49 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta name="viewport" content="initial-scale=1"> +<title>WebGL Canvas Resize Test</title> +<style type="text/css"> +.nomargin { + margin: 0px auto; +} +</style> +<script> +let g_swapsBeforeAck = 15; + +function sendResult(status) { + if (window.domAutomationController) { + window.domAutomationController.send(status); + } else { + console.log(status); + } +} + +function waitForFinish() { + if (g_swapsBeforeAck == 0) { + sendResult("SUCCESS"); + } else { + g_swapsBeforeAck--; + window.requestAnimationFrame(waitForFinish); + } +} + +function main() { + let canvas = document.getElementById("c"); + let gl = canvas.getContext("webgl", {preserveDrawingBuffer: true}); + gl.enable(gl.SCISSOR_TEST); + gl.scissor(0, 0, 50, 50); + gl.clearColor(0, 0, 1, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + + setTimeout(() => { + canvas.width = 150; + waitForFinish(); + }, 10); +} +</script> +</head> +<body onload="main()" class="nomargin"> +<canvas id="c" width="300" height="300" class="nomargin" style="background-color:red"></canvas> +</body> +</html>
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 17b869c..374f469 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -528,6 +528,10 @@ base_name + '_OffscreenCanvasIBRCWorker', test_rect=[0, 0, 100, 100], grace_period_end=date(2023, 8, 5)), + PixelTestPage('pixel_webgl_resized_canvas.html', + base_name + '_WebglResizedCanvas', + test_rect=[0, 0, 300, 300], + grace_period_end=date(2024, 3, 5)), ] @staticmethod
diff --git a/content/utility/services.cc b/content/utility/services.cc index 0cef357f..751e059 100644 --- a/content/utility/services.cc +++ b/content/utility/services.cc
@@ -307,8 +307,12 @@ auto RunVideoCapture( mojo::PendingReceiver<video_capture::mojom::VideoCaptureService> receiver) { #if BUILDFLAG(IS_CHROMEOS_ASH) - content::UtilityThread::Get()->BindHostReceiver( - GetContentClient()->utility()->InitMojoServiceManager()); + auto service_manager_receiver = + GetContentClient()->utility()->InitMojoServiceManager(); + if (service_manager_receiver.is_valid()) { + content::UtilityThread::Get()->BindHostReceiver( + std::move(service_manager_receiver)); + } #endif // BUILDFLAG(IS_CHROMEOS_ASH) auto service = std::make_unique<UtilityThreadVideoCaptureServiceImpl>( std::move(receiver), base::SingleThreadTaskRunner::GetCurrentDefault());
diff --git a/docs/memory/graphics_metrics.md b/docs/memory/graphics_metrics.md new file mode 100644 index 0000000..eae1a110 --- /dev/null +++ b/docs/memory/graphics_metrics.md
@@ -0,0 +1,26 @@ +# Graphics Memory Metrics + +The intent of this page is to provide more context and pointers to assess the +cost of Chromium's rendering. It is also meant to be used to complement to +warning in `//tools/metrics/histograms/metadata/memory/histograms.xml`. + +## GPU Process and Private Memory Footprint + +**tl;dr:** Memory.Gpu.PrivateMemoryFootprint does **not** reflect memory used by +graphics buffers on all platforms. A rough breakdown of platforms follows: + +- **Android (including Android WebView), Linux, Chrome OS:** None of the + graphics buffers are accounted for. Only CPU-side memory is reflected. +- **Windows:** Graphics memory may be partially or fully accounted for. +- **macOS, Intel CPUs:** Graphics memory may be partially or fully accounted for. +- **macOS, ARM64:** We believe that graphics buffers are fully accounted for. + +In summary, ARM64 macOS is the only platform where we are reasonably confident +that all memory allocations are properly reflected in +Memory.Gpu.PrivateMemoryFootprint. + +**Caution:** Rendering is heavily platform-specific. Do not assume that changes +impacting a platform are reflected on another one. Even for macOS, there are +many hardware, OS and Chromium-level differences. For instance, as of early +2024, rendering is performed using Metal on ARM64, and OpenGL on Intel mac +devices.
diff --git a/docs/website b/docs/website index 05de69c..986765e 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit 05de69cbec5c294245bfb96d9be826065c05e6eb +Subproject commit 986765e7d5353a13f3927a616ac4b19ed46753c8
diff --git a/extensions/browser/content_verifier/content_verifier_io_data.h b/extensions/browser/content_verifier/content_verifier_io_data.h index 58a231c..0cacec9 100644 --- a/extensions/browser/content_verifier/content_verifier_io_data.h +++ b/extensions/browser/content_verifier/content_verifier_io_data.h
@@ -7,6 +7,7 @@ #include <map> #include <memory> +#include <optional> #include <set> #include <string>
diff --git a/infra/config/generated/builders/ci/GPU Mac Builder/properties.json b/infra/config/generated/builders/ci/GPU Mac Builder/properties.json index 217052d..992dc73 100644 --- a/infra/config/generated/builders/ci/GPU Mac Builder/properties.json +++ b/infra/config/generated/builders/ci/GPU Mac Builder/properties.json
@@ -117,10 +117,6 @@ { "builder": "mac-rel", "group": "tryserver.chromium.mac" - }, - { - "builder": "mac-siso-rel", - "group": "tryserver.chromium.mac" } ] }
diff --git "a/infra/config/generated/builders/ci/Linux Builder \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/Linux Builder \050dbg\051/properties.json" index 89ce384..5c84483 100644 --- "a/infra/config/generated/builders/ci/Linux Builder \050dbg\051/properties.json" +++ "b/infra/config/generated/builders/ci/Linux Builder \050dbg\051/properties.json"
@@ -81,10 +81,6 @@ "group": "tryserver.chromium.linux" }, { - "builder": "linux_chromium_compile_siso_dbg_ng", - "group": "tryserver.chromium.linux" - }, - { "builder": "linux_chromium_dbg_ng", "group": "tryserver.chromium.linux" }
diff --git "a/infra/config/generated/builders/ci/Linux Tests \050dbg\051\0501\051/properties.json" "b/infra/config/generated/builders/ci/Linux Tests \050dbg\051\0501\051/properties.json" index f9d2c1b..267d5cd51 100644 --- "a/infra/config/generated/builders/ci/Linux Tests \050dbg\051\0501\051/properties.json" +++ "b/infra/config/generated/builders/ci/Linux Tests \050dbg\051\0501\051/properties.json"
@@ -71,10 +71,6 @@ "group": "tryserver.chromium.linux" }, { - "builder": "linux_chromium_compile_siso_dbg_ng", - "group": "tryserver.chromium.linux" - }, - { "builder": "linux_chromium_dbg_ng", "group": "tryserver.chromium.linux" }
diff --git a/infra/config/generated/builders/ci/Mac Builder/properties.json b/infra/config/generated/builders/ci/Mac Builder/properties.json index 81fab41..f0888005 100644 --- a/infra/config/generated/builders/ci/Mac Builder/properties.json +++ b/infra/config/generated/builders/ci/Mac Builder/properties.json
@@ -184,10 +184,6 @@ "group": "tryserver.chromium.mac" }, { - "builder": "mac-siso-rel", - "group": "tryserver.chromium.mac" - }, - { "builder": "mac12-tests", "group": "tryserver.chromium.mac" },
diff --git "a/infra/config/generated/builders/ci/Mac Release \050Intel\051/properties.json" "b/infra/config/generated/builders/ci/Mac Release \050Intel\051/properties.json" index 46d051e5..58648bd 100644 --- "a/infra/config/generated/builders/ci/Mac Release \050Intel\051/properties.json" +++ "b/infra/config/generated/builders/ci/Mac Release \050Intel\051/properties.json"
@@ -73,10 +73,6 @@ { "builder": "mac-rel", "group": "tryserver.chromium.mac" - }, - { - "builder": "mac-siso-rel", - "group": "tryserver.chromium.mac" } ] }
diff --git "a/infra/config/generated/builders/ci/Mac Retina Release \050AMD\051/properties.json" "b/infra/config/generated/builders/ci/Mac Retina Release \050AMD\051/properties.json" index 086fae8..83706f8 100644 --- "a/infra/config/generated/builders/ci/Mac Retina Release \050AMD\051/properties.json" +++ "b/infra/config/generated/builders/ci/Mac Retina Release \050AMD\051/properties.json"
@@ -73,10 +73,6 @@ { "builder": "mac-rel", "group": "tryserver.chromium.mac" - }, - { - "builder": "mac-siso-rel", - "group": "tryserver.chromium.mac" } ] }
diff --git a/infra/config/generated/builders/ci/Mac13 Tests/properties.json b/infra/config/generated/builders/ci/Mac13 Tests/properties.json index 5ef67b3..a611d44a 100644 --- a/infra/config/generated/builders/ci/Mac13 Tests/properties.json +++ b/infra/config/generated/builders/ci/Mac13 Tests/properties.json
@@ -74,10 +74,6 @@ "group": "tryserver.chromium.mac" }, { - "builder": "mac-siso-rel", - "group": "tryserver.chromium.mac" - }, - { "builder": "mac13-tests", "group": "tryserver.chromium.mac" },
diff --git a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/gn-args.json b/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/gn-args.json deleted file mode 100644 index cca82c7..0000000 --- a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/gn-args.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "args_file": "//build/args/chromeos/jacuzzi.gni", - "gn_args": { - "also_build_lacros_chrome_for_architecture": "arm64", - "dcheck_always_on": false, - "exclude_unwind_tables": false, - "is_chromeos_device": true, - "is_skylab": true, - "ozone_platform_headless": true, - "use_remoteexec": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/properties.json b/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/properties.json deleted file mode 100644 index 30a0df99..0000000 --- a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/properties.json +++ /dev/null
@@ -1,77 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "chromeos-jacuzzi-rel-skylab", - "project": "chromium" - }, - "builder_spec": { - "builder_group": "chromium.fyi", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "arm", - "target_bits": 32, - "target_cros_boards": [ - "jacuzzi", - "arm64-generic" - ], - "target_platform": "chromeos" - }, - "legacy_gclient_config": { - "apply_configs": [ - "chromeos", - "checkout_lacros_sdk" - ], - "config": "chromium" - }, - "skylab_upload_location": { - "gs_bucket": "chromium-skylab-try", - "gs_extra": "ash" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "chromeos-jacuzzi-rel-skylab", - "project": "chromium" - } - ], - "mirroring_builder_group_and_names": [ - { - "builder": "chromeos-jacuzzi-rel-skylab", - "group": "tryserver.chromium.chromiumos" - } - ] - } - }, - "$build/reclient": { - "instance": "rbe-chromium-trusted", - "jobs": 250, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "chromium.fyi", - "recipe": "chromium" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/shadow-properties.json b/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/shadow-properties.json deleted file mode 100644 index 999510c..0000000 --- a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/shadow-properties.json +++ /dev/null
@@ -1,8 +0,0 @@ -{ - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "jobs": 250, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/gn-args.json b/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/gn-args.json index ba7fbcc..cca82c7 100644 --- a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/gn-args.json +++ b/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/gn-args.json
@@ -1,8 +1,11 @@ { "args_file": "//build/args/chromeos/jacuzzi.gni", "gn_args": { - "dcheck_always_on": true, + "also_build_lacros_chrome_for_architecture": "arm64", + "dcheck_always_on": false, + "exclude_unwind_tables": false, "is_chromeos_device": true, + "is_skylab": true, "ozone_platform_headless": true, "use_remoteexec": true }
diff --git a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/properties.json b/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/properties.json index 1a285d6d..88db7996 100644 --- a/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/properties.json +++ b/infra/config/generated/builders/ci/chromeos-jacuzzi-rel/properties.json
@@ -13,7 +13,6 @@ "project": "chromium" }, "builder_spec": { - "build_gs_bucket": "chromium-chromiumos-archive", "builder_group": "chromium.chromiumos", "execution_mode": "COMPILE_AND_TEST", "legacy_chromium_config": { @@ -25,16 +24,21 @@ "target_arch": "arm", "target_bits": 32, "target_cros_boards": [ - "jacuzzi" + "jacuzzi", + "arm64-generic" ], "target_platform": "chromeos" }, "legacy_gclient_config": { "apply_configs": [ - "arm64", - "chromeos" + "chromeos", + "checkout_lacros_sdk" ], "config": "chromium" + }, + "skylab_upload_location": { + "gs_bucket": "chromium-skylab-try", + "gs_extra": "ash" } } } @@ -69,5 +73,8 @@ ] }, "builder_group": "chromium.chromiumos", - "recipe": "chromium" + "recipe": "chromium", + "sheriff_rotations": [ + "chromiumos" + ] } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/gn-args.json b/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/gn-args.json deleted file mode 100644 index c51c4426..0000000 --- a/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/gn-args.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "args_file": "//build/args/chromeos/octopus.gni", - "gn_args": { - "also_build_lacros_chrome_for_architecture": "amd64", - "exclude_unwind_tables": false, - "is_chromeos_device": true, - "is_skylab": true, - "ozone_platform_headless": true, - "use_remoteexec": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/properties.json b/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/properties.json deleted file mode 100644 index f3004a35..0000000 --- a/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/properties.json +++ /dev/null
@@ -1,77 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "chromeos-octopus-rel-skylab", - "project": "chromium" - }, - "builder_spec": { - "builder_group": "chromium.fyi", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "intel", - "target_bits": 32, - "target_cros_boards": [ - "octopus", - "amd64-generic" - ], - "target_platform": "chromeos" - }, - "legacy_gclient_config": { - "apply_configs": [ - "chromeos", - "checkout_lacros_sdk" - ], - "config": "chromium" - }, - "skylab_upload_location": { - "gs_bucket": "chromium-skylab-try", - "gs_extra": "ash" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "chromeos-octopus-rel-skylab", - "project": "chromium" - } - ], - "mirroring_builder_group_and_names": [ - { - "builder": "chromeos-octopus-rel-skylab", - "group": "tryserver.chromium.chromiumos" - } - ] - } - }, - "$build/reclient": { - "instance": "rbe-chromium-trusted", - "jobs": 250, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "chromium.fyi", - "recipe": "chromium" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/shadow-properties.json b/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/shadow-properties.json deleted file mode 100644 index 999510c..0000000 --- a/infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/shadow-properties.json +++ /dev/null
@@ -1,8 +0,0 @@ -{ - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "jobs": 250, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/chromeos-octopus-rel/gn-args.json b/infra/config/generated/builders/ci/chromeos-octopus-rel/gn-args.json index 5ceb701..cf15202 100644 --- a/infra/config/generated/builders/ci/chromeos-octopus-rel/gn-args.json +++ b/infra/config/generated/builders/ci/chromeos-octopus-rel/gn-args.json
@@ -1,8 +1,11 @@ { "args_file": "//build/args/chromeos/octopus.gni", "gn_args": { - "dcheck_always_on": true, + "also_build_lacros_chrome_for_architecture": "amd64", + "dcheck_always_on": false, + "exclude_unwind_tables": false, "is_chromeos_device": true, + "is_skylab": true, "ozone_platform_headless": true, "use_remoteexec": true }
diff --git a/infra/config/generated/builders/ci/chromeos-octopus-rel/properties.json b/infra/config/generated/builders/ci/chromeos-octopus-rel/properties.json index f658b5ae..06774958 100644 --- a/infra/config/generated/builders/ci/chromeos-octopus-rel/properties.json +++ b/infra/config/generated/builders/ci/chromeos-octopus-rel/properties.json
@@ -13,7 +13,6 @@ "project": "chromium" }, "builder_spec": { - "build_gs_bucket": "chromium-chromiumos-archive", "builder_group": "chromium.chromiumos", "execution_mode": "COMPILE_AND_TEST", "legacy_chromium_config": { @@ -25,15 +24,21 @@ "target_arch": "intel", "target_bits": 64, "target_cros_boards": [ - "octopus" + "octopus", + "amd64-generic" ], "target_platform": "chromeos" }, "legacy_gclient_config": { "apply_configs": [ - "chromeos" + "chromeos", + "checkout_lacros_sdk" ], "config": "chromium" + }, + "skylab_upload_location": { + "gs_bucket": "chromium-skylab-try", + "gs_extra": "ash" } } }
diff --git a/infra/config/generated/builders/ci/ios-simulator/properties.json b/infra/config/generated/builders/ci/ios-simulator/properties.json index 8a154b8b..b1463ea 100644 --- a/infra/config/generated/builders/ci/ios-simulator/properties.json +++ b/infra/config/generated/builders/ci/ios-simulator/properties.json
@@ -47,10 +47,6 @@ { "builder": "ios-simulator", "group": "tryserver.chromium.mac" - }, - { - "builder": "ios-simulator-siso", - "group": "tryserver.chromium.mac" } ] }
diff --git a/infra/config/generated/builders/gn_args_locations.json b/infra/config/generated/builders/gn_args_locations.json index bb0b281..aa4d166 100644 --- a/infra/config/generated/builders/gn_args_locations.json +++ b/infra/config/generated/builders/gn_args_locations.json
@@ -276,8 +276,6 @@ "Win x64 Builder (reclient)": "ci/Win x64 Builder (reclient)/gn-args.json", "android-fieldtrial-rel": "ci/android-fieldtrial-rel/gn-args.json", "android-perfetto-rel": "ci/android-perfetto-rel/gn-args.json", - "chromeos-jacuzzi-rel-skylab": "ci/chromeos-jacuzzi-rel-skylab/gn-args.json", - "chromeos-octopus-rel-skylab": "ci/chromeos-octopus-rel-skylab/gn-args.json", "ios-blink-dbg-fyi": "ci/ios-blink-dbg-fyi/gn-args.json", "ios-fieldtrial-rel": "ci/ios-fieldtrial-rel/gn-args.json", "ios-m1-simulator": "ci/ios-m1-simulator/gn-args.json", @@ -659,9 +657,7 @@ "chromeos-arm-generic-rel": "try/chromeos-arm-generic-rel/gn-args.json", "chromeos-arm64-generic-rel": "try/chromeos-arm64-generic-rel/gn-args.json", "chromeos-jacuzzi-rel": "try/chromeos-jacuzzi-rel/gn-args.json", - "chromeos-jacuzzi-rel-skylab": "try/chromeos-jacuzzi-rel-skylab/gn-args.json", "chromeos-octopus-rel": "try/chromeos-octopus-rel/gn-args.json", - "chromeos-octopus-rel-skylab": "try/chromeos-octopus-rel-skylab/gn-args.json", "gpu-fyi-try-chromeos-amd64-generic": "try/gpu-fyi-try-chromeos-amd64-generic/gn-args.json", "gpu-fyi-try-chromeos-skylab-volteer": "try/gpu-fyi-try-chromeos-skylab-volteer/gn-args.json", "lacros-amd64-generic-rel-gtest": "try/lacros-amd64-generic-rel-gtest/gn-args.json", @@ -813,7 +809,6 @@ "linux_chromium_clobber_deterministic": "try/linux_chromium_clobber_deterministic/gn-args.json", "linux_chromium_compile_dbg_ng": "try/linux_chromium_compile_dbg_ng/gn-args.json", "linux_chromium_compile_rel_ng": "try/linux_chromium_compile_rel_ng/gn-args.json", - "linux_chromium_compile_siso_dbg_ng": "try/linux_chromium_compile_siso_dbg_ng/gn-args.json", "linux_chromium_dbg_ng": "try/linux_chromium_dbg_ng/gn-args.json", "linux_chromium_msan_rel_ng": "try/linux_chromium_msan_rel_ng/gn-args.json", "linux_chromium_tsan_rel_ng": "try/linux_chromium_tsan_rel_ng/gn-args.json", @@ -850,7 +845,6 @@ "ios-simulator-full-configs": "try/ios-simulator-full-configs/gn-args.json", "ios-simulator-multi-window": "try/ios-simulator-multi-window/gn-args.json", "ios-simulator-noncq": "try/ios-simulator-noncq/gn-args.json", - "ios-simulator-siso": "try/ios-simulator-siso/gn-args.json", "ios-wpt-fyi-rel": "try/ios-wpt-fyi-rel/gn-args.json", "ios16-beta-simulator": "try/ios16-beta-simulator/gn-args.json", "ios16-sdk-simulator": "try/ios16-sdk-simulator/gn-args.json", @@ -867,7 +861,6 @@ "mac-osxbeta-rel": "try/mac-osxbeta-rel/gn-args.json", "mac-perfetto-rel": "try/mac-perfetto-rel/gn-args.json", "mac-rel": "try/mac-rel/gn-args.json", - "mac-siso-rel": "try/mac-siso-rel/gn-args.json", "mac-ubsan-fyi-rel": "try/mac-ubsan-fyi-rel/gn-args.json", "mac10.15-wpt-content-shell-fyi-rel": "try/mac10.15-wpt-content-shell-fyi-rel/gn-args.json", "mac11-arm64-rel": "try/mac11-arm64-rel/gn-args.json",
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/gn-args.json b/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/gn-args.json index 42bb990..d947a53 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/gn-args.json
@@ -5,6 +5,7 @@ "is_asan": true, "is_chromeos_device": true, "ozone_platform_headless": true, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/properties.json b/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/properties.json index 976a349..f46243b7 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/properties.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-asan-rel/properties.json
@@ -54,6 +54,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/gn-args.json b/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/gn-args.json index 70a452fb..9fc35c33 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/gn-args.json
@@ -8,6 +8,7 @@ "ozone_platform_headless": true, "use_cfi_cast": true, "use_remoteexec": true, + "use_siso": true, "use_thin_lto": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json b/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json index 08015147..dd95099d 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-cfi-thin-lto-rel/properties.json
@@ -55,6 +55,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/gn-args.json b/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/gn-args.json index e484fa7..c3e6615 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/gn-args.json
@@ -5,6 +5,7 @@ "is_chromeos_device": true, "is_debug": true, "ozone_platform_headless": true, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json b/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json index 3a220d6..e956619 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-dbg/properties.json
@@ -58,6 +58,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/gn-args.json b/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/gn-args.json index 5f38a1f5..5373ef7 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/gn-args.json
@@ -8,6 +8,7 @@ "is_debug": true, "ozone_platform_headless": true, "target_os": "chromeos", - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/properties.json b/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/properties.json index b40a243..05563b8 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/properties.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-lacros-dbg/properties.json
@@ -55,6 +55,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-rel/gn-args.json b/infra/config/generated/builders/try/chromeos-amd64-generic-rel/gn-args.json index b7f6c5a..1189a6d 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-rel/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-rel/gn-args.json
@@ -6,6 +6,7 @@ "is_chromeos_device": true, "ozone_platform_headless": true, "use_real_dbus_clients": false, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-amd64-generic-rel/properties.json b/infra/config/generated/builders/try/chromeos-amd64-generic-rel/properties.json index df1a393..166cc43 100644 --- a/infra/config/generated/builders/try/chromeos-amd64-generic-rel/properties.json +++ b/infra/config/generated/builders/try/chromeos-amd64-generic-rel/properties.json
@@ -58,6 +58,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-arm-generic-dbg/gn-args.json b/infra/config/generated/builders/try/chromeos-arm-generic-dbg/gn-args.json index 982f4c56..b57ffa44 100644 --- a/infra/config/generated/builders/try/chromeos-arm-generic-dbg/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-arm-generic-dbg/gn-args.json
@@ -5,6 +5,7 @@ "is_chromeos_device": true, "is_debug": true, "ozone_platform_headless": true, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-arm-generic-dbg/properties.json b/infra/config/generated/builders/try/chromeos-arm-generic-dbg/properties.json index 0ad21d14..8094e9d 100644 --- a/infra/config/generated/builders/try/chromeos-arm-generic-dbg/properties.json +++ b/infra/config/generated/builders/try/chromeos-arm-generic-dbg/properties.json
@@ -54,6 +54,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-arm64-generic-rel/gn-args.json b/infra/config/generated/builders/try/chromeos-arm64-generic-rel/gn-args.json index 5eda11b4..5430e90 100644 --- a/infra/config/generated/builders/try/chromeos-arm64-generic-rel/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-arm64-generic-rel/gn-args.json
@@ -4,6 +4,7 @@ "dcheck_always_on": true, "is_chromeos_device": true, "ozone_platform_headless": true, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-arm64-generic-rel/properties.json b/infra/config/generated/builders/try/chromeos-arm64-generic-rel/properties.json index 5094cab..d141a5e 100644 --- a/infra/config/generated/builders/try/chromeos-arm64-generic-rel/properties.json +++ b/infra/config/generated/builders/try/chromeos-arm64-generic-rel/properties.json
@@ -53,6 +53,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/gn-args.json b/infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/gn-args.json deleted file mode 100644 index cca82c7..0000000 --- a/infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/gn-args.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "args_file": "//build/args/chromeos/jacuzzi.gni", - "gn_args": { - "also_build_lacros_chrome_for_architecture": "arm64", - "dcheck_always_on": false, - "exclude_unwind_tables": false, - "is_chromeos_device": true, - "is_skylab": true, - "ozone_platform_headless": true, - "use_remoteexec": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/properties.json b/infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/properties.json deleted file mode 100644 index 0a951fe..0000000 --- a/infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/properties.json +++ /dev/null
@@ -1,71 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "chromeos-jacuzzi-rel-skylab", - "project": "chromium" - }, - "builder_spec": { - "builder_group": "chromium.fyi", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "arm", - "target_bits": 32, - "target_cros_boards": [ - "jacuzzi", - "arm64-generic" - ], - "target_platform": "chromeos" - }, - "legacy_gclient_config": { - "apply_configs": [ - "chromeos", - "checkout_lacros_sdk" - ], - "config": "chromium" - }, - "skylab_upload_location": { - "gs_bucket": "chromium-skylab-try", - "gs_extra": "ash" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "chromeos-jacuzzi-rel-skylab", - "project": "chromium" - } - ] - } - }, - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "jobs": 150, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.chromiumos", - "recipe": "chromium_trybot" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-jacuzzi-rel/gn-args.json b/infra/config/generated/builders/try/chromeos-jacuzzi-rel/gn-args.json index ba7fbcc..ca09531 100644 --- a/infra/config/generated/builders/try/chromeos-jacuzzi-rel/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-jacuzzi-rel/gn-args.json
@@ -1,9 +1,13 @@ { "args_file": "//build/args/chromeos/jacuzzi.gni", "gn_args": { - "dcheck_always_on": true, + "also_build_lacros_chrome_for_architecture": "arm64", + "dcheck_always_on": false, + "exclude_unwind_tables": false, "is_chromeos_device": true, + "is_skylab": true, "ozone_platform_headless": true, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-jacuzzi-rel/properties.json b/infra/config/generated/builders/try/chromeos-jacuzzi-rel/properties.json index 30979c1..8dba6cef 100644 --- a/infra/config/generated/builders/try/chromeos-jacuzzi-rel/properties.json +++ b/infra/config/generated/builders/try/chromeos-jacuzzi-rel/properties.json
@@ -13,7 +13,6 @@ "project": "chromium" }, "builder_spec": { - "build_gs_bucket": "chromium-chromiumos-archive", "builder_group": "chromium.chromiumos", "execution_mode": "COMPILE_AND_TEST", "legacy_chromium_config": { @@ -25,16 +24,21 @@ "target_arch": "arm", "target_bits": 32, "target_cros_boards": [ - "jacuzzi" + "jacuzzi", + "arm64-generic" ], "target_platform": "chromeos" }, "legacy_gclient_config": { "apply_configs": [ - "arm64", - "chromeos" + "chromeos", + "checkout_lacros_sdk" ], "config": "chromium" + }, + "skylab_upload_location": { + "gs_bucket": "chromium-skylab-try", + "gs_extra": "ash" } } } @@ -55,6 +59,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/chromeos-octopus-rel-skylab/gn-args.json b/infra/config/generated/builders/try/chromeos-octopus-rel-skylab/gn-args.json deleted file mode 100644 index c51c4426..0000000 --- a/infra/config/generated/builders/try/chromeos-octopus-rel-skylab/gn-args.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "args_file": "//build/args/chromeos/octopus.gni", - "gn_args": { - "also_build_lacros_chrome_for_architecture": "amd64", - "exclude_unwind_tables": false, - "is_chromeos_device": true, - "is_skylab": true, - "ozone_platform_headless": true, - "use_remoteexec": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-octopus-rel-skylab/properties.json b/infra/config/generated/builders/try/chromeos-octopus-rel-skylab/properties.json deleted file mode 100644 index 2a8ef97..0000000 --- a/infra/config/generated/builders/try/chromeos-octopus-rel-skylab/properties.json +++ /dev/null
@@ -1,71 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/chromeos-octopus-rel-skylab/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "chromeos-octopus-rel-skylab", - "project": "chromium" - }, - "builder_spec": { - "builder_group": "chromium.fyi", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "intel", - "target_bits": 32, - "target_cros_boards": [ - "octopus", - "amd64-generic" - ], - "target_platform": "chromeos" - }, - "legacy_gclient_config": { - "apply_configs": [ - "chromeos", - "checkout_lacros_sdk" - ], - "config": "chromium" - }, - "skylab_upload_location": { - "gs_bucket": "chromium-skylab-try", - "gs_extra": "ash" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "chromeos-octopus-rel-skylab", - "project": "chromium" - } - ] - } - }, - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "jobs": 150, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.chromiumos", - "recipe": "chromium_trybot" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-octopus-rel/gn-args.json b/infra/config/generated/builders/try/chromeos-octopus-rel/gn-args.json index 5ceb701..640dae4e 100644 --- a/infra/config/generated/builders/try/chromeos-octopus-rel/gn-args.json +++ b/infra/config/generated/builders/try/chromeos-octopus-rel/gn-args.json
@@ -1,9 +1,13 @@ { "args_file": "//build/args/chromeos/octopus.gni", "gn_args": { - "dcheck_always_on": true, + "also_build_lacros_chrome_for_architecture": "amd64", + "dcheck_always_on": false, + "exclude_unwind_tables": false, "is_chromeos_device": true, + "is_skylab": true, "ozone_platform_headless": true, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/chromeos-octopus-rel/properties.json b/infra/config/generated/builders/try/chromeos-octopus-rel/properties.json index 475c63200..2dda4db 100644 --- a/infra/config/generated/builders/try/chromeos-octopus-rel/properties.json +++ b/infra/config/generated/builders/try/chromeos-octopus-rel/properties.json
@@ -13,7 +13,6 @@ "project": "chromium" }, "builder_spec": { - "build_gs_bucket": "chromium-chromiumos-archive", "builder_group": "chromium.chromiumos", "execution_mode": "COMPILE_AND_TEST", "legacy_chromium_config": { @@ -25,15 +24,21 @@ "target_arch": "intel", "target_bits": 64, "target_cros_boards": [ - "octopus" + "octopus", + "amd64-generic" ], "target_platform": "chromeos" }, "legacy_gclient_config": { "apply_configs": [ - "chromeos" + "chromeos", + "checkout_lacros_sdk" ], "config": "chromium" + }, + "skylab_upload_location": { + "gs_bucket": "chromium-skylab-try", + "gs_extra": "ash" } } } @@ -54,6 +59,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/ios-simulator-siso-compilator/properties.json b/infra/config/generated/builders/try/ios-simulator-siso-compilator/properties.json deleted file mode 100644 index a4e223b7..0000000 --- a/infra/config/generated/builders/try/ios-simulator-siso-compilator/properties.json +++ /dev/null
@@ -1,85 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/ios-simulator-siso/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "ios-simulator", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-mac-archive", - "builder_group": "chromium.mac", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb", - "mac_toolchain" - ], - "build_config": "Debug", - "config": "chromium", - "target_bits": 64, - "target_platform": "ios" - }, - "legacy_gclient_config": { - "apply_configs": [ - "use_clang_coverage" - ], - "config": "ios" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "ios-simulator", - "project": "chromium" - } - ] - } - }, - "$build/code_coverage": { - "coverage_exclude_sources": "ios_test_files_and_test_utils", - "coverage_test_types": [ - "overall", - "unit" - ], - "use_clang_coverage": true - }, - "$build/flakiness": { - "check_for_flakiness": true, - "check_for_flakiness_with_resultdb": true - }, - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "jobs": 500, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - }, - "$build/siso": { - "configs": [ - "builder" - ], - "enable_cloud_profiler": true, - "enable_cloud_trace": true, - "experiments": [], - "project": "rbe-chromium-untrusted" - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.mac", - "recipe": "chromium/compilator", - "xcode_build_version": "15c500b" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-siso/gn-args.json b/infra/config/generated/builders/try/ios-simulator-siso/gn-args.json deleted file mode 100644 index 0180996..0000000 --- a/infra/config/generated/builders/try/ios-simulator-siso/gn-args.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "gn_args": { - "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt", - "enable_run_ios_unittests_with_xctest": true, - "is_component_build": false, - "is_debug": true, - "symbol_level": 1, - "target_cpu": "x64", - "target_environment": "simulator", - "target_os": "ios", - "use_clang_coverage": true, - "use_remoteexec": true, - "use_siso": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-siso/properties.json b/infra/config/generated/builders/try/ios-simulator-siso/properties.json deleted file mode 100644 index 2da9383..0000000 --- a/infra/config/generated/builders/try/ios-simulator-siso/properties.json +++ /dev/null
@@ -1,83 +0,0 @@ -{ - "$build/chromium_orchestrator": { - "compilator": "ios-simulator-siso-compilator", - "compilator_watcher_git_revision": "27c191f304c8d7329a393d8a69020fc14032c3c3" - }, - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/ios-simulator-siso/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "ios-simulator", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-mac-archive", - "builder_group": "chromium.mac", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb", - "mac_toolchain" - ], - "build_config": "Debug", - "config": "chromium", - "target_bits": 64, - "target_platform": "ios" - }, - "legacy_gclient_config": { - "apply_configs": [ - "use_clang_coverage" - ], - "config": "ios" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "ios-simulator", - "project": "chromium" - } - ] - } - }, - "$build/code_coverage": { - "coverage_exclude_sources": "ios_test_files_and_test_utils", - "coverage_test_types": [ - "overall", - "unit" - ], - "use_clang_coverage": true - }, - "$build/flakiness": { - "check_for_flakiness": true, - "check_for_flakiness_with_resultdb": true - }, - "$build/siso": { - "configs": [ - "builder" - ], - "enable_cloud_profiler": true, - "enable_cloud_trace": true, - "experiments": [], - "project": "rbe-chromium-untrusted" - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.mac", - "cq": "required", - "recipe": "chromium/orchestrator" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/gn-args.json b/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/gn-args.json index c7a4fad2..d84f9a41 100644 --- a/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/gn-args.json +++ b/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/gn-args.json
@@ -7,6 +7,7 @@ "is_debug": false, "ozone_platform_headless": true, "target_os": "chromeos", - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/properties.json b/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/properties.json index 63e63d99..3ff7075 100644 --- a/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/properties.json +++ b/infra/config/generated/builders/try/lacros-amd64-generic-rel-non-skylab/properties.json
@@ -58,6 +58,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/gn-args.json b/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/gn-args.json index fd9348f9..24d8fb2 100644 --- a/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/gn-args.json +++ b/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/gn-args.json
@@ -8,6 +8,7 @@ "is_skylab": true, "ozone_platform_headless": true, "target_os": "chromeos", - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/properties.json b/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/properties.json index 9306281..3d2f05e 100644 --- a/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/properties.json +++ b/infra/config/generated/builders/try/lacros-arm-generic-rel-skylab/properties.json
@@ -59,6 +59,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/gn-args.json b/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/gn-args.json index 4d95ed1..14d63c2 100644 --- a/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/gn-args.json +++ b/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/gn-args.json
@@ -8,6 +8,7 @@ "is_skylab": true, "ozone_platform_headless": true, "target_os": "chromeos", - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/properties.json b/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/properties.json index c6364dd..8403e2c 100644 --- a/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/properties.json +++ b/infra/config/generated/builders/try/lacros-arm64-generic-rel-skylab/properties.json
@@ -59,6 +59,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/lacros-arm64-generic-rel/gn-args.json b/infra/config/generated/builders/try/lacros-arm64-generic-rel/gn-args.json index 2150314d..e054545 100644 --- a/infra/config/generated/builders/try/lacros-arm64-generic-rel/gn-args.json +++ b/infra/config/generated/builders/try/lacros-arm64-generic-rel/gn-args.json
@@ -7,6 +7,7 @@ "is_debug": false, "ozone_platform_headless": true, "target_os": "chromeos", - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/lacros-arm64-generic-rel/properties.json b/infra/config/generated/builders/try/lacros-arm64-generic-rel/properties.json index 043b01c..29cb084 100644 --- a/infra/config/generated/builders/try/lacros-arm64-generic-rel/properties.json +++ b/infra/config/generated/builders/try/lacros-arm64-generic-rel/properties.json
@@ -55,6 +55,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/gn-args.json b/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/gn-args.json index 5198547..d1c7cdb 100644 --- a/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/gn-args.json +++ b/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/gn-args.json
@@ -10,6 +10,7 @@ "is_debug": false, "target_os": "chromeos", "use_cups": true, - "use_remoteexec": true + "use_remoteexec": true, + "use_siso": true } } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/properties.json b/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/properties.json index e3582a2..ec400d0d 100644 --- a/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/properties.json +++ b/infra/config/generated/builders/try/linux-lacros-rel-dangling-ptr-fyi/properties.json
@@ -51,6 +51,15 @@ "metrics_project": "chromium-reclient-metrics", "scandeps_server": true }, + "$build/siso": { + "configs": [ + "builder" + ], + "enable_cloud_profiler": true, + "enable_cloud_trace": true, + "experiments": [], + "project": "rbe-chromium-untrusted" + }, "$recipe_engine/resultdb/test_presentation": { "column_keys": [], "grouping_keys": [
diff --git a/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/gn-args.json b/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/gn-args.json deleted file mode 100644 index f73df1f..0000000 --- a/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/gn-args.json +++ /dev/null
@@ -1,9 +0,0 @@ -{ - "gn_args": { - "is_component_build": true, - "is_debug": true, - "symbol_level": 1, - "use_remoteexec": true, - "use_siso": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json b/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json deleted file mode 100644 index 9fe19e5d..0000000 --- a/infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json +++ /dev/null
@@ -1,110 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "Linux Builder (dbg)", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-linux-archive", - "builder_group": "chromium.linux", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Debug", - "config": "chromium", - "target_bits": 64, - "target_platform": "linux" - }, - "legacy_gclient_config": { - "config": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Linux Tests (dbg)(1)", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-linux-archive", - "builder_group": "chromium.linux", - "execution_mode": "TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Debug", - "config": "chromium", - "target_bits": 64, - "target_platform": "linux" - }, - "legacy_gclient_config": { - "config": "chromium" - }, - "parent": { - "bucket": "ci", - "builder": "Linux Builder (dbg)", - "project": "chromium" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "Linux Builder (dbg)", - "project": "chromium" - } - ], - "builder_ids_in_scope_for_testing": [ - { - "bucket": "ci", - "builder": "Linux Tests (dbg)(1)", - "project": "chromium" - } - ], - "is_compile_only": true - } - }, - "$build/flakiness": { - "check_for_flakiness": true, - "check_for_flakiness_with_resultdb": true - }, - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "jobs": 500, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - }, - "$build/siso": { - "configs": [ - "builder" - ], - "enable_cloud_profiler": true, - "enable_cloud_trace": true, - "experiments": [], - "project": "rbe-chromium-untrusted" - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.linux", - "cq": "required", - "recipe": "chromium_trybot" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac-siso-rel-compilator/properties.json b/infra/config/generated/builders/try/mac-siso-rel-compilator/properties.json deleted file mode 100644 index 781dbc60..0000000 --- a/infra/config/generated/builders/try/mac-siso-rel-compilator/properties.json +++ /dev/null
@@ -1,219 +0,0 @@ -{ - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/mac-siso-rel/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-gpu-archive", - "builder_group": "chromium.gpu", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "intel", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "apply_configs": [ - "use_clang_coverage" - ], - "config": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac Builder", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-mac-archive", - "builder_group": "chromium.mac", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "intel", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "apply_configs": [ - "use_clang_coverage" - ], - "config": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac Release (Intel)", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-gpu-archive", - "builder_group": "chromium.gpu", - "execution_mode": "TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - }, - "parent": { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac Retina Release (AMD)", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-gpu-archive", - "builder_group": "chromium.gpu", - "execution_mode": "TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - }, - "parent": { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac13 Tests", - "project": "chromium" - }, - "builder_spec": { - "builder_group": "chromium.mac", - "execution_mode": "TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - }, - "parent": { - "bucket": "ci", - "builder": "Mac Builder", - "project": "chromium" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - }, - { - "bucket": "ci", - "builder": "Mac Builder", - "project": "chromium" - } - ], - "builder_ids_in_scope_for_testing": [ - { - "bucket": "ci", - "builder": "Mac Release (Intel)", - "project": "chromium" - }, - { - "bucket": "ci", - "builder": "Mac Retina Release (AMD)", - "project": "chromium" - }, - { - "bucket": "ci", - "builder": "Mac13 Tests", - "project": "chromium" - } - ] - } - }, - "$build/code_coverage": { - "coverage_test_types": [ - "overall", - "unit" - ], - "use_clang_coverage": true - }, - "$build/flakiness": { - "check_for_flakiness": true, - "check_for_flakiness_with_resultdb": true - }, - "$build/reclient": { - "instance": "rbe-chromium-untrusted", - "jobs": 500, - "metrics_project": "chromium-reclient-metrics", - "scandeps_server": true - }, - "$build/siso": { - "configs": [ - "builder" - ], - "enable_cloud_profiler": true, - "enable_cloud_trace": true, - "experiments": [], - "project": "rbe-chromium-untrusted" - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.mac", - "recipe": "chromium/compilator" -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac-siso-rel/gn-args.json b/infra/config/generated/builders/try/mac-siso-rel/gn-args.json deleted file mode 100644 index 266a3e2..0000000 --- a/infra/config/generated/builders/try/mac-siso-rel/gn-args.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "gn_args": { - "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt", - "dcheck_always_on": true, - "enable_backup_ref_ptr_feature_flag": true, - "enable_dangling_raw_ptr_checks": true, - "enable_dangling_raw_ptr_feature_flag": true, - "ffmpeg_branding": "Chrome", - "is_component_build": false, - "is_debug": false, - "proprietary_codecs": true, - "symbol_level": 0, - "target_cpu": "x64", - "use_clang_coverage": true, - "use_remoteexec": true, - "use_siso": true - } -} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac-siso-rel/properties.json b/infra/config/generated/builders/try/mac-siso-rel/properties.json deleted file mode 100644 index 414f52e3..0000000 --- a/infra/config/generated/builders/try/mac-siso-rel/properties.json +++ /dev/null
@@ -1,218 +0,0 @@ -{ - "$build/chromium_orchestrator": { - "compilator": "mac-siso-rel-compilator", - "compilator_watcher_git_revision": "27c191f304c8d7329a393d8a69020fc14032c3c3" - }, - "$build/chromium_tests_builder_config": { - "builder_config": { - "additional_exclusions": [ - "infra/config/generated/builders/try/mac-siso-rel/gn-args.json" - ], - "builder_db": { - "entries": [ - { - "builder_id": { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-gpu-archive", - "builder_group": "chromium.gpu", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "intel", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "apply_configs": [ - "use_clang_coverage" - ], - "config": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac Builder", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-mac-archive", - "builder_group": "chromium.mac", - "execution_mode": "COMPILE_AND_TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_arch": "intel", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "apply_configs": [ - "use_clang_coverage" - ], - "config": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac Release (Intel)", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-gpu-archive", - "builder_group": "chromium.gpu", - "execution_mode": "TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - }, - "parent": { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac Retina Release (AMD)", - "project": "chromium" - }, - "builder_spec": { - "build_gs_bucket": "chromium-gpu-archive", - "builder_group": "chromium.gpu", - "execution_mode": "TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - }, - "parent": { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - } - } - }, - { - "builder_id": { - "bucket": "ci", - "builder": "Mac13 Tests", - "project": "chromium" - }, - "builder_spec": { - "builder_group": "chromium.mac", - "execution_mode": "TEST", - "legacy_chromium_config": { - "apply_configs": [ - "mb" - ], - "build_config": "Release", - "config": "chromium", - "target_bits": 64, - "target_platform": "mac" - }, - "legacy_gclient_config": { - "config": "chromium" - }, - "parent": { - "bucket": "ci", - "builder": "Mac Builder", - "project": "chromium" - } - } - } - ] - }, - "builder_ids": [ - { - "bucket": "ci", - "builder": "GPU Mac Builder", - "project": "chromium" - }, - { - "bucket": "ci", - "builder": "Mac Builder", - "project": "chromium" - } - ], - "builder_ids_in_scope_for_testing": [ - { - "bucket": "ci", - "builder": "Mac Release (Intel)", - "project": "chromium" - }, - { - "bucket": "ci", - "builder": "Mac Retina Release (AMD)", - "project": "chromium" - }, - { - "bucket": "ci", - "builder": "Mac13 Tests", - "project": "chromium" - } - ] - } - }, - "$build/code_coverage": { - "coverage_test_types": [ - "overall", - "unit" - ], - "use_clang_coverage": true - }, - "$build/flakiness": { - "check_for_flakiness": true, - "check_for_flakiness_with_resultdb": true - }, - "$build/siso": { - "configs": [ - "builder" - ], - "enable_cloud_profiler": true, - "enable_cloud_trace": true, - "experiments": [], - "project": "rbe-chromium-untrusted" - }, - "$recipe_engine/resultdb/test_presentation": { - "column_keys": [], - "grouping_keys": [ - "status", - "v.test_suite" - ] - }, - "builder_group": "tryserver.chromium.mac", - "cq": "required", - "recipe": "chromium/orchestrator" -} \ No newline at end of file
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index 59d07e80..7dc5d06 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -642,21 +642,12 @@ * [fuchsia-binary-size-siso](https://ci.chromium.org/p/chromium/builders/try/fuchsia-binary-size-siso) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""fuchsia-binary-size-siso"")) * Experiment percentage: 10.0 -* [ios-simulator-siso](https://ci.chromium.org/p/chromium/builders/try/ios-simulator-siso) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""ios-simulator-siso"")) - * Experiment percentage: 5.0 - * [linux_chromium_asan_siso_rel_ng](https://ci.chromium.org/p/chromium/builders/try/linux_chromium_asan_siso_rel_ng) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""linux_chromium_asan_siso_rel_ng"")) * Experiment percentage: 10.0 -* [linux_chromium_compile_siso_dbg_ng](https://ci.chromium.org/p/chromium/builders/try/linux_chromium_compile_siso_dbg_ng) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""linux_chromium_compile_siso_dbg_ng"")) - * Experiment percentage: 10.0 - * [linux_chromium_tsan_siso_rel_ng](https://ci.chromium.org/p/chromium/builders/try/linux_chromium_tsan_siso_rel_ng) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""linux_chromium_tsan_siso_rel_ng"")) * Experiment percentage: 10.0 -* [mac-siso-rel](https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""mac-siso-rel"")) - * Experiment percentage: 5.0 - * [mac13-arm64-rel](https://ci.chromium.org/p/chromium/builders/try/mac13-arm64-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""mac13-arm64-rel"")) * Experiment percentage: 100.0
diff --git a/infra/config/generated/cq-usage/mega_cq_bots.txt b/infra/config/generated/cq-usage/mega_cq_bots.txt index e919f439..4c48a3b 100644 --- a/infra/config/generated/cq-usage/mega_cq_bots.txt +++ b/infra/config/generated/cq-usage/mega_cq_bots.txt
@@ -32,6 +32,7 @@ chromium/try/chromeos-arm-generic-dbg chromium/try/chromeos-arm-generic-rel chromium/try/chromeos-arm64-generic-rel +chromium/try/chromeos-jacuzzi-rel chromium/try/chromeos-octopus-rel chromium/try/dawn-android-arm-deps-rel chromium/try/dawn-android-arm64-deps-rel @@ -65,7 +66,6 @@ chromium/try/ios-simulator chromium/try/ios-simulator-full-configs chromium/try/ios-simulator-noncq -chromium/try/ios-simulator-siso chromium/try/lacros-amd64-generic-rel-gtest chromium/try/lacros-amd64-generic-rel-gtest-and-tast chromium/try/lacros-amd64-generic-rel-non-skylab @@ -117,7 +117,6 @@ chromium/try/linux_chromium_chromeos_msan_rel_ng chromium/try/linux_chromium_compile_dbg_ng chromium/try/linux_chromium_compile_rel_ng -chromium/try/linux_chromium_compile_siso_dbg_ng chromium/try/linux_chromium_dbg_ng chromium/try/linux_chromium_msan_rel_ng chromium/try/linux_chromium_tsan_rel_ng @@ -131,7 +130,6 @@ chromium/try/mac-dawn-rel chromium/try/mac-official chromium/try/mac-rel -chromium/try/mac-siso-rel chromium/try/mac11-arm64-rel chromium/try/mac12-arm64-rel chromium/try/mac12-tests
diff --git a/infra/config/generated/health-specs/health-specs.json b/infra/config/generated/health-specs/health-specs.json index 5356bf1..b03064df 100644 --- a/infra/config/generated/health-specs/health-specs.json +++ b/infra/config/generated/health-specs/health-specs.json
@@ -8006,6 +8006,7 @@ ] }, "chromeos-jacuzzi-rel": { + "contact_team_email": "chromeos-velocity@google.com", "problem_specs": [ { "name": "Unhealthy", @@ -8038,27 +8039,6 @@ } ] }, - "chromeos-jacuzzi-rel-skylab": { - "contact_team_email": "chromeos-velocity@google.com", - "problem_specs": [ - { - "name": "Unhealthy", - "period_days": 7, - "score": 5, - "thresholds": { - "_default": "_default" - } - }, - { - "name": "Low Value", - "period_days": 90, - "score": 1, - "thresholds": { - "_default": "_default" - } - } - ] - }, "chromeos-js-code-coverage": { "problem_specs": [ { @@ -8080,6 +8060,7 @@ ] }, "chromeos-octopus-rel": { + "contact_team_email": "chromeos-velocity@google.com", "problem_specs": [ { "name": "Unhealthy", @@ -8112,27 +8093,6 @@ } ] }, - "chromeos-octopus-rel-skylab": { - "contact_team_email": "chromeos-velocity@google.com", - "problem_specs": [ - { - "name": "Unhealthy", - "period_days": 7, - "score": 5, - "thresholds": { - "_default": "_default" - } - }, - { - "name": "Low Value", - "period_days": 90, - "score": 1, - "thresholds": { - "_default": "_default" - } - } - ] - }, "fuchsia-angle-builder": { "contact_team_email": "angle-team@google.com", "problem_specs": [
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index 4112c54..b2dae0bf 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -1674,10 +1674,6 @@ includable_only: true } builders { - name: "chromium/try/chromeos-jacuzzi-rel-skylab" - includable_only: true - } - builders { name: "chromium/try/chromeos-js-code-coverage" includable_only: true } @@ -1714,10 +1710,6 @@ includable_only: true } builders { - name: "chromium/try/chromeos-octopus-rel-skylab" - includable_only: true - } - builders { name: "chromium/try/chromium_presubmit" disable_reuse: true mode_allowlist: "DRY_RUN" @@ -3012,33 +3004,6 @@ mode_allowlist: "FULL_RUN" } builders { - name: "chromium/try/ios-simulator-siso" - experiment_percentage: 5 - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "docs/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/generated/builders/try/ios-simulator-siso/.+" - } - mode_allowlist: "DRY_RUN" - mode_allowlist: "FULL_RUN" - } - builders { - name: "chromium/try/ios-simulator-siso-compilator" - includable_only: true - } - builders { name: "chromium/try/ios-wpt-fyi-rel" includable_only: true } @@ -4072,29 +4037,6 @@ includable_only: true } builders { - name: "chromium/try/linux_chromium_compile_siso_dbg_ng" - experiment_percentage: 10 - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "docs/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/.+" - } - mode_allowlist: "DRY_RUN" - mode_allowlist: "FULL_RUN" - } - builders { name: "chromium/try/linux_chromium_dbg_ng" location_filters { gerrit_host_regexp: ".*" @@ -4427,33 +4369,6 @@ includable_only: true } builders { - name: "chromium/try/mac-siso-rel" - experiment_percentage: 5 - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "docs/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/generated/builders/try/mac-siso-rel/.+" - } - mode_allowlist: "DRY_RUN" - mode_allowlist: "FULL_RUN" - } - builders { - name: "chromium/try/mac-siso-rel-compilator" - includable_only: true - } - builders { name: "chromium/try/mac-swangle-chromium-try-x64" includable_only: true }
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 3c6b02a..772cf37 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -14215,7 +14215,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel\">mac-siso-rel</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -16505,7 +16505,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_compile_dbg_ng\">linux_chromium_compile_dbg_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_compile_siso_dbg_ng\">linux_chromium_compile_siso_dbg_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_dbg_ng\">linux_chromium_dbg_ng</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_compile_dbg_ng\">linux_chromium_compile_dbg_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_dbg_ng\">linux_chromium_dbg_ng</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -18606,7 +18606,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_compile_dbg_ng\">linux_chromium_compile_dbg_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_compile_siso_dbg_ng\">linux_chromium_compile_siso_dbg_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_dbg_ng\">linux_chromium_dbg_ng</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_compile_dbg_ng\">linux_chromium_compile_dbg_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/linux_chromium_dbg_ng\">linux_chromium_dbg_ng</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -19361,7 +19361,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel\">mac-siso-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac12-tests\">mac12-tests</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac13-tests\">mac13-tests</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_10.15_rel_ng\">mac_chromium_10.15_rel_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_11.0_rel_ng\">mac_chromium_11.0_rel_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_compile_rel_ng\">mac_chromium_compile_rel_ng</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac12-tests\">mac12-tests</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac13-tests\">mac13-tests</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_10.15_rel_ng\">mac_chromium_10.15_rel_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_11.0_rel_ng\">mac_chromium_11.0_rel_ng</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_compile_rel_ng\">mac_chromium_compile_rel_ng</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -21154,7 +21154,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel\">mac-siso-rel</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -21344,7 +21344,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel\">mac-siso-rel</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -21906,7 +21906,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel\">mac-siso-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac13-tests\">mac13-tests</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_compile_rel_ng\">mac_chromium_compile_rel_ng</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-rel\">mac-rel</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac13-tests\">mac13-tests</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/mac_chromium_compile_rel_ng\">mac_chromium_compile_rel_ng</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -37613,7 +37613,10 @@ ' },' ' "builder_group": "chromium.chromiumos",' ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' + ' "recipe": "chromium",' + ' "sheriff_rotations": [' + ' "chromiumos"' + ' ]' '}' execution_timeout_secs: 10800 build_numbers: YES @@ -37658,100 +37661,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/chromeos-jacuzzi-rel\">chromeos-jacuzzi-rel</a></li></ul>" - shadow_builder_adjustments { - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - pool: "luci.chromium.try" - dimensions: "free_space:" - dimensions: "pool:luci.chromium.try" - } - } - builders { - name: "chromeos-jacuzzi-rel-skylab" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "free_space:standard" - dimensions: "os:Ubuntu-22.04" - dimensions: "pool:luci.chromium.ci" - dimensions: "ssd:0" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/properties.json",' - ' "shadow_properties_file": "infra/config/generated/builders/ci/chromeos-jacuzzi-rel-skylab/shadow-properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "chromium.fyi",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' - '}' - priority: 35 - execution_timeout_secs: 36000 - build_numbers: YES - service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "ci_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_ci_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This builder builds public image and runs tests on DUTs in the lab.\n<br/>This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/chromeos-jacuzzi-rel-skylab\">chromeos-jacuzzi-rel-skylab</a></li></ul>" + description_html: "This builder builds chromium and tests it on the public CrOS image on skylab DUTs.\n<br/>This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/chromeos-jacuzzi-rel\">chromeos-jacuzzi-rel</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -37940,100 +37850,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/chromeos-octopus-rel\">chromeos-octopus-rel</a></li></ul>" - shadow_builder_adjustments { - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - pool: "luci.chromium.try" - dimensions: "free_space:" - dimensions: "pool:luci.chromium.try" - } - } - builders { - name: "chromeos-octopus-rel-skylab" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "free_space:standard" - dimensions: "os:Ubuntu-22.04" - dimensions: "pool:luci.chromium.ci" - dimensions: "ssd:0" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/properties.json",' - ' "shadow_properties_file": "infra/config/generated/builders/ci/chromeos-octopus-rel-skylab/shadow-properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "chromium.fyi",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium"' - '}' - priority: 35 - execution_timeout_secs: 36000 - build_numbers: YES - service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "ci_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_ci_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_ci_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This builder builds public image and runs tests on octopus DUTs in the lab.\n<br/>This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/chromeos-octopus-rel-skylab\">chromeos-octopus-rel-skylab</a></li></ul>" + description_html: "This builder builds chromium and tests it on the public CrOS image on skylab DUTs.\n<br/>This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/chromeos-octopus-rel\">chromeos-octopus-rel</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -40178,7 +39995,7 @@ use_invocation_timestamp: true } } - description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/ios-simulator\">ios-simulator</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/ios-simulator-siso\">ios-simulator-siso</a></li></ul>" + description_html: "This builder is mirrored by any of the following try builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/try/ios-simulator\">ios-simulator</a></li></ul>" shadow_builder_adjustments { service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" pool: "luci.chromium.try" @@ -72874,101 +72691,6 @@ ' "led_builder_is_bootstrapped": true,' ' "recipe": "chromium_trybot"' '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "swarming.prpc.cli" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/chromeos-jacuzzi-rel\">chromeos-jacuzzi-rel</a></li></ul>" - } - builders { - name: "chromeos-jacuzzi-rel-skylab" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-22.04" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:0" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/chromeos-jacuzzi-rel-skylab/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.chromiumos",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' execution_timeout_secs: 28800 expiration_secs: 7200 grace_period { @@ -73023,7 +72745,7 @@ use_invocation_timestamp: true } } - description_html: "This is a builder that runs HW test on Skylab. This builder also build Lacros with alternative toolchain.<br/>This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/chromeos-jacuzzi-rel-skylab\">chromeos-jacuzzi-rel-skylab</a></li></ul>" + description_html: "\nThis builder builds chromium and tests it on the public CrOS image on skylab DUTs.\n<br/>This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/chromeos-jacuzzi-rel\">chromeos-jacuzzi-rel</a></li></ul>" contact_team_email: "chromeos-velocity@google.com" } builders { @@ -73256,101 +72978,6 @@ ' "led_builder_is_bootstrapped": true,' ' "recipe": "chromium_trybot"' '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "swarming.prpc.cli" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/chromeos-octopus-rel\">chromeos-octopus-rel</a></li></ul>" - } - builders { - name: "chromeos-octopus-rel-skylab" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builderless:1" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-22.04" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:0" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/chromeos-octopus-rel-skylab/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.chromiumos",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' execution_timeout_secs: 28800 expiration_secs: 7200 grace_period { @@ -73405,7 +73032,7 @@ use_invocation_timestamp: true } } - description_html: "This builder builds public image and runs tests on octopus DUTs in the lab.<br/>This is experimental.<br/>This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/chromeos-octopus-rel-skylab\">chromeos-octopus-rel-skylab</a></li></ul>" + description_html: "\nThis builder builds chromium and tests it on the public CrOS image on skylab DUTs.\n<br/>This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/chromeos-octopus-rel\">chromeos-octopus-rel</a></li></ul>" contact_team_email: "chromeos-velocity@google.com" } builders { @@ -82613,205 +82240,6 @@ description_html: "This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/ios-simulator-noncq\">ios-simulator-noncq</a></li></ul>" } builders { - name: "ios-simulator-siso" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:ios-simulator-siso" - dimensions: "cores:2" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-22.04" - dimensions: "pool:luci.chromium.try" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/ios-simulator-siso/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.mac",' - ' "cq": "required",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium/orchestrator"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - build_numbers: YES - service_account: "chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "chromium.add_one_test_shard" - value: 10 - } - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "swarming.prpc.cli" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This builder shadows ios-simulator builder to compare between Siso builds and Ninja builds.<br/>\nThis builder should be removed after migrating ios-simulator from Ninja to Siso. b/277863839\n<br/>This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/ios-simulator\">ios-simulator</a></li></ul><br/>This is the orchestrator half of an orchestrator + compilator pair of builders. The compilator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/ios-simulator-siso-compilator\">ios-simulator-siso-compilator</a>." - contact_team_email: "chrome-build-team@google.com" - } - builders { - name: "ios-simulator-siso-compilator" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:ios-simulator-siso-compilator" - dimensions: "cpu:arm64" - dimensions: "os:Mac-13" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:1" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/ios-simulator-siso-compilator/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.mac",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium/compilator"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - caches { - name: "xcode_ios_15c500b" - path: "xcode_ios_15c500b.app" - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "swarming.prpc.cli" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/ios-simulator-siso\">ios-simulator-siso</a>." - contact_team_email: "chrome-build-team@google.com" - } - builders { name: "ios-wpt-fyi-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builder:ios-wpt-fyi-rel" @@ -93257,106 +92685,6 @@ description_html: "This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/Linux Builder\">Linux Builder</a></li></ul>" } builders { - name: "linux_chromium_compile_siso_dbg_ng" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:linux_chromium_compile_siso_dbg_ng" - dimensions: "cores:8" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-22.04" - dimensions: "pool:luci.chromium.try" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/linux_chromium_compile_siso_dbg_ng/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.linux",' - ' "cq": "required",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium_trybot"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - caches { - name: "builder" - path: "linux_debug" - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "swarming.prpc.cli" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This builder shadows linux_chromium_compile_dbg_ng builder to compare between Siso builds and Ninja builds.<br/>\nThis builder should be removed after migrating linux_chromium_compile_dbg_ng from Ninja to Siso. b/277863839\n<br/>This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/Linux Builder (dbg)\">Linux Builder (dbg)</a></li></ul>" - contact_team_email: "chrome-build-team@google.com" - } - builders { name: "linux_chromium_dbg_ng" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -96303,201 +95631,6 @@ description_html: "This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/mac-rust-x64-dbg\">mac-rust-x64-dbg</a></li></ul>" } builders { - name: "mac-siso-rel" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:mac-siso-rel" - dimensions: "cores:2" - dimensions: "cpu:x86-64" - dimensions: "os:Ubuntu-22.04" - dimensions: "pool:luci.chromium.try" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/mac-siso-rel/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.mac",' - ' "cq": "required",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium/orchestrator"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - build_numbers: YES - service_account: "chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "chromium.add_one_test_shard" - value: 10 - } - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "swarming.prpc.cli" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This builder shadows mac-rel builder to compare between Siso builds and Ninja builds.<br/>\nThis builder should be removed after migrating mac-rel from Ninja to Siso. b/277863839\n<br/>This builder mirrors the following CI builders:<br/><ul><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/GPU Mac Builder\">GPU Mac Builder</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/Mac Builder\">Mac Builder</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/Mac Release (Intel)\">Mac Release (Intel)</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/Mac Retina Release (AMD)\">Mac Retina Release (AMD)</a></li><li><a href=\"https://ci.chromium.org/p/chromium/builders/ci/Mac13 Tests\">Mac13 Tests</a></li></ul><br/>This is the orchestrator half of an orchestrator + compilator pair of builders. The compilator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel-compilator\">mac-siso-rel-compilator</a>." - contact_team_email: "chrome-build-team@google.com" - } - builders { - name: "mac-siso-rel-compilator" - swarming_host: "chromium-swarm.appspot.com" - dimensions: "builder:mac-siso-rel-compilator" - dimensions: "cpu:arm64" - dimensions: "os:Mac-13" - dimensions: "pool:luci.chromium.try" - dimensions: "ssd:1" - exe { - cipd_package: "infra/chromium/bootstrapper/${platform}" - cipd_version: "latest" - cmd: "bootstrapper" - } - properties: - '{' - ' "$bootstrap/exe": {' - ' "exe": {' - ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' - ' "cipd_version": "refs/heads/main",' - ' "cmd": [' - ' "luciexe"' - ' ]' - ' }' - ' },' - ' "$bootstrap/properties": {' - ' "properties_file": "infra/config/generated/builders/try/mac-siso-rel-compilator/properties.json",' - ' "top_level_project": {' - ' "ref": "refs/heads/main",' - ' "repo": {' - ' "host": "chromium.googlesource.com",' - ' "project": "chromium/src"' - ' }' - ' }' - ' },' - ' "builder_group": "tryserver.chromium.mac",' - ' "led_builder_is_bootstrapped": true,' - ' "recipe": "chromium/compilator"' - '}' - execution_timeout_secs: 14400 - expiration_secs: 7200 - grace_period { - seconds: 120 - } - build_numbers: YES - service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" - task_template_canary_percentage { - value: 5 - } - experiments { - key: "chromium_swarming.expose_merge_script_failures" - value: 100 - } - experiments { - key: "luci.recipes.use_python3" - value: 100 - } - experiments { - key: "swarming.prpc.cli" - value: 100 - } - resultdb { - enable: true - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "try_test_results" - test_results {} - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "gpu_try_test_results" - test_results { - predicate { - test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" - } - } - } - bq_exports { - project: "chrome-luci-data" - dataset: "chromium" - table: "blink_web_tests_try_test_results" - test_results { - predicate { - test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*_wpt_tests/.+)" - } - } - } - history_options { - use_invocation_timestamp: true - } - } - description_html: "This is the compilator half of an orchestrator + compilator pair of builders. The orchestrator is <a href=\"https://ci.chromium.org/p/chromium/builders/try/mac-siso-rel\">mac-siso-rel</a>." - contact_team_email: "chrome-build-team@google.com" - } - builders { name: "mac-swangle-chromium-try-x64" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index 6d2214ff..80364f3 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -3141,18 +3141,12 @@ name: "buildbucket/luci.chromium.try/chromeos-jacuzzi-rel" } builders { - name: "buildbucket/luci.chromium.try/chromeos-jacuzzi-rel-skylab" - } - builders { name: "buildbucket/luci.chromium.try/chromeos-js-coverage-rel" } builders { name: "buildbucket/luci.chromium.try/chromeos-octopus-rel" } builders { - name: "buildbucket/luci.chromium.try/chromeos-octopus-rel-skylab" - } - builders { name: "buildbucket/luci.chromium.try/chromium_presubmit" } builders { @@ -3204,12 +3198,6 @@ name: "buildbucket/luci.chromium.try/ios-simulator-full-configs" } builders { - name: "buildbucket/luci.chromium.try/ios-simulator-siso" - } - builders { - name: "buildbucket/luci.chromium.try/ios-simulator-siso-compilator" - } - builders { name: "buildbucket/luci.chromium.try/lacros-amd64-generic-rel-gtest" } builders { @@ -3303,9 +3291,6 @@ name: "buildbucket/luci.chromium.try/linux_chromium_compile_dbg_ng" } builders { - name: "buildbucket/luci.chromium.try/linux_chromium_compile_siso_dbg_ng" - } - builders { name: "buildbucket/luci.chromium.try/linux_chromium_dbg_ng" } builders { @@ -3330,12 +3315,6 @@ name: "buildbucket/luci.chromium.try/mac-rel-compilator" } builders { - name: "buildbucket/luci.chromium.try/mac-siso-rel" - } - builders { - name: "buildbucket/luci.chromium.try/mac-siso-rel-compilator" - } - builders { name: "buildbucket/luci.chromium.try/mac-updater-try-builder-dbg" } builders { @@ -9609,16 +9588,6 @@ short_name: "cmp" } builders { - name: "buildbucket/luci.chromium.ci/chromeos-jacuzzi-rel-skylab" - category: "ash" - short_name: "jcz" - } - builders { - name: "buildbucket/luci.chromium.ci/chromeos-octopus-rel-skylab" - category: "ash" - short_name: "oct" - } - builders { name: "buildbucket/luci.chromium.ci/win-celab-builder-rel" category: "celab" } @@ -17658,9 +17627,6 @@ name: "buildbucket/luci.chromium.try/chromeos-jacuzzi-rel" } builders { - name: "buildbucket/luci.chromium.try/chromeos-jacuzzi-rel-skylab" - } - builders { name: "buildbucket/luci.chromium.try/chromeos-js-code-coverage" } builders { @@ -17670,9 +17636,6 @@ name: "buildbucket/luci.chromium.try/chromeos-octopus-rel" } builders { - name: "buildbucket/luci.chromium.try/chromeos-octopus-rel-skylab" - } - builders { name: "buildbucket/luci.chromium.try/chromium_presubmit" } builders { @@ -17964,12 +17927,6 @@ name: "buildbucket/luci.chromium.try/ios-simulator-noncq" } builders { - name: "buildbucket/luci.chromium.try/ios-simulator-siso" - } - builders { - name: "buildbucket/luci.chromium.try/ios-simulator-siso-compilator" - } - builders { name: "buildbucket/luci.chromium.try/ios-wpt-fyi-rel" } builders { @@ -18294,9 +18251,6 @@ name: "buildbucket/luci.chromium.try/linux_chromium_compile_rel_ng" } builders { - name: "buildbucket/luci.chromium.try/linux_chromium_compile_siso_dbg_ng" - } - builders { name: "buildbucket/luci.chromium.try/linux_chromium_dbg_ng" } builders { @@ -18387,12 +18341,6 @@ name: "buildbucket/luci.chromium.try/mac-rust-x64-dbg" } builders { - name: "buildbucket/luci.chromium.try/mac-siso-rel" - } - builders { - name: "buildbucket/luci.chromium.try/mac-siso-rel-compilator" - } - builders { name: "buildbucket/luci.chromium.try/mac-swangle-chromium-try-x64" } builders { @@ -19124,15 +19072,9 @@ name: "buildbucket/luci.chromium.try/chromeos-jacuzzi-rel" } builders { - name: "buildbucket/luci.chromium.try/chromeos-jacuzzi-rel-skylab" - } - builders { name: "buildbucket/luci.chromium.try/chromeos-octopus-rel" } builders { - name: "buildbucket/luci.chromium.try/chromeos-octopus-rel-skylab" - } - builders { name: "buildbucket/luci.chromium.try/gpu-fyi-try-chromeos-amd64-generic" } builders { @@ -19622,9 +19564,6 @@ name: "buildbucket/luci.chromium.try/linux_chromium_compile_rel_ng" } builders { - name: "buildbucket/luci.chromium.try/linux_chromium_compile_siso_dbg_ng" - } - builders { name: "buildbucket/luci.chromium.try/linux_chromium_dbg_ng" } builders { @@ -19753,12 +19692,6 @@ name: "buildbucket/luci.chromium.try/ios-simulator-noncq" } builders { - name: "buildbucket/luci.chromium.try/ios-simulator-siso" - } - builders { - name: "buildbucket/luci.chromium.try/ios-simulator-siso-compilator" - } - builders { name: "buildbucket/luci.chromium.try/ios-wpt-fyi-rel" } builders { @@ -19810,12 +19743,6 @@ name: "buildbucket/luci.chromium.try/mac-rel-compilator" } builders { - name: "buildbucket/luci.chromium.try/mac-siso-rel" - } - builders { - name: "buildbucket/luci.chromium.try/mac-siso-rel-compilator" - } - builders { name: "buildbucket/luci.chromium.try/mac-ubsan-fyi-rel" } builders {
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index 670c8880..2173816 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -4112,15 +4112,6 @@ } } job { - id: "chromeos-jacuzzi-rel-skylab" - realm: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "ci" - builder: "chromeos-jacuzzi-rel-skylab" - } -} -job { id: "chromeos-js-code-coverage" realm: "ci" schedule: "triggered" @@ -4144,15 +4135,6 @@ } } job { - id: "chromeos-octopus-rel-skylab" - realm: "ci" - buildbucket { - server: "cr-buildbucket.appspot.com" - bucket: "ci" - builder: "chromeos-octopus-rel-skylab" - } -} -job { id: "fuchsia-angle-builder" realm: "ci" buildbucket { @@ -6555,9 +6537,7 @@ triggers: "chromeos-arm-generic-rel" triggers: "chromeos-arm64-generic-rel" triggers: "chromeos-jacuzzi-rel" - triggers: "chromeos-jacuzzi-rel-skylab" triggers: "chromeos-octopus-rel" - triggers: "chromeos-octopus-rel-skylab" triggers: "fuchsia-angle-builder" triggers: "fuchsia-arm64-cast-receiver-rel" triggers: "fuchsia-fyi-arm64-dbg"
diff --git a/infra/config/generated/sheriff-rotations/chromiumos.txt b/infra/config/generated/sheriff-rotations/chromiumos.txt index b921a05e..66f7dec9 100644 --- a/infra/config/generated/sheriff-rotations/chromiumos.txt +++ b/infra/config/generated/sheriff-rotations/chromiumos.txt
@@ -1,4 +1,5 @@ ci/chromeos-amd64-generic-rel-tast +ci/chromeos-jacuzzi-rel ci/chromeos-octopus-rel ci/lacros-amd64-generic-rel-non-skylab ci/lacros-amd64-generic-rel-tast
diff --git a/infra/config/lib/description_exceptions.star b/infra/config/lib/description_exceptions.star index a4eb880..8f1af24 100644 --- a/infra/config/lib/description_exceptions.star +++ b/infra/config/lib/description_exceptions.star
@@ -782,7 +782,6 @@ "ios-simulator-full-configs", "ios-simulator-multi-window", "ios-simulator-noncq", - "ios-simulator-siso-compilator", "ios-wpt-fyi-rel", "ios16-beta-simulator", "ios16-sdk-simulator", @@ -916,7 +915,6 @@ "mac-rel-cft", "mac-rel-compilator", "mac-rust-x64-dbg", - "mac-siso-rel-compilator", "mac-swangle-chromium-try-x64", "mac-ubsan-fyi-rel", "mac-updater-try-builder-dbg",
diff --git a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star index ff47297..4bb8ac56 100644 --- a/infra/config/subprojects/chromium/ci/chromium.chromiumos.star +++ b/infra/config/subprojects/chromium/ci/chromium.chromiumos.star
@@ -523,12 +523,15 @@ ci.builder( name = "chromeos-jacuzzi-rel", branch_selector = branches.selector.CROS_LTS_BRANCHES, + description_html = """\ +This builder builds chromium and tests it on the public CrOS image on skylab DUTs. +""", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( config = "chromium", apply_configs = [ - "arm64", "chromeos", + "checkout_lacros_sdk", ], ), chromium_config = builder_config.chromium_config( @@ -542,38 +545,51 @@ target_platform = builder_config.target_platform.CHROMEOS, target_cros_boards = [ "jacuzzi", + # `arm64-generic` is necessary for lacros build. + "arm64-generic", ], ), - build_gs_bucket = "chromium-chromiumos-archive", + skylab_upload_location = builder_config.skylab_upload_location( + # Both CI and try use the same `chromium-skylab-try` bucket. + gs_bucket = "chromium-skylab-try", + gs_extra = "ash", + ), ), gn_args = gn_args.config( configs = [ + "also_build_lacros_chrome_for_architecture_arm64", "chromeos_device", - "reclient", + "dcheck_off", + "include_unwind_tables", + "is_skylab", "jacuzzi", "ozone_headless", - "dcheck_always_on", + "reclient", ], ), - # Need to remove this builder since it's not running tests and already - # migrated to skylab. - sheriff_rotations = args.ignore_default(None), + # Tast tests should be monitored by CrOS gardeners, not Chromium gardeners. + sheriff_rotations = args.ignore_default(sheriff_rotations.CHROMIUMOS), console_view_entry = consoles.console_view_entry( category = "simple|release", short_name = "jcz", ), main_console_view = "main", + contact_team_email = "chromeos-velocity@google.com", reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI, ) ci.builder( name = "chromeos-octopus-rel", branch_selector = branches.selector.CROS_LTS_BRANCHES, + description_html = """\ +This builder builds chromium and tests it on the public CrOS image on skylab DUTs. +""", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( config = "chromium", apply_configs = [ "chromeos", + "checkout_lacros_sdk", ], ), chromium_config = builder_config.chromium_config( @@ -587,17 +603,26 @@ target_platform = builder_config.target_platform.CHROMEOS, target_cros_boards = [ "octopus", + # `amd64-generic` is necessary for lacros build. + "amd64-generic", ], ), - build_gs_bucket = "chromium-chromiumos-archive", + skylab_upload_location = builder_config.skylab_upload_location( + # Both CI and try use the same `chromium-skylab-try` bucket. + gs_bucket = "chromium-skylab-try", + gs_extra = "ash", + ), ), gn_args = gn_args.config( configs = [ + "also_build_lacros_chrome_for_architecture_amd64", "chromeos_device", - "reclient", + "dcheck_off", + "include_unwind_tables", + "is_skylab", "octopus", "ozone_headless", - "dcheck_always_on", + "reclient", ], ), # Tast tests should be monitored by CrOS gardeners, not Chromium gardeners. @@ -607,6 +632,7 @@ short_name = "oct", ), main_console_view = "main", + contact_team_email = "chromeos-velocity@google.com", reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CI, )
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 74025407..44a570b 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -155,113 +155,6 @@ notifies = ["Site Isolation Android"], ) -# TODO(b/299215988): Move to chromium.chromiumos.star. -ci.builder( - name = "chromeos-jacuzzi-rel-skylab", - description_html = """\ -This builder builds public image and runs tests on DUTs in the lab. -""", - builder_spec = builder_config.builder_spec( - gclient_config = builder_config.gclient_config( - config = "chromium", - apply_configs = [ - "chromeos", - "checkout_lacros_sdk", - ], - ), - chromium_config = builder_config.chromium_config( - config = "chromium", - apply_configs = [ - "mb", - ], - build_config = builder_config.build_config.RELEASE, - target_arch = builder_config.target_arch.ARM, - target_bits = 32, - target_platform = builder_config.target_platform.CHROMEOS, - target_cros_boards = [ - "jacuzzi", - "arm64-generic", - ], - ), - skylab_upload_location = builder_config.skylab_upload_location( - # Both CI and try use the same `chromium-skylab-try` bucket. - gs_bucket = "chromium-skylab-try", - gs_extra = "ash", - ), - ), - gn_args = gn_args.config( - configs = [ - "chromeos_device", - "ozone_headless", - "dcheck_off", - "reclient", - "jacuzzi", - "include_unwind_tables", - "also_build_lacros_chrome_for_architecture_arm64", - "is_skylab", - ], - ), - os = os.LINUX_DEFAULT, - console_view_entry = consoles.console_view_entry( - category = "ash", - short_name = "jcz", - ), - contact_team_email = "chromeos-velocity@google.com", -) - -# TODO(b/299215988): Move to chromium.chromiumos.star. -ci.builder( - name = "chromeos-octopus-rel-skylab", - description_html = """\ -This builder builds public image and runs tests on octopus DUTs in the lab. -""", - builder_spec = builder_config.builder_spec( - gclient_config = builder_config.gclient_config( - config = "chromium", - apply_configs = [ - "chromeos", - "checkout_lacros_sdk", - ], - ), - chromium_config = builder_config.chromium_config( - config = "chromium", - apply_configs = [ - "mb", - ], - build_config = builder_config.build_config.RELEASE, - target_arch = builder_config.target_arch.INTEL, - target_bits = 32, - target_platform = builder_config.target_platform.CHROMEOS, - target_cros_boards = [ - "octopus", - "amd64-generic", - ], - ), - skylab_upload_location = builder_config.skylab_upload_location( - # Both CI and try use the same `chromium-skylab-try` bucket. - gs_bucket = "chromium-skylab-try", - gs_extra = "ash", - ), - ), - gn_args = gn_args.config( - configs = [ - "also_build_lacros_chrome_for_architecture_amd64", - "chromeos_device", - "include_unwind_tables", - "is_skylab", - "octopus", - "ozone_headless", - "reclient", - ], - ), - os = os.LINUX_DEFAULT, - console_view_entry = consoles.console_view_entry( - category = "ash", - short_name = "oct", - ), - contact_team_email = "chromeos-velocity@google.com", -) - ci.builder( name = "linux-annotator-rel", builder_spec = builder_config.builder_spec(
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star b/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star index 2c3975b..38b67a8d 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.chromiumos.star
@@ -28,6 +28,7 @@ siso_configs = ["builder"], siso_enable_cloud_profiler = True, siso_enable_cloud_trace = True, + siso_enabled = True, siso_project = siso.project.DEFAULT_UNTRUSTED, ) @@ -112,7 +113,6 @@ compilator = "chromeos-amd64-generic-rel-gtest-compilator", contact_team_email = "chromeos-sw-engprod@google.com", main_list_view = "try", - siso_enabled = True, tryjob = try_.job( equivalent_builder = "try/chromeos-amd64-generic-rel-gtest-and-tast", equivalent_builder_percentage = 100, @@ -149,7 +149,6 @@ compilator = "chromeos-amd64-generic-rel-gtest-and-tast-compilator", contact_team_email = "chromeos-sw-engprod@google.com", main_list_view = "try", - siso_enabled = True, tryjob = try_.job( omit_from_luci_cv = True, ), @@ -171,7 +170,6 @@ ], contact_team_email = "chromeos-sw-engprod@google.com", main_list_view = "try", - siso_enabled = True, ) try_.compilator_builder( @@ -188,7 +186,6 @@ ], contact_team_email = "chromeos-sw-engprod@google.com", main_list_view = "try", - siso_enabled = True, ) try_.builder( @@ -215,7 +212,6 @@ "chromium.enable_cleandead": 100, }, main_list_view = "try", - siso_enabled = True, tryjob = try_.job(), ) @@ -248,7 +244,6 @@ compilator = "lacros-amd64-generic-rel-gtest-compilator", contact_team_email = "chrome-desktop-engprod@google.com", main_list_view = "try", - siso_enabled = True, # TODO(crbug.com/1471166) Enable on CQ. tryjob = try_.job( equivalent_builder = "try/lacros-amd64-generic-rel-gtest-and-tast", @@ -286,7 +281,6 @@ compilator = "lacros-amd64-generic-rel-gtest-and-tast-compilator", contact_team_email = "chrome-desktop-engprod@google.com", main_list_view = "try", - siso_enabled = True, tryjob = try_.job( omit_from_luci_cv = True, ), @@ -308,7 +302,6 @@ ], contact_team_email = "chrome-desktop-engprod@google.com", main_list_view = "try", - siso_enabled = True, ) try_.compilator_builder( @@ -325,7 +318,6 @@ ], contact_team_email = "chrome-desktop-engprod@google.com", main_list_view = "try", - siso_enabled = True, ) try_.builder( @@ -371,7 +363,6 @@ "chromium.enable_cleandead": 100, }, main_list_view = "try", - siso_enabled = True, tryjob = try_.job(), ) @@ -442,41 +433,13 @@ try_.builder( name = "chromeos-jacuzzi-rel", branch_selector = branches.selector.CROS_LTS_BRANCHES, + description_html = """ +This builder builds chromium and tests it on the public CrOS image on skylab DUTs. +""", mirrors = [ "ci/chromeos-jacuzzi-rel", ], - gn_args = gn_args.config( - configs = [ - "ci/chromeos-jacuzzi-rel", - "dcheck_always_on", - ], - ), - main_list_view = "try", -) - -try_.builder( - name = "chromeos-jacuzzi-rel-skylab", - branch_selector = branches.selector.MAIN, - description_html = "This is a builder that runs HW test on Skylab." + - " This builder also build Lacros with alternative toolchain.", - mirrors = [ - "ci/chromeos-jacuzzi-rel-skylab", - ], - gn_args = "ci/chromeos-jacuzzi-rel-skylab", - contact_team_email = "chromeos-velocity@google.com", - execution_timeout = 8 * time.hour, - main_list_view = "try", -) - -try_.builder( - name = "chromeos-octopus-rel-skylab", - branch_selector = branches.selector.MAIN, - description_html = "This builder builds public image and runs tests on octopus DUTs in the lab.<br/>" + - "This is experimental.", - mirrors = [ - "ci/chromeos-octopus-rel-skylab", - ], - gn_args = "ci/chromeos-octopus-rel-skylab", + gn_args = "ci/chromeos-jacuzzi-rel", contact_team_email = "chromeos-velocity@google.com", execution_timeout = 8 * time.hour, main_list_view = "try", @@ -485,10 +448,15 @@ try_.builder( name = "chromeos-octopus-rel", branch_selector = branches.selector.CROS_LTS_BRANCHES, + description_html = """ +This builder builds chromium and tests it on the public CrOS image on skylab DUTs. +""", mirrors = [ "ci/chromeos-octopus-rel", ], gn_args = "ci/chromeos-octopus-rel", + contact_team_email = "chromeos-velocity@google.com", + execution_timeout = 8 * time.hour, main_list_view = "try", ) @@ -521,7 +489,6 @@ # TODO(crbug.com/1372179): Use orchestrator pool once overloaded test pools # are addressed # use_orchestrator_pool = True, - siso_enabled = True, tryjob = try_.job(), use_clang_coverage = True, ) @@ -531,7 +498,6 @@ branch_selector = branches.selector.CROS_LTS_BRANCHES, cores = 32, main_list_view = "try", - siso_enabled = True, ) try_.builder( @@ -542,7 +508,6 @@ "ci/linux-lacros-dbg", ], gn_args = "ci/linux-lacros-dbg", - siso_enabled = True, ) try_.orchestrator_builder( @@ -573,7 +538,6 @@ # TODO(crbug.com/1372179): Use orchestrator pool once overloaded test pools # are addressed # use_orchestrator_pool = True, - siso_enabled = True, tryjob = try_.job(), use_clang_coverage = True, ) @@ -583,7 +547,6 @@ branch_selector = branches.selector.CROS_BRANCHES, cores = 32, main_list_view = "try", - siso_enabled = True, ) try_.builder( @@ -599,7 +562,6 @@ "ci/linux-chromeos-dbg", ], ), - siso_enabled = True, ) try_.builder( @@ -619,7 +581,6 @@ "enable_backup_ref_ptr_feature_flag", ], ), - siso_enabled = True, ) try_.builder( @@ -634,7 +595,6 @@ ], ), reclient_instance = reclient.instance.DEFAULT_UNTRUSTED, - siso_enabled = True, tryjob = try_.job( location_filters = [ "chromeos/ash/components/chromebox_for_meetings/.+",
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star index af44544..51c2fbb 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.linux.star
@@ -733,35 +733,6 @@ tryjob = try_.job(), ) -# TODO: crbug.com/1502025 - Reduce duplicated configs from the shadow builder. -try_.builder( - name = "linux_chromium_compile_siso_dbg_ng", - description_html = """\ -This builder shadows linux_chromium_compile_dbg_ng builder to compare between Siso builds and Ninja builds.<br/> -This builder should be removed after migrating linux_chromium_compile_dbg_ng from Ninja to Siso. b/277863839 -""", - mirrors = builder_config.copy_from("try/linux_chromium_compile_dbg_ng"), - builder_config_settings = builder_config.try_settings( - include_all_triggered_testers = True, - is_compile_only = True, - ), - gn_args = "try/linux_chromium_compile_dbg_ng", - builderless = False, - caches = [ - swarming.cache( - name = "builder", - path = "linux_debug", - ), - ], - contact_team_email = "chrome-build-team@google.com", - main_list_view = "try", - reclient_jobs = reclient.jobs.HIGH_JOBS_FOR_CQ, - siso_enabled = True, - tryjob = try_.job( - experiment_percentage = 10, - ), -) - try_.builder( name = "linux_chromium_compile_rel_ng", mirrors = [
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star index 1102168..9f48a7a 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -188,38 +188,6 @@ siso_enabled = True, ) -# TODO: crbug.com/1502025 - Reduce duplicated configs from the shadow builder. -try_.orchestrator_builder( - name = "mac-siso-rel", - description_html = """\ -This builder shadows mac-rel builder to compare between Siso builds and Ninja builds.<br/> -This builder should be removed after migrating mac-rel from Ninja to Siso. b/277863839 -""", - mirrors = builder_config.copy_from("try/mac-rel"), - gn_args = "try/mac-rel", - compilator = "mac-siso-rel-compilator", - contact_team_email = "chrome-build-team@google.com", - coverage_test_types = ["overall", "unit"], - experiments = { - # go/nplus1shardsproposal - "chromium.add_one_test_shard": 10, - }, - main_list_view = "try", - siso_enabled = True, - tryjob = try_.job( - experiment_percentage = 5, - ), - use_clang_coverage = True, -) - -try_.compilator_builder( - name = "mac-siso-rel-compilator", - cpu = cpu.ARM64, - contact_team_email = "chrome-build-team@google.com", - main_list_view = "try", - siso_enabled = True, -) - try_.builder( name = "mac10.15-wpt-content-shell-fyi-rel", mirrors = [ @@ -631,41 +599,6 @@ xcode = xcode.xcode_default, ) -# TODO: crbug.com/1502025 - Reduce duplicated configs from the shadow builder. -try_.orchestrator_builder( - name = "ios-simulator-siso", - description_html = """\ -This builder shadows ios-simulator builder to compare between Siso builds and Ninja builds.<br/> -This builder should be removed after migrating ios-simulator from Ninja to Siso. b/277863839 -""", - mirrors = builder_config.copy_from("try/ios-simulator"), - gn_args = "try/ios-simulator", - os = os.LINUX_DEFAULT, - compilator = "ios-simulator-siso-compilator", - contact_team_email = "chrome-build-team@google.com", - coverage_exclude_sources = "ios_test_files_and_test_utils", - coverage_test_types = ["overall", "unit"], - experiments = { - # go/nplus1shardsproposal - "chromium.add_one_test_shard": 10, - }, - main_list_view = "try", - siso_enabled = True, - tryjob = try_.job( - experiment_percentage = 5, - ), - use_clang_coverage = True, -) - -try_.compilator_builder( - name = "ios-simulator-siso-compilator", - cpu = cpu.ARM64, - contact_team_email = "chrome-build-team@google.com", - main_list_view = "try", - siso_enabled = True, - xcode = xcode.xcode_default, -) - ios_builder( name = "ios-simulator-full-configs", branch_selector = branches.selector.IOS_BRANCHES,
diff --git a/internal b/internal index 29258ca..2f414f9 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 29258ca44e62a5796cd874022d3dc89c8e39b69c +Subproject commit 2f414f9eacfd0f8796e5eb675076cc7fb49c6954
diff --git a/ios/chrome/app/main_controller_unittest.mm b/ios/chrome/app/main_controller_unittest.mm index 0b8def0..7146101 100644 --- a/ios/chrome/app/main_controller_unittest.mm +++ b/ios/chrome/app/main_controller_unittest.mm
@@ -11,6 +11,7 @@ #import "ios/chrome/app/application_delegate/app_state.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/reading_list/model/reading_list_model_factory.h" #import "ios/chrome/browser/reading_list/model/reading_list_test_utils.h" @@ -46,11 +47,11 @@ browser_state_ = builder.Build(); - bookmarks::BookmarkModel* bookmarks_model = + LegacyBookmarkModel* bookmarks_model = ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( browser_state_.get()); bookmarks::test::WaitForBookmarkModelToLoad(bookmarks_model); - bookmarks::BookmarkModel* account_bookmark_model = + LegacyBookmarkModel* account_bookmark_model = ios::AccountBookmarkModelFactory::GetForBrowserState( browser_state_.get()); bookmarks::test::WaitForBookmarkModelToLoad(account_bookmark_model);
diff --git a/ios/chrome/app/spotlight/bookmark_spotlight_manager_unittest.mm b/ios/chrome/app/spotlight/bookmark_spotlight_manager_unittest.mm index 49553eaf..484fbd9a 100644 --- a/ios/chrome/app/spotlight/bookmark_spotlight_manager_unittest.mm +++ b/ios/chrome/app/spotlight/bookmark_spotlight_manager_unittest.mm
@@ -22,6 +22,7 @@ #import "ios/chrome/app/spotlight/spotlight_manager.h" #import "ios/chrome/app/spotlight/spotlight_util.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "net/base/apple/url_conversions.h" #import "testing/gmock/include/gmock/gmock.h"
diff --git a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h index abcec7b..ef7cb33 100644 --- a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h +++ b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h
@@ -8,6 +8,7 @@ #import "ios/chrome/app/spotlight/base_spotlight_manager.h" class ChromeBrowserState; +class LegacyBookmarkModel; namespace favicon { class LargeIconService; @@ -15,7 +16,6 @@ namespace bookmarks { class BookmarkNode; -class BookmarkModel; } @class CSSearchableItem; @@ -30,8 +30,8 @@ - (instancetype) initWithLargeIconService:(favicon::LargeIconService*)largeIconService localOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel - accountBookmarkModel:(bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel + accountBookmarkModel:(LegacyBookmarkModel*)accountBookmarkModel spotlightInterface:(SpotlightInterface*)spotlightInterface searchableItemFactory:(SearchableItemFactory*)searchableItemFactory;
diff --git a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm index 02d824b4..da60563c 100644 --- a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm +++ b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm
@@ -17,12 +17,12 @@ #import "base/timer/elapsed_timer.h" #import "base/version.h" #import "components/bookmarks/browser/base_bookmark_model_observer.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "ios/chrome/app/spotlight/searchable_item_factory.h" #import "ios/chrome/app/spotlight/spotlight_interface.h" #import "ios/chrome/app/spotlight/spotlight_logger.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/favicon/model/ios_chrome_large_icon_service_factory.h" @@ -67,9 +67,9 @@ std::unique_ptr<BookmarkModelBridge> _accountBookmarkModelBridge; // Keep a reference to detach before deallocing. - raw_ptr<bookmarks::BookmarkModel> _localOrSyncableBookmarkModel; // weak + raw_ptr<LegacyBookmarkModel> _localOrSyncableBookmarkModel; // weak // `_accountBookmarkModel` can be `nullptr`. - raw_ptr<bookmarks::BookmarkModel> _accountBookmarkModel; // weak + raw_ptr<LegacyBookmarkModel> _accountBookmarkModel; // weak // Number of nodes indexed in initial scan. NSUInteger _nodesIndexed; @@ -111,8 +111,8 @@ - (instancetype) initWithLargeIconService:(favicon::LargeIconService*)largeIconService localOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel - accountBookmarkModel:(bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel + accountBookmarkModel:(LegacyBookmarkModel*)accountBookmarkModel spotlightInterface:(SpotlightInterface*)spotlightInterface searchableItemFactory:(SearchableItemFactory*)searchableItemFactory { self = [super initWithSpotlightInterface:spotlightInterface @@ -168,7 +168,7 @@ } NSMutableArray* parentNames = [self parentFolderNamesForNode:node->parent()]; - bookmarks::BookmarkModel* parentModel = [self bookmarkModelForNode:node]; + LegacyBookmarkModel* parentModel = [self bookmarkModelForNode:node]; if (node->is_folder() && !parentModel->is_permanent_node(node)) { [parentNames addObject:base::SysUTF16ToNSString(node->GetTitle())]; @@ -302,7 +302,7 @@ // Refreshes all nodes in the subtree of node. - (void)refreshNodeInIndex:(const bookmarks::BookmarkNode*)node - inModel:(bookmarks::BookmarkModel*)model { + inModel:(LegacyBookmarkModel*)model { DCHECK(node); DCHECK(model); @@ -318,7 +318,7 @@ // order (see comment in NodeTypeForUuidLookup). - (const bookmarks::BookmarkNode*)nodeWithUUID:(base::Uuid)uuid usingLocalModel:(BOOL)isLocalModel { - bookmarks::BookmarkModel* model = + LegacyBookmarkModel* model = isLocalModel ? _localOrSyncableBookmarkModel : _accountBookmarkModel; if (!model || !model->loaded()) { @@ -488,7 +488,7 @@ _pendingLargeIconTasksCount); } -- (bookmarks::BookmarkModel*)bookmarkModelForNode: +- (LegacyBookmarkModel*)bookmarkModelForNode: (const bookmarks::BookmarkNode*)node { if (node->HasAncestor(_localOrSyncableBookmarkModel->root_node())) { return _localOrSyncableBookmarkModel; @@ -553,11 +553,11 @@ #pragma mark - BookmarkModelBridgeObserver -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { [self reindexBookmarksIfNeeded]; } -- (void)bookmarkModelBeingDeleted:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelBeingDeleted:(LegacyBookmarkModel*)model { if (_accountBookmarkModel == model) { _accountBookmarkModel = nullptr; } @@ -569,7 +569,7 @@ [self stopIndexing]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { if (self.isAppInBackground) { // Normally, no model updates should happen in background. @@ -591,11 +591,11 @@ [self refreshNodeInIndex:bookmarkNode inModel:model]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didAddNode:(const bookmarks::BookmarkNode*)node toFolder:(const bookmarks::BookmarkNode*)folder { if (self.isAppInBackground) { @@ -618,7 +618,7 @@ [self refreshNodeInIndex:node inModel:model]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { @@ -642,12 +642,12 @@ [self refreshNodeInIndex:bookmarkNode inModel:model]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { } -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { if (self.isAppInBackground) { // Normally, no model updates should happen in background. // In case they do, process them on foreground. @@ -668,7 +668,7 @@ [self clearAllBookmarkSpotlightItems]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model willDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { if (self.isAppInBackground) { @@ -692,7 +692,7 @@ } // The node favicon changed. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeFaviconForNode:(const bookmarks::BookmarkNode*)bookmarkNode { if (self.isAppInBackground) { // Normally, no model updates should happen in background. @@ -714,7 +714,7 @@ [self refreshNodeInIndex:bookmarkNode inModel:model]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model willChangeBookmarkNode:(const bookmarks::BookmarkNode*)bookmarkNode { if (self.isAppInBackground) { // Normally, no model updates should happen in background.
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 4be2be2f..477d900 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -2870,9 +2870,6 @@ <message name="IDS_IOS_PAGE_INFO_CONNECTION" desc="Title of the button opening the connection information (in page info)"> Connection </message> - <message name="IDS_IOS_PAGE_INFO_CONNECTION_SECURITY" desc="Title of the navigation controller to display when the page's security is presented."> - Connection Security - </message> <message name="IDS_IOS_PAGE_INFO_ABOUT_THIS_PAGE" desc="Title of the button opening the About This Page (in page info)"> About This Page </message> @@ -2891,6 +2888,9 @@ <message name="IDS_IOS_PAGE_INFO_RELOAD" desc="Button title in the page info bubble that allows to reload the current page."> Reload </message> + <message name="IDS_IOS_PAGE_INFO_SECURITY" desc="Title of the navigation controller to display when the page's security is presented."> + Security + </message> <message name="IDS_IOS_PAGE_INFO_SECURITY_BUTTON_ACCESSIBILITY_LABEL" desc="The accessibility text for the page security info button"> Page Security Info </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PAGE_INFO_CONNECTION_SECURITY.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PAGE_INFO_CONNECTION_SECURITY.png.sha1 deleted file mode 100644 index 4a856d5c3..0000000 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PAGE_INFO_CONNECTION_SECURITY.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -c3072dfa9774301493e9526e75624115fc3884a6 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PAGE_INFO_SECURITY.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PAGE_INFO_SECURITY.png.sha1 new file mode 100644 index 0000000..9f8a35f0 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_PAGE_INFO_SECURITY.png.sha1
@@ -0,0 +1 @@ +d599cb605f7e3ce2dc0c30bf9c97be0d21884f40 \ No newline at end of file
diff --git a/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc b/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc index e530214..2b47eba 100644 --- a/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc +++ b/ios/chrome/browser/autocomplete/model/in_memory_url_index_factory.cc
@@ -11,6 +11,7 @@ #include "components/keyed_service/core/service_access_type.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h" #include "components/omnibox/browser/in_memory_url_index.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #include "ios/chrome/browser/history/model/history_service_factory.h" #include "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
diff --git a/ios/chrome/browser/bookmarks/model/BUILD.gn b/ios/chrome/browser/bookmarks/model/BUILD.gn index b3799b57b..1f8b280 100644 --- a/ios/chrome/browser/bookmarks/model/BUILD.gn +++ b/ios/chrome/browser/bookmarks/model/BUILD.gn
@@ -20,6 +20,8 @@ "bookmark_model_factory.h", "bookmark_undo_service_factory.cc", "bookmark_undo_service_factory.h", + "legacy_bookmark_model.cc", + "legacy_bookmark_model.h", "local_or_syncable_bookmark_model_factory.cc", "local_or_syncable_bookmark_model_factory.h", "local_or_syncable_bookmark_sync_service_factory.h",
diff --git a/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.cc b/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.cc index c0a69bf..45e031f 100644 --- a/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.cc +++ b/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.cc
@@ -18,6 +18,7 @@ #include "ios/chrome/browser/bookmarks/model/bookmark_client_impl.h" #include "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #include "ios/chrome/browser/bookmarks/model/bookmark_undo_service_factory.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #include "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_sync_service_factory.h" #include "ios/chrome/browser/history/model/history_service_factory.h" @@ -35,8 +36,8 @@ ChromeBrowserState::FromBrowserState(context); // Using nullptr for `ManagedBookmarkService`, since managed bookmarks affect // only the local bookmark storage. - std::unique_ptr<bookmarks::BookmarkModel> bookmark_model( - new bookmarks::BookmarkModel(std::make_unique<BookmarkClientImpl>( + std::unique_ptr<LegacyBookmarkModel> bookmark_model( + new LegacyBookmarkModel(std::make_unique<BookmarkClientImpl>( browser_state, /*managed_bookmark_service=*/nullptr, ios::AccountBookmarkSyncServiceFactory::GetForBrowserState( browser_state), @@ -52,9 +53,9 @@ } // namespace // static -bookmarks::BookmarkModel* AccountBookmarkModelFactory::GetForBrowserState( +LegacyBookmarkModel* AccountBookmarkModelFactory::GetForBrowserState( ChromeBrowserState* browser_state) { - return static_cast<bookmarks::BookmarkModel*>( + return static_cast<LegacyBookmarkModel*>( GetInstance()->GetServiceForBrowserState(browser_state, true)); }
diff --git a/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h b/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h index 80af7fe98..bb4f2f38 100644 --- a/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h +++ b/ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h
@@ -11,16 +11,14 @@ #include "components/keyed_service/ios/browser_state_keyed_service_factory.h" class ChromeBrowserState; - -namespace bookmarks { -class BookmarkModel; -} +class LegacyBookmarkModel; namespace ios { + // Owns BookmarkModels associated with the primary account. class AccountBookmarkModelFactory : public BrowserStateKeyedServiceFactory { public: - static bookmarks::BookmarkModel* GetForBrowserState( + static LegacyBookmarkModel* GetForBrowserState( ChromeBrowserState* browser_state); static AccountBookmarkModelFactory* GetInstance(); // Returns the default factory, useful in tests where it's null by default.
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h b/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h index bd35b4c..409ac27 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h +++ b/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h
@@ -16,10 +16,10 @@ class Browser; class GURL; +class LegacyBookmarkModel; class TestChromeBrowserState; namespace bookmarks { -class BookmarkModel; class BookmarkNode; class ManagedBookmarkService; } // namespace bookmarks @@ -44,7 +44,7 @@ const std::u16string& title); void ChangeTitle(const std::u16string& title, const bookmarks::BookmarkNode* node); - bookmarks::BookmarkModel* GetBookmarkModelForNode( + LegacyBookmarkModel* GetBookmarkModelForNode( const bookmarks::BookmarkNode* node); const bool wait_for_initialization_; @@ -54,9 +54,9 @@ std::unique_ptr<Browser> browser_; std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; // Bookmark model for the LocalOrSyncable storage. - raw_ptr<bookmarks::BookmarkModel> local_or_syncable_bookmark_model_; + raw_ptr<LegacyBookmarkModel> local_or_syncable_bookmark_model_; // Bookmark model for the account storage. - raw_ptr<bookmarks::BookmarkModel> account_bookmark_model_; + raw_ptr<LegacyBookmarkModel> account_bookmark_model_; raw_ptr<bookmarks::ManagedBookmarkService> managed_bookmark_service_; };
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.mm b/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.mm index a35c31f..c0536226 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.mm +++ b/ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.mm
@@ -12,6 +12,7 @@ #import "components/bookmarks/test/bookmark_test_helpers.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h" #import "ios/chrome/browser/shared/model/browser/test/test_browser.h" @@ -78,24 +79,24 @@ const BookmarkNode* parent, const std::u16string& title, const GURL& url) { - bookmarks::BookmarkModel* model = GetBookmarkModelForNode(parent); + LegacyBookmarkModel* model = GetBookmarkModelForNode(parent); return model->AddURL(parent, parent->children().size(), title, url); } const BookmarkNode* BookmarkIOSUnitTestSupport::AddFolder( const BookmarkNode* parent, const std::u16string& title) { - bookmarks::BookmarkModel* model = GetBookmarkModelForNode(parent); + LegacyBookmarkModel* model = GetBookmarkModelForNode(parent); return model->AddFolder(parent, parent->children().size(), title); } void BookmarkIOSUnitTestSupport::ChangeTitle(const std::u16string& title, const BookmarkNode* node) { - bookmarks::BookmarkModel* model = GetBookmarkModelForNode(node); + LegacyBookmarkModel* model = GetBookmarkModelForNode(node); model->SetTitle(node, title, bookmarks::metrics::BookmarkEditSource::kUser); } -bookmarks::BookmarkModel* BookmarkIOSUnitTestSupport::GetBookmarkModelForNode( +LegacyBookmarkModel* BookmarkIOSUnitTestSupport::GetBookmarkModelForNode( const BookmarkNode* node) { if (node->HasAncestor(local_or_syncable_bookmark_model_->root_node())) { return local_or_syncable_bookmark_model_;
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h b/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h index c4e1d9e4..625c8723 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h +++ b/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h
@@ -8,52 +8,53 @@ #import <Foundation/Foundation.h> #include "base/scoped_observation.h" -#include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_model_observer.h" +class LegacyBookmarkModel; + // The ObjC translations of the C++ observer callbacks are defined here. @protocol BookmarkModelBridgeObserver <NSObject> // The bookmark model has loaded. -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model; +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model; // The node has changed, but not its children. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode; // The node has not changed, but the ordering and existence of its children have // changed. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode; // The node has moved to a new parent folder. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent; // `node` was deleted from `folder`. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder; // All non-permanent nodes have been removed in model. -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model; +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model; @optional // Called before removing a bookmark node. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model willDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder; // Called after adding a bookmark node. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didAddNode:(const bookmarks::BookmarkNode*)node toFolder:(const bookmarks::BookmarkNode*)folder; // Called before removing all non-permanent nodes. -- (void)bookmarkModelWillRemoveAllNodes:(const bookmarks::BookmarkModel*)model; +- (void)bookmarkModelWillRemoveAllNodes:(const LegacyBookmarkModel*)model; // The node favicon changed. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeFaviconForNode:(const bookmarks::BookmarkNode*)bookmarkNode; // Called before changing a bookmark node. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model willChangeBookmarkNode:(const bookmarks::BookmarkNode*)bookmarkNode; // Called when the model is being deleted. -- (void)bookmarkModelBeingDeleted:(bookmarks::BookmarkModel*)model; +- (void)bookmarkModelBeingDeleted:(LegacyBookmarkModel*)model; @end // A bridge that translates BookmarkModelObserver C++ callbacks into ObjC @@ -61,7 +62,7 @@ class BookmarkModelBridge : public bookmarks::BookmarkModelObserver { public: explicit BookmarkModelBridge(id<BookmarkModelBridgeObserver> observer, - bookmarks::BookmarkModel* model); + LegacyBookmarkModel* model); ~BookmarkModelBridge() override; private: @@ -93,8 +94,7 @@ __weak id<BookmarkModelBridgeObserver> observer_; - base::ScopedObservation<bookmarks::BookmarkModel, - bookmarks::BookmarkModelObserver> + base::ScopedObservation<LegacyBookmarkModel, bookmarks::BookmarkModelObserver> model_observation_{this}; };
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.mm b/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.mm index 4f22c59..9ac2852a 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.mm +++ b/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.mm
@@ -8,10 +8,12 @@ #import "base/check.h" #import "base/notreached.h" +#import "components/bookmarks/browser/bookmark_node.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" BookmarkModelBridge::BookmarkModelBridge( id<BookmarkModelBridgeObserver> observer, - bookmarks::BookmarkModel* model) + LegacyBookmarkModel* model) : observer_(observer) { DCHECK(observer_); DCHECK(model); @@ -21,12 +23,12 @@ BookmarkModelBridge::~BookmarkModelBridge() {} void BookmarkModelBridge::BookmarkModelLoaded(bool ids_reassigned) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); [observer_ bookmarkModelLoaded:model]; } void BookmarkModelBridge::BookmarkModelBeingDeleted() { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); model_observation_.Reset(); SEL selector = @selector(bookmarkModelBeingDeleted:); @@ -40,7 +42,7 @@ size_t old_index, const bookmarks::BookmarkNode* new_parent, size_t new_index) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); const bookmarks::BookmarkNode* node = new_parent->children()[new_index].get(); [observer_ bookmarkModel:model didMoveNode:node @@ -52,7 +54,7 @@ const bookmarks::BookmarkNode* parent, size_t index, bool added_by_user) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); [observer_ bookmarkModel:model didChangeChildrenForNode:parent]; SEL selector = @selector(bookmarkModel:didAddNode:toFolder:); if ([observer_ respondsToSelector:selector]) { @@ -65,7 +67,7 @@ const bookmarks::BookmarkNode* parent, size_t old_index, const bookmarks::BookmarkNode* node) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); SEL selector = @selector(bookmarkModel:willDeleteNode:fromFolder:); if ([observer_ respondsToSelector:selector]) { [observer_ bookmarkModel:model willDeleteNode:node fromFolder:parent]; @@ -77,7 +79,7 @@ size_t old_index, const bookmarks::BookmarkNode* node, const std::set<GURL>& removed_urls) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); // Calling -bookmarkModel:didDeleteNode:fromFolder: may cause the current // bridge object to be destroyed, so code must not access `this` after (even // implictly), so copy `observer_` to a local variable. Use `__weak` for the @@ -91,7 +93,7 @@ void BookmarkModelBridge::OnWillChangeBookmarkNode( const bookmarks::BookmarkNode* node) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); SEL selector = @selector(bookmarkModel:willChangeBookmarkNode:); if ([observer_ respondsToSelector:selector]) { [observer_ bookmarkModel:model willChangeBookmarkNode:node]; @@ -100,13 +102,13 @@ void BookmarkModelBridge::BookmarkNodeChanged( const bookmarks::BookmarkNode* node) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); [observer_ bookmarkModel:model didChangeNode:node]; } void BookmarkModelBridge::BookmarkNodeFaviconChanged( const bookmarks::BookmarkNode* node) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); SEL selector = @selector(bookmarkModel:didChangeFaviconForNode:); if ([observer_ respondsToSelector:selector]) { [observer_ bookmarkModel:model didChangeFaviconForNode:node]; @@ -115,12 +117,12 @@ void BookmarkModelBridge::BookmarkNodeChildrenReordered( const bookmarks::BookmarkNode* node) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); [observer_ bookmarkModel:model didChangeChildrenForNode:node]; } void BookmarkModelBridge::OnWillRemoveAllUserBookmarks() { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); SEL selector = @selector(bookmarkModelWillRemoveAllNodes:); if ([observer_ respondsToSelector:selector]) { [observer_ bookmarkModelWillRemoveAllNodes:model]; @@ -129,6 +131,6 @@ void BookmarkModelBridge::BookmarkAllUserNodesRemoved( const std::set<GURL>& removed_urls) { - bookmarks::BookmarkModel* model = model_observation_.GetSource(); + LegacyBookmarkModel* model = model_observation_.GetSource(); [observer_ bookmarkModelRemovedAllNodes:model]; }
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer_unittest.mm b/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer_unittest.mm index 7364af56..7a8e63b 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer_unittest.mm +++ b/ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer_unittest.mm
@@ -6,15 +6,15 @@ #import <memory> -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_metrics.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" @class TestBookmarkModelBridgeObserver; @interface TestBookmarkModelBridgeOwner : NSObject -- (instancetype)initWithModel:(bookmarks::BookmarkModel*)model +- (instancetype)initWithModel:(LegacyBookmarkModel*)model observer:(TestBookmarkModelBridgeObserver*)observer NS_DESIGNATED_INITIALIZER; @@ -40,7 +40,7 @@ bool _bookmarkNodeDeletedCalled; } -- (instancetype)initWithModel:(bookmarks::BookmarkModel*)model +- (instancetype)initWithModel:(LegacyBookmarkModel*)model observer:(TestBookmarkModelBridgeObserver*)observer { if ((self = [super init])) { DCHECK(model); @@ -72,27 +72,27 @@ #pragma mark - BookmarkModelBridgeObserver -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { } -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { } -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { [_owner bookmarkNodeDeleted];
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_model_factory.cc b/ios/chrome/browser/bookmarks/model/bookmark_model_factory.cc index 2cb9ba71..1552e72 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_model_factory.cc +++ b/ios/chrome/browser/bookmarks/model/bookmark_model_factory.cc
@@ -14,6 +14,7 @@ #include "components/bookmarks/browser/titled_url_match.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h" #include "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #include "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h" #include "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h"
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.cc b/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.cc index 65d0426..4aeb0e3 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.cc +++ b/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.cc
@@ -11,6 +11,7 @@ #include "components/bookmarks/browser/bookmark_model.h" #include "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" #include "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #include "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" @@ -56,12 +57,12 @@ } // Wait for BookmarkModels to finish loading before deleting entries. - bookmarks::BookmarkModel* local_or_syncable_bookmark_model = + LegacyBookmarkModel* local_or_syncable_bookmark_model = ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( browser_state_); bookmark_model_observations_.AddObservation(local_or_syncable_bookmark_model); - bookmarks::BookmarkModel* account_bookmark_model = + LegacyBookmarkModel* account_bookmark_model = ios::AccountBookmarkModelFactory::GetForBrowserState(browser_state_); if (account_bookmark_model) { bookmark_model_observations_.AddObservation(account_bookmark_model);
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.h b/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.h index c5c44389..0366d90 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.h +++ b/ios/chrome/browser/bookmarks/model/bookmark_remover_helper.h
@@ -12,10 +12,7 @@ #include "components/bookmarks/browser/base_bookmark_model_observer.h" class ChromeBrowserState; - -namespace bookmarks { -class BookmarkModel; -} // namespace bookmarks +class LegacyBookmarkModel; // Helper class to asynchronously remove bookmarks. class BookmarkRemoverHelper : public bookmarks::BaseBookmarkModelObserver { @@ -48,7 +45,7 @@ Callback completion_; raw_ptr<ChromeBrowserState> browser_state_ = nullptr; - base::ScopedMultiSourceObservation<bookmarks::BookmarkModel, + base::ScopedMultiSourceObservation<LegacyBookmarkModel, bookmarks::BookmarkModelObserver> bookmark_model_observations_{this};
diff --git a/ios/chrome/browser/bookmarks/model/bookmark_remover_helper_unittest.cc b/ios/chrome/browser/bookmarks/model/bookmark_remover_helper_unittest.cc index 6f9aa39..6893318 100644 --- a/ios/chrome/browser/bookmarks/model/bookmark_remover_helper_unittest.cc +++ b/ios/chrome/browser/bookmarks/model/bookmark_remover_helper_unittest.cc
@@ -7,6 +7,7 @@ #include "base/test/test_future.h" #include "components/bookmarks/test/bookmark_test_helpers.h" #include "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" class BookmarkRemoverHelperUnitTest : public BookmarkIOSUnitTestSupport {
diff --git a/ios/chrome/browser/bookmarks/model/bookmarks_utils.cc b/ios/chrome/browser/bookmarks/model/bookmarks_utils.cc index 2244a43..e304835 100644 --- a/ios/chrome/browser/bookmarks/model/bookmarks_utils.cc +++ b/ios/chrome/browser/bookmarks/model/bookmarks_utils.cc
@@ -7,24 +7,23 @@ #include "base/check.h" #include "base/containers/contains.h" #include "base/metrics/histogram_macros.h" -#include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_utils.h" #include "components/prefs/pref_service.h" #include "ios/chrome/browser/bookmarks/model/bookmark_model_factory.h" #include "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/shared/model/prefs/pref_names.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; namespace { // Returns the bookmark model designed by `type`. -bookmarks::BookmarkModel* GetBookmarkModelForType( +LegacyBookmarkModel* GetBookmarkModelForType( BookmarkModelType type, - bookmarks::BookmarkModel* local_or_syncable_bookmark_model, - bookmarks::BookmarkModel* account_bookmark_model) { + LegacyBookmarkModel* local_or_syncable_bookmark_model, + LegacyBookmarkModel* account_bookmark_model) { switch (type) { case BookmarkModelType::kAccount: return account_bookmark_model; @@ -59,7 +58,8 @@ return true; } -std::vector<const BookmarkNode*> PrimaryPermanentNodes(BookmarkModel* model) { +std::vector<const BookmarkNode*> PrimaryPermanentNodes( + LegacyBookmarkModel* model) { DCHECK(model->loaded()); std::vector<const BookmarkNode*> nodes; nodes.push_back(model->mobile_node()); @@ -68,7 +68,8 @@ return nodes; } -bool IsPrimaryPermanentNode(const BookmarkNode* node, BookmarkModel* model) { +bool IsPrimaryPermanentNode(const BookmarkNode* node, + LegacyBookmarkModel* model) { std::vector<const BookmarkNode*> primary_nodes(PrimaryPermanentNodes(model)); return base::Contains(primary_nodes, node); } @@ -98,15 +99,15 @@ const bookmarks::BookmarkNode* GetDefaultBookmarkFolder( PrefService* prefs, bool is_account_bookmark_model_available, - bookmarks::BookmarkModel* local_or_syncable_bookmark_model, - bookmarks::BookmarkModel* account_bookmark_model) { + LegacyBookmarkModel* local_or_syncable_bookmark_model, + LegacyBookmarkModel* account_bookmark_model) { int64_t node_id = prefs->GetInt64(prefs::kIosBookmarkLastUsedFolderReceivingBookmarks); if (node_id != kLastUsedBookmarkFolderNone) { BookmarkModelType type = static_cast<BookmarkModelType>(prefs->GetInteger( prefs::kIosBookmarkLastUsedStorageReceivingBookmarks)); - bookmarks::BookmarkModel* bookmark_model = GetBookmarkModelForType( + LegacyBookmarkModel* bookmark_model = GetBookmarkModelForType( type, local_or_syncable_bookmark_model, account_bookmark_model); const BookmarkNode* result = bookmarks::GetBookmarkNodeByID(bookmark_model, node_id); @@ -120,7 +121,7 @@ BookmarkModelType type = (is_account_bookmark_model_available) ? BookmarkModelType::kAccount : BookmarkModelType::kLocalOrSyncable; - bookmarks::BookmarkModel* bookmark_model = GetBookmarkModelForType( + LegacyBookmarkModel* bookmark_model = GetBookmarkModelForType( type, local_or_syncable_bookmark_model, account_bookmark_model); return bookmark_model->mobile_node(); }
diff --git a/ios/chrome/browser/bookmarks/model/bookmarks_utils.h b/ios/chrome/browser/bookmarks/model/bookmarks_utils.h index e5b5b3bd..3a7cc6c 100644 --- a/ios/chrome/browser/bookmarks/model/bookmarks_utils.h +++ b/ios/chrome/browser/bookmarks/model/bookmarks_utils.h
@@ -10,10 +10,10 @@ enum class BookmarkModelType; class ChromeBrowserState; +class LegacyBookmarkModel; class PrefService; namespace bookmarks { -class BookmarkModel; class BookmarkNode; } // namespace bookmarks @@ -37,12 +37,12 @@ // and whose folder children should be shown in the bookmark menu. // `model` must be loaded. std::vector<const bookmarks::BookmarkNode*> PrimaryPermanentNodes( - bookmarks::BookmarkModel* model); + LegacyBookmarkModel* model); // Returns whether `node` is a primary permanent node in the sense of // `PrimaryPermanentNodes`. bool IsPrimaryPermanentNode(const bookmarks::BookmarkNode* node, - bookmarks::BookmarkModel* model); + LegacyBookmarkModel* model); // Whether a bookmark was manually moved by the user to a different folder since // last signin/signout. @@ -65,7 +65,7 @@ const bookmarks::BookmarkNode* GetDefaultBookmarkFolder( PrefService* prefs, bool is_account_bookmark_model_available, - bookmarks::BookmarkModel* profile_bookmark_model, - bookmarks::BookmarkModel* account_bookmark_model); + LegacyBookmarkModel* profile_bookmark_model, + LegacyBookmarkModel* account_bookmark_model); #endif // IOS_CHROME_BROWSER_BOOKMARKS_MODEL_BOOKMARKS_UTILS_H_
diff --git a/ios/chrome/browser/bookmarks/model/bookmarks_utils_unittest.mm b/ios/chrome/browser/bookmarks/model/bookmarks_utils_unittest.mm index a17219e..0ef49c9a 100644 --- a/ios/chrome/browser/bookmarks/model/bookmarks_utils_unittest.mm +++ b/ios/chrome/browser/bookmarks/model/bookmarks_utils_unittest.mm
@@ -8,6 +8,7 @@ #import "components/bookmarks/browser/bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
diff --git a/ios/chrome/browser/bookmarks/model/legacy_bookmark_model.cc b/ios/chrome/browser/bookmarks/model/legacy_bookmark_model.cc new file mode 100644 index 0000000..901451d7 --- /dev/null +++ b/ios/chrome/browser/bookmarks/model/legacy_bookmark_model.cc
@@ -0,0 +1,17 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" + +#include <utility> + +LegacyBookmarkModel::LegacyBookmarkModel( + std::unique_ptr<bookmarks::BookmarkClient> client) + : BookmarkModel(std::move(client)) {} + +LegacyBookmarkModel::~LegacyBookmarkModel() = default; + +base::WeakPtr<LegacyBookmarkModel> LegacyBookmarkModel::AsWeakPtr() { + return legacy_weak_factory_.GetWeakPtr(); +}
diff --git a/ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h b/ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h new file mode 100644 index 0000000..bb12a6b --- /dev/null +++ b/ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h
@@ -0,0 +1,24 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_BOOKMARKS_MODEL_LEGACY_BOOKMARK_MODEL_H_ +#define IOS_CHROME_BROWSER_BOOKMARKS_MODEL_LEGACY_BOOKMARK_MODEL_H_ + +#include "base/memory/weak_ptr.h" +#include "components/bookmarks/browser/bookmark_model.h" + +// TODO(crbug.com/326185948): Replace this with a minimalistic fork of +// BookmarkModel. +class LegacyBookmarkModel : public bookmarks::BookmarkModel { + public: + LegacyBookmarkModel(std::unique_ptr<bookmarks::BookmarkClient> client); + ~LegacyBookmarkModel() override; + + base::WeakPtr<LegacyBookmarkModel> AsWeakPtr(); + + private: + base::WeakPtrFactory<LegacyBookmarkModel> legacy_weak_factory_{this}; +}; + +#endif // IOS_CHROME_BROWSER_BOOKMARKS_MODEL_LEGACY_BOOKMARK_MODEL_H_
diff --git a/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.cc b/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.cc index 75a596c..7b29357 100644 --- a/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.cc +++ b/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.cc
@@ -17,6 +17,7 @@ #include "ios/chrome/browser/bookmarks/model/bookmark_client_impl.h" #include "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #include "ios/chrome/browser/bookmarks/model/bookmark_undo_service_factory.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_sync_service_factory.h" #import "ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h" #include "ios/chrome/browser/history/model/history_service_factory.h" @@ -32,8 +33,8 @@ std::unique_ptr<KeyedService> BuildBookmarkModel(web::BrowserState* context) { ChromeBrowserState* browser_state = ChromeBrowserState::FromBrowserState(context); - std::unique_ptr<bookmarks::BookmarkModel> bookmark_model = std::make_unique< - bookmarks::BookmarkModel>(std::make_unique<BookmarkClientImpl>( + std::unique_ptr<LegacyBookmarkModel> bookmark_model = std::make_unique< + LegacyBookmarkModel>(std::make_unique<BookmarkClientImpl>( browser_state, ManagedBookmarkServiceFactory::GetForBrowserState(browser_state), ios::LocalOrSyncableBookmarkSyncServiceFactory::GetForBrowserState( @@ -49,18 +50,17 @@ } // namespace // static -bookmarks::BookmarkModel* -LocalOrSyncableBookmarkModelFactory::GetForBrowserState( +LegacyBookmarkModel* LocalOrSyncableBookmarkModelFactory::GetForBrowserState( ChromeBrowserState* browser_state) { - return static_cast<bookmarks::BookmarkModel*>( + return static_cast<LegacyBookmarkModel*>( GetInstance()->GetServiceForBrowserState(browser_state, true)); } // static -bookmarks::BookmarkModel* +LegacyBookmarkModel* LocalOrSyncableBookmarkModelFactory::GetForBrowserStateIfExists( ChromeBrowserState* browser_state) { - return static_cast<bookmarks::BookmarkModel*>( + return static_cast<LegacyBookmarkModel*>( GetInstance()->GetServiceForBrowserState(browser_state, false)); }
diff --git a/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h b/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h index 6c5d8bb..de27763 100644 --- a/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h +++ b/ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h
@@ -11,19 +11,17 @@ #include "components/keyed_service/ios/browser_state_keyed_service_factory.h" class ChromeBrowserState; - -namespace bookmarks { -class BookmarkModel; -} +class LegacyBookmarkModel; namespace ios { + // Owns local/syncable BookmarkModels. class LocalOrSyncableBookmarkModelFactory : public BrowserStateKeyedServiceFactory { public: - static bookmarks::BookmarkModel* GetForBrowserState( + static LegacyBookmarkModel* GetForBrowserState( ChromeBrowserState* browser_state); - static bookmarks::BookmarkModel* GetForBrowserStateIfExists( + static LegacyBookmarkModel* GetForBrowserStateIfExists( ChromeBrowserState* browser_state); static LocalOrSyncableBookmarkModelFactory* GetInstance();
diff --git a/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client.mm b/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client.mm index f5fc088..46633f4 100644 --- a/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client.mm +++ b/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client.mm
@@ -15,6 +15,7 @@ #import "components/commerce/core/proto/price_tracking.pb.h" #import "components/optimization_guide/core/hints_manager.h" #import "components/optimization_guide/proto/push_notification.pb.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/optimization_guide/model/optimization_guide_service.h" #import "ios/chrome/browser/optimization_guide/model/optimization_guide_service_factory.h"
diff --git a/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client_unittest.mm b/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client_unittest.mm index edb1d87..79eac10 100644 --- a/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client_unittest.mm +++ b/ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client_unittest.mm
@@ -23,6 +23,7 @@ #import "components/optimization_guide/proto/push_notification.pb.h" #import "components/session_proto_db/session_proto_db.h" #import "ios/chrome/app/application_delegate/app_state.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/commerce/model/session_proto_db_factory.h" #import "ios/chrome/browser/commerce/model/shopping_service_factory.h"
diff --git a/ios/chrome/browser/commerce/model/shopping_service_factory.mm b/ios/chrome/browser/commerce/model/shopping_service_factory.mm index cb98747..f962166 100644 --- a/ios/chrome/browser/commerce/model/shopping_service_factory.mm +++ b/ios/chrome/browser/commerce/model/shopping_service_factory.mm
@@ -14,6 +14,7 @@ #import "components/prefs/pref_service.h" #import "components/variations/service/variations_service_utils.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/commerce/model/session_proto_db_factory.h" #import "ios/chrome/browser/history/model/history_service_factory.h"
diff --git a/ios/chrome/browser/external_files/model/external_file_remover_impl.mm b/ios/chrome/browser/external_files/model/external_file_remover_impl.mm index 61a4b88..10087bd 100644 --- a/ios/chrome/browser/external_files/model/external_file_remover_impl.mm +++ b/ios/chrome/browser/external_files/model/external_file_remover_impl.mm
@@ -17,6 +17,7 @@ #import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/url_and_title.h" #import "components/sessions/core/tab_restore_service.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #import "ios/chrome/browser/shared/model/browser/browser.h"
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 794de7d6..f86d169 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1653,6 +1653,11 @@ flags_ui::kOsIos, FEATURE_VALUE_TYPE( autofill::features::kAutofillEnableCardBenefitsForCapitalOne)}, + {"autofill-enable-card-benefits-sync", + flag_descriptions::kAutofillEnableCardBenefitsSyncName, + flag_descriptions::kAutofillEnableCardBenefitsSyncDescription, + flags_ui::kOsIos, + FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableCardBenefitsSync)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index e4dde0f..a376c8b1 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -51,6 +51,12 @@ "When enabled, card benefits offered by Capital One will be shown in " "Autofill suggestions."; +const char kAutofillEnableCardBenefitsSyncName[] = + "Enable syncing card benefits from the server"; +const char kAutofillEnableCardBenefitsSyncDescription[] = + "When enabled, card benefits offered by issuers will be synced from " + "the Payments server."; + const char kAutofillEnableMerchantDomainInUnmaskCardRequestName[] = "Enable sending merchant domain in server card unmask requests"; const char kAutofillEnableMerchantDomainInUnmaskCardRequestDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 5c38c636..8dbd1e5 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -47,6 +47,11 @@ extern const char kAutofillEnableCardBenefitsForCapitalOneName[]; extern const char kAutofillEnableCardBenefitsForCapitalOneDescription[]; +// Title and description for the flag to enable syncing card benefits from +// the Payments server for Payments Autofill. +extern const char kAutofillEnableCardBenefitsSyncName[]; +extern const char kAutofillEnableCardBenefitsSyncDescription[]; + // Title and description for the flag to send merchant_domain as a top-level // parameter in card unmask requests. extern const char kAutofillEnableMerchantDomainInUnmaskCardRequestName[];
diff --git a/ios/chrome/browser/history/model/history_service_factory.cc b/ios/chrome/browser/history/model/history_service_factory.cc index 4582996..4260d67a 100644 --- a/ios/chrome/browser/history/model/history_service_factory.cc +++ b/ios/chrome/browser/history/model/history_service_factory.cc
@@ -16,6 +16,7 @@ #include "components/keyed_service/ios/browser_state_dependency_manager.h" #include "components/prefs/pref_service.h" #include "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#include "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #include "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #include "ios/chrome/browser/history/model/history_client_impl.h" #include "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h"
diff --git a/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm b/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm index 023f8ae96..90ab2ec 100644 --- a/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm +++ b/ios/chrome/browser/power_bookmarks/model/power_bookmark_service_factory.mm
@@ -7,6 +7,7 @@ #import "base/task/thread_pool.h" #import "components/keyed_service/ios/browser_state_dependency_manager.h" #import "components/power_bookmarks/core/power_bookmark_service.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/shared/model/browser_state/browser_state_otr_helper.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h"
diff --git a/ios/chrome/browser/share_extension/model/share_extension_service_factory.mm b/ios/chrome/browser/share_extension/model/share_extension_service_factory.mm index 375aa6b..7b60aa7 100644 --- a/ios/chrome/browser/share_extension/model/share_extension_service_factory.mm +++ b/ios/chrome/browser/share_extension/model/share_extension_service_factory.mm
@@ -6,6 +6,7 @@ #import "base/no_destructor.h" #import "components/keyed_service/ios/browser_state_dependency_manager.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/reading_list/model/reading_list_model_factory.h" #import "ios/chrome/browser/share_extension/model/share_extension_service.h"
diff --git a/ios/chrome/browser/signin/model/fake_system_identity_manager.mm b/ios/chrome/browser/signin/model/fake_system_identity_manager.mm index c676029..fa09e95 100644 --- a/ios/chrome/browser/signin/model/fake_system_identity_manager.mm +++ b/ios/chrome/browser/signin/model/fake_system_identity_manager.mm
@@ -72,6 +72,14 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); [storage_ addIdentity:identity]; FireIdentityListChanged(/*notify_user*/ false); + + // Set up capabilities to remove the delay while displaying the history sync + // opt-in screen for testing. + // TODO(b/327221052): verify if this should be replaced by a handler for + // default capabilities. + AccountCapabilitiesTestMutator* mutator = GetCapabilitiesMutator(identity); + mutator->set_can_show_history_sync_opt_ins_without_minor_mode_restrictions( + true); } void FakeSystemIdentityManager::AddIdentities(NSArray<NSString*>* names) {
diff --git a/ios/chrome/browser/ui/authentication/cells/BUILD.gn b/ios/chrome/browser/ui/authentication/cells/BUILD.gn index 01636a6..7982d5b 100644 --- a/ios/chrome/browser/ui/authentication/cells/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/cells/BUILD.gn
@@ -6,6 +6,8 @@ source_set("cells") { sources = [ + "central_account_view.h", + "central_account_view.mm", "signin_promo_view.h", "signin_promo_view.mm", "signin_promo_view_configurator.h", @@ -14,8 +16,6 @@ "signin_promo_view_delegate.h", "table_view_account_item.h", "table_view_account_item.mm", - "table_view_central_account_item.h", - "table_view_central_account_item.mm", "table_view_identity_cell.h", "table_view_identity_cell.mm", "table_view_identity_item.h", @@ -54,9 +54,9 @@ source_set("unit_tests") { testonly = true sources = [ + "central_account_view_unittest.mm", "signin_promo_view_unittest.mm", "table_view_account_item_unittest.mm", - "table_view_central_account_item_unittest.mm", ] deps = [ ":cells",
diff --git a/ios/chrome/browser/ui/authentication/cells/central_account_view.h b/ios/chrome/browser/ui/authentication/cells/central_account_view.h new file mode 100644 index 0000000..cfea5c0 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/cells/central_account_view.h
@@ -0,0 +1,34 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_CENTRAL_ACCOUNT_VIEW_H_ +#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_CENTRAL_ACCOUNT_VIEW_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_item.h" + +// View for the signed-in account, used in account settings page. Contains the +// following subviews: +// 1. Rounded avatarImage used for the account user picture. The value cannot be +// nil. +// 2. Name displayed in main label. The value can be nil. +// In case the value is nil, the main label will show the email and there will +// be no secondary label. +// 3. Email subtitle displayed in secondary label. The value cannot be nil. +@interface CentralAccountView : UIView + +- (instancetype)initWithFrame:(CGRect)frame + avatarImage:(UIImage*)avatarImage + name:(NSString*)name + email:(NSString*)email; + +// Returns the view parameters. +- (UIImage*)avatarImage; +- (NSString*)name; +- (NSString*)email; + +@end + +#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_CENTRAL_ACCOUNT_VIEW_H_
diff --git a/ios/chrome/browser/ui/authentication/cells/central_account_view.mm b/ios/chrome/browser/ui/authentication/cells/central_account_view.mm new file mode 100644 index 0000000..e4e7ed16 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/cells/central_account_view.mm
@@ -0,0 +1,128 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/authentication/cells/central_account_view.h" + +#import "base/apple/foundation_util.h" +#import "base/check_op.h" +#import "ios/chrome/browser/shared/ui/symbols/symbols.h" +#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h" +#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" +#import "ios/chrome/browser/signin/model/constants.h" +#import "ios/chrome/browser/signin/model/signin_util.h" +#import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h" +#import "ios/chrome/common/ui/colors/semantic_color_names.h" +#import "ios/chrome/common/ui/table_view/table_view_cells_constants.h" +#import "ios/chrome/grit/ios_strings.h" +#import "ui/base/l10n/l10n_util_mac.h" + +@implementation CentralAccountView { + // Rounded avatarImage used for the account user picture. Note: the image + // doesn't need to be rounded as the cell configs create the image rounded + // corners. + UIImage* _avatarImage; + // Name displayed in main label. + NSString* _name; + // Email subtitle displayed in secondary label. + NSString* _email; +} + +- (instancetype)initWithFrame:(CGRect)frame + avatarImage:(UIImage*)avatarImage + name:(NSString*)name + email:(NSString*)email { + self = [super initWithFrame:frame]; + if (self) { + CHECK(avatarImage); + CHECK(email); + _avatarImage = avatarImage; + _name = name ? name : email; + _email = name ? email : nil; + + UIImageView* imageView = [[UIImageView alloc] initWithImage:_avatarImage]; + // Creates the image rounded corners. + imageView.layer.cornerRadius = + GetSizeForIdentityAvatarSize(IdentityAvatarSize::Large).width / 2.0f; + imageView.clipsToBounds = YES; + imageView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:imageView]; + + UILabel* titleLabel = [[UILabel alloc] init]; + titleLabel.text = _name; + titleLabel.textAlignment = NSTextAlignmentCenter; + titleLabel.numberOfLines = 1; + titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; + titleLabel.adjustsFontForContentSizeCategory = YES; + titleLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + titleLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; + titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:titleLabel]; + + UILabel* subtitleLabel = [[UILabel alloc] init]; + subtitleLabel.text = _email; + subtitleLabel.textAlignment = NSTextAlignmentCenter; + subtitleLabel.numberOfLines = 1; + subtitleLabel.adjustsFontForContentSizeCategory = YES; + subtitleLabel.lineBreakMode = NSLineBreakByTruncatingTail; + subtitleLabel.textColor = [UIColor colorNamed:kTextSecondaryColor]; + subtitleLabel.font = + [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:subtitleLabel]; + + [NSLayoutConstraint activateConstraints:@[ + [imageView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor], + [imageView.topAnchor + constraintEqualToAnchor:self.topAnchor + constant:kTableViewLargeVerticalSpacing], + [imageView.widthAnchor + constraintEqualToConstant:GetSizeForIdentityAvatarSize( + IdentityAvatarSize::Large) + .width], + [imageView.heightAnchor constraintEqualToAnchor:imageView.widthAnchor], + + [titleLabel.topAnchor constraintEqualToAnchor:imageView.bottomAnchor + constant:kTableViewVerticalSpacing], + [titleLabel.leadingAnchor + constraintEqualToAnchor:self.leadingAnchor + constant:kTableViewHorizontalSpacing], + [titleLabel.trailingAnchor + constraintEqualToAnchor:self.trailingAnchor + constant:-kTableViewHorizontalSpacing], + + [subtitleLabel.topAnchor constraintEqualToAnchor:titleLabel.bottomAnchor], + [subtitleLabel.leadingAnchor + constraintEqualToAnchor:titleLabel.leadingAnchor], + [subtitleLabel.trailingAnchor + constraintEqualToAnchor:titleLabel.trailingAnchor], + [self.bottomAnchor + constraintEqualToAnchor:subtitleLabel.bottomAnchor + constant:2 * kTableViewLargeVerticalSpacing], + ]]; + + CGSize size = + [self systemLayoutSizeFittingSize:self.frame.size + withHorizontalFittingPriority:UILayoutPriorityRequired + verticalFittingPriority:UILayoutPriorityFittingSizeLevel]; + CGRect newFrame = CGRectZero; + newFrame.size = size; + self.frame = newFrame; + } + return self; +} + +- (UIImage*)avatarImage { + return _avatarImage; +} + +- (NSString*)name { + return _name; +} + +- (NSString*)email { + return _email; +} + +@end
diff --git a/ios/chrome/browser/ui/authentication/cells/central_account_view_unittest.mm b/ios/chrome/browser/ui/authentication/cells/central_account_view_unittest.mm new file mode 100644 index 0000000..ce63acd --- /dev/null +++ b/ios/chrome/browser/ui/authentication/cells/central_account_view_unittest.mm
@@ -0,0 +1,59 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/authentication/cells/central_account_view.h" + +#import <CoreGraphics/CoreGraphics.h> +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h" +#import "ios/chrome/browser/signin/model/constants.h" +#import "ios/chrome/browser/signin/model/signin_util.h" +#import "ios/chrome/common/ui/util/image_util.h" +#import "ios/public/provider/chrome/browser/signin/signin_resources_api.h" +#import "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#import "testing/platform_test.h" + +using CentralAccountViewTest = PlatformTest; + +// Tests that the UIImageView and UILabels are set properly in the view. +TEST_F(CentralAccountViewTest, ImageViewAndTextLabels) { + UIImage* image = ios::provider::GetSigninDefaultAvatar(); + image = ResizeImage(image, + GetSizeForIdentityAvatarSize(IdentityAvatarSize::Large), + ProjectionMode::kAspectFit); + NSString* mainText = @"Main text"; + NSString* detailText = @"Detail text"; + + CentralAccountView* accountView = + [[CentralAccountView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) + avatarImage:image + name:mainText + email:detailText]; + + EXPECT_NSEQ(accountView.avatarImage, image); + EXPECT_NSEQ(accountView.name, mainText); + EXPECT_NSEQ(accountView.email, detailText); +} + +// Tests that the UIImageView and UILabels are set properly in the view if the +// account name is not provided. +TEST_F(CentralAccountViewTest, ImageViewAndTextLabelsWithoutGivenName) { + UIImage* image = ios::provider::GetSigninDefaultAvatar(); + image = ResizeImage(image, + GetSizeForIdentityAvatarSize(IdentityAvatarSize::Large), + ProjectionMode::kAspectFit); + NSString* mainText = @"Main text"; + + CentralAccountView* accountView = + [[CentralAccountView alloc] initWithFrame:CGRectMake(0, 0, 100, 100) + avatarImage:image + name:nil + email:mainText]; + + EXPECT_NSEQ(accountView.avatarImage, image); + EXPECT_NSEQ(accountView.name, mainText); + EXPECT_NSEQ(accountView.email, nil); +}
diff --git a/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.h b/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.h deleted file mode 100644 index dfc0b56..0000000 --- a/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_TABLE_VIEW_CENTRAL_ACCOUNT_ITEM_H_ -#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_TABLE_VIEW_CENTRAL_ACCOUNT_ITEM_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_item.h" - -// Item for the signed-in account, used in account settings page. -@interface TableViewCentralAccountItem : TableViewItem - -// Rounded avatarImage used for the account user picture. The value cannot be -// nil. Note: the image doesn't need to be rounded as the cell configs create -// the image rounded corners. -@property(nonatomic, strong) UIImage* avatarImage; -// Cell title displayed in main label. The value can be nil. -// In case the value is nil, the main label will show the email and there will -// be no secondary label. -@property(nonatomic, copy) NSString* name; -// Cell subtitle displayed in secondary label. The value cannot be nil. -@property(nonatomic, copy) NSString* email; - -@end - -// Cell for central account details with a leading centered avatar -// avatarImageView, followed by the account name label, and an email label. -@interface TableViewCentralAccountCell : TableViewCell - -@property(nonatomic, strong, readonly) UIImageView* avatarImageView; -@property(nonatomic, strong, readonly) UILabel* nameLabel; -@property(nonatomic, strong, readonly) UILabel* emailLabel; - -@end - -#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_TABLE_VIEW_CENTRAL_ACCOUNT_ITEM_H_
diff --git a/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.mm b/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.mm deleted file mode 100644 index 42dd0bd8..0000000 --- a/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.mm +++ /dev/null
@@ -1,169 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.h" - -#import "base/apple/foundation_util.h" -#import "base/check_op.h" -#import "ios/chrome/browser/shared/ui/symbols/symbols.h" -#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h" -#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" -#import "ios/chrome/browser/signin/model/constants.h" -#import "ios/chrome/browser/signin/model/signin_util.h" -#import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" -#import "ios/chrome/common/ui/table_view/table_view_cells_constants.h" -#import "ios/chrome/grit/ios_strings.h" -#import "ui/base/l10n/l10n_util_mac.h" - -@implementation TableViewCentralAccountItem - -- (instancetype)initWithType:(NSInteger)type { - self = [super initWithType:type]; - if (self) { - self.cellClass = [TableViewCentralAccountCell class]; - self.accessibilityTraits |= UIAccessibilityTraitButton; - } - return self; -} - -#pragma mark - TableViewItem - -- (void)configureCell:(TableViewCentralAccountCell*)cell - withStyler:(ChromeTableViewStyler*)styler { - CHECK(self.avatarImage); - CHECK(self.email); - - [super configureCell:cell withStyler:styler]; - - CGSize tableViewCentralAccountAvartarSize = - GetSizeForIdentityAvatarSize(IdentityAvatarSize::Large); - CHECK_EQ(tableViewCentralAccountAvartarSize.width, - self.avatarImage.size.width); - CHECK_EQ(tableViewCentralAccountAvartarSize.height, - self.avatarImage.size.height); - - cell.avatarImageView.image = self.avatarImage; - cell.nameLabel.text = self.name ? self.name : self.email; - cell.emailLabel.text = self.name ? self.email : nil; - cell.backgroundColor = styler.tableViewBackgroundColor; -} - -@end - -@implementation TableViewCentralAccountCell - -@synthesize avatarImageView = _avatarImageView; -@synthesize nameLabel = _textLabel; -@synthesize emailLabel = _detailTextLabel; - -- (instancetype)initWithStyle:(UITableViewCellStyle)style - reuseIdentifier:(NSString*)reuseIdentifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - self.isAccessibilityElement = YES; - [self addSubviews]; - [self setViewConstraints]; - self.userInteractionEnabled = NO; - self.contentView.alpha = 1; - } - return self; -} - -// Create and add subviews. -- (void)addSubviews { - UIView* contentView = self.contentView; - contentView.clipsToBounds = YES; - - _avatarImageView = [[UIImageView alloc] init]; - _avatarImageView.translatesAutoresizingMaskIntoConstraints = NO; - _avatarImageView.layer.masksToBounds = YES; - _avatarImageView.contentMode = UIViewContentModeScaleAspectFit; - // Creates the image rounded corners. - _avatarImageView.layer.cornerRadius = - GetSizeForIdentityAvatarSize(IdentityAvatarSize::Large).width / 2.0f; - [contentView addSubview:_avatarImageView]; - - _textLabel = [[UILabel alloc] init]; - _textLabel.translatesAutoresizingMaskIntoConstraints = NO; - _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; - _textLabel.adjustsFontForContentSizeCategory = YES; - _textLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; - [contentView addSubview:_textLabel]; - - _detailTextLabel = [[UILabel alloc] init]; - _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; - _detailTextLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; - _detailTextLabel.adjustsFontForContentSizeCategory = YES; - _detailTextLabel.textColor = [UIColor colorNamed:kTextSecondaryColor]; - [contentView addSubview:_detailTextLabel]; -} - -// Set constraints on subviews. -- (void)setViewConstraints { - UIView* contentView = self.contentView; - - [NSLayoutConstraint activateConstraints:@[ - // Fix image widths. - [_avatarImageView.widthAnchor - constraintEqualToConstant:GetSizeForIdentityAvatarSize( - IdentityAvatarSize::Large) - .width], - [_avatarImageView.heightAnchor - constraintEqualToAnchor:_avatarImageView.widthAnchor], - - // Set horizontal anchors. - [_avatarImageView.centerXAnchor - constraintEqualToAnchor:contentView.centerXAnchor], - [_textLabel.centerXAnchor - constraintEqualToAnchor:_avatarImageView.centerXAnchor], - [_detailTextLabel.centerXAnchor - constraintEqualToAnchor:_textLabel.centerXAnchor], - - // Set vertical anchors. - [_avatarImageView.topAnchor constraintEqualToAnchor:contentView.topAnchor], - [_textLabel.topAnchor - constraintGreaterThanOrEqualToAnchor:_avatarImageView.bottomAnchor - constant:kTableViewVerticalSpacing], - [_detailTextLabel.topAnchor - constraintEqualToAnchor:_textLabel.bottomAnchor], - [_detailTextLabel.bottomAnchor - constraintEqualToAnchor:contentView.bottomAnchor], - ]]; -} - -#pragma mark - UIView - -- (void)layoutSubviews { - [super layoutSubviews]; -} - -#pragma mark - UITableViewCell - -- (void)prepareForReuse { - [super prepareForReuse]; - self.avatarImageView.image = nil; - self.nameLabel.text = nil; - self.emailLabel.text = nil; -} - -#pragma mark - NSObject(Accessibility) - -- (NSString*)accessibilityLabel { - return self.nameLabel.text; -} - -- (NSString*)accessibilityValue { - return self.emailLabel.text; -} - -- (NSArray<NSString*>*)accessibilityUserInputLabels { - if (!self.nameLabel.text) { - return @[]; - } - return @[ self.nameLabel.text ]; -} - -@end
diff --git a/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item_unittest.mm b/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item_unittest.mm deleted file mode 100644 index 08b2f5f..0000000 --- a/ios/chrome/browser/ui/authentication/cells/table_view_central_account_item_unittest.mm +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.h" - -#import <CoreGraphics/CoreGraphics.h> -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h" -#import "ios/chrome/browser/signin/model/constants.h" -#import "ios/chrome/browser/signin/model/signin_util.h" -#import "ios/chrome/common/ui/util/image_util.h" -#import "ios/public/provider/chrome/browser/signin/signin_resources_api.h" -#import "testing/gtest/include/gtest/gtest.h" -#import "testing/gtest_mac.h" -#import "testing/platform_test.h" - -using CentralAccountControlTableViewItemTest = PlatformTest; - -// Tests that the UIImageView and UILabels are set properly after a call to -// `configureCell:`. -TEST_F(CentralAccountControlTableViewItemTest, ImageViewAndTextLabels) { - TableViewCentralAccountItem* item = - [[TableViewCentralAccountItem alloc] initWithType:0]; - UIImage* image = ios::provider::GetSigninDefaultAvatar(); - image = ResizeImage(image, - GetSizeForIdentityAvatarSize(IdentityAvatarSize::Large), - ProjectionMode::kAspectFit); - NSString* mainText = @"Main text"; - NSString* detailText = @"Detail text"; - - item.avatarImage = image; - item.name = mainText; - item.email = detailText; - - id cell = [[[item cellClass] alloc] init]; - ASSERT_TRUE([cell isMemberOfClass:[TableViewCentralAccountCell class]]); - - TableViewCentralAccountCell* accountCell = cell; - EXPECT_FALSE(accountCell.avatarImageView.image); - EXPECT_FALSE(accountCell.nameLabel.text); - EXPECT_FALSE(accountCell.emailLabel.text); - - [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_NSEQ(image, accountCell.avatarImageView.image); - EXPECT_NSEQ(mainText, accountCell.nameLabel.text); - EXPECT_NSEQ(detailText, accountCell.emailLabel.text); -} - -// Tests that the UIImageView and UILabels are set properly after a call to -// `configureCell:` if the name is not provided. -TEST_F(CentralAccountControlTableViewItemTest, - ImageViewAndTextLabelsWithoutGivenName) { - TableViewCentralAccountItem* item = - [[TableViewCentralAccountItem alloc] initWithType:0]; - UIImage* image = ios::provider::GetSigninDefaultAvatar(); - image = ResizeImage(image, - GetSizeForIdentityAvatarSize(IdentityAvatarSize::Large), - ProjectionMode::kAspectFit); - NSString* mainlText = @"Detail text"; - - item.avatarImage = image; - item.name = nil; - item.email = mainlText; - - id cell = [[[item cellClass] alloc] init]; - ASSERT_TRUE([cell isMemberOfClass:[TableViewCentralAccountCell class]]); - - TableViewCentralAccountCell* accountCell = cell; - EXPECT_FALSE(accountCell.avatarImageView.image); - EXPECT_FALSE(accountCell.nameLabel.text); - EXPECT_FALSE(accountCell.emailLabel.text); - - [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_NSEQ(image, accountCell.avatarImageView.image); - EXPECT_NSEQ(mainlText, accountCell.nameLabel.text); - EXPECT_NSEQ(nil, accountCell.emailLabel.text); -}
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.mm index 54f79c92..21047f9 100644 --- a/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.mm +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.mm
@@ -11,7 +11,6 @@ #import "base/functional/callback_helpers.h" #import "base/notreached.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/titled_url_match.h" #import "components/prefs/pref_service.h" #import "components/signin/public/base/signin_pref_names.h" @@ -23,6 +22,7 @@ #import "components/sync/service/sync_service.h" #import "components/sync/service/sync_user_settings.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/shared/coordinator/scene/scene_controller.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h"
diff --git a/ios/chrome/browser/ui/bookmarks/BUILD.gn b/ios/chrome/browser/ui/bookmarks/BUILD.gn index 0aa3d70..9dcefcb 100644 --- a/ios/chrome/browser/ui/bookmarks/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/BUILD.gn
@@ -100,6 +100,7 @@ "//components/sync/service", "//components/sync_preferences:test_support", "//ios/chrome/app/strings", + "//ios/chrome/browser/bookmarks/model", "//ios/chrome/browser/bookmarks/model:bookmark_model_type", "//ios/chrome/browser/bookmarks/model:test_support", "//ios/chrome/browser/shared/model/application_context",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm b/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm index 0bc95353..74d6b7d 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_earl_grey_app_interface.mm
@@ -9,7 +9,6 @@ #import "base/format_macros.h" #import "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/titled_url_match.h" #import "components/bookmarks/common/bookmark_metrics.h" #import "components/prefs/pref_service.h" @@ -17,6 +16,7 @@ #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" @@ -34,9 +34,9 @@ #pragma mark - Public Interface + (NSError*)clearBookmarks { - bookmarks::BookmarkModel* localOrSyncableBookmarkModel = + LegacyBookmarkModel* localOrSyncableBookmarkModel = [BookmarkEarlGreyAppInterface localOrSyncableBookmarkModel]; - bookmarks::BookmarkModel* accountBookmarkModel = + LegacyBookmarkModel* accountBookmarkModel = [BookmarkEarlGreyAppInterface accountBookmarkModel]; ChromeBrowserState* browserState = chrome_test_util::GetOriginalBrowserState(); @@ -78,7 +78,7 @@ if (bookmarkModelsLoadedError) { return bookmarkModelsLoadedError; } - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = [BookmarkEarlGreyAppInterface bookmarkModelOfStorage:storageType]; NSString* firstTitle = @"First URL"; @@ -126,7 +126,7 @@ if (waitForBookmarkModelsLoadedError) { return waitForBookmarkModelsLoadedError; } - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = [BookmarkEarlGreyAppInterface bookmarkModelOfStorage:storageType]; const GURL dummyURL = GURL(base::SysNSStringToUTF8(URL)); @@ -157,7 +157,7 @@ } + (NSError*)waitForBookmarkModelsLoaded { - bookmarks::BookmarkModel* localOrSyncableBookmarkModel = + LegacyBookmarkModel* localOrSyncableBookmarkModel = [BookmarkEarlGreyAppInterface localOrSyncableBookmarkModel]; BOOL localOrSyncableModelSuccess = @@ -169,7 +169,7 @@ return testing::NSErrorWithLocalizedDescription( @"Local/Syncable bookmark model did not load"); } - bookmarks::BookmarkModel* accountBookmarkModel = + LegacyBookmarkModel* accountBookmarkModel = [BookmarkEarlGreyAppInterface accountBookmarkModel]; if (!accountBookmarkModel) { @@ -187,10 +187,10 @@ } + (void)commitPendingWrite { - bookmarks::BookmarkModel* localOrSyncableBookmarkModel = + LegacyBookmarkModel* localOrSyncableBookmarkModel = [BookmarkEarlGreyAppInterface localOrSyncableBookmarkModel]; localOrSyncableBookmarkModel->CommitPendingWriteForTest(); - bookmarks::BookmarkModel* accountBookmarkModel = + LegacyBookmarkModel* accountBookmarkModel = [BookmarkEarlGreyAppInterface accountBookmarkModel]; if (accountBookmarkModel) { accountBookmarkModel->CommitPendingWriteForTest(); @@ -225,7 +225,7 @@ expectedCount:(NSUInteger)expectedCount inStorage:(BookmarkModelType)storageType { // Get BookmarkModel and wait for it to be loaded. - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = [BookmarkEarlGreyAppInterface bookmarkModelOfStorage:storageType]; // Verify the correct number of bookmarks exist. @@ -253,7 +253,7 @@ } GURL bookmarkURL = GURL(base::SysNSStringToUTF8(url)); - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = [BookmarkEarlGreyAppInterface bookmarkModelOfStorage:storageType]; bookmarkModel->AddNewURL(bookmarkModel->mobile_node(), 0, base::SysNSStringToUTF16(title), bookmarkURL); @@ -264,7 +264,7 @@ + (NSError*)removeBookmarkWithTitle:(NSString*)title inStorage:(BookmarkModelType)storageType { std::u16string name16(base::SysNSStringToUTF16(title)); - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = [BookmarkEarlGreyAppInterface bookmarkModelOfStorage:storageType]; ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator( bookmarkModel->root_node()); @@ -284,7 +284,7 @@ toFolderWithTitle:(NSString*)newFolder inStorage:(BookmarkModelType)storageType { std::u16string name16(base::SysNSStringToUTF16(bookmarkTitle)); - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = [BookmarkEarlGreyAppInterface bookmarkModelOfStorage:storageType]; ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator( bookmarkModel->root_node()); @@ -307,7 +307,7 @@ folder = iteratorFolder.Next(); } std::vector<const bookmarks::BookmarkNode*> toMove{bookmark}; - bookmarks::BookmarkModel* accountBookmarkModel = + LegacyBookmarkModel* accountBookmarkModel = [BookmarkEarlGreyAppInterface accountBookmarkModel]; if (!bookmark_utils_ios::MoveBookmarks(toMove, bookmarkModel, accountBookmarkModel, folder)) { @@ -323,7 +323,7 @@ inFolderWithName:(NSString*)name inStorage:(BookmarkModelType)storageType { std::u16string name16(base::SysNSStringToUTF16(name)); - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = [BookmarkEarlGreyAppInterface bookmarkModelOfStorage:storageType]; ui::TreeNodeIterator<const bookmarks::BookmarkNode> iterator( @@ -441,18 +441,17 @@ } #pragma mark - Helpers -+ (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel { ++ (LegacyBookmarkModel*)localOrSyncableBookmarkModel { return ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( chrome_test_util::GetOriginalBrowserState()); } -+ (bookmarks::BookmarkModel*)accountBookmarkModel { ++ (LegacyBookmarkModel*)accountBookmarkModel { return ios::AccountBookmarkModelFactory::GetForBrowserState( chrome_test_util::GetOriginalBrowserState()); } -+ (bookmarks::BookmarkModel*)bookmarkModelOfStorage: - (BookmarkModelType)storageType { ++ (LegacyBookmarkModel*)bookmarkModelOfStorage:(BookmarkModelType)storageType { switch (storageType) { case BookmarkModelType::kLocalOrSyncable: return [BookmarkEarlGreyAppInterface localOrSyncableBookmarkModel];
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_mediator.h b/ios/chrome/browser/ui/bookmarks/bookmark_mediator.h index d3223eaa..74a8e19 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_mediator.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_mediator.h
@@ -9,18 +9,18 @@ class AuthenticationService; class GURL; +class LegacyBookmarkModel; @class MDCSnackbarMessage; class PrefService; @class URLWithTitle; namespace bookmarks { class BookmarkNode; -class BookmarkModel; } // namespace bookmarks namespace syncer { class SyncService; -} +} // namespace syncer namespace user_prefs { class PrefRegistrySyncable; @@ -32,9 +32,9 @@ - (instancetype)init NS_UNAVAILABLE; - (instancetype) initWithWithLocalOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel accountBookmarkModel: - (bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)accountBookmarkModel prefs:(PrefService*)prefs authenticationService: (AuthenticationService*)authenticationService
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm b/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm index f3fd8be..93d78f9 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_mediator.mm
@@ -12,7 +12,6 @@ #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/browser/bookmark_utils.h" #import "components/pref_registry/pref_registry_syncable.h" @@ -21,6 +20,7 @@ #import "components/sync/service/sync_user_settings.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" @@ -34,14 +34,13 @@ #import "net/base/apple/url_conversions.h" #import "ui/base/l10n/l10n_util.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; @implementation BookmarkMediator { // Profile bookmark model for this mediator. - base::WeakPtr<bookmarks::BookmarkModel> _localOrSyncableBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _localOrSyncableBookmarkModel; // Account bookmark model for this mediator. - base::WeakPtr<bookmarks::BookmarkModel> _accountBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _accountBookmarkModel; // Prefs model for this mediator. raw_ptr<PrefService> _prefs; @@ -64,9 +63,9 @@ - (instancetype) initWithWithLocalOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel accountBookmarkModel: - (bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)accountBookmarkModel prefs:(PrefService*)prefs authenticationService: (AuthenticationService*)authenticationService @@ -101,7 +100,7 @@ const BookmarkNode* defaultFolder = GetDefaultBookmarkFolder( _prefs, bookmark_utils_ios::IsAccountBookmarkStorageOptedIn(_syncService), _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); - BookmarkModel* modelForDefaultFolder = + LegacyBookmarkModel* modelForDefaultFolder = bookmark_utils_ios::GetBookmarkModelForNode( defaultFolder, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); @@ -139,7 +138,7 @@ const BookmarkNode* defaultFolder = GetDefaultBookmarkFolder( _prefs, bookmark_utils_ios::IsAccountBookmarkStorageOptedIn(_syncService), _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); - BookmarkModel* modelForDefaultFolder = + LegacyBookmarkModel* modelForDefaultFolder = bookmark_utils_ios::GetBookmarkModelForNode( defaultFolder, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); @@ -204,8 +203,10 @@ - (MDCSnackbarMessage*)addBookmarks:(NSArray<URLWithTitle*>*)URLs toFolder:(const BookmarkNode*)folder { - BookmarkModel* modelForFolder = bookmark_utils_ios::GetBookmarkModelForNode( - folder, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); + LegacyBookmarkModel* modelForFolder = + bookmark_utils_ios::GetBookmarkModelForNode( + folder, _localOrSyncableBookmarkModel.get(), + _accountBookmarkModel.get()); for (URLWithTitle* urlWithTitle in URLs) { RecordModuleFreshnessSignal(ContentSuggestionsModuleType::kShortcuts); base::RecordAction(base::UserMetricsAction("BookmarkAdded"));
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm b/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm index 6cab794..2c628592 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_mediator_unittest.mm
@@ -12,13 +12,13 @@ #import "base/strings/utf_string_conversions.h" #import "base/test/metrics/histogram_tester.h" #import "base/test/scoped_feature_list.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/url_and_title.h" #import "components/sync/base/user_selectable_type.h" #import "components/sync/service/sync_service.h" #import "components/sync/test/test_sync_service.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/shared/public/features/features.h"
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.h b/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.h index b730c74..8545fb1 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.h
@@ -8,17 +8,13 @@ #import <UIKit/UIKit.h> enum class BookmarkModelType; - -namespace bookmarks { -class BookmarkModel; -} // namespace bookmarks +class LegacyBookmarkModel; +class PrefService; namespace user_prefs { class PrefRegistrySyncable; } // namespace user_prefs -class PrefService; - // Stores and retrieves the bookmark top most row that the user was last // viewing. @interface BookmarkPathCache : NSObject @@ -37,9 +33,9 @@ // populated if the return is YES. + (BOOL)getBookmarkTopMostRowCacheWithPrefService:(PrefService*)prefService localOrSyncableModel: - (bookmarks::BookmarkModel*)localOrSyncableModel + (LegacyBookmarkModel*)localOrSyncableModel accountModel: - (bookmarks::BookmarkModel*)accountModel + (LegacyBookmarkModel*)accountModel folderId:(int64_t*)folderId modelType:(BookmarkModelType*)modelType topMostRow:(int*)topMostRow;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.mm b/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.mm index c371396..c1ffe2d 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_path_cache.mm
@@ -4,15 +4,14 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_path_cache.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/pref_registry/pref_registry_syncable.h" #import "components/prefs/pref_service.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; namespace { @@ -41,16 +40,16 @@ + (BOOL)getBookmarkTopMostRowCacheWithPrefService:(PrefService*)prefService localOrSyncableModel: - (bookmarks::BookmarkModel*)localOrSyncableModel + (LegacyBookmarkModel*)localOrSyncableModel accountModel: - (bookmarks::BookmarkModel*)accountModel + (LegacyBookmarkModel*)accountModel folderId:(int64_t*)folderId modelType:(BookmarkModelType*)modelType topMostRow:(int*)topMostRow { *folderId = prefService->GetInt64(prefs::kIosBookmarkCachedFolderId); *modelType = static_cast<BookmarkModelType>( prefService->GetInt64(prefs::kIosBookmarkCachedFolderModel)); - bookmarks::BookmarkModel* model; + LegacyBookmarkModel* model; if (*modelType == BookmarkModelType::kLocalOrSyncable) { model = localOrSyncableModel; } else {
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_path_cache_unittest.mm b/ios/chrome/browser/ui/bookmarks/bookmark_path_cache_unittest.mm index 4984fa1..937bd85 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_path_cache_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_path_cache_unittest.mm
@@ -4,11 +4,11 @@ #import "ios/chrome/browser/ui/bookmarks/bookmark_path_cache.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_metrics.h" #import "components/sync_preferences/testing_pref_service_syncable.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" #import "testing/platform_test.h"
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h index 6939077..5544bf9 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h +++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h
@@ -22,9 +22,9 @@ class ChromeBrowserState; class GURL; @class MDCSnackbarMessage; +class LegacyBookmarkModel; namespace bookmarks { -class BookmarkModel; class BookmarkNode; } // namespace bookmarks @@ -37,7 +37,7 @@ // This class holds a node id and its bookmark model. struct BookmarkNodeReference { BookmarkNodeReference(const base::Uuid& uuid, - bookmarks::BookmarkModel* bookmark_model); + LegacyBookmarkModel* bookmark_model); BookmarkNodeReference(const BookmarkNodeReference&); ~BookmarkNodeReference(); @@ -48,7 +48,7 @@ // Node id for the BookmarkNode. const base::Uuid uuid; // Bookmark model from the BookmarkNode. - raw_ptr<bookmarks::BookmarkModel> bookmark_model; + raw_ptr<LegacyBookmarkModel> bookmark_model; }; typedef std::vector<const bookmarks::BookmarkNode*> NodeVector; @@ -58,8 +58,8 @@ // Converts a set of BookmarkNode into a set of BookmarkNodeReference. NodeReferenceSet FindNodeReferenceByNodes( NodeSet nodes, - bookmarks::BookmarkModel* profile_bookmark_model, - bookmarks::BookmarkModel* account_bookmark_model); + LegacyBookmarkModel* profile_bookmark_model, + LegacyBookmarkModel* account_bookmark_model); // Converts a BookmarkNodeReference into a BookmarkNode. This function might // returns `nullptr` if the bookmark node doesn't exist anymore. @@ -72,12 +72,12 @@ NodeSet FindNodesByNodeReferences(NodeReferenceSet references); // Finds bookmark node passed in `id`, in the `model`. -const bookmarks::BookmarkNode* FindNodeById(bookmarks::BookmarkModel* model, +const bookmarks::BookmarkNode* FindNodeById(LegacyBookmarkModel* model, int64_t id); // Finds bookmark node passed in `id`, in the `model`. Returns null if the // node is found but not a folder. -const bookmarks::BookmarkNode* FindFolderById(bookmarks::BookmarkModel* model, +const bookmarks::BookmarkNode* FindFolderById(LegacyBookmarkModel* model, int64_t id); // The iOS code is doing some munging of the bookmark folder names in order @@ -93,8 +93,8 @@ // This function is linear in time in the depth of the bookmark_node. BookmarkModelType GetBookmarkModelType( const bookmarks::BookmarkNode* bookmark_node, - bookmarks::BookmarkModel* profile_model, - bookmarks::BookmarkModel* account_model); + LegacyBookmarkModel* profile_model, + LegacyBookmarkModel* account_model); // Returns the bookmark model for a node, based on profile model and account // model. @@ -104,10 +104,10 @@ // The node must belong to one of the two models. // This function is linear in time in the depth of the bookmark_node because it // uses `GetBookmarkModelType(...)`. -bookmarks::BookmarkModel* GetBookmarkModelForNode( +LegacyBookmarkModel* GetBookmarkModelForNode( const bookmarks::BookmarkNode* bookmark_node, - bookmarks::BookmarkModel* profile_model, - bookmarks::BookmarkModel* account_model); + LegacyBookmarkModel* profile_model, + LegacyBookmarkModel* account_model); // Returns true if the user is signed in and they opted in for the account // bookmark storage. @@ -122,8 +122,8 @@ NSString* title, const GURL& url, const bookmarks::BookmarkNode* folder, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model); + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model); // Similar to `UpdateBookmark`, but returns a snackbar that allows to // undo the performed action. Returns nil if there's nothing to undo. @@ -137,8 +137,8 @@ const GURL& url, const bookmarks::BookmarkNode* original_folder, const bookmarks::BookmarkNode* folder, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model, ChromeBrowserState* browser_state, base::WeakPtr<AuthenticationService> authenticationService, raw_ptr<syncer::SyncService> syncService); @@ -151,8 +151,8 @@ const GURL& url, const bookmarks::BookmarkNode* folder, int position, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model, ChromeBrowserState* browser_state); // Updates a bookmark node position, and returns a snackbar with an undo action. @@ -162,8 +162,8 @@ const bookmarks::BookmarkNode* node, const bookmarks::BookmarkNode* folder, size_t position, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model, ChromeBrowserState* browser_state); // Deletes all nodes in `bookmarks` from models in `bookmark_models` that are @@ -171,12 +171,12 @@ // the operation wasn't successful or there's nothing to undo. MDCSnackbarMessage* DeleteBookmarksWithUndoToast( const std::set<const bookmarks::BookmarkNode*>& bookmarks, - const std::vector<bookmarks::BookmarkModel*>& bookmark_models, + const std::vector<LegacyBookmarkModel*>& bookmark_models, ChromeBrowserState* browser_state); // Deletes all nodes in `bookmarks`. void DeleteBookmarks(const std::set<const bookmarks::BookmarkNode*>& bookmarks, - bookmarks::BookmarkModel* model); + LegacyBookmarkModel* model); // Move all `bookmarks_to_move` to the given `folder`, and returns a snackbar // with an undo action. Returns nil if the operation wasn't successful or @@ -185,8 +185,8 @@ // `MoveBookmarks` documentation for details. MDCSnackbarMessage* MoveBookmarksWithUndoToast( std::vector<const bookmarks::BookmarkNode*>& bookmarks_to_move, - bookmarks::BookmarkModel* local_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_model, + LegacyBookmarkModel* account_model, const bookmarks::BookmarkNode* destination_folder, ChromeBrowserState* browser_state, base::WeakPtr<AuthenticationService> authenticationService, @@ -201,8 +201,8 @@ // the same index N. bool MoveBookmarks( std::vector<const bookmarks::BookmarkNode*>& bookmarks_to_move, - bookmarks::BookmarkModel* local_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_model, + LegacyBookmarkModel* account_model, const bookmarks::BookmarkNode* destination_folder); // Category name for all bookmarks related snackbars. @@ -215,7 +215,7 @@ // sorted depth-first, then alphabetically. The returned nodes are visible, and // are guaranteed to not be descendants of any nodes in `obstructions`. NodeVector VisibleNonDescendantNodes(const NodeSet& obstructions, - bookmarks::BookmarkModel* model); + LegacyBookmarkModel* model); // Whether `vector1` contains only elements of `vector2` in the same order. BOOL IsSubvectorOfNodes(const NodeVector& vector1, const NodeVector& vector2); @@ -230,7 +230,7 @@ // Creates bookmark path for `folderId` passed in. For eg: for folderId = 76, // Root node(0) --> MobileBookmarks (3) --> Test1(76) will be returned as [0, 3, // 76]. -NSArray<NSNumber*>* CreateBookmarkPath(bookmarks::BookmarkModel* model, +NSArray<NSNumber*>* CreateBookmarkPath(LegacyBookmarkModel* model, int64_t folder_id); // Converts NSString entered by the user to a GURL. @@ -243,8 +243,8 @@ // models contain matching entries - returns null. `account_model` can be null. const bookmarks::BookmarkNode* GetMostRecentlyAddedUserNodeForURL( const GURL& url, - bookmarks::BookmarkModel* local_model, - bookmarks::BookmarkModel* account_model); + LegacyBookmarkModel* local_model, + LegacyBookmarkModel* account_model); // The localized strings for adding bookmarks. // `folderTitle`: The name of the folder. Assumed to be non-nil.
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm index 989de86..2937e42 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.mm
@@ -27,7 +27,6 @@ #import "base/strings/string_number_conversions.h" #import "base/strings/sys_string_conversions.h" #import "base/strings/utf_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/bookmarks/common/bookmark_metrics.h" @@ -41,6 +40,7 @@ #import "components/url_formatter/url_fixer.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/public/features/system_flags.h" #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/signin/model/authentication_service.h" @@ -61,7 +61,7 @@ BookmarkNodeReference::BookmarkNodeReference( const base::Uuid& uuid, - bookmarks::BookmarkModel* bookmark_model) + LegacyBookmarkModel* bookmark_model) : uuid(uuid), bookmark_model(bookmark_model) {} BookmarkNodeReference::BookmarkNodeReference( @@ -78,11 +78,11 @@ NodeReferenceSet FindNodeReferenceByNodes( NodeSet nodes, - bookmarks::BookmarkModel* profile_bookmark_model, - bookmarks::BookmarkModel* account_bookmark_model) { + LegacyBookmarkModel* profile_bookmark_model, + LegacyBookmarkModel* account_bookmark_model) { NodeReferenceSet references; for (const BookmarkNode* node : nodes) { - bookmarks::BookmarkModel* model = GetBookmarkModelForNode( + LegacyBookmarkModel* model = GetBookmarkModelForNode( node, profile_bookmark_model, account_bookmark_model); references.insert(BookmarkNodeReference(node->uuid(), model)); } @@ -112,7 +112,7 @@ return nodes; } -const BookmarkNode* FindNodeById(bookmarks::BookmarkModel* model, int64_t id) { +const BookmarkNode* FindNodeById(LegacyBookmarkModel* model, int64_t id) { DCHECK(model); ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); while (iterator.has_next()) { @@ -124,8 +124,7 @@ return nullptr; } -const BookmarkNode* FindFolderById(bookmarks::BookmarkModel* model, - int64_t id) { +const BookmarkNode* FindFolderById(LegacyBookmarkModel* model, int64_t id) { const BookmarkNode* node = FindNodeById(model, id); return node && node->is_folder() ? node : nullptr; } @@ -155,8 +154,8 @@ BookmarkModelType GetBookmarkModelType( const bookmarks::BookmarkNode* bookmark_node, - bookmarks::BookmarkModel* profile_model, - bookmarks::BookmarkModel* account_model) { + LegacyBookmarkModel* profile_model, + LegacyBookmarkModel* account_model) { DCHECK(bookmark_node); DCHECK(profile_model); if (bookmark_node->HasAncestor(profile_model->root_node())) { @@ -167,10 +166,10 @@ return BookmarkModelType::kAccount; } -bookmarks::BookmarkModel* GetBookmarkModelForNode( +LegacyBookmarkModel* GetBookmarkModelForNode( const bookmarks::BookmarkNode* bookmark_node, - bookmarks::BookmarkModel* profile_model, - bookmarks::BookmarkModel* account_model) { + LegacyBookmarkModel* profile_model, + LegacyBookmarkModel* account_model) { BookmarkModelType modelType = GetBookmarkModelType(bookmark_node, profile_model, account_model); return modelType == BookmarkModelType::kAccount ? account_model @@ -195,7 +194,7 @@ // Deletes all subnodes of `node`, including `node`, that are in `bookmarks`. void DeleteBookmarks(const std::set<const BookmarkNode*>& bookmarks, - bookmarks::BookmarkModel* model, + LegacyBookmarkModel* model, const BookmarkNode* node) { // Delete children in reverse order, so that the index remains valid. for (size_t i = node->children().size(); i > 0; --i) { @@ -238,8 +237,8 @@ NSString* title, const GURL& url, const BookmarkNode* folder, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model) { + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model) { DCHECK(node); DCHECK(folder); std::u16string titleString = base::SysNSStringToUTF16(title); @@ -249,9 +248,9 @@ return false; } - bookmarks::BookmarkModel* folder_model = + LegacyBookmarkModel* folder_model = GetBookmarkModelForNode(folder, local_or_syncable_model, account_model); - bookmarks::BookmarkModel* node_model = + LegacyBookmarkModel* node_model = GetBookmarkModelForNode(node, local_or_syncable_model, account_model); node_model->SetTitle(node, titleString, bookmarks::metrics::BookmarkEditSource::kUser); @@ -367,8 +366,8 @@ const GURL& url, const BookmarkNode* original_folder, const BookmarkNode* folder, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model, ChromeBrowserState* browser_state, base::WeakPtr<AuthenticationService> authenticationService, raw_ptr<syncer::SyncService> syncService) { @@ -408,8 +407,8 @@ const GURL& url, const bookmarks::BookmarkNode* folder, int position, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model, ChromeBrowserState* browser_state) { std::u16string titleString = base::SysNSStringToUTF16(title); @@ -419,7 +418,7 @@ RecordModuleFreshnessSignal(ContentSuggestionsModuleType::kShortcuts); base::RecordAction(base::UserMetricsAction("BookmarkAdded")); - bookmarks::BookmarkModel* folder_model = + LegacyBookmarkModel* folder_model = GetBookmarkModelForNode(folder, local_or_syncable_model, account_model); const bookmarks::BookmarkNode* node = folder_model->AddNewURL( folder, folder->children().size(), titleString, url); @@ -438,8 +437,8 @@ const bookmarks::BookmarkNode* node, const bookmarks::BookmarkNode* folder, size_t position, - bookmarks::BookmarkModel* local_or_syncable_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_or_syncable_model, + LegacyBookmarkModel* account_model, ChromeBrowserState* browser_state) { DCHECK(node); DCHECK(folder); @@ -451,9 +450,9 @@ return nil; } - bookmarks::BookmarkModel* node_model = + LegacyBookmarkModel* node_model = GetBookmarkModelForNode(node, local_or_syncable_model, account_model); - bookmarks::BookmarkModel* folder_model = + LegacyBookmarkModel* folder_model = GetBookmarkModelForNode(folder, local_or_syncable_model, account_model); CHECK_EQ(node_model, folder_model); @@ -476,14 +475,14 @@ } void DeleteBookmarks(const std::set<const BookmarkNode*>& bookmarks, - bookmarks::BookmarkModel* model) { + LegacyBookmarkModel* model) { CHECK(model && model->loaded()) << "Model: " << model; DeleteBookmarks(bookmarks, model, model->root_node()); } MDCSnackbarMessage* DeleteBookmarksWithUndoToast( const std::set<const BookmarkNode*>& nodes, - const std::vector<bookmarks::BookmarkModel*>& bookmark_models, + const std::vector<LegacyBookmarkModel*>& bookmark_models, ChromeBrowserState* browser_state) { CHECK_GT(bookmark_models.size(), 0u); size_t node_count = nodes.size(); @@ -522,8 +521,8 @@ // Returns whether any moves were performed. bool MoveToOtherModelRecursive( std::vector<BookmarkNodeVectorIterator>& bookmarks_to_move, - bookmarks::BookmarkModel* source_model, - bookmarks::BookmarkModel* dest_model, + LegacyBookmarkModel* source_model, + LegacyBookmarkModel* dest_model, const BookmarkNode* destination_folder, const BookmarkNode* node_cursor) { DCHECK(source_model != dest_model); @@ -557,18 +556,18 @@ bool MoveBookmarks( std::vector<const bookmarks::BookmarkNode*>& bookmarks_to_move, - bookmarks::BookmarkModel* local_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_model, + LegacyBookmarkModel* account_model, const bookmarks::BookmarkNode* destination_folder) { bool did_perform_move = false; - bookmarks::BookmarkModel* dest_model = + LegacyBookmarkModel* dest_model = GetBookmarkModelForNode(destination_folder, local_model, account_model); // The key is the source bookmark model and the value is a vector of iterators // that belong into `bookmarks_to_move`. Iterators are used to update node // pointers after the move. using ModelToIteratorVectorMap = - base::flat_map<bookmarks::BookmarkModel*, + base::flat_map<LegacyBookmarkModel*, std::vector<BookmarkNodeVectorIterator>>; ModelToIteratorVectorMap cross_model_moves; for (auto it = bookmarks_to_move.begin(); it != bookmarks_to_move.end(); @@ -580,7 +579,7 @@ continue; // Already in `destination_folder`, nothing to do. } - bookmarks::BookmarkModel* source_model = + LegacyBookmarkModel* source_model = GetBookmarkModelForNode((*it), local_model, account_model); if (source_model == dest_model) { // Since moving bookmarks within one model shouldn't invalidate any node @@ -608,8 +607,8 @@ MDCSnackbarMessage* MoveBookmarksWithUndoToast( std::vector<const BookmarkNode*>& bookmarks_to_move, - bookmarks::BookmarkModel* local_model, - bookmarks::BookmarkModel* account_model, + LegacyBookmarkModel* local_model, + LegacyBookmarkModel* account_model, const BookmarkNode* destination_folder, ChromeBrowserState* browser_state, base::WeakPtr<AuthenticationService> authenticationService, @@ -754,7 +753,7 @@ } NodeVector VisibleNonDescendantNodes(const NodeSet& obstructions, - bookmarks::BookmarkModel* model) { + LegacyBookmarkModel* model) { NodeVector primary_nodes = PrimaryPermanentNodes(model); NodeVector filtered_primary_nodes; for (auto* node : primary_nodes) { @@ -831,7 +830,7 @@ // Creates bookmark path for `folderId` passed in. For eg: for folderId = 76, // Root node(0) --> MobileBookmarks (3) --> Test1(76) will be returned as [0, 3, // 76]. Return nullptr if the folder is not found. -NSArray<NSNumber*>* CreateBookmarkPath(bookmarks::BookmarkModel* model, +NSArray<NSNumber*>* CreateBookmarkPath(LegacyBookmarkModel* model, int64_t folder_id) { // Create an array with root node id, if folder_id == root node. if (model->root_node()->id() == folder_id) { @@ -864,8 +863,8 @@ const BookmarkNode* GetMostRecentlyAddedUserNodeForURL( const GURL& url, - bookmarks::BookmarkModel* local_model, - bookmarks::BookmarkModel* account_model) { + LegacyBookmarkModel* local_model, + LegacyBookmarkModel* account_model) { CHECK(local_model); const BookmarkNode* local_bookmark = local_model->GetMostRecentlyAddedUserNodeForURL(url);
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm index a519e02..ebb0c81a 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_utils_ios_unittest.mm
@@ -13,12 +13,12 @@ #import "base/strings/sys_string_conversions.h" #import "base/strings/utf_string_conversions.h" #import "base/time/time.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/sync/base/features.h" #import "components/sync/test/test_sync_service.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "testing/gmock/include/gmock/gmock.h" #import "testing/gtest_mac.h"
diff --git a/ios/chrome/browser/ui/bookmarks/editor/BUILD.gn b/ios/chrome/browser/ui/bookmarks/editor/BUILD.gn index bcdf4b91..16cfa90 100644 --- a/ios/chrome/browser/ui/bookmarks/editor/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/editor/BUILD.gn
@@ -51,6 +51,7 @@ "//components/bookmarks/browser", "//components/strings", "//ios/chrome/app/strings", + "//ios/chrome/browser/bookmarks/model", "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/browser_state",
diff --git a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_coordinator.mm b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_coordinator.mm index a177797..e65c35fb 100644 --- a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_coordinator.mm +++ b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_coordinator.mm
@@ -86,10 +86,10 @@ _viewController.delegate = self; ChromeBrowserState* browserState = self.browser->GetBrowserState()->GetOriginalChromeBrowserState(); - bookmarks::BookmarkModel* localOrSyncableBookmarkModel = + LegacyBookmarkModel* localOrSyncableBookmarkModel = ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( browserState); - bookmarks::BookmarkModel* accountBookmarkModel = + LegacyBookmarkModel* accountBookmarkModel = ios::AccountBookmarkModelFactory::GetForBrowserState(browserState); syncer::SyncService* syncService = SyncServiceFactory::GetForBrowserState(browserState);
diff --git a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.h b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.h index 85b0e8f..63af32a 100644 --- a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.h +++ b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.h
@@ -13,11 +13,11 @@ @protocol BookmarksEditorConsumer; @protocol BookmarksEditorMediatorDelegate; class ChromeBrowserState; +class LegacyBookmarkModel; class PrefService; @protocol SnackbarCommands; namespace bookmarks { -class BookmarkModel; class BookmarkNode; } // namespace bookmarks @@ -47,9 +47,9 @@ // It also must be a URL. `prefs` is the user pref service. - (instancetype) initWithLocalOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel accountBookmarkModel: - (bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)accountBookmarkModel bookmarkNode: (const bookmarks::BookmarkNode*)bookmarkNode prefs:(PrefService*)prefs
diff --git a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.mm b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.mm index fe081f04..d5c3ac7 100644 --- a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.mm +++ b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.mm
@@ -7,7 +7,6 @@ #import "base/check.h" #import "base/memory/raw_ptr.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/prefs/pref_service.h" @@ -16,6 +15,7 @@ #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/public/commands/snackbar_commands.h" #import "ios/chrome/browser/signin/model/authentication_service.h" @@ -45,8 +45,8 @@ @end @implementation BookmarksEditorMediator { - base::WeakPtr<bookmarks::BookmarkModel> _localOrSyncableBookmarkModel; - base::WeakPtr<bookmarks::BookmarkModel> _accountBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _localOrSyncableBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _accountBookmarkModel; raw_ptr<syncer::SyncService> _syncService; // The folder in which was the bookmark when the view was opened. const bookmarks::BookmarkNode* _originalFolder; @@ -56,9 +56,9 @@ - (instancetype) initWithLocalOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel accountBookmarkModel: - (bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)accountBookmarkModel bookmarkNode: (const bookmarks::BookmarkNode*)bookmarkNode prefs:(PrefService*)prefs @@ -119,7 +119,7 @@ #pragma mark - Properties -- (bookmarks::BookmarkModel*)bookmarkModel { +- (LegacyBookmarkModel*)bookmarkModel { return bookmark_utils_ios::GetBookmarkModelForNode( self.bookmark, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); @@ -152,11 +152,11 @@ #pragma mark - BookmarkModelBridgeObserver -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { // No-op. } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { if (self.ignoresBookmarkModelChanges) { return; @@ -171,7 +171,7 @@ folderName:bookmark_utils_ios::TitleForBookmarkNode(_folder)]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { if (self.ignoresBookmarkModelChanges) { return; @@ -180,7 +180,7 @@ [self updateFolderLabel]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { @@ -193,7 +193,7 @@ } } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model willDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { if (self.ignoresBookmarkModelChanges) { @@ -211,14 +211,14 @@ } } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { // No-op. Bookmark deletion handled in // `bookmarkModel:willDeleteNode:fromFolder:` } -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { CHECK(!self.ignoresBookmarkModelChanges); _bookmark = nullptr; self.folder = nullptr;
diff --git a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mutator.h b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mutator.h index aec84a44..88da391b 100644 --- a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mutator.h +++ b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mutator.h
@@ -9,9 +9,10 @@ namespace bookmarks { class BookmarkNode; -class BookmarkModel; } // namespace bookmarks +class LegacyBookmarkModel; + // Allows the bookmark editor’s view controller to reflect user’s change in the // model. // TODO(crbug.com/1412479): Change of model should be done through the mutator. @@ -29,7 +30,7 @@ // TODO(crbug.com/1404311): Remove those accessor and setters. // We temporarily use them to facilitate code migration. - (const bookmarks::BookmarkNode*)bookmark; -- (bookmarks::BookmarkModel*)bookmarkModel; +- (LegacyBookmarkModel*)bookmarkModel; - (const bookmarks::BookmarkNode*)folder; - (BOOL)ignoresBookmarkModelChanges; - (BOOL)shouldDisplayCloudSlashSymbolForParentFolder;
diff --git a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller.mm b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller.mm index b8f55d48..5e85cc5 100644 --- a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller.mm
@@ -15,7 +15,7 @@ #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/shared/public/features/system_flags.h" #import "ios/chrome/browser/shared/ui/symbols/chrome_icon.h" @@ -39,7 +39,6 @@ #import "ui/gfx/image/image.h" #import "url/gurl.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; namespace {
diff --git a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller_unittest.mm b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller_unittest.mm index 9cb94622..3bf1284 100644 --- a/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_view_controller_unittest.mm
@@ -6,8 +6,8 @@ #import "ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_mediator.h" #import "base/test/metrics/user_action_tester.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/signin/model/authentication_service.h" #import "ios/chrome/browser/signin/model/authentication_service_factory.h"
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_coordinator.mm b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_coordinator.mm index 10f6349..c0879e75 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_coordinator.mm +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_coordinator.mm
@@ -12,9 +12,9 @@ #import "base/memory/raw_ptr.h" #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_features.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" @@ -116,10 +116,10 @@ [super start]; ChromeBrowserState* browserState = self.browser->GetBrowserState()->GetOriginalChromeBrowserState(); - bookmarks::BookmarkModel* localOrSyncableModel = + LegacyBookmarkModel* localOrSyncableModel = ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( browserState); - bookmarks::BookmarkModel* accountModel = + LegacyBookmarkModel* accountModel = ios::AccountBookmarkModelFactory::GetForBrowserState(browserState); AuthenticationService* authenticationService = AuthenticationServiceFactory::GetForBrowserState(browserState);
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.h b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.h index 4672f03..c9d4a93 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.h +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.h
@@ -11,11 +11,11 @@ #import <Foundation/Foundation.h> #import <set> -@protocol BookmarksFolderChooserMediatorDelegate; class AuthenticationService; +@protocol BookmarksFolderChooserMediatorDelegate; +class LegacyBookmarkModel; namespace bookmarks { -class BookmarkModel; class BookmarkNode; } // namespace bookmarks @@ -40,9 +40,9 @@ // nodes that are being edited (moved to a folder). - (instancetype) initWithLocalOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel accountBookmarkModel: - (bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)accountBookmarkModel editedNodes: (std::set<const bookmarks::BookmarkNode*>) editedNodes
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.mm b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.mm index 753cd1de4..2ecb873 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.mm +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mediator.mm
@@ -6,10 +6,10 @@ #import "base/containers/contains.h" #import "base/memory/raw_ptr.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/sync/base/features.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/signin/model/authentication_service_observer_bridge.h" #import "ios/chrome/browser/sync/model/sync_observer_bridge.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_ui_constants.h" @@ -19,7 +19,6 @@ #import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_mutator.h" #import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; @interface BookmarksFolderChooserMediator () < @@ -49,8 +48,9 @@ - (instancetype) initWithLocalOrSyncableBookmarkModel: - (BookmarkModel*)localOrSyncableBookmarkModel - accountBookmarkModel:(BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel + accountBookmarkModel: + (LegacyBookmarkModel*)accountBookmarkModel editedNodes: (std::set<const BookmarkNode*>)editedNodes authenticationService:(AuthenticationService*)authService @@ -155,7 +155,8 @@ } } -- (void)bookmarkModelWillRemoveAllNodes:(const BookmarkModel*)bookmarkModel { +- (void)bookmarkModelWillRemoveAllNodes: + (const LegacyBookmarkModel*)bookmarkModel { auto nodeInModel = [bookmarkModel](const BookmarkNode* node) { return node->HasAncestor(bookmarkModel->root_node()); };
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.h b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.h index 51da1de..e512244 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.h +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.h
@@ -11,10 +11,11 @@ #import <set> namespace bookmarks { -class BookmarkModel; class BookmarkNode; } // namespace bookmarks +class LegacyBookmarkModel; + // Protocol to access and update data from parent data source object. Please // note that the parent data source is not and should not be responsible for // updating the UI in these method calls as that distributes UI update logic @@ -26,7 +27,7 @@ - (void)bookmarkNodeDeleted:(const bookmarks::BookmarkNode*)bookmarkNode; // Called before all the bookmark nodes in the model are deleted. - (void)bookmarkModelWillRemoveAllNodes: - (const bookmarks::BookmarkModel*)bookmarkModel; + (const LegacyBookmarkModel*)bookmarkModel; // The set of nodes that are being considered for a move by folder chooser. - (const std::set<const bookmarks::BookmarkNode*>&)editedNodes; @@ -42,7 +43,7 @@ // Both `bookmarkModel` and `parentDataSource` needs to be non null. // Additionally, `bookmarkModel` needs to be fully loaded. -- (instancetype)initWithBookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel +- (instancetype)initWithBookmarkModel:(LegacyBookmarkModel*)bookmarkModel parentDataSource: (id<BookmarksFolderChooserParentDataSource>) parentDataSource NS_DESIGNATED_INITIALIZER;
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.mm b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.mm index 7cb4eba..78ece9d 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.mm +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.mm
@@ -5,11 +5,10 @@ #import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl.h" #import "base/memory/raw_ptr.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; @interface BookmarksFolderChooserSubDataSourceImpl () < @@ -18,13 +17,13 @@ @implementation BookmarksFolderChooserSubDataSourceImpl { // Bookmarks model object. - raw_ptr<BookmarkModel> _bookmarkModel; + raw_ptr<LegacyBookmarkModel> _bookmarkModel; // Observer for `_bookmarkModel` changes. std::unique_ptr<BookmarkModelBridge> _bookmarkModelBridge; __weak id<BookmarksFolderChooserParentDataSource> _parentDataSource; } -- (instancetype)initWithBookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel +- (instancetype)initWithBookmarkModel:(LegacyBookmarkModel*)bookmarkModel parentDataSource: (id<BookmarksFolderChooserParentDataSource>) parentDataSource { @@ -69,24 +68,24 @@ #pragma mark - BookmarkModelBridgeObserver -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { // The bookmark model is assumed to be loaded when this controller is created. NOTREACHED(); } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { if (bookmarkNode->is_folder()) { [_consumer notifyModelUpdated]; } } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { [_consumer notifyModelUpdated]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { @@ -95,20 +94,20 @@ } } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { [_parentDataSource bookmarkNodeDeleted:node]; [_consumer notifyModelUpdated]; } -- (void)bookmarkModelWillRemoveAllNodes:(const BookmarkModel*)model { +- (void)bookmarkModelWillRemoveAllNodes:(const LegacyBookmarkModel*)model { // `_consumer` is notified after the nodes are acutally deleted in // `bookmarkModelRemovedAllNodes`. [_parentDataSource bookmarkModelWillRemoveAllNodes:model]; } -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { [_consumer notifyModelUpdated]; }
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl_unittest.mm b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl_unittest.mm index 66dc2a81..655f8a8 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_sub_data_source_impl_unittest.mm
@@ -11,11 +11,11 @@ #import "base/memory/raw_ptr.h" #import "base/strings/sys_string_conversions.h" #import "base/test/scoped_feature_list.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/bookmarks/test/bookmark_test_helpers.h" #import "components/sync/base/features.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_consumer.h" @@ -24,7 +24,6 @@ #import "testing/gtest_mac.h" #import "testing/platform_test.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; namespace { @@ -43,7 +42,7 @@ @property(nonatomic, assign) const BookmarkNode* bookmarkNodeDeletedArg; // The argument provided when `bookmarkModelWillRemoveAllNodes:` was called. @property(nonatomic, assign) - const BookmarkModel* bookmarkModelWillRemoveAllNodesArg; + const LegacyBookmarkModel* bookmarkModelWillRemoveAllNodesArg; - (instancetype)initWithNodes:(const std::set<const BookmarkNode*>&)nodes; @@ -67,7 +66,8 @@ _bookmarkNodeDeletedArg = bookmarkNode; } -- (void)bookmarkModelWillRemoveAllNodes:(const BookmarkModel*)bookmarkModel { +- (void)bookmarkModelWillRemoveAllNodes: + (const LegacyBookmarkModel*)bookmarkModel { _editedNodes.clear(); _bookmarkModelWillRemoveAllNodesArg = bookmarkModel; } @@ -153,7 +153,7 @@ IOSChromeScopedTestingLocalState local_state_; web::WebTaskEnvironment task_environment_; std::unique_ptr<TestChromeBrowserState> browser_state_; - raw_ptr<BookmarkModel> model_; + raw_ptr<LegacyBookmarkModel> model_; BookmarksFolderChooserSubDataSourceImpl* sub_data_source_; id mock_consumer_; FakeBookmarksFolderChooserParentDataSource* fake_parent_data_source_;
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.h b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.h index 9452d6ba..d227a10 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.h +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.h
@@ -14,10 +14,6 @@ @protocol BookmarksFolderChooserMutator; @protocol BookmarksFolderChooserViewControllerPresentationDelegate; -namespace bookmarks { -class BookmarkModel; -} // namespace bookmarks - // A folder selector view controller. // This controller monitors the state of the bookmark model, so changes to the // bookmark model can affect this controller's state.
diff --git a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.mm b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.mm index b933eea..6bdb4153 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_view_controller.mm
@@ -13,10 +13,10 @@ #import "base/metrics/user_metrics_action.h" #import "base/notreached.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/sync/base/features.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/ui/symbols/chrome_icon.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_header_footer_item.h" #import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
diff --git a/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_coordinator.mm b/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_coordinator.mm index c0340708..08c0221 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_coordinator.mm +++ b/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_coordinator.mm
@@ -87,10 +87,10 @@ // TODO(crbug.com/1402758): Create a mediator. ChromeBrowserState* browserState = self.browser->GetBrowserState()->GetOriginalChromeBrowserState(); - bookmarks::BookmarkModel* localOrSyncableBookmarkModel = + LegacyBookmarkModel* localOrSyncableBookmarkModel = ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( browserState); - bookmarks::BookmarkModel* accountBookmarkModel = + LegacyBookmarkModel* accountBookmarkModel = ios::AccountBookmarkModelFactory::GetForBrowserState(browserState); AuthenticationService* authService = AuthenticationServiceFactory::GetForBrowserState(browserState);
diff --git a/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.h b/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.h index 874ad29..2e9a4e9 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.h +++ b/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.h
@@ -12,10 +12,10 @@ class AuthenticationService; @class BookmarksFolderEditorViewController; class Browser; +class LegacyBookmarkModel; @protocol SnackbarCommands; namespace bookmarks { -class BookmarkModel; class BookmarkNode; } // namespace bookmarks @@ -76,9 +76,9 @@ // `browser` must not be `nullptr`. - (instancetype) initWithLocalOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel accountBookmarkModel: - (bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)accountBookmarkModel folderNode:(const bookmarks::BookmarkNode*)folder parentFolderNode: (const bookmarks::BookmarkNode*)parentFolder
diff --git a/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.mm b/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.mm index 1a29e890..21269a4e 100644 --- a/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.mm
@@ -16,7 +16,6 @@ #import "base/metrics/user_metrics_action.h" #import "base/notreached.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/bookmarks/common/bookmark_metrics.h" @@ -24,6 +23,7 @@ #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/coordinator/alert/action_sheet_coordinator.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" @@ -43,7 +43,6 @@ #import "ios/chrome/grit/ios_strings.h" #import "ui/base/l10n/l10n_util.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; namespace { @@ -68,11 +67,11 @@ @implementation BookmarksFolderEditorViewController { // Model object for localOrSyncable bookmarks. - base::WeakPtr<BookmarkModel> _localOrSyncableBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _localOrSyncableBookmarkModel; // Observer for `_localOrSyncableBookmarkModel` changes. std::unique_ptr<BookmarkModelBridge> _localOrSyncableModelBridge; // Model object for account bookmarks. - base::WeakPtr<BookmarkModel> _accountBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _accountBookmarkModel; // Observer for `_accountBookmarkModel` changes. std::unique_ptr<BookmarkModelBridge> _accountModelBridge; // The authentication service. @@ -109,8 +108,9 @@ - (instancetype) initWithLocalOrSyncableBookmarkModel: - (BookmarkModel*)localOrSyncableBookmarkModel - accountBookmarkModel:(BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel + accountBookmarkModel: + (LegacyBookmarkModel*)accountBookmarkModel folderNode:(const BookmarkNode*)folder parentFolderNode:(const BookmarkNode*)parentFolder authenticationService:(AuthenticationService*)authService @@ -122,8 +122,9 @@ DCHECK(accountBookmarkModel->loaded()); DCHECK(parentFolder); if (folder) { - BookmarkModel* modelForFolder = bookmark_utils_ios::GetBookmarkModelForNode( - folder, localOrSyncableBookmarkModel, accountBookmarkModel); + LegacyBookmarkModel* modelForFolder = + bookmark_utils_ios::GetBookmarkModelForNode( + folder, localOrSyncableBookmarkModel, accountBookmarkModel); DCHECK(!modelForFolder->is_permanent_node(folder)); } DCHECK(browser); @@ -307,9 +308,10 @@ base::UserMetricsAction("MobileBookmarksFolderEditorDeletedFolder")); std::set<const BookmarkNode*> editedNodes; editedNodes.insert(_folder); - BookmarkModel* modelForFolder = bookmark_utils_ios::GetBookmarkModelForNode( - _folder, _localOrSyncableBookmarkModel.get(), - _accountBookmarkModel.get()); + LegacyBookmarkModel* modelForFolder = + bookmark_utils_ios::GetBookmarkModelForNode( + _folder, _localOrSyncableBookmarkModel.get(), + _accountBookmarkModel.get()); [self.snackbarCommandsHandler showSnackbarMessage:bookmark_utils_ios::DeleteBookmarksWithUndoToast( editedNodes, {modelForFolder}, _browserState)]; @@ -318,7 +320,7 @@ - (void)saveFolder { DCHECK(_parentFolder); - BookmarkModel* modelForParentFolder = + LegacyBookmarkModel* modelForParentFolder = bookmark_utils_ios::GetBookmarkModelForNode( _parentFolder, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); @@ -335,9 +337,10 @@ [self.delegate bookmarksFolderEditorWillCommitTitleChange:self]; } - BookmarkModel* modelForFolder = bookmark_utils_ios::GetBookmarkModelForNode( - _folder, _localOrSyncableBookmarkModel.get(), - _accountBookmarkModel.get()); + LegacyBookmarkModel* modelForFolder = + bookmark_utils_ios::GetBookmarkModelForNode( + _folder, _localOrSyncableBookmarkModel.get(), + _accountBookmarkModel.get()); modelForFolder->SetTitle(_folder, folderTitle, bookmarks::metrics::BookmarkEditSource::kUser); if (_folder->parent() != _parentFolder) { @@ -389,24 +392,24 @@ #pragma mark - BookmarkModelBridgeObserver -- (void)bookmarkModelLoaded:(BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { // The bookmark model is assumed to be loaded when this controller is created. NOTREACHED(); } -- (void)bookmarkModel:(BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const BookmarkNode*)bookmarkNode { if (bookmarkNode == _parentFolder) { [self updateParentFolderState]; } } -- (void)bookmarkModel:(BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const BookmarkNode*)bookmarkNode { // No-op. } -- (void)bookmarkModel:(BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const BookmarkNode*)bookmarkNode fromParent:(const BookmarkNode*)oldParent toParent:(const BookmarkNode*)newParent { @@ -420,7 +423,7 @@ } } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model willDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { if (_folder->HasAncestor(node)) { @@ -439,14 +442,14 @@ } } -- (void)bookmarkModel:(BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const BookmarkNode*)node fromFolder:(const BookmarkNode*)folder { // No-op. Bookmark deletion handled in // `bookmarkModel:willDeleteNode:fromFolder:` } -- (void)bookmarkModelRemovedAllNodes:(BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { if (model->is_permanent_node(_parentFolder)) { return; // The current parent folder is still valid. } @@ -496,7 +499,7 @@ // `accountBookmarkModel` becomes unavailable, this method will cancel folder // editor. Returns whether folder editor was cancelled or not. - (BOOL)cancelIfParentFolderIsUnavailable { - BookmarkModel* parentFolderModel = + LegacyBookmarkModel* parentFolderModel = bookmark_utils_ios::GetBookmarkModelForNode( _parentFolder, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get());
diff --git a/ios/chrome/browser/ui/bookmarks/home/BUILD.gn b/ios/chrome/browser/ui/bookmarks/home/BUILD.gn index 1c2332f..3d6f188 100644 --- a/ios/chrome/browser/ui/bookmarks/home/BUILD.gn +++ b/ios/chrome/browser/ui/bookmarks/home/BUILD.gn
@@ -106,6 +106,7 @@ deps = [ "//base/test:test_support", "//components/bookmarks/browser", + "//ios/chrome/browser/bookmarks/model", "//ios/chrome/browser/bookmarks/model:test_support", "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/browser_state:test_support",
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_coordinator.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_coordinator.mm index ecdaa61..7bd0180a 100644 --- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_coordinator.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_coordinator.mm
@@ -17,7 +17,6 @@ #import "base/strings/sys_string_conversions.h" #import "base/strings/utf_string_conversions.h" #import "base/time/time.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_utils.h" #import "components/signin/public/identity_manager/account_info.h" #import "components/sync/base/features.h" @@ -25,6 +24,7 @@ #import "components/sync/service/sync_service_utils.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/default_browser/model/default_browser_interest_signals.h" #import "ios/chrome/browser/metrics/model/new_tab_page_uma.h" @@ -65,7 +65,6 @@ #import "ios/web/public/web_state.h" #import "ui/base/l10n/l10n_util_mac.h" -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; namespace { @@ -139,9 +138,9 @@ base::WeakPtr<ChromeBrowserState> _browserState; // Profile bookmark model. - base::WeakPtr<bookmarks::BookmarkModel> _localOrSyncableBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _localOrSyncableBookmarkModel; // Account bookmark model. - base::WeakPtr<bookmarks::BookmarkModel> _accountBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _accountBookmarkModel; // Coordinator of manage sync settings. ManageSyncSettingsCoordinator* _manageSyncSettingsCoordinator; } @@ -162,7 +161,7 @@ ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState( _browserState.get()) ->AsWeakPtr(); - BookmarkModel* accountBookmarkModel = + LegacyBookmarkModel* accountBookmarkModel = ios::AccountBookmarkModelFactory::GetForBrowserState( _browserState.get()); if (accountBookmarkModel) {
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h index 9bde7d0..68ff8e29 100644 --- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.h
@@ -14,10 +14,10 @@ @class BookmarkTableCell; @protocol BookmarkTableCellTitleEditing; class Browser; +class LegacyBookmarkModel; @class TableViewModel; namespace bookmarks { -class BookmarkModel; class BookmarkNode; } // namespace bookmarks @@ -57,10 +57,6 @@ BookmarksHomeItemTypeBatchUploadRecommendation, }; -namespace bookmarks { -class BookmarkModel; -} // namespace bookmarks - // BookmarksHomeMediator manages model interactions for the // BookmarksHomeViewController. @interface BookmarksHomeMediator : NSObject @@ -93,7 +89,7 @@ // Bookmark model of the current displayed folder node. If the view is at // the root level, `displayedBookmarkModel` returns the localOrSyncable storage. @property(nonatomic, assign, readonly) - bookmarks::BookmarkModel* displayedBookmarkModel; + LegacyBookmarkModel* displayedBookmarkModel; // Registers the feature preferences. + (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry; @@ -105,8 +101,8 @@ // `BookmarksHomeMediator`. A mediator should not be aware of this class. - (instancetype)initWithBrowser:(Browser*)browser localOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel - accountBookmarkModel:(bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel + accountBookmarkModel:(LegacyBookmarkModel*)accountBookmarkModel displayedNode:(const bookmarks::BookmarkNode*)displayedNode NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @@ -141,7 +137,7 @@ // Returns weather the slashed cloud icon should be displayed for // `bookmarkModel`. - (BOOL)shouldDisplayCloudSlashIconWithBookmarkModel: - (bookmarks::BookmarkModel*)bookmarkModel; + (LegacyBookmarkModel*)bookmarkModel; // Called to update the promo after account settings is closed. - (void)updateReviewSettingsPromo;
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm index 05ccecd..e921d411 100644 --- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_mediator.mm
@@ -10,7 +10,6 @@ #import "base/i18n/message_formatter.h" #import "base/metrics/histogram_functions.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_utils.h" #import "components/bookmarks/browser/titled_url_match.h" #import "components/bookmarks/common/bookmark_features.h" @@ -29,6 +28,7 @@ #import "components/sync/service/sync_user_settings.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" @@ -115,9 +115,9 @@ @implementation BookmarksHomeMediator { // The model holding localOrSyncable bookmark data. - base::WeakPtr<bookmarks::BookmarkModel> _localOrSyncableBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _localOrSyncableBookmarkModel; // The model holding account bookmark data. - base::WeakPtr<bookmarks::BookmarkModel> _accountBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _accountBookmarkModel; // Bridge to register for bookmark changes in the localOrSyncable model. std::unique_ptr<BookmarkModelBridge> _localOrSyncableBookmarkModelBridge; // Bridge to register for bookmark changes in the account model. @@ -133,8 +133,8 @@ - (instancetype)initWithBrowser:(Browser*)browser localOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel - accountBookmarkModel:(bookmarks::BookmarkModel*)accountBookmarkModel + (LegacyBookmarkModel*)localOrSyncableBookmarkModel + accountBookmarkModel:(LegacyBookmarkModel*)accountBookmarkModel displayedNode:(const bookmarks::BookmarkNode*)displayedNode { if ((self = [super init])) { DCHECK(browser); @@ -269,7 +269,7 @@ [self maybeShowBatchUploadSection]; } -- (void)generateTableViewDataForModel:(bookmarks::BookmarkModel*)model +- (void)generateTableViewDataForModel:(LegacyBookmarkModel*)model inSection:(BookmarksHomeSectionIdentifier) sectionIdentifier addManagedBookmarks:(BOOL)addManagedBookmarks { @@ -492,7 +492,7 @@ } - (BOOL)shouldDisplayCloudSlashIconWithBookmarkModel: - (bookmarks::BookmarkModel*)bookmarkModel { + (LegacyBookmarkModel*)bookmarkModel { if (bookmarkModel == _localOrSyncableBookmarkModel.get()) { return bookmark_utils_ios::IsAccountBookmarkStorageOptedIn( self.syncService); @@ -520,7 +520,7 @@ #pragma mark - Properties -- (bookmarks::BookmarkModel*)displayedBookmarkModel { +- (LegacyBookmarkModel*)displayedBookmarkModel { return bookmark_utils_ios::GetBookmarkModelForNode( self.displayedNode, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); @@ -531,12 +531,12 @@ // BookmarkModelBridgeObserver Callbacks // Instances of this class automatically observe the bookmark model. // The bookmark model has loaded. -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { NOTREACHED(); } // The node has changed, but not its children. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { // The root folder changed. Do nothing. if (bookmarkNode == self.displayedNode) { @@ -550,7 +550,7 @@ } // The node has not changed, but its children have. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { // In search mode, we want to refresh any changes (like undo). if (self.currentlyShowingSearchResults) { @@ -578,7 +578,7 @@ } // The node has moved to a new parent folder. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { @@ -589,7 +589,7 @@ } // `node` will be deleted from `folder`. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model willDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { DCHECK(node); @@ -599,18 +599,18 @@ } // `node` was deleted from `folder`. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { [self.consumer refreshContents]; } // All non-permanent nodes have been removed. -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { // TODO(crbug.com/695749) Check if this case is applicable in the new UI. } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeFaviconForNode:(const bookmarks::BookmarkNode*)bookmarkNode { // Only urls have favicons. DCHECK(bookmarkNode->is_url()); @@ -895,7 +895,7 @@ } // Returns whether there are bookmark nodes in `model` that are added by users. -- (BOOL)hasBookmarksOrFoldersInModel:(bookmarks::BookmarkModel*)model { +- (BOOL)hasBookmarksOrFoldersInModel:(LegacyBookmarkModel*)model { // The root node always has its permanent nodes. If all the permanent nodes // are empty, we treat it as if the root itself is empty. const auto& childrenOfRootNode = model->root_node()->children(); @@ -951,7 +951,7 @@ // to `displayCloudSlashIcon`. // Returns the number of added items in the table view model. - (int)populateNodeItemWithQuery:(const bookmarks::QueryFields&)query - bookmarkModel:(bookmarks::BookmarkModel*)model + bookmarkModel:(LegacyBookmarkModel*)model displayCloudSlashIcon:(BOOL)displayCloudSlashIcon { std::vector<const BookmarkNode*> nodes; GetBookmarksMatchingProperties(model, query, kMaxBookmarksSearchResults,
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm index 41dccec..fb841a48 100644 --- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller.mm
@@ -15,7 +15,6 @@ #import "base/numerics/safe_conversions.h" #import "base/ranges/algorithm.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/bookmarks/common/bookmark_metrics.h" #import "components/bookmarks/common/bookmark_pref_names.h" @@ -28,6 +27,7 @@ #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_type.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/bookmarks/model/managed_bookmark_service_factory.h" #import "ios/chrome/browser/default_browser/model/default_browser_interest_signals.h" @@ -221,11 +221,11 @@ @implementation BookmarksHomeViewController { // The localOrSyncable bookmark model used. - base::WeakPtr<bookmarks::BookmarkModel> _localOrSyncableBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _localOrSyncableBookmarkModel; // The Browser in which bookmarks are presented base::WeakPtr<Browser> _browser; // The account bookmark model used. - base::WeakPtr<bookmarks::BookmarkModel> _accountBookmarkModel; + base::WeakPtr<LegacyBookmarkModel> _accountBookmarkModel; // Bridge to register for bookmark changes in the localOrSyncable model. std::unique_ptr<BookmarkModelBridge> _localOrSyncableBookmarkModelBridge; // Bridge to register for bookmark changes in the account model. @@ -342,7 +342,7 @@ cachedFolderID == _localOrSyncableBookmarkModel->root_node()->id()) { return stack; } - base::WeakPtr<bookmarks::BookmarkModel> folderModel; + base::WeakPtr<LegacyBookmarkModel> folderModel; if (modelType == BookmarkModelType::kAccount) { folderModel = _accountBookmarkModel; } else { @@ -860,7 +860,7 @@ userAction:(const char*)userAction { DCHECK_GE(nodes.size(), 1u); base::RecordAction(base::UserMetricsAction(userAction)); - std::vector<bookmarks::BookmarkModel*> models = { + std::vector<LegacyBookmarkModel*> models = { _localOrSyncableBookmarkModel.get()}; if (_accountBookmarkModel.get()) { models.push_back(_accountBookmarkModel.get()); @@ -1270,7 +1270,7 @@ #pragma mark - BookmarkModelBridgeObserver -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { if (!AreAllAvailableBookmarkModelsLoaded(_browserState)) { return; } @@ -1334,24 +1334,24 @@ }]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { // No-op here. Bookmarks might be refreshed in BookmarksHomeMediator. } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { // No-op here. Bookmarks might be refreshed in BookmarksHomeMediator. } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { // No-op here. Bookmarks might be refreshed in BookmarksHomeMediator. } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { if (self.displayedFolderNode == node) { @@ -1359,7 +1359,7 @@ } } -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { // No-op } @@ -1391,7 +1391,7 @@ // Returns a bookmark node reference for `bookmarkNode`. - (BookmarkNodeReference)bookmarkNodeReferenceWithNode: (const bookmarks::BookmarkNode*)bookmarkNode { - bookmarks::BookmarkModel* bookmarkModel = + LegacyBookmarkModel* bookmarkModel = bookmark_utils_ios::GetBookmarkModelForNode( bookmarkNode, _localOrSyncableBookmarkModel.get(), _accountBookmarkModel.get()); @@ -1525,7 +1525,7 @@ self.mediator.addingNewFolder = YES; std::u16string folderTitle = l10n_util::GetStringUTF16(IDS_IOS_BOOKMARK_NEW_GROUP_DEFAULT_NAME); - bookmarks::BookmarkModel* displayedBookmarkModel = + LegacyBookmarkModel* displayedBookmarkModel = self.mediator.displayedBookmarkModel; self.mediator.editingFolderNode = displayedBookmarkModel->AddFolder( self.mediator.displayedNode,
diff --git a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm index 82ac75e..0784681 100644 --- a/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/bookmarks/home/bookmarks_home_view_controller_unittest.mm
@@ -6,10 +6,10 @@ #import "base/test/metrics/user_action_tester.h" #import "base/test/scoped_feature_list.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_features.h" #import "components/sync/base/features.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" #import "ios/chrome/browser/shared/public/commands/application_commands.h"
diff --git a/ios/chrome/browser/ui/browser_view/key_commands_provider.mm b/ios/chrome/browser/ui/browser_view/key_commands_provider.mm index 7e34b30..6622e09 100644 --- a/ios/chrome/browser/ui/browser_view/key_commands_provider.mm +++ b/ios/chrome/browser/ui/browser_view/key_commands_provider.mm
@@ -9,10 +9,10 @@ #import "base/memory/weak_ptr.h" #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/prefs/pref_service.h" #import "components/sessions/core/tab_restore_service_helper.h" #import "components/strings/grit/components_strings.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/find_in_page/model/abstract_find_tab_helper.h" #import "ios/chrome/browser/ntp/model/new_tab_page_util.h"
diff --git a/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm b/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm index 918488e8..d853bb7a 100644 --- a/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/key_commands_provider_unittest.mm
@@ -7,12 +7,12 @@ #import "base/memory/raw_ptr.h" #import "base/test/metrics/user_action_tester.h" #import "base/test/task_environment.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/common/bookmark_metrics.h" #import "components/bookmarks/test/bookmark_test_helpers.h" #import "components/policy/core/common/policy_pref_names.h" #import "components/sync_preferences/testing_pref_service_syncable.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/find_in_page/model/find_tab_helper.h" #import "ios/chrome/browser/find_in_page/model/java_script_find_tab_helper.h"
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_presenter.mm index e01e795..4f1f3b2d 100644 --- a/ios/chrome/browser/ui/bubble/bubble_presenter.mm +++ b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
@@ -159,6 +159,7 @@ } - (void)hideAllHelpBubbles { + [self.sharePageIPHBubblePresenter dismissAnimated:NO]; [self.openNewTabIPHBubblePresenter dismissAnimated:NO]; [self.tabGridIPHBubblePresenter dismissAnimated:NO]; [self.bottomToolbarTipBubblePresenter dismissAnimated:NO];
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm index 4d40aeb..c38164a 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
@@ -67,6 +67,8 @@ // For example, tapping on a button both dismisses the bubble and triggers the // button's action. @property(nonatomic, strong) UITapGestureRecognizer* outsideBubbleTapRecognizer; +// The pan gesture recognizer to dismiss the bubble on scrolling events. +@property(nonatomic, strong) UIPanGestureRecognizer* outsideBubblePanRecognizer; // The swipe gesture recognizer to dismiss the bubble on swipes. @property(nonatomic, strong) UISwipeGestureRecognizer* swipeRecognizer; // The direction the underlying BubbleView's arrow is pointing. @@ -124,6 +126,13 @@ action:@selector(tapOutsideBubbleRecognized:)]; _outsideBubbleTapRecognizer.delegate = self; _outsideBubbleTapRecognizer.cancelsTouchesInView = NO; + + _outsideBubblePanRecognizer = [[UIPanGestureRecognizer alloc] + initWithTarget:self + action:@selector(tapOutsideBubbleRecognized:)]; + _outsideBubblePanRecognizer.delegate = self; + _outsideBubblePanRecognizer.cancelsTouchesInView = NO; + _insideBubbleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapInsideBubbleRecognized:)]; @@ -205,6 +214,7 @@ [self.bubbleViewController.view addGestureRecognizer:self.insideBubbleTapRecognizer]; [parentView addGestureRecognizer:self.outsideBubbleTapRecognizer]; + [parentView addGestureRecognizer:self.outsideBubblePanRecognizer]; [parentView addGestureRecognizer:self.swipeRecognizer]; self.bubbleDismissalTimer = [NSTimer @@ -281,6 +291,8 @@ removeGestureRecognizer:self.insideBubbleTapRecognizer]; [self.outsideBubbleTapRecognizer.view removeGestureRecognizer:self.outsideBubbleTapRecognizer]; + [self.outsideBubblePanRecognizer.view + removeGestureRecognizer:self.outsideBubblePanRecognizer]; [self.swipeRecognizer.view removeGestureRecognizer:self.swipeRecognizer]; [self.bubbleViewController dismissAnimated:animated]; self.presenting = NO; @@ -309,6 +321,8 @@ removeGestureRecognizer:self.insideBubbleTapRecognizer]; [self.outsideBubbleTapRecognizer.view removeGestureRecognizer:self.outsideBubbleTapRecognizer]; + [self.outsideBubblePanRecognizer.view + removeGestureRecognizer:self.outsideBubblePanRecognizer]; [self.swipeRecognizer.view removeGestureRecognizer:self.swipeRecognizer]; } @@ -317,10 +331,11 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer: (UIGestureRecognizer*)otherGestureRecognizer { - // Allow swipeRecognizer and outsideBubbleTapRecognizer to be triggered at the + // Allow certain types of `gestureRecognizer` to be triggered at the // same time as other gesture recognizers. return gestureRecognizer == self.swipeRecognizer || - gestureRecognizer == self.outsideBubbleTapRecognizer; + gestureRecognizer == self.outsideBubbleTapRecognizer || + gestureRecognizer == self.outsideBubblePanRecognizer; } - (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer @@ -367,7 +382,10 @@ } // Invoked by tapping outside the bubble. Dismisses the bubble. -- (void)tapOutsideBubbleRecognized:(UITapGestureRecognizer*)sender { +- (void)tapOutsideBubbleRecognized:(UIGestureRecognizer*)sender { + if (sender.numberOfTouches <= 0) { + return; + } CGPoint touchLocation = [sender locationOfTouch:0 inView:self.parentView]; IPHDismissalReasonType reasonType = IPHDismissalReasonType::kUnknown; if (CGRectContainsPoint(_anchorViewFrame, touchLocation)) {
diff --git a/ios/chrome/browser/ui/first_run/first_run_egtest.mm b/ios/chrome/browser/ui/first_run/first_run_egtest.mm index 5bdcc142..3d27082 100644 --- a/ios/chrome/browser/ui/first_run/first_run_egtest.mm +++ b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
@@ -459,7 +459,7 @@ (testHistorySyncShownWithoutMinorModeRestrictions)] || [self isRunningTest:@selector - (testHistorySyncShownWithEquallyWeightedButtonsOnCapabilitiesFetchTimeout + (DISABLED_testHistorySyncShownWithEquallyWeightedButtonsOnCapabilitiesFetchTimeout )]) { config.features_enabled.push_back( switches::kMinorModeRestrictionsForHistorySyncOptIn); @@ -1267,10 +1267,12 @@ assertWithMatcher:grey_sufficientlyVisible()]; } +// TODO(b/327221052): Set up the fake identity without value for the capability +// CanShowHistorySyncOptInsWithoutMinorModeRestrictions. // Tests that the History Sync Opt-In screen will have equally weighted button // for users with unknown minor mode restrictions status. - (void) - testHistorySyncShownWithEquallyWeightedButtonsOnCapabilitiesFetchTimeout { + DISABLED_testHistorySyncShownWithEquallyWeightedButtonsOnCapabilitiesFetchTimeout { // Add identity without specifiying capabilities. FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1]; [SigninEarlGrey addFakeIdentity:fakeIdentity];
diff --git a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm index 67b4e9b..1ab14eb 100644 --- a/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm +++ b/ios/chrome/browser/ui/omnibox/chrome_omnibox_client_ios.mm
@@ -23,6 +23,7 @@ #import "ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.h" #import "ios/chrome/browser/autocomplete/model/shortcuts_backend_factory.h" #import "ios/chrome/browser/bookmarks/model/bookmarks_utils.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/default_browser/model/utils.h" #import "ios/chrome/browser/https_upgrades/model/https_upgrade_service_factory.h"
diff --git a/ios/chrome/browser/ui/page_info/page_info_coordinator.mm b/ios/chrome/browser/ui/page_info/page_info_coordinator.mm index 1399d7f..9ace20d 100644 --- a/ios/chrome/browser/ui/page_info/page_info_coordinator.mm +++ b/ios/chrome/browser/ui/page_info/page_info_coordinator.mm
@@ -61,7 +61,11 @@ self.viewController.pageInfoPresentationHandler = self; self.navigationController = - [[TableViewNavigationController alloc] initWithTable:self.viewController]; + IsRevampPageInfoIosEnabled() + ? [[UINavigationController alloc] + initWithRootViewController:self.viewController] + : [[TableViewNavigationController alloc] + initWithTable:self.viewController]; self.navigationController.modalPresentationStyle = UIModalPresentationFormSheet; self.navigationController.presentationController.delegate =
diff --git a/ios/chrome/browser/ui/page_info/page_info_security_egtest.mm b/ios/chrome/browser/ui/page_info/page_info_security_egtest.mm index 876318a3..8d20598 100644 --- a/ios/chrome/browser/ui/page_info/page_info_security_egtest.mm +++ b/ios/chrome/browser/ui/page_info/page_info_security_egtest.mm
@@ -124,9 +124,8 @@ // Check that the navigation bar has both the security's page title and the // page URL. - [[EarlGrey - selectElementWithMatcher:grey_text(l10n_util::GetNSString( - IDS_IOS_PAGE_INFO_CONNECTION_SECURITY))] + [[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString( + IDS_IOS_PAGE_INFO_SECURITY))] assertWithMatcher:grey_sufficientlyVisible()]; [[EarlGrey selectElementWithMatcher: grey_text([NSString
diff --git a/ios/chrome/browser/ui/page_info/page_info_security_view_controller.mm b/ios/chrome/browser/ui/page_info/page_info_security_view_controller.mm index 0cf8d0a9..db30a22f 100644 --- a/ios/chrome/browser/ui/page_info/page_info_security_view_controller.mm +++ b/ios/chrome/browser/ui/page_info/page_info_security_view_controller.mm
@@ -54,7 +54,7 @@ [super viewDidLoad]; CHECK(!_pageInfoSecurityDescription.isEmpty); - self.title = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_CONNECTION_SECURITY); + self.title = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_SECURITY); self.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayModeNever; self.navigationItem.prompt = _pageInfoSecurityDescription.siteURL;
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h index 88571fa..0c8ee035 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h
@@ -11,9 +11,6 @@ #import "ios/chrome/browser/ui/browser_container/browser_container_consumer.h" #import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift.h" -namespace bookmarks { -class BookmarkModel; -} namespace feature_engagement { class Tracker; } @@ -26,7 +23,6 @@ @protocol ActivityServiceCommands; @protocol ApplicationCommands; -@protocol SettingsCommands; class AuthenticationService; @protocol BookmarksCommands; @protocol BrowserCoordinatorCommands; @@ -34,6 +30,7 @@ @protocol FindInPageCommands; class FollowBrowserAgent; @protocol HelpCommands; +class LegacyBookmarkModel; @protocol OverflowMenuCustomizationCommands; @class OverflowMenuOrderer; class OverlayPresenter; @@ -44,6 +41,7 @@ class PromosManager; class ReadingListBrowserAgent; class ReadingListModel; +@protocol SettingsCommands; class TabBasedIPHBrowserAgent; @protocol TextZoomCommands; class WebNavigationBrowserAgent; @@ -89,9 +87,8 @@ @property(nonatomic, weak) UIViewController* baseViewController; // Bookmarks models to know if the page is bookmarked. -@property(nonatomic, assign) - bookmarks::BookmarkModel* localOrSyncableBookmarkModel; -@property(nonatomic, assign) bookmarks::BookmarkModel* accountBookmarkModel; +@property(nonatomic, assign) LegacyBookmarkModel* localOrSyncableBookmarkModel; +@property(nonatomic, assign) LegacyBookmarkModel* accountBookmarkModel; // Readinglist model to know if model has finished loading. @property(nonatomic, assign) ReadingListModel* readingListModel;
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm index e6a4cf7..3f17541 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
@@ -10,7 +10,6 @@ #import "base/metrics/user_metrics_action.h" #import "base/strings/sys_string_conversions.h" #import "base/strings/utf_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_pref_names.h" #import "components/feature_engagement/public/event_constants.h" #import "components/feature_engagement/public/feature_constants.h" @@ -30,6 +29,7 @@ #import "components/translate/core/browser/translate_manager.h" #import "components/translate/core/browser/translate_prefs.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/commerce/model/push_notification/push_notification_feature.h" #import "ios/chrome/browser/default_browser/model/default_browser_interest_signals.h" #import "ios/chrome/browser/default_browser/model/utils.h" @@ -134,8 +134,8 @@ // Uses `IsBookmarked` to check whether `url` is bookmarked in any of the // provided bookmark models. `account_model` can be null. bool IsBookmarked(const GURL& url, - bookmarks::BookmarkModel* local_model, - bookmarks::BookmarkModel* account_model) { + LegacyBookmarkModel* local_model, + LegacyBookmarkModel* account_model) { CHECK(local_model); if (local_model->IsBookmarked(url)) { return true; @@ -368,7 +368,7 @@ } - (void)setLocalOrSyncableBookmarkModel: - (bookmarks::BookmarkModel*)localOrSyncableBookmarkModel { + (LegacyBookmarkModel*)localOrSyncableBookmarkModel { _localOrSyncableBookmarkModelBridge.reset(); _localOrSyncableBookmarkModel = localOrSyncableBookmarkModel; @@ -381,8 +381,7 @@ [self updateModel]; } -- (void)setAccountBookmarkModel: - (bookmarks::BookmarkModel*)accountBookmarkModel { +- (void)setAccountBookmarkModel:(LegacyBookmarkModel*)accountBookmarkModel { _accountBookmarkModelBridge.reset(); _accountBookmarkModel = accountBookmarkModel; @@ -1617,33 +1616,33 @@ // If an added or removed bookmark is the same as the current url, update the // toolbar so the star highlight is kept in sync. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { [self updateModel]; } // If all bookmarks are removed, update the toolbar so the star highlight is // kept in sync. -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { [self updateModel]; } // In case we are on a bookmarked page before the model is loaded. -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { [self updateModel]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { [self updateModel]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { // No-op -- required by BookmarkModelBridgeObserver but not used. } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { [self updateModel];
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm index b5cec7e..e3e5c94e 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator_unittest.mm
@@ -12,7 +12,6 @@ #import "base/test/metrics/histogram_tester.h" #import "base/test/scoped_feature_list.h" #import "base/time/default_clock.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_utils.h" #import "components/bookmarks/common/bookmark_pref_names.h" #import "components/bookmarks/test/bookmark_test_helpers.h" @@ -39,6 +38,7 @@ #import "components/translate/core/browser/translate_prefs.h" #import "components/translate/core/language_detection/language_detection_model.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/overlays/model/public/overlay_presenter.h" #import "ios/chrome/browser/overlays/model/public/overlay_request.h" @@ -97,7 +97,6 @@ #import "testing/platform_test.h" #import "ui/base/device_form_factor.h" -using bookmarks::BookmarkModel; using sync_preferences::PrefServiceMockFactory; using sync_preferences::PrefServiceSyncable; using testing::Return; @@ -437,8 +436,8 @@ OverflowMenuModel* model_; OverflowMenuMediator* mediator_; OverflowMenuOrderer* orderer_; - raw_ptr<BookmarkModel> local_or_syncable_bookmark_model_; - raw_ptr<BookmarkModel> account_bookmark_model_; + raw_ptr<LegacyBookmarkModel> local_or_syncable_bookmark_model_; + raw_ptr<LegacyBookmarkModel> account_bookmark_model_; raw_ptr<ReadingListModel> reading_list_model_; std::unique_ptr<TestingPrefServiceSimple> browserStatePrefs_; std::unique_ptr<TestingPrefServiceSimple> localStatePrefs_;
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h index 3f589f7..62d6597 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.h
@@ -11,14 +11,13 @@ #import "ios/chrome/browser/ui/popup_menu/popup_menu_action_handler_delegate.h" #import "ios/chrome/browser/ui/popup_menu/public/popup_menu_ui_updating.h" -namespace bookmarks { -class BookmarkModel; -} namespace feature_engagement { class Tracker; -} +} // namespace feature_engagement + class BrowserPolicyConnectorIOS; class FollowBrowserAgent; +class LegacyBookmarkModel; @protocol LensCommands; class OverlayPresenter; @protocol PopupMenuConsumer; @@ -62,7 +61,7 @@ // object. @property(nonatomic, assign) feature_engagement::Tracker* engagementTracker; // The bookmarks model to know if the page is bookmarked. -@property(nonatomic, assign) bookmarks::BookmarkModel* bookmarkModel; +@property(nonatomic, assign) LegacyBookmarkModel* bookmarkModel; // Pref service to retrieve preference values. @property(nonatomic, assign) PrefService* prefService; // The template url service to use for checking whether search by image is
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm index bfb894aa..c420875 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -13,7 +13,6 @@ #import "base/metrics/user_metrics.h" #import "base/metrics/user_metrics_action.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_pref_names.h" #import "components/feature_engagement/public/feature_constants.h" #import "components/feature_engagement/public/tracker.h" @@ -28,6 +27,7 @@ #import "components/translate/core/browser/translate_manager.h" #import "components/translate/core/browser/translate_prefs.h" #import "ios/chrome/browser/bookmarks/model/bookmark_model_bridge_observer.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/commerce/model/push_notification/push_notification_feature.h" #import "ios/chrome/browser/find_in_page/model/abstract_find_tab_helper.h" #import "ios/chrome/browser/follow/model/follow_browser_agent.h" @@ -358,34 +358,34 @@ // If an added or removed bookmark is the same as the current url, update the // toolbar so the star highlight is kept in sync. -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeChildrenForNode:(const bookmarks::BookmarkNode*)bookmarkNode { [self updateBookmarkItem]; } // If all bookmarks are removed, update the toolbar so the star highlight is // kept in sync. -- (void)bookmarkModelRemovedAllNodes:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelRemovedAllNodes:(LegacyBookmarkModel*)model { [self updateBookmarkItem]; } // In case we are on a bookmarked page before the model is loaded. -- (void)bookmarkModelLoaded:(bookmarks::BookmarkModel*)model { +- (void)bookmarkModelLoaded:(LegacyBookmarkModel*)model { [self updateBookmarkItem]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didChangeNode:(const bookmarks::BookmarkNode*)bookmarkNode { [self updateBookmarkItem]; } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didMoveNode:(const bookmarks::BookmarkNode*)bookmarkNode fromParent:(const bookmarks::BookmarkNode*)oldParent toParent:(const bookmarks::BookmarkNode*)newParent { // No-op -- required by BookmarkModelBridgeObserver but not used. } -- (void)bookmarkModel:(bookmarks::BookmarkModel*)model +- (void)bookmarkModel:(LegacyBookmarkModel*)model didDeleteNode:(const bookmarks::BookmarkNode*)node fromFolder:(const bookmarks::BookmarkNode*)folder { [self updateBookmarkItem]; @@ -508,7 +508,7 @@ } } -- (void)setBookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel { +- (void)setBookmarkModel:(LegacyBookmarkModel*)bookmarkModel { _bookmarkModel = bookmarkModel; _bookmarkModelBridge.reset(); if (bookmarkModel) {
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm index 610e65d..4b2dc80 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm
@@ -11,7 +11,6 @@ #import "base/strings/sys_string_conversions.h" #import "base/test/scoped_feature_list.h" #import "base/time/default_clock.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_utils.h" #import "components/bookmarks/common/bookmark_pref_names.h" #import "components/bookmarks/test/bookmark_test_helpers.h" @@ -27,6 +26,7 @@ #import "components/translate/core/browser/translate_pref_names.h" #import "components/translate/core/browser/translate_prefs.h" #import "components/translate/core/language_detection/language_detection_model.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/overlays/model/public/overlay_presenter.h" #import "ios/chrome/browser/overlays/model/public/overlay_request.h" @@ -69,8 +69,6 @@ #import "third_party/ocmock/gtest_support.h" #import "ui/base/device_form_factor.h" -using bookmarks::BookmarkModel; - @interface FakePopupMenuConsumer : NSObject <PopupMenuConsumer> @property(nonatomic, strong) NSArray<NSArray<TableViewItem<PopupMenuItem>*>*>* popupMenuItems; @@ -302,7 +300,7 @@ FakeOverlayPresentationContext presentation_context_; PopupMenuMediator* mediator_; - raw_ptr<BookmarkModel> bookmark_model_; + raw_ptr<LegacyBookmarkModel> bookmark_model_; raw_ptr<ReadingListModel> reading_list_model_; std::unique_ptr<TestingPrefServiceSimple> prefs_; raw_ptr<web::FakeWebState> web_state_;
diff --git a/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm b/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm index 97cde08..5f12250 100644 --- a/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm +++ b/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator.mm
@@ -9,7 +9,6 @@ #import "base/metrics/histogram_functions.h" #import "base/strings/string_number_conversions.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/commerce/core/commerce_constants.h" #import "components/commerce/core/price_tracking_utils.h" #import "components/commerce/core/shopping_service.h" @@ -19,6 +18,7 @@ #import "components/power_bookmarks/core/proto/power_bookmark_meta.pb.h" #import "components/power_bookmarks/core/proto/shopping_specifics.pb.h" #import "components/sync/base/features.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/push_notification/model/push_notification_client_id.h" #import "ios/chrome/browser/push_notification/model/push_notification_service.h" #import "ios/chrome/browser/push_notification/model/push_notification_util.h"
diff --git a/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator_unittest.mm b/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator_unittest.mm index 2a2cc808..65f0911 100644 --- a/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator_unittest.mm +++ b/ios/chrome/browser/ui/price_notifications/price_notifications_price_tracking_mediator_unittest.mm
@@ -9,7 +9,6 @@ #import "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #import "base/test/scoped_feature_list.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/test/bookmark_test_helpers.h" #import "components/commerce/core/mock_shopping_service.h" #import "components/commerce/core/price_tracking_utils.h" @@ -19,6 +18,7 @@ #import "components/power_bookmarks/core/power_bookmark_utils.h" #import "components/sync/base/features.h" #import "ios/chrome/browser/bookmarks/model/account_bookmark_model_factory.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/commerce/model/shopping_service_factory.h" #import "ios/chrome/browser/push_notification/model/push_notification_service.h"
diff --git a/ios/chrome/browser/ui/price_notifications/price_notifications_view_coordinator.mm b/ios/chrome/browser/ui/price_notifications/price_notifications_view_coordinator.mm index c9bdd57..6a2cb90 100644 --- a/ios/chrome/browser/ui/price_notifications/price_notifications_view_coordinator.mm +++ b/ios/chrome/browser/ui/price_notifications/price_notifications_view_coordinator.mm
@@ -10,6 +10,7 @@ #import "base/strings/sys_string_conversions.h" #import "components/image_fetcher/core/image_data_fetcher.h" #import "components/prefs/pref_service.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/commerce/model/shopping_service_factory.h" #import "ios/chrome/browser/push_notification/model/push_notification_service.h"
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h index 821aa82..859931a 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h
@@ -46,8 +46,6 @@ AdvancedSettingsSectionIdentifier, // Sync errors. SyncErrorsSectionIdentifier, - // Section to show the signed-in account. - AccountSectionIdentifier, // Section to show the batch upload option. BatchUploadSectionIdentifier, }; @@ -103,9 +101,6 @@ SyncDisabledByAdministratorErrorItemType, // Indicates the errors related to the signed in not syncing account. AccountErrorMessageItemType, - // AccountSectionIdentifier section. - // Item for the signed in identity. - IdentityAccountItemType, // BatchUploadSectionIdentifier section. // Item for the batch upload button. BatchUploadButtonItemType,
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_consumer.h b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_consumer.h index 9aaf077..2571efa 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_consumer.h +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_consumer.h
@@ -31,6 +31,11 @@ // Reloads `sections`. Does nothing if the model is not loaded yet. - (void)reloadSections:(NSIndexSet*)sections; +// Updates the primary account details. +- (void)updatePrimaryAccountWithAvatarImage:(UIImage*)avatarImage + name:(NSString*)name + email:(NSString*)email; + @end #endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_MANAGE_SYNC_SETTINGS_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm index 03e4c893..a837ab8 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
@@ -170,14 +170,9 @@ self.authService->GetServiceStatus() == AuthenticationService::ServiceStatus::SigninForcedByPolicy; - // For kSignedIn state the view will include the account details item with a - // transparent background, InsetGrouped should be used in this case to prevent - // grey lines from showing around this item with large fonts. - UITableViewStyle style = _accountState == SyncSettingsAccountState::kSignedIn - ? UITableViewStyleInsetGrouped - : ChromeTableViewStyle(); ManageSyncSettingsTableViewController* viewController = - [[ManageSyncSettingsTableViewController alloc] initWithStyle:style]; + [[ManageSyncSettingsTableViewController alloc] + initWithStyle:ChromeTableViewStyle()]; self.viewController = viewController; NSString* title = self.mediator.overrideViewControllerTitle;
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm index c06d53cc..dfd9b37 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
@@ -47,7 +47,7 @@ #import "ios/chrome/browser/sync/model/enterprise_utils.h" #import "ios/chrome/browser/sync/model/sync_observer_bridge.h" #import "ios/chrome/browser/sync/model/sync_setup_service.h" -#import "ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.h" +#import "ios/chrome/browser/ui/authentication/cells/central_account_view.h" #import "ios/chrome/browser/ui/authentication/history_sync/history_sync_utils.h" #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h" #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h" @@ -169,6 +169,12 @@ signin::ConsentLevel::kSignin); _prefService = prefService; _initialAccountState = initialAccountState; + // Register for font size change notifications + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(preferredContentSizeChanged:) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; } return self; } @@ -182,6 +188,7 @@ _accountManagerServiceObserver.reset(); _prefService = nullptr; _signedInIdentity = nil; + [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)autofillAlertConfirmed:(BOOL)value { @@ -202,31 +209,6 @@ #pragma mark - Loads sync data type section -// Loads the centered identity account section. -- (void)loadIdentityAccountSection { - TableViewModel* model = self.consumer.tableViewModel; - switch (self.syncAccountState) { - case SyncSettingsAccountState::kSignedOut: - case SyncSettingsAccountState::kSyncing: - case SyncSettingsAccountState::kAdvancedInitialSyncSetup: - return; - case SyncSettingsAccountState::kSignedIn: - [model addSectionWithIdentifier:AccountSectionIdentifier]; - CHECK(_signedInIdentity); - TableViewCentralAccountItem* identityAccountItem = - [[TableViewCentralAccountItem alloc] - initWithType:IdentityAccountItemType]; - identityAccountItem.avatarImage = - _chromeAccountManagerService->GetIdentityAvatarWithIdentity( - _signedInIdentity, IdentityAvatarSize::Large); - identityAccountItem.name = _signedInIdentity.userFullName; - identityAccountItem.email = _signedInIdentity.userEmail; - [model addItem:identityAccountItem - toSectionWithIdentifier:AccountSectionIdentifier]; - break; - } -} - // Loads the sync data type section. - (void)loadSyncDataTypeSection { TableViewModel* model = self.consumer.tableViewModel; @@ -338,27 +320,22 @@ } } -- (void)updateIdentityAccountSection { - if (![self.consumer.tableViewModel - hasItemForItemType:IdentityAccountItemType - sectionIdentifier:AccountSectionIdentifier]) { - return; +// Updates the consumer when the primary account is updated. +- (void)updatePrimaryAccountDetails { + switch (self.syncAccountState) { + case SyncSettingsAccountState::kSignedOut: + case SyncSettingsAccountState::kSyncing: + case SyncSettingsAccountState::kAdvancedInitialSyncSetup: + return; + case SyncSettingsAccountState::kSignedIn: + [self.consumer + updatePrimaryAccountWithAvatarImage: + _chromeAccountManagerService->GetIdentityAvatarWithIdentity( + _signedInIdentity, IdentityAvatarSize::Large) + name:_signedInIdentity.userFullName + email:_signedInIdentity.userEmail]; + break; } - - NSIndexPath* accountCellIndexPath = [self.consumer.tableViewModel - indexPathForItemType:IdentityAccountItemType - sectionIdentifier:AccountSectionIdentifier]; - TableViewCentralAccountItem* identityAccountItem = - base::apple::ObjCCast<TableViewCentralAccountItem>( - [self.consumer.tableViewModel itemAtIndexPath:accountCellIndexPath]); - CHECK(identityAccountItem); - CHECK(_signedInIdentity); - identityAccountItem.avatarImage = - _chromeAccountManagerService->GetIdentityAvatarWithIdentity( - _signedInIdentity, IdentityAvatarSize::Large); - identityAccountItem.name = _signedInIdentity.userFullName; - identityAccountItem.email = _signedInIdentity.userEmail; - [self.consumer reloadItem:identityAccountItem]; } // Updates all the sync data type items, and notify the consumer if @@ -835,16 +812,16 @@ TableViewModel* model = self.consumer.tableViewModel; DCHECK(![model hasSectionForSectionIdentifier:SyncErrorsSectionIdentifier]); - // During some signout flows, it can happen that the Account section doesn't - // exist at this point. In that case, there's nothing to update here. - if (![model hasSectionForSectionIdentifier:AccountSectionIdentifier]) { - return; + switch (self.syncAccountState) { + case SyncSettingsAccountState::kSignedOut: + case SyncSettingsAccountState::kSyncing: + case SyncSettingsAccountState::kAdvancedInitialSyncSetup: + return; + case SyncSettingsAccountState::kSignedIn: + break; } - NSInteger previousSection = - [model sectionForSectionIdentifier:AccountSectionIdentifier]; - DCHECK_NE(NSNotFound, previousSection); - NSInteger batchUploadSectionIndex = previousSection + 1; + NSInteger batchUploadSectionIndex = 0; BOOL batchUploadSectionAlreadyExists = self.batchUploadItem; if (!batchUploadSectionAlreadyExists) { @@ -972,6 +949,11 @@ } } +// Updates the consumer when the content size is updated. +- (void)preferredContentSizeChanged:(NSNotification*)notification { + [self updatePrimaryAccountDetails]; +} + #pragma mark - Properties - (BOOL)disabledBecauseOfSyncError { @@ -1052,7 +1034,6 @@ // closing and should not re-load the model. return; } - [self loadIdentityAccountSection]; [self loadSyncErrorsSection]; [self loadBatchUploadSection]; [self loadSyncDataTypeSection]; @@ -1060,6 +1041,9 @@ [self loadAdvancedSettingsSection]; [self loadSignOutAndManageAccountsSection]; [self fetchLocalDataDescriptionsForBatchUploadWithFirstLoad:YES]; + // Loading the header asks the consumer to reload the data, so it should be + // done after all sections are initially loaded. + [self updatePrimaryAccountDetails]; } #pragma mark - SyncObserverModelBridge @@ -1086,7 +1070,7 @@ case signin::PrimaryAccountChangeEvent::Type::kSet: _signedInIdentity = _authenticationService->GetPrimaryIdentity( signin::ConsentLevel::kSignin); - [self updateIdentityAccountSection]; + [self updatePrimaryAccountDetails]; break; case signin::PrimaryAccountChangeEvent::Type::kCleared: // Temporary state, we can ignore this event, until the UI is signed out. @@ -1099,7 +1083,7 @@ - (void)identityUpdated:(id<SystemIdentity>)identity { if ([_signedInIdentity isEqual:identity]) { - [self updateIdentityAccountSection]; + [self updatePrimaryAccountDetails]; [self updateSyncItemsNotifyConsumer:YES]; [self updateSyncErrorsSection:YES]; [self updateBatchUploadSectionWithNotifyConsumer:YES firstLoad:NO]; @@ -1213,7 +1197,6 @@ case SyncDisabledByAdministratorErrorItemType: case SignOutItemFooterType: case TypesListHeaderOrFooterType: - case IdentityAccountItemType: case AccountErrorMessageItemType: case BatchUploadButtonItemType: case BatchUploadRecommendationItemType: @@ -1293,7 +1276,6 @@ case SyncDisabledByAdministratorErrorItemType: case SignOutItemFooterType: case TypesListHeaderOrFooterType: - case IdentityAccountItemType: case AccountErrorMessageItemType: case BatchUploadRecommendationItemType: // Nothing to do. @@ -1470,10 +1452,7 @@ [self createSyncErrorIconItemWithItemType:type.value()]; } - NSInteger syncErrorSectionIndex = - self.syncAccountState == SyncSettingsAccountState::kSignedIn - ? [model sectionForSectionIdentifier:AccountSectionIdentifier] + 1 - : 0; + NSInteger syncErrorSectionIndex = 0; if (!errorSectionAlreadyExists) { if (self.syncAccountState == SyncSettingsAccountState::kSignedIn && type.value() != SyncDisabledByAdministratorErrorItemType) {
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm index 2925dd2..18c01bc0 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator_unittest.mm
@@ -34,7 +34,7 @@ #import "ios/chrome/browser/sync/model/sync_service_factory.h" #import "ios/chrome/browser/sync/model/sync_setup_service_factory.h" #import "ios/chrome/browser/sync/model/sync_setup_service_mock.h" -#import "ios/chrome/browser/ui/authentication/cells/table_view_central_account_item.h" +#import "ios/chrome/browser/ui/authentication/cells/central_account_view.h" #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h" #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h" #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_constants.h" @@ -445,32 +445,6 @@ } } -// Tests that the account details item is showing for a signed in not syncing -// account. -TEST_F(ManageSyncSettingsMediatorTest, - CheckAccountItemForSignedInNotSyncingAccount) { - CreateManageSyncSettingsMediator(SyncSettingsAccountState::kSignedIn); - SimulateFirstSetupSyncOffWithSignedInAccount(); - - // Loads the Sync page. - [mediator_ manageSyncSettingsTableViewControllerLoadModel:mediator_.consumer]; - - // Get account item. - NSArray* account_item = [mediator_.consumer.tableViewModel - itemsInSectionWithIdentifier:AccountSectionIdentifier]; - - EXPECT_EQ(1UL, account_item.count); - - TableViewCentralAccountItem* account_details = - base::apple::ObjCCastStrict<TableViewCentralAccountItem>(account_item[0]); - - EXPECT_EQ(account_details.type, - SyncSettingsItemType::IdentityAccountItemType); - EXPECT_TRUE(account_details.avatarImage); - EXPECT_NSEQ(account_details.name, fakeSystemIdentity_.userFullName); - EXPECT_NSEQ(account_details.email, fakeSystemIdentity_.userEmail); -} - // Tests that the sign out item exists in the SignOutSectionIdentifier for a // signed in not syncing account along with manage accounts items. TEST_F(ManageSyncSettingsMediatorTest, @@ -550,7 +524,7 @@ hasSectionForSectionIdentifier:SyncSettingsSectionIdentifier:: SignOutSectionIdentifier]); // Verify the number of section shown in the kSignedIn state. - ASSERT_EQ(4, [mediator_.consumer.tableViewModel numberOfSections]); + ASSERT_EQ(3, [mediator_.consumer.tableViewModel numberOfSections]); // Set sign out expectation with empty account info. ON_CALL(*sync_service_mock_, GetAccountInfo()) @@ -567,5 +541,5 @@ // Expected sections from the previous kSignedIn state should be showing and // no new sections are added in the kSignedOut state. - EXPECT_EQ(4, [mediator_.consumer.tableViewModel numberOfSections]); + EXPECT_EQ(3, [mediator_.consumer.tableViewModel numberOfSections]); }
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_table_view_controller.mm index d18a39d..fa90d9d5 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_table_view_controller.mm
@@ -6,9 +6,11 @@ #import "base/apple/foundation_util.h" #import "ios/chrome/browser/net/model/crurl.h" +#import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_cell.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h" #import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h" +#import "ios/chrome/browser/ui/authentication/cells/central_account_view.h" #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.h" #import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h" #import "ios/chrome/browser/ui/settings/elements/enterprise_info_popover_view_controller.h" @@ -23,13 +25,12 @@ namespace { // Table view customized header heights. -CGFloat kAccountSectionHeaderHeightPointSize = 22.17; CGFloat kSyncDataTypeSectionHeaderHeightPointSize = 48.; CGFloat kAdvancedSettingsSectionHeaderHeightPointSize = 26.; CGFloat kSignOutSectionHeaderHeightPointSize = 26.; +CGFloat kDefaultSectionHeaderHeightPointSize = 10.; // Table view customized footer heights. -CGFloat kAccountSectionFooterHeightPointSize = 28.; CGFloat kDefaultSectionFooterHeightPointSize = 10.; } // namespace @@ -203,6 +204,18 @@ withRowAnimation:UITableViewRowAnimationNone]; } +- (void)updatePrimaryAccountWithAvatarImage:(UIImage*)avatarImage + name:(NSString*)name + email:(NSString*)email { + CentralAccountView* identityAccountItem = [[CentralAccountView alloc] + initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 0) + avatarImage:avatarImage + name:name + email:email]; + self.tableView.tableHeaderView = identityAccountItem; + [self.tableView reloadData]; +} + #pragma mark - UITableViewDelegate - (void)tableView:(UITableView*)tableView @@ -220,8 +233,6 @@ NSInteger sectionIdentifier = [self.tableViewModel sectionIdentifierForSectionIndex:section]; switch (sectionIdentifier) { - case AccountSectionIdentifier: - return kAccountSectionHeaderHeightPointSize; case SyncDataTypeSectionIdentifier: return kSyncDataTypeSectionHeaderHeightPointSize; case AdvancedSettingsSectionIdentifier: @@ -233,7 +244,8 @@ } break; case SyncErrorsSectionIdentifier: - break; + case BatchUploadSectionIdentifier: + return kDefaultSectionHeaderHeightPointSize; } } return ChromeTableViewHeightForHeaderInSection(section); @@ -245,8 +257,6 @@ NSInteger sectionIdentifier = [self.tableViewModel sectionIdentifierForSectionIndex:section]; switch (sectionIdentifier) { - case AccountSectionIdentifier: - return kAccountSectionFooterHeightPointSize; case SyncDataTypeSectionIdentifier: case SignOutSectionIdentifier: return UITableViewAutomaticDimension;
diff --git a/ios/chrome/browser/ui/sharing/activity_services/activities/BUILD.gn b/ios/chrome/browser/ui/sharing/activity_services/activities/BUILD.gn index 633412f..a7cb1f7 100644 --- a/ios/chrome/browser/ui/sharing/activity_services/activities/BUILD.gn +++ b/ios/chrome/browser/ui/sharing/activity_services/activities/BUILD.gn
@@ -62,6 +62,7 @@ "//components/bookmarks/common", "//components/prefs:test_support", "//ios/chrome/app/strings", + "//ios/chrome/browser/bookmarks/model", "//ios/chrome/browser/bookmarks/model:test_support", "//ios/chrome/browser/lens/model", "//ios/chrome/browser/shared/model/browser",
diff --git a/ios/chrome/browser/ui/sharing/activity_services/activities/bookmark_activity_unittest.mm b/ios/chrome/browser/ui/sharing/activity_services/activities/bookmark_activity_unittest.mm index 4337d93..31817674 100644 --- a/ios/chrome/browser/ui/sharing/activity_services/activities/bookmark_activity_unittest.mm +++ b/ios/chrome/browser/ui/sharing/activity_services/activities/bookmark_activity_unittest.mm
@@ -4,13 +4,13 @@ #import "ios/chrome/browser/ui/sharing/activity_services/activities/bookmark_activity.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/browser/core_bookmark_model.h" #import "components/bookmarks/common/bookmark_pref_names.h" #import "components/prefs/pref_registry_simple.h" #import "components/prefs/testing_pref_service.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/public/commands/bookmarks_commands.h" #import "ios/chrome/browser/shared/ui/util/url_with_title.h" #import "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator.mm b/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator.mm index 36740133..a72f59f 100644 --- a/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator.mm +++ b/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator.mm
@@ -11,8 +11,8 @@ #import "base/metrics/user_metrics_action.h" #import "base/strings/string_number_conversions.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/prefs/pref_service.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/public/commands/bookmarks_commands.h"
diff --git a/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator_unittest.mm b/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator_unittest.mm index 37dab85..2e89c32 100644 --- a/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator_unittest.mm +++ b/ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator_unittest.mm
@@ -5,10 +5,10 @@ #import "ios/chrome/browser/ui/sharing/activity_services/activity_service_mediator.h" #import "base/test/metrics/histogram_tester.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/prefs/pref_registry_simple.h" #import "components/prefs/pref_service.h" #import "components/prefs/testing_pref_service.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/public/commands/bookmarks_commands.h" #import "ios/chrome/browser/shared/public/commands/browser_commands.h"
diff --git a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm index 0513a8d..3c1802e 100644 --- a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
@@ -11,10 +11,10 @@ #import "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #import "base/values.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/browser/bookmark_node.h" #import "components/bookmarks/test/bookmark_test_helpers.h" #import "ios/chrome/browser/bookmarks/model/bookmark_ios_unit_test_support.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/shared/model/browser/test/test_browser.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" @@ -47,7 +47,6 @@ using base::test::ios::kWaitForActionTimeout; using base::test::ios::WaitUntilConditionOrTimeout; -using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; // Test fixture for testing SharingCoordinator.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm index f07b28e..575d09c 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_mediator.mm
@@ -17,10 +17,10 @@ #import "base/scoped_multi_source_observation.h" #import "base/strings/stringprintf.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/common/bookmark_pref_names.h" #import "components/prefs/pref_service.h" #import "components/tab_groups/tab_group_visual_data.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/commerce/model/shopping_persisted_data_tab_helper.h" #import "ios/chrome/browser/default_browser/model/utils.h"
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm index 43bb78f..093c1b6 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -12,7 +12,7 @@ #import "base/metrics/user_metrics_action.h" #import "base/strings/sys_string_conversions.h" #import "base/time/time.h" -#import "components/bookmarks/browser/bookmark_model.h" +#import "components/bookmarks/browser/core_bookmark_model.h" #import "components/feature_engagement/public/feature_constants.h" #import "components/feature_engagement/public/tracker.h" #import "components/search_engines/template_url_service.h"
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator_unittest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator_unittest.mm index 0f1c5584..53c1035 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator_unittest.mm
@@ -13,8 +13,8 @@ #import "base/test/metrics/histogram_tester.h" #import "base/test/scoped_mock_clock_override.h" #import "base/test/test_timeouts.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/bookmarks/test/bookmark_test_helpers.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #import "ios/chrome/browser/shared/coordinator/scene/scene_state.h" @@ -191,7 +191,7 @@ std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; // Model for bookmarks. - raw_ptr<bookmarks::BookmarkModel> bookmark_model_; + raw_ptr<LegacyBookmarkModel> bookmark_model_; // Browser for the coordinator. std::unique_ptr<Browser> browser_;
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm index d64d492..8de8b753 100644 --- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm +++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -18,10 +18,10 @@ #import "base/metrics/user_metrics_action.h" #import "base/numerics/safe_conversions.h" #import "base/strings/sys_string_conversions.h" -#import "components/bookmarks/browser/bookmark_model.h" #import "components/favicon/ios/web_favicon_driver.h" #import "components/feature_engagement/public/event_constants.h" #import "components/feature_engagement/public/tracker.h" +#import "ios/chrome/browser/bookmarks/model/legacy_bookmark_model.h" #import "ios/chrome/browser/bookmarks/model/local_or_syncable_bookmark_model_factory.h" #import "ios/chrome/browser/drag_and_drop/model/drag_item_util.h" #import "ios/chrome/browser/drag_and_drop/model/url_drag_drop_handler.h"
diff --git a/ios/web/annotations/BUILD.gn b/ios/web/annotations/BUILD.gn index 442849e..b4e3b2c 100644 --- a/ios/web/annotations/BUILD.gn +++ b/ios/web/annotations/BUILD.gn
@@ -34,7 +34,10 @@ } optimize_ts("annotations_ts") { - visibility = [ ":annotations" ] + visibility = [ + ":annotations", + ":inttests", + ] sources = [ "resources/annotations.ts" ] @@ -123,6 +126,7 @@ deps = [ ":annotations", ":annotations_test_ts", + ":annotations_ts", ":text_tests_ts", "//base", "//base/test:test_support",
diff --git a/ios/web/annotations/annotations_inttest.mm b/ios/web/annotations/annotations_inttest.mm index e5078aa..33be13c 100644 --- a/ios/web/annotations/annotations_inttest.mm +++ b/ios/web/annotations/annotations_inttest.mm
@@ -33,19 +33,26 @@ namespace { -const char kScriptName[] = "annotations_test"; +const char kTestScriptName[] = "annotations_test"; +const char kNoViewportScriptName[] = "annotations"; +const char kViewportScriptName[] = "text_main"; // Feature to include test ts code only. class AnnotationsTestJavaScriptFeature : public JavaScriptFeature { public: - AnnotationsTestJavaScriptFeature() + AnnotationsTestJavaScriptFeature(std::string script_name) : JavaScriptFeature( ContentWorld::kIsolatedWorld, {FeatureScript::CreateWithFilename( - kScriptName, - FeatureScript::InjectionTime::kDocumentStart, - FeatureScript::TargetFrames::kMainFrame, - FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)}) {} + kTestScriptName, + FeatureScript::InjectionTime::kDocumentStart, + FeatureScript::TargetFrames::kMainFrame, + FeatureScript::ReinjectionBehavior::kInjectOncePerWindow), + FeatureScript::CreateWithFilename( + script_name, + FeatureScript::InjectionTime::kDocumentStart, + FeatureScript::TargetFrames::kMainFrame, + FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)}) {} AnnotationsTestJavaScriptFeature(const AnnotationsTestJavaScriptFeature&) = delete; @@ -56,7 +63,8 @@ // Class used to observe AnnotationTextManager interactions with an observer. class TestAnnotationTextObserver : public AnnotationsTextObserver { public: - TestAnnotationTextObserver() : successes_(0), annotations_(0), clicks_(0) {} + TestAnnotationTextObserver() + : successes_(0), annotations_(0), clicks_(0), decoration_calls_(0) {} TestAnnotationTextObserver(const TestAnnotationTextObserver&) = delete; TestAnnotationTextObserver& operator=(const TestAnnotationTextObserver&) = @@ -76,6 +84,7 @@ int successes, int failures, const base::Value::List& cancelled) override { + decoration_calls_++; annotations_ = annotations; successes_ = successes; failures_ = failures; @@ -89,6 +98,8 @@ click_data_ = data; } + void Reset() { seq_id_ = 0; } + const std::string& extracted_text() const { return extracted_text_; } int successes() const { return successes_; } int failures() const { return failures_; } @@ -98,10 +109,11 @@ const base::Value::Dict& metadata() const { return metadata_; } const std::string& click_data() const { return click_data_; } void SetAnnotations(int count) { annotations_ = count; } + int decoration_calls() const { return decoration_calls_; } private: std::string extracted_text_, click_data_; - int successes_, failures_, annotations_, clicks_, seq_id_; + int successes_, failures_, annotations_, clicks_, seq_id_, decoration_calls_; base::Value::Dict metadata_; }; @@ -134,9 +146,10 @@ JavaScriptFeatureManager::FromBrowserState(GetBrowserState()) ->GetContentWorldForFeature( AnnotationsJavaScriptFeature::GetInstance()); - + js_test_feature_ = + std::make_unique<AnnotationsTestJavaScriptFeature>(GetScriptName()); // Inject ts test helpers functions. - content_world_->AddFeature(&js_test_feature_); + content_world_->AddFeature(js_test_feature_.get()); } void TearDown() override { @@ -145,6 +158,8 @@ WebTestWithWebState::TearDown(); } + virtual std::string GetScriptName() { return ""; } + bool WaitForWebFramesCount(unsigned long web_frames_count) { return WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ return AllWebFrames().size() == web_frames_count; @@ -169,7 +184,7 @@ } // Loads given `html` and waits until text is extracted. - void LoadHtmlAndExtractText(const std::string& html) { + virtual void LoadHtmlAndExtractText(const std::string& html) { int seq_id = observer()->seq_id(); ASSERT_TRUE(LoadHtml(html)); ASSERT_TRUE(WaitForWebFramesCount(1)); @@ -188,6 +203,7 @@ NSString* source, NSDictionary<NSString*, NSArray<NSString*>*>* items, int seq_id) { + int decoration_calls = observer()->decoration_calls(); // Create annotation. base::Value::List annotations; for (NSString* type in items) { @@ -206,7 +222,8 @@ manager->DecorateAnnotations(web_state(), value, seq_id); EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ - return observer()->annotations() > 0; + return observer()->decoration_calls() > decoration_calls && + observer()->annotations() > 0; })); } @@ -286,12 +303,53 @@ base::test::ScopedFeatureList feature_; raw_ptr<JavaScriptContentWorld> content_world_; TestAnnotationTextObserver observer_; - AnnotationsTestJavaScriptFeature js_test_feature_; + std::unique_ptr<AnnotationsTestJavaScriptFeature> js_test_feature_; +}; + +class AnnotationTextManagerNoViewportTest : public AnnotationTextManagerTest { + public: + AnnotationTextManagerNoViewportTest() = default; + + AnnotationTextManagerNoViewportTest( + const AnnotationTextManagerNoViewportTest&) = delete; + AnnotationTextManagerNoViewportTest& operator=( + const AnnotationTextManagerNoViewportTest&) = delete; + + protected: + void SetUp() override { + feature_.InitAndDisableFeature(features::kEnableViewportIntents); + AnnotationTextManagerTest::SetUp(); + } + + std::string GetScriptName() override { return kNoViewportScriptName; } +}; + +class AnnotationTextManagerViewportTest : public AnnotationTextManagerTest { + public: + AnnotationTextManagerViewportTest() = default; + + AnnotationTextManagerViewportTest(const AnnotationTextManagerViewportTest&) = + delete; + AnnotationTextManagerViewportTest& operator=( + const AnnotationTextManagerViewportTest&) = delete; + + protected: + void SetUp() override { + feature_.InitAndEnableFeature(features::kEnableViewportIntents); + AnnotationTextManagerTest::SetUp(); + } + + std::string GetScriptName() override { return kViewportScriptName; } + + void LoadHtmlAndExtractText(const std::string& html) override { + observer()->Reset(); + AnnotationTextManagerTest::LoadHtmlAndExtractText(html); + } }; // Tests page text extraction. // Covers: PageLoaded, OnTextExtracted, StartExtractingText. -TEST_F(AnnotationTextManagerTest, ExtractText) { +TEST_F(AnnotationTextManagerNoViewportTest, ExtractText) { LoadHtmlAndExtractText("<html><body>" "<p>You'll find it on</p>" "<p>Castro Street, <span>Mountain View</span>, CA</p>" @@ -304,8 +362,33 @@ observer()->extracted_text()); } +// Tests page text extraction. +// Covers: PageLoaded, OnTextExtracted, StartExtractingText. +TEST_F(AnnotationTextManagerViewportTest, ExtractText) { + LoadHtmlAndExtractText("<html><body>" + "<p>You'll find it on</p>" + "<p>Castro Street, <span>Mountain View</span>, CA</p>" + "<p>Enjoy</p>" + "</body></html>"); + + EXPECT_EQ("You'll find it on " + "Castro Street, Mountain View, CA " + "Enjoy ", + observer()->extracted_text()); +} + +// Tests page text extraction with different type of tags. +TEST_F(AnnotationTextManagerViewportTest, ExtractTextTags) { + LoadHtmlAndExtractText("<html><body>" + "<div>abc<div>def<span>ghi</span><em>jkl</em>mno</div>" + "pqr</div>" + "</body></html>"); + + EXPECT_EQ("abc defghijklmno pqr ", observer()->extracted_text()); +} + // Tests no page text extraction if there is no supported type. -TEST_F(AnnotationTextManagerTest, ExtractNoText) { +TEST_F(AnnotationTextManagerNoViewportTest, ExtractNoText) { auto* manager = AnnotationsTextManager::FromWebState(web_state()); manager->SetSupportedTypes(0); @@ -323,7 +406,26 @@ EXPECT_EQ("", observer()->extracted_text()); } -TEST_F(AnnotationTextManagerTest, CheckMetadata) { +// Tests no page text extraction if there is no supported type. +TEST_F(AnnotationTextManagerViewportTest, ExtractNoText) { + auto* manager = AnnotationsTextManager::FromWebState(web_state()); + manager->SetSupportedTypes(0); + + int seq_id = observer()->seq_id(); + + ASSERT_TRUE(LoadHtml("<html><body>" + "<p>You'll find it on</p>" + "<p>Castro Street, <span>Mountain View</span>, CA</p>" + "<p>Enjoy</p>" + "</body></html>")); + ASSERT_TRUE(WaitForWebFramesCount(1)); + EXPECT_FALSE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ + return observer()->seq_id() > seq_id; + })); + EXPECT_EQ("", observer()->extracted_text()); +} + +TEST_F(AnnotationTextManagerNoViewportTest, CheckMetadata) { LoadHtmlAndExtractText("<html lang=\"fr\">" "<head>" "<meta http-equiv=\"content-language\" content=\"fr\">" @@ -342,7 +444,28 @@ EXPECT_EQ(fr, *observer()->metadata().FindString("httpContentLanguage")); } -TEST_F(AnnotationTextManagerTest, CheckNoMetadata) { +TEST_F(AnnotationTextManagerViewportTest, CheckMetadata) { + int seq_id = observer()->seq_id(); + + ASSERT_TRUE(LoadHtml("<html lang=\"fr\">" + "<head>" + "<meta http-equiv=\"content-language\" content=\"fr\">" + "<meta name=\"chrome\" content=\"nointentdetection\"/>" + "<meta name=\"google\" content=\"notranslate\"/>" + "</head>" + "<body>" + "<p>You'll find it on</p>" + "<p>Castro Street, <span>Mountain View</span>, CA</p>" + "<p>Enjoy</p>" + "</body></html>")); + ASSERT_TRUE(WaitForWebFramesCount(1)); + EXPECT_FALSE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^{ + return observer()->seq_id() > seq_id; + })); + EXPECT_EQ("", observer()->extracted_text()); +} + +TEST_F(AnnotationTextManagerNoViewportTest, CheckNoMetadata) { LoadHtmlAndExtractText("<html>" "<head>" "</head>" @@ -358,9 +481,25 @@ EXPECT_EQ(empty, *observer()->metadata().FindString("httpContentLanguage")); } +TEST_F(AnnotationTextManagerViewportTest, CheckNoMetadata) { + LoadHtmlAndExtractText("<html>" + "<head>" + "</head>" + "<body>" + "<p>You'll find it on</p>" + "<p>Castro Street, <span>Mountain View</span>, CA</p>" + "<p>Enjoy</p>" + "</body></html>"); + std::string empty = ""; + EXPECT_FALSE(observer()->metadata().FindBool("hasNoIntentDetection")); + EXPECT_FALSE(observer()->metadata().FindBool("hasNoTranslate")); + EXPECT_EQ(empty, *observer()->metadata().FindString("htmlLang")); + EXPECT_EQ(empty, *observer()->metadata().FindString("httpContentLanguage")); +} + // Tests page decoration when page doesn't change. // Covers: DecorateAnnotations, ConvertMatchToAnnotation. -TEST_F(AnnotationTextManagerTest, DecorateText) { +TEST_F(AnnotationTextManagerNoViewportTest, DecorateText) { LoadHtmlAndExtractText("<html><body>" "<p>text</p>" "<p>annotation</p>" @@ -387,8 +526,37 @@ "</body></html>"); } +// Tests page decoration when page doesn't change. +// Covers: DecorateAnnotations, ConvertMatchToAnnotation. +TEST_F(AnnotationTextManagerViewportTest, DecorateText) { + LoadHtmlAndExtractText("<html><body>" + "<p>text</p>" + "<p>annotation</p>" + "<p>text</p>" + "</body></html>"); + + std::string text = "text " + "annotation " + "text "; + EXPECT_EQ(text, observer()->extracted_text()); + + // Create annotation. + NSString* source = base::SysUTF8ToNSString(text); + CreateAndApplyAnnotations(source, @[ @"annotation" ], observer() -> seq_id()); + + EXPECT_EQ(observer()->successes(), 1); + EXPECT_EQ(observer()->annotations(), 1); + + // Check the resulting html is annotating at the right place. + CheckHtml("<html><body>" + "<p>text</p>" + "<p><chrome_annotation>annotation</chrome_annotation></p>" + "<p>text</p>" + "</body></html>"); +} + // Tests on no-decoration tags. -TEST_F(AnnotationTextManagerTest, NoDecorateText) { +TEST_F(AnnotationTextManagerNoViewportTest, NoDecorateText) { LoadHtmlAndExtractText("<html><body>" "<p>text</p>" "<a>annotation1</a>" @@ -402,9 +570,24 @@ EXPECT_EQ(text, observer()->extracted_text()); } +// Tests on no-decoration tags. +TEST_F(AnnotationTextManagerViewportTest, NoDecorateText) { + LoadHtmlAndExtractText("<html><body>" + "<p>text</p>" + "<a>annotation1</a>" + "<input type=\"radio\">" + "<label>annotation2</label>" + "<p>text</p>" + "</body></html>"); + + std::string text = "text ‡ " + "text "; + EXPECT_EQ(text, observer()->extracted_text()); +} + // Tests different annotation cases, including tags boundaries. // Covers: RemoveDecorations -TEST_F(AnnotationTextManagerTest, DecorateTextCrossingElements) { +TEST_F(AnnotationTextManagerNoViewportTest, DecorateTextCrossingElements) { std::string html = "<html><body>" "<p>abc</p>" "<p>def</p>" @@ -436,9 +619,43 @@ CheckHtml(html); } +// Tests different annotation cases, including tags boundaries. +// Covers: RemoveDecorations +TEST_F(AnnotationTextManagerViewportTest, DecorateTextCrossingElements) { + std::string html = "<html><body>" + "<p>abc</p>" + "<p>def</p>" + "<p>ghi</p>" + "<p>jkl</p>" + "<p>mno</p>" + "</body></html>"; + LoadHtmlAndExtractText(html); + + NSString* source = base::SysUTF8ToNSString(observer()->extracted_text()); + CreateAndApplyAnnotations(source, @[ @"a", @"c d", @"f ghi j", @"l mno " ], + observer() -> seq_id()); + + // Check the resulting html is annotating at the right place. + CheckHtml("<html><body>" + "<p><chrome_annotation>a</chrome_annotation>b<chrome_annotation>c</" + "chrome_annotation></p>" + "<p><chrome_annotation>d</chrome_annotation>e<chrome_annotation>f</" + "chrome_annotation></p>" + "<p><chrome_annotation>ghi</chrome_annotation></p>" + "<p><chrome_annotation>j</chrome_annotation>k<chrome_annotation>l</" + "chrome_annotation></p>" + "<p><chrome_annotation>mno</chrome_annotation></p>" + "</body></html>"); + + // Make sure it's back to the original. + auto* manager = AnnotationsTextManager::FromWebState(web_state()); + manager->RemoveDecorations(); + CheckHtml(html); +} + // Tests annotation cases with line breaks, including tags boundaries. // Covers: DecorateAnnotations, RemoveDecorations -TEST_F(AnnotationTextManagerTest, DecorateTextBreakElements) { +TEST_F(AnnotationTextManagerNoViewportTest, DecorateTextBreakElements) { std::string html = "<html><body>" "<p>abc<br>\ndef</p>" "</body></html>"; @@ -460,9 +677,51 @@ CheckHtml(html); } +// Tests annotation cases with line breaks, including tags boundaries. +// Covers: DecorateAnnotations, RemoveDecorations +TEST_F(AnnotationTextManagerViewportTest, DecorateTextBreakElements) { + std::string html = "<html><body>" + "<p>abc<br>\ndef</p>" + "</body></html>"; + LoadHtmlAndExtractText(html); + CheckHtml(html); + + NSString* source = base::SysUTF8ToNSString(observer()->extracted_text()); + // ` ‡ ` is used as a section break to avoid cross section annotations. + CreateAndApplyAnnotations(source, @[ @"abc ‡ \ndef" ], + observer() -> seq_id()); + + // Check the resulting html is annotating at the right place. + CheckHtml("<html><body>" + "<p><chrome_annotation>abc</chrome_annotation><br>" + "<chrome_annotation>\ndef</chrome_annotation></p>" + "</body></html>"); + + // Make sure it's back to the original. + auto* manager = AnnotationsTextManager::FromWebState(web_state()); + manager->RemoveDecorations(); + CheckHtml(html); +} + // Tests on click handler. // Covers: OnClick. -TEST_F(AnnotationTextManagerTest, ClickAnnotation) { +TEST_F(AnnotationTextManagerNoViewportTest, ClickAnnotation) { + LoadHtmlAndExtractText("<html><body>" + "<p>text</p>" + "<p>annotation</p>" + "<p>text</p>" + "</body></html>"); + NSString* source = base::SysUTF8ToNSString(observer()->extracted_text()); + CreateAndApplyAnnotations(source, @[ @"annotation" ], observer() -> seq_id()); + ClickAnnotation(0); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 1; + })); +} + +// Tests on click handler. +// Covers: OnClick. +TEST_F(AnnotationTextManagerViewportTest, ClickAnnotation) { LoadHtmlAndExtractText("<html><body>" "<p>text</p>" "<p>annotation</p>" @@ -477,7 +736,83 @@ } // Tests removing annotation of one type -TEST_F(AnnotationTextManagerTest, RemoveDecorationTypeTest) { +TEST_F(AnnotationTextManagerNoViewportTest, RemoveDecorationTypeTest) { + std::string html = "<html><body>" + "<p>abc def</p>" + "<p>zzzzz ghi zzzzz</p>" + "<p>zzzzz klm zzzzz</p>" + "</body></html>"; + LoadHtmlAndExtractText(html); + CheckHtml(html); + auto* manager = AnnotationsTextManager::FromWebState(web_state()); + + NSString* source = base::SysUTF8ToNSString(observer()->extracted_text()); + + CreateAndApplyAnnotationsWithTypes( + source, + @{@"type1" : @[ @"abc", @"ghi" ], + @"type2" : @[ @"def", @"klm" ]}, + observer()->seq_id()); + + // Check the resulting html is annotating at the right place. + CheckHtml("<html><body>" + "<p><chrome_annotation>abc</chrome_annotation> " + "<chrome_annotation>def</chrome_annotation></p>" + "<p>zzzzz <chrome_annotation>ghi</chrome_annotation> zzzzz</p>" + "<p>zzzzz <chrome_annotation>klm</chrome_annotation> zzzzz</p>" + "</body></html>"); + + CountAnnotation(); + ASSERT_EQ(observer()->annotations(), 4); + + ClickAnnotation(0); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 1; + })); + + ClickAnnotation(1); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 2; + })); + + ClickAnnotation(2); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 3; + })); + + ClickAnnotation(3); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 4; + })); + + manager->RemoveDecorationsWithType("type1"); + // Check the resulting html is annotating at the right place. + CheckHtml("<html><body>" + "<p>abc <chrome_annotation>def</chrome_annotation></p>" + "<p>zzzzz ghi zzzzz</p>" + "<p>zzzzz <chrome_annotation>klm</chrome_annotation> zzzzz</p>" + "</body></html>"); + + CountAnnotation(); + ASSERT_EQ(observer()->annotations(), 2); + + ClickAnnotation(0); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 5; + })); + + ClickAnnotation(1); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 6; + })); + + // Make sure it's back to the original. + manager->RemoveDecorations(); + CheckHtml(html); +} + +// Tests removing annotation of one type +TEST_F(AnnotationTextManagerViewportTest, RemoveDecorationTypeTest) { std::string html = "<html><body>" "<p>abc def</p>" "<p>zzzzz ghi zzzzz</p>" @@ -553,7 +888,7 @@ } // Tests on (simulated) navigation in web state. -TEST_F(AnnotationTextManagerTest, NavigationClearsAnnotation) { +TEST_F(AnnotationTextManagerNoViewportTest, NavigationClearsAnnotation) { std::string text1 = "<html><body>" "<p>text</p>" "<p>annotation</p>" @@ -600,4 +935,58 @@ ASSERT_TRUE(observer()->click_data() == "type1-annotation"); } +// Tests on (simulated) navigation in web state. +TEST_F(AnnotationTextManagerViewportTest, NavigationClearsAnnotation) { + std::string text1 = "<html><body>" + "<p>text</p>" + "<p>annotation</p>" + "<p>text</p>" + "</body></html>"; + + LoadHtmlAndExtractText(text1); + NSString* source = base::SysUTF8ToNSString(observer()->extracted_text()); + CreateAndApplyAnnotationsWithTypes( + source, + @{@"type1" : @[ @"annotation" ]}, observer()->seq_id()); + ClickAnnotation(0); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 1; + })); + ASSERT_TRUE(observer()->click_data() == "type1-annotation"); + + std::string text2 = "<html><body>" + "<p>bla</p>" + "<p>blurb</p>" + "<p>bla</p>" + "</body></html>"; + LoadHtmlAndExtractText(text2); + source = base::SysUTF8ToNSString(observer()->extracted_text()); + CreateAndApplyAnnotationsWithTypes( + source, + @{@"type2" : @[ @"blurb" ]}, observer()->seq_id()); + + CheckHtml("<html><body>" + "<p>bla</p>" + "<p><chrome_annotation>blurb</chrome_annotation></p>" + "<p>bla</p>" + "</body></html>"); + ClickAnnotation(0); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 2; + })); + ASSERT_TRUE(observer()->click_data() == "type2-blurb"); + + // Now navigate back to original text. + LoadHtmlAndExtractText(text1); + source = base::SysUTF8ToNSString(observer()->extracted_text()); + CreateAndApplyAnnotationsWithTypes( + source, + @{@"type1" : @[ @"annotation" ]}, observer()->seq_id()); + ClickAnnotation(0); + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return observer()->clicks() == 3; + })); + ASSERT_TRUE(observer()->click_data() == "type1-annotation"); +} + } // namespace web
diff --git a/ios/web/annotations/resources/text_decoration.ts b/ios/web/annotations/resources/text_decoration.ts index 0761580a..baaa0238 100644 --- a/ios/web/annotations/resources/text_decoration.ts +++ b/ios/web/annotations/resources/text_decoration.ts
@@ -129,6 +129,10 @@ if (parentNode && id) { parentNode.replaceChild(textNode, replacement); textNode[replacementNodeDecorationId] = id; + // The node has been replace. Remove the symbols so it is not + // considered as a replacement node in observers anymore.. + delete replacement[replacementNodeDecorationId]; + delete replacement[originalNodeDecorationId]; } this.replacements[i] = textNode; }
diff --git a/ios/web/annotations/resources/text_extractor.ts b/ios/web/annotations/resources/text_extractor.ts index e5a7bbe..6bea80c 100644 --- a/ios/web/annotations/resources/text_extractor.ts +++ b/ios/web/annotations/resources/text_extractor.ts
@@ -18,6 +18,11 @@ // Minimum number of characters to add at ends of sections. const EXTRA_CHARACTERS_AT_END = 128; +const KNOWN_INLINE_ELEMENTS: Set<string> = new Set([ + 'A', 'ABBR', 'B', 'CITE', 'CODE', 'I', 'DFN', 'EM', 'MARK', 'SMALL', 'SPAN', + 'STRONG', 'SUB', 'SUP', 'VAR' +]); + // A section is a `textNode` and an index. The index is the position when this // node's text is in the full extracted text. Note that some text, like breaks // and spaces, are not in `TextSection`s. Neither are text nodes with no text or @@ -107,24 +112,31 @@ this.index += textNode.textContent!.length; this.broken = false; this.spaced = false; - } else if (!this.spaced) { - // Spacer, no section registered. - this.parts.push(' '); - this.index++; - this.spaced = true; + } else { + this.addSpaceIfNeeded(); + } + } + + enterVisibleNode(node: Node): void { + if (node instanceof Element && !KNOWN_INLINE_ELEMENTS.has(node.nodeName)) { + this.addSpaceIfNeeded(); + } + } + + leaveVisibleNode(node: Node): void { + if (node instanceof Element && !KNOWN_INLINE_ELEMENTS.has(node.nodeName)) { + this.addSpaceIfNeeded(); } } invisibleNode(node: Node): void { - // Skip empty text nodes. They are not real breaks. - if (node.nodeType === Node.TEXT_NODE && + if (node.nodeType === Node.COMMENT_NODE) { + // Completely ignore comments. + } else if ( + node.nodeType === Node.TEXT_NODE && (!node.textContent || !node.textContent.trim())) { - if (!this.spaced) { - // Spacer, no section registered. - this.parts.push(' '); - this.index++; - this.spaced = true; - } + // Skip empty text nodes. They are not real breaks. + this.addSpaceIfNeeded(); } else if (!this.broken) { // Text section break, no section registered. this.parts.push(this.sectionBreak); @@ -163,6 +175,16 @@ // Mark: Private API + // Adds a single space between parts if there was none. + private addSpaceIfNeeded() { + if (!this.spaced) { + // Spacer, no section registered. + this.parts.push(' '); + this.index++; + this.spaced = true; + } + } + // Extracts up to `extraCharactersAtEnd` before `beforeNode`. Returns // an array of `TextSection`, its combined text and the offset to // the first character in the first section. In case nothing can be found,
diff --git a/ios/web/annotations/resources/text_extractor_test.ts b/ios/web/annotations/resources/text_extractor_test.ts index fc09770..69ef966f 100644 --- a/ios/web/annotations/resources/text_extractor_test.ts +++ b/ios/web/annotations/resources/text_extractor_test.ts
@@ -27,10 +27,14 @@ // Tests the normal flow of text extracting and prefix/suffix adding. testTextExtractorFlow() { const html = '<invisible>012</invisible>' + - '<visible>abcdefgh</visible>' + + '<visible>abc</visible>' + + '<visible>defgh</visible>' + ' ' + + '<!-- Comment should be ignored -->' + '<visible>ijkl</visible>' + - '<invisible>mnopqrstuv</invisible>' + + '<invisible>mno</invisible>' + + '<span>pqr</span>' + + '<span>stuv</span>' + '<visible>wxyz</visible>' + '\n' + '<div>345678</div>'; @@ -47,7 +51,13 @@ if (childNode.nodeType === Node.TEXT_NODE) { extractor.visibleTextNode(childNode as Text); } else if (childNode.nodeName === 'VISIBLE') { + extractor.enterVisibleNode(childNode); extractor.visibleTextNode(childNode.childNodes[0] as Text); + extractor.leaveVisibleNode(childNode); + } else if (childNode.nodeName === 'SPAN') { + extractor.enterVisibleNode(childNode); + extractor.visibleTextNode(childNode.childNodes[0] as Text); + extractor.leaveVisibleNode(childNode); } else if (childNode.nodeName === 'INVISIBLE') { extractor.invisibleNode(childNode); } @@ -57,31 +67,43 @@ expectNeq(undefined, this.textChunk, 'textChunk:'); expectEq( - '012 ' + // prefix (up to 5 chars) - 'abcdefgh' + // node text - ' ' + // single space - 'ijkl' + // node text - '|' + // section break - 'wxyz' + // node text - ' ' + // space - '34567', // postfix (5 chars) + '012 ' + // prefix (up to 5 chars) + 'abc' + // node text + ' ' + // single space + 'defgh' + // node text + ' ' + // single space + 'ijkl' + // node text + ' ' + // single space + '|' + // section break + 'pqr' + // node text (no space after) + 'stuv' + // node text (no space before) + ' ' + // single space + 'wxyz' + // node text + ' ' + // space + '34567', // postfix (5 chars) this.textChunk!.text); expectEq(0, this.textChunk!.firstNodeOffset); expectEq(4, this.textChunk!.visibleStart); - expectEq(23, this.textChunk!.visibleEnd); + expectEq(33, this.textChunk!.visibleEnd); - expectEq(5, this.textChunk!.sections.length); + expectEq(8, this.textChunk!.sections.length); expectEq(0, this.textChunk!.sections[0]!.index); expectEq('012', this.textChunk!.sections[0]!.textNode!.textContent); expectEq(4, this.textChunk!.sections[1]!.index); - expectEq('abcdefgh', this.textChunk!.sections[1]!.textNode!.textContent); - expectEq(13, this.textChunk!.sections[2]!.index); - expectEq('ijkl', this.textChunk!.sections[2]!.textNode!.textContent); - expectEq(18, this.textChunk!.sections[3]!.index); - expectEq('wxyz', this.textChunk!.sections[3]!.textNode!.textContent); - expectEq(23, this.textChunk!.sections[4]!.index); - expectEq('345678', this.textChunk!.sections[4]!.textNode!.textContent); + expectEq('abc', this.textChunk!.sections[1]!.textNode!.textContent); + expectEq(8, this.textChunk!.sections[2]!.index); + expectEq('defgh', this.textChunk!.sections[2]!.textNode!.textContent); + expectEq(14, this.textChunk!.sections[3]!.index); + expectEq('ijkl', this.textChunk!.sections[3]!.textNode!.textContent); + expectEq(20, this.textChunk!.sections[4]!.index); + expectEq('pqr', this.textChunk!.sections[4]!.textNode!.textContent); + expectEq(23, this.textChunk!.sections[5]!.index); + expectEq('stuv', this.textChunk!.sections[5]!.textNode!.textContent); + expectEq(28, this.textChunk!.sections[6]!.index); + expectEq('wxyz', this.textChunk!.sections[6]!.textNode!.textContent); + expectEq(33, this.textChunk!.sections[7]!.index); + expectEq('345678', this.textChunk!.sections[7]!.textNode!.textContent); } }
diff --git a/ios/web/annotations/resources/text_intersection_observer.ts b/ios/web/annotations/resources/text_intersection_observer.ts index 2fcccc0..df5c5bf 100644 --- a/ios/web/annotations/resources/text_intersection_observer.ts +++ b/ios/web/annotations/resources/text_intersection_observer.ts
@@ -73,6 +73,10 @@ visibleTextNode(textNode: Text): void; // Called for invisible `node` between `visibleTextNode`s. invisibleNode(node: Node): void; + // Called before entering `node` subtree. + enterVisibleNode(node: Node): void; + // Called after leaving `node` subtree. + leaveVisibleNode(node: Node): void; // Called when ending the visit. end(): void; } @@ -148,7 +152,9 @@ this.unobserve(childNode); } else if ( childNode[visibleDescendantCount] || childNode[visibleElement]) { + visitor.enterVisibleNode(childNode); traverseVisible(childNode); + visitor.leaveVisibleNode(childNode); } else { visitor.invisibleNode(childNode); }
diff --git a/ios/web/annotations/resources/text_intersection_observer_test.ts b/ios/web/annotations/resources/text_intersection_observer_test.ts index 108343d..646a29f 100644 --- a/ios/web/annotations/resources/text_intersection_observer_test.ts +++ b/ios/web/annotations/resources/text_intersection_observer_test.ts
@@ -71,6 +71,12 @@ this.invisibleNodes.push(node); this.invisibleNodeNames += ':' + node.nodeName; } + enterVisibleNode(node: Node): void { + this.visibleText += '+<' + node.nodeName + '>'; + } + leaveVisibleNode(node: Node): void { + this.visibleText += '+</' + node.nodeName + '>'; + } end(): void { this.flowState += '-end'; } @@ -149,7 +155,7 @@ this.timer.moveAhead(/* ms= */ 10, /* times= */ 6); // -> 60ms total // Check that the visit happened. - expectEq(this.visibleText, '+Small'); + expectEq(this.visibleText, '+<BODY>+<DIV>+Small+</DIV>+</BODY>'); expectEq(this.invisibleNodeNames, ':HEAD:DIV:DIV'); expectEq(this.invisibleNodes[1], d1); expectEq(this.invisibleNodes[2], d3); @@ -185,7 +191,7 @@ currentObserver?.hits([{target: d1, isIntersecting: true}]); this.timer.moveAhead(/* ms= */ 10, /* times= */ 6); // -> 60ms total // Check that the visit happened. - expectEq(this.visibleText, '+Hello'); + expectEq(this.visibleText, '+<BODY>+<DIV>+Hello+</DIV>+</BODY>'); expectEq(this.invisibleNodeNames, ':HEAD:DIV:DIV'); expectEq(this.invisibleNodes[1], d2); expectEq(this.invisibleNodes[2], d3); @@ -197,13 +203,15 @@ // But before text extraction, make it invisible. currentObserver?.hits([{target: d2, isIntersecting: false}]); this.timer.moveAhead(/* ms= */ 10, /* times= */ 6); // -> 140ms total - expectEq(this.visibleText, '+Hello'); + expectEq(this.visibleText, '+<BODY>+<DIV>+Hello+</DIV>+</BODY>'); expectEq(this.flowState, 'idle-begin-end-begin-end'); // Make d3 visible. currentObserver?.hits([{target: d3, isIntersecting: true}]); this.timer.moveAhead(/* ms= */ 10, /* times= */ 6); // -> 200ms total - expectEq(this.visibleText, '+Hello+World'); + expectEq( + this.visibleText, + '+<BODY>+<DIV>+Hello+</DIV>+</BODY>+<BODY>+<DIV>+World+</DIV>+</BODY>'); expectEq(this.flowState, 'idle-begin-end-begin-end-begin-end'); // d1 and d3 should not be observed anymore, d2 should.
diff --git a/ios_internal b/ios_internal index 6831732..688972f 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 68317323902aff53eb3ea1e381f48e9249f0f516 +Subproject commit 688972f572b29fa2d33f7cd37601e05e50d8fea8
diff --git a/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc index 341bb4c..bbd8476 100644 --- a/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc +++ b/media/gpu/vaapi/vp8_vaapi_video_encoder_delegate.cc
@@ -533,11 +533,22 @@ DVLOGF(3) << "Drop frame"; return PrepareEncodeJobResult::kDrop; } - picture.frame_hdr->quantization_hdr.y_ac_qi = rate_ctrl_->GetQP(); + picture.frame_hdr->quantization_hdr.y_ac_qi = + base::checked_cast<uint8_t>(rate_ctrl_->GetQP()); + libvpx::UVDeltaQP uv_delta_qp = rate_ctrl_->GetUVDeltaQP(); + picture.frame_hdr->quantization_hdr.uv_dc_delta = + base::checked_cast<int8_t>(uv_delta_qp.uvdc_delta_q); + picture.frame_hdr->quantization_hdr.uv_ac_delta = + base::checked_cast<int8_t>(uv_delta_qp.uvac_delta_q); picture.frame_hdr->loopfilter_hdr.level = base::checked_cast<uint8_t>(rate_ctrl_->GetLoopfilterLevel()); + DVLOGF(4) << "qp=" << static_cast<int>(picture.frame_hdr->quantization_hdr.y_ac_qi) + << ", uv_dc_delta=" + << static_cast<int>(picture.frame_hdr->quantization_hdr.uv_dc_delta) + << ", uv_ac_delta=" + << static_cast<int>(picture.frame_hdr->quantization_hdr.uv_ac_delta) << ", filter_level=" << static_cast<int>(picture.frame_hdr->loopfilter_hdr.level) << (keyframe ? " (keyframe)" : "")
diff --git a/services/webnn/BUILD.gn b/services/webnn/BUILD.gn index 6e09b74..b6ab37d 100644 --- a/services/webnn/BUILD.gn +++ b/services/webnn/BUILD.gn
@@ -17,6 +17,20 @@ ] } +source_set("tflite_graph_builder") { + sources = [ + "tflite/graph_builder.cc", + "tflite/graph_builder.h", + ] + public_deps = [ + "//base", + "//components/ml/webnn", + "//services/webnn/public/mojom", + "//third_party/flatbuffers", + "//third_party/tflite:tflite_public_headers", + ] +} + component("webnn_service") { sources = [ "error.h", @@ -30,6 +44,13 @@ "webnn_utils.h", ] + deps = [ + "//base", + "//components/ml/webnn", + "//mojo/public/cpp/bindings", + "//services/webnn/public/mojom", + ] + if (is_win) { sources += [ "dml/adapter.cc", @@ -52,15 +73,13 @@ "dml/utils.cc", "dml/utils.h", ] + deps += [ + "//third_party/fp16", + "//ui/gl", + "//ui/gl/init", + ] } - deps = [ - "//base", - "//components/ml/webnn", - "//mojo/public/cpp/bindings", - "//services/webnn/public/mojom", - ] - if (is_mac) { sources += [ "coreml/context_impl.h", @@ -76,11 +95,18 @@ deps += [ ":coreml_graph_builder" ] } - if (is_win) { + if (is_linux) { + sources += [ + "tflite/context_impl.cc", + "tflite/context_impl.h", + "tflite/graph_impl.cc", + "tflite/graph_impl.h", + "tflite/op_resolver.cc", + "tflite/op_resolver.h", + ] deps += [ - "//third_party/fp16", - "//ui/gl", - "//ui/gl/init", + ":tflite_graph_builder", + "//third_party/tflite", ] } @@ -111,7 +137,7 @@ ] } - if (is_mac || is_win) { + if (is_linux || is_mac || is_win) { sources += [ "webnn_graph_impl_backend_test.cc" ] } @@ -145,6 +171,7 @@ deps = [ ":coreml_graph_builder", + ":tflite_graph_builder", ":webnn_service", "//base", "//base/test:test_support",
diff --git a/services/webnn/DEPS b/services/webnn/DEPS index a6b144a..931e8d7 100644 --- a/services/webnn/DEPS +++ b/services/webnn/DEPS
@@ -5,5 +5,7 @@ "+third_party/fp16/src/include/fp16.h", "+ui/gl/gl_angle_util_win.h", "+ui/gl/init/gl_factory.h", - "+third_party/coremltools/mlmodel/format" + "+third_party/coremltools/mlmodel/format", + "+third_party/flatbuffers/src/include/flatbuffers", + "+third_party/tflite/src/tensorflow/lite", ]
diff --git a/services/webnn/dml/graph_impl.cc b/services/webnn/dml/graph_impl.cc index a9e9879f..43e8417f 100644 --- a/services/webnn/dml/graph_impl.cc +++ b/services/webnn/dml/graph_impl.cc
@@ -1189,19 +1189,37 @@ break; } case mojom::Pool2d::Kind::kMaxPool2d: { - DML_MAX_POOLING2_OPERATOR_DESC max_pooling_desc = { - .InputTensor = &input_tensor_desc.GetDMLTensorDesc(), - .OutputTensor = &output_tensor_desc.GetDMLTensorDesc(), - .OutputIndicesTensor = nullptr, - .DimensionCount = - base::checked_cast<uint32_t>(window_dimensions.size()), - .Strides = strides.data(), - .WindowSize = window_dimensions.data(), - .StartPadding = start_padding.data(), - .EndPadding = end_padding.data(), - .Dilations = dilations.data()}; - pool2d_node = graph_builder.CreateOperatorNode(DML_OPERATOR_MAX_POOLING2, - &max_pooling_desc, inputs); + // If the dilations are { 1, 1 } by default, prefer using + // `DML_MAX_POOLING_OPERATOR_DESC` without dilations supported for best + // compatibility. + // https://learn.microsoft.com/en-us/windows/win32/api/directml/ns-directml-dml_max_pooling_operator_desc. + if (dilations[0] == 1 && dilations[1] == 1) { + DML_MAX_POOLING_OPERATOR_DESC max_pooling_desc = { + .InputTensor = &input_tensor_desc.GetDMLTensorDesc(), + .OutputTensor = &output_tensor_desc.GetDMLTensorDesc(), + .DimensionCount = + base::checked_cast<uint32_t>(window_dimensions.size()), + .Strides = strides.data(), + .WindowSize = window_dimensions.data(), + .StartPadding = start_padding.data(), + .EndPadding = end_padding.data()}; + pool2d_node = graph_builder.CreateOperatorNode( + DML_OPERATOR_MAX_POOLING, &max_pooling_desc, inputs); + } else { + DML_MAX_POOLING2_OPERATOR_DESC max_pooling2_desc = { + .InputTensor = &input_tensor_desc.GetDMLTensorDesc(), + .OutputTensor = &output_tensor_desc.GetDMLTensorDesc(), + .OutputIndicesTensor = nullptr, + .DimensionCount = + base::checked_cast<uint32_t>(window_dimensions.size()), + .Strides = strides.data(), + .WindowSize = window_dimensions.data(), + .StartPadding = start_padding.data(), + .EndPadding = end_padding.data(), + .Dilations = dilations.data()}; + pool2d_node = graph_builder.CreateOperatorNode( + DML_OPERATOR_MAX_POOLING2, &max_pooling2_desc, inputs); + } break; } default:
diff --git a/services/webnn/tflite/context_impl.cc b/services/webnn/tflite/context_impl.cc new file mode 100644 index 0000000..23a6953 --- /dev/null +++ b/services/webnn/tflite/context_impl.cc
@@ -0,0 +1,23 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/webnn/tflite/context_impl.h" + +#include "services/webnn/tflite/graph_impl.h" + +namespace webnn::tflite { + +ContextImpl::ContextImpl(mojo::PendingReceiver<mojom::WebNNContext> receiver, + WebNNContextProviderImpl* context_provider) + : WebNNContextImpl(std::move(receiver), context_provider) {} + +ContextImpl::~ContextImpl() = default; + +void ContextImpl::CreateGraphImpl( + mojom::GraphInfoPtr graph_info, + mojom::WebNNContext::CreateGraphCallback callback) { + GraphImpl::CreateAndBuild(std::move(graph_info), std::move(callback)); +} + +} // namespace webnn::tflite
diff --git a/services/webnn/tflite/context_impl.h b/services/webnn/tflite/context_impl.h new file mode 100644 index 0000000..e998a94e --- /dev/null +++ b/services/webnn/tflite/context_impl.h
@@ -0,0 +1,31 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_WEBNN_TFLITE_CONTEXT_IMPL_H_ +#define SERVICES_WEBNN_TFLITE_CONTEXT_IMPL_H_ + +#include "services/webnn/webnn_context_impl.h" + +namespace webnn::tflite { + +// `ContextImpl` is created by `WebNNContextProviderImpl` and responsible for +// creating a `GraphImpl` which uses TFLite for inference. +class ContextImpl final : public WebNNContextImpl { + public: + ContextImpl(mojo::PendingReceiver<mojom::WebNNContext> receiver, + WebNNContextProviderImpl* context_provider); + + ContextImpl(const WebNNContextImpl&) = delete; + ContextImpl& operator=(const ContextImpl&) = delete; + + ~ContextImpl() override; + + private: + void CreateGraphImpl(mojom::GraphInfoPtr graph_info, + CreateGraphCallback callback) override; +}; + +} // namespace webnn::tflite + +#endif // SERVICES_WEBNN_DML_CONTEXT_IMPL_H_
diff --git a/services/webnn/tflite/graph_builder.cc b/services/webnn/tflite/graph_builder.cc new file mode 100644 index 0000000..c9a9403 --- /dev/null +++ b/services/webnn/tflite/graph_builder.cc
@@ -0,0 +1,459 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/webnn/tflite/graph_builder.h" + +#include "base/numerics/checked_math.h" +#include "base/ranges/algorithm.h" +#include "base/strings/stringprintf.h" +#include "base/types/expected_macros.h" +#include "components/ml/webnn/graph_validation_utils.h" +#include "services/webnn/public/mojom/webnn_graph.mojom.h" +#include "third_party/tflite/src/tensorflow/lite/schema/schema_generated.h" + +namespace webnn::tflite { + +namespace { + +// The version number of the Schema. Ideally all changes will be backward +// compatible. If that ever changes, we must ensure that version is the first +// entry in the new tflite root so that we can see that version is not 1. +#define TFLITE_SCHEMA_VERSION (3) + +base::expected<std::vector<int32_t>, std::string> ConvertDimensions( + const std::vector<uint32_t>& input_dimensions) { + std::vector<int32_t> output_dimensions; + output_dimensions.reserve(input_dimensions.size()); + for (auto dimension : input_dimensions) { + auto checked_dimension = base::MakeCheckedNum<int32_t>(dimension); + if (!checked_dimension.IsValid()) { + return base::unexpected("The dimension is too large."); + } + output_dimensions.push_back(checked_dimension.ValueOrDie()); + } + return output_dimensions; +} + +::tflite::TensorType MojoOperandTypeToTFLite( + mojom::Operand::DataType data_type) { + switch (data_type) { + case mojom::Operand::DataType::kFloat32: + return ::tflite::TensorType_FLOAT32; + case mojom::Operand::DataType::kFloat16: + return ::tflite::TensorType_FLOAT16; + case mojom::Operand::DataType::kInt32: + return ::tflite::TensorType_INT32; + case mojom::Operand::DataType::kUint32: + return ::tflite::TensorType_UINT32; + case mojom::Operand::DataType::kInt64: + return ::tflite::TensorType_INT64; + case mojom::Operand::DataType::kUint64: + return ::tflite::TensorType_UINT64; + case mojom::Operand::DataType::kInt8: + return ::tflite::TensorType_INT8; + case mojom::Operand::DataType::kUint8: + return ::tflite::TensorType_UINT8; + } +} + +enum class ClampRange { kRelu, kRelu1, kRelu6 }; + +base::expected<ClampRange, std::string> GetClampRange( + const mojom::Clamp& clamp) { + // TODO(crbug.com/326156496): Use RELU_0_TO_1 to support min = 0.0f and max + // = 1.0f. + if (clamp.min_value == -1.0f && clamp.max_value == 1.0f) { + return ClampRange::kRelu1; + } else if (clamp.min_value == 0.0f && clamp.max_value == 6.0f) { + return ClampRange::kRelu6; + } else if (clamp.min_value == 0.0f && + clamp.max_value == std::numeric_limits<float>::infinity()) { + return ClampRange::kRelu; + } + + // TODO(crbug.com/326156496): Support other range. + return base::unexpected( + "The range of clamp is not supported in tflite schema."); +} + +} // namespace + +// static +base::expected<flatbuffers::DetachedBuffer, std::string> +GraphBuilder::CreateAndBuild(const mojom::GraphInfo& graph_info) { + GraphBuilder builder; + + for (const auto& [operand_id, operand] : graph_info.id_to_operand_map) { + RETURN_IF_ERROR(builder.SerializeOperand( + operand_id, *operand, graph_info.constant_id_to_buffer_map)); + } + + for (const mojom::OperationPtr& operation : graph_info.operations) { + RETURN_IF_ERROR(builder.SerializeOperation(*operation)); + } + + return builder.FinishAndTakeFlatBuffer(graph_info.input_operands, + graph_info.output_operands); +} + +GraphBuilder::GraphBuilder() { + // TFLite requires the first entry in FlatBuffer to be an empty buffer. + buffers_.push_back( + ::tflite::CreateBuffer(builder_, builder_.CreateVector({}))); +} + +GraphBuilder::~GraphBuilder() = default; + +base::expected<void, std::string> GraphBuilder::SerializeOperand( + uint64_t operand_id, + const mojom::Operand& operand, + const base::flat_map<uint64_t, mojo_base::BigBuffer>& + constant_id_to_buffer_map) { + // The index of `tflite::Tensor` array, each `Operand` (input, constant, + // output) will be converted and pushed back into the array, so it's increased + // by one after each serialization in flat buffer. + int32_t tensor_index = base::checked_cast<int32_t>(tensors_.size()); + CHECK_GE(tensor_index, 0); + + // The buffer index 0 represents input and output operand because there is no + // data buffer associated. + uint32_t buffer_index = 0; + if (operand.kind == mojom::Operand::Kind::kConstant) { + // Serialize buffer and return buffer index which starts from 1, it is + // used to create the constant's tensor. + buffer_index = SerializeBuffer(constant_id_to_buffer_map.at(operand_id)); + } + + // Create `Tensor` with operand shape, the index of buffer and the name. + const auto dimensions_result = ConvertDimensions(operand.dimensions); + RETURN_IF_ERROR(dimensions_result); + const flatbuffers::Offset<flatbuffers::Vector<int32_t>> dimensions = + builder_.CreateVector<int32_t>(dimensions_result.value()); + const auto operand_type = MojoOperandTypeToTFLite(operand.data_type); + const StringOffset operand_name = + operand.name.has_value() ? builder_.CreateString(*operand.name) : 0; + tensors_.emplace_back(::tflite::CreateTensor(builder_, std::move(dimensions), + operand_type, buffer_index, + operand_name)); + operand_to_index_map_.insert({operand_id, tensor_index}); + return base::ok(); +} + +base::expected<void, std::string> GraphBuilder::SerializeOperation( + const mojom::Operation& op) { + OperatorOffset operator_offset; + switch (op.which()) { + case mojom::Operation::Tag::kClamp: { + const auto clamp_result = SerializeClamp(*op.get_clamp()); + RETURN_IF_ERROR(clamp_result); + operator_offset = clamp_result.value(); + break; + } + case mojom::Operation::Tag::kConcat: + operator_offset = SerializeConcat(*op.get_concat()); + break; + case mojom::Operation::Tag::kElementWiseBinary: { + const auto elementwise_result = + SerializeElementWiseBinary(*op.get_element_wise_binary()); + RETURN_IF_ERROR(elementwise_result); + operator_offset = elementwise_result.value(); + break; + } + case mojom::Operation::Tag::kElementWiseUnary: { + const auto elementwise_result = + SerializeElementWiseUnary(*op.get_element_wise_unary()); + RETURN_IF_ERROR(elementwise_result); + operator_offset = elementwise_result.value(); + break; + } + case mojom::Operation::Tag::kArgMinMax: + return base::unexpected("argMinMax is not implemented"); + case mojom::Operation::Tag::kBatchNormalization: + return base::unexpected("batchNormalization is not implemented"); + case mojom::Operation::Tag::kConv2d: + return base::unexpected("conv2d is not implemented"); + case mojom::Operation::Tag::kElu: + return base::unexpected("elu is not implemented"); + case mojom::Operation::Tag::kExpand: + return base::unexpected("expand is not implemented"); + case mojom::Operation::Tag::kGather: + return base::unexpected("gather is not implemented"); + case mojom::Operation::Tag::kGemm: + return base::unexpected("gemm is not implemented"); + case mojom::Operation::Tag::kHardSigmoid: + return base::unexpected("hardSigmoid is not implemented"); + case mojom::Operation::Tag::kHardSwish: + return base::unexpected("hardSwish is not implemented"); + case mojom::Operation::Tag::kLayerNormalization: + return base::unexpected("layerNormalization is not implemented"); + case mojom::Operation::Tag::kInstanceNormalization: + return base::unexpected("instanceNormalization is not implemented"); + case mojom::Operation::Tag::kLeakyRelu: + return base::unexpected("leakyRelu is not implemented"); + case mojom::Operation::Tag::kLinear: + return base::unexpected("linear is not implemented"); + case mojom::Operation::Tag::kMatmul: + return base::unexpected("matmul is not implemented"); + case mojom::Operation::Tag::kPad: + return base::unexpected("pad is not implemented"); + case mojom::Operation::Tag::kPool2d: + return base::unexpected("pool2d is not implemented"); + case mojom::Operation::Tag::kPrelu: + return base::unexpected("prelu is not implemented"); + case mojom::Operation::Tag::kReduce: + return base::unexpected("reduce is not implemented"); + case mojom::Operation::Tag::kRelu: + return base::unexpected("relu is not implemented"); + case mojom::Operation::Tag::kResample2d: + return base::unexpected("resample2d is not implemented"); + case mojom::Operation::Tag::kReshape: + return base::unexpected("reshape is not implemented"); + case mojom::Operation::Tag::kSigmoid: + return base::unexpected("sigmoid is not implemented"); + case mojom::Operation::Tag::kSlice: + return base::unexpected("slice is not implemented"); + case mojom::Operation::Tag::kSoftmax: + return base::unexpected("softmax is not implemented"); + case mojom::Operation::Tag::kSoftplus: + return base::unexpected("softplus is not implemented"); + case mojom::Operation::Tag::kSoftsign: + return base::unexpected("softsign is not implemented"); + case mojom::Operation::Tag::kSplit: + return base::unexpected("split is not implemented"); + case mojom::Operation::Tag::kTanh: + return base::unexpected("tanh is not implemented"); + case mojom::Operation::Tag::kTranspose: + return base::unexpected("transpose is not implemented"); + case mojom::Operation::Tag::kWhere: + return base::unexpected("where is not implemented"); + } + operators_.emplace_back(operator_offset); + + return base::ok(); +} + +flatbuffers::DetachedBuffer GraphBuilder::FinishAndTakeFlatBuffer( + const std::vector<uint64_t>& input_operands, + const std::vector<uint64_t>& output_operands) { + CHECK(!is_created_model_); + + int32_t* graph_input_ids = nullptr; + auto graph_input_ids_index = builder_.CreateUninitializedVector<int32_t>( + input_operands.size(), &graph_input_ids); + base::ranges::transform(input_operands, graph_input_ids, + [&](uint64_t operand_id) { + return operand_to_index_map_.at(operand_id); + }); + + int32_t* graph_output_ids = nullptr; + auto graph_output_ids_index = builder_.CreateUninitializedVector<int32_t>( + output_operands.size(), &graph_output_ids); + base::ranges::transform(output_operands, graph_output_ids, + [&](uint64_t operand_id) { + return operand_to_index_map_.at(operand_id); + }); + + // Create `tflite::SubGraph`, which typically represents an entire model. + // The inputs of subgraph are the list of non-static tensors that feed into + // the subgraph for inference. The outputs of subgraph are considered the + // product of the subgraph's inference. The operators are in execution order. + flatbuffers::Offset<::tflite::SubGraph> subgraph = ::tflite::CreateSubGraph( + builder_, builder_.CreateVector(tensors_.data(), tensors_.size()), + graph_input_ids_index, graph_output_ids_index, + builder_.CreateVector(operators_.data(), operators_.size())); + + StringOffset description = + builder_.CreateString("TFLite model converted from WebNN Graph"); + + // The operator codes used in this model are kept in order because operators + // carry an index into this std::vector. + // There is only one subgraph in the model. The buffers of the model must be + // initialized an empty buffer. + flatbuffers::Offset<::tflite::Model> model_buffer = ::tflite::CreateModel( + builder_, TFLITE_SCHEMA_VERSION, + builder_.CreateVector(operator_codes_.data(), operator_codes_.size()), + builder_.CreateVector(&subgraph, 1), description, + builder_.CreateVector(buffers_.data(), buffers_.size())); + + ::tflite::FinishModelBuffer(builder_, model_buffer); + is_created_model_ = true; + + return builder_.Release(); +} + +uint32_t GraphBuilder::SerializeBuffer(const mojo_base::BigBuffer& constant) { + // Create `tflite::Buffer` with raw data buffers for constant operand. + const auto buffer_data = + builder_.CreateVector(constant.data(), constant.size()); + const auto buffer_index = base::checked_cast<uint32_t>(buffers_.size()); + buffers_.emplace_back(::tflite::CreateBuffer(builder_, buffer_data)); + // The index of buffer is referenced by tensors. + return buffer_index; +} + +uint32_t GraphBuilder::GetOperatorCodeIndex(::tflite::BuiltinOperator code) { + auto operator_code_index = + base::checked_cast<uint32_t>(operator_codes_.size()); + operator_codes_.push_back(::tflite::CreateOperatorCode(builder_, code)); + // The type of operation is determined by the index into the list of the valid + // OperatorCodes. + return operator_code_index; +} + +auto GraphBuilder::SerializeUnaryOperator(::tflite::BuiltinOperator code, + uint64_t input_operand_id, + uint64_t output_operand_id) + -> OperatorOffset { + // Create `tflite::Operator` with the tensor index of inputs and outputs + // operand. The type of operation is determined by the index of the operator + // code. + const uint32_t operator_code_index = GetOperatorCodeIndex(code); + const std::array<int32_t, 1> op_inputs = { + operand_to_index_map_.at(input_operand_id)}; + const std::array<int32_t, 1> op_outputs = { + operand_to_index_map_.at(output_operand_id)}; + return ::tflite::CreateOperator(builder_, operator_code_index, + builder_.CreateVector<int32_t>(op_inputs), + builder_.CreateVector<int32_t>(op_outputs)); +} + +auto GraphBuilder::SerializeClamp(const mojom::Clamp& clamp) + -> base::expected<OperatorOffset, std::string> { + const auto range_result = GetClampRange(clamp); + RETURN_IF_ERROR(range_result); + + ::tflite::BuiltinOperator code; + switch (range_result.value()) { + case ClampRange::kRelu: + code = ::tflite::BuiltinOperator_RELU; + break; + case ClampRange::kRelu1: + code = ::tflite::BuiltinOperator_RELU_N1_TO_1; + break; + case ClampRange::kRelu6: + code = ::tflite::BuiltinOperator_RELU6; + break; + } + + return SerializeUnaryOperator(code, clamp.input_operand_id, + clamp.output_operand_id); +} + +auto GraphBuilder::SerializeConcat(const mojom::Concat& concat) + -> OperatorOffset { + int32_t* operator_inputs = nullptr; + auto operator_inputs_index = builder_.CreateUninitializedVector<int32_t>( + concat.input_operand_ids.size(), &operator_inputs); + base::ranges::transform(concat.input_operand_ids, operator_inputs, + [&](uint64_t operand_id) { + return operand_to_index_map_.at(operand_id); + }); + + const int32_t output_index = + operand_to_index_map_.at(concat.output_operand_id); + + // Create `tflite::ConcatenationOptions` with axis. + const auto concat_options = + ::tflite::CreateConcatenationOptions(builder_, concat.axis); + + // Create `tflite::Operator` with the tensor index of inputs and outputs + // operand. The type of operation is determined by the index of the operator + // code. + const auto operator_code_index = + GetOperatorCodeIndex(::tflite::BuiltinOperator_CONCATENATION); + const std::array<int32_t, 1> operator_outputs = {output_index}; + return ::tflite::CreateOperator( + builder_, operator_code_index, operator_inputs_index, + builder_.CreateVector<int32_t>(operator_outputs), + ::tflite::BuiltinOptions_ConcatenationOptions, concat_options.Union()); +} + +auto GraphBuilder::SerializeElementWiseBinary( + const mojom::ElementWiseBinary& op) + -> base::expected<OperatorOffset, std::string> { + ::tflite::BuiltinOperator code; + switch (op.kind) { + case mojom::ElementWiseBinary_Kind::kAdd: + code = ::tflite::BuiltinOperator_ADD; + break; + case mojom::ElementWiseBinary_Kind::kSub: + code = ::tflite::BuiltinOperator_SUB; + break; + case mojom::ElementWiseBinary_Kind::kMul: + code = ::tflite::BuiltinOperator_MUL; + break; + case mojom::ElementWiseBinary_Kind::kDiv: + code = ::tflite::BuiltinOperator_DIV; + break; + case mojom::ElementWiseBinary_Kind::kMax: + code = ::tflite::BuiltinOperator_MAXIMUM; + break; + case mojom::ElementWiseBinary_Kind::kMin: + code = ::tflite::BuiltinOperator_MINIMUM; + break; + case mojom::ElementWiseBinary_Kind::kPow: + code = ::tflite::BuiltinOperator_POW; + break; + case mojom::ElementWiseBinary_Kind::kEqual: + case mojom::ElementWiseBinary_Kind::kGreater: + case mojom::ElementWiseBinary_Kind::kGreaterOrEqual: + case mojom::ElementWiseBinary_Kind::kLesser: + case mojom::ElementWiseBinary_Kind::kLesserOrEqual: + return base::unexpected( + base::StrCat({base::ToString(op.kind), " is not implemented."})); + } + + const uint32_t operator_code_index = GetOperatorCodeIndex(code); + const std::array<int32_t, 2> op_inputs = { + operand_to_index_map_.at(op.lhs_operand), + operand_to_index_map_.at(op.rhs_operand)}; + const std::array<int32_t, 1> op_outputs = { + operand_to_index_map_.at(op.output_operand)}; + return ::tflite::CreateOperator(builder_, operator_code_index, + builder_.CreateVector<int32_t>(op_inputs), + builder_.CreateVector<int32_t>(op_outputs)); +} + +auto GraphBuilder::SerializeElementWiseUnary(const mojom::ElementWiseUnary& op) + -> base::expected<OperatorOffset, std::string> { + switch (op.kind) { + case mojom::ElementWiseUnary::Kind::kAbs: + return SerializeUnaryOperator(::tflite::BuiltinOperator_ABS, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kCeil: + return SerializeUnaryOperator(::tflite::BuiltinOperator_CEIL, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kCos: + return SerializeUnaryOperator(::tflite::BuiltinOperator_COS, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kExp: + return SerializeUnaryOperator(::tflite::BuiltinOperator_EXP, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kFloor: + return SerializeUnaryOperator(::tflite::BuiltinOperator_FLOOR, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kLog: + return SerializeUnaryOperator(::tflite::BuiltinOperator_LOG, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kNeg: + return SerializeUnaryOperator(::tflite::BuiltinOperator_NEG, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kSin: + return SerializeUnaryOperator(::tflite::BuiltinOperator_SIN, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kSqrt: + return SerializeUnaryOperator(::tflite::BuiltinOperator_SQRT, + op.input_operand_id, op.output_operand_id); + case mojom::ElementWiseUnary::Kind::kTan: + case mojom::ElementWiseUnary::Kind::kLogicalNot: + case mojom::ElementWiseUnary::Kind::kIdentity: + case mojom::ElementWiseUnary::Kind::kErf: + case mojom::ElementWiseUnary::Kind::kReciprocal: + case mojom::ElementWiseUnary::Kind::kCast: + return base::unexpected( + base::StrCat({base::ToString(op.kind), " is not implemented."})); + } +} + +} // namespace webnn::tflite
diff --git a/services/webnn/tflite/graph_builder.h b/services/webnn/tflite/graph_builder.h new file mode 100644 index 0000000..8227340 --- /dev/null +++ b/services/webnn/tflite/graph_builder.h
@@ -0,0 +1,129 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_WEBNN_TFLITE_GRAPH_BUILDER_H_ +#define SERVICES_WEBNN_TFLITE_GRAPH_BUILDER_H_ + +#include <cstdint> +#include <map> +#include <string> +#include <vector> + +#include "base/containers/flat_map.h" +#include "base/types/expected.h" +#include "mojo/public/cpp/base/big_buffer.h" +#include "services/webnn/public/mojom/webnn_graph.mojom-forward.h" +#include "third_party/flatbuffers/src/include/flatbuffers/flatbuffers.h" +#include "third_party/tflite/src/tensorflow/lite/schema/schema_generated.h" + +namespace webnn::tflite { + +// This class converts WebNN graph to tflite model and persist into FlatBuffer. +// The schema_generated.h file defines the format for each data structure to +// serialize. +// +// The instances of the class may not be allocated on the heap, but as a member +// variable of a non-stack-allocated and be single-use per conversion. +class GraphBuilder final { + public: + GraphBuilder(const GraphBuilder&) = delete; + GraphBuilder& operator=(const GraphBuilder&) = delete; + + // Factory method that creates a GraphBuilder and builds a TFLite Flatbuffer + // Returns unexpected if it fails. + [[nodiscard]] static base::expected<flatbuffers::DetachedBuffer, std::string> + CreateAndBuild(const mojom::GraphInfo& graph_info); + + private: + using IdToOperandMap = base::flat_map<uint64_t, mojom::OperandPtr>; + using OperatorCodeOffset = flatbuffers::Offset<::tflite::OperatorCode>; + using OperatorOffset = flatbuffers::Offset<::tflite::Operator>; + using BufferOffset = flatbuffers::Offset<::tflite::Buffer>; + using TensorOffset = flatbuffers::Offset<::tflite::Tensor>; + using StringOffset = flatbuffers::Offset<flatbuffers::String>; + + GraphBuilder(); + ~GraphBuilder(); + + // Serialize tensor for input, constant and output operand. It's output + // operand of graph if the `graph_output_name` is specified, returns the index + // in the `tflite::Tensor` array if it's successful. + base::expected<void, std::string> SerializeOperand( + uint64_t operand_id, + const mojom::Operand& operand, + const base::flat_map<uint64_t, mojo_base::BigBuffer>& + constant_id_to_buffer_map); + + // The following steps implement the `SerializeOperation` function: + // 1. Create `tflite::OperatorCode` with the kind of operator. + // 2. Create `tflite::Operator` with the tensor index of inputs and outputs + // operand. + // + // Returns error messages if it could not be serialized because of unsupported + // options or it is otherwise invalid. + base::expected<void, std::string> SerializeOperation( + const mojom::Operation& op); + + // Serializes the constant data (e.g. weights) to the flat buffer and returns + // the index in the `tflite::Buffer` array if it's successful. + // + // The `Buffer` in TFLite schema is the table of raw data buffers, it is used + // for WebNN constant operations. Referenced by tensors with the index of + // buffer. + uint32_t SerializeBuffer(const mojo_base::BigBuffer& constant); + + uint32_t GetOperatorCodeIndex(::tflite::BuiltinOperator code); + + OperatorOffset SerializeUnaryOperator(::tflite::BuiltinOperator code, + uint64_t input_operand_id, + uint64_t output_operand_id); + + // Serialize functions for members of the mojom::Operation union. Keep these + // functions in the same order as in webnn_graph.mojom. + base::expected<OperatorOffset, std::string> SerializeClamp( + const mojom::Clamp& clamp); + OperatorOffset SerializeConcat(const mojom::Concat& concat); + base::expected<OperatorOffset, std::string> SerializeElementWiseBinary( + const mojom::ElementWiseBinary& op); + base::expected<OperatorOffset, std::string> SerializeElementWiseUnary( + const mojom::ElementWiseUnary& op); + + // There are no further methods should be called on this class after this + // function because the buffer of `buffer_` is now owned by the detached + // buffer. + flatbuffers::DetachedBuffer FinishAndTakeFlatBuffer( + const std::vector<uint64_t>& input_operands, + const std::vector<uint64_t>& output_operands); + + flatbuffers::FlatBufferBuilder builder_; + // `is_created_model_` indicates whether the tflite model is created and the + // detached buffer owns the buffer and its allocator of the `builder_`. + bool is_created_model_ = false; + + // Map from operand IDs in the GraphInfo structure to tensor indices in the + // flat buffer. + std::map<uint64_t, int32_t> operand_to_index_map_; + + // The following std::vector<Offset<tflite:XXX>>> stores the weights of model + // and the tensor information (shape, data type). + // + // The first entry of this `tflite::Buffer` array must be an empty buffer. + // The tensor index in the `tflite::Tensor` array is used to create `Operator` + // and `SubGraph`. + std::vector<BufferOffset> buffers_; + std::vector<TensorOffset> tensors_; + + // The following std::vector<Offset<tflite:XXX>>> stores all operator + // information including operator type, the index of input output tensor to + // get tensor's information. + // + // The list of all operator codes used in this model. This is kept in order + // because operators carry an index into this std::vector. + std::vector<OperatorCodeOffset> operator_codes_; + std::vector<OperatorOffset> operators_; +}; + +} // namespace webnn::tflite + +#endif // SERVICES_WEBNN_TFLITE_GRAPH_BUILDER_H_
diff --git a/services/webnn/tflite/graph_impl.cc b/services/webnn/tflite/graph_impl.cc new file mode 100644 index 0000000..55813ae --- /dev/null +++ b/services/webnn/tflite/graph_impl.cc
@@ -0,0 +1,144 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/webnn/tflite/graph_impl.h" + +#include "base/ranges/algorithm.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "services/webnn/error.h" +#include "services/webnn/public/mojom/webnn_context_provider.mojom.h" +#include "services/webnn/tflite/graph_builder.h" +#include "services/webnn/tflite/op_resolver.h" +#include "services/webnn/webnn_graph_impl.h" +#include "third_party/tflite/src/tensorflow/lite/interpreter_builder.h" +#include "third_party/tflite/src/tensorflow/lite/stderr_reporter.h" + +namespace webnn::tflite { + +namespace { + +std::string_view TfLiteStatusToString(TfLiteStatus status) { + switch (status) { + case kTfLiteOk: + return "ok"; + case kTfLiteError: + return "error"; + case kTfLiteDelegateError: + return "delegate error"; + case kTfLiteApplicationError: + return "application error"; + case kTfLiteDelegateDataNotFound: + return "delegate data not found"; + case kTfLiteDelegateDataWriteError: + return "delegate data write error"; + case kTfLiteDelegateDataReadError: + return "delegate data read error"; + case kTfLiteUnresolvedOps: + return "unresolved ops"; + case kTfLiteCancelled: + return "cancelled"; + } +} + +} // namespace + +// static +void GraphImpl::CreateAndBuild( + mojom::GraphInfoPtr graph_info, + mojom::WebNNContext::CreateGraphCallback callback) { + base::expected<flatbuffers::DetachedBuffer, std::string> conversion_result = + GraphBuilder::CreateAndBuild(*graph_info); + if (!conversion_result.has_value()) { + std::move(callback).Run(ToError<mojom::CreateGraphResult>( + mojom::Error::Code::kUnknownError, conversion_result.error())); + return; + } + flatbuffers::DetachedBuffer model_content = + std::move(conversion_result).value(); + + std::unique_ptr<::tflite::FlatBufferModel> model = + ::tflite::FlatBufferModel::BuildFromBuffer( + reinterpret_cast<const char*>(model_content.data()), + model_content.size(), ::tflite::DefaultErrorReporter()); + if (!model) { + std::move(callback).Run(ToError<mojom::CreateGraphResult>( + mojom::Error::Code::kUnknownError, "Unable to build flatbuffer model")); + return; + } + + OpResolver op_resolver; + std::unique_ptr<::tflite::Interpreter> interpreter; + TfLiteStatus status = + ::tflite::InterpreterBuilder(*model, op_resolver)(&interpreter); + if (status != kTfLiteOk) { + std::move(callback).Run(ToError<mojom::CreateGraphResult>( + mojom::Error::Code::kUnknownError, + base::StrCat({"Unable to build TFLite intepreter: ", + TfLiteStatusToString(status)}))); + return; + } + + status = interpreter->AllocateTensors(); + if (status != kTfLiteOk) { + std::move(callback).Run(ToError<mojom::CreateGraphResult>( + mojom::Error::Code::kUnknownError, + base::StrCat( + {"Unable to allocate tensors: ", TfLiteStatusToString(status)}))); + return; + } + + mojo::PendingRemote<mojom::WebNNGraph> graph; + mojo::MakeSelfOwnedReceiver<mojom::WebNNGraph>( + base::WrapUnique(new GraphImpl(ComputeResourceInfo(graph_info), + std::move(model_content), std::move(model), + std::move(interpreter))), + graph.InitWithNewPipeAndPassReceiver()); + std::move(callback).Run( + mojom::CreateGraphResult::NewGraphRemote(std::move(graph))); +} + +GraphImpl::~GraphImpl() = default; + +GraphImpl::GraphImpl(ComputeResourceInfo compute_resource_info, + flatbuffers::DetachedBuffer model_content, + std::unique_ptr<::tflite::FlatBufferModel> model, + std::unique_ptr<::tflite::Interpreter> interpreter) + : WebNNGraphImpl(std::move(compute_resource_info)), + model_content_(std::move(model_content)), + model_(std::move(model)), + interpreter_(std::move(interpreter)) {} + +void GraphImpl::ComputeImpl( + base::flat_map<std::string, mojo_base::BigBuffer> named_inputs, + mojom::WebNNGraph::ComputeCallback callback) { + for (int tensor_idx : interpreter_->inputs()) { + TfLiteTensor* tensor = interpreter_->tensor(tensor_idx); + auto it = named_inputs.find(tensor->name); + // The caller guarantees that all expected tensors have been provided. + CHECK(it != named_inputs.end()); + std::ranges::copy(base::make_span(it->second), tensor->data.raw); + } + + TfLiteStatus status = interpreter_->Invoke(); + if (status != kTfLiteOk) { + std::move(callback).Run(ToError<mojom::ComputeResult>( + mojom::Error::Code::kUnknownError, + base::StrCat({"Failed to compute: ", TfLiteStatusToString(status)}))); + return; + } + + std::vector<std::pair<std::string, mojo_base::BigBuffer>> named_outputs; + named_outputs.reserve(interpreter_->outputs().size()); + for (int tensor_idx : interpreter_->outputs()) { + TfLiteTensor* tensor = interpreter_->tensor(tensor_idx); + auto tensor_span = base::make_span(tensor->data.raw, tensor->bytes); + named_outputs.emplace_back( + tensor->name, mojo_base::BigBuffer(base::as_bytes(tensor_span))); + } + + std::move(callback).Run( + mojom::ComputeResult::NewNamedOutputs(std::move(named_outputs))); +} + +} // namespace webnn::tflite
diff --git a/services/webnn/tflite/graph_impl.h b/services/webnn/tflite/graph_impl.h new file mode 100644 index 0000000..502082e8 --- /dev/null +++ b/services/webnn/tflite/graph_impl.h
@@ -0,0 +1,50 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_WEBNN_TFLITE_GRAPH_IMPL_H_ +#define SERVICES_WEBNN_TFLITE_GRAPH_IMPL_H_ + +#include "services/webnn/public/mojom/webnn_graph.mojom.h" +#include "services/webnn/webnn_graph_impl.h" +#include "third_party/flatbuffers/src/include/flatbuffers/flatbuffers.h" +#include "third_party/tflite/src/tensorflow/lite/core/interpreter.h" +#include "third_party/tflite/src/tensorflow/lite/model_builder.h" + +namespace webnn::tflite { + +// GraphImpl inherits from WebNNGraphImpl to represent a TFLite graph +// implementation. It is mainly responsible for building a TFLite flatbuffer +// model from mojom::GraphInfo via tflite::GraphBuilder, then initializing and +// executing the graph. +class GraphImpl final : public WebNNGraphImpl { + public: + static void CreateAndBuild(mojom::GraphInfoPtr graph_info, + mojom::WebNNContext::CreateGraphCallback callback); + + GraphImpl(const GraphImpl&) = delete; + GraphImpl& operator=(const GraphImpl&) = delete; + ~GraphImpl() override; + + private: + GraphImpl(ComputeResourceInfo compute_resource_info, + flatbuffers::DetachedBuffer model_content, + std::unique_ptr<::tflite::FlatBufferModel> model, + std::unique_ptr<::tflite::Interpreter> intepreter); + + // Execute the compiled platform graph asynchronously. The `named_inputs` were + // validated in base class so we can use them to compute directly, the result + // of execution will be returned to renderer process with the `callback`. + void ComputeImpl( + base::flat_map<std::string, mojo_base::BigBuffer> named_inputs, + mojom::WebNNGraph::ComputeCallback callback) override; + + // `interpreter_` depends on `model_` and `model_content_` outliving it. + flatbuffers::DetachedBuffer model_content_; + std::unique_ptr<::tflite::FlatBufferModel> model_; + std::unique_ptr<::tflite::Interpreter> interpreter_; +}; + +} // namespace webnn::tflite + +#endif // SERVICES_WEBNN_TFLITE_GRAPH_IMPL_H_
diff --git a/services/webnn/tflite/op_resolver.cc b/services/webnn/tflite/op_resolver.cc new file mode 100644 index 0000000..e868aa3 --- /dev/null +++ b/services/webnn/tflite/op_resolver.cc
@@ -0,0 +1,133 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/webnn/tflite/op_resolver.h" + +#include "third_party/tflite/src/tensorflow/lite/kernels/builtin_op_kernels.h" + +namespace webnn::tflite { + +OpResolver::OpResolver() { + AddBuiltin(::tflite::BuiltinOperator_ABS, + ::tflite::ops::builtin::Register_ABS()); + AddBuiltin(::tflite::BuiltinOperator_AVERAGE_POOL_2D, + ::tflite::ops::builtin::Register_AVERAGE_POOL_2D(), + /* min_version */ 1, + /* max_version */ 3); + AddBuiltin(::tflite::BuiltinOperator_CONCATENATION, + ::tflite::ops::builtin::Register_CONCATENATION(), + /* min_version = */ 1, + /* max_version = */ 3); + AddBuiltin(::tflite::BuiltinOperator_CAST, + ::tflite::ops::builtin::Register_CAST()); + AddBuiltin(::tflite::BuiltinOperator_ADD, + ::tflite::ops::builtin::Register_ADD(), + /* min_version = */ 1, + /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_CEIL, + ::tflite::ops::builtin::Register_CEIL()); + AddBuiltin(::tflite::BuiltinOperator_CONV_2D, + ::tflite::ops::builtin::Register_CONV_2D(), + /* min_version = */ 1, + /* max_version = */ 4); + AddBuiltin(::tflite::BuiltinOperator_COS, + ::tflite::ops::builtin::Register_COS()); + AddBuiltin(::tflite::BuiltinOperator_DEPTHWISE_CONV_2D, + ::tflite::ops::builtin::Register_DEPTHWISE_CONV_2D(), + /* min_version = */ 1, + /* max_version = */ 5); + AddBuiltin(::tflite::BuiltinOperator_DIV, + ::tflite::ops::builtin::Register_DIV(), + /* min_version */ 1, + /* max_version */ 2); + AddBuiltin(::tflite::BuiltinOperator_ELU, + ::tflite::ops::builtin::Register_ELU()); + AddBuiltin(::tflite::BuiltinOperator_EXP, + ::tflite::ops::builtin::Register_EXP()); + AddBuiltin(::tflite::BuiltinOperator_FLOOR, + ::tflite::ops::builtin::Register_FLOOR()); + AddBuiltin(::tflite::BuiltinOperator_FULLY_CONNECTED, + ::tflite::ops::builtin::Register_FULLY_CONNECTED(), + /* min_version = */ 1, + /* max_version = */ 9); + AddBuiltin(::tflite::BuiltinOperator_HARD_SWISH, + ::tflite::ops::builtin::Register_HARD_SWISH()); + AddBuiltin(::tflite::BuiltinOperator_LEAKY_RELU, + ::tflite::ops::builtin::Register_LEAKY_RELU(), + /* min_version = */ 1, + /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_LOG, + ::tflite::ops::builtin::Register_LOG()); + AddBuiltin(::tflite::BuiltinOperator_LOGISTIC, + ::tflite::ops::builtin::Register_LOGISTIC(), + /* min_version = */ 1, + /* max_version = */ 3); + AddBuiltin(::tflite::BuiltinOperator_MAX_POOL_2D, + ::tflite::ops::builtin::Register_MAX_POOL_2D(), + /* min_version */ 1, + /* max_version */ 3); + AddBuiltin(::tflite::BuiltinOperator_MAXIMUM, + ::tflite::ops::builtin::Register_MAXIMUM(), + /* min_version = */ 1, + /* max_version = */ 4); + AddBuiltin(::tflite::BuiltinOperator_MINIMUM, + ::tflite::ops::builtin::Register_MINIMUM(), + /* min_version = */ 1, + /* max_version = */ 4); + AddBuiltin(::tflite::BuiltinOperator_MIRROR_PAD, + ::tflite::ops::builtin::Register_MIRROR_PAD(), + /* min_version = */ 1, + /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_MUL, + ::tflite::ops::builtin::Register_MUL(), + /* min_version = */ 1, + /* max_version = */ 4); + AddBuiltin(::tflite::BuiltinOperator_NEG, + ::tflite::ops::builtin::Register_NEG()); + AddBuiltin(::tflite::BuiltinOperator_PAD, + ::tflite::ops::builtin::Register_PAD(), + /* min_version = */ 1, + /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_PADV2, + ::tflite::ops::builtin::Register_PADV2(), /* min_version = */ 1, + /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_POW, + ::tflite::ops::builtin::Register_POW()); + AddBuiltin(::tflite::BuiltinOperator_RELU, + ::tflite::ops::builtin::Register_RELU(), /* min_version = */ 1, + /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_RELU_N1_TO_1, + ::tflite::ops::builtin::Register_RELU_N1_TO_1()); + AddBuiltin(::tflite::BuiltinOperator_RELU6, + ::tflite::ops::builtin::Register_RELU6(), /* min_version = */ 1, + /* max_version = */ 2); + AddBuiltin(::tflite::BuiltinOperator_RESHAPE, + ::tflite::ops::builtin::Register_RESHAPE()); + AddBuiltin(::tflite::BuiltinOperator_RESIZE_BILINEAR, + ::tflite::ops::builtin::Register_RESIZE_BILINEAR(), + /* min_version = */ 1, + /* max_version = */ 3); + AddBuiltin(::tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, + ::tflite::ops::builtin::Register_RESIZE_NEAREST_NEIGHBOR(), + /* min_version = */ 1, + /* max_version = */ 3); + AddBuiltin(::tflite::BuiltinOperator_SIN, + ::tflite::ops::builtin::Register_SIN()); + AddBuiltin(::tflite::BuiltinOperator_SOFTMAX, + ::tflite::ops::builtin::Register_SOFTMAX(), + /* min_version = */ 1, + /* max_version = */ 3); + AddBuiltin(::tflite::BuiltinOperator_SQRT, + ::tflite::ops::builtin::Register_SQRT()); + AddBuiltin(::tflite::BuiltinOperator_SUB, + ::tflite::ops::builtin::Register_SUB(), + /* min_version = */ 1, + /* max_version = */ 3); + AddBuiltin(::tflite::BuiltinOperator_TRANSPOSE, + ::tflite::ops::builtin::Register_TRANSPOSE(), + /* min_version = */ 1, + /* max_version = */ 4); +} + +} // namespace webnn::tflite
diff --git a/services/webnn/tflite/op_resolver.h b/services/webnn/tflite/op_resolver.h new file mode 100644 index 0000000..413c202 --- /dev/null +++ b/services/webnn/tflite/op_resolver.h
@@ -0,0 +1,21 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SERVICES_WEBNN_TFLITE_OP_RESOLVER_H_ +#define SERVICES_WEBNN_TFLITE_OP_RESOLVER_H_ + +#include "third_party/tflite/src/tensorflow/lite/mutable_op_resolver.h" + +namespace webnn::tflite { + +// This class maintains all the currently supported TFLite +// operations for the Chromium build of TFLite and registers them for use. +class OpResolver : public ::tflite::MutableOpResolver { + public: + OpResolver(); +}; + +} // namespace webnn::tflite + +#endif // SERVICES_WEBNN_TFLITE_OP_RESOLVER_H_
diff --git a/services/webnn/webnn_context_provider_impl.cc b/services/webnn/webnn_context_provider_impl.cc index 221e108..d5fbd13 100644 --- a/services/webnn/webnn_context_provider_impl.cc +++ b/services/webnn/webnn_context_provider_impl.cc
@@ -21,6 +21,10 @@ #include "services/webnn/coreml/context_impl.h" #endif +#if BUILDFLAG(IS_LINUX) +#include "services/webnn/tflite/context_impl.h" +#endif + namespace webnn { namespace { @@ -67,6 +71,7 @@ std::move(callback)); return; } +#if BUILDFLAG(IS_WIN) if (!is_gpu_supported_) { std::move(callback).Run(ToError<mojom::CreateContextResult>( mojom::Error::Code::kNotSupportedError, @@ -74,7 +79,6 @@ DLOG(ERROR) << "WebNN is not compatible with GPU."; return; } -#if BUILDFLAG(IS_WIN) // Get the default `Adapter` instance which is created for the adapter queried // from ANGLE. At the current stage, all `ContextImpl` share this instance. // @@ -112,6 +116,13 @@ "WebNN Service is not supported on this platform.")); DLOG(ERROR) << "WebNN Service is not supported on this platform."; } +#elif BUILDFLAG(IS_LINUX) + // The remote sent to the renderer. + mojo::PendingRemote<mojom::WebNNContext> blink_remote; + impls_.push_back(base::WrapUnique<WebNNContextImpl>(new tflite::ContextImpl( + blink_remote.InitWithNewPipeAndPassReceiver(), this))); + std::move(callback).Run( + mojom::CreateContextResult::NewContextRemote(std::move(blink_remote))); #else // TODO(crbug.com/1273291): Supporting WebNN Service on the platform. std::move(callback).Run(ToError<mojom::CreateContextResult>(
diff --git a/services/webnn/webnn_context_provider_impl_unittest.cc b/services/webnn/webnn_context_provider_impl_unittest.cc index 12a9679..ad668d90 100644 --- a/services/webnn/webnn_context_provider_impl_unittest.cc +++ b/services/webnn/webnn_context_provider_impl_unittest.cc
@@ -45,10 +45,13 @@ // For Windows platform, `dml::ContextImpl` is implemented by the DirectML // backend. It relies on a real GPU adapter and is tested by // `WebNNContextDMLImplTest`. +// +// For Linux platform, `tflite::ContextImpl` is implemented using TFLite which +// is always available. -#if !BUILDFLAG(IS_WIN) +#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_LINUX) -TEST_F(WebNNContextProviderImplTest, CreateWebNNContextTest) { +TEST_F(WebNNContextProviderImplTest, NotSupported) { #if BUILDFLAG(IS_MAC) if (base::mac::MacOSVersion() >= 13'00'00) { GTEST_SKIP() << "Skipping test because WebNN is supported on Mac OS " @@ -74,6 +77,9 @@ #endif +#if BUILDFLAG(IS_WIN) +// Checking for GPU compatibility is Windows-specific because only the DirectML +// implementation unconditionally depends on a GPU. TEST_F(WebNNContextProviderImplTest, GPUNotSupported) { mojo::Remote<mojom::WebNNContextProvider> provider_remote; @@ -89,5 +95,6 @@ EXPECT_EQ(create_context_error->code, mojom::Error::Code::kNotSupportedError); EXPECT_EQ(create_context_error->message, "WebNN is not compatible with GPU."); } +#endif } // namespace webnn
diff --git a/services/webnn/webnn_graph_impl_backend_test.cc b/services/webnn/webnn_graph_impl_backend_test.cc index ae50995d..8318590 100644 --- a/services/webnn/webnn_graph_impl_backend_test.cc +++ b/services/webnn/webnn_graph_impl_backend_test.cc
@@ -6,6 +6,7 @@ #include <cmath> #include <type_traits> +#include "base/containers/fixed_flat_set.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/test/bind.h" @@ -38,7 +39,6 @@ #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_MAC) -#include "base/containers/fixed_flat_set.h" #include "base/mac/mac_util.h" #endif // BUILDFLAG(IS_MAC) @@ -74,6 +74,8 @@ webnn_context_remote.Bind( std::move(create_context_result->get_context_remote())); } + EXPECT_FALSE(create_context_result->is_error()) + << create_context_result->get_error()->message; EXPECT_TRUE(webnn_context_remote.is_bound()); // The GraphImpl should be built successfully. @@ -95,6 +97,8 @@ base::RunLoop().RunUntilIdle(); return; } + EXPECT_FALSE(create_graph_result->is_error()) + << create_graph_result->get_error()->message; EXPECT_TRUE(webnn_graph_remote.is_bound()); // The GraphImpl should compute successfully. @@ -324,6 +328,33 @@ } #endif // BUILDFLAG(IS_MAC) +#if BUILDFLAG(IS_LINUX) +class WebNNGraphImplBackendTest : public testing::Test { + public: + void SetUp() override; + + protected: + base::test::ScopedFeatureList scoped_feature_list_; + base::test::TaskEnvironment task_environment_; +}; + +void WebNNGraphImplBackendTest::SetUp() { + const std::string_view current_test_name = + ::testing::UnitTest::GetInstance()->current_test_info()->name(); + static auto kSupportedTests = base::MakeFixedFlatSet<std::string_view>({ + "BuildAndComputeSingleOperatorElementWiseBinary", + "BuildAndComputeSingleOperatorElementWiseUnary", + "BuildAndComputeSingleOperatorConcat", + "BuildAndComputeConcatWithConstants", + }); + if (!kSupportedTests.contains(current_test_name)) { + GTEST_SKIP() << "Skipping test because the operator is not yet supported."; + } + scoped_feature_list_.InitAndEnableFeature( + webnn::mojom::features::kWebMachineLearningNeuralNetwork); +} +#endif // BUILDFLAG(IS_LINUX) + template <typename T> struct ArgMinMaxTester { OperandInfo<T> input; @@ -1782,6 +1813,10 @@ .values = {-1, 0, 1, 2, 3, 4}}} .Test(); } + + // TODO(https://issues.chromium.org/326356909): Enable these tests on Linux, + // after adding support for other binary operators. +#if !BUILDFLAG(IS_LINUX) // Test building and computing a graph with single operator equal. { ElementWiseBinaryTester<float, uint8_t>{ @@ -1947,6 +1982,7 @@ .values = {1, 1, 1, 1, 0, 0}}} .Test(); } +#endif // !BUILDFLAG(IS_LINUX) #endif // !BUILDFLAG(IS_MAC) } @@ -2000,6 +2036,10 @@ .type = mojom::Operand::DataType::kUint8, .dimensions = {1, 2, 3, 1}, .values = {0, 2, 0, 4, 5, 120}}; + + // TODO(https://issues.chromium.org/326356909): Enable these tests on Linux, + // after adding support for other unary operators. +#if !BUILDFLAG(IS_LINUX) { ElementWiseUnaryTester<uint8_t>{ .input = {.type = mojom::Operand::DataType::kUint8, @@ -2053,6 +2093,8 @@ .output = test_operand_info_uint8} .Test(); } +#endif // !BUILDFLAG(IS_LINUX) + { // Test Sqrt with 0-D scalar input. ElementWiseUnaryTester<float>{ @@ -2076,6 +2118,10 @@ .values = {0, 2, 5, 4, 8, 7}}} .Test(); } + + // TODO(https://issues.chromium.org/326356909): Enable these tests on Linux, + // after adding support for float16 and other unary operators. +#if !BUILDFLAG(IS_LINUX) { ElementWiseUnaryTester<float16>{ .input = {.type = mojom::Operand::DataType::kFloat16, @@ -2134,6 +2180,8 @@ std::numeric_limits<float>::infinity()})}} .Test(); } +#endif // !BUILDFLAG(IS_LINUX) + { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32, @@ -2178,6 +2226,10 @@ .values = {exp(1.f), exp(-2.f), exp(3.f), exp(-4.f)}}} .Test(); } + + // TODO(https://issues.chromium.org/326356909): Enable these tests on Linux, + // after adding support for other unary operators. +#if !BUILDFLAG(IS_LINUX) { ElementWiseUnaryTester<float16>{ .input = {.type = mojom::Operand::DataType::kFloat16, @@ -2189,6 +2241,8 @@ .values = Float16FromFloat32({-2, 0, 1, -3, 0, 2})}} .Test(); } +#endif // !BUILDFLAG(IS_LINUX) + { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32, @@ -2222,6 +2276,10 @@ .values = {sin(1.f), sin(-2.f), sin(3.f), sin(-4.f)}}} .Test(); } + + // TODO(https://issues.chromium.org/326356909): Enable these tests on Linux, + // after adding support for other unary operators. +#if !BUILDFLAG(IS_LINUX) { ElementWiseUnaryTester<float>{ .input = {.type = mojom::Operand::DataType::kFloat32, @@ -2233,6 +2291,7 @@ .values = {tan(1.f), tan(-2.f), tan(3.f), tan(-4.f)}}} .Test(); } +#endif // !BUILDFLAG(IS_LINUX) } template <typename T> @@ -2829,23 +2888,44 @@ // Test building and computing a graph with single operator max pool2d // with nchw layout. TEST_F(WebNNGraphImplBackendTest, BuildAndComputeSingleOperatorMaxPool2d) { - // Test max pool2d with nchw layout, strides=1, padding=0, and floor - // rounding. - Pool2dTester<float>{ - .input = {.type = mojom::Operand::DataType::kFloat32, - .dimensions = {1, 2, 3, 3}, - .values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18}}, - .attributes = {.window_dimensions = {2, 2}, - .padding = {0, 0, 0, 0}, - .strides = {1, 1}, - .dilations = {1, 1}, - .layout = mojom::InputOperandLayout::kChannelsFirst}, - .kind = mojom::Pool2d::Kind::kMaxPool2d, - .output = {.type = mojom::Operand::DataType::kFloat32, - .dimensions = {1, 2, 2, 2}, - .values = {5, 6, 8, 9, 14, 15, 17, 18}}} - .Test(); + { + // Test max pool2d with nchw layout, strides=1, padding=0, dilations={1,1} + // and floor rounding. + Pool2dTester<float>{ + .input = {.type = mojom::Operand::DataType::kFloat32, + .dimensions = {1, 2, 3, 3}, + .values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18}}, + .attributes = {.window_dimensions = {2, 2}, + .padding = {0, 0, 0, 0}, + .strides = {1, 1}, + .dilations = {1, 1}, + .layout = mojom::InputOperandLayout::kChannelsFirst}, + .kind = mojom::Pool2d::Kind::kMaxPool2d, + .output = {.type = mojom::Operand::DataType::kFloat32, + .dimensions = {1, 2, 2, 2}, + .values = {5, 6, 8, 9, 14, 15, 17, 18}}} + .Test(); + } + { + // Test max pool2d with nchw layout, strides=1, padding=0, dilations={2,2} + // and floor rounding. + Pool2dTester<float>{ + .input = {.type = mojom::Operand::DataType::kFloat32, + .dimensions = {1, 1, 4, 4}, + .values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16}}, + .attributes = {.window_dimensions = {2, 2}, + .padding = {0, 0, 0, 0}, + .strides = {1, 1}, + .dilations = {2, 2}, + .layout = mojom::InputOperandLayout::kChannelsFirst}, + .kind = mojom::Pool2d::Kind::kMaxPool2d, + .output = {.type = mojom::Operand::DataType::kFloat32, + .dimensions = {1, 1, 2, 2}, + .values = {11, 12, 15, 16}}} + .Test(); + } } template <typename T>
diff --git a/services/webnn/webnn_graph_mojolpm_fuzzer.cc b/services/webnn/webnn_graph_mojolpm_fuzzer.cc index f965e86d..2976e37 100644 --- a/services/webnn/webnn_graph_mojolpm_fuzzer.cc +++ b/services/webnn/webnn_graph_mojolpm_fuzzer.cc
@@ -14,6 +14,7 @@ #include "services/webnn/coreml/graph_builder.h" #include "services/webnn/public/mojom/webnn_graph.mojom-mojolpm.h" #include "services/webnn/public/mojom/webnn_graph.mojom.h" +#include "services/webnn/tflite/graph_builder.h" #include "services/webnn/webnn_graph_impl.h" #include "services/webnn/webnn_graph_mojolpm_fuzzer.pb.h" #include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h" @@ -47,7 +48,7 @@ class WebnnGraphLPMFuzzer { public: - WebnnGraphLPMFuzzer( + explicit WebnnGraphLPMFuzzer( const services::fuzzing::webnn_graph::proto::Testcase& testcase) : testcase_(testcase) {} @@ -59,9 +60,12 @@ // Test the cross platform webnn graph validator. mojolpm::FromProto(create_graph.graph_info(), graph_info_ptr); if (webnn::WebNNGraphImpl::ValidateGraph(graph_info_ptr)) { - // Test the coreml graph builder. + // Test the Core ML graph builder. auto coreml_graph_builder = webnn::coreml::GraphBuilder::CreateAndBuild(*graph_info_ptr); + // Test the TFLite graph builder. + auto flatbuffer = + webnn::tflite::GraphBuilder::CreateAndBuild(*graph_info_ptr); } ++action_index_;
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index cd7f0bf..5f3ebefe 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -1118,24 +1118,79 @@ "additional_compile_targets": [ "chromiumos_preflight" ], - "gtest_tests": [ + "skylab_tests": [ { - "merge": { - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "name": "base_unittests", - "swarming": { - "dimensions": { - "device_type": "jacuzzi", - "os": "ChromeOS" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, + "autotest_name": "chromium", + "bucket": "chromiumos-image-archive", + "cros_board": "jacuzzi", + "name": "base_unittests JACUZZI_CQ_PUBLIC_LKGM", + "public_builder": "cros_test_platform_public", + "public_builder_bucket": "testplatform-public", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", - "trigger_script": { - "script": "//testing/trigger_scripts/chromeos_device_trigger.py" - } + "use_lkgm": true, + "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" + }, + { + "args": [ + "-var=setup.FieldTrialConfig=enable" + ], + "autotest_name": "tast.chrome-from-gcs", + "bucket": "chromiumos-image-archive", + "cros_board": "jacuzzi", + "name": "chrome_all_tast_tests JACUZZI_CQ_PUBLIC_LKGM", + "public_builder": "cros_test_platform_public", + "public_builder_bucket": "testplatform-public", + "shards": 20, + "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", + "test": "chrome_all_tast_tests", + "test_id_prefix": "ninja://chromeos:chrome_all_tast_tests/", + "test_level_retries": 2, + "timeout_sec": 14400, + "use_lkgm": true, + "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" + }, + { + "args": [ + "-var=setup.FieldTrialConfig=enable" + ], + "autotest_name": "tast.chrome-from-gcs", + "bucket": "chromiumos-image-archive", + "ci_only": true, + "cros_board": "jacuzzi", + "experiment_percentage": 100, + "name": "chrome_criticalstaging_tast_tests JACUZZI_CQ_PUBLIC_LKGM", + "public_builder": "cros_test_platform_public", + "public_builder_bucket": "testplatform-public", + "shards": 3, + "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", + "test": "chrome_criticalstaging_tast_tests", + "test_id_prefix": "ninja://chromeos:chrome_criticalstaging_tast_tests/", + "test_level_retries": 2, + "timeout_sec": 14400, + "use_lkgm": true, + "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" + }, + { + "args": [ + "-var=setup.FieldTrialConfig=enable" + ], + "autotest_name": "tast.chrome-from-gcs", + "bucket": "chromiumos-image-archive", + "ci_only": true, + "cros_board": "jacuzzi", + "experiment_percentage": 100, + "name": "chrome_disabled_tast_tests JACUZZI_CQ_PUBLIC_LKGM", + "public_builder": "cros_test_platform_public", + "public_builder_bucket": "testplatform-public", + "shards": 2, + "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", + "test": "chrome_disabled_tast_tests", + "test_id_prefix": "ninja://chromeos:chrome_disabled_tast_tests/", + "test_level_retries": 1, + "timeout_sec": 14400, + "use_lkgm": true, + "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" } ] }, @@ -1143,24 +1198,65 @@ "additional_compile_targets": [ "chromiumos_preflight" ], - "gtest_tests": [ + "skylab_tests": [ { - "merge": { - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "name": "base_unittests", - "swarming": { - "dimensions": { - "device_type": "octopus", - "os": "ChromeOS" - }, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, + "autotest_name": "chromium", + "bucket": "chromiumos-image-archive", + "cros_board": "octopus", + "name": "base_unittests OCTOPUS_PUBLIC_LKGM", "test": "base_unittests", "test_id_prefix": "ninja://base:base_unittests/", - "trigger_script": { - "script": "//testing/trigger_scripts/chromeos_device_trigger.py" - } + "use_lkgm": true, + "variant_id": "OCTOPUS_PUBLIC_LKGM" + }, + { + "args": [ + "-var=setup.FieldTrialConfig=enable" + ], + "autotest_name": "tast.chrome-from-gcs", + "bucket": "chromiumos-image-archive", + "cros_board": "octopus", + "name": "chrome_all_tast_tests OCTOPUS_PUBLIC_LKGM", + "shards": 15, + "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", + "test": "chrome_all_tast_tests", + "test_id_prefix": "ninja://chromeos:chrome_all_tast_tests/", + "test_level_retries": 2, + "timeout_sec": 14400, + "use_lkgm": true, + "variant_id": "OCTOPUS_PUBLIC_LKGM" + }, + { + "autotest_name": "tast.chrome-from-gcs", + "bucket": "chromiumos-image-archive", + "ci_only": true, + "cros_board": "octopus", + "experiment_percentage": 100, + "name": "chrome_criticalstaging_tast_tests OCTOPUS_PUBLIC_LKGM", + "shards": 3, + "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", + "test": "chrome_criticalstaging_tast_tests", + "test_id_prefix": "ninja://chromeos:chrome_criticalstaging_tast_tests/", + "test_level_retries": 2, + "timeout_sec": 14400, + "use_lkgm": true, + "variant_id": "OCTOPUS_PUBLIC_LKGM" + }, + { + "autotest_name": "tast.chrome-from-gcs", + "bucket": "chromiumos-image-archive", + "ci_only": true, + "cros_board": "octopus", + "experiment_percentage": 100, + "name": "chrome_disabled_tast_tests OCTOPUS_PUBLIC_LKGM", + "shards": 2, + "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", + "test": "chrome_disabled_tast_tests", + "test_id_prefix": "ninja://chromeos:chrome_disabled_tast_tests/", + "test_level_retries": 1, + "timeout_sec": 14400, + "use_lkgm": true, + "variant_id": "OCTOPUS_PUBLIC_LKGM" } ] },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index b3fe1fdf..bb4c377 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -3547,152 +3547,6 @@ } ] }, - "chromeos-jacuzzi-rel-skylab": { - "additional_compile_targets": [ - "chromiumos_preflight" - ], - "skylab_tests": [ - { - "autotest_name": "chromium", - "bucket": "chromiumos-image-archive", - "cros_board": "jacuzzi", - "name": "base_unittests JACUZZI_CQ_PUBLIC_LKGM", - "public_builder": "cros_test_platform_public", - "public_builder_bucket": "testplatform-public", - "test": "base_unittests", - "test_id_prefix": "ninja://base:base_unittests/", - "use_lkgm": true, - "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" - }, - { - "args": [ - "-var=setup.FieldTrialConfig=enable" - ], - "autotest_name": "tast.chrome-from-gcs", - "bucket": "chromiumos-image-archive", - "cros_board": "jacuzzi", - "name": "chrome_all_tast_tests JACUZZI_CQ_PUBLIC_LKGM", - "public_builder": "cros_test_platform_public", - "public_builder_bucket": "testplatform-public", - "shards": 20, - "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", - "test": "chrome_all_tast_tests", - "test_id_prefix": "ninja://chromeos:chrome_all_tast_tests/", - "test_level_retries": 2, - "timeout_sec": 14400, - "use_lkgm": true, - "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" - }, - { - "args": [ - "-var=setup.FieldTrialConfig=enable" - ], - "autotest_name": "tast.chrome-from-gcs", - "bucket": "chromiumos-image-archive", - "ci_only": true, - "cros_board": "jacuzzi", - "experiment_percentage": 100, - "name": "chrome_criticalstaging_tast_tests JACUZZI_CQ_PUBLIC_LKGM", - "public_builder": "cros_test_platform_public", - "public_builder_bucket": "testplatform-public", - "shards": 3, - "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", - "test": "chrome_criticalstaging_tast_tests", - "test_id_prefix": "ninja://chromeos:chrome_criticalstaging_tast_tests/", - "test_level_retries": 2, - "timeout_sec": 14400, - "use_lkgm": true, - "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" - }, - { - "args": [ - "-var=setup.FieldTrialConfig=enable" - ], - "autotest_name": "tast.chrome-from-gcs", - "bucket": "chromiumos-image-archive", - "ci_only": true, - "cros_board": "jacuzzi", - "experiment_percentage": 100, - "name": "chrome_disabled_tast_tests JACUZZI_CQ_PUBLIC_LKGM", - "public_builder": "cros_test_platform_public", - "public_builder_bucket": "testplatform-public", - "shards": 2, - "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", - "test": "chrome_disabled_tast_tests", - "test_id_prefix": "ninja://chromeos:chrome_disabled_tast_tests/", - "test_level_retries": 1, - "timeout_sec": 14400, - "use_lkgm": true, - "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" - } - ] - }, - "chromeos-octopus-rel-skylab": { - "additional_compile_targets": [ - "chromiumos_preflight" - ], - "skylab_tests": [ - { - "autotest_name": "chromium", - "bucket": "chromiumos-image-archive", - "cros_board": "octopus", - "name": "base_unittests OCTOPUS_PUBLIC_LKGM", - "test": "base_unittests", - "test_id_prefix": "ninja://base:base_unittests/", - "use_lkgm": true, - "variant_id": "OCTOPUS_PUBLIC_LKGM" - }, - { - "args": [ - "-var=setup.FieldTrialConfig=enable" - ], - "autotest_name": "tast.chrome-from-gcs", - "bucket": "chromiumos-image-archive", - "cros_board": "octopus", - "name": "chrome_all_tast_tests OCTOPUS_PUBLIC_LKGM", - "shards": 15, - "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", - "test": "chrome_all_tast_tests", - "test_id_prefix": "ninja://chromeos:chrome_all_tast_tests/", - "test_level_retries": 2, - "timeout_sec": 14400, - "use_lkgm": true, - "variant_id": "OCTOPUS_PUBLIC_LKGM" - }, - { - "autotest_name": "tast.chrome-from-gcs", - "bucket": "chromiumos-image-archive", - "ci_only": true, - "cros_board": "octopus", - "experiment_percentage": 100, - "name": "chrome_criticalstaging_tast_tests OCTOPUS_PUBLIC_LKGM", - "shards": 3, - "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", - "test": "chrome_criticalstaging_tast_tests", - "test_id_prefix": "ninja://chromeos:chrome_criticalstaging_tast_tests/", - "test_level_retries": 2, - "timeout_sec": 14400, - "use_lkgm": true, - "variant_id": "OCTOPUS_PUBLIC_LKGM" - }, - { - "autotest_name": "tast.chrome-from-gcs", - "bucket": "chromiumos-image-archive", - "ci_only": true, - "cros_board": "octopus", - "experiment_percentage": 100, - "name": "chrome_disabled_tast_tests OCTOPUS_PUBLIC_LKGM", - "shards": 2, - "tast_expr": "STUB_STRING_TO_RUN_TAST_TESTS", - "test": "chrome_disabled_tast_tests", - "test_id_prefix": "ninja://chromeos:chrome_disabled_tast_tests/", - "test_level_retries": 1, - "timeout_sec": 14400, - "use_lkgm": true, - "variant_id": "OCTOPUS_PUBLIC_LKGM" - } - ] - }, "ios-blink-dbg-fyi": { "additional_compile_targets": [ "all"
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e80d6a6..9824d214 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1519,11 +1519,8 @@ 'additional_compile_targets': [ 'chromiumos_preflight', ], - 'mixins': [ - 'chromeos-jacuzzi', - ], 'test_suites': { - 'gtest_tests': 'chromeos_device_only_gtests', + 'skylab_tests': 'chromeos_jacuzzi_rel_skylab_tests', }, 'os_type': 'chromeos', }, @@ -1531,11 +1528,8 @@ 'additional_compile_targets': [ 'chromiumos_preflight', ], - 'mixins': [ - 'chromeos-octopus', - ], 'test_suites': { - 'gtest_tests': 'chromeos_device_only_gtests', + 'skylab_tests': 'chromeos_octopus_rel_skylab_tests', }, 'os_type': 'chromeos', }, @@ -3348,26 +3342,6 @@ 'gtest_tests': 'perfetto_gtests_android', }, }, - - 'chromeos-jacuzzi-rel-skylab': { - 'additional_compile_targets': [ - 'chromiumos_preflight', - ], - 'test_suites': { - 'skylab_tests': 'chromeos_jacuzzi_rel_skylab_tests', - }, - 'os_type': 'chromeos', - }, - 'chromeos-octopus-rel-skylab': { - 'additional_compile_targets': [ - 'chromiumos_preflight', - ], - 'test_suites': { - 'skylab_tests': 'chromeos_octopus_rel_skylab_tests', - }, - 'os_type': 'chromeos', - }, - 'ios-blink-dbg-fyi': { 'additional_compile_targets': [ 'all'
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index bb9c0a1..9273e81 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -12866,6 +12866,53 @@ ] } ], + "PasswordGenerationExperimentBatch1": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros", + "fuchsia", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "EnabledWithEditPassword", + "params": { + "PasswordGenerationExperimentSurveyTriggedId": "4yPTnSKPN0ugnJ3q1cK0YJ18dkNR", + "password_generation_variation": "edit_password", + "probability": "1.0" + }, + "enable_features": [ + "PasswordGenerationExperiment" + ] + }, + { + "name": "EnabledWithTrustedAdvice", + "params": { + "PasswordGenerationExperimentSurveyTriggedId": "Vm6DB1ki50ugnJ3q1cK0SpkrheAJ", + "password_generation_variation": "trusted_advice", + "probability": "1.0" + }, + "enable_features": [ + "PasswordGenerationExperiment" + ] + }, + { + "name": "EnabledWithSafetyFirst", + "params": { + "PasswordGenerationExperimentSurveyTriggedId": "sD7hmDAoo0ugnJ3q1cK0VQ2Y8p6e", + "password_generation_variation": "safety_first", + "probability": "1.0" + }, + "enable_features": [ + "PasswordGenerationExperiment" + ] + } + ] + } + ], "PasswordInfobarDisplayLength": [ { "platforms": [ @@ -17127,6 +17174,21 @@ ] } ], + "SkiaGraphite": [ + { + "platforms": [ + "mac" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "SkiaGraphite" + ] + } + ] + } + ], "SkipUnnecessaryThreadHopsForParseHeaders": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index 75c8ef1..d334a6f2 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 75c8ef1c6371b2922a6cab9687b9a53fe6674ffc +Subproject commit d334a6f265750b754868d6c3ebeaa84a527a33b0
diff --git a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc index ea41de2c..74d766a 100644 --- a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc +++ b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
@@ -128,6 +128,8 @@ return {"media-stream", "page has live MediaStreamTrack"}; case WebSchedulerTrackedFeature::kUnloadHandler: return {"unload-handler", "page contains unload handler"}; + case WebSchedulerTrackedFeature::kParserAborted: + return {"parser-aborted", "parser was aborted"}; } return {}; } @@ -218,7 +220,8 @@ kJsNetworkRequestReceivedCacheControlNoStoreResource, WebSchedulerTrackedFeature::kWebRTCSticky, WebSchedulerTrackedFeature::kWebSocketSticky, - WebSchedulerTrackedFeature::kWebTransportSticky}; + WebSchedulerTrackedFeature::kWebTransportSticky, + WebSchedulerTrackedFeature::kParserAborted}; } // static
diff --git a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h index c4a738a..6b3c45b 100644 --- a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h +++ b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
@@ -161,11 +161,12 @@ // so that the source location can be tracked. See https://crbug.com/1513120 // for details. kUnloadHandler = 67, + kParserAborted = 68, // Please keep in sync with WebSchedulerTrackedFeature in // tools/metrics/histograms/enums.xml. These values should not be renumbered. - kMaxValue = kUnloadHandler, + kMaxValue = kParserAborted, }; using WebSchedulerTrackedFeatures =
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index c9ced71f..e9067bb 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -9003,6 +9003,7 @@ SmartCard LiveMediaStreamTrack UnloadHandler + ParserAborted # Disabled for RenderFrameHost reasons # See content/browser/renderer_host/back_forward_cache_disable.h for explanations. ContentSecurityHandler
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index ea520af..a0ab107 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -3198,7 +3198,6 @@ To<StyleRuleTry>(position_fallback_rule->ChildRules()[index].Get()); StyleResolverState state(GetDocument(), element); state.SetStyle(base_style); - state.SetIsResolvingPositionFallbackStyle(); const CSSPropertyValueSet& properties = try_rule->Properties(); STACK_UNINITIALIZED StyleCascade cascade(state);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc index 5bbe093..ad2dc0d8 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -85,11 +85,7 @@ is_outside_flat_tree_(style_recalc_context ? style_recalc_context->is_outside_flat_tree : false), - can_trigger_animations_(style_request.can_trigger_animations), - // TODO(crbug.com/1475321): Remove is_resolving_position_fallback_style - // when auto-fallbacks are reworked. - is_resolving_position_fallback_style_( - style_recalc_context && style_recalc_context->is_interleaved_oof) { + can_trigger_animations_(style_request.can_trigger_animations) { DCHECK(!!parent_style_ == !!layout_parent_style_); if (UsesHighlightPseudoInheritance()) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h index 7f251429..e811e96 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
@@ -237,13 +237,6 @@ void UpdateLengthConversionData(); - void SetIsResolvingPositionFallbackStyle(bool is_resolving = true) { - is_resolving_position_fallback_style_ = is_resolving; - } - bool IsResolvingPositionFallbackStyle() const { - return is_resolving_position_fallback_style_; - } - float TextAutosizingMultiplier() const { const ComputedStyle* old_style = GetElement().GetComputedStyle(); if (element_type_ != ElementType::kPseudoElement && old_style) { @@ -341,10 +334,6 @@ // flag. bool rejected_legacy_overlapping_ = false; - // True if we are currently resolving a position fallback style by applying - // rules in a `@try` block. - bool is_resolving_position_fallback_style_ = false; - // True if the resolved ComputedStyle depends on tree-scoped references. bool has_tree_scoped_reference_ = false; };
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 4999a38..c1d6b50 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3717,8 +3717,16 @@ // open() or write() after an active parser is aborted. See // https://github.com/whatwg/html/issues/4723 for discussion about // standardizing this behavior. - if (parser_ && parser_->IsParsing()) + if (parser_ && parser_->IsParsing()) { ignore_opens_and_writes_for_abort_ = true; + if (GetFrame()) { + // Only register the sticky feature when the parser was parsing and then + // was cancelled. + GetFrame()->GetFrameScheduler()->RegisterStickyFeature( + SchedulingPolicy::Feature::kParserAborted, + {SchedulingPolicy::DisableBackForwardCache()}); + } + } DetachParser(); SetParsingState(kFinishedParsing); SetReadyState(kComplete);
diff --git a/third_party/blink/renderer/core/dom/document_parser.h b/third_party/blink/renderer/core/dom/document_parser.h index 0b7f258..8fc2c9a 100644 --- a/third_party/blink/renderer/core/dom/document_parser.h +++ b/third_party/blink/renderer/core/dom/document_parser.h
@@ -77,9 +77,8 @@ virtual void Finish() = 0; - // document() will return 0 after detach() is called. + // GetDocument() returns null after detach() is called. Document* GetDocument() const { - CHECK(document_); return document_.Get(); }
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 1fedbdff..a51b5c3 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3428,7 +3428,10 @@ // We are both a size container and trying to compute interleaved styles // from out-of-flow layout. Our children should be the first opportunity to // skip recalc. - if (style_recalc_context.is_interleaved_oof) { + // + // Note that anchor_evaluator will be non-null only for the root element + // of the interleaved style recalc. + if (style_recalc_context.anchor_evaluator) { return false; } @@ -3543,7 +3546,6 @@ } StyleRecalcContext child_recalc_context = local_style_recalc_context; - child_recalc_context.is_interleaved_oof = false; // If we're in StyleEngine::UpdateStyleForOutOfFlow, then anchor_evaluator // may be non-nullptr to allow evaluation of anchor() and anchor-size() // queries. Descendants of the current out-of-flow element must not be @@ -4036,6 +4038,14 @@ apply_changes = LayoutObject::ApplyStyleChanges::kYes; } } + if (RuntimeEnabledFeatures::CSSAnchorPositioningCascadeFallbackEnabled()) { + if (style_recalc_context.is_interleaved_oof) { + // If we're in interleaved style recalc from out-of-flow, + // we're already in the middle of laying out the objects + // we would mark for layout. + apply_changes = LayoutObject::ApplyStyleChanges::kNo; + } + } layout_object->SetStyle(layout_style, apply_changes); } return child_change;
diff --git a/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc b/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc index 38d1617..20e47e95 100644 --- a/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc +++ b/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc
@@ -318,13 +318,17 @@ if (end_style->ShouldPreserveBreaks() && start == end && end.OffsetInContainerNode() < static_cast<int>(To<Text>(end.ComputeContainerNode())->length())) { - int end_offset = end.OffsetInContainerNode(); - // TODO(yosin) We should use |PositionMoveType::CodePoint| for - // |previousPositionOf()|. - if (!IsNewLineAtPosition( - PreviousPositionOf(end, PositionMoveType::kCodeUnit)) && - IsNewLineAtPosition(end)) - end = Position(end.ComputeContainerNode(), end_offset + 1); + if (!RuntimeEnabledFeatures:: + NoIncreasingEndOffsetOnSplittingTextNodesEnabled()) { + int end_offset = end.OffsetInContainerNode(); + // TODO(yosin) We should use |PositionMoveType::CodePoint| for + // |previousPositionOf()|. + if (!IsNewLineAtPosition( + PreviousPositionOf(end, PositionMoveType::kCodeUnit)) && + IsNewLineAtPosition(end)) { + end = Position(end.ComputeContainerNode(), end_offset + 1); + } + } if (is_end_and_end_of_last_paragraph_on_same_node && end.OffsetInContainerNode() >= end_of_last_paragraph.OffsetInContainerNode())
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 45915189..dc44163 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -2029,6 +2029,7 @@ // buffer will also start off clear (and this matches what reshape will do). GetDrawingBuffer()->set_low_latency_enabled(Host()->LowLatencyEnabled()); GetDrawingBuffer()->Resize(gfx::Size(width, height)); + GetDrawingBuffer()->MarkContentsChanged(); if (buffer) { ContextGL()->BindBuffer(GL_PIXEL_UNPACK_BUFFER,
diff --git a/third_party/blink/renderer/modules/websockets/websocket_error.cc b/third_party/blink/renderer/modules/websockets/websocket_error.cc index a8e33066..2fdf8f8 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_error.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_error.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_websocket_close_info.h" +#include "third_party/blink/renderer/modules/websockets/websocket_channel.h" #include "third_party/blink/renderer/modules/websockets/websocket_common.h" #include "third_party/blink/renderer/platform/bindings/exception_code.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -29,15 +30,13 @@ v8::Local<v8::Value> WebSocketError::Create(v8::Isolate* isolate, String message, std::optional<uint16_t> close_code, - String reason, - ExceptionState& exception_state) { - auto* dom_exception = ValidateAndCreate(std::move(message), close_code, - std::move(reason), exception_state); - if (!dom_exception) { - CHECK(exception_state.HadException()); - return v8::Local<v8::Value>(); + String reason) { + if (!reason.empty() && !close_code.has_value()) { + close_code = WebSocketChannel::kCloseEventCodeNormalClosure; } - return V8ThrowDOMException::AttachStackProperty(isolate, dom_exception); + auto* error = MakeGarbageCollected<WebSocketError>( + PassKey(), std::move(message), close_code, std::move(reason)); + return V8ThrowDOMException::AttachStackProperty(isolate, error); } WebSocketError::WebSocketError(PassKey,
diff --git a/third_party/blink/renderer/modules/websockets/websocket_error.h b/third_party/blink/renderer/modules/websockets/websocket_error.h index be03d85..b35d5c489 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_error.h +++ b/third_party/blink/renderer/modules/websockets/websocket_error.h
@@ -39,8 +39,7 @@ static v8::Local<v8::Value> Create(v8::Isolate*, String message, std::optional<uint16_t> close_code, - String reason, - ExceptionState&); + String reason); // Use one of the Create() methods instead. This constructor has to be public // so that it can be used with MakeGarbageCollected<> inside the
diff --git a/third_party/blink/renderer/modules/websockets/websocket_error_test.cc b/third_party/blink/renderer/modules/websockets/websocket_error_test.cc index 364ce00..d22ac42 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_error_test.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_error_test.cc
@@ -124,8 +124,7 @@ V8TestingScope scope; auto* isolate = scope.GetIsolate(); auto context = scope.GetContext(); - auto v8value = WebSocketError::Create(isolate, "message", 1000, "reason", - ASSERT_NO_EXCEPTION); + auto v8value = WebSocketError::Create(isolate, "message", 1000, "reason"); ASSERT_FALSE(v8value.IsEmpty()); ASSERT_TRUE(v8value->IsObject());
diff --git a/third_party/blink/renderer/modules/websockets/websocket_stream.cc b/third_party/blink/renderer/modules/websockets/websocket_stream.cc index 9ad7c252..6f0563cb 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_stream.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_stream.cc
@@ -61,7 +61,8 @@ void DidReceiveTextMessage(const String&); void DidReceiveBinaryMessage(const Vector<base::span<const char>>&); void DidStartClosingHandshake(); - void DidClose(bool was_clean, uint16_t code, const String& reason); + void DidCloseCleanly(uint16_t code, const String& reason); + void CloseWithError(v8::Local<v8::Value> error); void Trace(Visitor* visitor) const override { visitor->Trace(creator_); @@ -92,7 +93,8 @@ // API for WebSocketStream. void DidStartClosingHandshake(); - void DidClose(bool was_clean, uint16_t code, const String& reason); + void DidCloseCleanly(uint16_t code, const String& reason); + void CloseWithError(v8::Local<v8::Value> error); bool AllDataHasBeenConsumed() { return !is_writing_; } void Trace(Visitor* visitor) const override { @@ -175,24 +177,28 @@ closed_ = true; } -void WebSocketStream::UnderlyingSource::DidClose(bool was_clean, - uint16_t code, - const String& reason) { +void WebSocketStream::UnderlyingSource::DidCloseCleanly(uint16_t code, + const String& reason) { DVLOG(1) << "WebSocketStream::UnderlyingSource " << this - << " DidClose() was_clean=" << was_clean << " code=" << code - << " reason=" << reason; + << " DidCloseCleanly() code=" << code << " reason=" << reason; if (closed_) return; closed_ = true; - if (was_clean) { - Controller()->Close(); + Controller()->Close(); +} + +void WebSocketStream::UnderlyingSource::CloseWithError( + v8::Local<v8::Value> error) { + DVLOG(1) << "WebSocketStream::UnderlyingSource::CloseWithError"; + if (closed_) { return; } - Controller()->Error(creator_->CreateWebSocketError( - kWebSocketNotCleanlyClosedErrorMessage, code, reason)); + closed_ = true; + + Controller()->Error(error); } ScriptPromise WebSocketStream::UnderlyingSink::start( @@ -258,31 +264,36 @@ ErrorControllerBecauseClosed(); } -void WebSocketStream::UnderlyingSink::DidClose(bool was_clean, - uint16_t code, - const String& reason) { +void WebSocketStream::UnderlyingSink::DidCloseCleanly(uint16_t code, + const String& reason) { DVLOG(1) << "WebSocketStream::UnderlyingSink " << this - << " DidClose() was_clean=" << was_clean << " code=" << code - << " reason=" << reason; + << " DidCloseCleanly() code=" << code << " reason=" << reason; - if (close_resolver_) - ResolveClose(was_clean); + if (close_resolver_) { + ResolveClose(/*was_clean=*/true); + } if (closed_) return; closed_ = true; - if (was_clean) { - ErrorControllerBecauseClosed(); - return; + ErrorControllerBecauseClosed(); +} + +void WebSocketStream::UnderlyingSink::CloseWithError( + v8::Local<v8::Value> error) { + if (close_resolver_) { + ResolveClose(/*was_clean=*/false); } + if (closed_) { + return; + } + closed_ = true; + ScriptState* script_state = creator_->script_state_; - Controller()->error( - script_state, - ScriptValue(script_state->GetIsolate(), - creator_->CreateWebSocketError( - kWebSocketNotCleanlyClosedErrorMessage, code, reason))); + Controller()->error(script_state, + ScriptValue(script_state->GetIsolate(), error)); } void WebSocketStream::UnderlyingSink::ErrorControllerBecauseClosed() { @@ -580,15 +591,24 @@ channel_->Disconnect(); channel_ = nullptr; abort_handle_.Clear(); - if (source_) - source_->DidClose(was_clean, code, reason); - if (sink_) - sink_->DidClose(was_clean, code, reason); if (was_clean) { + if (source_) { + source_->DidCloseCleanly(code, reason); + } + if (sink_) { + sink_->DidCloseCleanly(code, reason); + } closed_resolver_->Resolve(MakeCloseInfo(code, reason)); } else { - closed_resolver_->Reject( - CreateWebSocketError(kWebSocketNotCleanlyClosedErrorMessage)); + auto error = CreateWebSocketError(kWebSocketNotCleanlyClosedErrorMessage, + code, reason); + if (source_) { + source_->CloseWithError(error); + } + if (sink_) { + sink_->CloseWithError(error); + } + closed_resolver_->Reject(error); } } @@ -714,12 +734,8 @@ String message, std::optional<uint16_t> close_code, String reason) { - // This method should not be called with invalid `close_code` and `reason`, - // but the use of ASSERT_NO_EXCEPTION here is bad practice. - // TODO(ricea): Do something else. return WebSocketError::Create(script_state_->GetIsolate(), std::move(message), - close_code, std::move(reason), - ASSERT_NO_EXCEPTION); + close_code, std::move(reason)); } void WebSocketStream::OnAbort() {
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm b/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm index 0c5eba8..019eb04 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm +++ b/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
@@ -238,7 +238,7 @@ !(substitute_font_traits & kCTFontTraitItalic); return FontPlatformDataFromCTFont( - substitute_font, font_description.EffectiveFontSize(), + substitute_font.get(), font_description.EffectiveFontSize(), font_description.SpecifiedSize(), synthetic_bold, synthetic_italic, font_description.TextRendering(), ResolvedFontFeatures(), platform_data.Orientation(), font_description.FontOpticalSizing(), @@ -326,7 +326,7 @@ code_units_length = 2; } - NSFont* ns_font = base::apple::CFToNSPtrCast(platform_data.CtFont()); + NSFont* ns_font = CFToNSPtrCast(platform_data.CtFont()); NSString* string = [[NSString alloc] initWithCharacters:reinterpret_cast<UniChar*>(code_units) @@ -407,8 +407,7 @@ !IsAppKitFontWeightBold(substitute_font_weight); alternate_font = FontPlatformDataFromCTFont( - ScopedCFTypeRef<CTFontRef>(base::apple::NSToCFOwnershipCast( - substitute_font)), // Ownership -> Ptr + base::apple::NSToCFPtrCast(substitute_font), font_description.EffectiveFontSize(), font_description.SpecifiedSize(), synthetic_bold, (traits & NSFontItalicTrait) && @@ -525,8 +524,8 @@ // stored in non-system locations. When loading fails, we do not want to use // the returned FontPlatformData since it will not have a valid SkTypeface. const FontPlatformData* platform_data = FontPlatformDataFromCTFont( - matched_font, size, font_description.SpecifiedSize(), synthetic_bold, - synthetic_italic, font_description.TextRendering(), + matched_font.get(), size, font_description.SpecifiedSize(), + synthetic_bold, synthetic_italic, font_description.TextRendering(), ResolvedFontFeatures(), font_description.Orientation(), font_description.FontOpticalSizing(), font_description.VariationSettings());
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm index f9072c5..c7b5583 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm +++ b/third_party/blink/renderer/platform/fonts/mac/font_matcher_mac_test.mm
@@ -17,7 +17,7 @@ using base::apple::CFCast; using base::apple::GetValueFromDictionary; -using base::apple::NSToCFPtrCast; +using base::apple::NSToCFOwnershipCast; using base::apple::ScopedCFTypeRef; namespace blink { @@ -84,7 +84,7 @@ traits |= NSFontCondensedTrait; } - return ScopedCFTypeRef<CTFontRef>(NSToCFPtrCast( + return ScopedCFTypeRef<CTFontRef>(NSToCFOwnershipCast( MatchNSFontFamily(font_name, traits, desired_weight, size))); } @@ -150,8 +150,8 @@ kNormalWeightValue, kItalicSlopeValue, kNormalWidthValue, 11); EXPECT_TRUE(font); ScopedCFTypeRef<CFDictionaryRef> traits(CTFontCopyTraits(font.get())); - CFNumberRef slant_num = base::apple::GetValueFromDictionary<CFNumberRef>( - traits.get(), kCTFontSlantTrait); + CFNumberRef slant_num = + GetValueFromDictionary<CFNumberRef>(traits.get(), kCTFontSlantTrait); float slant; CFNumberGetValue(slant_num, kCFNumberFloatType, &slant); EXPECT_NE(slant, 0.0);
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h index 0a8c5c9..1c3697ec 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h +++ b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
@@ -58,7 +58,7 @@ // optical sizing and tracking, needed in particular for the San Francisco // system font. const FontPlatformData* FontPlatformDataFromCTFont( - base::apple::ScopedCFTypeRef<CTFontRef>, + CTFontRef, float size, float specified_size, bool synthetic_bold,
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm index fc890568..97d550c 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm +++ b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
@@ -46,7 +46,6 @@ #include "third_party/skia/include/core/SkTypes.h" #import "third_party/skia/include/ports/SkTypeface_mac.h" -using base::apple::NSToCFPtrCast; using base::apple::ScopedCFTypeRef; namespace { @@ -102,19 +101,17 @@ return false; } -static bool CanLoadInProcess(ScopedCFTypeRef<CTFontRef> ct_font) { +static bool CanLoadInProcess(CTFontRef ct_font) { ScopedCFTypeRef<CGFontRef> cg_font( - CTFontCopyGraphicsFont(ct_font.get(), /*attributes=*/nullptr)); + CTFontCopyGraphicsFont(ct_font, /*attributes=*/nullptr)); ScopedCFTypeRef<CFStringRef> font_name( CGFontCopyPostScriptName(cg_font.get())); - ScopedCFTypeRef<CFStringRef> last_resort_font_name(CFStringCreateWithCString( - kCFAllocatorDefault, "LastResort", kCFStringEncodingUTF8)); - return CFStringCompare(font_name.get(), last_resort_font_name.get(), 0) != + return CFStringCompare(font_name.get(), CFSTR("LastResort"), 0) != kCFCompareEqualTo; } const FontPlatformData* FontPlatformDataFromCTFont( - ScopedCFTypeRef<CTFontRef> ct_font, + CTFontRef ct_font, float size, float specified_size, bool synthetic_bold, @@ -130,7 +127,7 @@ // activated fonts that would otherwise be restricted by the sandbox. DCHECK(CanLoadInProcess(ct_font)); - sk_sp<SkTypeface> typeface = SkMakeTypefaceFromCTFont(ct_font.get()); + sk_sp<SkTypeface> typeface = SkMakeTypefaceFromCTFont(ct_font); auto make_typeface_fontplatformdata = [&typeface, &size, &synthetic_bold, &synthetic_italic, &text_rendering,
diff --git a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc index 4d1b3d7..0a8659d 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.cc
@@ -146,6 +146,12 @@ NOTREACHED_NORETURN(); } +bool HanKerning::MayApply(StringView text) { + return !text.Is8Bit() && !text.IsAllSpecialCharacters<[](UChar ch) { + return !Character::MaybeHanKerningOpenOrCloseFast(ch); + }>(); +} + inline bool HanKerning::ShouldKern(CharType type, CharType last_type) { return type == CharType::kOpen && (last_type == CharType::kOpen || last_type == CharType::kMiddle || @@ -169,6 +175,10 @@ Options options, FontFeatures* features) { DCHECK(!features_); + DCHECK_GT(end, start); + if (!MayApply(StringView(text, start, end - start))) { + return; + } const LayoutLocale& locale = font_description.LocaleOrDefault(); const FontData& font_data = font.HanKerningData(locale, options.is_horizontal);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h index 4a085ae..63f0a68 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h +++ b/third_party/blink/renderer/platform/fonts/shaping/han_kerning.h
@@ -107,8 +107,12 @@ }; private: + FRIEND_TEST_ALL_PREFIXES(HanKerningTest, MayApply); + static CharType GetCharType(UChar ch, const FontData& font_data); + static bool MayApply(StringView text); + static bool ShouldKern(CharType type, CharType last_type); static bool ShouldKernLast(CharType type, CharType last_type);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/han_kerning_test.cc b/third_party/blink/renderer/platform/fonts/shaping/han_kerning_test.cc index d6db178a..089d39f 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/han_kerning_test.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/han_kerning_test.cc
@@ -15,8 +15,6 @@ namespace blink { -namespace { - Font CreateNotoCjk() { return blink::test::CreateTestFont( AtomicString("Noto Sans CJK"), @@ -30,6 +28,34 @@ explicit HanKerningTest() : ScopedCSSTextSpacingTrimForTest(true) {} }; +TEST_F(HanKerningTest, MayApply) { + Font noto_cjk = CreateNotoCjk(); + const SimpleFontData* noto_cjk_data = noto_cjk.PrimaryFont(); + EXPECT_TRUE(noto_cjk_data); + scoped_refptr<LayoutLocale> ja = + LayoutLocale::CreateForTesting(AtomicString("ja")); + HanKerning::FontData ja_data(*noto_cjk_data, *ja, true); + + for (UChar32 ch = 0; ch < kMaxCodepoint; ++ch) { + StringBuilder builder; + builder.Append(ch); + String text = builder.ToString(); + + for (wtf_size_t i = 0; i < text.length(); ++i) { + const HanKerning::CharType type = + HanKerning::GetCharType(text[i], ja_data); + if (type == HanKerning::CharType::kOpen || + type == HanKerning::CharType::kOpenQuote || + type == HanKerning::CharType::kClose || + type == HanKerning::CharType::kCloseQuote) { + EXPECT_EQ(HanKerning::MayApply(text), true) + << String::Format("U+%06X", ch); + break; + } + } + } +} + TEST_F(HanKerningTest, FontDataHorizontal) { Font noto_cjk = CreateNotoCjk(); const SimpleFontData* noto_cjk_data = noto_cjk.PrimaryFont(); @@ -165,6 +191,4 @@ EXPECT_EQ(features.size(), 1u); } -} // namespace - } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc index c21b84b..ffb1189 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.cc
@@ -53,15 +53,15 @@ node.IsBackfaceHiddenInternal(parent.is_backface_hidden_); nearest_scroll_translation_ = - node.ScrollNode() ? &node : parent.nearest_scroll_translation_.get(); + node.ScrollNode() ? &node : parent.nearest_scroll_translation_; scroll_translation_state_ = node.ScrollTranslationForFixed() ? node.ScrollTranslationForFixed() - : nearest_scroll_translation_.get(); + : nearest_scroll_translation_; nearest_directly_composited_ancestor_ = node.HasDirectCompositingReasons() ? &node - : parent.nearest_directly_composited_ancestor_.get(); + : parent.nearest_directly_composited_ancestor_; if (node.IsIdentityOr2dTranslation() && !node.HasActiveTransformAnimation()) { root_of_2d_translation_ = parent.root_of_2d_translation_;
diff --git a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h index fdb9692..0b1c8042 100644 --- a/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h +++ b/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_transform_cache.h
@@ -9,7 +9,6 @@ #include "base/check_op.h" #include "base/dcheck_is_on.h" -#include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr_exclusion.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -110,9 +109,8 @@ } } const TransformPaintPropertyNode* plane_root() const { - return UNLIKELY(plane_root_transform_) - ? plane_root_transform_->plane_root.get() - : root_of_2d_translation(); + return UNLIKELY(plane_root_transform_) ? plane_root_transform_->plane_root + : root_of_2d_translation(); } bool has_animation_to_plane_root() const { return UNLIKELY(plane_root_transform_) && @@ -153,8 +151,8 @@ // transform node, or the root of the tree if the whole path from the // transform node to the root contains identity or 2d translations only. // - // RAW_PTR_EXCLUSION: Performance reasons: visible regression in MotionMark - // (crbug.com/1495275#c116). + // Excluded from being a `raw_ptr` for visible regression in + // MotionMark (crbug.com/1495275#c116). RAW_PTR_EXCLUSION const TransformPaintPropertyNode* root_of_2d_translation_; // The cached values here can be categorized in two logical groups: @@ -216,8 +214,7 @@ struct PlaneRootTransform { gfx::Transform to_plane_root; gfx::Transform from_plane_root; - raw_ptr<const TransformPaintPropertyNode, DanglingUntriaged> plane_root = - nullptr; + const TransformPaintPropertyNode* plane_root = nullptr; bool has_animation = false; USING_FAST_MALLOC(PlaneRootTransform); }; @@ -232,12 +229,10 @@ }; std::optional<ScreenTransform> screen_transform_; - raw_ptr<const TransformPaintPropertyNode, DanglingUntriaged> - nearest_scroll_translation_ = nullptr; - raw_ptr<const TransformPaintPropertyNode, DanglingUntriaged> - scroll_translation_state_ = nullptr; - raw_ptr<const TransformPaintPropertyNode, DanglingUntriaged> - nearest_directly_composited_ancestor_ = nullptr; + const TransformPaintPropertyNode* nearest_scroll_translation_ = nullptr; + const TransformPaintPropertyNode* scroll_translation_state_ = nullptr; + const TransformPaintPropertyNode* nearest_directly_composited_ancestor_ = + nullptr; // Whether or not there is a sticky or anchor position scroll translation to // the root.
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h index 4437a85..231c187 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h +++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
@@ -8,7 +8,6 @@ #include <optional> #include "base/dcheck_is_on.h" -#include "base/memory/raw_ptr.h" #include "cc/input/hit_test_opaqueness.h" #include "cc/input/layer_selection_bound.h" #include "third_party/blink/renderer/platform/graphics/paint/display_item.h" @@ -126,7 +125,7 @@ void FinalizeLastChunkProperties(); - raw_ptr<Vector<PaintChunk>> chunks_ = nullptr; + Vector<PaintChunk>* chunks_ = nullptr; WeakPersistent<HeapVector<Member<const DisplayItemClient>>> clients_to_validate_ = nullptr; // The id specified by UpdateCurrentPaintChunkProperties(). If it is not
diff --git a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc index e4559d7..f796682 100644 --- a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc +++ b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
@@ -133,8 +133,7 @@ } String PropertyTreeStateOrAlias::ToString() const { - return String::Format("t:%p c:%p e:%p", transform_.get(), clip_.get(), - effect_.get()); + return String::Format("t:%p c:%p e:%p", transform_, clip_, effect_); } #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h index 196e03f..05d5a30 100644 --- a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h +++ b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
@@ -7,7 +7,6 @@ #include "base/dcheck_is_on.h" #include "base/functional/function_ref.h" -#include "base/memory/raw_ptr.h" #include "third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h" #include "third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h" #include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h" @@ -106,12 +105,9 @@ PropertyTreeStateOrAlias() = default; private: - raw_ptr<const TransformPaintPropertyNodeOrAlias, DanglingUntriaged> - transform_ = nullptr; - raw_ptr<const ClipPaintPropertyNodeOrAlias, DanglingUntriaged> clip_ = - nullptr; - raw_ptr<const EffectPaintPropertyNodeOrAlias, DanglingUntriaged> effect_ = - nullptr; + const TransformPaintPropertyNodeOrAlias* transform_ = nullptr; + const ClipPaintPropertyNodeOrAlias* clip_ = nullptr; + const EffectPaintPropertyNodeOrAlias* effect_ = nullptr; }; class PLATFORM_EXPORT PropertyTreeState : public PropertyTreeStateOrAlias {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index c194557..374f90b 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2486,6 +2486,12 @@ name: "NoIdleEncodingForWebTests", status: "test", }, + // Doesn't increase the end offset on getting the range for a new line + // character. See https://crbug.com/326888905 + { + name: "NoIncreasingEndOffsetOnSplittingTextNodes", + status: "stable", + }, // Makes enter/leave Mouse and Pointer Events non-composed as per // corresponding specifications. {
diff --git a/third_party/blink/renderer/platform/text/character.h b/third_party/blink/renderer/platform/text/character.h index 9f1e305..9ad34f01 100644 --- a/third_party/blink/renderer/platform/text/character.h +++ b/third_party/blink/renderer/platform/text/character.h
@@ -120,10 +120,18 @@ // It depends on fonts, so it may not be `kOpen` or `kClose` even when this // function returns `true`. See `HanKerning::GetCharType`. static bool MaybeHanKerningOpen(UChar32 ch) { - return MaybeHanKerningOpenOrClose(ch) && MaybeHanKerningOpenSlow(ch); + return MaybeHanKerningOpenOrCloseFast(ch) && MaybeHanKerningOpenSlow(ch); } static bool MaybeHanKerningClose(UChar32 ch) { - return MaybeHanKerningOpenOrClose(ch) && MaybeHanKerningCloseSlow(ch); + return MaybeHanKerningOpenOrCloseFast(ch) && MaybeHanKerningCloseSlow(ch); + } + // Check if the character may be `kOpen` or `kClose` only by ranges, without + // getting the Unicode property. Faster than `MaybeHanKerningOpen` and + // `MaybeHanKerningClose` but has more cases where it returns `true` for other + // characters. + static bool MaybeHanKerningOpenOrCloseFast(UChar32 character) { + return IsInRange(character, kLeftSingleQuotationMarkCharacter, 0x301F) || + IsInRange(character, 0xFF08, 0xFF60); } // Collapsible white space characters defined in CSS: @@ -239,10 +247,6 @@ static bool IsCJKIdeographOrSymbolSlow(UChar32); static bool IsHangulSlow(UChar32); - static bool MaybeHanKerningOpenOrClose(UChar32 character) { - return IsInRange(character, kLeftSingleQuotationMarkCharacter, 0x301F) || - IsInRange(character, 0xFF08, 0xFF60); - } static bool MaybeHanKerningOpenSlow(UChar32); static bool MaybeHanKerningCloseSlow(UChar32); };
diff --git a/third_party/blink/renderer/platform/text/character_test.cc b/third_party/blink/renderer/platform/text/character_test.cc index 5498993..4dc1571 100644 --- a/third_party/blink/renderer/platform/text/character_test.cc +++ b/third_party/blink/renderer/platform/text/character_test.cc
@@ -41,7 +41,7 @@ EXPECT_EQ(Character::IsEastAsianWidthFullwidth(ch), eaw == UEastAsianWidth::U_EA_FULLWIDTH); - if (!Character::MaybeHanKerningOpenOrClose(ch)) { + if (!Character::MaybeHanKerningOpenOrCloseFast(ch)) { DCHECK(!Character::MaybeHanKerningOpenSlow(ch)); DCHECK(!Character::MaybeHanKerningCloseSlow(ch)); }
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 0fe407e..d4ab553 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -458,10 +458,8 @@ crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=normal&right-white-space=pre-wrap [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=nowrap&right-white-space=normal [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=nowrap&right-white-space=pre [ Failure ] -crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=nowrap&right-white-space=pre-wrap [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=pre&right-white-space=normal [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=pre&right-white-space=nowrap [ Failure ] -crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=pre&right-white-space=pre-line [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=pre&right-white-space=pre-wrap [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=pre-line&right-white-space=normal [ Failure ] crbug.com/1370704 external/wpt/editing/other/join-different-white-space-style-left-paragraph-and-right-line.html?method=backspace&left-white-space=pre-line&right-white-space=pre-wrap [ Failure ] @@ -2620,7 +2618,19 @@ crbug.com/626703 external/wpt/css/css-page/page-name-unnamed-trailing-001-print.html [ Crash Failure ] # These tests generate baselines whose names are too long. -crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html* [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=span* [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=normal&display=block&command=insertParagraph [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=normal&display=block&command=insertText [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=normal&display=inline&command=insertParagraph [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=normal&display=inline&command=insertText [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=normal&display=inline-block&command=insertParagraph [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=normal&display=inline-block&command=insertText [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=pre&display=block&command=insertParagraph [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=pre&display=block&command=insertText [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=pre-line&display=block&command=insertParagraph [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=pre-line&display=block&command=insertText [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=pre-wrap&display=block&command=insertParagraph [ Failure ] +crbug.com/626703 external/wpt/editing/other/insertparagraph-in-editing-host-cannot-have-div.tentative.html?host=p&white-space=pre-wrap&display=block&command=insertText [ Failure ] # Flaky output (https://crrev.com/c/5228398) crbug.com/626703 [ Mac ] external/wpt/mediacapture-insertable-streams/tentative/MediaStreamTrackProcessor-backpressure.https.html [ Failure ]
diff --git a/third_party/blink/web_tests/editing/execCommand/indent/indent_pre_with_new_lines.html b/third_party/blink/web_tests/editing/execCommand/indent/indent_pre_with_new_lines.html new file mode 100644 index 0000000..77a9300 --- /dev/null +++ b/third_party/blink/web_tests/editing/execCommand/indent/indent_pre_with_new_lines.html
@@ -0,0 +1,19 @@ +<!doctype html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../assert_selection.js"></script> +<div id="log"></div> +<script> +test(() => { + assert_selection( + '<div contenteditable style="white-space: pre">^\nHello|</div>', + 'indent', + '<div contenteditable style="white-space: pre"><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">^\nHello|</blockquote></div>'); +}, 'Indent a block that preserves white spaces. The block has texts started with a new line.'); +test(() => { + assert_selection( + '<div contenteditable style="white-space: pre">^\n<div>Hello|</div></div>', + 'indent', + '<div contenteditable style="white-space: pre"><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">^\n<div>Hello|</div></blockquote></div>'); +}, 'Indent a block that preserves white spaces. The block has a new line text and a div.'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/credential-management/fedcm-login-status-unknown.https.html b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-login-status-unknown.https.html new file mode 100644 index 0000000..d542524 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/credential-management/fedcm-login-status-unknown.https.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>FedCM IDP sign-in status API tests for unknown state</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> + +<script type="module"> + import {request_options_with_mediation_required, + fedcm_test, + select_manifest, + fedcm_get_and_select_first_account} from './support/fedcm-helper.sub.js'; + + // TODO(crbug.com/1494119): move the test under fedcm-login-status. + fedcm_test(async t => { + let test_options = request_options_with_mediation_required("manifest_with_no_accounts.json"); + await select_manifest(t, test_options); + + let request = navigator.credentials.get(test_options); + return promise_rejects_dom(t, 'NetworkError', request); + }, 'Test that promise is rejected silently when accounts fetch fails in unknown state'); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js index 80c164f..ad2119b 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js +++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/back-forward-cache/resources/rc-helper.js
@@ -41,13 +41,14 @@ return Array.from(s).sort(); } -// Assert expected reasons and the reported reasons match. +// Assert expected reasons are all present. Note that the extra reasons are allowed +// as UAs might block bfcache for their specific reasons. function matchReasons(expectedNotRestoredReasonsSet, notRestoredReasonsSet) { const missing = setMinus( expectedNotRestoredReasonsSet, notRestoredReasonsSet, 'Missing reasons'); const extra = setMinus( notRestoredReasonsSet, expectedNotRestoredReasonsSet, 'Extra reasons'); - assert_true(missing.size + extra.size == 0, `Expected: ${sorted(expectedNotRestoredReasonsSet)}\n` + + assert_true(missing.size == 0, `Expected: ${sorted(expectedNotRestoredReasonsSet)}\n` + `Got: ${sorted(notRestoredReasonsSet)}\n` + `Missing: ${sorted(missing)}\n` + `Extra: ${sorted(extra)}\n`);
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window-expected.txt b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window-expected.txt deleted file mode 100644 index 6ff24d8..0000000 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] aborting a parser should block bfcache. - assert_equals: expected "parser-aborted" but got "loading" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js index 09a73509..e5dbb0f 100644 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/abort-block-bfcache.window.js
@@ -1,4 +1,5 @@ // META: title=Aborting a parser should block bfcache +// META: script=./test-helper.js // META: timeout=long @@ -14,8 +15,7 @@ window.stop(); } else { const nrr = performance.getEntriesByType('navigation')[0].notRestoredReasons; - assert_equals(nrr.reasons[0].reason, "parser-aborted"); - assert_equals(nrr.reasons.length, 1); + assert_true(ReasonsInclude(nrr.reasons, "parser-aborted")); t.done(); } }, "aborting a parser should block bfcache.");
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-lock.https.tentative.window-expected.txt b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-lock.https.tentative.window-expected.txt deleted file mode 100644 index 781a7c7a..0000000 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-lock.https.tentative.window-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] Ensure that if WebLock is held upon entering bfcache, it cannot enter bfcache and gets reported. - assert_true: Expected: lock\nGot: lock,masked\nMissing: \nExtra: masked\n expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window-expected.txt b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window-expected.txt deleted file mode 100644 index 0a4aa3f9..0000000 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-navigation-failure.tentative.window-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] Ensure that navigation failure blocks bfcache and gets recorded. - assert_true: Expected: navigation-failure\nGot: http-status-not-ok,masked\nMissing: navigation-failure\nExtra: http-status-not-ok,masked\n expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/test-helper.js b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/test-helper.js index 97695cd..826b0cc 100644 --- a/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/test-helper.js +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/not-restored-reasons/test-helper.js
@@ -34,6 +34,15 @@ } } +function ReasonsInclude(reasons, targetReason) { + for (const reason of reasons) { + if (reason.reason == targetReason) { + return true; + } + } + return false; +} + // Requires: // - /websockets/constants.sub.js in the test file and pass the domainPort // constant here.
diff --git a/third_party/blink/web_tests/external/wpt/websockets/handlers/passive-close-abort_wsh.py b/third_party/blink/web_tests/external/wpt/websockets/handlers/passive-close-abort_wsh.py new file mode 100644 index 0000000..ac3f67c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/websockets/handlers/passive-close-abort_wsh.py
@@ -0,0 +1,24 @@ +# Copyright (c) 2024 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. + +""" +Wait for a Close frame from the client and then close the connection without +sending a Close frame in return. +""" + +from mod_pywebsocket.handshake import AbortedByUserException + + +def web_socket_do_extra_handshake(request): + pass + + +def web_socket_transfer_data(request): + while True: + if request.ws_stream.receive_message() is None: + return + + +def web_socket_passive_closing_handshake(request): + raise AbortedByUserException('abrupt close')
diff --git a/third_party/blink/web_tests/external/wpt/websockets/handlers/remote-close_wsh.py b/third_party/blink/web_tests/external/wpt/websockets/handlers/remote-close_wsh.py new file mode 100644 index 0000000..aadd99e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/websockets/handlers/remote-close_wsh.py
@@ -0,0 +1,44 @@ +# Copyright (c) 2024 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. + +""" +Perform a server-initiated close according to the parameters passed in the +query string. Supported parameters: + + * code=INT: The close code to send in the close frame. If omitted the Close + frame will have an empty body. + + * reason=TEXT: The reason to be sent in the close frame. Only sent if `code` is + set. + + * abrupt=1: Close the connection without sending a Close frame. + +Example: /remote-close?code=1000&reason=Done + +""" + +import urllib + +from mod_pywebsocket.handshake import AbortedByUserException + + +def web_socket_do_extra_handshake(request): + pass + + +def web_socket_transfer_data(request): + parts = urllib.parse.urlsplit(request.uri) + parameters = urllib.parse.parse_qs(parts.query) + if 'abrupt' in parameters: + # Send a ping frame to make sure this isn't misinterpreted as a + # handshake failure. + request.ws_stream.send_ping('ping') + # Rudely close the connection. + raise AbortedByUserException('Abort the connection') + code = None + reason = None + if 'code' in parameters: + code = int(parameters['code'][0]) + reason = parameters.get('reason', [''])[0] + request.ws_stream.close_connection(code, reason)
diff --git a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/close.any.js b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/close.any.js index 098caf3..ad41dc6 100644 --- a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/close.any.js +++ b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/close.any.js
@@ -1,6 +1,7 @@ // META: script=../../constants.sub.js // META: script=resources/url-constants.js // META: global=window,worker +// META: variant=?default // META: variant=?wss // META: variant=?wpt_flags=h2 @@ -108,6 +109,15 @@ 'one second should have elapsed'); }, 'writer close() promise should not resolve until handshake completes'); +promise_test(async t => { + const wss = new WebSocketStream(`${BASEURL}/passive-close-abort`); + await wss.opened; + wss.close({closeCode: 4000, reason: 'because'}); + const error = await wss.closed.then(t.unreached_func('closed should reject'), e => e); + assert_equals(error.constructor, WebSocketError, 'error should be WebSocketError'); + assert_equals(error.closeCode, 1006, 'close code should be Abnormal Closure'); +}, 'incomplete closing handshake should be considered unclean close'); + const abortOrCancel = [ { method: 'abort',
diff --git a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.js b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.js new file mode 100644 index 0000000..b7fd321 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.js
@@ -0,0 +1,74 @@ +// META: script=../../constants.sub.js +// META: script=resources/url-constants.js +// META: global=window,worker +// META: variant=?default +// META: variant=?wss +// META: variant=?wpt_flags=h2 + +'use strict'; + +promise_test(async t => { + const wss = new WebSocketStream(`${BASEURL}/remote-close?code=1000`); + const { readable, writable } = await wss.opened; + const { closeCode, reason } = await wss.closed; + assert_equals(closeCode, 1000, 'code should be 1000'); + assert_equals(reason, '', 'reason should be empty'); + const { value, done } = await readable.getReader().read(); + assert_true(done, 'readable should be closed'); + await promise_rejects_dom(t, 'InvalidStateError', writable.getWriter().ready, + 'writable should be errored'); +}, 'clean close should be clean'); + +promise_test(async () => { + const wss = new WebSocketStream(`${BASEURL}/remote-close`); + const { closeCode, reason } = await wss.closed; + assert_equals(closeCode, 1005, 'code should be No Status Rcvd'); + assert_equals(reason, '', 'reason should be empty'); +}, 'close frame with no body should result in status code 1005'); + +promise_test(async () => { + const wss = new WebSocketStream(`${BASEURL}/remote-close?code=4000&reason=robot`); + const { closeCode, reason } = await wss.closed; + assert_equals(closeCode, 4000, 'code should be 4000'); + assert_equals(reason, 'robot', 'reason should be set'); +}, 'reason should be passed through'); + +promise_test(async () => { + const wss = new WebSocketStream(`${BASEURL}/remote-close?code=4000&` + + 'reason=%E3%83%AD%E3%83%9C%E3%83%83%E3%83%88'); + const { reason } = await wss.closed; + assert_equals(reason, 'ãƒãƒœãƒƒãƒˆ', 'reason should be set'); +}, 'UTF-8 reason should work'); + +promise_test(async t => { + const wss = new WebSocketStream(`${BASEURL}/remote-close?code=4567`); + const { writable } = await wss.opened; + const veryLargeMessage = new Uint8Array(20 * 1024 * 1024); // 20MB. + const writePromise = writable.getWriter().write(veryLargeMessage); + const closedError = await wss.closed.then(t.unreached_func('closed should reject'), e => e); + assert_equals(closedError.constructor, WebSocketError, 'error should be WebSocketError'); + assert_equals(closedError.closeCode, 4567, 'closeCode should be set'); + promise_rejects_js(t, WebSocketError, writePromise, 'write() should reject'); +}, 'close with unwritten data should not be considered clean'); + +promise_test(async t => { + const wss = new WebSocketStream(`${BASEURL}/remote-close?code=4222&reason=remote`); + await wss.opened; + wss.close({closeCode: 4111, reason: 'local'}); + const { closeCode, reason } = await wss.closed; + assert_equals(closeCode, 4222, 'remote code should be used'); + assert_equals(reason, 'remote', 'remote reason should be used'); +}, 'remote code and reason should be used'); + +promise_test(async t => { + const wss = new WebSocketStream(`${BASEURL}/remote-close?abrupt=1`); + const { readable, writable } = await wss.opened; + const closedError = await wss.closed.then(t.unreached_func('closed should reject'), e => e); + assert_equals(closedError.constructor, WebSocketError, 'error should be a WebSocketError'); + assert_equals(closedError.name, 'WebSocketError', 'error name should be WebSocketError'); + assert_equals(closedError.closeCode, 1006, 'code should be Abnormal Closure'); + await promise_rejects_exactly(t, closedError, readable.getReader().read(), + 'readable should be errored with the same object'); + await promise_rejects_exactly(t, closedError, writable.getWriter().ready, + 'writable should be errored with the same object'); +}, 'abrupt close should give an error');
diff --git a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.serviceworker_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.serviceworker_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..7d8f8682 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.serviceworker_wpt_flags=h2-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: WebSocket was not cleanly closed. +[FAIL] clean close should be clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] close frame with no body should result in status code 1005 + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] reason should be passed through + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] UTF-8 reason should work + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] close with unwritten data should not be considered clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] remote code and reason should be used + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] abrupt close should give an error + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.sharedworker_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.sharedworker_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..7d8f8682 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.sharedworker_wpt_flags=h2-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: WebSocket was not cleanly closed. +[FAIL] clean close should be clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] close frame with no body should result in status code 1005 + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] reason should be passed through + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] UTF-8 reason should work + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] close with unwritten data should not be considered clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] remote code and reason should be used + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] abrupt close should give an error + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.worker_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.worker_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..7d8f8682 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any.worker_wpt_flags=h2-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: WebSocket was not cleanly closed. +[FAIL] clean close should be clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] close frame with no body should result in status code 1005 + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] reason should be passed through + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] UTF-8 reason should work + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] close with unwritten data should not be considered clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] remote code and reason should be used + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] abrupt close should give an error + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..7d8f8682 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/websockets/stream/tentative/remote-close.any_wpt_flags=h2-expected.txt
@@ -0,0 +1,18 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Unhandled rejection: WebSocket was not cleanly closed. +[FAIL] clean close should be clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] close frame with no body should result in status code 1005 + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] reason should be passed through + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] UTF-8 reason should work + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket was not cleanly closed." +[FAIL] close with unwritten data should not be considered clean + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] remote code and reason should be used + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +[FAIL] abrupt close should give an error + promise_test: Unhandled rejection with value: object "WebSocketError: WebSocket closed before handshake complete." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.serviceworker_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.serviceworker_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..5b37deb --- /dev/null +++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.serviceworker_wpt_flags=h2-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +All subtests passed and are omitted for brevity. +See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.sharedworker_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.sharedworker_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..5b37deb --- /dev/null +++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.sharedworker_wpt_flags=h2-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +All subtests passed and are omitted for brevity. +See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.worker_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.worker_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..5b37deb --- /dev/null +++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any.worker_wpt_flags=h2-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +All subtests passed and are omitted for brevity. +See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any_wpt_flags=h2-expected.txt b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any_wpt_flags=h2-expected.txt new file mode 100644 index 0000000..5b37deb --- /dev/null +++ b/third_party/blink/web_tests/platform/linux-chrome/external/wpt/websockets/stream/tentative/remote-close.any_wpt_flags=h2-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +All subtests passed and are omitted for brevity. +See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. +Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-in-multicol-crash.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-in-multicol-crash.html new file mode 100644 index 0000000..140c3f6 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-in-multicol-crash.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<title>CSS Anchor Positioning: Crash with anchor in multicol</title> +<link rel="help" href="https://issues.chromium.org/issues/324930388"> +<style> +.cb { + position: relative; + border: 1px solid black; +} +.columns { + column-count: 4; + column-width: 100px; + width: 320px; + height: 100px; +} +.anchor { + anchor-name: --a1; + width: 100px; + height: 90px; + background: blue; +} +.target { + position: absolute; + width: 10px; + height: 10px; + background: purple; + position-fallback: --pf; +} +@position-fallback --pf { + @try { + right: 400px; + bottom: 10px; + } + @try { + right: 40px; + bottom: 30px; + } +} +</style> +<body> + PASS if no crash + <div class="columns"> + <div class="cb"> + <div class=anchor></div> + <div class=target></div> + </div> + </div> +</body>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-in-multicol-inherit-crash.html b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-in-multicol-inherit-crash.html new file mode 100644 index 0000000..b2e644b --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-anchor-position/anchor-in-multicol-inherit-crash.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<title>CSS Anchor Positioning: Crash with anchor in multicol (inheritance)</title> +<link rel="help" href="https://issues.chromium.org/issues/324930388"> +<style> +.cb { + position: relative; + border: 1px solid black; +} +.columns { + column-count: 4; + column-width: 100px; + width: 320px; + height: 100px; +} +.anchor { + anchor-name: --a1; + width: 100px; + height: 90px; + background: blue; +} +.target { + position: absolute; + width: 10px; + height: 10px; + background: purple; + position-fallback: --pf; +} +.child { + position: absolute; + right: inherit; + bottom: inherit; +} +@position-fallback --pf { + @try { + right: 400px; + bottom: 10px; + } + @try { + right: 40px; + bottom: 30px; + } +} +</style> +<body> + PASS if no crash + <div class="columns"> + <div class="cb"> + <div class=anchor></div> + <div class=target> + <div class=child></div> + </div> + </div> + </div> +</body>
diff --git a/third_party/catapult b/third_party/catapult index fa6a888..56ba67e 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit fa6a888a12fcdba798061eb6680cabc8e1573a42 +Subproject commit 56ba67e870f9511d59155a9d8f40ff4afdea73d7
diff --git a/third_party/chromium-variations b/third_party/chromium-variations index d1a16c4..bc7922f 160000 --- a/third_party/chromium-variations +++ b/third_party/chromium-variations
@@ -1 +1 @@ -Subproject commit d1a16c439233c3c7199fcc3f0507b1d012611ab9 +Subproject commit bc7922fea2a34cdd9f5b704b95cae57b3779fcbd
diff --git a/third_party/cros-components/src b/third_party/cros-components/src index caaac73..62c84c4 160000 --- a/third_party/cros-components/src +++ b/third_party/cros-components/src
@@ -1 +1 @@ -Subproject commit caaac730221dc9e0a461e7eedcae4a35a46696bd +Subproject commit 62c84c45907dd68c94ad119532653edffed86e5c
diff --git a/third_party/dawn b/third_party/dawn index f5abb82..2ed7112 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit f5abb823f98d0ab55b31b63453d46188b7f9e5a3 +Subproject commit 2ed7112412452a0104c1a7dc68748549d385392b
diff --git a/third_party/depot_tools b/third_party/depot_tools index af26c1df..00915b6 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit af26c1dfaae2f3c632d88bf9bd78526866afe180 +Subproject commit 00915b68748cc78969f6269b78ddaae0a120e993
diff --git a/third_party/skia b/third_party/skia index 292f17e..a673ab6 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 292f17ed8a19f7f18c386a691001148f503c9611 +Subproject commit a673ab63fccc0d194dcd3d0414aeaf2f53920a9e
diff --git a/third_party/webrtc b/third_party/webrtc index a8c4727..2825f0a 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit a8c47276cb6d3188db8b5a4ba77abd07797c0071 +Subproject commit 2825f0a7bbd08f8ee466291d7ee7a77fa7838e03
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index e1dde16a..ad7b372d 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -18827,6 +18827,7 @@ <int value="-908421850" label="PointerEvent:enabled"/> <int value="-907481658" label="ArcMouseWheelSmoothScroll:enabled"/> <int value="-907234795" label="NewAudioRenderingMixingStrategy:disabled"/> + <int value="-906173229" label="AutofillEnableCardBenefitsSync:disabled"/> <int value="-905538983" label="SimplifyHttpsIndicator:disabled"/> <int value="-904337228" label="CameraMicPreview:enabled"/> <int value="-903524547" label="DiscoFeedEndpoint:disabled"/> @@ -18899,6 +18900,7 @@ <int value="-871419968" label="FilesTrashDrive:enabled"/> <int value="-870994173" label="NtpChromeCartModule:enabled"/> <int value="-870120067" label="EnableSearchBoxSelection:enabled"/> + <int value="-870118210" label="AutofillEnableCardBenefitsSync:enabled"/> <int value="-869690461" label="ShoppingListTrackByDefault:enabled"/> <int value="-868138290" label="CrostiniPortForwarding:disabled"/> <int value="-868041476" label="OmniboxFocusTriggersSRPZeroSuggest:enabled"/>
diff --git a/tools/metrics/histograms/metadata/autofill/enums.xml b/tools/metrics/histograms/metadata/autofill/enums.xml index 8e47548..7a2aefd 100644 --- a/tools/metrics/histograms/metadata/autofill/enums.xml +++ b/tools/metrics/histograms/metadata/autofill/enums.xml
@@ -1522,6 +1522,9 @@ <int value="25" label="The user edited the field. Currently applied only to Compose suggestions."/> + <int value="26" + label="The popup has faded due to an expired timer. Currently applied + only to Compose suggestions."/> </enum> <enum name="AutofillPredictionsComparisonResult">
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index 05604d9..00f18f3 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -1852,6 +1852,18 @@ </summary> </histogram> +<histogram name="Autofill.EmailPredictionCorrectness.Recall" + enum="EmailPredictionConfusionMatrix" expires_after="2024-12-12"> + <owner>vizcay@chromium.org</owner> + <owner>jkeitel@chromium.org</owner> + <owner>src/components/autofill/OWNERS</owner> + <summary> + Logs the recall of an EMAIL_ADDRESS field prediction. Emitted at form + submission time for every field for which its value matches the email + format. + </summary> +</histogram> + <histogram name="Autofill.ErrorDialogShown" enum="AutofillErrorDialogType" expires_after="2024-07-01"> <owner>siyua@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml index 03158697..0d847cf1 100644 --- a/tools/metrics/histograms/metadata/memory/histograms.xml +++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -1226,6 +1226,15 @@ way to compare any system level memory metric across platforms due to the different nature of memory management on each platform. + WARNING: This metric does not include the footprint of the graphics buffers + on all platforms. Concretely, this means that on these platforms, this + metric will drastically underestimate the true cost of rendering. On devices + with unified memory (most Android, laptop and desktop clients with + integrated graphics, and all ARM64 mac clients), graphics buffers come from + the same memory pool as system RAM. For more details, alternative metrics to + monitor, and the state of various platforms, see + docs/memory/graphics_metrics.md. + This histogram is of special interest to the chrome-analysis-team@. Do not change its semantics or retire it without talking to them first. </summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index e4c3d7b0..6be0864 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1836,7 +1836,7 @@ <histogram name="Prerender.Experimental.CrossOriginRedirectionProtocolChange{PreloadingTriggerType}" enum="PrerenderCrossOriginRedirectionProtocolChange" - expires_after="2024-03-01"> + expires_after="2024-06-01"> <owner>lingqi@chromium.org</owner> <owner>nhiroki@chromium.org</owner> <owner>src/content/browser/preloading/prerender/OWNERS</owner> @@ -1919,7 +1919,7 @@ <histogram name="Prerender.Experimental.PrerenderCrossOriginRedirectionMismatch{PreloadingTriggerType}" - enum="PrerenderCrossOriginRedirectionMismatch" expires_after="2024-03-01"> + enum="PrerenderCrossOriginRedirectionMismatch" expires_after="2024-06-01"> <owner>lingqi@chromium.org</owner> <owner>nhiroki@chromium.org</owner> <owner>src/content/browser/preloading/prerender/OWNERS</owner> @@ -2041,10 +2041,13 @@ </histogram> <histogram name="Prerender.Experimental.Search.ResponseReuseCount" - units="count" expires_after="2023-11-20"> + units="count" expires_after="2024-08-20"> <owner>lingqi@chromium.org</owner> <owner>chrome-prerendering@google.com</owner> <summary> + Warning: this histogram was expired from 2023-11-20 to 2024-02-27; data may + be missing. + Recorded by StreamingSearchPrefetchURLLoader in its destructor. This instance is created per (non-duplicated) prefetch attempt. The destructor runs upon:
diff --git a/tools/metrics/histograms/metadata/password/enums.xml b/tools/metrics/histograms/metadata/password/enums.xml index 57a882d..54c9365 100644 --- a/tools/metrics/histograms/metadata/password/enums.xml +++ b/tools/metrics/histograms/metadata/password/enums.xml
@@ -111,6 +111,11 @@ <int value="7" label="Android version not supported"/> </enum> +<enum name="BooleanCalled"> + <int value="0" label="Not called"/> + <int value="1" label="Called"/> +</enum> + <enum name="BooleanFormManager"> <int value="0" label="Has Form Manager"/> <int value="1" label="Lacks Form Manager"/>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index ab509739..9b183c7 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -78,6 +78,12 @@ <variant name="UpdateLoginAsync" summary="UpdateLoginAsync()"/> </variants> +<variants name="PasswordStoreBackendType"> + <variant name="AccountBackend" summary="account backend"/> + <variant name="BuiltInBackend" summary="built in backend"/> + <variant name="LocalBackend" summary="local backend"/> +</variants> + <variants name="PasswordType"> <variant name="AutoGenerated" summary="automatically generated"/> <variant name="Overall" summary="generated or created or shared"/> @@ -2739,6 +2745,30 @@ </histogram> <histogram + name="PasswordManager.PasswordStore.{PasswordStoreBackendType}.AddLoginCalledOnStore" + enum="BooleanCalled" expires_after="2024-06-30"> + <owner>sygiet@google.com</owner> + <owner>vasilii@chromium.org</owner> + <summary> + Records calls to AddLoginAsync made from the PasswordStore. Recorded after + the call to AddLoginAsync() on the backend. + </summary> + <token key="PasswordStoreBackendType" variants="PasswordStoreBackendType"/> +</histogram> + +<histogram + name="PasswordManager.PasswordStore.{PasswordStoreBackendType}.UpdateLoginCalledOnStore" + enum="BooleanCalled" expires_after="2024-06-30"> + <owner>sygiet@google.com</owner> + <owner>vasilii@chromium.org</owner> + <summary> + Records calls to UpdateLoginAsync made from the PasswordStore. Recorded + after the call to UpdateLoginAsync() on the backend. + </summary> + <token key="PasswordStoreBackendType" variants="PasswordStoreBackendType"/> +</histogram> + +<histogram name="PasswordManager.PasswordStoreAndroidBackend.Retry{Operation}.APIError" enum="PasswordStoreAndroidBackendAPIError" expires_after="2024-07-07"> <owner>izuzic@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml index 0fccc52..8551179 100644 --- a/tools/metrics/histograms/metadata/security/histograms.xml +++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -427,7 +427,7 @@ </histogram> <histogram name="Security.PrivateNetworkAccess.PermissionDeviceValidity" - enum="PrivateNetworkDeviceValidity" expires_after="M125"> + enum="PrivateNetworkDeviceValidity" expires_after="M128"> <owner>lyf@chromium.org</owner> <owner>phao@chromium.org</owner> <owner>clamy@chromium.org</owner> @@ -440,7 +440,7 @@ </histogram> <histogram name="Security.PrivateNetworkAccess.PermissionNewAcceptedDeviceType" - enum="NewAcceptedDeviceType" expires_after="M125"> + enum="NewAcceptedDeviceType" expires_after="M128"> <owner>lyf@chromium.org</owner> <owner>phao@chromium.org</owner> <owner>clamy@chromium.org</owner> @@ -453,7 +453,7 @@ </histogram> <histogram name="Security.PrivateNetworkAccess.PrivateIpInferrable" - enum="Boolean" expires_after="2024-03-03"> + enum="Boolean" expires_after="2024-08-20"> <owner>titouan@chromium.org</owner> <owner>lyf@chromium.org</owner> <owner>clamy@chromium.org</owner>
diff --git a/tools/perf/contrib/shared_storage/README.md b/tools/perf/contrib/shared_storage/README.md index 8904058..9a72e113 100644 --- a/tools/perf/contrib/shared_storage/README.md +++ b/tools/perf/contrib/shared_storage/README.md
@@ -62,3 +62,16 @@ ```bash tools/perf/run_benchmark shared_storage.small --browser=system --story-filter=Append --iterations=5 --pageset-repeat=1 --xvfb --verbose-cpu-metrics --verbose-memory-metrics --verbose ``` + +## Post-Test Result Processing + +By default, shared storage perf test results will be displayed in a file at path `$CHROMIUM_SRC/tools/perf/results.html`, where `$CHROMIUM_SRC` is your Chromium source directory. + +The shared storage perf tests have a script to process results further into various human-friendly files with paths `$CHROMIUM_SRC/tools/perf/contrib/shared_storage/data/histograms_*.json`. + +To run the script, run the following command manually after a perf test run completes: +```bash +tools/perf/contrib/shared_storage/process_results +``` + +In particular, the above script will compare the actual histogram sample counts recorded during the run with the expected counts, and notify you of any deltas. If there are any non-zero deltas.
diff --git a/tools/perf/contrib/shared_storage/process_results b/tools/perf/contrib/shared_storage/process_results new file mode 100755 index 0000000..7d7bdfbe --- /dev/null +++ b/tools/perf/contrib/shared_storage/process_results
@@ -0,0 +1,12 @@ +#!/usr/bin/env vpython3 +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import sys + +import utils + + +if __name__ == '__main__': + sys.exit(utils.ProcessResults()) \ No newline at end of file
diff --git a/tools/perf/contrib/shared_storage/utils/__init__.py b/tools/perf/contrib/shared_storage/utils/__init__.py index 6df177a..823762d 100644 --- a/tools/perf/contrib/shared_storage/utils/__init__.py +++ b/tools/perf/contrib/shared_storage/utils/__init__.py
@@ -8,11 +8,13 @@ 'GetExpectedHistogramsDictionary', 'GetExpectedHistogramsFile', 'GetHistogramsFromEventType', + 'GetNonePlaceholder', 'GetSharedStorageIteratorHistograms', 'GetSharedStorageUmaHistograms', 'GetRunPathFile', 'JsonDump', 'MovePreviousExpectedHistogramsFile', + 'ProcessResults', ] from .file_util import (CleanUpRunPathFile, EnsureDataDir, @@ -22,4 +24,5 @@ from .histogram_list import (GetHistogramsFromEventType, GetSharedStorageIteratorHistograms, GetSharedStorageUmaHistograms) -from .util import JsonDump +from .process_results import ProcessResults +from .util import GetNonePlaceholder, JsonDump
diff --git a/tools/perf/contrib/shared_storage/utils/file_util.py b/tools/perf/contrib/shared_storage/utils/file_util.py index db09ba8..a5ee98f 100644 --- a/tools/perf/contrib/shared_storage/utils/file_util.py +++ b/tools/perf/contrib/shared_storage/utils/file_util.py
@@ -6,10 +6,21 @@ import logging import os import shutil +import string _SHARED_STORAGE_DIR = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir)) +_PROCESSOR = os.path.abspath( + os.path.join(_SHARED_STORAGE_DIR, os.pardir, os.pardir, + 'results_processor')) + +_HISTOGRAMS_RAW = os.path.abspath( + os.path.join(_SHARED_STORAGE_DIR, os.pardir, os.pardir, 'histograms.json')) + +_SHARED_STORAGE_FILE = os.path.abspath( + os.path.join(_SHARED_STORAGE_DIR, 'shared_storage.py')) + _DATA_DIR = os.path.abspath(os.path.join(_SHARED_STORAGE_DIR, 'data')) _RUN_PATH_FILE = os.path.abspath(os.path.join(_DATA_DIR, 'run_path.txt')) @@ -17,6 +28,41 @@ _HISTOGRAMS_EXPECTED = os.path.abspath( os.path.join(_DATA_DIR, 'histograms_expected.json')) +_HISTOGRAMS_INFO = os.path.abspath( + os.path.join(_DATA_DIR, 'histograms_info.json')) + +_HISTOGRAMS_AGG = os.path.abspath( + os.path.join(_DATA_DIR, 'histograms_aggregated.json')) + +_HISTOGRAMS_STORY = os.path.abspath( + os.path.join(_DATA_DIR, 'histograms_by_story.json')) + +_HISTOGRAM_COUNTS = os.path.abspath( + os.path.join(_DATA_DIR, 'histogram_counts.json')) + +_HISTOGRAM_COUNT_DELTAS = os.path.abspath( + os.path.join(_DATA_DIR, 'histogram_count_deltas.json')) + +_PROCESSED_FILES = [ + _HISTOGRAMS_INFO, + _HISTOGRAMS_AGG, + _HISTOGRAMS_STORY, + _HISTOGRAM_COUNTS, + _HISTOGRAM_COUNT_DELTAS, +] + + +def GetProcessor(): + return _PROCESSOR + + +def GetRawHistogramsFile(): + return _HISTOGRAMS_RAW + + +def GetDataDir(): + return _DATA_DIR + def GetRunPathFile(): return _RUN_PATH_FILE @@ -26,6 +72,14 @@ return _HISTOGRAMS_EXPECTED +def GetHistogramCountDeltasFile(): + return _HISTOGRAM_COUNT_DELTAS + + +def GetProcessedFiles(): + return _PROCESSED_FILES + + def EnsureDataDir(): # Ensure that /data exists and is a directory. (Delete and recreate # if it's not a directory.) @@ -75,8 +129,51 @@ _MovePreviousFile(_HISTOGRAMS_EXPECTED) +def _MovePreviousRawHistogramsFile(): + # If histograms.json exists from a previous run, move it. + destination = os.path.abspath(os.path.join(_DATA_DIR, 'histograms_.json')) + _MovePreviousFile(_HISTOGRAMS_RAW, dest_path_without_time=destination) + + +def _MovePreviousProcessedHistogramsFiles(): + for filename in _PROCESSED_FILES: + _MovePreviousFile(filename) + + +def MovePreviousHistogramsFiles(): + _MovePreviousRawHistogramsFile() + _MovePreviousProcessedHistogramsFiles() + + def GetExpectedHistogramsDictionary(): counts_data = {} with open(_HISTOGRAMS_EXPECTED, 'r') as f: counts_data = json.load(f) return counts_data + + +def GetBenchmarkDBSize(benchmark_name): + # We read the file instead of importing to prevent a circular import. + benchmark_file = None + if (not os.path.exists(_SHARED_STORAGE_FILE) + or not os.path.isfile(_SHARED_STORAGE_FILE)): + raise RuntimeError('%s does not exist or is not a file' % + _SHARED_STORAGE_FILE) + with open(_SHARED_STORAGE_FILE, 'r') as f: + benchmark_file = f.read() + + name_pos = benchmark_file.find(benchmark_name) + if name_pos < 0: + raise ValueError('benchmark_name %s not found' % benchmark_name) + size_prefix = 'SIZE = ' + size_prefix_pos = benchmark_file.rfind(size_prefix, 0, name_pos - 1) + if size_prefix_pos < 0: + raise RuntimeError("%s not found before benchmark name" % size_prefix) + start_pos = size_prefix_pos + len(size_prefix) + end_pos = start_pos + 1 + while end_pos < name_pos and benchmark_file[end_pos] in string.digits: + end_pos += 1 + size_str = benchmark_file[start_pos:end_pos] + if not size_str.isdigit(): + raise RuntimeError('Expected %s to be castable to an integer' % size_str) + return int(size_str)
diff --git a/tools/perf/contrib/shared_storage/utils/process_results.py b/tools/perf/contrib/shared_storage/utils/process_results.py new file mode 100644 index 0000000..5cab7ce --- /dev/null +++ b/tools/perf/contrib/shared_storage/utils/process_results.py
@@ -0,0 +1,234 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from collections import Counter +import json +import logging +import os +import subprocess +import traceback + +from .file_util import (GetBenchmarkDBSize, GetDataDir, + GetExpectedHistogramsDictionary, + GetExpectedHistogramsFile, GetHistogramCountDeltasFile, + GetProcessedFiles, GetProcessor, GetRawHistogramsFile, + GetRunPathFile, MovePreviousHistogramsFiles) +from .histogram_list import GetSharedStorageUmaHistograms +from .util import GetNonePlaceholder, JsonDump + + +def _ProcessHistograms(histogram_data): + if not isinstance(histogram_data, list): + raise RuntimeError( + 'Expected histogram_data to be type list but got type %s' % + type(histogram_data)) + + guid_map = {} + histogram_info = {} + expected_processed_all_guids = False + benchmark_name = None + + for item in histogram_data: + if not isinstance(item, dict): + raise RuntimeError('Expected item to be type dict but got type %s' % + type(item)) + + if 'guid' in item: + if expected_processed_all_guids: + info = ('; %s\nitem[`guid`]: %s' % + (JsonDump(item), item.get('guid', '[[Not Found]]'))) + msg = 'Expected to process all items with `guid` before any with `name`' + raise RuntimeError(msg + info) + if len(item) != 3: + raise RuntimeError( + 'Expected item with `guid` to have length 3; got item: %s' % + JsonDump(item)) + if 'type' not in item: + raise RuntimeError( + 'Expected item with `guid` to have key `type`; got: %s' % + JsonDump(item)) + [value_key] = [key for key in item if key not in ('guid', 'type')] + guid_map[item['guid']] = item[value_key] + + elif 'name' in item: + expected_processed_all_guids = True + name = item['name'] + if not name in GetSharedStorageUmaHistograms(): + continue + for key in ['diagnostics', 'running', 'sampleValues']: + if key not in item: + raise RuntimeError( + 'Expected item with `name` to have key `%s`; got: %s' % + (key, JsonDump(item))) + + histogram_info.setdefault(name, []) + item_diagnostics = item['diagnostics'] + diagnostics = { + key: guid_map.get(item_diagnostics[key], item_diagnostics[key]) + for key in item_diagnostics + } + item_info = { + 'diagnostics': diagnostics, + 'running': item['running'], + 'sampleValues': item['sampleValues'] + } + histogram_info[name].append(item_info) + if not benchmark_name: + if (not 'benchmarks' in diagnostics + or len(diagnostics['benchmarks']) != 1): + RuntimeError( + 'Expected `diagnostics` to have `benchmarks` of length 1; got %s' + % JsonDump(diagnostics)) + benchmark_name = diagnostics['benchmarks'][0] + + agg_histograms = {} + by_story = {} + counts = {} + + for histogram, info_list in histogram_info.items(): + agg_histograms.setdefault(histogram, []) + + for entry in info_list: + for key in ['diagnostics', 'sampleValues']: + if key not in entry: + raise RuntimeError('Entry %s does not have key `%s`' % + (JsonDump(entry), key)) + for key in ['stories', 'storysetRepeats']: + if key not in entry['diagnostics']: + raise RuntimeError('Entry diagnostics %s does not have key `%s`' % + (JsonDump(entry), key)) + if len(entry['diagnostics'][key]) != 1: + raise RuntimeError( + 'Entry diagnostics %s expected `%s` to lave length 1' % + (JsonDump(entry), key)) + + agg_histograms[histogram] += entry['sampleValues'] + + [story] = entry['diagnostics']['stories'] + [rep] = entry['diagnostics']['storysetRepeats'] + + by_story.setdefault(story, {}).setdefault(rep, + {}).setdefault(histogram, []) + by_story[story][rep][histogram] += entry['sampleValues'] + counts.setdefault(story, {}).setdefault(rep, Counter()) + counts[story][rep][histogram] += len(entry['sampleValues']) + + runs_all_match, deltas = _CheckHistogramCounts(counts) + results = [histogram_info, agg_histograms, by_story, counts, deltas] + size = GetBenchmarkDBSize(benchmark_name) + return runs_all_match, size, list(map(JsonDump, results)) + + +def _CheckHistogramCounts(actual_counts): + counts_match = True + expected_counts = GetExpectedHistogramsDictionary() + missed_stories = (set(expected_counts.keys()).difference( + set(actual_counts.keys()))) + if len(missed_stories) > 0: + counts_match = False + logging.warning('Missed recording for stories %s' % + repr(list(missed_stories))) + unexpected_stories = (set(actual_counts.keys()).difference( + set(expected_counts.keys()))) + if len(missed_stories) > 0: + counts_match = False + logging.warning('Unexpectedly recorded for stories %s' % + repr(list(unexpected_stories))) + + deltas = {} + for story, repeats in actual_counts.items(): + for repeat, histogram_counts in repeats.items(): + if histogram_counts == expected_counts[story]: + continue + counts_match = False + deltas.setdefault(story, {}).setdefault(repeat, Counter()) + missed_histograms = (set(expected_counts[story].keys()).difference( + set(histogram_counts.keys()))) + for histogram in missed_histograms: + expected_count = expected_counts[story][histogram] + deltas[story][repeat][histogram] = -expected_count + for histogram, count in histogram_counts.items(): + expected_count = expected_counts[story].get(histogram, 0) + if count != expected_count: + deltas[story][repeat][histogram] = count - expected_count + logging.warning( + 'Story %s, repeat %s failed to record expected histogram counts' % + (story, repeat)) + logging.warning('Expected counts: %s' % JsonDump(expected_counts[story])) + logging.warning('Actual counts: %s' % JsonDump(histogram_counts)) + + return counts_match, deltas + + +def _ProcessResultsInternal(): + if not os.path.exists(GetDataDir()) or not os.path.isdir(GetDataDir()): + raise RuntimeError( + 'Data directory %s does not exist or is not a directory' % + (GetDataDir())) + + if (not os.path.exists(GetRunPathFile()) + or not os.path.isfile(GetRunPathFile())): + raise RuntimeError('Run path file %s does not exist or is not a file' % + GetRunPathFile()) + + run_results_path = None + with open(GetRunPathFile(), 'r') as f: + run_results_path = f.read() + none_placeholder = GetNonePlaceholder() + if not run_results_path or run_results_path.find(none_placeholder) > -1: + raise RuntimeError('Directory path of perf results not found') + + MovePreviousHistogramsFiles() + + subprocess.check_call([ + GetProcessor(), "--output-format=histograms", + "--intermediate-dir=" + run_results_path + ]) + + if (not os.path.exists(GetRawHistogramsFile()) + or not os.path.isfile(GetRawHistogramsFile())): + raise RuntimeError('Histogram results %s not found or is not a file' % + GetRawHistogramsFile()) + + histogram_data = None + with open(GetRawHistogramsFile(), 'r') as f: + histogram_data = json.load(f) + + runs_all_match, size, results = _ProcessHistograms(histogram_data) + print("Benchmark's initial database size: %s" % size) + if runs_all_match: + print('SUCCESS: Actual histogram counts are equal to expected counts ' + + 'for all stories and repeats.') + else: + print('WARNING: Actual histogram counts differ from expected counts for ' + + 'at least one story/repeat. See file://%s for the deltas.' % + GetHistogramCountDeltasFile()) + print('View expected histogram counts at file://%s' % + GetExpectedHistogramsFile()) + for (result, filename) in zip(results, GetProcessedFiles()): + if filename == GetHistogramCountDeltasFile(): + json_result = json.loads(result) + if runs_all_match and len(json_result) == 0: + continue + if runs_all_match: + logging.warning(('Unexpectedly got histogram count deltas %s when ' % + result) + + 'all runs were reported to have counts match') + elif len(json_result) == 0: + logging.warning( + 'A discrepancy in run counts was reported, but the returned ' + + 'deltas object was empty') + with open(filename, 'w') as f: + f.write(result) + print('View processed results at file://%s' % filename) + + +def ProcessResults(): + try: + _ProcessResultsInternal() + return 0 + except Exception as e: # pylint: disable=broad-except + logging.warning('Encountered exception: %s\n%s' % + (repr(e), traceback.format_exc())) + return 1
diff --git a/tools/perf/contrib/shared_storage/utils/util.py b/tools/perf/contrib/shared_storage/utils/util.py index 39d1b279..14f5986 100644 --- a/tools/perf/contrib/shared_storage/utils/util.py +++ b/tools/perf/contrib/shared_storage/utils/util.py
@@ -4,6 +4,12 @@ import json +_NONE_PLACEHOLDER = '[[None]]' + + +def GetNonePlaceholder(): + return _NONE_PLACEHOLDER + def JsonDump(data): return json.dumps(data, indent=2, sort_keys=True)
diff --git a/tools/perf/process_perf_results.pydeps b/tools/perf/process_perf_results.pydeps index e731331..c4f67c1 100644 --- a/tools/perf/process_perf_results.pydeps +++ b/tools/perf/process_perf_results.pydeps
@@ -562,6 +562,7 @@ contrib/shared_storage/utils/__init__.py contrib/shared_storage/utils/file_util.py contrib/shared_storage/utils/histogram_list.py +contrib/shared_storage/utils/process_results.py contrib/shared_storage/utils/util.py contrib/system_health_scroll_jank/__init__.py contrib/system_health_scroll_jank/janky_story_set.py
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index ae9f328c..74d27c6 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -1466,8 +1466,7 @@ // Opaque regions for occlusion do not apply to opaque windows, so only // allow opaque regions for occlusion to be set for them if they are the // same as the window bounds size. - DCHECK(GetTransparent() || layer()->type() == ui::LAYER_NOT_DRAWN || - opaque_regions_for_occlusion.empty() || + DCHECK(GetTransparent() || opaque_regions_for_occlusion.empty() || (opaque_regions_for_occlusion.size() == 1 && opaque_regions_for_occlusion[0] == gfx::Rect(bounds().size()))); if (opaque_regions_for_occlusion == opaque_regions_for_occlusion_) @@ -1542,11 +1541,8 @@ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking; // Non-transparent windows should not have opaque regions for occlusion set. -#if DCHECK_IS_ON() - if (!GetTransparent() && layer()->type() != ui::LAYER_NOT_DRAWN) { + if (!GetTransparent()) DCHECK(opaque_regions_for_occlusion_.empty()); - } -#endif for (WindowObserver& observer : observers_) observer.OnWindowTransparentChanged(this, reason);
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc index 53f7c3e..cabb73c 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -897,6 +897,10 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) +PlatformWindowDelegate::State WaylandToplevelWindow::GetLatchedState() const { + return latched_state(); +} + void WaylandToplevelWindow::RoundTripQueue() { connection()->RoundTripQueue(); }
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h index 9528a66..4e22973 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -162,6 +162,7 @@ gfx::RoundedCornersF GetWindowCornersRadii() override; void SetShadowCornersRadii(const gfx::RoundedCornersF& radii) override; #endif // BUILDFLAG(IS_CHROMEOS_LACROS) + PlatformWindowDelegate::State GetLatchedState() const override; void RoundTripQueue() override; void ShowSnapPreview(WaylandWindowSnapDirection snap, bool allow_haptic_feedback) override;
diff --git a/ui/platform_window/extensions/wayland_extension.h b/ui/platform_window/extensions/wayland_extension.h index 7713b08..540fc23b 100644 --- a/ui/platform_window/extensions/wayland_extension.h +++ b/ui/platform_window/extensions/wayland_extension.h
@@ -8,6 +8,7 @@ #include "base/component_export.h" #include "build/chromeos_buildflags.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h" +#include "ui/platform_window/platform_window_delegate.h" namespace gfx { class RoundedCornersF; @@ -72,10 +73,17 @@ #endif // BUILDFLAG(IS_CHROMEOS_LACROS) - // Wait for a Wayland roundtrip to ensure all side effects have been + // Waits for a Wayland roundtrip to ensure all side effects have been // processed. virtual void RoundTripQueue() = 0; + // Returns the current configuration state of the window. This is initially + // set to values provided by the client, until we get an actual configure from + // the server. + // See the comment to the member of WaylandWindow `applied_state_` + // in `ui/ozone/platform/wayland/host/wayland_window.h` for more info. + virtual PlatformWindowDelegate::State GetLatchedState() const = 0; + // Signals the underneath platform to shows a preview for the given window // snap direction. `allow_haptic_feedback` indicates if it should send haptic // feedback.
diff --git a/v8 b/v8 index b53eb02..45524bc 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit b53eb026438b102249f055de1af5d8aff5bb0779 +Subproject commit 45524bc2f627d7733ed31196b8c1eb7d7db391e7