diff --git a/DEPS b/DEPS index 987bfbe..a7448c1 100644 --- a/DEPS +++ b/DEPS
@@ -228,7 +228,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'f61ec43f84dd73508a566c36ef085156b40285f0', + 'skia_revision': '0733d484289faa5ea51b97bd19e6afadc82ab042', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -240,11 +240,11 @@ # 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': 'e3f2acb978d84b9da06e66515d2183b82fa29865', + 'angle_revision': 'f2c968874230190cc1d7719f77b07abccd46a20a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '803ceb58c92cc4c817685efa896c8e7421a86cc2', + 'swiftshader_revision': 'f2bf63b016782359ca581dded874bb3eda79cbce', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -275,11 +275,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '63b3cb448cf22e589a4d125ee1829c894cb582c2', + 'nacl_revision': '0c1b812efbe7731df5b40858689f857d80c6372b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'f44c2d586064bcccdb504bf098b9dc78e660269e', + 'freetype_revision': 'e2cceed857f0b4f3f3fd48681d2f3009e62d1194', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -307,7 +307,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '7f672f7f8446ca82c02ad16bc5231c7ef512dd88', + 'devtools_frontend_revision': 'f423747da6817c98e025e0044dfe3dbb276dd004', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -347,7 +347,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': '71d7c2e6707e76fbdd96087c57d34657b0103b52', + 'dawn_revision': '41e3931b04b694dec2b5e0952e7837d9db227ea1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -610,7 +610,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '93ccaa53c1fce39f8223f2be5ebccebc7214aa4c', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'da985561a1c5611756d27f6d8f2998899ee24c5c', 'condition': 'checkout_ios', }, @@ -932,7 +932,7 @@ }, 'src/third_party/breakpad/breakpad': - Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'b95c4868b10f69e642666742233aede1eb653012', + Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '524a6249f0b4dc4e24d38a29a36e1c8ae611d28f', 'src/third_party/byte_buddy': { 'packages': [ @@ -983,7 +983,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '16cd88facdb0b74c17adb8498b7411315bcbc1c5', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '4a2e809002c96046f1583b3a5c6db9660eb473c4', 'condition': 'checkout_chromeos', }, @@ -1003,7 +1003,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9107458ff61fae58c97b0523714dd73211a02758', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '67574d7a19b6dd25af19ed83d4822695169e3a22', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1503,7 +1503,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'Nu_mvQJe34CotIXadFlA3w732CJ9EvQGuVs4udcZedAC', + 'version': 'version:2@3.1.16', }, ], 'condition': 'checkout_android', @@ -1621,7 +1621,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'a03fcf00c1a1c40c1dd9a0dd2c8071333b882a09', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '124889f6f9a2fcdcf54eebfea3ba2ccb7a352ea5', + Var('webrtc_git') + '/src.git' + '@' + 'b6f19d7dfd29209b0a45fff629c1c0ed02d3b6d7', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1682,7 +1682,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@aa168d0bfa1740dd9faf01381f340852655e3f18', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7807e2400514d2035c6c4d4f19c2d8bff5a9db7b', 'condition': 'checkout_src_internal', }, @@ -1701,7 +1701,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': '-mUXyaeW3TjdvF9VQ0soGGdiAla8v5-nZoFd9lcPoLsC', + 'version': 'vEd6WxCBEatoB1gAVQ1u73pT32gi5xR0RB-ikMBZ2LUC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index fe9d70e2..fcdbf54d 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -774,6 +774,7 @@ deps = [ "//base:base_java", "//cc/base:cc_base_java", + "//components/autofill/android:autofill_features_java", "//components/metrics:metrics_java", "//components/power_scheduler:power_scheduler_java", "//components/viz:viz_java",
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java index 51cd297..bed9ebc 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -418,12 +418,16 @@ actions.size()); RecordHistogram.recordCount100Histogram( "Android.WebView.SafeMode.ActionsCount", actions.size()); - controller.executeActions(actions); + boolean success = controller.executeActions(actions); long safeModeQueryExecuteEnd = SystemClock.elapsedRealtime(); RecordHistogram.recordTimesHistogram( "Android.WebView.SafeMode.QueryAndExecuteBlockingTime", safeModeQueryExecuteEnd - safeModeQueryExecuteStart); - logSafeModeExecutionResult(SafeModeExecutionResult.SUCCESS); + if (success) { + logSafeModeExecutionResult(SafeModeExecutionResult.SUCCESS); + } else { + logSafeModeExecutionResult(SafeModeExecutionResult.ACTION_FAILED); + } } catch (Throwable t) { // Don't let SafeMode crash WebView. Instead just log the error. Log.e(TAG, "WebViewSafeMode threw exception: ", t); @@ -460,11 +464,13 @@ // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. - @IntDef({SafeModeExecutionResult.SUCCESS, SafeModeExecutionResult.UNKNOWN_ERROR}) + @IntDef({SafeModeExecutionResult.SUCCESS, SafeModeExecutionResult.UNKNOWN_ERROR, + SafeModeExecutionResult.ACTION_FAILED}) private @interface SafeModeExecutionResult { int SUCCESS = 0; int UNKNOWN_ERROR = 1; - int COUNT = 2; + int ACTION_FAILED = 2; + int COUNT = 3; } private static void logSafeModeExecutionResult(@SafeModeExecutionResult int result) {
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index dc25dbb..98f01f8 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -7,6 +7,7 @@ import org.chromium.base.BaseSwitches; import org.chromium.blink_public.common.BlinkFeatures; import org.chromium.cc.base.CcSwitches; +import org.chromium.components.autofill.AutofillFeatures; import org.chromium.components.metrics.MetricsSwitches; import org.chromium.components.power_scheduler.PowerSchedulerFeatures; import org.chromium.components.viz.common.VizFeatures; @@ -141,6 +142,13 @@ Flag.baseFeature(BlinkFeatures.GMS_CORE_EMOJI, "Enables retrieval of the emoji font through GMS Core " + "improving emoji glyph coverage."), + Flag.baseFeature(AutofillFeatures.AUTOFILL_ENABLE_SUPPORT_FOR_MORE_STRUCTURE_IN_NAMES, + "Enables support for names with a rich structure including multiple last " + + "names."), + Flag.baseFeature( + AutofillFeatures.AUTOFILL_ENABLE_SUPPORT_FOR_MORE_STRUCTURE_IN_ADDRESSES, + "Enables support for address with a rich structure including separate street " + + "names and house numberse."), Flag.baseFeature( NetworkServiceFeatures.TRUST_TOKENS, "Enables the prototype Trust Tokens API."), Flag.baseFeature(AwFeatures.WEBVIEW_APPS_PACKAGE_NAMES_ALLOWLIST,
diff --git a/android_webview/java/src/org/chromium/android_webview/common/SafeModeAction.java b/android_webview/java/src/org/chromium/android_webview/common/SafeModeAction.java index adf048e..5e41eed8 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/SafeModeAction.java +++ b/android_webview/java/src/org/chromium/android_webview/common/SafeModeAction.java
@@ -18,8 +18,11 @@ public String getId(); /** - * Executes the given action. Implementations of this method should be Java-only (no JNI/C++) - * because the native library may not yet be loaded. + * Executes the given action. Implementations of this method should be Java-only (no JNI/C++) + * because the native library may not yet be loaded. The return status is used for logging + * purposes only. + * + * @return {@code true} if the action succeeded, {@code false} otherwise. */ - void execute(); + boolean execute(); }
diff --git a/android_webview/java/src/org/chromium/android_webview/common/SafeModeController.java b/android_webview/java/src/org/chromium/android_webview/common/SafeModeController.java index 3789920..b7f14981 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/SafeModeController.java +++ b/android_webview/java/src/org/chromium/android_webview/common/SafeModeController.java
@@ -118,24 +118,32 @@ * Executes the given set of {@link SafeModeAction}s. Execution order is determined by the order * of the array registered by {@link registerActions}. * + * @return {@code true} if <b>all</b> actions succeeded, {@code false} otherwise. * @throws IllegalStateException if this is called before {@link registerActions}. */ - public void executeActions(Set<String> actionsToExecute) { + public boolean executeActions(Set<String> actionsToExecute) { // Execute SafeModeActions in a deterministic order. if (mRegisteredActions == null) { throw new IllegalStateException( "Must registerActions() before calling executeActions()"); } + boolean overallStatus = true; for (SafeModeAction action : mRegisteredActions) { if (actionsToExecute.contains(action.getId())) { // Allow SafeModeActions in general to perform disk reads and writes. try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) { Log.i(TAG, "Starting to execute %s", action.getId()); - action.execute(); - Log.i(TAG, "Finished executing %s", action.getId()); + boolean status = action.execute(); + overallStatus &= status; + if (status) { + Log.i(TAG, "Finished executing %s (%s)", action.getId(), "success"); + } else { + Log.e(TAG, "Finished executing %s (%s)", action.getId(), "failure"); + } } } } + return overallStatus; } /**
diff --git a/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedSafeModeAction.java b/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedSafeModeAction.java index 5e58b47..3b1787a 100644 --- a/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedSafeModeAction.java +++ b/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedSafeModeAction.java
@@ -28,21 +28,27 @@ } @Override - public void execute() { - deleteIfExists(VariationsUtils.getSeedFile()); - deleteIfExists(VariationsUtils.getNewSeedFile()); - deleteIfExists(VariationsUtils.getStampFile()); + public boolean execute() { + boolean success = true; + // Try deleting each file even if a previous step failed, but indicate the overall success + // of all steps. + success &= deleteIfExists(VariationsUtils.getSeedFile()); + success &= deleteIfExists(VariationsUtils.getNewSeedFile()); + success &= deleteIfExists(VariationsUtils.getStampFile()); + return success; } - private static void deleteIfExists(File file) { + private static boolean deleteIfExists(File file) { if (!file.exists()) { Log.i(TAG, "File does not exist (skipping): %s", file); - return; + return true; } if (file.delete()) { Log.i(TAG, "Successfully deleted %s", file); + return true; } else { Log.e(TAG, "Failed to delete %s", file); + return false; } } }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeModeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeModeTest.java index 138039d..c5681f0 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeModeTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeModeTest.java
@@ -287,9 +287,15 @@ private int mCallCount; private int mExecutionOrder; private final String mId; + private final boolean mSuccess; TestSafeModeAction(String id) { + this(id, true); + } + + TestSafeModeAction(String id, boolean success) { mId = id; + mSuccess = success; } @Override @@ -299,9 +305,10 @@ } @Override - public void execute() { + public boolean execute() { mCallCount++; mExecutionOrder = mTestSafeModeActionExecutionCounter.incrementAndGet(); + return mSuccess; } public int getCallCount() { @@ -449,6 +456,42 @@ } @Test + @SmallTest + @Feature({"AndroidWebView"}) + public void testSafeModeAction_overallSuccessStatus() throws Throwable { + TestSafeModeAction successAction1 = new TestSafeModeAction("successAction1"); + TestSafeModeAction successAction2 = new TestSafeModeAction("successAction2"); + Set<String> allSuccessful = asSet(successAction1.getId(), successAction2.getId()); + SafeModeController.getInstance().registerActions( + new SafeModeAction[] {successAction1, successAction2}); + boolean success = SafeModeController.getInstance().executeActions(allSuccessful); + Assert.assertTrue( + "Overall status should be successful if all actions are successful", success); + Assert.assertEquals("successAction1 should have been executed exactly 1 time", 1, + successAction1.getCallCount()); + Assert.assertEquals("successAction2 should have been executed exactly 1 time", 1, + successAction2.getCallCount()); + + // Register a new set of actions where at least one indicates failure. + SafeModeController.getInstance().unregisterActionsForTesting(); + TestSafeModeAction failAction = new TestSafeModeAction("failAction", false); + Set<String> oneFailure = + asSet(successAction1.getId(), failAction.getId(), successAction2.getId()); + SafeModeController.getInstance().registerActions( + new SafeModeAction[] {successAction1, failAction, successAction2}); + success = SafeModeController.getInstance().executeActions(oneFailure); + Assert.assertFalse( + "Overall status should be failure if at least one action fails", success); + // One step failing should not block subsequent steps from executing. + Assert.assertEquals( + "successAction1 should have been executed again", 2, successAction1.getCallCount()); + Assert.assertEquals("failAction should have been executed exactly 1 time", 1, + failAction.getCallCount()); + Assert.assertEquals( + "successAction2 should have been executed again", 2, successAction2.getCallCount()); + } + + @Test @MediumTest public void testSafeModeAction_canRegisterBrowserActions() throws Exception { // Validity check: verify we can register the production SafeModeAction list. As long as @@ -468,7 +511,8 @@ VariationsTestUtils.writeMockSeed(oldFile); VariationsTestUtils.writeMockSeed(newFile); VariationsSeedSafeModeAction action = new VariationsSeedSafeModeAction(); - action.execute(); + boolean success = action.execute(); + Assert.assertTrue("VariationsSeedSafeModeAction should indicate success", success); Assert.assertFalse( "Old seed should have been deleted but it still exists", oldFile.exists()); Assert.assertFalse( @@ -489,7 +533,8 @@ VariationsTestUtils.writeMockSeed(oldFile); VariationsTestUtils.writeMockSeed(newFile); VariationsSeedSafeModeAction action = new VariationsSeedSafeModeAction(); - action.execute(); + boolean success = action.execute(); + Assert.assertTrue("VariationsSeedSafeModeAction should indicate success", success); TestLoader loader = new TestLoader(new TestLoaderResult()); loader.startVariationsInit(); @@ -509,7 +554,8 @@ File oldFile = VariationsUtils.getSeedFile(); File newFile = VariationsUtils.getNewSeedFile(); VariationsSeedSafeModeAction action = new VariationsSeedSafeModeAction(); - action.execute(); + boolean success = action.execute(); + Assert.assertTrue("VariationsSeedSafeModeAction should indicate success", success); Assert.assertFalse("Old seed should never have existed", oldFile.exists()); Assert.assertFalse("New seed should never have existed", newFile.exists()); } finally {
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/ComponentUpdaterResetSafeModeAction.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/ComponentUpdaterResetSafeModeAction.java index 9348979..d21f88a6 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/ComponentUpdaterResetSafeModeAction.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/ComponentUpdaterResetSafeModeAction.java
@@ -24,8 +24,9 @@ } @Override - public void execute() { + public boolean execute() { // Each Component Updater Service will take requisite steps on startup. // Do nothing here. + return true; } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index dfcfa8e..0e76b55 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2554,6 +2554,7 @@ "//components/arc:notification_test_support", "//components/full_restore", "//components/media_message_center", + "//components/onc", "//components/password_manager/core/browser:hash_password_manager", "//components/prefs:test_support", "//components/quirks",
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc index 4ecf67ef..b6f555e6 100644 --- a/ash/accelerators/accelerator_controller_impl.cc +++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -2341,8 +2341,6 @@ break; } - NotifyActionPerformed(action); - // Reset any in progress composition. if (::features::IsImprovedKeyboardShortcutsEnabled()) { auto* input_method =
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 6cebdd8..b7a7a4a 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -252,13 +252,6 @@ (override)); }; -class MockAcceleratorObserver - : public testing::NiceMock<AcceleratorController::Observer> { - public: - // AcceleratorController::Observer: - MOCK_METHOD(void, OnActionPerformed, (AcceleratorAction action), (override)); -}; - } // namespace // Note AcceleratorControllerTest can't be in the anonymous namespace because @@ -2112,10 +2105,6 @@ } TEST_F(AcceleratorControllerTest, CalculatorKey) { - auto observer = std::make_unique<MockAcceleratorObserver>(); - auto* accelerator_controller = ash::AcceleratorController::Get(); - accelerator_controller->AddObserver(observer.get()); - // Verify that the launch calculator key (VKEY_MEDIA_LAUNCH_APP2) is // registered. ui::Accelerator accelerator(ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_NONE); @@ -2124,9 +2113,6 @@ // Verify that the delegate to open the app is called. EXPECT_CALL(*new_window_delegate_, OpenCalculator) .WillOnce(testing::Return()); - EXPECT_CALL(*observer, OnActionPerformed) - .WillOnce( - [](AcceleratorAction action) { EXPECT_EQ(OPEN_CALCULATOR, action); }); EXPECT_TRUE(ProcessInController(accelerator)); }
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 187ecbd..1cb86916 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -726,7 +726,7 @@ // minor mode(e.g. under the age of 18) to provide unnecessary consents to share // personal data. const base::Feature kMinorModeRestriction{"MinorModeRestriction", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Enables the use of Mojo by Chrome-process code to communicate with Power // Manager. In order to use mojo, this feature must be turned on and a callsite
diff --git a/ash/keyboard/keyboard_controller_impl.cc b/ash/keyboard/keyboard_controller_impl.cc index b67461e..f25dc84 100644 --- a/ash/keyboard/keyboard_controller_impl.cc +++ b/ash/keyboard/keyboard_controller_impl.cc
@@ -73,8 +73,7 @@ if (!features) return false; - bool feature_value = false; - return features->GetBoolean(feature_path, &feature_value) && feature_value; + return features->FindBoolPath(feature_path).value_or(false); } } // namespace
diff --git a/ash/login/ui/lock_screen_media_controls_view.cc b/ash/login/ui/lock_screen_media_controls_view.cc index 5049e865..c73870d 100644 --- a/ash/login/ui/lock_screen_media_controls_view.cc +++ b/ash/login/ui/lock_screen_media_controls_view.cc
@@ -134,6 +134,7 @@ case MediaSessionAction::kToggleCamera: case MediaSessionAction::kHangUp: case MediaSessionAction::kRaise: + case MediaSessionAction::kSetMute: NOTREACHED(); break; }
diff --git a/ash/public/cpp/accelerators.cc b/ash/public/cpp/accelerators.cc index 8c247ec..2d27b38 100644 --- a/ash/public/cpp/accelerators.cc +++ b/ash/public/cpp/accelerators.cc
@@ -325,14 +325,6 @@ GetVolumeAdjustmentCallback()->Run(); } -void AcceleratorController::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void AcceleratorController::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - AcceleratorController::AcceleratorController() { DCHECK_EQ(nullptr, g_instance); g_instance = this; @@ -343,9 +335,4 @@ g_instance = nullptr; } -void AcceleratorController::NotifyActionPerformed(AcceleratorAction action) { - for (Observer& observer : observers_) - observer.OnActionPerformed(action); -} - } // namespace ash
diff --git a/ash/public/cpp/accelerators.h b/ash/public/cpp/accelerators.h index b97d8bda..bd57004 100644 --- a/ash/public/cpp/accelerators.h +++ b/ash/public/cpp/accelerators.h
@@ -9,7 +9,6 @@ #include "ash/public/cpp/ash_public_export.h" #include "base/callback_forward.h" -#include "base/observer_list.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -186,12 +185,6 @@ // implement. class ASH_PUBLIC_EXPORT AcceleratorController { public: - class Observer : public base::CheckedObserver { - public: - // Invoked when `action` is performed. - virtual void OnActionPerformed(AcceleratorAction action) = 0; - }; - // Returns the singleton instance. static AcceleratorController* Get(); @@ -235,15 +228,9 @@ virtual bool DoesAcceleratorMatchAction(const ui::Accelerator& accelerator, const AcceleratorAction action) = 0; - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - protected: AcceleratorController(); virtual ~AcceleratorController(); - void NotifyActionPerformed(AcceleratorAction action); - - base::ObserverList<Observer> observers_; }; // The public facing interface for AcceleratorHistory, which is implemented in
diff --git a/ash/quick_pair/common/log_buffer.cc b/ash/quick_pair/common/log_buffer.cc index fbe7dd4..63c923c 100644 --- a/ash/quick_pair/common/log_buffer.cc +++ b/ash/quick_pair/common/log_buffer.cc
@@ -4,7 +4,7 @@ #include "ash/quick_pair/common/log_buffer.h" -#include "base/lazy_instance.h" +#include "base/no_destructor.h" namespace ash { namespace quick_pair { @@ -14,9 +14,6 @@ // The maximum number of logs that can be stored in the buffer. const size_t kMaxBufferSize = 1000; -// The global instance returned by LogBuffer::GetInstance(). -base::LazyInstance<LogBuffer>::Leaky g_log_buffer = LAZY_INSTANCE_INITIALIZER; - } // namespace LogBuffer::LogMessage::LogMessage(const std::string& text, @@ -28,7 +25,8 @@ // static LogBuffer* LogBuffer::GetInstance() { - return &g_log_buffer.Get(); + static base::NoDestructor<LogBuffer> log_buffer; + return log_buffer.get(); } LogBuffer::LogBuffer() {}
diff --git a/ash/system/media/unified_media_controls_view.cc b/ash/system/media/unified_media_controls_view.cc index 87f2201..80faac0 100644 --- a/ash/system/media/unified_media_controls_view.cc +++ b/ash/system/media/unified_media_controls_view.cc
@@ -90,6 +90,7 @@ case MediaSessionAction::kToggleCamera: case MediaSessionAction::kHangUp: case MediaSessionAction::kRaise: + case MediaSessionAction::kSetMute: NOTREACHED(); break; }
diff --git a/ash/system/message_center/unified_message_list_view.cc b/ash/system/message_center/unified_message_list_view.cc index e8e8cc8b..9ed381b 100644 --- a/ash/system/message_center/unified_message_list_view.cc +++ b/ash/system/message_center/unified_message_list_view.cc
@@ -415,6 +415,13 @@ ->set_notification_id(new_grouped_notification_id); } +void UnifiedMessageListView::ConvertGroupedNotificationViewToNotificationView( + const std::string& grouped_notification_id, + const std::string& new_single_notification_id) { + GetMessageViewForNotificationId(grouped_notification_id) + ->set_notification_id(new_single_notification_id); +} + void UnifiedMessageListView::OnNotificationAdded(const std::string& id) { if (ash::features::IsNotificationsRefreshEnabled()) message_center::NotificationViewController::OnNotificationAdded(id);
diff --git a/ash/system/message_center/unified_message_list_view.h b/ash/system/message_center/unified_message_list_view.h index adb33a5..c65c4c2 100644 --- a/ash/system/message_center/unified_message_list_view.h +++ b/ash/system/message_center/unified_message_list_view.h
@@ -91,6 +91,9 @@ void ConvertNotificationViewToGroupedNotificationView( const std::string& ungrouped_notification_id, const std::string& new_grouped_notification_id) override; + void ConvertGroupedNotificationViewToNotificationView( + const std::string& grouped_notification_id, + const std::string& new_single_notification_id) override; void OnNotificationAdded(const std::string& id) override; void OnNotificationRemoved(const std::string& id, bool by_user) override; void OnNotificationUpdated(const std::string& id) override;
diff --git a/ash/webui/common/resources/navigation_view_panel.html b/ash/webui/common/resources/navigation_view_panel.html index fac17f7..a98fe4e 100644 --- a/ash/webui/common/resources/navigation_view_panel.html +++ b/ash/webui/common/resources/navigation_view_panel.html
@@ -5,26 +5,61 @@ position: fixed; } - #container { - align-items: flex-start; + :host([show-tool-bar]) #container { + display: grid; + grid-template-areas: "head head" "sideNav main"; + grid-template-columns: 1fr 4fr; + grid-template-rows: 1fr 9fr; + width: 100%; + } + + :host(:not([show-tool-bar])) #container { + display: grid; + grid-template-areas: "sideNav main"; + grid-template-columns: 1fr 4fr; + } + + :host([show-tool-bar]) #topNav { + grid-area: head; + position: sticky; + top: 0; + } + + #sideNav { + grid-area: sideNav; display: flex; - flex: 1; - position: relative; + flex-direction: column; + justify-content: flex-start; + } + + #navigationBody { + grid-area: main; } .left-aligned { - height: 100%; position: sticky; top: 75px; } + + page-toolbar { + font-size: 0.7rem; + } </style> <div id="container"> - <div id="navigationSelector" class="left-aligned"> - <navigation-selector menu-items={{menuItems_}} - selected-item={{selectedItem}}> - </navigation-selector> - <slot name="bottom-nav-content"></slot> + <template is="dom-if" if="[[showToolBar]]"> + <div id="topNav"> + <page-toolbar title="[[title]]"></page-toolbar> + </div> + </template> + + <div id="sideNav"> + <div id="navigationSelector" class="left-aligned"> + <navigation-selector menu-items={{menuItems_}} + selected-item={{selectedItem}}> + </navigation-selector> + <slot name="bottom-nav-content"></slot> + </div> </div> <div id="navigationBody" class="right-aligned"></div>
diff --git a/ash/webui/common/resources/navigation_view_panel.js b/ash/webui/common/resources/navigation_view_panel.js index 64dfa6a..0a370a9 100644 --- a/ash/webui/common/resources/navigation_view_panel.js +++ b/ash/webui/common/resources/navigation_view_panel.js
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './page_toolbar.js'; + import {assert} from 'chrome://resources/js/assert.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -43,7 +45,7 @@ */ selectedItem: { type: Object, - observer: "selectedItemChanged_", + observer: 'selectedItemChanged_', value: null, }, @@ -54,7 +56,28 @@ menuItems_: { type: Array, value: () => [], - } + }, + + /** + * This title only appears if |showToolBar| is True. Is otherwise a + * no-opt if title is set and |showToolbar| is False. + */ + title: { + type: String, + value: '', + }, + + /** + * Can only be set to True if specified from the parent element by adding + * show-tool-bar as an attribute to <navigation-view-panel>. If True, + * a toolbar will appear at the top of the navigation view panel with + * a 2 column view below it (sidebar + page). If False, navigation view + * panel will only be a 2 column view (sidebar + page). + */ + showToolBar: { + type: Boolean, + value: false, + }, } }
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_app.html b/ash/webui/diagnostics_ui/resources/diagnostics_app.html index e89e1ebc..5db2e438 100644 --- a/ash/webui/diagnostics_ui/resources/diagnostics_app.html +++ b/ash/webui/diagnostics_ui/resources/diagnostics_app.html
@@ -18,8 +18,8 @@ </style> <div id="diagnosticsAppContainer"> <div hidden$="[[!showNavPanel_]]"> - <page-toolbar title="[[i18n('diagnosticsTitle')]]"></page-toolbar> - <navigation-view-panel id="navigationPanel"> + <navigation-view-panel id="navigationPanel" + title="[[i18n('diagnosticsTitle')]]" show-tool-bar> <div slot="bottom-nav-content" class="session-log-container"> <cr-button on-click="onSessionLogClick_" class="session-log-button" hidden="[[!isLoggedIn_]]">
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html b/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html index 9da66b4..8207e0f 100644 --- a/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html +++ b/ash/webui/diagnostics_ui/resources/diagnostics_shared_css.html
@@ -54,7 +54,6 @@ align-items: center; display: flex; flex-direction: column; - padding-inline: var(--container-padding); width: var(--content-container-width); }
diff --git a/ash/webui/scanning/scanning_handler.cc b/ash/webui/scanning/scanning_handler.cc index 1fbb084..b159c24 100644 --- a/ash/webui/scanning/scanning_handler.cc +++ b/ash/webui/scanning/scanning_handler.cc
@@ -11,6 +11,9 @@ #include "base/check_op.h" #include "base/feature_list.h" #include "base/files/file_util.h" +#include "base/sequenced_task_runner.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "base/values.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "content/public/browser/web_contents.h" @@ -29,7 +32,10 @@ ScanningHandler::ScanningHandler( std::unique_ptr<ScanningAppDelegate> scanning_app_delegate) - : scanning_app_delegate_(std::move(scanning_app_delegate)) {} + : scanning_app_delegate_(std::move(scanning_app_delegate)), + task_runner_(base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {} ScanningHandler::~ScanningHandler() = default; @@ -230,13 +236,22 @@ const std::string callback = args->GetList()[0].GetString(); const base::FilePath file_path(args->GetList()[1].GetString()); + task_runner_->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&base::PathExists, file_path), + base::BindOnce(&ScanningHandler::OnPathExists, base::Unretained(this), + file_path, callback)); +} + +void ScanningHandler::OnPathExists(const base::FilePath& file_path, + const std::string& callback, + bool file_path_exists) { // When |file_path| is not valid, return a dictionary with an empty file path. - const bool filePathValid = - scanning_app_delegate_->IsFilePathSupported(file_path) && - base::PathExists(file_path); + const bool file_path_valid = + file_path_exists && + scanning_app_delegate_->IsFilePathSupported(file_path); ResolveJavascriptCallback( base::Value(callback), - CreateSelectedPathValue(filePathValid ? file_path : base::FilePath())); + CreateSelectedPathValue(file_path_valid ? file_path : base::FilePath())); } } // namespace ash
diff --git a/ash/webui/scanning/scanning_handler.h b/ash/webui/scanning/scanning_handler.h index 2248ff2..416b055 100644 --- a/ash/webui/scanning/scanning_handler.h +++ b/ash/webui/scanning/scanning_handler.h
@@ -17,6 +17,7 @@ namespace base { class ListValue; +class SequencedTaskRunner; } // namespace base namespace content { @@ -87,6 +88,11 @@ // display name. If the file path doesn't exist, return an empty file path. void HandleEnsureValidFilePath(const base::ListValue* args); + // Callback for HandleEnsureValidFilePath(). + void OnPathExists(const base::FilePath& file_path, + const std::string& callback, + bool file_path_exists); + std::string scan_location_callback_id_; scoped_refptr<ui::SelectFileDialog> select_file_dialog_; @@ -95,6 +101,9 @@ std::unique_ptr<ScanningAppDelegate> scanning_app_delegate_; std::map<std::string, int> string_id_map_; + + // Task runner for the I/O function base::FilePath(). + scoped_refptr<base::SequencedTaskRunner> task_runner_; }; } // namespace ash
diff --git a/ash/webui/scanning/scanning_handler_unittest.cc b/ash/webui/scanning/scanning_handler_unittest.cc index 73b88275..39ed3df 100644 --- a/ash/webui/scanning/scanning_handler_unittest.cc +++ b/ash/webui/scanning/scanning_handler_unittest.cc
@@ -356,6 +356,7 @@ args.Append(kHandlerFunctionName); args.Append(myScanPath.value()); web_ui_.HandleReceivedMessage("ensureValidFilePath", &args); + task_environment_.RunUntilIdle(); const content::TestWebUI::CallData& call_data = GetCallData(call_data_count_before_call); @@ -376,6 +377,7 @@ args.Append(kHandlerFunctionName); args.Append(invalidFilePath); web_ui_.HandleReceivedMessage("ensureValidFilePath", &args); + task_environment_.RunUntilIdle(); const content::TestWebUI::CallData& call_data = GetCallData(call_data_count_before_call);
diff --git a/ash/webui/shortcut_customization_ui/resources/shortcut_customization_app.html b/ash/webui/shortcut_customization_ui/resources/shortcut_customization_app.html index 8475727..ec1fb405 100644 --- a/ash/webui/shortcut_customization_ui/resources/shortcut_customization_app.html +++ b/ash/webui/shortcut_customization_ui/resources/shortcut_customization_app.html
@@ -2,14 +2,11 @@ :host { @apply --shortcut-customization-default-font; } - - page-toolbar { - font-size: 0.7rem; - } </style> <!-- TODO(jimmyxgong): Localize this title --> -<page-toolbar title="Shortcut Customization"></page-toolbar> -<navigation-view-panel id="navigationPanel"></navigation-view-panel> +<navigation-view-panel id="navigationPanel" title="Shortcut Customization" + show-tool-bar> +</navigation-view-panel> <template is="dom-if" if="[[showEditDialog_]]" restamp> <accelerator-edit-dialog id="editDialog"
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc index 43e8764e..37eada04 100644 --- a/ash/wm/toplevel_window_event_handler.cc +++ b/ash/wm/toplevel_window_event_handler.cc
@@ -322,7 +322,8 @@ if (window_resizer_ && !in_gesture_drag_) return; - if (window_resizer_ && window_resizer_->resizer()->GetTarget() != target) + if (window_resizer_ && window_resizer_->resizer()->GetTarget() != target && + !target->bounds().IsEmpty()) return; if (event->details().touch_points() > 2) {
diff --git a/base/allocator/partition_allocator/extended_api.cc b/base/allocator/partition_allocator/extended_api.cc index 67f2255..0321c3b2a 100644 --- a/base/allocator/partition_allocator/extended_api.cc +++ b/base/allocator/partition_allocator/extended_api.cc
@@ -6,14 +6,11 @@ #include "base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h" #include "base/allocator/buildflags.h" -#include "base/allocator/partition_allocator/partition_root.h" #include "base/allocator/partition_allocator/thread_cache.h" namespace base { namespace internal { - -#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) void DisableThreadCacheForRootIfEnabled(ThreadSafePartitionRoot* root) { // Some platforms don't have a thread cache, or it could already have been // disabled. @@ -26,10 +23,40 @@ // will be collected (and free cached memory) at thread destruction // time. For the main thread, we leak it. } -#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + +void EnablePartitionAllocThreadCacheForRootIfDisabled( + ThreadSafePartitionRoot* root) { + if (!root) + return; + root->with_thread_cache = true; +} } // namespace internal +void SwapOutProcessThreadCacheForTesting(ThreadSafePartitionRoot* root) { +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ + defined(PA_THREAD_CACHE_SUPPORTED) + DisablePartitionAllocThreadCacheForProcess(); + internal::ThreadCache::SwapForTesting(root); + internal::EnablePartitionAllocThreadCacheForRootIfDisabled(root); +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && + // defined(PA_THREAD_CACHE_SUPPORTED) +} + +void SwapInProcessThreadCacheForTesting(ThreadSafePartitionRoot* root) { +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ + defined(PA_THREAD_CACHE_SUPPORTED) + // First, disable the test thread cache we have. + internal::DisableThreadCacheForRootIfEnabled(root); + + auto* regular_allocator = base::internal::PartitionAllocMalloc::Allocator(); + internal::EnablePartitionAllocThreadCacheForRootIfDisabled(regular_allocator); + + internal::ThreadCache::SwapForTesting(regular_allocator); +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && + // defined(PA_THREAD_CACHE_SUPPORTED) +} + void DisablePartitionAllocThreadCacheForProcess() { #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) auto* regular_allocator = base::internal::PartitionAllocMalloc::Allocator();
diff --git a/base/allocator/partition_allocator/extended_api.h b/base/allocator/partition_allocator/extended_api.h index b8aeb78..5513e4c 100644 --- a/base/allocator/partition_allocator/extended_api.h +++ b/base/allocator/partition_allocator/extended_api.h
@@ -5,9 +5,23 @@ #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_EXTENDED_API_H_ #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_EXTENDED_API_H_ +#include "base/allocator/partition_allocator/partition_root.h" +#include "base/allocator/partition_allocator/thread_cache.h" #include "base/base_export.h" namespace base { +// These two functions are unsafe to run if there are multiple threads running +// in the process. +// +// Disables the thread cache for the entire process, and replaces it with a +// thread cache for |root|. +BASE_EXPORT void SwapOutProcessThreadCacheForTesting( + ThreadSafePartitionRoot* root); +// Disables the current thread cache, and replaces it with the default for the +// process. +BASE_EXPORT void SwapInProcessThreadCacheForTesting( + ThreadSafePartitionRoot* root); + // Disables the thread cache for the entire process. // // Saves memory but slows down the allocator *significantly*. Only use for
diff --git a/base/allocator/partition_allocator/thread_cache.cc b/base/allocator/partition_allocator/thread_cache.cc index ff28466..4ed0f399 100644 --- a/base/allocator/partition_allocator/thread_cache.cc +++ b/base/allocator/partition_allocator/thread_cache.cc
@@ -303,6 +303,21 @@ } // static +void ThreadCache::DeleteForTesting(ThreadCache* tcache) { + ThreadCache::Delete(tcache); +} + +// static +void ThreadCache::SwapForTesting(PartitionRoot<ThreadSafe>* root) { + auto* old_tcache = ThreadCache::Get(); + g_thread_cache_root.store(nullptr, std::memory_order_relaxed); + if (old_tcache) + ThreadCache::DeleteForTesting(old_tcache); + Init(root); + Create(root); +} + +// static void ThreadCache::Init(PartitionRoot<ThreadSafe>* root) { #if defined(OS_NACL) IMMEDIATE_CRASH();
diff --git a/base/allocator/partition_allocator/thread_cache.h b/base/allocator/partition_allocator/thread_cache.h index 29d073dc..7f0670da 100644 --- a/base/allocator/partition_allocator/thread_cache.h +++ b/base/allocator/partition_allocator/thread_cache.h
@@ -178,6 +178,11 @@ static void Init(PartitionRoot<ThreadSafe>* root); static void Init(PartitionRoot<NotThreadSafe>* root) { IMMEDIATE_CRASH(); } + static void DeleteForTesting(ThreadCache* tcache); + + // Deletes existing thread cache and creates a new one for |root|. + static void SwapForTesting(PartitionRoot<ThreadSafe>* root); + // Can be called several times, must be called before any ThreadCache // interactions. static void EnsureThreadSpecificDataInitialized();
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc index 8707eb25..ea89ff7 100644 --- a/base/allocator/partition_allocator/thread_cache_unittest.cc +++ b/base/allocator/partition_allocator/thread_cache_unittest.cc
@@ -9,6 +9,7 @@ #include <vector> #include "base/allocator/buildflags.h" +#include "base/allocator/partition_allocator/extended_api.h" #include "base/allocator/partition_allocator/partition_address_space.h" #include "base/allocator/partition_allocator/partition_alloc.h" #include "base/bind.h" @@ -20,15 +21,11 @@ #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" -// Only a single partition can have a thread cache at a time. When -// PartitionAlloc is malloc(), it is already in use. -// // With *SAN, PartitionAlloc is replaced in partition_alloc.h by ASAN, so we // cannot test the thread cache. // // Finally, the thread cache is not supported on all platforms. -#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && \ +#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && \ defined(PA_THREAD_CACHE_SUPPORTED) namespace base { @@ -77,7 +74,11 @@ // Forbid extras, since they make finding out which bucket is used harder. NoDestructor<ThreadSafePartitionRoot> g_root{ PartitionOptions{PartitionOptions::AlignedAlloc::kAllowed, +#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) PartitionOptions::ThreadCache::kEnabled, +#else + PartitionOptions::ThreadCache::kDisabled, +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) PartitionOptions::Quarantine::kAllowed, PartitionOptions::Cookies::kDisallowed, PartitionOptions::RefCount::kDisallowed}}; @@ -120,10 +121,11 @@ // Another test can uninitialize the pools, so make sure they are // initialized. PartitionAddressSpace::Init(); -#endif +#endif // defined(PA_HAS_64_BITS_POINTERS) ThreadCacheRegistry::Instance().SetThreadCacheMultiplier( ThreadCache::kDefaultMultiplier); ThreadCache::SetLargestCachedSize(ThreadCache::kLargeSizeThreshold); + // Make sure that enough slot spans have been touched, otherwise cache fill // becomes unpredictable (because it doesn't take slow paths in the // allocator), which is an issue for tests. @@ -143,6 +145,24 @@ ASSERT_EQ(0u, task_env_.GetPendingMainThreadTaskCount()); } + // Used to disable the thread cache for the lifetime of a scope (in this case + // the lifetime of the PartitionAllocThreadCacheTest). + class ScopedThreadCacheDisabler { + public: + ScopedThreadCacheDisabler() { + SwapOutProcessThreadCacheForTesting(g_root.get()); + } + ~ScopedThreadCacheDisabler() { + ThreadCache::SetLargestCachedSize(ThreadCache::kDefaultSizeThreshold); + SwapInProcessThreadCacheForTesting(g_root.get()); + } + }; + + // We do this here instead of in SetUp()/TearDown() because we need this to + // run before the task environment (which creates threads and hence is racy + // with attempting to disable the thread cache). + ScopedThreadCacheDisabler scoped_thread_cache_disabler_{}; + base::test::TaskEnvironment task_env_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; }; @@ -324,10 +344,24 @@ g_root->Free(ptr); } -TEST_F(PartitionAllocThreadCacheTest, ThreadCacheRegistry) { +// On Android with PartitionAlloc as malloc, we have extra thread caches being +// created, causing this test to fail. +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && defined(OS_ANDROID) +#define MAYBE_ThreadCacheRegistry DISABLED_ThreadCacheRegistry +#else +#define MAYBE_ThreadCacheRegistry ThreadCacheRegistry +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && defined(OS_ANDROID) + +TEST_F(PartitionAllocThreadCacheTest, MAYBE_ThreadCacheRegistry) { auto* parent_thread_tcache = g_root->thread_cache_for_testing(); ASSERT_TRUE(parent_thread_tcache); + { + PartitionAutoLock lock(ThreadCacheRegistry::GetLock()); + EXPECT_EQ(parent_thread_tcache->prev_, nullptr); + EXPECT_EQ(parent_thread_tcache->next_, nullptr); + } + LambdaThreadDelegate delegate{BindLambdaForTesting([&]() { EXPECT_FALSE(g_root->thread_cache_for_testing()); // No allocations yet. FillThreadCacheAndReturnIndex(kSmallSize); @@ -855,6 +889,5 @@ } // namespace internal } // namespace base -#endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && - // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && +#endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) && // defined(PA_THREAD_CACHE_SUPPORTED)
diff --git a/base/i18n/break_iterator.cc b/base/i18n/break_iterator.cc index 0471763..32786974 100644 --- a/base/i18n/break_iterator.cc +++ b/base/i18n/break_iterator.cc
@@ -5,6 +5,7 @@ #include "base/i18n/break_iterator.h" #include <stdint.h> +#include <ostream> #include "base/check.h" #include "base/lazy_instance.h"
diff --git a/base/mac/mach_port_rendezvous_unittest.cc b/base/mac/mach_port_rendezvous_unittest.cc index 94a353b..7676342 100644 --- a/base/mac/mach_port_rendezvous_unittest.cc +++ b/base/mac/mach_port_rendezvous_unittest.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/at_exit.h" +#include "base/cxx17_backports.h" #include "base/mac/foundation_util.h" #include "base/mac/mach_logging.h" #include "base/strings/stringprintf.h"
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc index 2c0216e..51c5ae3 100644 --- a/base/process/memory_unittest.cc +++ b/base/process/memory_unittest.cc
@@ -179,8 +179,9 @@ #if defined(OS_ANDROID) && defined(ARCH_CPU_X86) return base::android::BuildInfo::GetInstance()->sdk_int() < base::android::SDK_VERSION_NOUGAT; -#endif +#else return false; +#endif } };
diff --git a/base/synchronization/lock_impl.h b/base/synchronization/lock_impl.h index cfe53db2..0d05dce 100644 --- a/base/synchronization/lock_impl.h +++ b/base/synchronization/lock_impl.h
@@ -106,9 +106,12 @@ #elif defined(OS_POSIX) || defined(OS_FUCHSIA) +BASE_EXPORT std::string SystemErrorCodeToString(int error_code); + bool LockImpl::Try() { int rv = pthread_mutex_trylock(&native_handle_); - DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv); + DCHECK(rv == 0 || rv == EBUSY) + << ". " << base::internal::SystemErrorCodeToString(rv); return rv == 0; }
diff --git a/base/synchronization/lock_impl_posix.cc b/base/synchronization/lock_impl_posix.cc index 217808d..069bd5294 100644 --- a/base/synchronization/lock_impl_posix.cc +++ b/base/synchronization/lock_impl_posix.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/base_export.h" #include "base/check_op.h" #include "base/debug/activity_tracker.h" #include "base/posix/safe_strerror.h" @@ -29,7 +30,9 @@ } #endif // DCHECK_IS_ON() -std::string SystemErrorCodeToString(int error_code) { +} // namespace + +BASE_EXPORT std::string SystemErrorCodeToString(int error_code) { #if DCHECK_IS_ON() return base::safe_strerror(error_code) + ". " + AdditionalHintForSystemErrorCode(error_code); @@ -38,8 +41,6 @@ #endif // DCHECK_IS_ON() } -} // namespace - // Determines which platforms can consider using priority inheritance locks. Use // this define for platform code that may not compile if priority inheritance // locks aren't available. For this platform code,
diff --git a/base/system/sys_info.cc b/base/system/sys_info.cc index b0e5f815..84a2e7a 100644 --- a/base/system/sys_info.cc +++ b/base/system/sys_info.cc
@@ -16,6 +16,7 @@ #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -97,8 +98,8 @@ std::move(callback)); #else NOTIMPLEMENTED(); - base::ThreadPool::PostTask( - FROM_HERE, {}, base::BindOnce(std::move(callback), HardwareInfo())); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), HardwareInfo())); #endif }
diff --git a/base/threading/sequence_local_storage_map.cc b/base/threading/sequence_local_storage_map.cc index 26ce4b17..c152566 100644 --- a/base/threading/sequence_local_storage_map.cc +++ b/base/threading/sequence_local_storage_map.cc
@@ -4,6 +4,7 @@ #include "base/threading/sequence_local_storage_map.h" +#include <ostream> #include <utility> #include "base/check_op.h"
diff --git a/base/threading/thread_restrictions.cc b/base/threading/thread_restrictions.cc index b4cf3c9..1259fa12 100644 --- a/base/threading/thread_restrictions.cc +++ b/base/threading/thread_restrictions.cc
@@ -4,6 +4,7 @@ #include "base/threading/thread_restrictions.h" +#include "base/threading/hang_watcher.h" #include "base/trace_event/base_tracing.h" #if DCHECK_IS_ON()
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 67f44e5..dedab0bc 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -14,7 +14,9 @@ #include "base/gtest_prod_util.h" #include "base/location.h" #include "base/macros.h" -#include "base/threading/hang_watcher.h" +#include "base/strings/string_number_conversions.h" +#include "base/threading/platform_thread.h" +#include "base/time/time.h" #include "build/build_config.h" // -----------------------------------------------------------------------------
diff --git a/base/win/win_util.cc b/base/win/win_util.cc index 4e4ec94..42d3fa3 100644 --- a/base/win/win_util.cc +++ b/base/win/win_util.cc
@@ -37,6 +37,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/scoped_native_library.h" #include "base/strings/string_util.h" #include "base/strings/string_util_win.h"
diff --git a/build/android/adb_logcat_monitor.py b/build/android/adb_logcat_monitor.py index 5cdbfc7..6230db4d 100755 --- a/build/android/adb_logcat_monitor.py +++ b/build/android/adb_logcat_monitor.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/adb_logcat_printer.py b/build/android/adb_logcat_printer.py index 63a84af..f80845a 100755 --- a/build/android/adb_logcat_printer.py +++ b/build/android/adb_logcat_printer.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/apk_operations.pydeps b/build/android/apk_operations.pydeps index 60b1289..0bd7b7f9 100644 --- a/build/android/apk_operations.pydeps +++ b/build/android/apk_operations.pydeps
@@ -65,6 +65,9 @@ ../../third_party/catapult/third_party/six/six.py ../../third_party/jinja2/__init__.py ../../third_party/jinja2/_compat.py +../../third_party/jinja2/_identifier.py +../../third_party/jinja2/asyncfilters.py +../../third_party/jinja2/asyncsupport.py ../../third_party/jinja2/bccache.py ../../third_party/jinja2/compiler.py ../../third_party/jinja2/defaults.py
diff --git a/build/android/asan_symbolize.py b/build/android/asan_symbolize.py index a10ac49..60b00d00 100755 --- a/build/android/asan_symbolize.py +++ b/build/android/asan_symbolize.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2013 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/diff_resource_sizes.py b/build/android/diff_resource_sizes.py index e0a23a1..0bd2c47 100755 --- a/build/android/diff_resource_sizes.py +++ b/build/android/diff_resource_sizes.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/build/android/download_doclava.py b/build/android/download_doclava.py index 1982fdb8..059d1cb 100755 --- a/build/android/download_doclava.py +++ b/build/android/download_doclava.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2016 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.
diff --git a/build/android/gradle/gn_to_cmake.py b/build/android/gradle/gn_to_cmake.py index d3e80ae..7289825 100755 --- a/build/android/gradle/gn_to_cmake.py +++ b/build/android/gradle/gn_to_cmake.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2016 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.
diff --git a/build/android/gyp/compile_resources.pydeps b/build/android/gyp/compile_resources.pydeps index 174b5269..9076014 100644 --- a/build/android/gyp/compile_resources.pydeps +++ b/build/android/gyp/compile_resources.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/compile_resources.pydeps build/android/gyp/compile_resources.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py @@ -23,29 +24,6 @@ ../../../third_party/markupsafe/__init__.py ../../../third_party/markupsafe/_compat.py ../../../third_party/markupsafe/_native.py -../../../third_party/protobuf/python/google/__init__.py -../../../third_party/protobuf/python/google/protobuf/__init__.py -../../../third_party/protobuf/python/google/protobuf/descriptor.py -../../../third_party/protobuf/python/google/protobuf/descriptor_database.py -../../../third_party/protobuf/python/google/protobuf/descriptor_pool.py -../../../third_party/protobuf/python/google/protobuf/internal/__init__.py -../../../third_party/protobuf/python/google/protobuf/internal/api_implementation.py -../../../third_party/protobuf/python/google/protobuf/internal/containers.py -../../../third_party/protobuf/python/google/protobuf/internal/decoder.py -../../../third_party/protobuf/python/google/protobuf/internal/encoder.py -../../../third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py -../../../third_party/protobuf/python/google/protobuf/internal/extension_dict.py -../../../third_party/protobuf/python/google/protobuf/internal/message_listener.py -../../../third_party/protobuf/python/google/protobuf/internal/python_message.py -../../../third_party/protobuf/python/google/protobuf/internal/type_checkers.py -../../../third_party/protobuf/python/google/protobuf/internal/well_known_types.py -../../../third_party/protobuf/python/google/protobuf/internal/wire_format.py -../../../third_party/protobuf/python/google/protobuf/message.py -../../../third_party/protobuf/python/google/protobuf/message_factory.py -../../../third_party/protobuf/python/google/protobuf/reflection.py -../../../third_party/protobuf/python/google/protobuf/symbol_database.py -../../../third_party/protobuf/python/google/protobuf/text_encoding.py -../../../third_party/protobuf/python/google/protobuf/text_format.py ../../../third_party/six/src/six.py ../../gn_helpers.py compile_resources.py
diff --git a/build/android/gyp/create_apk_operations_script.py b/build/android/gyp/create_apk_operations_script.py index 660567f0..82a6e5be 100755 --- a/build/android/gyp/create_apk_operations_script.py +++ b/build/android/gyp/create_apk_operations_script.py
@@ -12,7 +12,7 @@ from util import build_utils SCRIPT_TEMPLATE = string.Template("""\ -#!/usr/bin/env python +#!/usr/bin/env python3 # # This file was generated by build/android/gyp/create_apk_operations_script.py
diff --git a/build/android/gyp/create_app_bundle.pydeps b/build/android/gyp/create_app_bundle.pydeps index cbb471a..503dfb0 100644 --- a/build/android/gyp/create_app_bundle.pydeps +++ b/build/android/gyp/create_app_bundle.pydeps
@@ -14,6 +14,7 @@ ../../../third_party/catapult/devil/devil/utils/cmd_helper.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/create_app_bundle_apks.pydeps b/build/android/gyp/create_app_bundle_apks.pydeps index 20d8ffe8..5e04dae 100644 --- a/build/android/gyp/create_app_bundle_apks.pydeps +++ b/build/android/gyp/create_app_bundle_apks.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_app_bundle_apks.pydeps build/android/gyp/create_app_bundle_apks.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/create_bundle_wrapper_script.py b/build/android/gyp/create_bundle_wrapper_script.py index 282e206..1bdb767 100755 --- a/build/android/gyp/create_bundle_wrapper_script.py +++ b/build/android/gyp/create_bundle_wrapper_script.py
@@ -13,7 +13,7 @@ from util import build_utils SCRIPT_TEMPLATE = string.Template("""\ -#!/usr/bin/env python +#!/usr/bin/env python3 # # This file was generated by build/android/gyp/create_bundle_wrapper_script.py
diff --git a/build/android/gyp/create_java_binary_script.py b/build/android/gyp/create_java_binary_script.py index 5bc9d08ab1..91fe600 100755 --- a/build/android/gyp/create_java_binary_script.py +++ b/build/android/gyp/create_java_binary_script.py
@@ -21,7 +21,7 @@ # to the directory that the script is written in and then, when run, must # recalculate the paths relative to the current directory. script_template = """\ -#!/usr/bin/env python +#!/usr/bin/env python3 # # This file was generated by build/android/gyp/create_java_binary_script.py
diff --git a/build/android/gyp/create_r_java.pydeps b/build/android/gyp/create_r_java.pydeps index 45121e3..b259751 100644 --- a/build/android/gyp/create_r_java.pydeps +++ b/build/android/gyp/create_r_java.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_r_java.pydeps build/android/gyp/create_r_java.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/create_r_txt.pydeps b/build/android/gyp/create_r_txt.pydeps index c7698eef..54e5670 100644 --- a/build/android/gyp/create_r_txt.pydeps +++ b/build/android/gyp/create_r_txt.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_r_txt.pydeps build/android/gyp/create_r_txt.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/create_ui_locale_resources.pydeps b/build/android/gyp/create_ui_locale_resources.pydeps index 6bb98dd2..a147237 100644 --- a/build/android/gyp/create_ui_locale_resources.pydeps +++ b/build/android/gyp/create_ui_locale_resources.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_ui_locale_resources.pydeps build/android/gyp/create_ui_locale_resources.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/jinja_template.pydeps b/build/android/gyp/jinja_template.pydeps index af22c40..98de9329b 100644 --- a/build/android/gyp/jinja_template.pydeps +++ b/build/android/gyp/jinja_template.pydeps
@@ -11,6 +11,7 @@ ../../../third_party/catapult/devil/devil/constants/exit_codes.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/prepare_resources.pydeps b/build/android/gyp/prepare_resources.pydeps index b225918..8136e73 100644 --- a/build/android/gyp/prepare_resources.pydeps +++ b/build/android/gyp/prepare_resources.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/prepare_resources.pydeps build/android/gyp/prepare_resources.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/unused_resources.pydeps b/build/android/gyp/unused_resources.pydeps index 4753ec3..b821d70 100644 --- a/build/android/gyp/unused_resources.pydeps +++ b/build/android/gyp/unused_resources.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/unused_resources.pydeps build/android/gyp/unused_resources.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/gyp/write_build_config.pydeps b/build/android/gyp/write_build_config.pydeps index b1276bc..e9c7d9fc 100644 --- a/build/android/gyp/write_build_config.pydeps +++ b/build/android/gyp/write_build_config.pydeps
@@ -2,6 +2,7 @@ # build/print_python_deps.py --root build/android/gyp --output build/android/gyp/write_build_config.pydeps build/android/gyp/write_build_config.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py ../../../third_party/jinja2/asyncfilters.py ../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py
diff --git a/build/android/incremental_install/generate_android_manifest.py b/build/android/incremental_install/generate_android_manifest.py index c4912837..67feaa5a 100755 --- a/build/android/incremental_install/generate_android_manifest.py +++ b/build/android/incremental_install/generate_android_manifest.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2015 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/incremental_install/generate_android_manifest.pydeps b/build/android/incremental_install/generate_android_manifest.pydeps index 568ea1e2..b28c307 100644 --- a/build/android/incremental_install/generate_android_manifest.pydeps +++ b/build/android/incremental_install/generate_android_manifest.pydeps
@@ -2,6 +2,9 @@ # build/print_python_deps.py --root build/android/incremental_install --output build/android/incremental_install/generate_android_manifest.pydeps build/android/incremental_install/generate_android_manifest.py ../../../third_party/jinja2/__init__.py ../../../third_party/jinja2/_compat.py +../../../third_party/jinja2/_identifier.py +../../../third_party/jinja2/asyncfilters.py +../../../third_party/jinja2/asyncsupport.py ../../../third_party/jinja2/bccache.py ../../../third_party/jinja2/compiler.py ../../../third_party/jinja2/defaults.py
diff --git a/build/android/incremental_install/write_installer_json.py b/build/android/incremental_install/write_installer_json.py index cf1d2d4..ce88e8a 100755 --- a/build/android/incremental_install/write_installer_json.py +++ b/build/android/incremental_install/write_installer_json.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/lighttpd_server.py b/build/android/lighttpd_server.py index ce2afbe..561174d 100755 --- a/build/android/lighttpd_server.py +++ b/build/android/lighttpd_server.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/method_count.py b/build/android/method_count.py index a39a390..80d0073 100755 --- a/build/android/method_count.py +++ b/build/android/method_count.py
@@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # Copyright 2015 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.
diff --git a/build/android/native_flags/argcapture.py b/build/android/native_flags/argcapture.py index 159b03ab..b0e2acd9 100755 --- a/build/android/native_flags/argcapture.py +++ b/build/android/native_flags/argcapture.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2021 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.
diff --git a/build/android/pylib/dex/dex_parser.py b/build/android/pylib/dex/dex_parser.py index be5f1af..1ff8d2527 100755 --- a/build/android/pylib/dex/dex_parser.py +++ b/build/android/pylib/dex/dex_parser.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2019 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file.
diff --git a/build/android/pylib/results/presentation/standard_gtest_merge.py b/build/android/pylib/results/presentation/standard_gtest_merge.py index 64f40e6..d458223 100755 --- a/build/android/pylib/results/presentation/standard_gtest_merge.py +++ b/build/android/pylib/results/presentation/standard_gtest_merge.py
@@ -1,4 +1,4 @@ -#! /usr/bin/env python +#! /usr/bin/env python3 # # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/pylib/results/presentation/test_results_presentation.py b/build/android/pylib/results/presentation/test_results_presentation.py index 2fd98b11..fc14b8b 100755 --- a/build/android/pylib/results/presentation/test_results_presentation.py +++ b/build/android/pylib/results/presentation/test_results_presentation.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/pylib/symbols/apk_lib_dump.py b/build/android/pylib/symbols/apk_lib_dump.py index 933a0ab..f40c758 100755 --- a/build/android/pylib/symbols/apk_lib_dump.py +++ b/build/android/pylib/symbols/apk_lib_dump.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2018 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps index 3ee560c..87b39ef 100644 --- a/build/android/test_runner.pydeps +++ b/build/android/test_runner.pydeps
@@ -95,6 +95,7 @@ ../../third_party/catapult/devil/devil/utils/timeout_retry.py ../../third_party/catapult/devil/devil/utils/watchdog_timer.py ../../third_party/catapult/devil/devil/utils/zip_utils.py +../../third_party/catapult/third_party/six/six.py ../../third_party/colorama/src/colorama/__init__.py ../../third_party/colorama/src/colorama/ansi.py ../../third_party/colorama/src/colorama/ansitowin32.py
diff --git a/build/android/update_deps/update_third_party_deps.py b/build/android/update_deps/update_third_party_deps.py index 3a869c4..c03fec5d 100755 --- a/build/android/update_deps/update_third_party_deps.py +++ b/build/android/update_deps/update_third_party_deps.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2016 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.
diff --git a/build/config/ios/BUILD.gn b/build/config/ios/BUILD.gn index 5309e82..1626097c 100644 --- a/build/config/ios/BUILD.gn +++ b/build/config/ios/BUILD.gn
@@ -16,11 +16,6 @@ # Mimicking how Xcode handles it, the production builds (is_debug = false) # get real bitcode sections added, while the debug builds (is_debug = true) # only get bitcode-section "markers" added in them. - # NOTE: This option is ignored when building versions for the iOS simulator, - # where a part of libvpx is compiled from the assembly code written using - # Intel assembly syntax; Yasm / Nasm do not support emitting bitcode parts. - # That is not a limitation for now as Xcode mandates the presence of bitcode - # only when building bitcode-enabled projects for real devices (ARM CPUs). enable_ios_bitcode = false }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 5a39db4..a4b7306c3 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -341,6 +341,7 @@ "//chrome/browser/consent_auditor/android:java", "//chrome/browser/contextmenu:java", "//chrome/browser/continuous_search:java", + "//chrome/browser/dependency_injection:java", "//chrome/browser/device:java", "//chrome/browser/download/android:factory_java", "//chrome/browser/download/android:file_provider_java", @@ -357,6 +358,7 @@ "//chrome/browser/history_clusters:java", "//chrome/browser/image_descriptions:java", "//chrome/browser/image_editor/public:java", + "//chrome/browser/incognito:java", "//chrome/browser/language/android:base_module_java", "//chrome/browser/language/android:java", "//chrome/browser/lens:java", @@ -776,6 +778,7 @@ "//chrome/browser/flags:jni_headers", "//chrome/browser/history_clusters:jni_headers", "//chrome/browser/image_descriptions:jni_headers", + "//chrome/browser/incognito:jni_headers", "//chrome/browser/locale:jni_headers", "//chrome/browser/performance_hints/android:jni_headers", "//chrome/browser/preferences:jni_headers", @@ -926,6 +929,7 @@ "//chrome/browser/contextmenu:java", "//chrome/browser/continuous_search:junit", "//chrome/browser/continuous_search/internal:junit", + "//chrome/browser/dependency_injection:java", "//chrome/browser/device:java", "//chrome/browser/device:junit", "//chrome/browser/download/android:java", @@ -945,6 +949,7 @@ "//chrome/browser/gsa:java", "//chrome/browser/image_descriptions:java", "//chrome/browser/image_editor/public:java", + "//chrome/browser/incognito:java", "//chrome/browser/lens:delegate_public_impl_java", "//chrome/browser/lens:java", "//chrome/browser/locale:java", @@ -1287,6 +1292,7 @@ "//chrome/browser/content_creation/notes/internal/android:javatests", "//chrome/browser/contextmenu:java", "//chrome/browser/continuous_search:javatests", + "//chrome/browser/dependency_injection:java", "//chrome/browser/device:java", "//chrome/browser/download/android:file_provider_java", "//chrome/browser/download/android:java", @@ -1301,6 +1307,7 @@ "//chrome/browser/fullscreen/android:java", "//chrome/browser/gsa:java", "//chrome/browser/image_descriptions:javatests", + "//chrome/browser/incognito:java", "//chrome/browser/language/android:base_module_java", "//chrome/browser/language/android:java", "//chrome/browser/language/android:javatests", @@ -3753,7 +3760,6 @@ "java/src/org/chromium/chrome/browser/history/HistoryDeletionBridge.java", "java/src/org/chromium/chrome/browser/history/HistoryDeletionInfo.java", "java/src/org/chromium/chrome/browser/historyreport/HistoryReportJniBridge.java", - "java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java", "java/src/org/chromium/chrome/browser/infobar/AutofillCreditCardFillingInfoBar.java", "java/src/org/chromium/chrome/browser/infobar/AutofillOfferNotificationInfoBar.java", "java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index dd58dafd..fb91a5a 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -488,7 +488,6 @@ "java/src/org/chromium/chrome/browser/datareduction/settings/DataReductionPreferenceFragment.java", "java/src/org/chromium/chrome/browser/datareduction/settings/DataReductionSiteBreakdownView.java", "java/src/org/chromium/chrome/browser/datareduction/settings/DataReductionStatsPreference.java", - "java/src/org/chromium/chrome/browser/dependency_injection/ActivityScope.java", "java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityCommonsModule.java", "java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityComponent.java", "java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppComponent.java", @@ -669,15 +668,12 @@ "java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java", "java/src/org/chromium/chrome/browser/homepage/settings/RadioButtonGroupHomepagePreference.java", "java/src/org/chromium/chrome/browser/identity_disc/IdentityDiscController.java", - "java/src/org/chromium/chrome/browser/incognito/IncognitoCctProfileManager.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationManager.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationPresenceController.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationServiceImpl.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoProfileDestroyer.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java", - "java/src/org/chromium/chrome/browser/incognito/IncognitoTabPersistence.java", "java/src/org/chromium/chrome/browser/incognito/IncognitoTabSnapshotController.java", - "java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java", "java/src/org/chromium/chrome/browser/infobar/AutofillCreditCardFillingInfoBar.java", "java/src/org/chromium/chrome/browser/infobar/AutofillOfferNotificationInfoBar.java", "java/src/org/chromium/chrome/browser/infobar/AutofillSaveCardInfoBar.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsAdapter.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsAdapter.java index 24bdfb2..c5e373bd 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsAdapter.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsAdapter.java
@@ -456,8 +456,8 @@ if (!clickthroughData.getDescription().isEmpty()) { builder.with(ModalDialogProperties.MESSAGE, clickthroughData.getDescription()); } else { - builder.with(ModalDialogProperties.MESSAGE, resources, - R.string.autofill_assistant_view_original_image_desc); + builder.with(ModalDialogProperties.MESSAGE, + resources.getString(R.string.autofill_assistant_view_original_image_desc)); } if (!clickthroughData.getPositiveText().isEmpty()) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java index e78cb15..cd08cf1 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinator.java
@@ -146,9 +146,11 @@ itemList.add(new ListItem(ListItemType.MENU_ITEM, buildPropertyModel(context, R.string.tab_grid_dialog_toolbar_remove_from_group, R.id.ungroup_tab))); - itemList.add(new ListItem(ListItemType.MENU_ITEM, - buildPropertyModel(context, R.string.tab_grid_dialog_toolbar_share_group, - R.id.share_tab_group))); + if (TabUiFeatureUtilities.ENABLE_TAB_GROUP_SHARING.getValue()) { + itemList.add(new ListItem(ListItemType.MENU_ITEM, + buildPropertyModel(context, R.string.tab_grid_dialog_toolbar_share_group, + R.id.share_tab_group))); + } if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { itemList.add(new ListItem(ListItemType.MENU_ITEM, buildPropertyModel(context, R.string.tab_grid_dialog_toolbar_edit_group_name,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java index 5a05bc8..7bac445 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java
@@ -92,6 +92,11 @@ new BooleanCachedFieldTrialParameter( ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, TAB_GROUP_AUTO_CREATION_PARAM, true); + private static final String TAB_GROUP_SHARING_PARAM = "enable_tab_group_sharing"; + public static final BooleanCachedFieldTrialParameter ENABLE_TAB_GROUP_SHARING = + new BooleanCachedFieldTrialParameter(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID, + TAB_GROUP_SHARING_PARAM, false); + private static Boolean sTabManagementModuleSupportedForTesting; /**
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java index f53a58e..87ae142 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -367,8 +367,12 @@ @Test @MediumTest - @Features.EnableFeatures(ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID) + // clang-format off + @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID + "<Study"}) + @CommandLineFlags.Add({"force-fieldtrials=Study/Group", + "force-fieldtrial-params=Study.Group:enable_tab_group_sharing/true"}) public void testDialogToolbarMenuShareGroup() { + // clang-format on final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); createTabs(cta, false, 2); enterTabSwitcher(cta); @@ -391,7 +395,9 @@ @Test @MediumTest // clang-format off - @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID}) + @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID + "<Study"}) + @CommandLineFlags.Add({"force-fieldtrials=Study/Group", + "force-fieldtrial-params=Study.Group:enable_tab_group_sharing/true"}) public void testDialogToolbarMenuShareGroup_WithSharingHub() { // clang-format on final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); @@ -1131,8 +1137,10 @@ ListView listView = (ListView) v; verifyTabGridDialogToolbarMenuItem(listView, 0, cta.getString(R.string.tab_grid_dialog_toolbar_remove_from_group)); - verifyTabGridDialogToolbarMenuItem(listView, 1, - cta.getString(R.string.tab_grid_dialog_toolbar_share_group)); + if (TabUiFeatureUtilities.ENABLE_TAB_GROUP_SHARING.getValue()) { + verifyTabGridDialogToolbarMenuItem(listView, 1, + cta.getString(R.string.tab_grid_dialog_toolbar_share_group)); + } if (TabUiFeatureUtilities.isLaunchPolishEnabled()) { assertEquals(3, listView.getCount()); verifyTabGridDialogToolbarMenuItem(listView, 2,
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 fc40ac6a..a9d8268 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -98,6 +98,7 @@ import org.chromium.chrome.browser.incognito.IncognitoNotificationManager; import org.chromium.chrome.browser.incognito.IncognitoNotificationPresenceController; import org.chromium.chrome.browser.incognito.IncognitoProfileDestroyer; +import org.chromium.chrome.browser.incognito.IncognitoStartup; import org.chromium.chrome.browser.incognito.IncognitoTabLauncher; import org.chromium.chrome.browser.incognito.IncognitoTabSnapshotController; import org.chromium.chrome.browser.incognito.IncognitoUtils; @@ -910,15 +911,8 @@ public void onResumeWithNative() { super.onResumeWithNative(); - if (IncognitoUtils.shouldDestroyIncognitoProfileOnStartup( - getTabModelSelector().getCurrentModel().isIncognito(), - TABBED_MODE_COMPONENT_NAMES)) { - Profile.getLastUsedRegularProfile() - .getPrimaryOTRProfile(/*createIfNeeded=*/true) - .destroyWhenAppropriate(); - } else { - CookiesFetcher.restoreCookies(); - } + IncognitoStartup.onResumeWithNative( + getTabModelSelectorSupplier(), TABBED_MODE_COMPONENT_NAMES); mLocaleManager.setSnackbarManager(getSnackbarManager()); mLocaleManager.startObservingPhoneChanges();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/DEPS index 1b5dcd6..6feddbb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/DEPS +++ b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
@@ -110,9 +110,6 @@ "IncognitoNotificationServiceImpl\.java": [ "+chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" ], - "IncognitoUtils\.java": [ - "+chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" - ], "StartupTabPreloader\.java": [ "+chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java" ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index edfb5a9..5de202c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -144,6 +144,7 @@ add(TabUiFeatureUtilities.ENABLE_SEARCH_CHIP); add(TabUiFeatureUtilities.ENABLE_SEARCH_CHIP_ADAPTIVE); add(TabUiFeatureUtilities.ENABLE_TAB_GROUP_AUTO_CREATION); + add(TabUiFeatureUtilities.ENABLE_TAB_GROUP_SHARING); add(TabUiFeatureUtilities.ZOOMING_MIN_MEMORY); add(TabUiFeatureUtilities.ZOOMING_MIN_SDK); add(TabUiFeatureUtilities.SKIP_SLOW_ZOOMING);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java index c94d78b9..6e1bcb57 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tab_activity_glue/ActivityTabWebContentsDelegateAndroid.java
@@ -424,7 +424,8 @@ .with(ModalDialogProperties.CONTROLLER, dialogController) .with(ModalDialogProperties.TITLE, resources, R.string.http_post_warning_title) - .with(ModalDialogProperties.MESSAGE, resources, R.string.http_post_warning) + .with(ModalDialogProperties.MESSAGE, + resources.getString(R.string.http_post_warning)) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.http_post_warning_resend) .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java index cf5a3f9..bfff9a9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java
@@ -114,7 +114,7 @@ assert !mPendingSearchPromoDecision; assert !isVoiceSearchIntent || mNativeInitialized; - if (voiceRecognitionHandler.isVoiceSearchEnabled() && isVoiceSearchIntent) { + if (isVoiceSearchIntent && voiceRecognitionHandler.isVoiceSearchEnabled()) { voiceRecognitionHandler.startVoiceRecognition( VoiceRecognitionHandler.VoiceInteractionSource.SEARCH_WIDGET); } else { @@ -159,4 +159,9 @@ mUrlBarFocusRequested = false; } } + + @Override + public void notifyVoiceRecognitionCanceled() { + focusTextBox(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsConsentDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsConsentDialog.java index 06febbaf..51b078c7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsConsentDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/usage_stats/UsageStatsConsentDialog.java
@@ -45,13 +45,13 @@ if (mIsRevocation) { builder.with(ModalDialogProperties.TITLE, resources, R.string.usage_stats_revocation_prompt) - .with(ModalDialogProperties.MESSAGE, resources, - R.string.usage_stats_revocation_explanation) + .with(ModalDialogProperties.MESSAGE, + resources.getString(R.string.usage_stats_revocation_explanation)) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.remove); } else { builder.with(ModalDialogProperties.TITLE, resources, R.string.usage_stats_consent_title) - .with(ModalDialogProperties.MESSAGE, resources, - R.string.usage_stats_consent_prompt) + .with(ModalDialogProperties.MESSAGE, + resources.getString(R.string.usage_stats_consent_prompt)) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.show); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIconNameUpdateDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIconNameUpdateDialog.java index af2ad8f..6167b31 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIconNameUpdateDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkIconNameUpdateDialog.java
@@ -101,8 +101,8 @@ new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) .with(ModalDialogProperties.CONTROLLER, this) .with(ModalDialogProperties.TITLE, resources, titleId) - .with(ModalDialogProperties.MESSAGE, resources, - R.string.webapp_update_explanation) + .with(ModalDialogProperties.MESSAGE, + resources.getString(R.string.webapp_update_explanation)) .with(ModalDialogProperties.CUSTOM_VIEW, dialogCustomView) .with(ModalDialogProperties.PRIMARY_BUTTON_FILLED, true) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.ok)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java index c369f04..209799f2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarTest.java
@@ -593,8 +593,12 @@ @Test @MediumTest + @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.VOICE_BUTTON_IN_TOP_TOOLBAR, + "disable-features=" + ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR + "," + + ChromeFeatureList.ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_CUSTOMIZATION_V2}) @Restriction(UiRestriction.RESTRICTION_TYPE_TABLET) - public void testFocusLogic_buttonVisibilityTablet() { + public void + testFocusLogic_buttonVisibilityTablet() { startActivityNormally(); doReturn(true).when(mVoiceRecognitionHandler).isVoiceSearchEnabled(); String url = mActivityTestRule.getEmbeddedTestServerRule().getServer().getURLWithHostName(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java index d43161c..d337a00 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandlerTest.java
@@ -473,6 +473,9 @@ public String getUrl() { return mUrl; } + + @Override + public void notifyVoiceRecognitionCanceled() {} } /**
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 41f9644e..217149a 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -2025,6 +2025,12 @@ <message name="IDS_SETTINGS_BLUETOOTH_CHANGE_DEVICE_NAME_DIALOG_DONE" desc="Bluetooth device details page > Change device name dialog: Label for button that initiates device's name change."> Done </message> + <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_MOUSE" desc="Bluetooth device details page: label for button that changes current mouse device settings."> + Change mouse settings + </message> + <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_KEYBOARD" desc="Bluetooth device details page: label for button that changes current keyboard device settings."> + Change keyboard settings + </message> <message name="IDS_SETTINGS_BLUETOOTH_TOGGLE_ACCESSIBILITY_LABEL" desc="Accessibility only label for Bluetooth enable/disable toggle."> Bluetooth enable </message> @@ -2070,6 +2076,63 @@ <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_BATTERY_PERCENTAGE" desc="Label for a paired Bluetooth device in a list that indicates the battery level of the device."> <ph name="BATTERY_PERCENTAGE">$1<ex>32</ex></ph>% </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN" desc="Accessibility label for paired Bluetooth device list item with a device type of unknown."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Unknown device type + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of unknown and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Unknown device type, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER" desc="Accessibility label for paired Bluetooth device list item with a device type of computer."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Computer + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of computer and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Computer, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE" desc="Accessibility label for paired Bluetooth device list item with a device type of phone."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Phone + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of phone and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Phone, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET" desc="Accessibility label for paired Bluetooth device list item with a device type of audio device."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Audio device + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of audio device and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Audio device, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA" desc="Accessibility label for paired Bluetooth device list item with a device type of video camera."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Video camera + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of video camera and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Video camera, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER" desc="Accessibility label for paired Bluetooth device list item with a device type of game controller."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Game controller + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of game controller and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Game controller, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD" desc="Accessibility label for paired Bluetooth device list item with a device type of keyboard."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Keyboard + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of keyboard and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Keyboard, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE" desc="Accessibility label for paired Bluetooth device list item with a device type of mouse."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Mouse + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of mouse and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Mouse, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET" desc="Accessibility label for paired Bluetooth device list item with a device type of tablet."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Tablet + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET_WITH_BATTERY_INFO" desc="Accessibility label for paired Bluetooth device list item with a device type of tablet and available battery info."> + Device <ph name="DEVICE_INDEX">$1<ex>1</ex></ph> of <ph name="DEVICE_COUNT">$2<ex>15</ex></ph>, <ph name="DEVICE_NAME">$3<ex>Beats</ex></ph>, Tablet, Battery level <ph name="BATTERY_PERCENTAGE">$4<ex>50</ex></ph>% + </message> + <message name="IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_SUBPAGE_BUTTON_A11Y_LABEL" desc="Accessibility label for button in a paired Bluetooth device list item that routes to the detail page for the device."> + <ph name="DEVICE">$1<ex>Beats</ex></ph>, Details + </message> <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_DETAILS" desc="Name of the settings page which displays Bluetooth device details."> Bluetooth device details </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_KEYBOARD.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_KEYBOARD.png.sha1 new file mode 100644 index 0000000..7303f4c --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_KEYBOARD.png.sha1
@@ -0,0 +1 @@ +2dc524c14a803cfd6e1b7fac0dfcaea98ec1084f \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_MOUSE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_MOUSE.png.sha1 new file mode 100644 index 0000000..6736288 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_MOUSE.png.sha1
@@ -0,0 +1 @@ +0c0d756e242386c82a2359fe599e85eddd6607c9 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER.png.sha1 new file mode 100644 index 0000000..63bb59a --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER.png.sha1
@@ -0,0 +1 @@ +77d711c149e055a401f13707015648435173b3be \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..cb1bd81c --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +df2f9b854954a5d4a8a1eb874793897e9b688bac \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER.png.sha1 new file mode 100644 index 0000000..48203d87 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER.png.sha1
@@ -0,0 +1 @@ +0f03c8c9f2d4b73a68317b3815960d188302c51d \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..ef61b4c1 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +236471ea7a3253d9356f05ba96a9f2ad358ca458 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET.png.sha1 new file mode 100644 index 0000000..1dde5c58 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET.png.sha1
@@ -0,0 +1 @@ +74b63a5fba11bf77b9c74e48818de5058f8c1c70 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..8acd3b6 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +d415824b9802d499cc6db252bd19a8db63c8b8ff \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD.png.sha1 new file mode 100644 index 0000000..1f8f6e4 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD.png.sha1
@@ -0,0 +1 @@ +2be849292e89f74ff78e7c2bc404fc3947c74207 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..f5ddc5d --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +7b6643132fac08170adf0da0cd90a6a28879604f \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE.png.sha1 new file mode 100644 index 0000000..6707e32 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE.png.sha1
@@ -0,0 +1 @@ +025d119796fde76b9ae66e7dcd669f0214b92262 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..82b97d4 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +c43dcc75766ed9300c62d624a5340d5753b151fc \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE.png.sha1 new file mode 100644 index 0000000..3311d2fc --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE.png.sha1
@@ -0,0 +1 @@ +8eefe5c08186a9473717a44dc239e9b7c660a52d \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..1408d7b --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +2c7e33bf810d184b0e223976f76153a91ba9ae2a \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET.png.sha1 new file mode 100644 index 0000000..58699a8 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET.png.sha1
@@ -0,0 +1 @@ +b749c7595996c5b471d803ec88b9a6dc69161fb8 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..f9d2d29 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +b7db253df89c7ce360c8dc16beaaab1dba959a06 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN.png.sha1 new file mode 100644 index 0000000..c69328d3 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN.png.sha1
@@ -0,0 +1 @@ +3dd05a9ab89e3fdff620068255f6b4c56c455385 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..b31a50f --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +76ab44de9efc6172f425242f064de8f8e465bd7b \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA.png.sha1 new file mode 100644 index 0000000..e4a0ad9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA.png.sha1
@@ -0,0 +1 @@ +dac2dfd7833f1e0a9ee0e0d07b4c73447457d788 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA_WITH_BATTERY_INFO.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA_WITH_BATTERY_INFO.png.sha1 new file mode 100644 index 0000000..5250785 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA_WITH_BATTERY_INFO.png.sha1
@@ -0,0 +1 @@ +2719e66d6d8e42a0fb67eabd6ba7d99f3e24942e \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_SUBPAGE_BUTTON_A11Y_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_SUBPAGE_BUTTON_A11Y_LABEL.png.sha1 new file mode 100644 index 0000000..18453f9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_SUBPAGE_BUTTON_A11Y_LABEL.png.sha1
@@ -0,0 +1 @@ +8ea28bdda83d0d5ce6a9a889bcdaae4fe7ceb1b8 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 0be54dab..ee2cda4d 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3042,6 +3042,7 @@ "geolocation/geolocation_permission_context_delegate_android.h", "history_clusters/history_clusters_tab_helper_android.cc", "icon_loader_android.cc", + "incognito/android/incognito_utils_android.cc", "installable/installed_webapp_bridge.cc", "installable/installed_webapp_bridge.h", "installable/installed_webapp_geolocation_bridge.cc", @@ -3172,7 +3173,6 @@ "profiles/android/profile_manager_utils.cc", "profiles/android/profile_resolver.cc", "profiles/android/profile_resolver.h", - "profiles/incognito_utils_android.cc", "profiles/profile_android.cc", "profiles/profile_android.h", "profiles/profile_key_android.cc", @@ -6992,7 +6992,6 @@ deps += [ "//chrome/browser/resources/chromeos/account_manager:web_components", "//chrome/browser/resources/chromeos/account_manager/components:web_components", - "//chrome/browser/resources/chromeos/add_supervision:post_message_api", "//chrome/browser/resources/chromeos/add_supervision:web_components", "//chrome/browser/resources/chromeos/crostini_installer:web_components", "//chrome/browser/resources/chromeos/crostini_upgrader:web_components",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index accfb7dc..f2a7c81 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1445,6 +1445,13 @@ "(electronicexpress.com|zazzle.com|wish.com|homesquare.com)"}}; const FeatureEntry::FeatureParam kNtpChromeCartModuleHeuristicsImprovement[] = { {ntp_features::kNtpChromeCartModuleHeuristicsImprovementParam, "true"}}; +const FeatureEntry::FeatureParam kNtpChromeCartModuleRBDAndCouponDiscount[] = { + {ntp_features::kNtpChromeCartModuleHeuristicsImprovementParam, "true"}, + {ntp_features::kNtpChromeCartModuleAbandonedCartDiscountParam, "true"}, + {ntp_features::NtpChromeCartModuleAbandonedCartDiscountUseUtmParam, "true"}, + {"partner-merchant-pattern", + "(electronicexpress.com|zazzle.com|wish.com|homesquare.com)"}, + {ntp_features::kNtpChromeCartModuleCouponParam, "true"}}; const FeatureEntry::FeatureVariation kNtpChromeCartModuleVariations[] = { {"- Fake Data And Discount", kNtpChromeCartModuleFakeData, base::size(kNtpChromeCartModuleFakeData), nullptr}, @@ -1452,6 +1459,8 @@ base::size(kNtpChromeCartModuleAbandonedCartDiscount), nullptr}, {"- Heuristics Improvement", kNtpChromeCartModuleHeuristicsImprovement, base::size(kNtpChromeCartModuleHeuristicsImprovement), nullptr}, + {"- RBD and Coupons", kNtpChromeCartModuleRBDAndCouponDiscount, + base::size(kNtpChromeCartModuleRBDAndCouponDiscount), nullptr}, }; const FeatureEntry::FeatureParam kNtpRecipeTasksModuleFakeData[] = { @@ -2588,6 +2597,13 @@ base::size(kContinuousSearchDoubleRowChip), nullptr}}; #endif // defined(OS_ANDROID) +const FeatureEntry::Choice kDocumentTransitionSlowdownFactorChoices[] = { + {flags_ui::kGenericExperimentChoiceDefault, "", ""}, + {"5", switches::kDocumentTransitionSlowdownFactor, "5"}, + {"10", switches::kDocumentTransitionSlowdownFactor, "10"}, + {"20", switches::kDocumentTransitionSlowdownFactor, "20"}, + {"50", switches::kDocumentTransitionSlowdownFactor, "50"}}; + // RECORDING USER METRICS FOR FLAGS: // ----------------------------------------------------------------------------- // The first line of the entry is the internal name. @@ -3779,6 +3795,10 @@ {"document-transition", flag_descriptions::kDocumentTransitionName, flag_descriptions::kDocumentTransitionDescription, kOsAll, FEATURE_VALUE_TYPE(blink::features::kDocumentTransition)}, + {"document-transition-slowdown-factor", + flag_descriptions::kDocumentTransitionSlowdownFactorName, + flag_descriptions::kDocumentTransitionSlowdownFactorDescription, kOsAll, + MULTI_VALUE_TYPE(kDocumentTransitionSlowdownFactorChoices)}, #if defined(OS_WIN) {"use-winrt-midi-api", flag_descriptions::kUseWinrtMidiApiName, flag_descriptions::kUseWinrtMidiApiDescription, kOsWin, @@ -5573,12 +5593,12 @@ {"enhanced-network-voices", flag_descriptions::kEnhancedNetworkVoicesName, flag_descriptions::kEnhancedNetworkVoicesDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kEnhancedNetworkVoices)}, -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - +#else {"enable-extended-sync-promos-capability", flag_descriptions::kEnableExtendedSyncPromosCapabilityName, flag_descriptions::kEnableExtendedSyncPromosCapabilityDescription, flags_ui::kOsAndroid, FEATURE_VALUE_TYPE(switches::kMinorModeSupport)}, +#endif // BUILDFLAG(IS_CHROMEOS_ASH) {"enable-fenced-frames", flag_descriptions::kEnableFencedFramesName, flag_descriptions::kEnableFencedFramesDescription, kOsAll, @@ -7469,6 +7489,11 @@ flag_descriptions::kExtensionsMenuAccessControlDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kExtensionsMenuAccessControl)}, + {"persistent-quota-is-temporary-quota", + flag_descriptions::kPersistentQuotaIsTemporaryQuotaName, + flag_descriptions::kPersistentQuotaIsTemporaryQuotaDescription, kOsAll, + FEATURE_VALUE_TYPE(blink::features::kPersistentQuotaIsTemporaryQuota)}, + // 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/android/feed/v2/feed_service_factory.cc b/chrome/browser/android/feed/v2/feed_service_factory.cc index f6bd6309..9844bff4 100644 --- a/chrome/browser/android/feed/v2/feed_service_factory.cc +++ b/chrome/browser/android/feed/v2/feed_service_factory.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/android/feed/v2/feed_service_bridge.h" #include "chrome/browser/android/feed/v2/refresh_task_scheduler_impl.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/flags/android/chrome_feature_list.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/profiles/profile.h" @@ -120,6 +121,8 @@ feed::ChromeInfo chrome_info; chrome_info.version = base::Version({CHROME_VERSION}); chrome_info.channel = chrome::GetChannel(); + chrome_info.start_surface = + base::FeatureList::IsEnabled(chrome::android::kStartSurfaceAndroid); return new FeedService( std::make_unique<FeedServiceDelegateImpl>(),
diff --git a/chrome/browser/apps/app_service/app_service_proxy_factory.h b/chrome/browser/apps/app_service/app_service_proxy_factory.h index a8ae786..315303c 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_factory.h +++ b/chrome/browser/apps/app_service/app_service_proxy_factory.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_APPS_APP_SERVICE_APP_SERVICE_PROXY_FACTORY_H_ #include "base/memory/singleton.h" +#include "build/chromeos_buildflags.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" class Profile;
diff --git a/chrome/browser/ash/accessibility/accessibility_input_method_observer.h b/chrome/browser/ash/accessibility/accessibility_input_method_observer.h index 7fab5bd..53d23a4 100644 --- a/chrome/browser/ash/accessibility/accessibility_input_method_observer.h +++ b/chrome/browser/ash/accessibility/accessibility_input_method_observer.h
@@ -10,6 +10,7 @@ namespace ui { class InputMethod; +class InputMethodObserver; } namespace ash {
diff --git a/chrome/browser/ash/arc/print_spooler/print_session_impl.cc b/chrome/browser/ash/arc/print_spooler/print_session_impl.cc index 8516ac8..2ec3e7d 100644 --- a/chrome/browser/ash/arc/print_spooler/print_session_impl.cc +++ b/chrome/browser/ash/arc/print_spooler/print_session_impl.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/ash/arc/print_spooler/arc_print_spooler_util.h" #include "chrome/browser/printing/print_view_manager_common.h" #include "chrome/browser/printing/printing_service.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom.h" #include "components/arc/intent_helper/custom_tab.h" #include "components/arc/mojom/print_common.mojom.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ash/customization/customization_document.h b/chrome/browser/ash/customization/customization_document.h index 3a01f43..4d8e7526 100644 --- a/chrome/browser/ash/customization/customization_document.h +++ b/chrome/browser/ash/customization/customization_document.h
@@ -16,6 +16,7 @@ #include "base/macros.h" #include "base/memory/singleton.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "base/values.h" #include "url/gurl.h"
diff --git a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.cc b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.cc index aac6f8f9..191c1cf 100644 --- a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.cc +++ b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.cc
@@ -11,6 +11,8 @@ #include "base/bind.h" #include "base/logging.h" #include "base/no_destructor.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_constants.h" #include "chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.h" #include "components/google/core/common/google_util.h" @@ -42,7 +44,8 @@ EnhancedNetworkTtsImpl::EnhancedNetworkTtsImpl() : api_key_(kApiKey.Get().empty() ? google_apis::GetReadAloudAPIKey() - : kApiKey.Get()) {} + : kApiKey.Get()), + char_limit_per_request_(mojom::kEnhancedNetworkTtsMaxCharacterSize) {} EnhancedNetworkTtsImpl::~EnhancedNetworkTtsImpl() = default; void EnhancedNetworkTtsImpl::BindReceiverAndURLFactory( @@ -80,20 +83,50 @@ return; } - // TODO(crbug.com/1240445): Chop the utterance into text pieces, and queue - // them into the |server_requests_|. Currently we send the entire utterance - // as a single text piece. - std::unique_ptr<network::SimpleURLLoader> url_loader = MakeRequestLoader(); - url_loader->AttachStringForUpload(FormatJsonRequest(std::move(request)), - kNetworkRequestUploadType); - server_requests_.emplace_back(std::move(url_loader), - 0 /* text_piece_start_index */, - true /* is_last_request */); + std::u16string utterance_u16string = base::UTF8ToUTF16(request->utterance); + // Ignore the whitespaces at start. The ICU break iterator does not work well + // with text that has whitespaces at start. We must trim the text before + // sending it to |FindTextBreaks|. + int start_offset = 0; + while (base::IsUnicodeWhitespace(utterance_u16string[start_offset])) { + start_offset++; + } + utterance_u16string = utterance_u16string.substr(start_offset); + + // Chop the utterance into smaller text pieces and queue them into + // |server_requests_|. + std::vector<uint16_t> text_breaks = + FindTextBreaks(utterance_u16string, char_limit_per_request_); + uint16_t text_piece_start_index = 0; + for (int i = 0; i < text_breaks.size(); i++) { + uint16_t text_piece_end_index = text_breaks[i]; + auto size = text_piece_end_index - text_piece_start_index + 1; + const std::string text_piece = base::UTF16ToUTF8( + utterance_u16string.substr(text_piece_start_index, size)); + + mojom::TtsRequestPtr new_tts_request = mojom::TtsRequest::New( + text_piece, request->rate, request->voice, request->lang); + std::unique_ptr<network::SimpleURLLoader> url_loader = MakeRequestLoader(); + const bool last_request = i == text_breaks.size() - 1; + url_loader->AttachStringForUpload( + FormatJsonRequest(std::move(new_tts_request)), + kNetworkRequestUploadType); + server_requests_.emplace_back(std::move(url_loader), + text_piece_start_index + start_offset, + last_request); + + // Prepare for the next text piece. + text_piece_start_index = text_piece_end_index + 1; + } // Kick off the server requests. ProcessNextServerRequest(); } +void EnhancedNetworkTtsImpl::SetCharLimitPerRequestForTesting(int limit) { + char_limit_per_request_ = limit; +} + data_decoder::mojom::JsonParser* EnhancedNetworkTtsImpl::GetJsonParser() { // TODO(crbug.com/1217301): Sets an explicit disconnect handler. if (!json_parser_) {
diff --git a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.h b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.h index 4e363f5..ccc7e46 100644 --- a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.h +++ b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.h
@@ -52,6 +52,11 @@ static constexpr base::Feature kOverrideParams{ "EnhancedNetworkTtsOverride", base::FEATURE_DISABLED_BY_DEFAULT}; + // Set the character limit of text piece in each |ServerRequest|. Unit tests + // can use this method to modify the limit. Otherwise, the limit is set to + // |mojom::kEnhancedNetworkTtsMaxCharacterSize|. + void SetCharLimitPerRequestForTesting(int limit); + private: // An input utterance may be chopped into several text pieces, which will be // sent over several |ServerRequest|. A |ServerRequest| contains three @@ -131,6 +136,11 @@ const std::string api_key_; + // The character limit of text piece in each |ServerRequest|. The limit is set + // to |mojom::kEnhancedNetworkTtsMaxCharacterSize| but can be overridden by + // |SetCharLimitPerRequestForTesting|. + int char_limit_per_request_; + // Used for all callbacks. base::WeakPtrFactory<EnhancedNetworkTtsImpl> weak_factory_{this};
diff --git a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl_unittest.cc b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl_unittest.cc index 05734cde..1dfde40 100644 --- a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl_unittest.cc +++ b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl_unittest.cc
@@ -235,6 +235,48 @@ EXPECT_EQ(timing_data[1].text_offset, 6); } +TEST_F(EnhancedNetworkTtsImplTest, GetAudioDataIgnoresWhitespacesAtStart) { + const std::string input_text = " test1 test2"; + const std::string input_text_trimmed = "test1 test2"; + const float rate = 1.0; + GetTestingInstance().GetAudioData( + mojom::TtsRequest::New(input_text, rate, absl::nullopt, absl::nullopt), + base::BindOnce( + [](TestAudioDataObserverImpl* observer, + mojo::PendingReceiver<mojom::AudioDataObserver> pending_receiver) { + observer->BindReceiver(std::move(pending_receiver)); + }, + GetTestingObserverPtr())); + test_task_env_.RunUntilIdle(); + + const std::map<std::string, absl::optional<std::string>> expected_headers = { + {kGoogApiKeyHeader, google_apis::GetReadAloudAPIKey()}}; + const std::string expected_body = + CreateCorrectRequest(input_text_trimmed, rate); + // |expected_output| here is arbitrary, which is encoded into a fake response + // sent by the fake server, |TestServerURLLoaderFactory|. In general, we + // expect the real server sends the audio data back as a base64 encoded JSON + // string. + const std::vector<uint8_t> expected_output = {1, 2, 5}; + test_url_factory_.ExpectRequestAndSimulateResponse( + kReadAloudServerUrl, expected_headers, expected_body, + CreateServerResponse(expected_output), net::HTTP_OK); + test_task_env_.RunUntilIdle(); + + // We only get the data after the server's response. We simulate the response + // in the code above. + absl::optional<mojom::TtsRequestError> error; + std::vector<uint8_t> audio_data; + std::vector<mojom::TimingInfo> timing_data; + UnpackResult(&error, &audio_data, &timing_data, + GetTestingObserverPtr()->GetNexResponse()); + // The text offset will be compensated with whitespaces. + EXPECT_EQ(timing_data[0].text, "test1"); + EXPECT_EQ(timing_data[0].text_offset, 4); + EXPECT_EQ(timing_data[1].text, "test2"); + EXPECT_EQ(timing_data[1].text_offset, 10); +} + TEST_F(EnhancedNetworkTtsImplTest, GetAudioDataSucceedsWithFasterRate) { const std::string input_text = "Rate will be capped to kMaxRate"; const float rate = kMaxRate + 1.0f; @@ -307,6 +349,53 @@ EXPECT_EQ(audio_data, expected_output); } +TEST_F(EnhancedNetworkTtsImplTest, GetAudioDataWithLongUtterance) { + const std::string input_text = "Sent 1. Hello world!"; + const float rate = 1.0; + // Sets the limit to cover the first sentence and every words in the second + // sentence. + GetTestingInstance().SetCharLimitPerRequestForTesting(8); + GetTestingInstance().GetAudioData( + mojom::TtsRequest::New(input_text, rate, absl::nullopt, absl::nullopt), + base::BindOnce( + [](TestAudioDataObserverImpl* observer, + mojo::PendingReceiver<mojom::AudioDataObserver> pending_receiver) { + observer->BindReceiver(std::move(pending_receiver)); + }, + GetTestingObserverPtr())); + test_task_env_.RunUntilIdle(); + + const std::map<std::string, absl::optional<std::string>> expected_headers = { + {kGoogApiKeyHeader, google_apis::GetReadAloudAPIKey()}}; + // |expected_output| here is arbitrary, which is encoded into a fake response + // sent by the fake server, |TestServerURLLoaderFactory|. In general, we + // expect the real server sends the audio data back as a base64 encoded JSON + // string. + const std::vector<uint8_t> expected_output = {1, 2, 5}; + + // The first request contains the first sentence. + const std::string first_expected_body = + CreateCorrectRequest("Sent 1. ", rate); + test_url_factory_.ExpectRequestAndSimulateResponse( + kReadAloudServerUrl, expected_headers, first_expected_body, + CreateServerResponse(expected_output), net::HTTP_OK); + test_task_env_.RunUntilIdle(); + + // The second request contains the first word in the second sentence. + const std::string second_expected_body = CreateCorrectRequest("Hello", rate); + test_url_factory_.ExpectRequestAndSimulateResponse( + kReadAloudServerUrl, expected_headers, second_expected_body, + CreateServerResponse(expected_output), net::HTTP_OK); + test_task_env_.RunUntilIdle(); + + // The third request contains the second word in the second sentence. + const std::string third_expected_body = CreateCorrectRequest(" world!", rate); + test_url_factory_.ExpectRequestAndSimulateResponse( + kReadAloudServerUrl, expected_headers, third_expected_body, + CreateServerResponse(expected_output), net::HTTP_OK); + test_task_env_.RunUntilIdle(); +} + TEST_F(EnhancedNetworkTtsImplTest, EmptyUtteranceError) { const std::string input_text(""); const float rate = 1.0;
diff --git a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc index 713138f..7fdd910 100644 --- a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc +++ b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.cc
@@ -12,7 +12,7 @@ #include "base/json/json_writer.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" -#include "base/strings/utf_string_conversions.h" +#include "base/strings/string_util.h" #include "chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_constants.h" #include "ui/accessibility/ax_text_utils.h" @@ -93,7 +93,7 @@ return json_request; } -std::vector<uint16_t> FindTextBreaks(const std::string& utterance, +std::vector<uint16_t> FindTextBreaks(const std::u16string& utterance, const int length_limit) { std::vector<uint16_t> breaks; DCHECK_GT(length_limit, 0); @@ -101,6 +101,11 @@ if (utterance.empty()) return breaks; + // The input utterance must be pre-trimmed so that it does not start with + // whitespaces. The ICU break iterator does not work well with text that + // has whitespaces at start. + DCHECK(!base::IsUnicodeWhitespace(utterance[0])); + const int utterance_length = utterance.length(); if (utterance_length <= length_limit) { breaks.push_back(utterance_length - 1); @@ -113,12 +118,9 @@ return breaks; } - const std::u16string utterance_u16string = base::UTF8ToUTF16(utterance); - - std::vector<int> sentence_ends = - ui::GetSentenceEndOffsets(utterance_u16string); + std::vector<int> sentence_ends = ui::GetSentenceEndOffsets(utterance); ConvertOffsetsToIndexes(sentence_ends); - std::vector<int> word_ends = ui::GetWordEndOffsets(utterance_u16string); + std::vector<int> word_ends = ui::GetWordEndOffsets(utterance); ConvertOffsetsToIndexes(word_ends); const int sentence_ends_length = sentence_ends.size(); @@ -231,10 +233,14 @@ timing_info.FindStringPath("location.timeLocation.timeOffset"); const std::string* timing_info_duration_ptr = timing_info.FindStringPath("location.timeLocation.duration"); - // The first item in the timing_info_list does not have a text offset, we - // default that to 0. - const absl::optional<int> timing_info_text_offset = - i == 0 ? 0 : timing_info.FindIntPath("location.textLocation.offset"); + // If the first item in the timing_info_list does not have a text offset, + // we default that to 0. If the first item starts with whitespaces, the + // server will send back the text offset for the item. + absl::optional<int> timing_info_text_offset = + timing_info.FindIntPath("location.textLocation.offset"); + if (timing_info_text_offset == absl::nullopt && i == 0) { + timing_info_text_offset = 0; + } if (timing_info_text_offset == absl::nullopt || !timing_info_text_ptr || !timing_info_timeoffset_ptr || !timing_info_duration_ptr) {
diff --git a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.h b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.h index d19e9a7..c9bc844 100644 --- a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.h +++ b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils.h
@@ -26,8 +26,10 @@ // contains a over-length word and we calculate text breaks using // |length_limit| directly. The returned vector contains the indexes for the // breaks. For example, a [2, 4] vector means we should pass the utterance -// "hello" as: "hel" and "lo". -std::vector<uint16_t> FindTextBreaks(const std::string& utterance, +// "hello" as: "hel" and "lo". The |utterance| must not start with +// whitespaces, and the caller might need to pre-trim the |utterance| before +// calling this method. +std::vector<uint16_t> FindTextBreaks(const std::u16string& utterance, const int length_limit); // Generate a response when encountering errors (e.g., server error, unexpected
diff --git a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils_unittest.cc b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils_unittest.cc index 4ece57a..8ce45dc 100644 --- a/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils_unittest.cc +++ b/chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_utils_unittest.cc
@@ -75,23 +75,23 @@ } TEST_F(EnhancedNetworkTtsUtilsTest, FindTextBreaks) { - std::string utterance = ""; + std::u16string utterance = u""; int length_limit = 10; std::vector<uint16_t> expected_output = {}; EXPECT_EQ(FindTextBreaks(utterance, length_limit), expected_output); - utterance = "utterance is shorter than length_limit"; + utterance = u"utterance is shorter than length_limit"; length_limit = 1000; expected_output = {37}; EXPECT_EQ(FindTextBreaks(utterance, length_limit), expected_output); - utterance = "limit is 1"; + utterance = u"limit is 1"; length_limit = 1; expected_output = {1, 2, 3, 4, 5, 6, 7, 8, 9}; EXPECT_EQ(FindTextBreaks(utterance, length_limit), expected_output); - // Index ref:012345678901234 - utterance = "Sent 1! Sent 2!"; + // Index ref: 012345678901234 + utterance = u"Sent 1! Sent 2!"; length_limit = 4; // 3 = word end of "Sent" // 7 = first sentence end @@ -100,8 +100,8 @@ expected_output = {3, 7, 11, 14}; EXPECT_EQ(FindTextBreaks(utterance, length_limit), expected_output); - // Index ref:01234567890123456789012 - utterance = "Sent 1! Sent 2. Sent 3!"; + // Index ref: 01234567890123456789012 + utterance = u"Sent 1! Sent 2. Sent 3!"; length_limit = 8; // 7 = first sentence end // 15 = second sentence end @@ -109,8 +109,8 @@ expected_output = {7, 15, 22}; EXPECT_EQ(FindTextBreaks(utterance, length_limit), expected_output); - // Index ref:01234567890123456 - utterance = "Sent 1! Sent two!"; + // Index ref: 01234567890123456 + utterance = u"Sent 1! Sent two!"; length_limit = 3; // 2 = over length limit at char 'n' // 5 = word end of "1"
diff --git a/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc b/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc index 23fe0f7d..4920fed8 100644 --- a/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc +++ b/chrome/browser/ash/file_system_provider/operations/read_file_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> #include <utility> +#include <vector> #include "base/bind.h" #include "base/containers/span.h" @@ -164,15 +165,15 @@ const bool has_more = false; const int execution_time = 0; - base::Value values_as_list(base::Value::Type::LIST); - values_as_list.Append(kFileSystemId); - values_as_list.Append(kRequestId); - values_as_list.Append(base::Value(base::as_bytes(base::make_span(data)))); - values_as_list.Append(has_more); - values_as_list.Append(execution_time); + std::vector<base::Value> values_as_list; + values_as_list.emplace_back(kFileSystemId); + values_as_list.emplace_back(kRequestId); + values_as_list.emplace_back( + base::Value(base::as_bytes(base::make_span(data)))); + values_as_list.emplace_back(has_more); + values_as_list.emplace_back(execution_time); - std::unique_ptr<Params> params( - Params::Create(base::Value::AsListValue(std::move(values_as_list)))); + std::unique_ptr<Params> params(Params::Create(std::move(values_as_list))); ASSERT_TRUE(params.get()); std::unique_ptr<RequestValue> request_value( RequestValue::CreateForReadFileSuccess(std::move(params)));
diff --git a/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc b/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc index 8e4fd98..0639e83f 100644 --- a/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc +++ b/chrome/browser/ash/file_system_provider/provided_file_system_unittest.cc
@@ -93,7 +93,7 @@ using extensions::api::file_system_provider_internal:: OperationRequestedSuccess::Params; - std::unique_ptr<Params> params(Params::Create(value_as_list)); + std::unique_ptr<Params> params(Params::Create(value_as_list.GetList())); ASSERT_TRUE(params.get()); file_system_->GetRequestManager()->FulfillRequest( request_id,
diff --git a/chrome/browser/ash/full_restore/full_restore_service.cc b/chrome/browser/ash/full_restore/full_restore_service.cc index 55cecd5..d5b1787 100644 --- a/chrome/browser/ash/full_restore/full_restore_service.cc +++ b/chrome/browser/ash/full_restore/full_restore_service.cc
@@ -197,9 +197,6 @@ if (notification_ != nullptr && !is_shut_down_) { NotificationDisplayService::GetForProfile(profile_)->Close( NotificationHandler::Type::TRANSIENT, notification_->id()); - - if (accelerator_controller_observer_.IsObserving()) - accelerator_controller_observer_.Reset(); } if (allow_save) { @@ -275,21 +272,6 @@ ::full_restore::FullRestoreSaveHandler::GetInstance()->SetShutDown(); } -void FullRestoreService::OnActionPerformed(AcceleratorAction action) { - switch (action) { - case NEW_INCOGNITO_WINDOW: - case NEW_TAB: - case NEW_WINDOW: - case OPEN_CROSH: - case OPEN_DIAGNOSTICS: - case RESTORE_TAB: - MaybeCloseNotification(); - return; - default: - return; - } -} - void FullRestoreService::SetAppLaunchHanlderForTesting( std::unique_ptr<FullRestoreAppLaunchHandler> app_launch_handler) { app_launch_handler_ = std::move(app_launch_handler); @@ -303,12 +285,6 @@ if (!ShouldShowNotification()) return; - auto* accelerator_controller = ash::AcceleratorController::Get(); - if (accelerator_controller) { - DCHECK(!accelerator_controller_observer_.IsObserving()); - accelerator_controller_observer_.Observe(accelerator_controller); - } - message_center::RichNotificationData notification_data; message_center::ButtonInfo restore_button(
diff --git a/chrome/browser/ash/full_restore/full_restore_service.h b/chrome/browser/ash/full_restore/full_restore_service.h index 808a3ec..851b45c7 100644 --- a/chrome/browser/ash/full_restore/full_restore_service.h +++ b/chrome/browser/ash/full_restore/full_restore_service.h
@@ -7,9 +7,7 @@ #include <memory> -#include "ash/public/cpp/accelerators.h" #include "base/memory/weak_ptr.h" -#include "base/scoped_observation.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" #include "content/public/browser/notification_observer.h" @@ -57,8 +55,7 @@ // interfaces to restore the app launchings and app windows. class FullRestoreService : public KeyedService, public message_center::NotificationObserver, - public content::NotificationObserver, - public ash::AcceleratorController::Observer { + public content::NotificationObserver { public: static FullRestoreService* GetForProfile(Profile* profile); static void MaybeCloseNotification(Profile* profile); @@ -89,9 +86,6 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override; - // ash::AcceleratorController::Observer: - void OnActionPerformed(AcceleratorAction action) override; - FullRestoreAppLaunchHandler* app_launch_handler() { return app_launch_handler_.get(); } @@ -160,10 +154,6 @@ content::NotificationRegistrar notification_registrar_; - base::ScopedObservation<ash::AcceleratorController, - ash::AcceleratorController::Observer> - accelerator_controller_observer_{this}; - base::WeakPtrFactory<FullRestoreService> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ash/login/screens/error_screen.cc b/chrome/browser/ash/login/screens/error_screen.cc index cefa0b3..38ac42f 100644 --- a/chrome/browser/ash/login/screens/error_screen.cc +++ b/chrome/browser/ash/login/screens/error_screen.cc
@@ -39,7 +39,6 @@ #include "chromeos/network/portal_detector/network_portal_detector_strategy.h" #include "components/session_manager/core/session_manager.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" -#include "content/public/browser/notification_service.h" #include "third_party/cros_system_api/dbus/service_constants.h" #include "ui/gfx/native_widget_types.h" @@ -192,10 +191,7 @@ void ErrorScreen::DoShow() { LOG(WARNING) << "Network error screen message is shown"; - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, - content::NotificationService::AllSources(), - content::NotificationService::NoDetails()); + session_manager::SessionManager::Get()->NotifyNetworkErrorScreenShown(); network_portal_detector::GetInstance()->SetStrategy( PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN); }
diff --git a/chrome/browser/ash/login/ui/login_display_host_webui.cc b/chrome/browser/ash/login/ui/login_display_host_webui.cc index c531c98..3fe58ce 100644 --- a/chrome/browser/ash/login/ui/login_display_host_webui.cc +++ b/chrome/browser/ash/login/ui/login_display_host_webui.cc
@@ -454,8 +454,8 @@ // these notifications. registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, content::NotificationService::AllSources()); - registrar_.Add(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, - content::NotificationService::AllSources()); + + session_observation_.Observe(session_manager::SessionManager::Get()); audio::SoundsManager* manager = audio::SoundsManager::Get(); ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); @@ -694,14 +694,12 @@ const content::NotificationDetails& details) { LoginDisplayHostCommon::Observe(type, source, details); - if (chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE == type || - chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN == type) { + if (chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE == type) { VLOG(1) << "Login WebUI >> WEBUI_VISIBLE"; ShowWebUI(); registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, content::NotificationService::AllSources()); - registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, - content::NotificationService::AllSources()); + session_observation_.Reset(); } } @@ -1076,6 +1074,14 @@ observers_.RemoveObserver(observer); } +void LoginDisplayHostWebUI::OnNetworkErrorScreenShown() { + VLOG(1) << "Login WebUI >> WEBUI_VISIBLE"; + ShowWebUI(); + registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()); + session_observation_.Reset(); +} + void LoginDisplayHostWebUI::PlayStartupSoundIfPossible() { if (!need_to_play_startup_sound_ || oobe_startup_sound_played_) return;
diff --git a/chrome/browser/ash/login/ui/login_display_host_webui.h b/chrome/browser/ash/login/ui/login_display_host_webui.h index f7f7bcc..53f62ba 100644 --- a/chrome/browser/ash/login/ui/login_display_host_webui.h +++ b/chrome/browser/ash/login/ui/login_display_host_webui.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/scoped_observation.h" #include "base/timer/elapsed_timer.h" #include "chrome/browser/ash/login/existing_user_controller.h" #include "chrome/browser/ash/login/oobe_configuration.h" @@ -23,6 +24,8 @@ #include "chrome/browser/ash/login/wizard_controller.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" #include "chromeos/dbus/session_manager/session_manager_client.h" +#include "components/session_manager/core/session_manager.h" +#include "components/session_manager/core/session_manager_observer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_observer.h" @@ -46,6 +49,7 @@ // WebUI signals ready (via NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE) or there // is a network error (via NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN). class LoginDisplayHostWebUI : public LoginDisplayHostCommon, + public session_manager::SessionManagerObserver, public content::WebContentsObserver, public chromeos::SessionManagerClient::Observer, public CrasAudioHandler::AudioObserver, @@ -93,6 +97,9 @@ void AddObserver(LoginDisplayHost::Observer* observer) override; void RemoveObserver(LoginDisplayHost::Observer* observer) override; + // session_manager::SessionManagerObserver: + void OnNetworkErrorScreenShown() override; + // Trace id for ShowLoginWebUI event (since there exists at most one login // WebUI at a time). static const char kShowLoginWebUIid[]; @@ -270,6 +277,10 @@ // Measures OOBE WebUI load time. absl::optional<base::ElapsedTimer> oobe_load_timer_; + base::ScopedObservation<session_manager::SessionManager, + session_manager::SessionManagerObserver> + session_observation_{this}; + display::ScopedDisplayObserver display_observer_{this}; base::ObserverList<LoginDisplayHost::Observer> observers_;
diff --git a/chrome/browser/ash/login/ui/webui_login_view.cc b/chrome/browser/ash/login/ui/webui_login_view.cc index 0ee0772..a8f85648 100644 --- a/chrome/browser/ash/login/ui/webui_login_view.cc +++ b/chrome/browser/ash/login/ui/webui_login_view.cc
@@ -38,7 +38,6 @@ #include "chromeos/network/network_state_handler.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/password_manager/core/browser/password_manager.h" -#include "components/session_manager/core/session_manager.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_frame_host.h" @@ -96,11 +95,11 @@ registrar_.Add(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, content::NotificationService::AllSources()); - registrar_.Add(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, - content::NotificationService::AllSources()); registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, content::NotificationService::AllSources()); + session_observation_.Observe(session_manager::SessionManager::Get()); + for (size_t i = 0; i < kLoginAcceleratorDataLength; ++i) { ui::Accelerator accelerator(kLoginAcceleratorData[i].keycode, kLoginAcceleratorData[i].modifiers); @@ -305,13 +304,11 @@ const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { - case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: - case chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN: { + case chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE: { OnLoginPromptVisible(); registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, content::NotificationService::AllSources()); - registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, - content::NotificationService::AllSources()); + session_observation_.Reset(); break; } case chrome::NOTIFICATION_APP_TERMINATING: { @@ -329,6 +326,13 @@ } } +void WebUILoginView::OnNetworkErrorScreenShown() { + OnLoginPromptVisible(); + registrar_.Remove(this, chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE, + content::NotificationService::AllSources()); + session_observation_.Reset(); +} + //////////////////////////////////////////////////////////////////////////////// // ChromeKeyboardControllerClient::Observer
diff --git a/chrome/browser/ash/login/ui/webui_login_view.h b/chrome/browser/ash/login/ui/webui_login_view.h index 8b85b900..2bc27ba 100644 --- a/chrome/browser/ash/login/ui/webui_login_view.h +++ b/chrome/browser/ash/login/ui/webui_login_view.h
@@ -13,8 +13,11 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" +#include "base/scoped_observation.h" #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h" #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h" +#include "components/session_manager/core/session_manager.h" +#include "components/session_manager/core/session_manager_observer.h" // TODO(https://crbug.com/1164001): use forward declaration. #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" #include "components/web_modal/web_contents_modal_dialog_host.h" @@ -46,6 +49,7 @@ public ChromeKeyboardControllerClient::Observer, public content::WebContentsDelegate, public content::NotificationObserver, + public session_manager::SessionManagerObserver, public ChromeWebModalDialogManagerDelegate, public web_modal::WebContentsModalDialogHost, public SystemTrayObserver { @@ -133,6 +137,9 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override; + // session_manager::SessionManagerObserver: + void OnNetworkErrorScreenShown() override; + private: // Map type for the accelerator-to-identifier map. typedef std::map<ui::Accelerator, LoginAcceleratorAction> AccelMap; @@ -169,6 +176,9 @@ content::NotificationRegistrar registrar_; + base::ScopedObservation<session_manager::SessionManager, + session_manager::SessionManagerObserver> + session_observation_{this}; // WebView configuration options. const WebViewSettings settings_;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 8f4c3a3..e7c06a1 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -350,7 +350,6 @@ <include name="IDR_ADD_SUPERVISION_NETWORK_UNAVAILABLE_SVG" file="resources\chromeos\add_supervision\images\network_unavailable.svg" type="BINDATA" /> <include name="IDR_ADD_SUPERVISION_UI_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\add_supervision\add_supervision_ui.js" use_base_dir="false" type="chrome_html" /> <include name="IDR_ADD_SUPERVISION_API_SERVER_JS" file="resources\chromeos\add_supervision\add_supervision_api_server.js" type="BINDATA" /> - <include name="IDR_ADD_SUPERVISION_POST_MESSAGE_API_JS" file="resources\chromeos\add_supervision\post_message_api.js" type="BINDATA" /> <include name="IDR_ADD_SUPERVISION_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\chromeos\add_supervision\add_supervision.mojom-lite.js" use_base_dir="false" type="BINDATA" /> </if> <if expr="chromeos">
diff --git a/chrome/browser/cart/cart_discount_fetcher.cc b/chrome/browser/cart/cart_discount_fetcher.cc index c0e2136..4b99dd2 100644 --- a/chrome/browser/cart/cart_discount_fetcher.cc +++ b/chrome/browser/cart/cart_discount_fetcher.cc
@@ -430,6 +430,12 @@ const base::Value* is_tester_value = value->FindKey("externalTester"); if (is_tester_value && is_tester_value->is_bool()) { is_tester = is_tester_value->GetBool(); + } else { + const base::Value* is_internal_tester_value = + value->FindKey("internalTester"); + if (is_internal_tester_value && is_internal_tester_value->is_bool()) { + is_tester = is_internal_tester_value->GetBool(); + } } std::move(callback).Run(std::move(cart_discount_map), is_tester);
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h index dbcaa4ce..361775c3 100644 --- a/chrome/browser/chrome_notification_types.h +++ b/chrome/browser/chrome_notification_types.h
@@ -94,11 +94,6 @@ // Misc -------------------------------------------------------------------- #if BUILDFLAG(IS_CHROMEOS_ASH) - // Sent when a network error message is displayed on the WebUI login screen. - // First paint event of this fires NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE. - // TODO(https://crbug.com/1174791): Remove. - NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN, - // Sent when the specific part of login/lock WebUI is considered to be // visible. That moment is tracked as the first paint event after one of the: // NOTIFICATION_LOGIN_NETWORK_ERROR_SHOWN
diff --git a/chrome/browser/chromeos/android_sms/fcm_connection_establisher.h b/chrome/browser/chromeos/android_sms/fcm_connection_establisher.h index 40fe8ac..aa21b4fa 100644 --- a/chrome/browser/chromeos/android_sms/fcm_connection_establisher.h +++ b/chrome/browser/chromeos/android_sms/fcm_connection_establisher.h
@@ -8,6 +8,7 @@ #include <memory> #include <string> +#include "base/containers/queue.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "chrome/browser/chromeos/android_sms/connection_establisher.h"
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_thumbnail.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_thumbnail.cc index b197c40..0d8893b 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_thumbnail.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_thumbnail.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/file_manager_private.h" #include "chrome/common/extensions/api/file_manager_private_internal.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom.h" #include "components/signin/public/identity_manager/consent_level.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/phonehub/browser_tabs_metadata_fetcher_impl_unittest.cc b/chrome/browser/chromeos/phonehub/browser_tabs_metadata_fetcher_impl_unittest.cc index 79f25d49..2e2e6f2 100644 --- a/chrome/browser/chromeos/phonehub/browser_tabs_metadata_fetcher_impl_unittest.cc +++ b/chrome/browser/chromeos/phonehub/browser_tabs_metadata_fetcher_impl_unittest.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/chromeos/phonehub/browser_tabs_metadata_fetcher_impl.h" +#include <deque> + #include "base/strings/utf_string_conversions.h" #include "chrome/common/webui_url_constants.h" #include "components/favicon/core/history_ui_favicon_request_handler.h"
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc index c9ec1187..4d80136 100644 --- a/chrome/browser/client_hints/client_hints_browsertest.cc +++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -2402,10 +2402,18 @@ absl::optional<std::string> ch_lang_ GUARDED_BY(ch_lang_lock_); }; +#if defined(OS_CHROMEOS) +// Flaky on the linux-chromeos-chrome try bot: http://crbug.com/1222742 +#define MAYBE_CriticalClientHintInRequestHeader \ + DISABLED_CriticalClientHintInRequestHeader +#else +#define MAYBE_CriticalClientHintInRequestHeader \ + CriticalClientHintInRequestHeader +#endif // Verify that setting Critical-CH in the response header causes the request to // be resent with the client hint included. IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest, - CriticalClientHintInRequestHeader) { + MAYBE_CriticalClientHintInRequestHeader) { blink::UserAgentMetadata ua = embedder_support::GetUserAgentMetadata(); // On the first navigation request, the client hints in the Critical-CH // should be set on the request header. @@ -2725,8 +2733,16 @@ /*critical_ch_ua_reduced_expected=*/false); } +#if defined(OS_CHROMEOS) +// Flaky on the linux-chromeos-chrome try bot: http://crbug.com/1222742 +#define MAYBE_CriticalChUaReducedWithValidOriginTrialToken \ + DISABLED_CriticalChUaReducedWithValidOriginTrialToken +#else +#define MAYBE_CriticalChUaReducedWithValidOriginTrialToken \ + CriticalChUaReducedWithValidOriginTrialToken +#endif IN_PROC_BROWSER_TEST_F(UaReducedOriginTrialBrowserTest, - CriticalChUaReducedWithValidOriginTrialToken) { + MAYBE_CriticalChUaReducedWithValidOriginTrialToken) { // The initial navigation also contains the Critical-CH header, so the // Sec-CH-UA-Reduced header should be set after the first navigation. NavigateTwiceAndCheckHeader(
diff --git a/chrome/browser/continuous_search/BUILD.gn b/chrome/browser/continuous_search/BUILD.gn index bb9d13c5..e94b396a 100644 --- a/chrome/browser/continuous_search/BUILD.gn +++ b/chrome/browser/continuous_search/BUILD.gn
@@ -39,6 +39,7 @@ "//services/network/public/mojom:url_loader_base_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_coordinatorlayout_coordinatorlayout_java", + "//third_party/androidx:androidx_core_core_java", "//third_party/androidx:androidx_recyclerview_recyclerview_java", "//ui/android:ui_full_java", "//url:gurl_java",
diff --git a/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_item.xml b/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_item.xml index ac37cd63..ecfd197 100644 --- a/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_item.xml +++ b/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_item.xml
@@ -8,5 +8,4 @@ android:id="@+id/csn_chip" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="center" - app:extendLateralPadding="true" /> \ No newline at end of file + android:gravity="center" /> \ No newline at end of file
diff --git a/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_provider.xml b/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_provider.xml index 28086f8..8861469 100644 --- a/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_provider.xml +++ b/chrome/browser/continuous_search/android/java/res/layout/continuous_search_list_provider.xml
@@ -9,8 +9,8 @@ android:id="@+id/continuous_search_provider_label" android:layout_width="wrap_content" android:layout_height="match_parent" - android:paddingStart="@dimen/csn_chip_list_side_padding" - android:paddingEnd="@dimen/csn_chip_list_side_padding" + android:paddingStart="@dimen/csn_chip_provider_button_padding" + android:paddingEnd="@dimen/csn_chip_provider_button_padding" android:maxLines="2" android:gravity="center_vertical" android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
diff --git a/chrome/browser/continuous_search/android/java/res/values/dimens.xml b/chrome/browser/continuous_search/android/java/res/values/dimens.xml index ef7bf8f..6545bab 100644 --- a/chrome/browser/continuous_search/android/java/res/values/dimens.xml +++ b/chrome/browser/continuous_search/android/java/res/values/dimens.xml
@@ -4,12 +4,13 @@ found in the LICENSE file. --> <resources xmlns:tools="http://schemas.android.com/tools"> - <dimen name="csn_chip_vertical_padding">5dp</dimen> - <dimen name="csn_chip_side_padding">@dimen/chip_element_leading_padding</dimen> - <dimen name="csn_chip_text_max_width">200dp</dimen> + <dimen name="csn_double_row_chip_vertical_padding">16dp</dimen> + <dimen name="csn_double_row_chip_side_padding">16dp</dimen> + <dimen name='csn_single_row_chip_side_padding'>4dp</dimen> + <dimen name="csn_chip_text_max_width">180dp</dimen> <dimen name="csn_chip_list_chip_spacing">4dp</dimen> - <dimen name="csn_chip_list_side_padding">8dp</dimen> - <dimen name="csn_chip_dismissal_button_padding">6dp</dimen> + <dimen name="csn_chip_provider_button_padding">12dp</dimen> + <dimen name="csn_chip_dismissal_button_padding">16dp</dimen> </resources>
diff --git a/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchChipView.java b/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchChipView.java index af2ce69..c4bdf22f 100644 --- a/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchChipView.java +++ b/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchChipView.java
@@ -12,6 +12,7 @@ import android.widget.TextView; import androidx.annotation.Px; +import androidx.core.view.ViewCompat; import org.chromium.ui.widget.ChipView; @@ -24,6 +25,10 @@ public ContinuousSearchChipView(Context context, AttributeSet attrs) { super(context, attrs); mIsTwoLineChipView = false; + // One-row chip padding modification. + int padding = + getResources().getDimensionPixelOffset(R.dimen.csn_single_row_chip_side_padding); + ViewCompat.setPaddingRelative(this, padding, 0, padding, 0); } /** @@ -41,14 +46,7 @@ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); layout.setOrientation(VERTICAL); - // Modify chip to accommodate vertically stacked TextViews - @Px - int sidePadding = getResources().getDimensionPixelSize(R.dimen.csn_chip_side_padding); - @Px - int verticalPadding = - getResources().getDimensionPixelSize(R.dimen.csn_chip_vertical_padding); - setPaddingRelative(sidePadding, getPaddingTop(), sidePadding, getPaddingBottom()); - layout.setPaddingRelative(0, verticalPadding, 0, verticalPadding); + // Modify TextViews to have them vertically stacked. setupTextView(primaryText); setupTextView(secondaryText); @@ -59,6 +57,16 @@ layout.addView(primaryText); layout.addView(secondaryText); addView(layout); + + // Adjust chip paddings + @Px + int sidePadding = + getResources().getDimensionPixelSize(R.dimen.csn_double_row_chip_side_padding); + @Px + int verticalPadding = + getResources().getDimensionPixelSize(R.dimen.csn_double_row_chip_vertical_padding); + ViewCompat.setPaddingRelative( + this, sidePadding, verticalPadding, sidePadding, verticalPadding); mIsTwoLineChipView = true; }
diff --git a/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListCoordinator.java b/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListCoordinator.java index dec5e3e..9b75954 100644 --- a/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListCoordinator.java +++ b/chrome/browser/continuous_search/android/java/src/org/chromium/chrome/browser/continuous_search/ContinuousSearchListCoordinator.java
@@ -167,13 +167,10 @@ private static class SpaceItemDecoration extends ItemDecoration { private final int mChipSpacingPx; - private final int mSidePaddingPx; public SpaceItemDecoration(Resources resources) { mChipSpacingPx = (int) resources.getDimensionPixelSize(R.dimen.csn_chip_list_chip_spacing); - mSidePaddingPx = - (int) resources.getDimensionPixelSize(R.dimen.csn_chip_list_side_padding); } @Override @@ -182,10 +179,10 @@ boolean isFirst = position == 0; boolean isLast = position == parent.getAdapter().getItemCount() - 1; - // Provider icon/text already has the required padding so the first item doesn't need to - // have any. + // Border chip paddings are provided by the provider icon and the dismiss button so no + // need to add any paddings here. outRect.left = isFirst ? 0 : mChipSpacingPx; - outRect.right = isLast ? mSidePaddingPx : mChipSpacingPx; + outRect.right = isLast ? 0 : mChipSpacingPx; } } }
diff --git a/chrome/browser/dependency_injection/BUILD.gn b/chrome/browser/dependency_injection/BUILD.gn new file mode 100644 index 0000000..01f35779 --- /dev/null +++ b/chrome/browser/dependency_injection/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +android_library("java") { + sources = [ "android/java/src/org/chromium/chrome/browser/dependency_injection/ActivityScope.java" ] + deps = [ + "//base:base_java", + "//third_party/android_deps:dagger_java", + "//third_party/android_deps:javax_inject_javax_inject_java", + "//third_party/androidx:androidx_annotation_annotation_java", + "//third_party/androidx:androidx_core_core_java", + ] +}
diff --git a/chrome/browser/dependency_injection/DIR_METADATA b/chrome/browser/dependency_injection/DIR_METADATA new file mode 100644 index 0000000..7b9b438 --- /dev/null +++ b/chrome/browser/dependency_injection/DIR_METADATA
@@ -0,0 +1,4 @@ +monorail { + component: "Internals>Core" +} +os: ANDROID
diff --git a/chrome/browser/dependency_injection/OWNERS b/chrome/browser/dependency_injection/OWNERS new file mode 100644 index 0000000..e31d7a8 --- /dev/null +++ b/chrome/browser/dependency_injection/OWNERS
@@ -0,0 +1 @@ +file://chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ActivityScope.java b/chrome/browser/dependency_injection/android/java/src/org/chromium/chrome/browser/dependency_injection/ActivityScope.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ActivityScope.java rename to chrome/browser/dependency_injection/android/java/src/org/chromium/chrome/browser/dependency_injection/ActivityScope.java
diff --git a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc index 0aed593..46b08aa 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.cc
@@ -71,6 +71,8 @@ // intentionally distinct from kFileSystemBoxFindFolderResponseFolderId above // to identify where the test flow gets the folder_id from. const char kFileSystemBoxFolderIdInPref[] = "1337"; +const char kFileSystemBoxFolderIdInPrefUrl[] = + "https://app.box.com/folder/1337"; const char kFileSystemBoxFindFolderResponseEmptyEntriesList[] = R"({ "entries": [ @@ -294,7 +296,4 @@ const char kFileSystemBoxUploadResponseFileUrl[] = "https://app.box.com/file/314159"; -const char kFileSystemBoxUploadResponseFolderUrl[] = - "https://app.box.com/folder/1337"; - } // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h index 13ee3a7..ed5b58c 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h +++ b/chrome/browser/enterprise/connectors/file_system/box_api_call_test_helper.h
@@ -48,6 +48,8 @@ // Saved folder id extracted from the kFileSystemUploadFolderIdPref pref. extern const char kFileSystemBoxFolderIdInPref[]; +// Expected folder url for the uploaded file with kFileSystemBoxFolderIdInPref. +extern const char kFileSystemBoxFolderIdInPrefUrl[]; // For Box Chunked Uploads ///////////////////////////////////////////////////// @@ -79,8 +81,7 @@ // Expected file id/url extracted from above. extern const char kFileSystemBoxUploadResponseFileId[]; extern const char kFileSystemBoxUploadResponseFileUrl[]; -// Expected folder url for the uploaded file with kFileSystemBoxFolderIdInPref. -extern const char kFileSystemBoxUploadResponseFolderUrl[]; + } // namespace enterprise_connectors #endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_FILE_SYSTEM_BOX_API_CALL_TEST_HELPER_H_
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader.cc b/chrome/browser/enterprise/connectors/file_system/box_uploader.cc index 9e1bac0..2e5a750 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader.cc
@@ -145,6 +145,7 @@ authentication_retry_callback_ = std::move(authen_retry_callback); progress_update_cb_ = std::move(progress_update_cb); upload_complete_cb_ = std::move(upload_complete_cb); + SendProgressUpdate(); SetCurrentApiCall(GetFolderId().empty() ? MakeFindUpstreamFolderApiCall() : MakePreflightCheckApiCall()); }
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc index aeddd93..271e8d3 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc
@@ -156,6 +156,7 @@ const download::DownloadItemRenameProgressUpdate& update) { ++progress_update_cb_called_; file_name_reported_back_ = update.target_file_name; + reroute_info_reported_back_ = update.reroute_info; } void BoxUploaderTestBase::OnUploaderFinished(
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h index e28e862..96d9cd5 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h
@@ -26,6 +26,8 @@ class BoxUploader; +using State = download::DownloadItem::DownloadState; + class BoxUploaderTestBase : public testing::Test { public: explicit BoxUploaderTestBase(base::FilePath::StringPieceType file_name = @@ -35,8 +37,6 @@ base::FilePath GetFilePath() const; protected: - using State = download::DownloadItem::DownloadState; - virtual void CreateTemporaryFile(); void CreateTemporaryFileWithContent(std::string content); void InitFolderIdInPrefs(std::string folder_id); @@ -87,6 +87,7 @@ download::DownloadInterruptReason reason_{ download::DOWNLOAD_INTERRUPT_REASON_NONE}; base::FilePath file_name_reported_back_; + DownloadItemRerouteInfo reroute_info_reported_back_; private: content::BrowserTaskEnvironment task_environment_;
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc b/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc index 1738f4eb..3c850049 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc
@@ -91,7 +91,7 @@ ASSERT_EQ(uploader_->GetUploadedFileUrl(), GURL(kFileSystemBoxUploadResponseFileUrl)); ASSERT_EQ(uploader_->GetDestinationFolderUrl(), - GURL(kFileSystemBoxUploadResponseFolderUrl)); + GURL(kFileSystemBoxFolderIdInPrefUrl)); ASSERT_FALSE(authentication_retry_); EXPECT_FALSE(download_thread_cb_called_); @@ -154,8 +154,9 @@ // deleted as part of error handling. Otherwise, upload API call flow got // InterceptedPreUpload(), so file was not deleted. EXPECT_EQ(upload_initiated_, base::PathExists(GetFilePath())); - // Only 1 update in StartUpload() when PreflightCheck succeeds. - EXPECT_EQ(progress_update_cb_called_, 1); + // 1 update in Init(), and 1 update in StartUpload() when PreflightCheck + // succeeds. + EXPECT_EQ(progress_update_cb_called_, 2); } void InterceptedPreUpload() { @@ -214,7 +215,7 @@ // Should be retrying authentication, no report via callback yet. ASSERT_EQ(authentication_retry_, 1); - ASSERT_EQ(progress_update_cb_called_, 0); + ASSERT_EQ(progress_update_cb_called_, 1); // 1 in Init(). EXPECT_FALSE(upload_initiated_); EXPECT_FALSE(download_thread_cb_called_); EXPECT_EQ(uploader_->GetFolderIdForTesting(), ""); @@ -498,7 +499,7 @@ // Need to retry authentication, so no report via callback yet. ASSERT_EQ(authentication_retry_, 1); - ASSERT_EQ(progress_update_cb_called_, 0); + ASSERT_EQ(progress_update_cb_called_, 1); // 1 in Init(). ASSERT_FALSE(upload_initiated_); EXPECT_FALSE(download_thread_cb_called_); EXPECT_FALSE(upload_success_); @@ -582,9 +583,9 @@ // If upload was not initiated due to some error, file should've been // deleted as part of error handling. EXPECT_FALSE(base::PathExists(GetFilePath())); - // 1 update in StartUpload() when PreflightCheck succeeds, and 1 update in - // OnApiCallFlowDone(). - EXPECT_EQ(progress_update_cb_called_, 2); + // 1 update in Init(), 1 update in StartUpload() when PreflightCheck + // succeeds, and 1 update in OnApiCallFlowDone(). + EXPECT_EQ(progress_update_cb_called_, 3); } std::unique_ptr<BoxUploaderForNetErrorTest> uploader_; }; @@ -701,56 +702,107 @@ ASSERT_FALSE(upload_success_); } -TEST_F(BoxUploader_FileDeleteTest, LoadFromReroutedInfo_InProgress) { - test_item_.SetState(State::IN_PROGRESS); +DownloadItemRerouteInfo MakeDownloadItemRerouteInfo( + std::string folder_id = std::string(), + std::string file_id = std::string()) { + DownloadItemRerouteInfo info; + info.set_service_provider(BoxUploader::kServiceProvider); + info.mutable_box(); // Set the oneof to be Box. + if (!folder_id.empty()) + info.mutable_box()->set_folder_id(folder_id); + if (!file_id.empty()) + info.mutable_box()->set_file_id(file_id); + return info; +} + +class BoxUploader_FromRerouteInfoTestBase : public BoxUploaderTestBase { + public: + BoxUploader_FromRerouteInfoTestBase() + : BoxUploaderTestBase( + FILE_PATH_LITERAL("box_uploader_from_reroute_info_test.txt")) {} + + protected: + void TearDown() override { + EXPECT_EQ(authentication_retry_, 0); + EXPECT_EQ(progress_update_cb_called_ > 0, download_thread_cb_called_); + EXPECT_FALSE(test_item_.GetFileExternallyRemoved()); + // Ended with no local temporary file. + ASSERT_FALSE(base::PathExists(GetFilePath())); + } + + std::unique_ptr<BoxUploader> uploader_; +}; + +class BoxUploader_IncompleteItemFromRerouteInfoTest + : public BoxUploader_FromRerouteInfoTestBase, + public testing::WithParamInterface<State> {}; + +TEST_P(BoxUploader_IncompleteItemFromRerouteInfoTest, RetryUpload) { + // Skip COMPLETE to allow Range() to generate all other enum values. + if (GetParam() == State::COMPLETE) + return SUCCEED(); + CreateTemporaryFile(); - DownloadItemRerouteInfo rerouted_info; - rerouted_info.set_service_provider(BoxUploader::kServiceProvider); - rerouted_info.mutable_box(); // set the oneof to be box; - test_item_.SetRerouteInfo(rerouted_info); + test_item_.SetState(GetParam()); + DownloadItemRerouteInfo reroute_info = MakeDownloadItemRerouteInfo(); + test_item_.SetRerouteInfo(reroute_info); + uploader_ = BoxUploader::Create(&test_item_); + ASSERT_TRUE(uploader_); - // Recreate uploader to load rerouted info. - uploader_ = std::make_unique<BoxUploaderForFileDeleteTest>(&test_item_); + // Assume there is already a folder_id stored in prefs, preflight check + // passes, and upload request succeeds. + InitFolderIdInPrefs(kFileSystemBoxFolderIdInPref); + AddFetchResult(kFileSystemBoxPreflightCheckUrl, net::HTTP_OK); + AddFetchResult(kFileSystemBoxDirectUploadUrl, net::HTTP_CREATED, + kFileSystemBoxUploadResponseBody); + + // Try uploading. InitUploader(uploader_.get()); InitQuitClosure(); uploader_->TryTask(url_factory_, "test_token"); RunWithQuitClosure(); - ASSERT_TRUE(uploader_); - ASSERT_EQ(uploader_->GetUploadedFileUrl(), - GURL(kFileSystemBoxUploadResponseFileUrl)); - // TODO(https://crbug.com/1215847) Update to set folder id and check folder - // link too. - - ASSERT_FALSE(authentication_retry_); - EXPECT_TRUE(download_thread_cb_called_); - EXPECT_TRUE(progress_update_cb_called_); - ASSERT_TRUE(upload_success_); - EXPECT_FALSE(base::PathExists(GetFilePath())); // File deleted. -} - -TEST_F(BoxUploader_FileDeleteTest, LoadFromReroutedInfo_Complete) { - test_item_.SetState(State::COMPLETE); - - DownloadItemRerouteInfo rerouted_info; - rerouted_info.set_service_provider(BoxUploader::kServiceProvider); - rerouted_info.mutable_box()->set_file_id(kFileSystemBoxUploadResponseFileId); - rerouted_info.mutable_box()->set_folder_id(kFileSystemBoxFolderIdInPref); - test_item_.SetRerouteInfo(rerouted_info); - - // Recreate uploader to load rerouted info. - uploader_ = std::make_unique<BoxUploaderForFileDeleteTest>(&test_item_); - ASSERT_TRUE(uploader_); + ASSERT_EQ(reroute_info_reported_back_.box().file_id(), + kFileSystemBoxUploadResponseFileId); + ASSERT_EQ(reroute_info_reported_back_.box().folder_id(), + kFileSystemBoxFolderIdInPref); ASSERT_EQ(uploader_->GetUploadedFileUrl(), GURL(kFileSystemBoxUploadResponseFileUrl)); ASSERT_EQ(uploader_->GetDestinationFolderUrl(), - GURL(kFileSystemBoxUploadResponseFolderUrl)); + GURL(kFileSystemBoxFolderIdInPrefUrl)); ASSERT_FALSE(authentication_retry_); + EXPECT_TRUE(download_thread_cb_called_); + EXPECT_GE(progress_update_cb_called_, 2); + ASSERT_TRUE(upload_success_); +} + +INSTANTIATE_TEST_CASE_P(, + BoxUploader_IncompleteItemFromRerouteInfoTest, + testing::Range(State::IN_PROGRESS, + State::MAX_DOWNLOAD_STATE)); + +class BoxUploader_CompletedItemFromRerouteInfoTest + : public BoxUploader_FromRerouteInfoTestBase {}; + +TEST_F(BoxUploader_CompletedItemFromRerouteInfoTest, Normal) { + test_item_.SetState(State::COMPLETE); + const std::string folder_id = "357321"; + const std::string file_id = "13576123"; + DownloadItemRerouteInfo reroute_info = + MakeDownloadItemRerouteInfo(folder_id, file_id); + test_item_.SetRerouteInfo(reroute_info); + + uploader_ = BoxUploader::Create(&test_item_); + ASSERT_TRUE(uploader_); + ASSERT_EQ(uploader_->GetUploadedFileUrl(), + BoxApiCallFlow::MakeUrlToShowFile(file_id)); + ASSERT_EQ(uploader_->GetDestinationFolderUrl(), + BoxApiCallFlow::MakeUrlToShowFolder(folder_id)); + EXPECT_FALSE(download_thread_cb_called_); // No upload call was made. EXPECT_FALSE(progress_update_cb_called_); - EXPECT_FALSE(base::PathExists(GetFilePath())); // File not created. } //////////////////////////////////////////////////////////////////////////////// @@ -798,7 +850,7 @@ EXPECT_EQ(uploader_->GetUploadedFileUrl(), kFileSystemBoxUploadResponseFileUrl); EXPECT_EQ(uploader_->GetDestinationFolderUrl(), - kFileSystemBoxUploadResponseFolderUrl); + kFileSystemBoxFolderIdInPrefUrl); } TEST_F(BoxDirectUploaderTest, FileReadFailure) { @@ -813,7 +865,7 @@ EXPECT_FALSE(upload_success_); EXPECT_TRUE(uploader_->GetUploadedFileUrl().is_empty()); EXPECT_EQ(uploader_->GetDestinationFolderUrl(), - kFileSystemBoxUploadResponseFolderUrl); + kFileSystemBoxFolderIdInPrefUrl); ASSERT_REASON_EQ(FILE_FAILED, reason_); }
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 3c3358a..004ceba7 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -1268,8 +1268,6 @@ } if (enable_basic_printing && (is_win || is_mac || is_linux || is_chromeos)) { - # Needed by files which include //chrome/browser/service_sandbox_type.h. - # Inclusion of print_backend_service_manager.h depends on this. # TODO(crbug.com/1213762) Replace this with more accurate dependency # once //chrome/browser/printing build is able to be cleanly targeted. deps += [ "//chrome/services/printing/public/mojom" ]
diff --git a/chrome/browser/extensions/api/cookies/cookies_unittest.cc b/chrome/browser/extensions/api/cookies/cookies_unittest.cc index 1c31973..ff2856a8e3 100644 --- a/chrome/browser/extensions/api/cookies/cookies_unittest.cc +++ b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
@@ -9,6 +9,7 @@ #include <memory> #include <utility> +#include <vector> #include "base/cxx17_backports.h" #include "base/values.h" @@ -173,10 +174,10 @@ for (size_t i = 0; i < base::size(tests); ++i) { // Build up the Params struct. - base::ListValue args; - auto dict = std::make_unique<base::DictionaryValue>(); - dict->SetString(keys::kDomainKey, std::string(tests[i].filter)); - args.Set(0, std::move(dict)); + std::vector<base::Value> args; + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey(keys::kDomainKey, std::string(tests[i].filter)); + args.emplace_back(std::move(dict)); std::unique_ptr<GetAll::Params> params(GetAll::Params::Create(args)); cookies_helpers::MatchFilter filter(¶ms->details);
diff --git a/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chrome/browser/extensions/api/debugger/debugger_apitest.cc index 7aaffd3d..432de4bc8 100644 --- a/chrome/browser/extensions/api/debugger/debugger_apitest.cc +++ b/chrome/browser/extensions/api/debugger/debugger_apitest.cc
@@ -117,13 +117,13 @@ std::unique_ptr<base::Value> value( extension_function_test_utils::RunFunctionAndReturnSingleResult( get_targets_function.get(), "[]", browser())); - base::ListValue* targets = nullptr; - EXPECT_TRUE(value->GetAsList(&targets)); + EXPECT_TRUE(value->is_list()); + const base::ListValue& targets = base::Value::AsListValue(*value); std::string debugger_target_id; - for (size_t i = 0; i < targets->GetSize(); ++i) { - base::DictionaryValue* target_dict = nullptr; - EXPECT_TRUE(targets->GetDictionary(i, &target_dict)); + for (size_t i = 0; i < targets.GetSize(); ++i) { + const base::DictionaryValue* target_dict = nullptr; + EXPECT_TRUE(targets.GetDictionary(i, &target_dict)); int id = -1; if (target_dict->GetInteger("tabId", &id) && id == tab_id) { EXPECT_TRUE(target_dict->GetString("id", &debugger_target_id));
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc index d8dee11..df9327e 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
@@ -43,16 +43,14 @@ const base::Value& value, std::string* error) { std::vector<std::string> css_rules; - const base::ListValue* css_rules_value = nullptr; - if (value.GetAsList(&css_rules_value)) { - for (size_t i = 0; i < css_rules_value->GetSize(); ++i) { - std::string css_rule; - if (!css_rules_value->GetString(i, &css_rule)) { + if (value.is_list()) { + for (const base::Value& css_rule_value : value.GetList()) { + if (!css_rule_value.is_string()) { *error = base::StringPrintf(kCssInvalidTypeOfParameter, declarative_content_constants::kCss); return nullptr; } - css_rules.push_back(css_rule); + css_rules.push_back(css_rule_value.GetString()); } } else { *error = base::StringPrintf(kCssInvalidTypeOfParameter,
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index ca243f02..35dbb319 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -71,6 +71,7 @@ #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_operation_runner.h" #include "storage/browser/file_system/file_system_url.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/page_transition_types.h" #include "url/origin.h" @@ -1181,9 +1182,8 @@ std::unique_ptr<base::Value> result( RunFunctionAndReturnResult(new DownloadsSearchFunction(), "[{}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); } // Test that file existence check should be performed after search. @@ -1201,9 +1201,9 @@ std::unique_ptr<base::Value> result( RunFunctionAndReturnResult(new DownloadsSearchFunction(), "[{}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = nullptr; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); + // Check file removal update will eventually come. WaitForEvent() will // immediately return if the file is already removed. content::DownloadUpdatedObserver( @@ -1248,14 +1248,13 @@ std::unique_ptr<base::Value> result(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{\"filenameRegex\": \"foobar\"}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); - base::DictionaryValue* item_value = NULL; - ASSERT_TRUE(result_list->GetDictionary(0, &item_value)); - int item_id = -1; - ASSERT_TRUE(item_value->GetInteger("id", &item_id)); - ASSERT_EQ(all_downloads[0]->GetId(), static_cast<uint32_t>(item_id)); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); + const base::Value& item_value = result->GetList()[0]; + ASSERT_TRUE(item_value.is_dict()); + absl::optional<int> item_id = item_value.FindIntKey("id"); + ASSERT_TRUE(item_id); + ASSERT_EQ(all_downloads[0]->GetId(), static_cast<uint32_t>(*item_id)); } // Test the |id| parameter for search(). @@ -1269,14 +1268,13 @@ new DownloadsSearchFunction(), base::StringPrintf("[{\"id\": %u}]", items[0]->GetId()))); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); - base::DictionaryValue* item_value = NULL; - ASSERT_TRUE(result_list->GetDictionary(0, &item_value)); - int item_id = -1; - ASSERT_TRUE(item_value->GetInteger("id", &item_id)); - ASSERT_EQ(items[0]->GetId(), static_cast<uint32_t>(item_id)); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); + const base::Value& item_value = result->GetList()[0]; + ASSERT_TRUE(item_value.is_dict()); + absl::optional<int> item_id = item_value.FindIntKey("id"); + ASSERT_TRUE(item_id); + ASSERT_EQ(items[0]->GetId(), static_cast<uint32_t>(*item_id)); } // Test specifying both the |id| and |filename| parameters for search(). @@ -1291,9 +1289,8 @@ RunFunctionAndReturnResult(new DownloadsSearchFunction(), "[{\"id\": 0, \"filename\": \"foobar\"}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(0UL, result_list->GetSize()); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(0UL, result->GetList().size()); } // Test a single |orderBy| parameter for search(). @@ -1311,19 +1308,19 @@ std::unique_ptr<base::Value> result(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{\"orderBy\": [\"filename\"]}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(2UL, result_list->GetSize()); - base::DictionaryValue* item0_value = NULL; - base::DictionaryValue* item1_value = NULL; - ASSERT_TRUE(result_list->GetDictionary(0, &item0_value)); - ASSERT_TRUE(result_list->GetDictionary(1, &item1_value)); - std::string item0_name, item1_name; - ASSERT_TRUE(item0_value->GetString("filename", &item0_name)); - ASSERT_TRUE(item1_value->GetString("filename", &item1_name)); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(2UL, result->GetList().size()); + const base::Value& item0_value = result->GetList()[0]; + const base::Value& item1_value = result->GetList()[1]; + ASSERT_TRUE(item0_value.is_dict()); + ASSERT_TRUE(item1_value.is_dict()); + const std::string* item0_name = item0_value.FindStringKey("filename"); + const std::string* item1_name = item1_value.FindStringKey("filename"); + ASSERT_TRUE(item0_name); + ASSERT_TRUE(item1_name); ASSERT_GT(items[0]->GetTargetFilePath().value(), items[1]->GetTargetFilePath().value()); - ASSERT_LT(item0_name, item1_name); + ASSERT_LT(*item0_name, *item1_name); } // Test specifying an empty |orderBy| parameter for search(). @@ -1341,16 +1338,16 @@ std::unique_ptr<base::Value> result(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{\"orderBy\": []}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(2UL, result_list->GetSize()); - base::DictionaryValue* item0_value = NULL; - base::DictionaryValue* item1_value = NULL; - ASSERT_TRUE(result_list->GetDictionary(0, &item0_value)); - ASSERT_TRUE(result_list->GetDictionary(1, &item1_value)); - std::string item0_name, item1_name; - ASSERT_TRUE(item0_value->GetString("filename", &item0_name)); - ASSERT_TRUE(item1_value->GetString("filename", &item1_name)); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(2UL, result->GetList().size()); + const base::Value& item0_value = result->GetList()[0]; + const base::Value& item1_value = result->GetList()[1]; + ASSERT_TRUE(item0_value.is_dict()); + ASSERT_TRUE(item1_value.is_dict()); + const std::string* item0_name = item0_value.FindStringKey("filename"); + const std::string* item1_name = item1_value.FindStringKey("filename"); + ASSERT_TRUE(item0_name); + ASSERT_TRUE(item1_name); ASSERT_GT(items[0]->GetTargetFilePath().value(), items[1]->GetTargetFilePath().value()); // The order of results when orderBy is empty is unspecified. When there are @@ -1375,9 +1372,8 @@ std::unique_ptr<base::Value> result(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{\"danger\": \"content\"}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); } // Test the |state| option for search(). @@ -1392,9 +1388,8 @@ std::unique_ptr<base::Value> result(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{\"state\": \"in_progress\"}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); } // Test the |limit| option for search(). @@ -1407,9 +1402,8 @@ std::unique_ptr<base::Value> result(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{\"limit\": 1}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); } // Test invalid search parameters. @@ -1452,14 +1446,13 @@ "\"orderBy\": [\"filename\"], " "\"limit\": 1}]")); ASSERT_TRUE(result.get()); - base::ListValue* result_list = NULL; - ASSERT_TRUE(result->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); - base::DictionaryValue* item_value = NULL; - ASSERT_TRUE(result_list->GetDictionary(0, &item_value)); - std::string item_name; - ASSERT_TRUE(item_value->GetString("filename", &item_name)); - ASSERT_EQ(items[2]->GetTargetFilePath().AsUTF8Unsafe(), item_name); + ASSERT_TRUE(result->is_list()); + ASSERT_EQ(1UL, result->GetList().size()); + const base::Value& item_value = result->GetList()[0]; + ASSERT_TRUE(item_value.is_dict()); + const std::string* item_name = item_value.FindStringKey("filename"); + ASSERT_TRUE(item_name); + ASSERT_EQ(items[2]->GetTargetFilePath().AsUTF8Unsafe(), *item_name); } // Test that incognito downloads are only visible in incognito contexts, and @@ -1470,13 +1463,7 @@ DownloadExtensionTest, DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) { std::unique_ptr<base::Value> result_value; - base::ListValue* result_list = NULL; - base::DictionaryValue* result_dict = NULL; - std::string filename; - bool is_incognito = false; std::string error; - std::string on_item_arg; - std::string off_item_arg; std::string result_string; // Set up one on-record item and one off-record item. @@ -1486,12 +1473,12 @@ GoOffTheRecord(); DownloadItem* off_item = CreateFirstSlowTestDownload(); ASSERT_TRUE(off_item); - off_item_arg = DownloadItemIdAsArgList(off_item); + const std::string off_item_arg = DownloadItemIdAsArgList(off_item); GoOnTheRecord(); DownloadItem* on_item = CreateSecondSlowTestDownload(); ASSERT_TRUE(on_item); - on_item_arg = DownloadItemIdAsArgList(on_item); + const std::string on_item_arg = DownloadItemIdAsArgList(on_item); ASSERT_TRUE(on_item->GetTargetFilePath() != off_item->GetTargetFilePath()); // Extensions running in the incognito window should have access to both @@ -1500,20 +1487,30 @@ result_value.reset(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{}]")); ASSERT_TRUE(result_value.get()); - ASSERT_TRUE(result_value->GetAsList(&result_list)); - ASSERT_EQ(2UL, result_list->GetSize()); - ASSERT_TRUE(result_list->GetDictionary(0, &result_dict)); - ASSERT_TRUE(result_dict->GetString("filename", &filename)); - ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito)); - EXPECT_TRUE(on_item->GetTargetFilePath() == - base::FilePath::FromUTF8Unsafe(filename)); - EXPECT_FALSE(is_incognito); - ASSERT_TRUE(result_list->GetDictionary(1, &result_dict)); - ASSERT_TRUE(result_dict->GetString("filename", &filename)); - ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito)); - EXPECT_TRUE(off_item->GetTargetFilePath() == - base::FilePath::FromUTF8Unsafe(filename)); - EXPECT_TRUE(is_incognito); + ASSERT_TRUE(result_value->is_list()); + ASSERT_EQ(2UL, result_value->GetList().size()); + { + const base::Value& result_dict = result_value->GetList()[0]; + ASSERT_TRUE(result_dict.is_dict()); + const std::string* filename = result_dict.FindStringKey("filename"); + ASSERT_TRUE(filename); + absl::optional<bool> is_incognito = result_dict.FindBoolKey("incognito"); + ASSERT_TRUE(is_incognito.has_value()); + EXPECT_TRUE(on_item->GetTargetFilePath() == + base::FilePath::FromUTF8Unsafe(*filename)); + EXPECT_FALSE(is_incognito.value()); + } + { + const base::Value& result_dict = result_value->GetList()[1]; + ASSERT_TRUE(result_dict.is_dict()); + const std::string* filename = result_dict.FindStringKey("filename"); + ASSERT_TRUE(filename); + absl::optional<bool> is_incognito = result_dict.FindBoolKey("incognito"); + ASSERT_TRUE(is_incognito.has_value()); + EXPECT_TRUE(off_item->GetTargetFilePath() == + base::FilePath::FromUTF8Unsafe(*filename)); + EXPECT_TRUE(is_incognito.value()); + } // Extensions running in the on-record window should have access only to the // on-record item. @@ -1521,14 +1518,19 @@ result_value.reset(RunFunctionAndReturnResult( new DownloadsSearchFunction(), "[{}]")); ASSERT_TRUE(result_value.get()); - ASSERT_TRUE(result_value->GetAsList(&result_list)); - ASSERT_EQ(1UL, result_list->GetSize()); - ASSERT_TRUE(result_list->GetDictionary(0, &result_dict)); - ASSERT_TRUE(result_dict->GetString("filename", &filename)); - EXPECT_TRUE(on_item->GetTargetFilePath() == - base::FilePath::FromUTF8Unsafe(filename)); - ASSERT_TRUE(result_dict->GetBoolean("incognito", &is_incognito)); - EXPECT_FALSE(is_incognito); + ASSERT_TRUE(result_value->is_list()); + ASSERT_EQ(1UL, result_value->GetList().size()); + { + const base::Value& result_dict = result_value->GetList()[0]; + ASSERT_TRUE(result_dict.is_dict()); + const std::string* filename = result_dict.FindStringKey("filename"); + ASSERT_TRUE(filename); + EXPECT_TRUE(on_item->GetTargetFilePath() == + base::FilePath::FromUTF8Unsafe(*filename)); + absl::optional<bool> is_incognito = result_dict.FindBoolKey("incognito"); + ASSERT_TRUE(is_incognito.has_value()); + EXPECT_FALSE(is_incognito.value()); + } // Pausing/Resuming the off-record item while on the record should return an // error. Cancelling "non-existent" downloads is not an error.
diff --git a/chrome/browser/extensions/api/font_settings/font_settings_api.cc b/chrome/browser/extensions/api/font_settings/font_settings_api.cc index 60d10f006..afba024 100644 --- a/chrome/browser/extensions/api/font_settings/font_settings_api.cc +++ b/chrome/browser/extensions/api/font_settings/font_settings_api.cc
@@ -298,23 +298,23 @@ FontSettingsGetFontListFunction::CopyFontsToResult(base::ListValue* fonts) { std::unique_ptr<base::ListValue> result(new base::ListValue()); for (const auto& entry : fonts->GetList()) { - const base::ListValue* font_list_value; - if (!entry.GetAsList(&font_list_value)) { + if (!entry.is_list()) { NOTREACHED(); return Error(""); } + const base::Value::ConstListView font_list_value = entry.GetList(); - std::string name; - if (!font_list_value->GetString(0, &name)) { + if (font_list_value.size() < 2 || !font_list_value[0].is_string()) { NOTREACHED(); return Error(""); } + const std::string& name = font_list_value[0].GetString(); - std::string localized_name; - if (!font_list_value->GetString(1, &localized_name)) { + if (!font_list_value[1].is_string()) { NOTREACHED(); return Error(""); } + const std::string& localized_name = font_list_value[1].GetString(); std::unique_ptr<base::DictionaryValue> font_name( new base::DictionaryValue());
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc index f4ebc716..2416294f 100644 --- a/chrome/browser/extensions/api/identity/identity_apitest.cc +++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -79,6 +79,7 @@ #include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -139,10 +140,10 @@ content::BrowserContext* browser_context) { response_delegate_ = std::make_unique<api_test_utils::SendResponseHelper>(function); - std::unique_ptr<base::ListValue> parsed_args(utils::ParseList(args)); - ASSERT_TRUE(parsed_args.get()) + absl::optional<base::Value> parsed_args(utils::ParseList(args)); + ASSERT_TRUE(parsed_args) << "Could not parse extension function arguments: " << args; - function->SetArgs(base::Value::FromUniquePtrValue(std::move(parsed_args))); + function->SetArgs(std::move(*parsed_args)); if (!function->extension()) { scoped_refptr<const Extension> empty_extension(
diff --git a/chrome/browser/extensions/api/management/management_api_browsertest.cc b/chrome/browser/extensions/api/management/management_api_browsertest.cc index 7cd11d6..d48ef5f 100644 --- a/chrome/browser/extensions/api/management/management_api_browsertest.cc +++ b/chrome/browser/extensions/api/management/management_api_browsertest.cc
@@ -268,9 +268,8 @@ std::unique_ptr<base::Value> result( test_utils::RunFunctionAndReturnSingleResult(function.get(), "[]", browser())); - base::ListValue* list; - ASSERT_TRUE(result->GetAsList(&list)); - EXPECT_EQ(1U, list->GetSize()); + ASSERT_TRUE(result->is_list()); + EXPECT_EQ(1U, result->GetList().size()); // And it should continue to do so even after it crashes. ASSERT_TRUE(CrashEnabledExtension(extension->id())); @@ -278,8 +277,8 @@ function = new ManagementGetAllFunction(); result.reset(test_utils::RunFunctionAndReturnSingleResult(function.get(), "[]", browser())); - ASSERT_TRUE(result->GetAsList(&list)); - EXPECT_EQ(1U, list->GetSize()); + ASSERT_TRUE(result->is_list()); + EXPECT_EQ(1U, result->GetList().size()); } class ExtensionManagementApiEscalationTest :
diff --git a/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc b/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc index c4cf4d1f..b239bf2 100644 --- a/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc +++ b/chrome/browser/extensions/api/omnibox/omnibox_unittest.cc
@@ -77,7 +77,7 @@ styles_expected.push_back(ACMatchClassification(9, kNone)); std::unique_ptr<SendSuggestions::Params> params( - SendSuggestions::Params::Create(*list)); + SendSuggestions::Params::Create(list->GetList())); EXPECT_TRUE(params); ASSERT_FALSE(params->suggest_results.empty()); CompareClassification(styles_expected, StyleTypesToACMatchClassifications( @@ -109,7 +109,7 @@ .Build(); std::unique_ptr<SendSuggestions::Params> swapped_params( - SendSuggestions::Params::Create(*swap_list)); + SendSuggestions::Params::Create(swap_list->GetList())); EXPECT_TRUE(swapped_params); ASSERT_FALSE(swapped_params->suggest_results.empty()); CompareClassification( @@ -173,7 +173,7 @@ styles_expected.push_back(ACMatchClassification(9, kMatch | kDim)); std::unique_ptr<SendSuggestions::Params> params( - SendSuggestions::Params::Create(*list)); + SendSuggestions::Params::Create(list->GetList())); EXPECT_TRUE(params); ASSERT_FALSE(params->suggest_results.empty()); CompareClassification(styles_expected, StyleTypesToACMatchClassifications( @@ -221,7 +221,7 @@ .Build(); std::unique_ptr<SendSuggestions::Params> moved_params( - SendSuggestions::Params::Create(*moved_list)); + SendSuggestions::Params::Create(moved_list->GetList())); EXPECT_TRUE(moved_params); ASSERT_FALSE(moved_params->suggest_results.empty()); CompareClassification(styles_expected, StyleTypesToACMatchClassifications( @@ -280,7 +280,7 @@ styles_expected.push_back(ACMatchClassification(5, kNone)); std::unique_ptr<SendSuggestions::Params> params( - SendSuggestions::Params::Create(*list)); + SendSuggestions::Params::Create(list->GetList())); EXPECT_TRUE(params); ASSERT_FALSE(params->suggest_results.empty()); CompareClassification(styles_expected, StyleTypesToACMatchClassifications( @@ -332,7 +332,7 @@ .Build(); std::unique_ptr<SetDefaultSuggestion::Params> params( - SetDefaultSuggestion::Params::Create(*list)); + SetDefaultSuggestion::Params::Create(list->GetList())); EXPECT_TRUE(params); }
diff --git a/chrome/browser/extensions/api/printing/print_job_submitter.cc b/chrome/browser/extensions/api/printing/print_job_submitter.cc index f266659..039644d3 100644 --- a/chrome/browser/extensions/api/printing/print_job_submitter.cc +++ b/chrome/browser/extensions/api/printing/print_job_submitter.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/native_window_tracker.h" #include "chrome/common/pref_names.h" #include "chrome/services/printing/public/mojom/pdf_flattener.mojom.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom.h" #include "chromeos/crosapi/mojom/local_printer.mojom.h" #include "chromeos/printing/printer_configuration.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc b/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc index 9c3169e..4cfbc2f 100644 --- a/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc +++ b/chrome/browser/extensions/api/printing/printing_api_handler_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> #include <utility> +#include <vector> #include "base/containers/span.h" #include "base/json/json_reader.h" @@ -172,8 +173,8 @@ request.job.content_type = content_type; request.document_blob_uuid = std::move(document_blob_uuid); - base::ListValue args; - args.Set(0, request.ToValue()); + std::vector<base::Value> args; + args.emplace_back(base::Value::FromUniquePtrValue(request.ToValue())); return api::printing::SubmitJob::Params::Create(args); }
diff --git a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc index df436342..0f6c66cc 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
@@ -431,10 +431,10 @@ scoped_refptr<TabsUpdateFunction> function = new TabsUpdateFunction(); function->set_extension(extension.get()); - std::unique_ptr<base::ListValue> args( + function->SetArgs( extension_function_test_utils::ParseList( - base::StringPrintf(R"([%d, {"url":"http://example.com"}])", tab_id))); - function->SetArgs(base::Value::FromUniquePtrValue(std::move(args))); + base::StringPrintf(R"([%d, {"url":"http://example.com"}])", tab_id)) + .value()); api_test_utils::SendResponseHelper response_helper(function.get()); function->RunWithValidation()->Execute();
diff --git a/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc b/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc index b885e0b..c672b319 100644 --- a/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc +++ b/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
@@ -79,9 +79,8 @@ std::unique_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult( get_top_sites_function.get(), "[]", browser())); - base::ListValue* list; - ASSERT_TRUE(result->GetAsList(&list)); - EXPECT_GE(list->GetSize(), top_sites_prepopulated_pages_size()); + ASSERT_TRUE(result->is_list()); + EXPECT_GE(result->GetList().size(), top_sites_prepopulated_pages_size()); } } // namespace extensions
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc index 9111dde..1a504d1 100644 --- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc +++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -123,14 +123,13 @@ params->Append(std::move(request_info)); } - std::unique_ptr<base::Value> InvokeGetSinks(base::ListValue** sink_list) { + std::unique_ptr<base::Value> InvokeGetSinks() { scoped_refptr<WebrtcAudioPrivateGetSinksFunction> function = new WebrtcAudioPrivateGetSinksFunction(); function->set_source_url(source_url_); std::unique_ptr<base::Value> result( RunFunctionAndReturnSingleResult(function.get(), "[]", browser())); - result->GetAsList(sink_list); return result; } @@ -143,23 +142,22 @@ AudioDeviceDescriptions devices; GetAudioDeviceDescriptions(false, &devices); - base::ListValue* sink_list = NULL; - std::unique_ptr<base::Value> result = InvokeGetSinks(&sink_list); + std::unique_ptr<base::Value> result = InvokeGetSinks(); + const base::ListValue& sink_list = base::Value::AsListValue(*result); std::string result_string; JSONWriter::Write(*result, &result_string); VLOG(2) << result_string; - EXPECT_EQ(devices.size(), sink_list->GetSize()); + EXPECT_EQ(devices.size(), sink_list.GetSize()); // Iterate through both lists in lockstep and compare. The order // should be identical. size_t ix = 0; AudioDeviceDescriptions::const_iterator it = devices.begin(); - for (; ix < sink_list->GetSize() && it != devices.end(); - ++ix, ++it) { - base::DictionaryValue* dict = NULL; - sink_list->GetDictionary(ix, &dict); + for (; ix < sink_list.GetSize() && it != devices.end(); ++ix, ++it) { + const base::DictionaryValue* dict = NULL; + sink_list.GetDictionary(ix, &dict); std::string sink_id; dict->GetString("sinkId", &sink_id);
diff --git a/chrome/browser/extensions/extension_api_unittest.cc b/chrome/browser/extensions/extension_api_unittest.cc index 1867985..ba8e3a3fd 100644 --- a/chrome/browser/extensions/extension_api_unittest.cc +++ b/chrome/browser/extensions/extension_api_unittest.cc
@@ -53,15 +53,13 @@ ExtensionFunction* function, const std::string& args) { base::Value* value = RunFunctionAndReturnValue(function, args).release(); - base::ListValue* list = NULL; - if (value && !value->GetAsList(&list)) + if (value && !value->is_list()) delete value; - // We expect to either have successfuly retrieved a list from the value, - // or the value to have been NULL. - EXPECT_TRUE(list); - return std::unique_ptr<base::ListValue>(list); + // We expect to have successfully retrieved a list from the value. + EXPECT_TRUE(value); + return base::ListValue::From(std::unique_ptr<base::Value>(value)); } std::string ExtensionApiUnittest::RunFunctionAndReturnError(
diff --git a/chrome/browser/extensions/extension_function_test_utils.cc b/chrome/browser/extensions/extension_function_test_utils.cc index 2ec364aa..d2572965 100644 --- a/chrome/browser/extensions/extension_function_test_utils.cc +++ b/chrome/browser/extensions/extension_function_test_utils.cc
@@ -21,6 +21,7 @@ #include "extensions/browser/extension_function_dispatcher.h" #include "extensions/common/extension.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" using content::WebContents; using extensions::Extension; @@ -50,16 +51,15 @@ namespace extension_function_test_utils { -base::ListValue* ParseList(const std::string& data) { - std::unique_ptr<base::Value> result = base::JSONReader::ReadDeprecated(data); +absl::optional<base::Value> ParseList(const std::string& data) { + absl::optional<base::Value> result = base::JSONReader::Read(data); if (!result) { ADD_FAILURE() << "Failed to parse: " << data; - return nullptr; + return absl::nullopt; } - base::ListValue* list = NULL; - result->GetAsList(&list); - ignore_result(result.release()); - return list; + if (!result->is_list()) + return absl::nullopt; + return result; } base::DictionaryValue* ToDictionary(base::Value* val) { @@ -134,9 +134,12 @@ const std::string& args, Browser* browser, extensions::api_test_utils::RunFunctionFlags flags) { - std::unique_ptr<base::ListValue> parsed_args(ParseList(args)); - EXPECT_TRUE(parsed_args.get()) + absl::optional<base::Value> maybe_parsed_args(ParseList(args)); + EXPECT_TRUE(maybe_parsed_args) << "Could not parse extension function arguments: " << args; + std::unique_ptr<base::ListValue> parsed_args(base::ListValue::From( + base::Value::ToUniquePtrValue(std::move(*maybe_parsed_args)))); + return RunFunction(function, std::move(parsed_args), browser, flags); }
diff --git a/chrome/browser/extensions/extension_function_test_utils.h b/chrome/browser/extensions/extension_function_test_utils.h index b1c76c47..3f9aa92f 100644 --- a/chrome/browser/extensions/extension_function_test_utils.h +++ b/chrome/browser/extensions/extension_function_test_utils.h
@@ -8,8 +8,10 @@ #include <string> #include "base/memory/ref_counted.h" +#include "base/values.h" #include "extensions/browser/api_test_utils.h" #include "extensions/common/manifest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" class Browser; class ExtensionFunction; @@ -26,8 +28,8 @@ // extensions/browser/api_test_utils.h. namespace extension_function_test_utils { -// Parse JSON and return as a ListValue, or null if invalid. -base::ListValue* ParseList(const std::string& data); +// Parse JSON and return as a list Value, or nullopt if invalid. +absl::optional<base::Value> ParseList(const std::string& data); // If |val| is a dictionary, return it as one, otherwise NULL. base::DictionaryValue* ToDictionary(base::Value* val);
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc index cb2e6b4b..75095fb 100644 --- a/chrome/browser/extensions/extension_web_ui.cc +++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -461,11 +461,10 @@ // chrome://bookmarks/#1 for display in the omnibox. for (base::DictionaryValue::Iterator dict_iter(*overrides); !dict_iter.IsAtEnd(); dict_iter.Advance()) { - const base::ListValue* url_list = nullptr; - if (!dict_iter.value().GetAsList(&url_list)) + if (!dict_iter.value().is_list()) continue; - for (const auto& list_iter : url_list->GetList()) { + for (const auto& list_iter : dict_iter.value().GetList()) { const std::string* override = nullptr; if (list_iter.is_dict()) override = list_iter.FindStringKey(kEntry);
diff --git a/chrome/browser/extensions/menu_manager.cc b/chrome/browser/extensions/menu_manager.cc index 3241ff3..ad93682 100644 --- a/chrome/browser/extensions/menu_manager.cc +++ b/chrome/browser/extensions/menu_manager.cc
@@ -73,16 +73,15 @@ base::Value* value) { MenuItem::OwnedList items; - base::ListValue* list = nullptr; - if (!value || !value->GetAsList(&list)) + if (!value || !value->is_list()) return items; - for (size_t i = 0; i < list->GetSize(); ++i) { - base::DictionaryValue* dict = nullptr; - if (!list->GetDictionary(i, &dict)) + for (const base::Value& elem : value->GetList()) { + if (!elem.is_dict()) continue; + const base::DictionaryValue& dict = base::Value::AsDictionaryValue(elem); std::unique_ptr<MenuItem> item = - MenuItem::Populate(extension_id, *dict, nullptr); + MenuItem::Populate(extension_id, dict, nullptr); if (!item) continue; items.push_back(std::move(item));
diff --git a/chrome/browser/extensions/policy_handlers.cc b/chrome/browser/extensions/policy_handlers.cc index 5ab665f..73269a3 100644 --- a/chrome/browser/extensions/policy_handlers.cc +++ b/chrome/browser/extensions/policy_handlers.cc
@@ -108,15 +108,14 @@ if (!policy_value) return true; - const base::ListValue* policy_list_value = nullptr; - if (!policy_value->GetAsList(&policy_list_value)) { + if (!policy_value->is_list()) { // This should have been caught in CheckPolicySettings. NOTREACHED(); return false; } int index = -1; - for (const auto& entry : policy_list_value->GetList()) { + for (const auto& entry : policy_value->GetList()) { ++index; if (!entry.is_string()) { if (errors) { @@ -179,15 +178,14 @@ if (!value) return true; - const base::ListValue* list_value = NULL; - if (!value->GetAsList(&list_value)) { + if (!value->is_list()) { NOTREACHED(); return false; } // Check that the list contains valid URLPattern strings only. int index = 0; - for (const auto& entry : list_value->GetList()) { + for (const auto& entry : value->GetList()) { if (!entry.is_string()) { errors->AddError(policy_name(), index, IDS_POLICY_TYPE_ERROR, base::Value::GetTypeName(base::Value::Type::STRING));
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc index cee19d84..34eaaae 100644 --- a/chrome/browser/external_protocol/external_protocol_handler.cc +++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -68,6 +68,7 @@ "hcp", "ie.http", "javascript", + "mk", "ms-help", "nntp", "res",
diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc index 9b60d89f..d356d73 100644 --- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc +++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
@@ -345,6 +345,10 @@ block_state = ExternalProtocolHandler::GetBlockState("ie.http", nullptr, profile_.get()); EXPECT_EQ(ExternalProtocolHandler::BLOCK, block_state); + EXPECT_EQ("mk", GURL("mk:@FooBar:ie.http:res://foo.bar/baz").scheme()); + block_state = + ExternalProtocolHandler::GetBlockState("mk", nullptr, profile_.get()); + EXPECT_EQ(ExternalProtocolHandler::BLOCK, block_state); EXPECT_TRUE( profile_->GetPrefs() ->GetDictionary(prefs::kProtocolHandlerPerOriginAllowedProtocols)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index b1c1643..69235ac6 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1171,8 +1171,13 @@ }, { "name": "document-transition", - "owners": [ "vmpstr", "chrishtr" ], - "expiry_milestone" : 94 + "owners": [ "khushalsagar", "vmpstr", "chrishtr" ], + "expiry_milestone" : 98 + }, + { + "name": "document-transition-slowdown-factor", + "owners": [ "khushalsagar", "vmpstr", "chrishtr" ], + "expiry_milestone" : 98 }, { "name": "double-buffer-compositing", @@ -4417,6 +4422,11 @@ "expiry_milestone": 100 }, { + "name": "persistent-quota-is-temporary-quota", + "owners": [ "mek", "cfredric" ], + "expiry_milestone": 100 + }, + { "name": "photo-picker-video-support", "owners": [ "finnur" ], "expiry_milestone": 92
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 2d92a0a..8f16c48 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -614,6 +614,12 @@ const char kDocumentTransitionDescription[] = "Controls the availability of the documentTransition JavaScript API."; +const char kDocumentTransitionSlowdownFactorName[] = + "documentTransition API Duration Control"; +const char kDocumentTransitionSlowdownFactorDescription[] = + "Slows down animations triggered by documentTransition JavaScript API for " + "debugging."; + const char kEnableAudioFocusEnforcementName[] = "Audio Focus Enforcement"; const char kEnableAudioFocusEnforcementDescription[] = "Enables enforcement of a single media session having audio focus at " @@ -2032,6 +2038,12 @@ "prompts. Requires chrome://flags/#quiet-notification-prompts to be " "enabled."; +const char kPersistentQuotaIsTemporaryQuotaName[] = + "window.PERSISTENT is temporary quota."; +const char kPersistentQuotaIsTemporaryQuotaDescription[] = + "Causes the window.PERSISTENT quota type to have the same semantics as " + "window.TEMPORARY."; + const char kPlaybackSpeedButtonName[] = "Playback Speed Button"; const char kPlaybackSpeedButtonDescription[] = "Enable the playback speed button on the media controls.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index cd82848..b50f698 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -370,6 +370,9 @@ extern const char kDocumentTransitionName[]; extern const char kDocumentTransitionDescription[]; +extern const char kDocumentTransitionSlowdownFactorName[]; +extern const char kDocumentTransitionSlowdownFactorDescription[]; + extern const char kEnableAudioFocusEnforcementName[]; extern const char kEnableAudioFocusEnforcementDescription[]; @@ -1157,6 +1160,9 @@ extern const char kPermissionQuietChipName[]; extern const char kPermissionQuietChipDescription[]; +extern const char kPersistentQuotaIsTemporaryQuotaName[]; +extern const char kPersistentQuotaIsTemporaryQuotaDescription[]; + extern const char kPlaybackSpeedButtonName[]; extern const char kPlaybackSpeedButtonDescription[];
diff --git a/chrome/browser/incognito/BUILD.gn b/chrome/browser/incognito/BUILD.gn new file mode 100644 index 0000000..583cbbd9 --- /dev/null +++ b/chrome/browser/incognito/BUILD.gn
@@ -0,0 +1,33 @@ +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +android_library("java") { + sources = [ + "android/java/src/org/chromium/chrome/browser/incognito/IncognitoCctProfileManager.java", + "android/java/src/org/chromium/chrome/browser/incognito/IncognitoStartup.java", + "android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabPersistence.java", + "android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java", + ] + deps = [ + "//base:base_java", + "//chrome/browser/dependency_injection:java", + "//chrome/browser/profiles/android:java", + "//chrome/browser/tab:java", + "//chrome/browser/tabmodel:java", + "//chrome/browser/tabpersistence:java", + "//chrome/browser/util:java", + "//third_party/android_deps:dagger_java", + "//third_party/android_deps:javax_inject_javax_inject_java", + "//third_party/androidx:androidx_annotation_annotation_java", + "//ui/android:ui_full_java", + "//url:gurl_java", + ] + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] +} + +generate_jni("jni_headers") { + sources = [ "android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java" ] +}
diff --git a/chrome/browser/incognito/DIR_METADATA b/chrome/browser/incognito/DIR_METADATA new file mode 100644 index 0000000..7d2fe23 --- /dev/null +++ b/chrome/browser/incognito/DIR_METADATA
@@ -0,0 +1,5 @@ +monorail { + component: "Privacy>Incognito" +} +team_email: "chrome-incognito@google.com" +os: ANDROID
diff --git a/chrome/browser/incognito/OWNERS b/chrome/browser/incognito/OWNERS new file mode 100644 index 0000000..cab471dc --- /dev/null +++ b/chrome/browser/incognito/OWNERS
@@ -0,0 +1,3 @@ +rhalavati@chromium.org +roagarwal@chromium.org +sideyilmaz@chromium.org
diff --git a/chrome/browser/profiles/incognito_utils_android.cc b/chrome/browser/incognito/android/incognito_utils_android.cc similarity index 94% rename from chrome/browser/profiles/incognito_utils_android.cc rename to chrome/browser/incognito/android/incognito_utils_android.cc index ee69be1..203519c 100644 --- a/chrome/browser/profiles/incognito_utils_android.cc +++ b/chrome/browser/incognito/android/incognito_utils_android.cc
@@ -4,7 +4,7 @@ #include <jni.h> -#include "chrome/android/chrome_jni_headers/IncognitoUtils_jni.h" +#include "chrome/browser/incognito/jni_headers/IncognitoUtils_jni.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/pref_names.h"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoCctProfileManager.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoCctProfileManager.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoCctProfileManager.java rename to chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoCctProfileManager.java
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoStartup.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoStartup.java new file mode 100644 index 0000000..22eda94e --- /dev/null +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoStartup.java
@@ -0,0 +1,83 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.incognito; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.ActivityManager.RecentTaskInfo; + +import org.chromium.base.ApplicationStatus; +import org.chromium.base.ContextUtils; +import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.chrome.browser.cookies.CookiesFetcher; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tabmodel.IncognitoTabHostUtils; +import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.util.AndroidTaskUtils; + +import java.util.HashSet; +import java.util.Set; + +/** + * Operations that need to be executed on startup for incognito mode. + */ +public class IncognitoStartup { + public static void onResumeWithNative( + ObservableSupplier<TabModelSelector> tabModelSelectorSupplier, + Set<String> componentNames) { + if (shouldDestroyIncognitoProfileOnStartup( + tabModelSelectorSupplier.get().getCurrentModel().isIncognito(), + componentNames)) { + Profile.getLastUsedRegularProfile() + .getPrimaryOTRProfile(/*createIfNeeded=*/true) + .destroyWhenAppropriate(); + } else { + CookiesFetcher.restoreCookies(); + } + } + + /** + * Determine whether the incognito profile needs to be destroyed as part of startup. This is + * only needed on L+ when it is possible to swipe away tasks from Android recents without + * killing the process. When this occurs, the normal incognito profile shutdown does not + * happen, which can leave behind incognito cookies from an existing session. + */ + @SuppressLint("NewApi") + private static boolean shouldDestroyIncognitoProfileOnStartup( + boolean selectedTabModelIsIncognito, Set<String> componentNames) { + if (!Profile.getLastUsedRegularProfile().hasPrimaryOTRProfile()) { + return false; + } + + Set<RecentTaskInfo> matchingTaskInfos = + AndroidTaskUtils.getRecentTaskInfosMatchingComponentNames( + ContextUtils.getApplicationContext(), componentNames); + Set<Integer> tabbedModeTaskIds = new HashSet<>(); + for (RecentTaskInfo info : matchingTaskInfos) { + tabbedModeTaskIds.add(info.id); + } + + if (tabbedModeTaskIds.size() == 0) { + return true; + } + + for (Activity activity : ApplicationStatus.getRunningActivities()) { + tabbedModeTaskIds.remove(activity.getTaskId()); + } + + // If all tabbed mode tasks listed in Android recents are alive, check to see if + // any incognito tabs exist and the current tab model isn't incognito. If so, we should + // destroy the incognito profile; otherwise it's not safe to do so yet. + if (tabbedModeTaskIds.size() == 0) { + return !(IncognitoTabHostUtils.doIncognitoTabsExist() || selectedTabModelIsIncognito); + } + + // In this case, we have tabbed mode activities listed in recents that do not have an + // active running activity associated with them. We can not accurately get an incognito + // tab count as we do not know if any incognito tabs are associated with the yet unrestored + // tabbed mode. Thus we do not proactively destroy the incognito profile. + return false; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabPersistence.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabPersistence.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabPersistence.java rename to chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabPersistence.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java similarity index 66% rename from chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java rename to chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java index aa9a060..73c9c3b9b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java
@@ -4,26 +4,15 @@ package org.chromium.chrome.browser.incognito; -import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.ActivityManager.RecentTaskInfo; - import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import org.chromium.base.ApplicationStatus; -import org.chromium.base.ContextUtils; import org.chromium.base.annotations.NativeMethods; import org.chromium.chrome.browser.profiles.OTRProfileID; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileKey; -import org.chromium.chrome.browser.tabmodel.IncognitoTabHostUtils; -import org.chromium.chrome.browser.util.AndroidTaskUtils; import org.chromium.ui.base.WindowAndroid; -import java.util.HashSet; -import java.util.Set; - /** * Utilities for working with incognito tabs spread across multiple activities. */ @@ -33,49 +22,6 @@ private IncognitoUtils() {} /** - * Determine whether the incognito profile needs to be destroyed as part of startup. This is - * only needed on L+ when it is possible to swipe away tasks from Android recents without - * killing the process. When this occurs, the normal incognito profile shutdown does not - * happen, which can leave behind incognito cookies from an existing session. - */ - @SuppressLint("NewApi") - public static boolean shouldDestroyIncognitoProfileOnStartup( - boolean selectedTabModelIsIncognito, Set<String> componentNames) { - if (!Profile.getLastUsedRegularProfile().hasPrimaryOTRProfile()) { - return false; - } - - Set<RecentTaskInfo> matchingTaskInfos = - AndroidTaskUtils.getRecentTaskInfosMatchingComponentNames( - ContextUtils.getApplicationContext(), componentNames); - Set<Integer> tabbedModeTaskIds = new HashSet<>(); - for (RecentTaskInfo info : matchingTaskInfos) { - tabbedModeTaskIds.add(info.id); - } - - if (tabbedModeTaskIds.size() == 0) { - return true; - } - - for (Activity activity : ApplicationStatus.getRunningActivities()) { - tabbedModeTaskIds.remove(activity.getTaskId()); - } - - // If all tabbed mode tasks listed in Android recents are alive, check to see if - // any incognito tabs exist and the current tab model isn't incognito. If so, we should - // destroy the incognito profile; otherwise it's not safe to do so yet. - if (tabbedModeTaskIds.size() == 0) { - return !(IncognitoTabHostUtils.doIncognitoTabsExist() || selectedTabModelIsIncognito); - } - - // In this case, we have tabbed mode activities listed in recents that do not have an - // active running activity associated with them. We can not accurately get an incognito - // tab count as we do not know if any incognito tabs are associated with the yet unrestored - // tabbed mode. Thus we do not proactively destroy the incognito profile. - return false; - } - - /** * @return true if incognito mode is enabled. */ public static boolean isIncognitoModeEnabled() {
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc index f7dd53aa..4fd1bec 100644 --- a/chrome/browser/lifetime/application_lifetime.cc +++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -316,7 +316,14 @@ } #if !defined(OS_ANDROID) +namespace { + +bool g_relaunch_ignore_unload_handlers_called = false; + +} // namespace + void RelaunchIgnoreUnloadHandlers() { + g_relaunch_ignore_unload_handlers_called = true; #if BUILDFLAG(IS_CHROMEOS_ASH) chromeos::PowerManagerClient::Get()->RequestRestart( power_manager::REQUEST_RESTART_OTHER, "Chrome relaunch"); @@ -324,6 +331,11 @@ #endif AttemptRestartInternal(IgnoreUnloadHandlers(true)); } + +bool DidCallRelaunchIgnoreUnloadHandlers() { + return g_relaunch_ignore_unload_handlers_called; +} + #endif void AttemptExit() {
diff --git a/chrome/browser/lifetime/application_lifetime.h b/chrome/browser/lifetime/application_lifetime.h index 66f2d81..13f4a7f 100644 --- a/chrome/browser/lifetime/application_lifetime.h +++ b/chrome/browser/lifetime/application_lifetime.h
@@ -41,6 +41,8 @@ // that all user prompts (e.g., beforeunload handlers and confirmation to abort // in-progress downloads) are bypassed. void RelaunchIgnoreUnloadHandlers(); +// TODO(https://crbug.com/1227426): for debugging. +bool DidCallRelaunchIgnoreUnloadHandlers(); #endif // Attempt to exit by closing all browsers. This is equivalent to
diff --git a/chrome/browser/lifetime/browser_shutdown.cc b/chrome/browser/lifetime/browser_shutdown.cc index 083ee5be..a97092c 100644 --- a/chrome/browser/lifetime/browser_shutdown.cc +++ b/chrome/browser/lifetime/browser_shutdown.cc
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/clang_profiling_buildflags.h" #include "base/command_line.h" +#include "base/debug/dump_without_crashing.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/metrics/histogram_functions.h" @@ -462,6 +463,11 @@ PrefService* pref_service = g_browser_process->local_state(); if (pref_service) { #if !defined(OS_ANDROID) + // TODO(https://crbug.com/1227426): for debugging. + if (pref_service->GetBoolean(prefs::kWasRestarted) && + chrome::DidCallRelaunchIgnoreUnloadHandlers()) { + base::debug::DumpWithoutCrashing(); + } pref_service->ClearPref(prefs::kWasRestarted); #endif // !defined(OS_ANDROID) pref_service->ClearPref(prefs::kRestartLastSessionOnShutdown);
diff --git a/chrome/browser/media/cast_mirroring_service_host.cc b/chrome/browser/media/cast_mirroring_service_host.cc index 0998b005..71b8d59d 100644 --- a/chrome/browser/media/cast_mirroring_service_host.cc +++ b/chrome/browser/media/cast_mirroring_service_host.cc
@@ -20,9 +20,9 @@ #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/net/system_network_context_manager.h" -#include "chrome/browser/service_sandbox_type.h" #include "components/mirroring/browser/single_client_video_capture_host.h" #include "components/mirroring/mojom/cast_message_channel.mojom.h" +#include "components/mirroring/mojom/mirroring_service.mojom.h" #include "components/mirroring/mojom/session_observer.mojom.h" #include "components/mirroring/mojom/session_parameters.mojom.h" #include "content/public/browser/audio_service.h"
diff --git a/chrome/browser/metrics/cloned_install_client_id_reset_browsertest.cc b/chrome/browser/metrics/cloned_install_client_id_reset_browsertest.cc index 81f6cb1..40c4c1b 100644 --- a/chrome/browser/metrics/cloned_install_client_id_reset_browsertest.cc +++ b/chrome/browser/metrics/cloned_install_client_id_reset_browsertest.cc
@@ -2,20 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/path_service.h" +#include "base/test/task_environment.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" +#include "chrome/common/chrome_paths.h" #include "chrome/installer/util/google_update_settings.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_service.h" #include "components/metrics/metrics_state_manager.h" #include "components/metrics_services_manager/metrics_services_manager.h" +#include "components/prefs/json_pref_store.h" #include "content/public/test/browser_test.h" - -#if defined(OS_WIN) -#include "base/test/test_reg_util_win.h" -#endif // defined(OS_WIN) +#include "content/public/test/test_launcher.h" namespace { const char kInitialClientId[] = "11111111-2222-aaaa-bbbb-cccccccccccc"; @@ -26,6 +27,36 @@ ClonedInstallClientIdResetBrowserTest() = default; ~ClonedInstallClientIdResetBrowserTest() override = default; + bool SetUpUserDataDirectory() override { + if (!InProcessBrowserTest::SetUpUserDataDirectory()) + return false; + + // Changing in user's data directory should only be done once before + // PRE_TestClonedInstallClientIdReset. + if (!content::IsPreTest()) + return true; + + base::ScopedAllowBlockingForTesting allow_blocking; + base::FilePath user_dir; + CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &user_dir)); + + // Create a local-state file with what we want the browser to use. This + // has to be done here because there is no hook between when the browser + // is initialized and the metrics-client acts on the pref values. The + // "Local State" directory is hard-coded because the FILE_LOCAL_STATE + // path is not yet defined at this point. + base::test::TaskEnvironment task_env; + auto state = base::MakeRefCounted<JsonPrefStore>( + user_dir.Append(FILE_PATH_LITERAL("Local State"))); + + // Set up the initial client id for (before) + // PRE_TestClonedInstallClientIdReset. + state->SetValue(metrics::prefs::kMetricsClientID, + std::make_unique<base::Value>(kInitialClientId), 0); + + return true; + } + void SetUp() override { // Make metrics reporting work same as in Chrome branded builds, for test // consistency between Chromium and Chrome builds. @@ -34,16 +65,6 @@ ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting( &metrics_enabled_); -// On windows, the registry is used for client info backups. -#if defined(OS_WIN) - ASSERT_NO_FATAL_FAILURE( - registry_override_.OverrideRegistry(HKEY_CURRENT_USER)); -#endif // defined(OS_WIN) - - metrics::ClientInfo client_info; - client_info.client_id = kInitialClientId; - GoogleUpdateSettings::StoreMetricsClientInfo(client_info); - InProcessBrowserTest::SetUp(); } @@ -55,10 +76,6 @@ private: bool metrics_enabled_ = true; - -#if defined(OS_WIN) - registry_util::RegistryOverrideManager registry_override_; -#endif // defined(OS_WIN) }; IN_PROC_BROWSER_TEST_F(ClonedInstallClientIdResetBrowserTest, @@ -67,16 +84,8 @@ EXPECT_EQ(kInitialClientId, metrics_service()->GetClientId()); } -// Test is flaky on Mac (https://crbug.com/1175077). -// And on Linux (https://crbug.com/1227760). -#if defined(OS_MAC) || defined(OS_LINUX) -#define MAYBE_TestClonedInstallClientIdReset \ - DISABLED_TestClonedInstallClientIdReset -#else -#define MAYBE_TestClonedInstallClientIdReset TestClonedInstallClientIdReset -#endif IN_PROC_BROWSER_TEST_F(ClonedInstallClientIdResetBrowserTest, - MAYBE_TestClonedInstallClientIdReset) { + TestClonedInstallClientIdReset) { EXPECT_NE(kInitialClientId, metrics_service()->GetClientId()); EXPECT_FALSE(local_state()->GetBoolean(metrics::prefs::kMetricsResetIds)); }
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 2f2c148..2151966 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -75,13 +75,13 @@ #include "components/policy/core/browser/configuration_policy_handler.h" #include "components/policy/core/browser/configuration_policy_handler_list.h" #include "components/policy/core/browser/configuration_policy_handler_parameters.h" -#include "components/policy/core/browser/proxy_policy_handler.h" #include "components/policy/core/browser/url_blocklist_policy_handler.h" #include "components/policy/core/common/policy_details.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_pref_names.h" #include "components/policy/core/common/schema.h" #include "components/policy/policy_constants.h" +#include "components/proxy_config/proxy_policy_handler.h" #include "components/safe_browsing/core/common/safe_browsing_policy_handler.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/search_engines/default_search_policy_handler.h" @@ -1551,7 +1551,7 @@ std::make_unique<bookmarks::ManagedBookmarksPolicyHandler>( chrome_schema)); handlers->AddHandler(std::make_unique<HomepageLocationPolicyHandler>()); - handlers->AddHandler(std::make_unique<ProxyPolicyHandler>()); + handlers->AddHandler(std::make_unique<proxy_config::ProxyPolicyHandler>()); handlers->AddHandler(std::make_unique<SecureDnsPolicyHandler>()); #if !defined(OS_ANDROID) handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>(
diff --git a/chrome/browser/policy/profile_policy_connector_unittest.cc b/chrome/browser/policy/profile_policy_connector_unittest.cc index d3d6e751..4e76c833 100644 --- a/chrome/browser/policy/profile_policy_connector_unittest.cc +++ b/chrome/browser/policy/profile_policy_connector_unittest.cc
@@ -16,7 +16,6 @@ #include "components/account_id/account_id.h" #include "components/autofill/core/common/autofill_prefs.h" #include "components/policy/core/browser/browser_policy_connector.h" -#include "components/policy/core/browser/proxy_policy_handler.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_manager.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
diff --git a/chrome/browser/policy/test/proxy_policies_browsertest.cc b/chrome/browser/policy/test/proxy_policies_browsertest.cc index 11ab2af..b6cbb55a 100644 --- a/chrome/browser/policy/test/proxy_policies_browsertest.cc +++ b/chrome/browser/policy/test/proxy_policies_browsertest.cc
@@ -15,10 +15,60 @@ #include "components/policy/core/common/policy_service.h" #include "components/policy/core/common/policy_types.h" #include "components/policy/policy_constants.h" +#include "components/prefs/pref_service.h" +#include "components/proxy_config/proxy_config_dictionary.h" +#include "components/proxy_config/proxy_config_pref_names.h" +#include "components/proxy_config/proxy_prefs.h" #include "content/public/test/browser_test.h" namespace policy { +namespace { + +// Verify that all the proxy prefs are set to the specified expected values. +void VerifyProxyPrefs(PrefService* prefs, + const std::string& expected_proxy_server, + const std::string& expected_proxy_pac_url, + absl::optional<bool> expected_proxy_pac_mandatory, + const std::string& expected_proxy_bypass_list, + const ProxyPrefs::ProxyMode& expected_proxy_mode) { + const base::Value* value = prefs->Get(proxy_config::prefs::kProxy); + ASSERT_TRUE(value); + ASSERT_TRUE(value->is_dict()); + ProxyConfigDictionary dict(value->Clone()); + std::string s; + bool b; + if (expected_proxy_server.empty()) { + EXPECT_FALSE(dict.GetProxyServer(&s)); + } else { + ASSERT_TRUE(dict.GetProxyServer(&s)); + EXPECT_EQ(expected_proxy_server, s); + } + if (expected_proxy_pac_url.empty()) { + EXPECT_FALSE(dict.GetPacUrl(&s)); + } else { + ASSERT_TRUE(dict.GetPacUrl(&s)); + EXPECT_EQ(expected_proxy_pac_url, s); + } + if (!expected_proxy_pac_mandatory) { + EXPECT_FALSE(dict.GetPacMandatory(&b)); + } else { + ASSERT_TRUE(dict.GetPacMandatory(&b)); + EXPECT_EQ(*expected_proxy_pac_mandatory, b); + } + if (expected_proxy_bypass_list.empty()) { + EXPECT_FALSE(dict.GetBypassList(&s)); + } else { + ASSERT_TRUE(dict.GetBypassList(&s)); + EXPECT_EQ(expected_proxy_bypass_list, s); + } + ProxyPrefs::ProxyMode mode; + ASSERT_TRUE(dict.GetMode(&mode)); + EXPECT_EQ(expected_proxy_mode, mode); +} + +} // namespace + IN_PROC_BROWSER_TEST_F(PolicyTest, SeparateProxyPoliciesMerging) { // Add an individual proxy policy value. PolicyMap policies; @@ -26,30 +76,12 @@ POLICY_SOURCE_CLOUD, base::Value(3), nullptr); UpdateProviderPolicy(policies); - // It should be removed and replaced with a dictionary. - PolicyMap expected; - base::Value expected_value(base::Value::Type::DICTIONARY); - expected_value.SetIntKey(key::kProxyServerMode, 3); - expected.Set(key::kProxySettings, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - POLICY_SOURCE_CLOUD, std::move(expected_value), nullptr); -#if defined(OS_CHROMEOS) - SetEnterpriseUsersDefaults(&expected); -#endif - - // Check both the browser and the profile. - const PolicyMap& actual_from_browser = - g_browser_process->browser_policy_connector() - ->GetPolicyService() - ->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); - - EXPECT_TRUE(expected.Equals(actual_from_browser)); - const PolicyMap& actual_from_profile = - browser() - ->profile() - ->GetProfilePolicyConnector() - ->policy_service() - ->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())); - EXPECT_TRUE(expected.Equals(actual_from_profile)); + VerifyProxyPrefs(g_browser_process->local_state(), std::string(), + std::string(), absl::nullopt, std::string(), + ProxyPrefs::MODE_SYSTEM); + VerifyProxyPrefs(browser()->profile()->GetPrefs(), std::string(), + std::string(), absl::nullopt, std::string(), + ProxyPrefs::MODE_SYSTEM); } } // namespace policy
diff --git a/chrome/browser/printing/pdf_nup_converter_client.cc b/chrome/browser/printing/pdf_nup_converter_client.cc index 275e664..06d90ac4 100644 --- a/chrome/browser/printing/pdf_nup_converter_client.cc +++ b/chrome/browser/printing/pdf_nup_converter_client.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "chrome/browser/printing/printing_service.h" #include "chrome/services/printing/public/mojom/pdf_nup_converter.mojom.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom.h" namespace printing {
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc index cb76164..be19d700 100644 --- a/chrome/browser/printing/pdf_to_emf_converter.cc +++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -27,6 +27,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/printing/printing_service.h" #include "chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_data.h" #include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chrome/browser/printing/printing_service.cc b/chrome/browser/printing/printing_service.cc index 2b73b110..986568e 100644 --- a/chrome/browser/printing/printing_service.cc +++ b/chrome/browser/printing/printing_service.cc
@@ -5,8 +5,8 @@ #include "chrome/browser/printing/printing_service.h" #include "base/no_destructor.h" -#include "chrome/browser/service_sandbox_type.h" #include "chrome/grit/generated_resources.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom.h" #include "content/public/browser/service_process_host.h" const mojo::Remote<printing::mojom::PrintingService>& GetPrintingService() {
diff --git a/chrome/browser/printing/printing_service.h b/chrome/browser/printing/printing_service.h index 59529e75..7e367ea 100644 --- a/chrome/browser/printing/printing_service.h +++ b/chrome/browser/printing/printing_service.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_PRINTING_PRINTING_SERVICE_H_ #define CHROME_BROWSER_PRINTING_PRINTING_SERVICE_H_ -#include "chrome/services/printing/public/mojom/printing_service.mojom.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom-forward.h" #include "mojo/public/cpp/bindings/remote.h" // Acquires a remote handle to the sandboxed Printing Service
diff --git a/chrome/browser/printing/pwg_raster_converter.cc b/chrome/browser/printing/pwg_raster_converter.cc index b01eaefb..8ed000ad 100644 --- a/chrome/browser/printing/pwg_raster_converter.cc +++ b/chrome/browser/printing/pwg_raster_converter.cc
@@ -18,6 +18,7 @@ #include "base/notreached.h" #include "chrome/browser/printing/printing_service.h" #include "chrome/services/printing/public/mojom/pdf_to_pwg_raster_converter.mojom.h" +#include "chrome/services/printing/public/mojom/printing_service.mojom.h" #include "components/cloud_devices/common/cloud_device_description.h" #include "components/cloud_devices/common/printer_description.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index f9237e83..b4d0202f 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -2896,12 +2896,15 @@ source_web_contents_)) { return false; } + std::string source_lang = + chrome_translate_client->GetLanguageState().source_language(); // Note that we intentionally enable the menu even if the source and // target languages are identical. This is to give a way to user to // translate a page that might contains text fragments in a different // language. return ((params_.edit_flags & ContextMenuDataEditFlags::kCanTranslate) != 0) && + !source_lang.empty() && // Did we receive the page language yet? // Disable on the Instant Extended NTP. !search::IsInstantNTP(embedder_web_contents_); } @@ -3438,7 +3441,11 @@ if (!chrome_translate_client) return; - chrome_translate_client->ManualTranslateWhenReady(); + translate::TranslateManager* manager = + chrome_translate_client->GetTranslateManager(); + DCHECK(manager); + manager->ShowTranslateUI(/*auto_translate=*/true, + /*triggered_from_menu=*/true); } void RenderViewContextMenu::ExecLanguageSettings(int event_flags) {
diff --git a/chrome/browser/resources/chromeos/add_supervision/BUILD.gn b/chrome/browser/resources/chromeos/add_supervision/BUILD.gn index 51ca7b9..bff720e 100644 --- a/chrome/browser/resources/chromeos/add_supervision/BUILD.gn +++ b/chrome/browser/resources/chromeos/add_supervision/BUILD.gn
@@ -10,14 +10,14 @@ deps = [ ":add_supervision_api_server", ":add_supervision_ui", - ":post_message_api", + "//ui/webui/resources/js:post_message_api_server.m", ] } js_library("add_supervision_api_server") { deps = [ - ":post_message_api", "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings_js_library_for_compile", + "//ui/webui/resources/js:post_message_api_server.m", ] } @@ -33,9 +33,6 @@ ] } -js_library("post_message_api") { -} - html_to_js("web_components") { js_files = [ "add_supervision_ui.js" ] }
diff --git a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js index f12e53e..d86f3e9 100644 --- a/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js +++ b/chrome/browser/resources/chromeos/add_supervision/add_supervision_api_server.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {PostMessageAPIServer} from './post_message_api.js'; +import {PostMessageAPIServer} from 'chrome://resources/js/post_message_api_server.m.js'; /** * The methods to expose to the client.
diff --git a/chrome/browser/resources/chromeos/add_supervision/post_message_api.js b/chrome/browser/resources/chromeos/add_supervision/post_message_api.js deleted file mode 100644 index c3dbbdc..0000000 --- a/chrome/browser/resources/chromeos/add_supervision/post_message_api.js +++ /dev/null
@@ -1,369 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Initialization retry wait in milliseconds (subject to exponential backoff). - */ -const INITIALIZATION_ATTEMPT_RETRY_WAIT_MS = 100; - -/** - * Maximum number of initialization attempts before resetting the - * initialization attempt cycle. With exponential backoff, this works out - * a maximum wait of 25 seconds on the 8th attempt before restarting. - */ -const MAX_INITIALIZATION_ATTEMPTS = 8; - -/** - * Class that provides the functionality for talking to a client - * over the PostMessageAPI. This should be subclassed and the - * methods provided in methodList should be implemented as methods - * of the subclass. - */ -export class PostMessageAPIServer { - constructor(clientElement, methodList, targetURL, messageOriginURLFilter) { - /** - * The Window type element to which this server will listen for messages, - * probably a <webview>, but also could be an <iframe> or a browser window - * object. - * @private @const {!Element} - */ - this.clientElement_ = clientElement; - - /** - * The guest URL embedded in the element above. Used for message targeting. - * This should be same as the URL loaded in the clientElement, i.e. the - * "src" attribute of a <webview>. - * @private @const {!URL} - */ - this.targetURL_ = new URL(targetURL); - - /** - * Incoming messages received from origin URLs without this prefix - * will not be accepted. This should be used to restrict the API access - * to the intended guest content. - * @private @const {!URL} - */ - this.messageOriginURLFilter_ = new URL(messageOriginURLFilter); - - /** - * Map that stores references to the methods implemented by the API. - * @private {!Map<string, function(!Array):?>} - */ - this.apiFns_ = new Map(); - - /** - * The ID of the timeout set before checking whether initialization has - * taken place yet. - * @private {number} - */ - this.initialization_timeout_id_ = 0; - - /** - * Indicates how many attempts have been made to initialize the channel. - * @private {number} - */ - this.numInitializationAttempts_ = 0; - - /** - * Indicates whether the communication channel between this server and the - * WebView has been established. - * @private {boolean} - */ - this.isInitialized_ = false; - - // Wait for content to load before attempting to initializing the - // message listener. - this.clientElement_.addEventListener('contentload', () => { - this.numInitializationAttempts_ = 0; - this.isInitialized_ = false; - this.initialize(); - }); - - // Listen for events. - window.addEventListener('message', (event) => { - this.onMessage_(event); - }); - } - - /** - * Registers the specified method name with the specified - * function. - * - * @param {!string} methodName name of the method to register. - * @param {!function(!Array):?} method The function to associate with the - * name. - */ - registerMethod(methodName, method) { - this.apiFns_.set(methodName, method); - } - - /** - * Send initialization message to client element. - */ - initialize() { - if (this.isInitialized_ || - !this.originMatchesFilter(this.clientElement_.src)) { - return; - } - - if (this.numInitializationAttempts_ < MAX_INITIALIZATION_ATTEMPTS) { - // Tell the embedded webviews whose src matches our origin to initialize - // by sending it a message, which will include a handle for it to use to - // send messages back. - console.log( - 'Sending init message to guest content, attempt # :' + - this.numInitializationAttempts_); - - this.clientElement_.contentWindow.postMessage( - 'init', this.targetURL_.toString()); - - // Set timeout to check if initialization message has been received using - // exponential backoff. - this.initialization_timeout_id_ = setTimeout( - () => { - // If the timeout id is non-zero, that indicates that initialization - // hasn't succeeded yet, so try to initialize again. - this.initialize(); - }, - INITIALIZATION_ATTEMPT_RETRY_WAIT_MS * - (2 ** this.numInitializationAttempts_)); - - this.numInitializationAttempts_++; - } else { - // Exponential backoff has maxed out. Show error page if present. - this.onInitializationError(this.clientElement_.src); - } - } - - /** - * Virtual method to be overridden by implementations of this class to notify - * them that we were unable to initialize communication channel with the - * `clientElement_`. - * - * @param {!string} origin The origin URL that was not able to initialize - * communication. - */ - onInitializationError(origin) {} - - /** - * Determines if the specified origin matches the origin filter. - * @param {!string} origin The origin URL to match with the filter. - * @return {boolean} whether the specified origin matches the filter. - */ - originMatchesFilter(origin) { - const originURL = new URL(origin); - - // We allow the pathname portion of the URL to be a prefix filter, - // to permit for different paths communicating with this server. - return originURL.protocol == this.messageOriginURLFilter_.protocol && - originURL.host == this.messageOriginURLFilter_.host && - originURL.pathname.startsWith(this.messageOriginURLFilter_.pathname); - } - - /** - * Handles postMessage events from the client. - * @private - * @param {Event} event The postMessage event to handle. - */ - onMessage_(event) { - if (!this.originMatchesFilter(event.origin)) { - console.log('Message received from unauthorized origin: ' + event.origin); - return; - } - - if (event.data === 'init') { - if (this.initialization_timeout_id_) { - // Cancel the current init timeout, and signal to the initialization - // polling process that we have received an init message from the guest - // content, so it doesn't reschedule the timer. - clearTimeout(this.initialization_timeout_id_); - this.initialization_timeout_id_ = 0; - } - - this.isInitialized_ = true; - return; - } - // If we have gotten this far, we have received a message from a trusted - // origin, and we should try to process it. We can't gate this on whether - // the channel is initialized, because we can receive events out of order, - // and method calls can be received before the init event. Essentially, we - // should treat the channel as being potentially as soon as we send 'init' - // to the guest content. - const methodId = event.data.methodId; - const fn = event.data.fn; - const args = event.data.args || []; - - if (!this.apiFns_.has(fn)) { - console.error('Unknown function requested: ' + fn); - return; - } - - const sendMessage = (methodId, result) => { - this.clientElement_.contentWindow.postMessage( - { - methodId: methodId, - result: result, - }, - this.targetURL_.toString()); - }; - - // Some methods return a promise and some don't. If we have a promise, - // we resolve it first, otherwise we send the result directly (e.g., for - // void functions we send 'undefined'). - const result = this.apiFns_.get(fn)(args); - if (result instanceof Promise) { - result.then((result) => sendMessage(methodId, result)); - } else { - sendMessage(methodId, result); - } - } -} - -/** - * Class that provides the functionality for talking to a PostMessageAPIServer - * over the postMessage API. This should be subclassed and the methods in the - * server that the client needs to access should be provided in methodList. - */ -export class PostMessageAPIClient { - /** - * @param {!Array<string>} methodList The list of methods accessible via the - * client. - * @param {!string} serverOriginURLFilter Only messages from this origin - * will be accepted. - */ - constructor(methodList, serverOriginURLFilter) { - /** - * @private @const {!string} Filter to use to validate - * the origin of received messages. The origin of messages - * must exactly match this value. - */ - this.serverOriginURLFilter_ = serverOriginURLFilter; - - /** - * The parent window. - * @private {Window} - */ - this.parentWindow_ = null; - /* - * @private {number} - */ - this.nextMethodId_ = 0; - /** - * Map of methods awaiting a response. - * @private {!Map} - */ - this.methodsAwaitingResponse_ = new Map; - /** - * Function property that tracks whether client has - * been initialized by the server. - * @private {Function} - */ - this.boundOnInitialize_ = null; - - // Generate the client-callable methods. - this.generateAPIMethods_(methodList); - } - - /* - * Generates methods for the specified method names. - * @private - * @param {!Array<string>} methods The names of the methods. - */ - generateAPIMethods_(methods) { - methods.forEach((method) => { - Object.getPrototypeOf(this)[method] = function(args) { - return this.callApiFn_(method, args); - }; - }); - } - - initialize() { - this.boundOnInitialize_ = this.onInitialize_.bind(this); - // Wait for an init message from the server. - window.addEventListener('message', this.boundOnInitialize_); - } - - // - // Private implementation: - // - - /** - * Handles initialization event sent from the server to establish - * communication. - * @private - * @param {!Event} event An event received when the initialization message is - * sent from the server. - */ - onInitialize_(event) { - if (!this.originMatchesFilter(event.origin)) { - console.error( - 'Initialization event received from non-authorized origin: ' + - event.origin); - return; - } - this.parentWindow_ = event.source; - window.removeEventListener('message', this.boundOnInitialize_); - this.boundOnInitialize_ = null; - window.addEventListener('message', this.onMessage_.bind(this)); - } - - /** - * Determine if the specified server origin URL matches the origin filter. - * @param {!string} origin The origin URL to match with the filter. - * @return {boolean} whether the specified origin matches the filter. - */ - originMatchesFilter(origin) { - return origin == this.serverOriginURLFilter_; - } - - /** - * Handles postMessage events sent from the server. - * @param {Event} event An event received from the server via the postMessage - * API. - */ - onMessage_(event) { - if (!this.originMatchesFilter(event.origin)) { - console.error( - 'Message received from non-authorized origin: ' + event.origin); - return; - } - if (event.source != this.parentWindow_) { - console.error('discarding event whose source is not the parent window'); - return; - } - if (!this.methodsAwaitingResponse_.has(event.data.methodId)) { - console.error('discarding event method is not waiting for a response'); - return; - } - let method = this.methodsAwaitingResponse_.get(event.data.methodId); - this.methodsAwaitingResponse_.delete(event.data.methodId); - method(event.data.result); - } - - /** - * Converts a function call with arguments into a postMessage event - * and sends it to the server via the postMessage API. - * @param {string} fn The function to call. - * @param {!Array<Object>} args The arguments to pass to the function. - * @return {!Promise} A promise capturing the executing of the function. - */ - callApiFn_(fn, args) { - let newMethodId = this.nextMethodId_++; - let promise = new Promise((resolve, reject) => { - if (!this.parentWindow_) { - reject('No parent window defined'); - } - this.parentWindow_.postMessage( - { - methodId: newMethodId, - fn: fn, - args: args, - }, - '*'); - - this.methodsAwaitingResponse_.set(newMethodId, resolve); - }); - return promise; - } -}
diff --git a/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn b/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn index 9eda9cc..6f9193a6 100644 --- a/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn +++ b/chrome/browser/resources/chromeos/edu_coexistence/BUILD.gn
@@ -88,8 +88,8 @@ js_library("edu_coexistence_controller") { deps = [ ":edu_coexistence_browser_proxy", - "//chrome/browser/resources/chromeos/add_supervision:post_message_api", "//chrome/browser/resources/gaia_auth_host:authenticator.m", + "//ui/webui/resources/js:post_message_api_server.m", ] externs_list = [ "$externs_path/chrome_extensions.js",
diff --git a/chrome/browser/resources/chromeos/edu_coexistence/edu_coexistence_controller.js b/chrome/browser/resources/chromeos/edu_coexistence/edu_coexistence_controller.js index 9301f09..122f1c2 100644 --- a/chrome/browser/resources/chromeos/edu_coexistence/edu_coexistence_controller.js +++ b/chrome/browser/resources/chromeos/edu_coexistence/edu_coexistence_controller.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {PostMessageAPIServer} from '../../chromeos/add_supervision/post_message_api.js'; +import {PostMessageAPIServer} from 'chrome://resources/js/post_message_api_server.m.js'; import {AuthCompletedCredentials, Authenticator, AuthParams} from '../../gaia_auth_host/authenticator.m.js'; import {EduCoexistenceBrowserProxyImpl} from './edu_coexistence_browser_proxy.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn index 93d6eeb..02ef447 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn
@@ -65,6 +65,7 @@ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_utils", "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js/cr/ui:focus_row_behavior.m", ] }
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html index 97f9d18..f472b2a 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html
@@ -3,8 +3,9 @@ color: var(--google-green-500); } - #bluetoothDeviceName { - padding-inline-start: 0; + .bluetooth-middle { + align-items: center; + flex: auto; } .cancel-button { @@ -32,8 +33,9 @@ </template> </div> </div> - <div id="deviceNameSettings" class="settings-box "> - <div id="bluetoothDeviceName" class="middle settings-box-text no-padding" + <div id="deviceNameSettings" class="settings-box"> + <div id="bluetoothDeviceName" + class="bluetooth-middle settings-box-text no-padding" aria-hidden="true"> $i18n{bluetoothDeviceDetailName} <div class="secondary" id="bluetoothDeviceNameLabel"> @@ -46,9 +48,22 @@ $i18n{bluetoothDeviceDetailChangeDeviceName} </cr-button> </div> - <div id="changeDeviceSettings" class="settings-box" aria-hidden="true"> - <!-- TODO(crbug.com/1010321): Add device settings string --> - </div> + <template is="dom-if" + if="[[shouldShowChangeMouseDeviceSettings_(device_.*)]]" restamp> + <cr-link-row + id="changeMouseSettings" + class="hr settings-box" + label="$i18n{bluetoothDeviceDetailChangeDeviceSettingsMouse}"> + </cr-link-row> + </template> + <template is="dom-if" + if="[[shouldShowChangeKeyboardDeviceSettings_(device_.*)]]" restamp> + <cr-link-row + id="changeKeyboardSettings" + class="hr settings-box" + label="$i18n{bluetoothDeviceDetailChangeDeviceSettingsKeyboard}"> + </cr-link-row> + </template> </div> <template is="dom-if" if="[[shouldShowChangeDeviceNameDialog_]]" restamp>
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js index b39666e..543b633 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js
@@ -199,6 +199,29 @@ onCloseChangeDeviceNameDialog_() { this.shouldShowChangeDeviceNameDialog_ = false; } + + /** + * @return {boolean} + * @private + */ + shouldShowChangeMouseDeviceSettings_() { + if (!this.device_) { + return false; + } + return this.device_.deviceProperties.deviceType === mojom.DeviceType.kMouse; + } + + /** + * @return {boolean} + * @private + */ + shouldShowChangeKeyboardDeviceSettings_() { + if (!this.device_) { + return false; + } + return this.device_.deviceProperties.deviceType === + mojom.DeviceType.kKeyboard; + } } customElements.define(
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.html index 47eebe9..9e5472a 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.html +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_summary.html
@@ -53,4 +53,3 @@ </cr-icon-button> </div> </template> -
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.html index e83e7e5..7052a8c 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.html +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list.html
@@ -11,10 +11,12 @@ no-bottom-scroll-border> <iron-list items="[[devices]]" scroll-target="container" preserve-focus> <template> - <!-- TODO(crbug.com/1010321): Fix focus behavior. --> <os-settings-paired-bluetooth-list-item device="[[item]]" - tabindex="[[tabIndex]]"> + tabindex$="[[tabIndex]]" + iron-list-tab-index="[[tabIndex]]" + item-index="[[index]]" + list-size="[[devices.length]]"> </os-settings-paired-bluetooth-list-item> </template> </iron-list>
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.html index 89d768f..3bda49d 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.html +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.html
@@ -21,12 +21,12 @@ } </style> <div focus-row-container> - <!-- TODO(crbug.com/1010321): Add a11y label. --> <div class="list-item" focus-row-control focus-type="rowWrapper" role="button" - selectable> + selectable + aria-label="[[getAriaLabel_(device, itemIndex, listSize)]]"> <iron-icon id="deviceTypeIcon" icon="os-settings:[[getDeviceTypeIcon_(device)]]"> </iron-icon> @@ -45,9 +45,11 @@ </div> <div> <!-- TODO(crbug.com/1010321): Add click listener. --> - <cr-icon-button class="subpage-arrow" + <cr-icon-button id="subpageButton" + class="subpage-arrow" focus-row-control - focus-type="subpageButton"> + focus-type="subpageButton" + aria-label="[[getSubpageButtonA11yLabel_(device)]]"> </cr-icon-button> </div> </div>
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js index 4252e27..01f2224b 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_paired_bluetooth_list_item.js
@@ -16,6 +16,7 @@ import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getDeviceName} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_utils.js'; import {assert} from 'chrome://resources/js/assert.m.js'; +import {FocusRowBehavior, FocusRowBehaviorInterface} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js'; /** * The threshold percentage where any battery percentage lower is considered @@ -30,7 +31,7 @@ * the maximum battery percentage in the range (inclusive). * @type {Array<Array<number>>} */ -const batteryIconsRanges = [ +const BATTERY_ICONS_RANGES = [ [0, 7], [8, 14], [15, 21], [22, 28], [29, 35], [36, 42], [43, 49], [50, 56], [57, 63], [64, 70], [71, 77], [78, 85], [86, 92], [93, 100] ]; @@ -39,9 +40,10 @@ * @constructor * @extends {PolymerElement} * @implements {I18nBehaviorInterface} + * @implements {FocusRowBehaviorInterface} */ const SettingsPairedBluetoothListItemElementBase = - mixinBehaviors([I18nBehavior], PolymerElement); + mixinBehaviors([I18nBehavior, FocusRowBehavior], PolymerElement); /** @polymer */ class SettingsPairedBluetoothListItemElement extends @@ -63,6 +65,15 @@ type: Object, }, + /** The index of this item in its parent list, used for its a11y label. */ + itemIndex: Number, + + /** + * The total number of elements in this item's parent list, used for its + * a11y label. + */ + listSize: Number, + /** @private {boolean} */ isBatteryPercentageAvailable_: { type: Boolean, @@ -201,7 +212,7 @@ // Range should always find a value because isBatteryPercentageAvailable_ // ensures batteryPercentage is within bounds. - const range = batteryIconsRanges.find(range => { + const range = BATTERY_ICONS_RANGES.find(range => { return range[0] <= batteryPercentage && batteryPercentage <= range[1]; }); assert( @@ -209,6 +220,87 @@ return 'os-settings:battery-' + range[0] + '-' + range[1]; } + + /** + * @param {!chromeos.bluetoothConfig.mojom.PairedBluetoothDeviceProperties} + * device + * @return {string} + * @private + */ + getAriaLabel_(device) { + const deviceName = this.getDeviceName_(device); + const deviceType = chromeos.bluetoothConfig.mojom.DeviceType; + let stringName; + switch (device.deviceProperties.deviceType) { + case deviceType.kComputer: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeComputerWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeComputer'; + break; + case deviceType.kPhone: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypePhoneWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypePhone'; + break; + case deviceType.kHeadset: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeHeadsetWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeHeadset'; + break; + case deviceType.kVideoCamera: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeVideoCameraWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeVideoCamera'; + break; + case deviceType.kGameController: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeGameControllerWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeGameController'; + break; + case deviceType.kKeyboard: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeKeyboardWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeKeyboard'; + break; + case deviceType.kMouse: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeMouseWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeMouse'; + break; + case deviceType.kTablet: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeTabletWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeTablet'; + break; + default: + stringName = this.isBatteryPercentageAvailable_ ? + 'bluetoothPairedDeviceItemA11yLabelTypeUnknownWithBatteryInfo' : + 'bluetoothPairedDeviceItemA11yLabelTypeUnknown'; + } + + if (!this.isBatteryPercentageAvailable_) { + return this.i18n( + stringName, this.itemIndex + 1, this.listSize, deviceName); + } + + const batteryPercentage = this.getBatteryPercentage_(device); + assert(batteryPercentage !== undefined); + return this.i18n( + stringName, this.itemIndex + 1, this.listSize, deviceName, + batteryPercentage); + } + + /** + * @param {!chromeos.bluetoothConfig.mojom.PairedBluetoothDeviceProperties} + * device + * @return {string} + * @private + */ + getSubpageButtonA11yLabel_(device) { + const deviceName = this.getDeviceName_(device); + return this.i18n( + 'bluetoothPairedDeviceItemSubpageButtonA11yLabel', deviceName); + } } customElements.define(
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/NoProtectionConfirmationDialog.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/NoProtectionConfirmationDialog.java index a2faec5..85b6b93 100644 --- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/NoProtectionConfirmationDialog.java +++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/NoProtectionConfirmationDialog.java
@@ -43,8 +43,9 @@ .with(ModalDialogProperties.CONTROLLER, makeController()) .with(ModalDialogProperties.TITLE, resources, R.string.safe_browsing_no_protection_confirmation_dialog_title) - .with(ModalDialogProperties.MESSAGE, resources, - R.string.safe_browsing_no_protection_confirmation_dialog_message) + .with(ModalDialogProperties.MESSAGE, + resources.getString( + R.string.safe_browsing_no_protection_confirmation_dialog_message)) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.safe_browsing_no_protection_confirmation_dialog_confirm) .with(ModalDialogProperties.PRIMARY_BUTTON_FILLED, true)
diff --git a/chrome/browser/service_sandbox_type.h b/chrome/browser/service_sandbox_type.h index 4b72e57f..1c3bbdf 100644 --- a/chrome/browser/service_sandbox_type.h +++ b/chrome/browser/service_sandbox_type.h
@@ -108,41 +108,6 @@ } #endif // !defined(OS_ANDROID) -// mirroring::mojom::MirroringService -namespace mirroring { -namespace mojom { -class MirroringService; -} -} // namespace mirroring -template <> -inline sandbox::policy::SandboxType -content::GetServiceSandboxType<mirroring::mojom::MirroringService>() { -#if defined(OS_MAC) - return sandbox::policy::SandboxType::kMirroring; -#else - return sandbox::policy::SandboxType::kUtility; -#endif // OS_MAC -} - -// printing::mojom::PrintingService -#if BUILDFLAG(ENABLE_PRINT_PREVIEW) -namespace printing { -namespace mojom { -class PrintingService; -} -} // namespace printing - -template <> -inline sandbox::policy::SandboxType -content::GetServiceSandboxType<printing::mojom::PrintingService>() { -#if defined(OS_WIN) - return sandbox::policy::SandboxType::kPdfConversion; -#else - return sandbox::policy::SandboxType::kUtility; -#endif -} -#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) - // printing::mojom::PrintBackendService #if (defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \ defined(OS_CHROMEOS)) && \
diff --git a/chrome/browser/share/share_ranking.cc b/chrome/browser/share/share_ranking.cc index 7f2df68..087af67f 100644 --- a/chrome/browser/share/share_ranking.cc +++ b/chrome/browser/share/share_ranking.cc
@@ -358,6 +358,8 @@ if (fix_more) computed_display_ranking[logical_fold] = kMoreTarget; + else + computed_display_ranking.push_back(kMoreTarget); *persisted_ranking = new_ranking; *display_ranking = computed_display_ranking; @@ -374,6 +376,8 @@ DCHECK(AtMostOneSlotChanged(old_ranking, *persisted_ranking, logical_fold)); DCHECK(NoEmptySlots(*display_ranking, logical_fold)); + DCHECK(RankingContains(*display_ranking, kMoreTarget)); + DCHECK_GE(persisted_ranking->size(), fold); } #endif // DCHECK_IS_ON()
diff --git a/chrome/browser/share/share_ranking_unittest.cc b/chrome/browser/share/share_ranking_unittest.cc index 59502db2..47d416f2 100644 --- a/chrome/browser/share/share_ranking_unittest.cc +++ b/chrome/browser/share/share_ranking_unittest.cc
@@ -61,7 +61,8 @@ // The "easy case": the existing usage counts are the same as the current // ranking, and every app in the ranking is available, so the new ranking and -// the displayed ranking should both be the same as the current ranking. +// the displayed ranking should both be the same as the current ranking, modulo +// the addition of the More target. TEST(ShareRankingStaticTest, CountsMatchOldRanking) { std::map<std::string, int> history = { {"bar", 2}, @@ -74,9 +75,11 @@ ShareRanking::ComputeRanking(history, history, current, {"foo", "bar", "baz"}, 3, false, &displayed, &persisted); - ASSERT_EQ(displayed.size(), current.size()); + + ShareRanking::Ranking expected_displayed{"foo", "bar", "baz", "$more"}; + ASSERT_EQ(displayed.size(), expected_displayed.size()); ASSERT_EQ(persisted.size(), current.size()); - EXPECT_EQ(displayed, current); + EXPECT_EQ(displayed, expected_displayed); EXPECT_EQ(persisted, current); } @@ -95,10 +98,7 @@ {"foo", "quxx", "baz", "blit"}, 4, false, &displayed, &persisted); ShareRanking::Ranking expected_displayed{ - "foo", - "blit", - "baz", - "quxx", + "foo", "blit", "baz", "quxx", "$more", }; EXPECT_EQ(displayed, expected_displayed); EXPECT_EQ(persisted, current); @@ -114,10 +114,7 @@ {"foo", "bar", "quxx", "baz", "blit"}, 4, false, &displayed, &persisted); ShareRanking::Ranking expected_displayed{ - "foo", - "bar", - "baz", - "blit", + "foo", "bar", "baz", "blit", "$more", }; ShareRanking::Ranking expected_persisted{"foo", "bar", "baz", "blit", "quxx"}; EXPECT_EQ(displayed, expected_displayed); @@ -133,12 +130,8 @@ ShareRanking::ComputeRanking({}, history, current, {"foo", "bar", "quxx", "baz", "blit"}, 4, false, &displayed, &persisted); - ShareRanking::Ranking expected_displayed{ - "foo", - "bar", - "baz", - "blit", - }; + ShareRanking::Ranking expected_displayed{"foo", "bar", "baz", "blit", + "$more"}; ShareRanking::Ranking expected_persisted{"foo", "bar", "baz", "blit", "quxx"}; EXPECT_EQ(displayed, expected_displayed); EXPECT_EQ(persisted, expected_persisted); @@ -210,7 +203,7 @@ // Note that since "abc" isn't available on the system, it won't appear in the // displayed ranking, but the persisted ranking should still get updated. - ShareRanking::Ranking expected_displayed{"foo", "bar", "baz"}; + ShareRanking::Ranking expected_displayed{"foo", "bar", "baz", "$more"}; ShareRanking::Ranking expected_persisted{"foo", "bar", "abc", "baz"}; EXPECT_EQ(displayed, expected_displayed);
diff --git a/chrome/browser/translate/chrome_translate_client.cc b/chrome/browser/translate/chrome_translate_client.cc index 63d81e15..ba68be6 100644 --- a/chrome/browser/translate/chrome_translate_client.cc +++ b/chrome/browser/translate/chrome_translate_client.cc
@@ -300,7 +300,6 @@ int ChromeTranslateClient::GetInfobarIconID() const { return IDR_ANDROID_INFOBAR_TRANSLATE; } -#endif void ChromeTranslateClient::ManualTranslateWhenReady() { if (GetLanguageState().source_language().empty()) { @@ -311,6 +310,7 @@ /*triggered_from_menu=*/true); } } +#endif void ChromeTranslateClient::SetPredefinedTargetLanguage( const std::string& translate_language_code) { @@ -360,11 +360,13 @@ GetTranslateManager()->NotifyLanguageDetected(details); } +#if defined(OS_ANDROID) + // See ChromeTranslateClient::ManualTranslateOnReady if (manual_translate_on_ready_) { - GetTranslateManager()->ShowTranslateUI(/*auto_translate=*/true, - /*triggered_from_menu=*/true); + GetTranslateManager()->ShowTranslateUI(/*auto_translate=*/true); manual_translate_on_ready_ = false; } +#endif } // The bubble is implemented only on the desktop platforms.
diff --git a/chrome/browser/translate/chrome_translate_client.h b/chrome/browser/translate/chrome_translate_client.h index 0b69cef..307b23b 100644 --- a/chrome/browser/translate/chrome_translate_client.h +++ b/chrome/browser/translate/chrome_translate_client.h
@@ -92,12 +92,11 @@ std::unique_ptr<translate::TranslateInfoBarDelegate> delegate) const override; int GetInfobarIconID() const override; -#endif // Trigger a manual translation when the necessary state (e.g. source // language) is ready. void ManualTranslateWhenReady(); - +#endif void SetPredefinedTargetLanguage(const std::string& translate_language_code); bool ShowTranslateUI(translate::TranslateStep step, @@ -145,9 +144,11 @@ per_frame_translate_driver_; std::unique_ptr<translate::TranslateManager> translate_manager_; +#if defined(OS_ANDROID) // Whether to trigger a manual translation when ready. // See ChromeTranslateClient::ManualTranslateOnReady bool manual_translate_on_ready_ = false; +#endif WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index f92d547a3..ad34128 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -295,4 +295,6 @@ /* package */ void setUrlActionContainerVisibility(int visibility) { mUrlActionContainer.setVisibility(visibility); } + + public void notifyVoiceRecognitionCanceled() {} }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java index 4b9f0a0..a142e8e 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarMediator.java
@@ -1253,6 +1253,11 @@ setUrlBarFocus(/*shouldBeFocused=*/false, /*pastedText=*/null, OmniboxFocusReason.UNFOCUS); } + @Override + public void notifyVoiceRecognitionCanceled() { + mLocationBarLayout.notifyVoiceRecognitionCanceled(); + } + // AssistantVoiceSearchService.Observer implementation. @Override
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index b220a7f..0f7cc6a 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -540,7 +540,7 @@ new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) .with(ModalDialogProperties.CONTROLLER, dialogController) .with(ModalDialogProperties.TITLE, suggestion.getDisplayText()) - .with(ModalDialogProperties.MESSAGE, resources, dialogMessageId) + .with(ModalDialogProperties.MESSAGE, resources.getString(dialogMessageId)) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.ok) .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources, R.string.cancel)
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java index 3826b94..cbec1a13 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/voice/VoiceRecognitionHandler.java
@@ -272,6 +272,9 @@ /** Clears omnibox focus, used to display the dialog when the keyboard is shown. */ void clearOmniboxFocus(); + + /** Notifies the delegate that voice recognition could not complete. */ + void notifyVoiceRecognitionCanceled(); } /** Interface for observers interested in updates to the voice state. */ @@ -466,10 +469,12 @@ mCallbackComplete = true; if (resultCode == Activity.RESULT_CANCELED) { recordVoiceSearchDismissedEvent(mSource, mTarget); + mDelegate.notifyVoiceRecognitionCanceled(); return; } if (resultCode != Activity.RESULT_OK || data.getExtras() == null) { recordVoiceSearchFailureEvent(mSource, mTarget); + mDelegate.notifyVoiceRecognitionCanceled(); return; } @@ -730,9 +735,16 @@ startTrackingQueryDuration(); WindowAndroid windowAndroid = mDelegate.getWindowAndroid(); - if (windowAndroid == null) return; + if (windowAndroid == null) { + mDelegate.notifyVoiceRecognitionCanceled(); + return; + } + Activity activity = windowAndroid.getActivity().get(); - if (activity == null) return; + if (activity == null) { + mDelegate.notifyVoiceRecognitionCanceled(); + return; + } if (FeatureList.isInitialized() && ChromeFeatureList.isEnabled( @@ -744,6 +756,7 @@ @Nullable PrefService prefService = getPrefService(); if (prefService == null || !prefService.getBoolean(Pref.AUDIO_CAPTURE_ALLOWED)) { + mDelegate.notifyVoiceRecognitionCanceled(); return; } } @@ -789,6 +802,7 @@ PermissionCallback callback = (permissions, grantResults) -> { if (grantResults.length != 1) { recordAudioPermissionStateEvent(AudioPermissionState.DENIED_CAN_ASK_AGAIN); + mDelegate.notifyVoiceRecognitionCanceled(); return; } @@ -799,8 +813,10 @@ } else if (!windowAndroid.canRequestPermission(Manifest.permission.RECORD_AUDIO)) { recordAudioPermissionStateEvent(AudioPermissionState.DENIED_CANNOT_ASK_AGAIN); notifyVoiceAvailabilityImpacted(); + mDelegate.notifyVoiceRecognitionCanceled(); } else { recordAudioPermissionStateEvent(AudioPermissionState.DENIED_CAN_ASK_AGAIN); + mDelegate.notifyVoiceRecognitionCanceled(); } }; windowAndroid.requestPermissions(new String[] {Manifest.permission.RECORD_AUDIO}, callback); @@ -813,7 +829,10 @@ Activity activity, WindowAndroid windowAndroid, @VoiceInteractionSource int source) { // Check if we need to request audio permissions. If we don't, then trigger a permissions // prompt will appear and startVoiceRecognition will be called again. - if (!ensureAudioPermissionGranted(activity, windowAndroid, source)) return false; + if (!ensureAudioPermissionGranted(activity, windowAndroid, source)) { + mDelegate.notifyVoiceRecognitionCanceled(); + return false; + } Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc index b4862ab..758789e 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.cc
@@ -4,8 +4,6 @@ #include "chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h" -#include <vector> - #include "ash/constants/ash_features.h" #include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_progress.h" @@ -19,9 +17,11 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/holding_space/holding_space_util.h" #include "components/download/public/common/download_item.h" +#include "components/download/public/common/simple_download_manager.h" #include "components/vector_icons/vector_icons.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/download_item_utils.h" +#include "content/public/browser/download_manager.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" @@ -32,8 +32,6 @@ namespace { -content::DownloadManager* download_manager_for_testing = nullptr; - // Helpers --------------------------------------------------------------------- // Returns a mojo download state converted from the specified item `state`. @@ -75,7 +73,9 @@ mojo_download_item->is_mixed_content = item->IsMixedContent(); mojo_download_item->has_is_mixed_content = true; - // NOTE: `browser_context` may be `nullptr` in tests. + // NOTE: `browser_context` may be `nullptr` in tests. We assume in this case + // that the item is not from an incognito profile; tests exercising incognito + // behavior should make sure `browser_context` is not `nullptr`. auto* browser_context = content::DownloadItemUtils::GetBrowserContext(item); mojo_download_item->is_from_incognito_profile = browser_context @@ -110,12 +110,6 @@ : nullptr; } -// Returns the download manager to use for the given `profile`. -content::DownloadManager* GetDownloadManager(Profile* profile) { - return download_manager_for_testing ? download_manager_for_testing - : profile->GetDownloadManager(); -} - // Returns whether the specified `mojo_download_item` is complete. bool IsComplete(const crosapi::mojom::DownloadItem* mojo_download_item) { return mojo_download_item->state == crosapi::mojom::DownloadState::kComplete; @@ -163,9 +157,11 @@ InProgressDownload(Type type, HoldingSpaceDownloadsDelegate* delegate, + content::DownloadManager* manager, crosapi::mojom::DownloadItemPtr mojo_download_item) : type_(type), delegate_(delegate), + manager_(manager), mojo_download_item_(std::move(mojo_download_item)) { DCHECK(IsInProgress(mojo_download_item_.get())); } @@ -345,6 +341,10 @@ return secondary_text; } + // Returns the download manager that originated this download. NOTE: This will + // be `nullptr` for Lacros downloads. + const content::DownloadManager* manager() const { return manager_; } + protected: // Updates the `mojo_download_item_` associated with this in-progress // download, notifying `delegate_` of the change in state. Note that invoking @@ -387,6 +387,7 @@ private: const Type type_; HoldingSpaceDownloadsDelegate* const delegate_; // NOTE: Owns `this`. + content::DownloadManager* const manager_; crosapi::mojom::DownloadItemPtr mojo_download_item_; // The in-progress holding space item associated with this in-progress @@ -409,9 +410,11 @@ public download::DownloadItem::Observer { public: InProgressAshDownload(HoldingSpaceDownloadsDelegate* delegate, + content::DownloadManager* manager, download::DownloadItem* download_item) : InProgressDownload(Type::kAsh, delegate, + manager, ConvertToMojoDownloadItem(download_item)), download_item_(download_item) { download_item_observation_.Observe(download_item); @@ -463,6 +466,7 @@ crosapi::mojom::DownloadItemPtr mojo_download_item) : InProgressDownload(Type::kLacros, delegate, + /*manager=*/nullptr, std::move(mojo_download_item)) { auto* const download_controller_ash = GetDownloadControllerAsh(); if (download_controller_ash) @@ -535,12 +539,6 @@ download_controller_ash->RemoveObserver(this); } -// static -void HoldingSpaceDownloadsDelegate::SetDownloadManagerForTesting( - content::DownloadManager* download_manager) { - download_manager_for_testing = download_manager; -} - void HoldingSpaceDownloadsDelegate::Cancel(const HoldingSpaceItem* item) { DCHECK(HoldingSpaceItem::IsDownload(item->type())); for (const auto& in_progress_download : in_progress_downloads_) { @@ -595,10 +593,7 @@ } // Ash Chrome downloads. - auto* const download_manager = GetDownloadManager(profile()); - download_manager_observation_.Observe(download_manager); - if (download_manager->IsManagerInitialized()) - OnManagerInitialized(); + download_notifier_.AddProfile(profile()); // Lacros Chrome downloads. auto* const download_controller_ash = GetDownloadControllerAsh(); @@ -619,6 +614,54 @@ }); } +void HoldingSpaceDownloadsDelegate::OnManagerInitialized( + content::DownloadManager* manager) { + DCHECK(!is_restoring_persistence()); + download::SimpleDownloadManager::DownloadVector downloads; + manager->GetAllDownloads(&downloads); + for (auto* download : downloads) + OnDownloadCreated(manager, download); +} + +void HoldingSpaceDownloadsDelegate::OnManagerGoingDown( + content::DownloadManager* manager) { + // Collect all downloads associated with `manager`. These downloads will be + // removed from `in_progress_downloads_` on failure, so they cannot be failed + // in a loop that iterates over `in_progress_downloads_`. + std::set<InProgressDownload*> downloads_to_remove; + for (const auto& in_progress_download : in_progress_downloads_) { + if (in_progress_download->manager() == manager) + downloads_to_remove.insert(in_progress_download.get()); + } + + // Fail all of `manager`'s downloads. + for (InProgressDownload* in_progress_download : downloads_to_remove) + OnDownloadFailed(in_progress_download); +} + +void HoldingSpaceDownloadsDelegate::OnDownloadCreated( + content::DownloadManager* manager, + download::DownloadItem* download_item) { + DCHECK(!is_restoring_persistence()); + if (IsInProgress(download_item)) { + in_progress_downloads_.emplace( + std::make_unique<InProgressAshDownload>(this, manager, download_item)); + } +} + +// Override to avoid hiding `OnDownloadUpdated(InProgressDownload*, bool)`. +void HoldingSpaceDownloadsDelegate::OnDownloadUpdated( + content::DownloadManager* manager, + download::DownloadItem* download_item) { + // TODO(crbug.com/1240644): Create an `InProgressDownload` here if one does + // not already exist, e.g., because the download was interrupted and resumed. +} + +bool HoldingSpaceDownloadsDelegate::ShouldObserveProfile(Profile* profile) { + return !profile->IsIncognitoProfile() || + features::IsHoldingSpaceIncognitoProfileIntegrationEnabled(); +} + void HoldingSpaceDownloadsDelegate::OnArcDownloadAdded( const base::FilePath& relative_path, const std::string& owner_package_name) { @@ -646,46 +689,6 @@ service()->AddDownload(HoldingSpaceItem::Type::kArcDownload, path); } -void HoldingSpaceDownloadsDelegate::OnManagerInitialized() { - if (is_restoring_persistence()) - return; - - content::DownloadManager* download_manager = GetDownloadManager(profile()); - DCHECK(download_manager->IsManagerInitialized()); - - download::SimpleDownloadManager::DownloadVector downloads; - download_manager->GetAllDownloads(&downloads); - - for (download::DownloadItem* download_item : downloads) { - if (IsInProgress(download_item)) { - in_progress_downloads_.emplace( - std::make_unique<InProgressAshDownload>(this, download_item)); - } - } -} - -void HoldingSpaceDownloadsDelegate::ManagerGoingDown( - content::DownloadManager* manager) { - download_manager_observation_.Reset(); - base::EraseIf(in_progress_downloads_, [](const auto& in_progress_download) { - return in_progress_download->GetType() == InProgressDownload::Type::kAsh; - }); -} - -void HoldingSpaceDownloadsDelegate::OnDownloadCreated( - content::DownloadManager* manager, - download::DownloadItem* download_item) { - // Ignore `OnDownloadCreated()` events prior to `manager` initialization. For - // those events we create any objects necessary in `OnManagerInitialized()`. - if (is_restoring_persistence() || !manager->IsManagerInitialized()) - return; - - if (IsInProgress(download_item)) { - in_progress_downloads_.emplace( - std::make_unique<InProgressAshDownload>(this, download_item)); - } -} - void HoldingSpaceDownloadsDelegate::OnLacrosDownloadCreated( const crosapi::mojom::DownloadItem& mojo_download_item) { if (mojo_download_item.is_from_incognito_profile &&
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h index d34bb73..9757c90 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h +++ b/chrome/browser/ui/ash/holding_space/holding_space_downloads_delegate.h
@@ -8,28 +8,33 @@ #include <memory> #include <set> #include <string> +#include <vector> #include "base/containers/unique_ptr_adapters.h" #include "base/scoped_observation.h" #include "chrome/browser/ash/crosapi/download_controller_ash.h" +#include "chrome/browser/download/notification/multi_profile_download_notifier.h" #include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_delegate.h" #include "chromeos/crosapi/mojom/download_controller.mojom-forward.h" #include "components/arc/intent_helper/arc_intent_helper_bridge.h" #include "components/arc/intent_helper/arc_intent_helper_observer.h" -#include "content/public/browser/download_manager.h" namespace base { class FilePath; } // namespace base +namespace content { +class DownloadManager; +} // namespace content + namespace ash { // A delegate of `HoldingSpaceKeyedService` tasked with monitoring the status of // of downloads on its behalf. class HoldingSpaceDownloadsDelegate : public HoldingSpaceKeyedServiceDelegate, + public MultiProfileDownloadNotifier::Client, public arc::ArcIntentHelperObserver, - public content::DownloadManager::Observer, public crosapi::DownloadControllerAsh::DownloadControllerObserver { public: HoldingSpaceDownloadsDelegate(HoldingSpaceKeyedService* service, @@ -39,11 +44,6 @@ const HoldingSpaceDownloadsDelegate&) = delete; ~HoldingSpaceDownloadsDelegate() override; - // Sets the `content::DownloadManager` to be used for testing. - // NOTE: This method must be called prior to delegate initialization. - static void SetDownloadManagerForTesting( - content::DownloadManager* download_manager); - // Attempts to cancel/pause/resume the download underlying the given `item`. void Cancel(const HoldingSpaceItem* item); void Pause(const HoldingSpaceItem* item); @@ -63,16 +63,19 @@ void OnHoldingSpaceItemsRemoved( const std::vector<const HoldingSpaceItem*>& items) override; + // MultiProfileDownloadNotifier::Client: + void OnManagerInitialized(content::DownloadManager* manager) override; + void OnManagerGoingDown(content::DownloadManager* manager) override; + void OnDownloadCreated(content::DownloadManager* manager, + download::DownloadItem* item) override; + void OnDownloadUpdated(content::DownloadManager* manager, + download::DownloadItem* item) override; + bool ShouldObserveProfile(Profile* profile) override; + // arc::ArcIntentHelperObserver: void OnArcDownloadAdded(const base::FilePath& relative_path, const std::string& owner_package_name) override; - // content::DownloadManager::Observer: - void OnManagerInitialized() override; - void ManagerGoingDown(content::DownloadManager* manager) override; - void OnDownloadCreated(content::DownloadManager* manager, - download::DownloadItem* download_item) override; - // crosapi::DownloadControllerAsh::DownloadControllerObserver: void OnLacrosDownloadCreated( const crosapi::mojom::DownloadItem& mojo_download_item) override; @@ -124,9 +127,13 @@ arc::ArcIntentHelperObserver> arc_intent_helper_observation_{this}; - base::ScopedObservation<content::DownloadManager, - content::DownloadManager::Observer> - download_manager_observation_{this}; + // Notifies this delegate of download events created for the profile + // associated with this delegate's service. If the incognito profile + // integration feature is enabled, the delegate is also notified of download + // events created for incognito profiles spawned from the service's main + // profile. + MultiProfileDownloadNotifier download_notifier_{ + this, /*wait_for_manager_initialization=*/true}; base::WeakPtrFactory<HoldingSpaceDownloadsDelegate> weak_factory_{this}; };
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc index 0ab3831..691d4f1 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_keyed_service_unittest.cc
@@ -282,6 +282,11 @@ observers_.RemoveObserver(observer); } + void Shutdown() override { + for (auto& observer : observers_) + observer.ManagerGoingDown(this); + } + void NotifyDownloadCreated(download::DownloadItem* item) { for (auto& observer : observers_) observer.OnDownloadCreated(this, item); @@ -314,7 +319,6 @@ // Needed by `file_manager::VolumeManager`. chromeos::disks::DiskMountManager::InitializeForTesting( new file_manager::FakeDiskMountManager); - SetUpDownloadManager(); BrowserWithTestWindowTest::SetUp(); holding_space_util::SetNowForTesting(absl::nullopt); } @@ -322,7 +326,6 @@ void TearDown() override { BrowserWithTestWindowTest::TearDown(); chromeos::disks::DiskMountManager::Shutdown(); - HoldingSpaceDownloadsDelegate::SetDownloadManagerForTesting(nullptr); } TestingProfile* CreateProfile() override { @@ -335,13 +338,15 @@ GetSessionControllerClient()->AddUserSession(kPrimaryProfileName); GetSessionControllerClient()->SwitchActiveUser(account_id); - return profile_manager()->CreateTestingProfile( + TestingProfile* profile = profile_manager()->CreateTestingProfile( kPrimaryProfileName, /*testing_factories=*/{ {arc::ArcIntentHelperBridge::GetFactory(), base::BindRepeating(&BuildArcIntentHelperBridge)}, {file_manager::VolumeManagerFactory::GetInstance(), base::BindRepeating(&BuildVolumeManager)}}); + SetUpDownloadManager(profile); + return profile; } TestingProfile* CreateSecondaryProfile( @@ -350,7 +355,7 @@ const AccountId account_id(AccountId::FromUserEmail(kSecondaryProfileName)); fake_user_manager_->AddUser(account_id); fake_user_manager_->LoginUser(account_id); - return profile_manager()->CreateTestingProfile( + TestingProfile* profile = profile_manager()->CreateTestingProfile( kSecondaryProfileName, std::move(prefs), u"Test profile", 1 /*avatar_id*/, std::string() /*supervised_user_id*/, /*testing_factories=*/ @@ -358,6 +363,8 @@ base::BindRepeating(&BuildArcIntentHelperBridge)}, {file_manager::VolumeManagerFactory::GetInstance(), base::BindRepeating(&BuildVolumeManager)}}); + SetUpDownloadManager(profile); + return profile; } using PopulatePrefStoreCallback = base::OnceCallback<void(TestingPrefStore*)>; @@ -437,9 +444,11 @@ return result; } - // Creates and returns a fake download item with the specified `state`, - // `file_path`, `target_file_path`, `received_bytes`, and `total_bytes`. + // Creates and returns a fake download item for `profile` with the specified + // `state`, `file_path`, `target_file_path`, `received_bytes`, and + // `total_bytes`. std::unique_ptr<content::FakeDownloadItem> CreateFakeDownloadItem( + Profile* profile, download::DownloadItem::DownloadState state, const base::FilePath& file_path, const base::FilePath& target_file_path, @@ -453,29 +462,26 @@ fake_download_item->SetTotalBytes(total_bytes); // Notify observers of the created download. - download_manager()->NotifyDownloadCreated(fake_download_item.get()); + download_managers_[profile]->NotifyDownloadCreated( + fake_download_item.get()); return fake_download_item; } - MockDownloadManager* download_manager() { return &download_manager_; } - - private: - void SetUpDownloadManager() { - // The `content::DownloadManager` needs to be set prior to initialization - // of the `HoldingSpaceDownloadsDelegate`. This must happen before the - // `HoldingSpaceKeyedService` is created for the profile under test. - MockDownloadManager* mock_download_manager = download_manager(); - HoldingSpaceDownloadsDelegate::SetDownloadManagerForTesting( - mock_download_manager); - - // Spoof initialization of the `mock_download_manager`. - ON_CALL(*mock_download_manager, IsManagerInitialized) + protected: + // Creates a `MockDownloadManager` for `profile` to use. + void SetUpDownloadManager(Profile* profile) { + auto manager = std::make_unique<testing::NiceMock<MockDownloadManager>>(); + ON_CALL(*manager, IsManagerInitialized) .WillByDefault(testing::Return(true)); + download_managers_[profile] = manager.get(); + profile->SetDownloadManagerForTesting(std::move(manager)); } + private: FakeChromeUserManager* fake_user_manager_; user_manager::ScopedUserManager user_manager_enabler_; - testing::NiceMock<MockDownloadManager> download_manager_; + std::map<Profile*, testing::NiceMock<MockDownloadManager>*> + download_managers_; arc::ArcServiceManager arc_service_manager_; }; @@ -1579,7 +1585,7 @@ // Verifies that screenshots restored from persistence are not older than // kMaxFileAge. -TEST_F(HoldingSpaceKeyedServiceTest, RemoveOlderFilesFromPersistance) { +TEST_F(HoldingSpaceKeyedServiceTest, RemoveOlderFilesFromPersistence) { // Create file system mount point. std::unique_ptr<ScopedTestMountPoint> downloads_mount = ScopedTestMountPoint::CreateAndMountDownloads(GetProfile()); @@ -1702,7 +1708,7 @@ // Create a fake in-progress download item and cache a function to update it. std::unique_ptr<content::FakeDownloadItem> fake_download_item = - CreateFakeDownloadItem(current_state, current_path, + CreateFakeDownloadItem(profile, current_state, current_path, /*target_file_path=*/base::FilePath(), current_received_bytes, current_total_bytes); auto UpdateFakeDownloadItem = [&]() { @@ -1768,8 +1774,9 @@ // Create a fake download item and cache a function to update it. std::unique_ptr<content::FakeDownloadItem> fake_download_item = - CreateFakeDownloadItem(current_state, current_path, current_target_path, - current_received_bytes, current_total_bytes); + CreateFakeDownloadItem(profile, current_state, current_path, + current_target_path, current_received_bytes, + current_total_bytes); auto UpdateFakeDownloadItem = [&]() { fake_download_item->SetDummyFilePath(current_path); fake_download_item->SetReceivedBytes(current_received_bytes); @@ -1867,9 +1874,9 @@ current_path = base::FilePath(); current_target_path = base::FilePath(); current_received_bytes = 0; - fake_download_item = - CreateFakeDownloadItem(current_state, current_path, current_target_path, - current_received_bytes, current_total_bytes); + fake_download_item = CreateFakeDownloadItem( + profile, current_state, current_path, current_target_path, + current_received_bytes, current_total_bytes); // Verify that no holding space item has been created since the download does // not yet have file path set. @@ -2214,7 +2221,8 @@ } // Base class for tests of print-to-PDF integration. Parameterized by whether -// tests should use an incognito browser. +// tests should use an incognito browser and whether the holding space incognito +// profile feature is enabled. class HoldingSpaceKeyedServicePrintToPdfIntegrationTest : public HoldingSpaceKeyedServiceTest, public testing::WithParamInterface< @@ -2323,4 +2331,180 @@ EXPECT_EQ(model->items()[0]->file_path(), file_path); } +// Base class for tests of incognito profile integration. Parameterized by +// whether the holding space incognito profile feature is enabled. +class HoldingSpaceKeyedServiceIncognitoDownloadsTest + : public HoldingSpaceKeyedServiceTest, + public testing::WithParamInterface< + bool /* incognito_downloads_enabled */> { + public: + HoldingSpaceKeyedServiceIncognitoDownloadsTest() { + scoped_feature_list_.InitWithFeatureState( + features::kHoldingSpaceIncognitoProfileIntegration, + IncognitoDownloadsEnabled()); + } + + // HoldingSpaceKeyedServiceTest: + TestingProfile* CreateProfile() override { + TestingProfile* profile = HoldingSpaceKeyedServiceTest::CreateProfile(); + + // Construct an incognito profile from the primary profile. + TestingProfile::Builder incognito_profile_builder; + incognito_profile_builder.SetProfileName(profile->GetProfileUserName()); + incognito_profile_ = incognito_profile_builder.BuildIncognito(profile); + EXPECT_TRUE(incognito_profile_); + EXPECT_TRUE(incognito_profile_->IsIncognitoProfile()); + SetUpDownloadManager(incognito_profile_); + EXPECT_NE(incognito_profile_->GetDownloadManager(), + profile->GetDownloadManager()); + + return profile; + } + + // Returns true if the test should run with the incognito profile feature + // enabled, false otherwise. + bool IncognitoDownloadsEnabled() const { return GetParam(); } + + // Returns the incognito profile spawned from the test's main profile. + TestingProfile* incognito_profile() { return incognito_profile_; } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + TestingProfile* incognito_profile_ = nullptr; +}; + +INSTANTIATE_TEST_SUITE_P(All, + HoldingSpaceKeyedServiceIncognitoDownloadsTest, + /*incognito_downloads_enabled=*/::testing::Bool()); + +TEST_P(HoldingSpaceKeyedServiceIncognitoDownloadsTest, AddDownloadItem) { + TestingProfile* profile = GetProfile(); + HoldingSpaceModelAttachedWaiter(profile).Wait(); + + // Create a test downloads mount point. + std::unique_ptr<ScopedTestMountPoint> downloads_mount = + ScopedTestMountPoint::CreateAndMountDownloads(profile); + ASSERT_TRUE(downloads_mount->IsValid()); + + // Cache current state, file path, received bytes, and total bytes. + auto current_state = download::DownloadItem::IN_PROGRESS; + base::FilePath current_path; + int64_t current_received_bytes = 0; + int64_t current_total_bytes = 100; + + // Create a fake in-progress download item for the incognito profile and cache + // a function to update it. + std::unique_ptr<content::FakeDownloadItem> fake_download_item = + CreateFakeDownloadItem(incognito_profile(), current_state, current_path, + /*target_file_path=*/base::FilePath(), + current_received_bytes, current_total_bytes); + auto UpdateFakeDownloadItem = [&]() { + fake_download_item->SetDummyFilePath(current_path); + fake_download_item->SetReceivedBytes(current_received_bytes); + fake_download_item->SetState(current_state); + fake_download_item->SetTotalBytes(current_total_bytes); + fake_download_item->NotifyDownloadUpdated(); + }; + + // Verify holding space is empty. + HoldingSpaceModel* const model = HoldingSpaceController::Get()->model(); + ASSERT_EQ(0u, model->items().size()); + + // Update the file path for the download. + current_path = downloads_mount->CreateFile(base::FilePath("tmp/temp_path")); + UpdateFakeDownloadItem(); + + // Verify holding space is empty. + ASSERT_EQ(0u, model->items().size()); + + // Complete the download. + current_state = download::DownloadItem::COMPLETE; + current_path = downloads_mount->CreateFile(base::FilePath("tmp/final_path")); + current_received_bytes = current_total_bytes; + UpdateFakeDownloadItem(); + + // Verify that a holding space item is created if and only if the incognito + // profile feature is enabled. + if (!IncognitoDownloadsEnabled()) { + ASSERT_EQ(model->items().size(), 0u); + return; + } + + ASSERT_EQ(1u, model->items().size()); + HoldingSpaceItem* download_item = model->items()[0].get(); + EXPECT_EQ(download_item->type(), HoldingSpaceItem::Type::kDownload); + EXPECT_EQ(download_item->file_path(), current_path); + EXPECT_TRUE(download_item->progress().IsComplete()); +} + +TEST_P(HoldingSpaceKeyedServiceIncognitoDownloadsTest, + AddInProgressDownloadItem) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + features::kHoldingSpaceInProgressDownloadsIntegration); + + TestingProfile* profile = GetProfile(); + HoldingSpaceModelAttachedWaiter(profile).Wait(); + + // Verify the holding space model is empty. + HoldingSpaceModel* const model = HoldingSpaceController::Get()->model(); + ASSERT_TRUE(model); + EXPECT_EQ(model->items().size(), 0u); + + // Create a test downloads mount point. + std::unique_ptr<ScopedTestMountPoint> downloads_mount = + ScopedTestMountPoint::CreateAndMountDownloads(profile); + ASSERT_TRUE(downloads_mount->IsValid()); + + // Cache current state, file paths, received bytes, and total bytes. + auto current_state = download::DownloadItem::IN_PROGRESS; + base::FilePath current_path; + base::FilePath current_target_path; + int64_t current_received_bytes = 0; + int64_t current_total_bytes = 100; + bool current_is_dangerous = false; + + // Create a fake download item and cache a function to update it. + std::unique_ptr<content::FakeDownloadItem> fake_download_item = + CreateFakeDownloadItem(incognito_profile(), current_state, current_path, + current_target_path, current_received_bytes, + current_total_bytes); + auto UpdateFakeDownloadItem = [&]() { + fake_download_item->SetDummyFilePath(current_path); + fake_download_item->SetReceivedBytes(current_received_bytes); + fake_download_item->SetState(current_state); + fake_download_item->SetTargetFilePath(current_target_path); + fake_download_item->SetTotalBytes(current_total_bytes); + fake_download_item->SetIsDangerous(current_is_dangerous); + fake_download_item->NotifyDownloadUpdated(); + }; + + // Verify that no holding space item has been created since the download does + // not yet have file path set. + EXPECT_EQ(model->items().size(), 0u); + + // Update the file paths for the download. + current_path = downloads_mount->CreateFile(base::FilePath("foo.crdownload")); + current_target_path = downloads_mount->CreateFile(base::FilePath("foo.png")); + UpdateFakeDownloadItem(); + + // Verify that a holding space item is created if and only if the incognito + // profile feature is enabled. + if (!IncognitoDownloadsEnabled()) { + ASSERT_EQ(model->items().size(), 0u); + return; + } + + ASSERT_EQ(1u, model->items().size()); + HoldingSpaceItem* download_item = model->items()[0].get(); + EXPECT_EQ(download_item->type(), HoldingSpaceItem::Type::kDownload); + EXPECT_EQ(download_item->file_path(), current_path); + EXPECT_FALSE(download_item->progress().IsComplete()); + + // Verify that destroying a profile with an in-progress download destroys + // the holding space item. + profile->DestroyOffTheRecordProfile(incognito_profile()); + ASSERT_EQ(0u, model->items().size()); +} + } // namespace ash
diff --git a/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc b/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc index 2d86e97..9ca918a 100644 --- a/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc +++ b/chrome/browser/ui/ash/holding_space/holding_space_ui_browsertest.cc
@@ -1359,6 +1359,7 @@ HoldingSpaceKeyedServiceFactory::SetTestingFactory(base::NullCallback()); } + // HoldingSpaceUiBrowserTest: void SetUpOnMainThread() override { HoldingSpaceUiBrowserTest::SetUpOnMainThread();
diff --git a/chrome/browser/ui/global_media_controls/cast_media_session_controller.cc b/chrome/browser/ui/global_media_controls/cast_media_session_controller.cc index 6ac80f6..79d7050f 100644 --- a/chrome/browser/ui/global_media_controls/cast_media_session_controller.cc +++ b/chrome/browser/ui/global_media_controls/cast_media_session_controller.cc
@@ -68,6 +68,7 @@ case media_session::mojom::MediaSessionAction::kToggleCamera: case media_session::mojom::MediaSessionAction::kHangUp: case media_session::mojom::MediaSessionAction::kRaise: + case media_session::mojom::MediaSessionAction::kSetMute: NOTREACHED(); return; }
diff --git a/chrome/browser/ui/global_media_controls/media_session_notification_item.cc b/chrome/browser/ui/global_media_controls/media_session_notification_item.cc index d44c82f..e0e1d42 100644 --- a/chrome/browser/ui/global_media_controls/media_session_notification_item.cc +++ b/chrome/browser/ui/global_media_controls/media_session_notification_item.cc
@@ -71,8 +71,10 @@ MaybeUnfreeze(); MaybeHideOrShowNotification(); - if (view_ && !frozen_) + if (view_ && !frozen_) { view_->UpdateWithMediaSessionInfo(session_info_); + view_->UpdateWithMuteStatus(session_info_->muted); + } } void MediaSessionNotificationItem::MediaSessionMetadataChanged( @@ -153,6 +155,7 @@ view_->UpdateWithMediaSessionInfo(session_info_); view_->UpdateWithMediaMetadata(session_metadata_); view_->UpdateWithMediaActions(session_actions_); + view_->UpdateWithMuteStatus(session_info_->muted); if (session_position_.has_value()) view_->UpdateWithMediaPosition(*session_position_); @@ -196,6 +199,11 @@ media_controller_remote_->Raise(); } +void MediaSessionNotificationItem::SetMute(bool mute) { + if (!frozen_) + media_controller_remote_->SetMute(mute); +} + void MediaSessionNotificationItem::SetController( mojo::Remote<media_session::mojom::MediaController> controller, media_session::mojom::MediaSessionInfoPtr session_info) { @@ -310,6 +318,7 @@ view_->UpdateWithMediaSessionInfo(session_info_); view_->UpdateWithMediaMetadata(session_metadata_); view_->UpdateWithMediaActions(session_actions_); + view_->UpdateWithMuteStatus(session_info_->muted); if (session_position_.has_value()) view_->UpdateWithMediaPosition(*session_position_);
diff --git a/chrome/browser/ui/global_media_controls/media_session_notification_item.h b/chrome/browser/ui/global_media_controls/media_session_notification_item.h index 6723ee4..10b59aa 100644 --- a/chrome/browser/ui/global_media_controls/media_session_notification_item.h +++ b/chrome/browser/ui/global_media_controls/media_session_notification_item.h
@@ -92,7 +92,7 @@ void Dismiss() override; media_message_center::SourceType SourceType() override; void SetVolume(float volume) override {} - void SetMute(bool mute) override {} + void SetMute(bool mute) override; // Calls |Raise()| on the underlying MediaSession, which will focus the // WebContents if the MediaSession is associated with one.
diff --git a/chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.cc b/chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.cc index c4b1d4b..88e04a9 100644 --- a/chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.cc +++ b/chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.h" +#include "base/callback.h" #include "base/check.h" #include "base/logging.h" #include "base/macros.h"
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc index 6dec3a06..1e6682f1 100644 --- a/chrome/browser/ui/views/download/download_item_view.cc +++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -912,8 +912,15 @@ void DownloadItemView::UpdateAccessibleAlertAndAnimationsForNormalMode() { using State = download::DownloadItem::DownloadState; const State state = model_->GetState(); + const std::u16string web_drive = model_->GetWebDriveName(); if ((state == State::IN_PROGRESS) && !model_->IsPaused()) { - UpdateAccessibleAlert(GetInProgressAccessibleAlertText()); + if (web_drive.empty()) { + UpdateAccessibleAlert(GetInProgressAccessibleAlertText()); + } else { + announce_accessible_alert_soon_ = true; + UpdateAccessibleAlert( + l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_UPLOADING, web_drive)); + } if (!indeterminate_progress_timer_.IsRunning()) { indeterminate_progress_start_time_ = base::TimeTicks::Now(); @@ -944,8 +951,17 @@ {State::COMPLETE, IDS_DOWNLOAD_COMPLETE_ACCESSIBLE_ALERT}, {State::CANCELLED, IDS_DOWNLOAD_CANCELLED_ACCESSIBLE_ALERT}, }); - const std::u16string alert_text = l10n_util::GetStringFUTF16( - kMap.at(state), model_->GetFileNameToReportUser().LossyDisplayName()); + const std::u16string alert_text = + (web_drive.empty() || state == State::CANCELLED) + ? l10n_util::GetStringFUTF16( + kMap.at(state), + model_->GetFileNameToReportUser().LossyDisplayName()) + // When the file is rereouted to web drive and not cancelled, use + // regular string formulated in DownloadUIModel. + // TODO(https://crbug.com/1240372) Update with accessibility + // specific localized strings. + : model_->GetStatusText(); + announce_accessible_alert_soon_ = true; UpdateAccessibleAlert(alert_text); }
diff --git a/chrome/browser/ui/views/external_protocol_dialog.cc b/chrome/browser/ui/views/external_protocol_dialog.cc index 264af90..cf4fc1b 100644 --- a/chrome/browser/ui/views/external_protocol_dialog.cc +++ b/chrome/browser/ui/views/external_protocol_dialog.cc
@@ -75,7 +75,7 @@ const GURL& url, const std::u16string& program_name, const absl::optional<url::Origin>& initiating_origin) - : content::WebContentsObserver(web_contents), + : web_contents_(web_contents->GetWeakPtr()), url_(url), program_name_(program_name), initiating_origin_(initiating_origin) { @@ -156,7 +156,7 @@ ExternalProtocolHandler::RecordHandleStateMetrics( remember, ExternalProtocolHandler::DONT_BLOCK); - if (!web_contents()) { + if (!web_contents_) { // Dialog outlasted the WebContents. return; } @@ -164,14 +164,15 @@ if (remember) { DCHECK(initiating_origin_); Profile* profile = - Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + Profile::FromBrowserContext(web_contents_->GetBrowserContext()); ExternalProtocolHandler::SetBlockState(url_.scheme(), *initiating_origin_, ExternalProtocolHandler::DONT_BLOCK, profile); } - ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_, web_contents()); + ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_, + web_contents_.get()); } views::View* ExternalProtocolDialog::GetContentsView() {
diff --git a/chrome/browser/ui/views/external_protocol_dialog.h b/chrome/browser/ui/views/external_protocol_dialog.h index b2e0cf3f..c8e9996 100644 --- a/chrome/browser/ui/views/external_protocol_dialog.h +++ b/chrome/browser/ui/views/external_protocol_dialog.h
@@ -6,8 +6,8 @@ #define CHROME_BROWSER_UI_VIEWS_EXTERNAL_PROTOCOL_DIALOG_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/profiles/profile.h" -#include "content/public/browser/web_contents_observer.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/window/dialog_delegate.h" #include "url/gurl.h" @@ -25,8 +25,7 @@ class MessageBoxView; } -class ExternalProtocolDialog : public views::DialogDelegateView, - public content::WebContentsObserver { +class ExternalProtocolDialog : public views::DialogDelegateView { public: METADATA_HEADER(ExternalProtocolDialog); // Show by calling ExternalProtocolHandler::RunExternalProtocolDialog(). @@ -52,6 +51,8 @@ void SetRememberSelectionCheckboxCheckedForTesting(bool checked); void OnDialogAccepted(); + base::WeakPtr<content::WebContents> web_contents_; + const GURL url_; const std::u16string program_name_; const absl::optional<url::Origin> initiating_origin_;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc index d787e397..f2925b8 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc
@@ -551,8 +551,16 @@ EXPECT_EQ(u"onresize", title_watcher2.WaitAndGetTitle()); } +// TODO(https://crbug.com/1234323): Very flaky on Wayland builder. +#if defined(OS_LINUX) +#define MAYBE_WindowControlsOverlayDraggableRegions \ + DISABLED_WindowControlsOverlayDraggableRegions +#else +#define MAYBE_WindowControlsOverlayDraggableRegions \ + WindowControlsOverlayDraggableRegions +#endif // defined(OS_LINUX) IN_PROC_BROWSER_TEST_F(WebAppOpaqueBrowserFrameViewWindowControlsOverlayTest, - WindowControlsOverlayDraggableRegions) { + MAYBE_WindowControlsOverlayDraggableRegions) { if (!InstallAndLaunchWebAppWithWindowControlsOverlay()) return;
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc index 01f1c517..d91e24b 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
@@ -122,16 +122,18 @@ if (reason == USER_GESTURE) { GetWidget()->Show(); } else { - GetWidget()->ShowInactive(); - +// TODO(crbug.com/1186729): Reenable this announcement on Mac when the keyboard +// shortcut to reach it gets a keybinding and is verified to work. This will +// also require a string update with the new key binding on Mac. +#if !defined(OS_MAC) if (allow_refocus_alert) { - // Since this widget is inactive (but shown), accessibility tools won't - // alert the user to its presence. Accessibility tools such as screen - // readers work by tracking system focus. Give users of these tools a hint - // description and alert them to the presence of this widget. + // Since this will show as inactive, add a description for how to get to + // it. GetWidget()->GetRootView()->GetViewAccessibility().OverrideDescription( l10n_util::GetStringUTF8(IDS_SHOW_BUBBLE_INACTIVE_DESCRIPTION)); } +#endif + GetWidget()->ShowInactive(); } }
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index a36c248..e13ae10 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -203,7 +203,7 @@ void OmniboxViewViews::Init() { set_controller(this); - SetTextInputType(ui::TEXT_INPUT_TYPE_URL); + SetTextInputType(GetPreferredTextInputType()); GetRenderText()->SetElideBehavior(gfx::ELIDE_TAIL); GetRenderText()->set_symmetric_selection_visual_bounds(true); InstallPlaceholderText(); @@ -531,6 +531,13 @@ void OmniboxViewViews::OnInputMethodChanged() { #if defined(OS_WIN) + // Update the input type with the input method on Windows for CJK. + SetTextInputType(GetPreferredTextInputType()); +#endif // OS_WIN +} + +ui::TextInputType OmniboxViewViews::GetPreferredTextInputType() const { +#if defined(OS_WIN) // We'd like to set the text input type to TEXT_INPUT_TYPE_URL, because this // triggers URL-specific layout in software keyboards, e.g. adding top-level // "/" and ".com" keys for English. However, this also causes IMEs to default @@ -541,11 +548,10 @@ ui::InputMethod* input_method = location_bar_view_->GetWidget()->GetInputMethod(); if (input_method && input_method->IsInputLocaleCJK()) - SetTextInputType(ui::TEXT_INPUT_TYPE_SEARCH); - else - SetTextInputType(ui::TEXT_INPUT_TYPE_URL); + return ui::TEXT_INPUT_TYPE_SEARCH; } -#endif +#endif // OS_WIN + return ui::TEXT_INPUT_TYPE_URL; } void OmniboxViewViews::AddedToWidget() {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h index 206c174..05a7703 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -225,6 +225,9 @@ void AnnounceFriendlySuggestionText(); #endif + // Get the preferred text input type, this checks the IME locale on Windows. + ui::TextInputType GetPreferredTextInputType() const; + // OmniboxView: void SetCaretPos(size_t caret_pos) override; void UpdatePopup() override;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc index 74112d7..cc9f1d40 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -881,6 +881,21 @@ omnibox_view_views->OnInputMethodChanged(); EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, omnibox_view_views->GetTextInputType()); } + +IN_PROC_BROWSER_TEST_F(OmniboxViewViewsIMETest, TextInputTypeInitRespectsIME) { + OmniboxMockInputMethod* input_method = new OmniboxMockInputMethod(); + ui::SetUpInputMethodForTesting(input_method); + input_method->SetInputLocaleCJK(/*is_cjk=*/true); + Browser* browser_2 = CreateBrowser(browser()->profile()); + OmniboxView* view = nullptr; + ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser_2, &view)); + OmniboxViewViews* omnibox_view_views = static_cast<OmniboxViewViews*>(view); + EXPECT_EQ(omnibox_view_views->GetWidget()->GetInputMethod(), input_method); + EXPECT_EQ(ui::TEXT_INPUT_TYPE_SEARCH, omnibox_view_views->GetTextInputType()); + input_method->SetInputLocaleCJK(/*is_cjk=*/false); + omnibox_view_views->OnInputMethodChanged(); + EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, omnibox_view_views->GetTextInputType()); +} #endif // OS_WIN // ClickOnView(VIEW_ID_OMNIBOX) does not set focus to omnibox on Mac.
diff --git a/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.cc b/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.cc index 53a6fdbf..cf23a23b 100644 --- a/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.cc +++ b/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.cc
@@ -16,9 +16,10 @@ PaymentHandlerModalDialogManagerDelegate:: PaymentHandlerModalDialogManagerDelegate( content::WebContents* host_web_contents) - : content::WebContentsObserver(host_web_contents), web_contents_(nullptr) { - DCHECK(host_web_contents); -} + : host_web_contents_(host_web_contents->GetWeakPtr()) {} + +PaymentHandlerModalDialogManagerDelegate:: + ~PaymentHandlerModalDialogManagerDelegate() = default; void PaymentHandlerModalDialogManagerDelegate::SetWebContentsBlocked( content::WebContents* web_contents, @@ -32,12 +33,12 @@ web_modal::WebContentsModalDialogHost* PaymentHandlerModalDialogManagerDelegate::GetWebContentsModalDialogHost() { - if (!web_contents()) + if (!host_web_contents_) return nullptr; auto* dialog_manager = static_cast<web_modal::WebContentsModalDialogManagerDelegate*>( - chrome::FindBrowserWithWebContents(web_contents())); + chrome::FindBrowserWithWebContents(host_web_contents_.get())); if (!dialog_manager) return nullptr;
diff --git a/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.h b/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.h index 6733888..efaa2f9 100644 --- a/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.h +++ b/chrome/browser/ui/views/payments/payment_handler_modal_dialog_manager_delegate.h
@@ -6,8 +6,8 @@ #define CHROME_BROWSER_UI_VIEWS_PAYMENTS_PAYMENT_HANDLER_MODAL_DIALOG_MANAGER_DELEGATE_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" -#include "content/public/browser/web_contents_observer.h" namespace content { class WebContents; @@ -25,13 +25,12 @@ // spawned the payment sheet. Observes the WebContents that spawned the payment // handler. class PaymentHandlerModalDialogManagerDelegate - : public web_modal::WebContentsModalDialogManagerDelegate, - public content::WebContentsObserver { + : public web_modal::WebContentsModalDialogManagerDelegate { public: // |host| must not be null. explicit PaymentHandlerModalDialogManagerDelegate( content::WebContents* host_web_contents); - ~PaymentHandlerModalDialogManagerDelegate() override = default; + ~PaymentHandlerModalDialogManagerDelegate() override; // Sets the |web_contents| that is behind the modal dialogs managed by this // modal dialog manager. |web_contents| must not be null. @@ -47,8 +46,11 @@ bool IsWebContentsVisible(content::WebContents* web_contents) override; private: + // The WebContents hosting the dialog. + base::WeakPtr<content::WebContents> host_web_contents_; + // A not-owned pointer to the WebContents behind the modal dialogs. - content::WebContents* web_contents_; + content::WebContents* web_contents_ = nullptr; DISALLOW_COPY_AND_ASSIGN(PaymentHandlerModalDialogManagerDelegate); };
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index cf46bda..022b9a5 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -222,10 +222,7 @@ translate_bubble_view_->SwitchToErrorView(error_type); } - // |allow_refocus_alert| is set to false because translate bubble does not - // have an additional screen reader alert instructing the user to use a - // hotkey combination to focus the bubble. - view->ShowForReason(reason, false); + view->ShowForReason(reason); translate::ReportUiAction(translate::BUBBLE_SHOWN); ChromeTranslateClient::GetManagerFromWebContents(web_contents)
diff --git a/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.h b/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.h index 8e24b13..76dc0ac1 100644 --- a/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.h +++ b/chrome/browser/ui/views/webauthn/authenticator_request_dialog_view.h
@@ -80,6 +80,7 @@ void OnStepTransition() override; void OnSheetModelChanged() override; + // content::WebContentsObserver: void OnVisibilityChanged(content::Visibility visibility) override; private:
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc index 644ccb0..032228bd 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
@@ -204,8 +204,6 @@ source->EnableReplaceI18nInJS(); // Forward data to the WebUI. - source->AddResourcePath("post_message_api.js", - IDR_ADD_SUPERVISION_POST_MESSAGE_API_JS); source->AddResourcePath("add_supervision_api_server.js", IDR_ADD_SUPERVISION_API_SERVER_JS); source->AddResourcePath("add_supervision_ui.js", IDR_ADD_SUPERVISION_UI_JS);
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc index b3cfbe7..d34125d 100644 --- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
@@ -197,6 +197,10 @@ IDS_SETTINGS_BLUETOOTH_CHANGE_DEVICE_NAME_DIALOG_CANCEL}, {"bluetoothDeviceDetailChangeNameDialogDone", IDS_SETTINGS_BLUETOOTH_CHANGE_DEVICE_NAME_DIALOG_DONE}, + {"bluetoothDeviceDetailChangeDeviceSettingsKeyboard", + IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_KEYBOARD}, + {"bluetoothDeviceDetailChangeDeviceSettingsMouse", + IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_SETTINGS_MOUSE}, {"bluetoothDeviceDetailChangeDeviceName", IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CHANGE_DEVICE_NAME}, {"bluetoothToggleA11yLabel", @@ -221,6 +225,44 @@ {"bluetoothSummaryPageOn", IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_ON}, {"bluetoothPairedDeviceItemBatteryPercentage", IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_BATTERY_PERCENTAGE}, + {"bluetoothPairedDeviceItemA11yLabelTypeUnknown", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN}, + {"bluetoothPairedDeviceItemA11yLabelTypeUnknownWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_UNKNOWN_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypeComputer", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER}, + {"bluetoothPairedDeviceItemA11yLabelTypeComputerWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_COMPUTER_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypePhone", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE}, + {"bluetoothPairedDeviceItemA11yLabelTypePhoneWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_PHONE_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypeHeadset", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET}, + {"bluetoothPairedDeviceItemA11yLabelTypeHeadsetWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_HEADSET_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypeVideoCamera", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA}, + {"bluetoothPairedDeviceItemA11yLabelTypeVideoCameraWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_VIDEO_CAMERA_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypeGameController", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER}, + {"bluetoothPairedDeviceItemA11yLabelTypeGameControllerWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_GAME_CONTROLLER_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypeKeyboard", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD}, + {"bluetoothPairedDeviceItemA11yLabelTypeKeyboardWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_KEYBOARD_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypeMouse", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE}, + {"bluetoothPairedDeviceItemA11yLabelTypeMouseWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_MOUSE_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemA11yLabelTypeTablet", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET}, + {"bluetoothPairedDeviceItemA11yLabelTypeTabletWithBatteryInfo", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_A11Y_LABEL_TYPE_TABLET_WITH_BATTERY_INFO}, + {"bluetoothPairedDeviceItemSubpageButtonA11yLabel", + IDS_SETTINGS_BLUETOOTH_PAIRED_DEVICE_ITEM_SUBPAGE_BUTTON_A11Y_LABEL}, {"bluetoothPairDevicePageTitle", IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE}, {"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE},
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc index fd3d2f2e..e08f8acf 100644 --- a/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.h" +#include "chrome/browser/apps/app_service/app_service_proxy_chromeos.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/kerberos/kerberos_credentials_manager_factory.h" #include "chrome/browser/ash/profiles/profile_helper.h"
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc index 2dfff4b..63d9916a 100644 --- a/chrome/browser/ui/webui/signin/inline_login_ui.cc +++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -158,8 +158,6 @@ {"edu_coexistence_ui.js", IDR_EDU_COEXISTENCE_EDU_COEXISTENCE_UI_JS}, {"edu_coexistence_controller.js", IDR_EDU_COEXISTENCE_EDU_COEXISTENCE_CONTROLLER_JS}, - {"chromeos/add_supervision/post_message_api.js", - IDR_ADD_SUPERVISION_POST_MESSAGE_API_JS}, {"edu_coexistence_browser_proxy.js", IDR_EDU_COEXISTENCE_EDU_COEXISTENCE_BROWSER_PROXY_JS}, {"edu_coexistence_button.js", @@ -237,6 +235,9 @@ chrome::GetOSSettingsUrl( chromeos::settings::mojom::kMyAccountsSubpagePath) .spec()); + + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::FrameSrc, "frame-src chrome://test/;"); #endif return source;
diff --git a/chrome/browser/ui/webui/test_data_source.cc b/chrome/browser/ui/webui/test_data_source.cc index cd0e7e7..7d1247bc 100644 --- a/chrome/browser/ui/webui/test_data_source.cc +++ b/chrome/browser/ui/webui/test_data_source.cc
@@ -101,6 +101,10 @@ return std::string(); } else if (directive == network::mojom::CSPDirectiveName::FrameAncestors) { return "frame-ancestors chrome://* 'self';"; + } else if (directive == network::mojom::CSPDirectiveName::FrameSrc) { + return "frame-src chrome://test/;"; + } else if (directive == network::mojom::CSPDirectiveName::ChildSrc) { + return "child-src chrome://test/;"; } return content::URLDataSource::GetContentSecurityPolicy(directive);
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc index 41f756e..fa53bf6 100644 --- a/chrome/browser/web_applications/components/web_app_install_utils.cc +++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -388,7 +388,6 @@ } } - // TODO(crbug.com/1152661): Consider eliminating duplicates. return web_app_info_icon_urls; }
diff --git a/chrome/chrome_cleaner/os/initializer.cc b/chrome/chrome_cleaner/os/initializer.cc index 3d19dee..265b413 100644 --- a/chrome/chrome_cleaner/os/initializer.cc +++ b/chrome/chrome_cleaner/os/initializer.cc
@@ -12,6 +12,7 @@ #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/synchronization/waitable_event.h" +#include "base/time/time.h" #include "base/win/scoped_handle.h" #include "base/win/win_util.h" #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
diff --git a/chrome/chrome_cleaner/settings/settings.h b/chrome/chrome_cleaner/settings/settings.h index 33fcd48b..16577dc 100644 --- a/chrome/chrome_cleaner/settings/settings.h +++ b/chrome/chrome_cleaner/settings/settings.h
@@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/memory/singleton.h" +#include "base/time/time.h" #include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h" #include "chrome/chrome_cleaner/settings/settings_definitions.h" #include "components/chrome_cleaner/public/constants/constants.h"
diff --git a/chrome/credential_provider/gaiacp/gcp_utils.cc b/chrome/credential_provider/gaiacp/gcp_utils.cc index 2eb1b169..4ce1ca6 100644 --- a/chrome/credential_provider/gaiacp/gcp_utils.cc +++ b/chrome/credential_provider/gaiacp/gcp_utils.cc
@@ -37,6 +37,7 @@ #include "base/macros.h" #include "base/no_destructor.h" #include "base/path_service.h" +#include "base/strings/string_number_conversions_win.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/installer/setup/downgrade_cleanup_unittest.cc b/chrome/installer/setup/downgrade_cleanup_unittest.cc index 9fb951f9..a7aa8b1b 100644 --- a/chrome/installer/setup/downgrade_cleanup_unittest.cc +++ b/chrome/installer/setup/downgrade_cleanup_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/installer/setup/downgrade_cleanup.h" #include "base/command_line.h" +#include "base/notreached.h" #include "base/strings/utf_string_conversions.h" #include "base/test/multiprocess_test.h" #include "base/test/test_reg_util_win.h"
diff --git a/chrome/services/printing/public/mojom/BUILD.gn b/chrome/services/printing/public/mojom/BUILD.gn index bae6a32..fe6901a 100644 --- a/chrome/services/printing/public/mojom/BUILD.gn +++ b/chrome/services/printing/public/mojom/BUILD.gn
@@ -20,6 +20,7 @@ public_deps = [ "//mojo/public/mojom/base", + "//sandbox/policy/mojom", "//url/mojom:url_mojom_gurl", ]
diff --git a/chrome/services/printing/public/mojom/printing_service.mojom b/chrome/services/printing/public/mojom/printing_service.mojom index dc16846..990346a6 100644 --- a/chrome/services/printing/public/mojom/printing_service.mojom +++ b/chrome/services/printing/public/mojom/printing_service.mojom
@@ -6,6 +6,7 @@ import "chrome/services/printing/public/mojom/pdf_nup_converter.mojom"; import "chrome/services/printing/public/mojom/pdf_to_pwg_raster_converter.mojom"; +import "sandbox/policy/mojom/sandbox.mojom"; [EnableIf=is_chromeos] import "chrome/services/printing/public/mojom/pdf_flattener.mojom"; @@ -15,8 +16,18 @@ [EnableIf=is_win] import "chrome/services/printing/public/mojom/pdf_to_emf_converter.mojom"; +// The different sandbox on Windows allows the service to know it should +// patch certain GDI functions prior to service startup. +[EnableIf=is_win] +const sandbox.mojom.Sandbox kPrintingServiceSandbox + = sandbox.mojom.Sandbox.kPdfConversion; +[EnableIfNot=is_win] +const sandbox.mojom.Sandbox kPrintingServiceSandbox + = sandbox.mojom.Sandbox.kUtility; + // The main interface to Chrome's Printing Service, which performs various PDF // conversion operations in an isolated sandboxed process. +[ServiceSandbox=kPrintingServiceSandbox] interface PrintingService { // Binds an interface that can be used to do Nup PDF conversion. BindPdfNupConverter(pending_receiver<PdfNupConverter> receiver);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 20679af..942fc32 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -9546,7 +9546,7 @@ } } -if (is_linux) { +if (is_linux || is_win) { script_test("variations_smoke_tests") { run_under_python2 = true
diff --git a/chrome/test/chromedriver/chrome/status.cc b/chrome/test/chromedriver/chrome/status.cc index 155432a..f878cdc 100644 --- a/chrome/test/chromedriver/chrome/status.cc +++ b/chrome/test/chromedriver/chrome/status.cc
@@ -74,10 +74,6 @@ return "target frame detached"; case kElementClickIntercepted: return "element click intercepted"; - case kNoSuchShadowRoot: - return "no such shadow root"; - case kDetachedShadowRoot: - return "detached shadow root"; default: return "<unknown>"; }
diff --git a/chrome/test/chromedriver/chrome/status.h b/chrome/test/chromedriver/chrome/status.h index e08d017..098746a9 100644 --- a/chrome/test/chromedriver/chrome/status.h +++ b/chrome/test/chromedriver/chrome/status.h
@@ -34,8 +34,6 @@ kInvalidArgument = 61, kNoSuchCookie = 62, kElementClickIntercepted = 64, - kNoSuchShadowRoot = 65, - kDetachedShadowRoot = 66, kUnsupportedOperation = 405, // Chrome-specific status codes. kChromeNotReachable = 100,
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py index 9480307..935b59d 100644 --- a/chrome/test/chromedriver/client/chromedriver.py +++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -11,12 +11,10 @@ import command_executor from command_executor import Command from webelement import WebElement -from webshadowroot import WebShadowRoot from websocket_connection import WebSocketConnection ELEMENT_KEY_W3C = "element-6066-11e4-a52e-4f735466cecf" ELEMENT_KEY = "ELEMENT" -SHADOW_KEY = "shadow-6066-11e4-a52e-4f735466cecf" MAX_RETRY_COUNT = 5 class ChromeDriverException(Exception): @@ -65,10 +63,6 @@ pass class UnsupportedOperation(ChromeDriverException): pass -class NoSuchShadowRoot(ChromeDriverException): - pass -class DetachedShadowRoot(ChromeDriverException): - pass def _ExceptionForLegacyResponse(response): exception_class_map = { @@ -123,8 +117,6 @@ 'invalid argument': InvalidArgument, 'element not interactable': ElementNotInteractable, 'unsupported operation': UnsupportedOperation, - 'no such shadow root': NoSuchShadowRoot, - 'detached shadow root': DetachedShadowRoot, } error = response['value']['error'] @@ -332,8 +324,6 @@ return {ELEMENT_KEY_W3C: value._id} else: return {ELEMENT_KEY: value._id} - elif isinstance(value, WebShadowRoot): - return {SHADOW_KEY: value._id} elif isinstance(value, list): return list(self._WrapValue(item) for item in value) else: @@ -346,9 +336,6 @@ and isinstance( value[ELEMENT_KEY_W3C], basestring)): return WebElement(self, value[ELEMENT_KEY_W3C]) - elif (len(value) == 1 and SHADOW_KEY in value - and isinstance(value[SHADOW_KEY], basestring)): - return WebShadowRoot(self, value[SHADOW_KEY]) elif (len(value) == 1 and ELEMENT_KEY in value and isinstance(value[ELEMENT_KEY], basestring)): return WebElement(self, value[ELEMENT_KEY])
diff --git a/chrome/test/chromedriver/client/command_executor.py b/chrome/test/chromedriver/client/command_executor.py index 5d8a3fd..f3e03fed 100644 --- a/chrome/test/chromedriver/client/command_executor.py +++ b/chrome/test/chromedriver/client/command_executor.py
@@ -83,12 +83,6 @@ _Method.GET, '/session/:sessionId/element/:id/computedlabel') GET_ELEMENT_COMPUTED_ROLE = ( _Method.GET, '/session/:sessionId/element/:id/computedrole') - GET_ELEMENT_SHADOW_ROOT = ( - _Method.GET, '/session/:sessionId/element/:id/shadow') - FIND_ELEMENT_FROM_SHADOW_ROOT = ( - _Method.POST, '/session/:sessionId/shadow/:id/element') - FIND_ELEMENTS_FROM_SHADOW_ROOT = ( - _Method.POST, '/session/:sessionId/shadow/:id/elements') ELEMENT_EQUALS = ( _Method.GET, '/session/:sessionId/element/:id/equals/:other') GET_COOKIES = (_Method.GET, '/session/:sessionId/cookie')
diff --git a/chrome/test/chromedriver/client/webelement.py b/chrome/test/chromedriver/client/webelement.py index 70cd829..422b226 100644 --- a/chrome/test/chromedriver/client/webelement.py +++ b/chrome/test/chromedriver/client/webelement.py
@@ -14,7 +14,7 @@ def _Execute(self, command, params=None): if params is None: params = {} - params['id'] = self._id + params['id'] = self._id; return self._chromedriver.ExecuteCommand(command, params) def FindElement(self, strategy, target): @@ -25,9 +25,6 @@ return self._Execute( Command.FIND_CHILD_ELEMENTS, {'using': strategy, 'value': target}) - def GetElementShadowRoot(self): - return self._Execute(Command.GET_ELEMENT_SHADOW_ROOT) - def GetText(self): return self._Execute(Command.GET_ELEMENT_TEXT)
diff --git a/chrome/test/chromedriver/client/webshadowroot.py b/chrome/test/chromedriver/client/webshadowroot.py deleted file mode 100644 index a822b0e6..0000000 --- a/chrome/test/chromedriver/client/webshadowroot.py +++ /dev/null
@@ -1,27 +0,0 @@ -# Copyright 2021 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. - -from command_executor import Command - -class WebShadowRoot(object): - """Represents an HTML shadow root""" - def __init__(self, chromedriver, id_): - self._chromedriver = chromedriver - self._id = id_ - - def _Execute(self, command, params=None): - if params is None: - params = {} - params['id'] = self._id - return self._chromedriver.ExecuteCommand(command, params) - - def FindElement(self, strategy, target): - return self._Execute( - Command.FIND_ELEMENT_FROM_SHADOW_ROOT, - {'using': strategy, 'value': target}) - - def FindElements(self, strategy, target): - return self._Execute( - Command.FIND_ELEMENTS_FROM_SHADOW_ROOT, - {'using': strategy, 'value': target})
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc index ddd523d..977bb10 100644 --- a/chrome/test/chromedriver/element_commands.cc +++ b/chrome/test/chromedriver/element_commands.cc
@@ -201,62 +201,6 @@ interval_ms, true, &element_id, session, web_view, params, value); } -Status ExecuteFindChildElementFromShadowRoot( - int interval_ms, - Session* session, - WebView* web_view, - const std::string& shadow_root_id, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value) { - return FindShadowElement(interval_ms, true, &shadow_root_id, session, - web_view, params, value); -} - -Status ExecuteFindChildElementsFromShadowRoot( - int interval_ms, - Session* session, - WebView* web_view, - const std::string& shadow_root_id, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value) { - return FindShadowElement(interval_ms, false, &shadow_root_id, session, - web_view, params, value); -} - -Status ExecuteGetElementShadowRoot(Session* session, - WebView* web_view, - const std::string& element_id, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value) { - Status status = CheckElement(element_id); - - if (status.IsError()) - return status; - - base::ListValue args; - args.Append(CreateElement(element_id)); - - std::string currentFrameId = session->GetCurrentFrameId(); - - status = web_view->CallFunction(session->GetCurrentFrameId(), - "function(elem) { return elem.shadowRoot; }", - args, value); - - if (status.IsError()) { - if (status.message().find("no such shadow root") != std::string::npos) { - return Status(kNoSuchShadowRoot); - } - - return status; - } - - if (value->get()->is_none()) { - return Status(kNoSuchShadowRoot); - } - - return status; -} - Status ExecuteFindChildElements(int interval_ms, Session* session, WebView* web_view,
diff --git a/chrome/test/chromedriver/element_commands.h b/chrome/test/chromedriver/element_commands.h index 7c51c4c9..d74c7a8 100644 --- a/chrome/test/chromedriver/element_commands.h +++ b/chrome/test/chromedriver/element_commands.h
@@ -221,26 +221,4 @@ const base::DictionaryValue& params, std::unique_ptr<base::Value>* value); -Status ExecuteGetElementShadowRoot(Session* session, - WebView* web_view, - const std::string& element_id, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value); - -Status ExecuteFindChildElementFromShadowRoot( - int interval_ms, - Session* session, - WebView* web_view, - const std::string& shadow_root_id, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value); - -Status ExecuteFindChildElementsFromShadowRoot( - int interval_ms, - Session* session, - WebView* web_view, - const std::string& shadow_root_id, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value); - #endif // CHROME_TEST_CHROMEDRIVER_ELEMENT_COMMANDS_H_
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc index 0b18b8c2..d6d019c 100644 --- a/chrome/test/chromedriver/element_util.cc +++ b/chrome/test/chromedriver/element_util.cc
@@ -28,7 +28,6 @@ const char kElementKey[] = "ELEMENT"; const char kElementKeyW3C[] = "element-6066-11e4-a52e-4f735466cecf"; -const char kShadowRootKey[] = "shadow-6066-11e4-a52e-4f735466cecf"; bool ParseFromValue(base::Value* value, WebPoint* point) { if (!value->is_dict()) @@ -313,22 +312,11 @@ return Status(kOk); } -std::unique_ptr<base::DictionaryValue> CreateElementCommon( - const std::string& key, - const std::string& value) { - std::unique_ptr<base::DictionaryValue> element(new base::DictionaryValue()); - element->SetString(key, value); - return element; -} - std::unique_ptr<base::DictionaryValue> CreateElement( const std::string& element_id) { - return CreateElementCommon(GetElementKey(), element_id); -} - -std::unique_ptr<base::DictionaryValue> CreateShadowRoot( - const std::string& shadow_root_id) { - return CreateElementCommon(kShadowRootKey, shadow_root_id); + std::unique_ptr<base::DictionaryValue> element(new base::DictionaryValue()); + element->SetString(GetElementKey(), element_id); + return element; } std::unique_ptr<base::DictionaryValue> CreateValueFrom(const WebPoint& point) { @@ -338,14 +326,13 @@ return dict; } -Status FindElementCommon(int interval_ms, - bool only_one, - const std::string* root_element_id, - Session* session, - WebView* web_view, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value, - bool isShadowRoot) { +Status FindElement(int interval_ms, + bool only_one, + const std::string* root_element_id, + Session* session, + WebView* web_view, + const base::DictionaryValue& params, + std::unique_ptr<base::Value>* value) { std::string strategy; if (!params.GetString("using", &strategy)) return Status(kInvalidArgument, "'using' must be a string"); @@ -357,17 +344,6 @@ strategy != "xpath") return Status(kInvalidArgument, "invalid locator"); - /* - * Currently there is an opened discussion about if the - * following values has to be supported for a Shadow Root - * because the current implementation doesn't support them. - * We have them disabled for now. - * https://github.com/w3c/webdriver/issues/1610 - */ - if (isShadowRoot && (strategy == "tag name" || strategy == "xpath")) { - return Status(kInvalidArgument, "invalid locator"); - } - std::string target; if (!params.GetString("value", &target)) return Status(kInvalidArgument, "'value' must be a string"); @@ -381,12 +357,8 @@ locator->SetString(strategy, target); base::ListValue arguments; arguments.Append(std::move(locator)); - if (root_element_id) { - if (isShadowRoot) - arguments.Append(CreateShadowRoot(*root_element_id)); - else - arguments.Append(CreateElement(*root_element_id)); - } + if (root_element_id) + arguments.Append(CreateElement(*root_element_id)); base::TimeTicks start_time = base::TimeTicks::Now(); int context_retry = 0; @@ -394,7 +366,6 @@ std::unique_ptr<base::Value> temp; Status status = web_view->CallFunction( session->GetCurrentFrameId(), script, arguments, &temp); - // A "Cannot find context" error can occur due to transition from in-process // iFrame to OOPIF. Retry a couple of times. if (status.IsError() && @@ -430,28 +401,6 @@ } } -Status FindElement(int interval_ms, - bool only_one, - const std::string* root_element_id, - Session* session, - WebView* web_view, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value) { - return FindElementCommon(interval_ms, only_one, root_element_id, session, - web_view, params, value, false); -} - -Status FindShadowElement(int interval_ms, - bool only_one, - const std::string* shadow_root_id, - Session* session, - WebView* web_view, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value) { - return FindElementCommon(interval_ms, only_one, shadow_root_id, session, - web_view, params, value, true); -} - Status GetActiveElement(Session* session, WebView* web_view, std::unique_ptr<base::Value>* value) {
diff --git a/chrome/test/chromedriver/element_util.h b/chrome/test/chromedriver/element_util.h index 3d7a2b4..b66e56d 100644 --- a/chrome/test/chromedriver/element_util.h +++ b/chrome/test/chromedriver/element_util.h
@@ -37,14 +37,6 @@ const base::DictionaryValue& params, std::unique_ptr<base::Value>* value); -Status FindShadowElement(int interval_ms, - bool only_one, - const std::string* shadow_root_id, - Session* session, - WebView* web_view, - const base::DictionaryValue& params, - std::unique_ptr<base::Value>* value); - Status GetActiveElement(Session* session, WebView* web_view, std::unique_ptr<base::Value>* value);
diff --git a/chrome/test/chromedriver/js/call_function.js b/chrome/test/chromedriver/js/call_function.js index ac516eb3..e2b41d7 100644 --- a/chrome/test/chromedriver/js/call_function.js +++ b/chrome/test/chromedriver/js/call_function.js
@@ -9,8 +9,6 @@ var StatusCode = { STALE_ELEMENT_REFERENCE: 10, JAVA_SCRIPT_ERROR: 17, - NO_SUCH_SHADOW_ROOT: 65, - DETACHED_SHADOW_ROOT: 66 }; /** @@ -30,13 +28,6 @@ var ELEMENT_KEY = 'ELEMENT'; /** - * Dictionary key to use for holding a shadow element ID. - * @const - * @type {string} - */ - var SHADOW_ROOT_KEY = 'shadow-6066-11e4-a52e-4f735466cecf'; - -/** * True if using W3C Element references. * @const * @type {boolean} @@ -329,23 +320,11 @@ if (isElement(item)) { const root = getNodeRootThroughAnyShadows(item); const cache = getPageCache(root, w3cEnabled); - if (!cache.isNodeReachable_(item)) { - if (item instanceof ShadowRoot) - throw newError('detached shadow root', StatusCode.DETACHED_SHADOW_ROOT); + if (!cache.isNodeReachable_(item)) throw newError('stale element not found', StatusCode.STALE_ELEMENT_REFERENCE); - } const ret = {}; - let key = ELEMENT_KEY; - if (item instanceof ShadowRoot) { - if (!item.nodeType || - item.nodeType !== item.DOCUMENT_FRAGMENT_NODE || - !item.host) { - throw newError('no such shadow root', StatusCode.NO_SUCH_SHADOW_ROOT); - } - key = SHADOW_ROOT_KEY; - } - ret[key] = cache.storeItem(item); + ret[ELEMENT_KEY] = cache.storeItem(item); return ret; } if (isCollection(item)) @@ -382,22 +361,12 @@ typeof item === 'string' || typeof item === 'function') return item; - if (item.hasOwnProperty(ELEMENT_KEY) || - item.hasOwnProperty(SHADOW_ROOT_KEY)) { + if (item.hasOwnProperty(ELEMENT_KEY)) { if (opt_cache === undefined || opt_cache === null) { const root = getNodeRootThroughAnyShadows(item); opt_cache = getPageCache(root, w3cEnabled); } - try { - return opt_cache.retrieveItem(item[ELEMENT_KEY] || - item[SHADOW_ROOT_KEY]); - } catch(err) { - if (err.message && - err.message === 'element is not attached to the page document' && - item.hasOwnProperty(SHADOW_ROOT_KEY)) - throw newError('detached shadow root', StatusCode.DETACHED_SHADOW_ROOT); - throw err; - } + return opt_cache.retrieveItem(item[ELEMENT_KEY]); } if (isCollection(item) || typeof item === 'object') return cloneWithAlgorithm(item, opt_seen, jsonDeserialize, opt_cache);
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc index 67cbc6da..ac73f3f 100644 --- a/chrome/test/chromedriver/server/http_handler.cc +++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -264,20 +264,6 @@ WrapToCommand("GetActiveElement", base::BindRepeating(&ExecuteGetActiveElement))), CommandMapping( - kGet, "session/:sessionId/element/:id/shadow", - WrapToCommand("GetElementShadowRoot", - base::BindRepeating(&ExecuteGetElementShadowRoot))), - CommandMapping( - kPost, "session/:sessionId/shadow/:id/element", - WrapToCommand( - "FindChildElementFromShadowRoot", - base::BindRepeating(&ExecuteFindChildElementFromShadowRoot, 50))), - CommandMapping( - kPost, "session/:sessionId/shadow/:id/elements", - WrapToCommand("FindChildElementsFromShadowRoot", - base::BindRepeating( - &ExecuteFindChildElementsFromShadowRoot, 50))), - CommandMapping( kPost, "session/:sessionId/element", WrapToCommand("FindElement", base::BindRepeating(&ExecuteFindElement, 50))), @@ -1296,14 +1282,6 @@ response = std::make_unique<net::HttpServerResponseInfo>( net::HTTP_INTERNAL_SERVER_ERROR); break; - case kNoSuchShadowRoot: - response = - std::make_unique<net::HttpServerResponseInfo>(net::HTTP_NOT_FOUND); - break; - case kDetachedShadowRoot: - response = - std::make_unique<net::HttpServerResponseInfo>(net::HTTP_NOT_FOUND); - break; default: DCHECK(false);
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index 61c8b19..e8a2cef 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -52,7 +52,6 @@ import chromedriver import websocket_connection import webelement -import webshadowroot sys.path.remove(_CLIENT_DIR) sys.path.insert(1, _SERVER_DIR) @@ -848,70 +847,6 @@ self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html')) self.assertTrue('Link to empty.html' in self._driver.GetPageSource()) - def testGetElementShadowRoot(self): - self._driver.Load( - self.GetHttpUrlForFile('/chromedriver/get_element_shadow_root.html')) - element = self._driver.FindElement('tag name', 'custom-checkbox-element') - shadow = element.GetElementShadowRoot() - self.assertTrue(isinstance(shadow, webshadowroot.WebShadowRoot)) - - def testGetElementShadowRootNotExists(self): - self._driver.Load( - self.GetHttpUrlForFile('/chromedriver/get_element_shadow_root.html')) - element = self._driver.FindElement('tag name', 'div') - with self.assertRaises(chromedriver.NoSuchShadowRoot): - element.GetElementShadowRoot() - - def testFindElementFromShadowRoot(self): - self._driver.Load( - self.GetHttpUrlForFile('/chromedriver/get_element_shadow_root.html')) - element = self._driver.FindElement('tag name', 'custom-checkbox-element') - shadow = element.GetElementShadowRoot() - self.assertTrue(isinstance(shadow, webshadowroot.WebShadowRoot)) - elementInShadow = shadow.FindElement('css selector', 'input') - self.assertTrue(isinstance(elementInShadow, webelement.WebElement)) - - def testFindElementFromShadowRootInvalidArgs(self): - self._driver.Load( - self.GetHttpUrlForFile('/chromedriver/get_element_shadow_root.html')) - element = self._driver.FindElement('tag name', 'custom-checkbox-element') - shadow = element.GetElementShadowRoot() - self.assertTrue(isinstance(shadow, webshadowroot.WebShadowRoot)) - with self.assertRaises(chromedriver.InvalidArgument): - shadow.FindElement('tag name', 'input') - with self.assertRaises(chromedriver.InvalidArgument): - shadow.FindElement('xpath', '//') - - def testDetachedShadowRootError(self): - self._driver.Load( - self.GetHttpUrlForFile('/chromedriver/get_element_shadow_root.html')) - element = self._driver.FindElement('tag name', 'custom-checkbox-element') - shadow = element.GetElementShadowRoot() - self._driver.Refresh() - with self.assertRaises(chromedriver.DetachedShadowRoot): - shadow.FindElement('css selector', 'input') - - def testFindElementsFromShadowRoot(self): - self._driver.Load( - self.GetHttpUrlForFile('/chromedriver/get_element_shadow_root.html')) - element = self._driver.FindElement('tag name', 'custom-checkbox-element') - shadow = element.GetElementShadowRoot() - self.assertTrue(isinstance(shadow, webshadowroot.WebShadowRoot)) - elementsInShadow = shadow.FindElements('css selector', 'input') - self.assertTrue(isinstance(elementsInShadow, list)) - self.assertTrue(2, len(elementsInShadow)) - - def testFindElementsFromShadowRootInvalidArgs(self): - self._driver.Load( - self.GetHttpUrlForFile('/chromedriver/get_element_shadow_root.html')) - element = self._driver.FindElement('tag name', 'custom-checkbox-element') - shadow = element.GetElementShadowRoot() - self.assertTrue(isinstance(shadow, webshadowroot.WebShadowRoot)) - with self.assertRaises(chromedriver.InvalidArgument): - shadow.FindElements('tag name', 'input') - with self.assertRaises(chromedriver.InvalidArgument): - shadow.FindElements('xpath', '//') - def testFindElement(self): self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html')) self._driver.ExecuteScript(
diff --git a/chrome/test/chromedriver/test/run_py_tests.pydeps b/chrome/test/chromedriver/test/run_py_tests.pydeps index ae77f00..f34373f 100644 --- a/chrome/test/chromedriver/test/run_py_tests.pydeps +++ b/chrome/test/chromedriver/test/run_py_tests.pydeps
@@ -83,7 +83,6 @@ ../client/chromedriver.py ../client/command_executor.py ../client/webelement.py -../client/webshadowroot.py ../client/websocket_connection.py ../server/server.py ../util.py
diff --git a/chrome/test/data/chromedriver/get_element_shadow_root.html b/chrome/test/data/chromedriver/get_element_shadow_root.html deleted file mode 100644 index d103f88..0000000 --- a/chrome/test/data/chromedriver/get_element_shadow_root.html +++ /dev/null
@@ -1,21 +0,0 @@ -<style> - custom-checkbox-element { - display: block; - width: 20px; - height: 20px; - } -</style> -<div></div> -<custom-checkbox-element></custom-checkbox-element> -<script> - customElements.define('custom-checkbox-element', - class extends HTMLElement { - constructor() { - super(); - this.attachShadow({ mode: 'open' }).innerHTML = ` - <div><input/><input type="button"/></div> - `; - } - } - ); -</script>
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index a55c077e..9209520 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -41,6 +41,8 @@ deps = [ ":modulize", "//chrome/browser/ui", + "//ui/webui/resources/js:post_message_api_client.m", + "//ui/webui/resources/js:post_message_api_server.m", ] data = [ "$root_gen_dir/chrome/test/data/webui/fake_chrome_event.m.js", @@ -164,6 +166,7 @@ "chromeos/gaia_action_buttons/gaia_action_buttons_browsertest.js", "chromeos/internet_detail_dialog_browsertest.js", "cr_components/chromeos/cr_components_chromeos_v3_browsertest.js", + "post_message_api/post_message_api_browsertest.js", "set_time_dialog_browsertest.js", "settings/chromeos/a11y/v3_os_a11y_browsertest.js", "settings/chromeos/os_settings_v3_browsertest.js",
diff --git a/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js b/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js index 8aa66b3..12357474 100644 --- a/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js +++ b/chrome/test/data/webui/chromeos/ash_common/navigation_view_panel_test.js
@@ -193,4 +193,19 @@ assertFalse(!!viewElement.shadowRoot.querySelector(`#${id1}`)); assertFalse(!!viewElement.shadowRoot.querySelector(`#${dummyPage2}`)); }); + + test('toolBarVisible', async () => { + const dummyPage1 = 'dummy-page1'; + const expectedTitle = 'title'; + viewElement.title = expectedTitle; + viewElement.showToolBar = true; + + await addNavigationSection('dummyPage1', dummyPage1); + + assertFalse(viewElement.shadowRoot.querySelector(`#${dummyPage1}`).hidden); + // The title is only visible if the toolbar is stamped. + const pageToolbar = viewElement.shadowRoot.querySelector('page-toolbar'); + const toolbarTitle = pageToolbar.$.title.textContent.trim(); + assertEquals(expectedTitle, toolbarTitle); + }); }
diff --git a/chrome/test/data/webui/post_message_api/iframe.html b/chrome/test/data/webui/post_message_api/iframe.html new file mode 100644 index 0000000..7c5fa3a --- /dev/null +++ b/chrome/test/data/webui/post_message_api/iframe.html
@@ -0,0 +1,6 @@ +<html> +<body> +<script type="module" src="chrome://test/post_message_api/post_message_api_client_test.js"></script> +HELLO WORLD. +</body> +</html>
diff --git a/chrome/test/data/webui/post_message_api/post_message_api_browsertest.js b/chrome/test/data/webui/post_message_api/post_message_api_browsertest.js new file mode 100644 index 0000000..d58cd746 --- /dev/null +++ b/chrome/test/data/webui/post_message_api/post_message_api_browsertest.js
@@ -0,0 +1,32 @@ +// Copyright 2021 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. + +// Polymer BrowserTest fixture. +GEN_INCLUDE(['//chrome/test/data/webui/polymer_browser_test_base.js']); + +GEN('#include "content/public/test/browser_test.h"'); + +function PostMessageAPIModuleTest() {} + +PostMessageAPIModuleTest.prototype = { + + __proto__: testing.Test.prototype, + + /** @override */ + browsePreload: + 'chrome://chrome-signin/test_loader.html?module=post_message_api/post_message_api_test.js', + + extraLibraries: [ + '//third_party/mocha/mocha.js', + '//chrome/test/data/webui/mocha_adapter.js', + ], + + isAsync: true, +}; + +// Test the postmessage api server and client by defining server methods, and +// passing a series of postmessages. +TEST_F('PostMessageAPIModuleTest', 'PostMessageCommTest', function() { + runMochaTest('PostMessageAPIModuleTest', 'PostMessageCommTest'); +});
diff --git a/chrome/test/data/webui/post_message_api/post_message_api_client_test.js b/chrome/test/data/webui/post_message_api/post_message_api_client_test.js new file mode 100644 index 0000000..79d20e04 --- /dev/null +++ b/chrome/test/data/webui/post_message_api/post_message_api_client_test.js
@@ -0,0 +1,76 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {PostMessageAPIClient} from 'chrome://resources/js/post_message_api_client.m.js'; + +const METHODS = ['setX', 'increment', 'decrement', 'finalize']; +const ServerOriginURLFilter = 'chrome://chrome-signin/'; + +class TestPostMessageAPIClient extends PostMessageAPIClient { + constructor() { + super(METHODS, ServerOriginURLFilter); + } + + setX(x) { + return this.callApiFn('setX', x); + } + + increment(y) { + return this.callApiFn('increment', y); + } + + decrement(z) { + return this.callApiFn('decrement', z); + } + + finalize(success) { + return this.callApiFn('finalize', success); + } + + /** + * Exercise the methods in the METHOD list above, which are defined in the + * TestPostMessageAPIServer class. + * @override + */ + onInitialized() { + // Iinitializes the "x" value in the test PostMessageAPIServer and ensures + // that it has been set via the callback. + this.setX(1).then((result) => { + if (result !== 1) { + this.finalize(false); + return; + } + + // Increments the "x" value in the test PostMessageAPIServer and ensures + // that the value has been updated. + this.increment(5).then((result) => { + if (result !== 6) { + this.finalize(false); + return; + } + + // Decrements the "x" value in the test PostMessageAPIServer and ensures + // that the value has been updated. + this.decrement(1).then((result) => { + if (result !== 5) { + this.finalize(false); + return; + } + + // By this time, multiple requests have been successfully sent and + // received between the test PostMessageAPIServer and + // PostMessageAPIClient. Notify the server that the test is + // successfully completed. + this.finalize(true); + }); + }); + }); + } +} + +document.addEventListener('DOMContentLoaded', function() { + // Construct the PostMessageAPIClient so that it can run the tests. + const post_message_listener = + new TestPostMessageAPIClient(METHODS, ServerOriginURLFilter); +});
diff --git a/chrome/test/data/webui/post_message_api/post_message_api_test.js b/chrome/test/data/webui/post_message_api/post_message_api_test.js new file mode 100644 index 0000000..068f513 --- /dev/null +++ b/chrome/test/data/webui/post_message_api/post_message_api_test.js
@@ -0,0 +1,99 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {PostMessageAPIServer} from 'chrome://resources/js/post_message_api_server.m.js'; + +const METHODS = ['setX', 'increment', 'decrement', 'finalize']; +const TARGET_URL = 'chrome://test/post_message_api/iframe.html'; +const TARGET_ORIGIN = 'chrome://test/'; + +class TestPostMessageAPIServer extends PostMessageAPIServer { + constructor(iframeElement) { + super(iframeElement, METHODS, TARGET_URL, TARGET_ORIGIN); + /** + * Whether the test was successful or not. + * {boolean} + */ + this.success = false; + + /** + * The value that is being communicated between the server and client. + * {integer} + */ + this.x = -1; + + /** + * The promise to be resolved when test finishes successfully. + * {Promise<boolean>} + */ + this.promise_resolve = null; + + this.registerMethod('setX', this.setX.bind(this)); + this.registerMethod('increment', this.increment.bind(this)); + this.registerMethod('decrement', this.decrement.bind(this)); + this.registerMethod('finalize', this.finalize.bind(this)); + } + + /** + * @param {int} x + */ + setX(x) { + this.x = x; + return this.x; + } + + /** + * @param {int} y + */ + increment(y) { + this.x = this.x + y; + return this.x; + } + /** + * @param {int} y + */ + decrement(y) { + this.x = this.x - y; + return this.x; + } + /** + * @param {boolean} success + */ + finalize(success) { + this.success = success; + if (this.promise_resolve) { + this.promise_resolve(this.success); + } + } + + /** + * Returns a promise which when resolved will tell whether the test passed or + * not. + * @return {Promise<boolean>} + */ + getTestFinalized() { + const promise = new Promise((resolve, reject) => { + this.promise_resolve = resolve; + }); + + if (this.success) { + this.promise_resolve(this.success); + } + return promise; + } +} + +suite('PostMessageAPIModuleTest', function() { + suiteSetup(function() { + this.innerFrame = document.createElement('iframe'); + this.innerFrame.src = TARGET_URL; + document.body.appendChild(this.innerFrame); + }); + + test('PostMessageCommTest', async function() { + var server = new TestPostMessageAPIServer(this.innerFrame); + let success = await server.getTestFinalized(); + assertTrue(success); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/fake_bluetooth_config.js b/chrome/test/data/webui/settings/chromeos/fake_bluetooth_config.js index 8bcc4b6..8983e12 100644 --- a/chrome/test/data/webui/settings/chromeos/fake_bluetooth_config.js +++ b/chrome/test/data/webui/settings/chromeos/fake_bluetooth_config.js
@@ -16,18 +16,21 @@ * @param {string} publicName * @param {boolean} connected * @param {string|undefined} nickname - * @param {!chromeos.bluetoothConfig.mojom.AudioOutputCapability} + * @param {?chromeos.bluetoothConfig.mojom.AudioOutputCapability} * audioCapability + * @param {?chromeos.bluetoothConfig.mojom.DeviceType} + * deviceType * @return {!chromeos.bluetoothConfig.mojom.PairedBluetoothDeviceProperties} */ export function createDefaultBluetoothDevice( id, publicName, connected, nickname = undefined, - audioCapability = mojom.AudioOutputCapability.kNotCapableOfAudio) { + audioCapability = mojom.AudioOutputCapability.kNotCapableOfAudio, + deviceType = mojom.DeviceType.kUnknown) { return { deviceProperties: { id: id, publicName: stringToMojoString16(publicName), - deviceType: mojom.DeviceType.kUnknown, + deviceType: deviceType, audioCapability: audioCapability, connectionState: connected ? mojom.DeviceConnectionState.kConnected : mojom.DeviceConnectionState.kNotConnected,
diff --git a/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js index 2400d2c..669e0ac 100644 --- a/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js
@@ -89,6 +89,43 @@ assertEquals('device1', bluetoothDeviceDetailPage.parentNode.pageTitle); }); + test('Show change settings row', async function() { + init(); + bluetoothConfig.setBluetoothEnabledState(/*enabled=*/ true); + + const getChangeMouseSettings = () => + bluetoothDeviceDetailPage.$$('#changeMouseSettings'); + const getChangeKeyboardSettings = () => + bluetoothDeviceDetailPage.$$('#changeKeyboardSettings'); + + const device1 = createDefaultBluetoothDevice( + /*id=*/ '12//345&6789', + /*publicName=*/ 'BeatsX', + /*connected=*/ true, + /*nickname=*/ 'device1', + /*audioCapability=*/ mojom.AudioOutputCapability.kCapableOfAudioOutput, + /*deviceType=*/ mojom.DeviceType.kMouse); + + bluetoothConfig.appendToPairedDeviceList([device1]); + await flushAsync(); + + assertFalse(!!getChangeMouseSettings()); + assertFalse(!!getChangeKeyboardSettings()); + + const params = new URLSearchParams(); + params.append('id', '12//345&6789'); + settings.Router.getInstance().navigateTo( + settings.routes.BLUETOOTH_DEVICE_DETAIL, params); + + await flushAsync(); + assertTrue(!!getChangeMouseSettings()); + assertFalse(!!getChangeKeyboardSettings()); + assertEquals( + bluetoothDeviceDetailPage.i18n( + 'bluetoothDeviceDetailChangeDeviceSettingsMouse'), + getChangeMouseSettings().label); + }); + test('Device becomes unavailable while viewing page.', async function() { init(); bluetoothConfig.setBluetoothEnabledState(/*enabled=*/ true); @@ -146,7 +183,8 @@ /*publicName=*/ 'BeatsX', /*connected=*/ true, /*nickname=*/ 'device1', - /*audioCapability=*/ mojom.AudioOutputCapability.kCapableOfAudioOutput); + /*audioCapability=*/ mojom.AudioOutputCapability.kCapableOfAudioOutput, + /*deviceType=*/ mojom.DeviceType.kHeadset); bluetoothConfig.appendToPairedDeviceList([device1]); await flushAsync();
diff --git a/chrome/test/data/webui/settings/chromeos/os_paired_bluetooth_list_item_tests.js b/chrome/test/data/webui/settings/chromeos/os_paired_bluetooth_list_item_tests.js index 8a712b5..c5225c5d 100644 --- a/chrome/test/data/webui/settings/chromeos/os_paired_bluetooth_list_item_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_paired_bluetooth_list_item_tests.js
@@ -50,51 +50,86 @@ 'os-settings:battery-' + batteryIconRange); } - test('Device name, type and battery percentage', async function() { - // Device with no nickname, battery info and unknown device type. - const publicName = 'BeatsX'; - const device = createDefaultBluetoothDevice( - /*id=*/ '123456789', /*publicName=*/ publicName, /*connected=*/ true); - pairedBluetoothListItem.device = device; - await flushAsync(); + test( + 'Device name, type, battery percentage and a11y labels', + async function() { + // Device with no nickname, battery info and unknown device type. + const publicName = 'BeatsX'; + const device = createDefaultBluetoothDevice( + /*id=*/ '123456789', /*publicName=*/ publicName, + /*connected=*/ true); + pairedBluetoothListItem.device = device; - const getDeviceName = () => { - return pairedBluetoothListItem.$.deviceName; - }; - const getBatteryPercentage = () => { - return pairedBluetoothListItem.shadowRoot.querySelector( - '#batteryPercentage'); - }; - const getDeviceTypeIcon = () => { - return pairedBluetoothListItem.$.deviceTypeIcon; - }; - assertTrue(!!getDeviceName()); - assertEquals(getDeviceName().innerText, publicName); - assertFalse(!!getBatteryPercentage()); - assertTrue(!!getDeviceTypeIcon()); - assertEquals(getDeviceTypeIcon().icon, 'os-settings:bluetooth'); + const itemIndex = 3; + const listSize = 15; + pairedBluetoothListItem.itemIndex = itemIndex; + pairedBluetoothListItem.listSize = listSize; + await flushAsync(); - // Set device nickname, type and battery info. - const nickname = 'nickname'; - device.nickname = nickname; - device.deviceProperties.deviceType = - chromeos.bluetoothConfig.mojom.DeviceType.kComputer; - const batteryPercentage = 60; - device.deviceProperties.batteryInfo = { - defaultProperties: {batteryPercentage: batteryPercentage} - }; - pairedBluetoothListItem.device = {...device}; - await flushAsync(); + const getDeviceName = () => { + return pairedBluetoothListItem.$.deviceName; + }; + const getBatteryPercentage = () => { + return pairedBluetoothListItem.shadowRoot.querySelector( + '#batteryPercentage'); + }; + const getDeviceTypeIcon = () => { + return pairedBluetoothListItem.$.deviceTypeIcon; + }; + const getItemA11yLabel = () => { + return pairedBluetoothListItem.shadowRoot.querySelector('.list-item') + .ariaLabel; + }; + const getSubpageButtonA11yLabel = () => { + return pairedBluetoothListItem.$.subpageButton.ariaLabel; + }; + assertTrue(!!getDeviceName()); + assertEquals(getDeviceName().innerText, publicName); + assertFalse(!!getBatteryPercentage()); + assertTrue(!!getDeviceTypeIcon()); + assertEquals(getDeviceTypeIcon().icon, 'os-settings:bluetooth'); + assertEquals( + getItemA11yLabel(), + pairedBluetoothListItem.i18n( + 'bluetoothPairedDeviceItemA11yLabelTypeUnknown', itemIndex + 1, + listSize, publicName)); + assertEquals( + getSubpageButtonA11yLabel(), + pairedBluetoothListItem.i18n( + 'bluetoothPairedDeviceItemSubpageButtonA11yLabel', publicName)); - assertTrue(!!getDeviceName()); - assertEquals(getDeviceName().innerText, nickname); - assertTrue(!!getBatteryPercentage()); - assertEquals( - getBatteryPercentage().innerText.trim(), - pairedBluetoothListItem.i18n( - 'bluetoothPairedDeviceItemBatteryPercentage', batteryPercentage)); - assertEquals(getDeviceTypeIcon().icon, 'os-settings:bluetooth-computer'); - }); + // Set device nickname, type and battery info. + const nickname = 'nickname'; + device.nickname = nickname; + device.deviceProperties.deviceType = + chromeos.bluetoothConfig.mojom.DeviceType.kComputer; + const batteryPercentage = 60; + device.deviceProperties.batteryInfo = { + defaultProperties: {batteryPercentage: batteryPercentage} + }; + pairedBluetoothListItem.device = {...device}; + await flushAsync(); + + assertTrue(!!getDeviceName()); + assertEquals(getDeviceName().innerText, nickname); + assertTrue(!!getBatteryPercentage()); + assertEquals( + getBatteryPercentage().innerText.trim(), + pairedBluetoothListItem.i18n( + 'bluetoothPairedDeviceItemBatteryPercentage', + batteryPercentage)); + assertEquals( + getDeviceTypeIcon().icon, 'os-settings:bluetooth-computer'); + assertEquals( + getItemA11yLabel(), + pairedBluetoothListItem.i18n( + 'bluetoothPairedDeviceItemA11yLabelTypeComputerWithBatteryInfo', + itemIndex + 1, listSize, nickname, batteryPercentage)); + assertEquals( + getSubpageButtonA11yLabel(), + pairedBluetoothListItem.i18n( + 'bluetoothPairedDeviceItemSubpageButtonA11yLabel', nickname)); + }); test('Battery icon and color', async function() { const device = createDefaultBluetoothDevice(
diff --git a/chrome/updater/activity_impl_win.cc b/chrome/updater/activity_impl_win.cc index 3ecc1780..37d415e 100644 --- a/chrome/updater/activity_impl_win.cc +++ b/chrome/updater/activity_impl_win.cc
@@ -26,7 +26,7 @@ constexpr wchar_t kDidRun[] = L"dr"; std::wstring GetAppClientStateKey(const std::string& id) { - return base::ASCIIToWide(base::StrCat({CLIENT_STATE_KEY, id})); + return base::StrCat({CLIENT_STATE_KEY, base::ASCIIToWide(id)}); } bool GetActiveBitUnderKey(HKEY rootkey, const std::wstring& key_name) {
diff --git a/chrome/updater/activity_impl_win_unittest.cc b/chrome/updater/activity_impl_win_unittest.cc index 7559cd1..5c65200 100644 --- a/chrome/updater/activity_impl_win_unittest.cc +++ b/chrome/updater/activity_impl_win_unittest.cc
@@ -4,8 +4,6 @@ #include "chrome/updater/activity_impl.h" -#include <tchar.h> - #include <string> #include <tuple> @@ -52,7 +50,7 @@ constexpr wchar_t kDidRun[] = L"dr"; constexpr char kAppId[] = "{6ACB7D4D-E5BA-48b0-85FE-A4051500A1BD}"; constexpr wchar_t kClientStateKeyPath[] = - _T(CLIENT_STATE_KEY) L"{6ACB7D4D-E5BA-48b0-85FE-A4051500A1BD}"; + CLIENT_STATE_KEY L"{6ACB7D4D-E5BA-48b0-85FE-A4051500A1BD}"; DWORD WriteActiveBitAsString(base::win::RegKey& key, bool value) { return key.WriteValue(kDidRun, value ? L"1" : L"0");
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc index 43ab3af..4df5377 100644 --- a/chrome/updater/test/integration_tests_impl.cc +++ b/chrome/updater/test/integration_tests_impl.cc
@@ -21,6 +21,7 @@ #include "base/process/process.h" #include "base/run_loop.h" #include "base/strings/strcat.h" +#include "base/synchronization/waitable_event.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h"
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc index 24fd2622..cb8c9c7 100644 --- a/chrome/updater/test/integration_tests_win.cc +++ b/chrome/updater/test/integration_tests_win.cc
@@ -83,7 +83,7 @@ } std::wstring GetAppClientStateKey(const std::string& id) { - return base::ASCIIToWide(base::StrCat({CLIENT_STATE_KEY, id})); + return base::StrCat({CLIENT_STATE_KEY, base::ASCIIToWide(id)}); } bool RegKeyExists(HKEY root, REGSAM regsam, const std::wstring& path) { @@ -139,8 +139,7 @@ ::CloseServiceHandle(service); } - base::win::RegKey(HKEY_LOCAL_MACHINE, base::ASCIIToWide(UPDATER_KEY).c_str(), - KEY_WRITE) + base::win::RegKey(HKEY_LOCAL_MACHINE, UPDATER_KEY, KEY_WRITE) .DeleteValue(service_name); ::CloseServiceHandle(scm); @@ -151,8 +150,8 @@ void Clean(UpdaterScope scope) { const HKEY root = scope == UpdaterScope::kSystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - for (const char* key : {CLIENT_STATE_KEY, CLIENTS_KEY, UPDATER_KEY}) { - EXPECT_TRUE(DeleteRegKey(root, KEY_WOW64_32KEY, base::ASCIIToWide(key))); + for (const wchar_t* key : {CLIENT_STATE_KEY, CLIENTS_KEY, UPDATER_KEY}) { + EXPECT_TRUE(DeleteRegKey(root, KEY_WOW64_32KEY, key)); } for (const wchar_t* key : {kRegKeyCompanyCloudManagement, kRegKeyCompanyEnrollment, UPDATER_POLICIES_KEY}) { @@ -212,16 +211,15 @@ ::CloseServiceHandle(scm); return is_service_gone && - !base::win::RegKey(HKEY_LOCAL_MACHINE, - base::ASCIIToWide(UPDATER_KEY).c_str(), KEY_READ) + !base::win::RegKey(HKEY_LOCAL_MACHINE, UPDATER_KEY, KEY_READ) .HasValue(service_name); } void ExpectClean(UpdaterScope scope) { const HKEY root = scope == UpdaterScope::kSystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; - for (const char* key : {CLIENT_STATE_KEY, CLIENTS_KEY, UPDATER_KEY}) { - EXPECT_FALSE(RegKeyExists(root, KEY_WOW64_32KEY, base::ASCIIToWide(key))); + for (const wchar_t* key : {CLIENT_STATE_KEY, CLIENTS_KEY, UPDATER_KEY}) { + EXPECT_FALSE(RegKeyExists(root, KEY_WOW64_32KEY, key)); } for (const wchar_t* key : {kRegKeyCompanyCloudManagement, kRegKeyCompanyEnrollment, UPDATER_POLICIES_KEY}) {
diff --git a/chrome/updater/win/installer_api.cc b/chrome/updater/win/installer_api.cc index 7051c2e..f9dd983 100644 --- a/chrome/updater/win/installer_api.cc +++ b/chrome/updater/win/installer_api.cc
@@ -35,8 +35,7 @@ if (!base::UTF8ToWide(app_id.c_str(), app_id.size(), &subkey)) return absl::nullopt; regsam = regsam | KEY_WOW64_32KEY; - base::win::RegKey key(HKEY_CURRENT_USER, - base::ASCIIToWide(CLIENT_STATE_KEY).c_str(), regsam); + base::win::RegKey key(HKEY_CURRENT_USER, CLIENT_STATE_KEY, regsam); if (key.OpenKey(subkey.c_str(), regsam) != ERROR_SUCCESS) return absl::nullopt; return key; @@ -52,8 +51,7 @@ if (!base::UTF8ToWide(app_id.c_str(), app_id.size(), &subkey)) return absl::nullopt; regsam = regsam | KEY_WOW64_32KEY; - base::win::RegKey key(HKEY_CURRENT_USER, - base::ASCIIToWide(CLIENT_STATE_KEY).c_str(), regsam); + base::win::RegKey key(HKEY_CURRENT_USER, CLIENT_STATE_KEY, regsam); if (key.CreateKey(subkey.c_str(), regsam) != ERROR_SUCCESS) return absl::nullopt; return key; @@ -70,8 +68,7 @@ if (!base::UTF8ToWide(app_id.c_str(), app_id.size(), &subkey)) return false; constexpr REGSAM kRegSam = KEY_WRITE | KEY_WOW64_32KEY; - base::win::RegKey key(HKEY_CURRENT_USER, - base::ASCIIToWide(CLIENT_STATE_KEY).c_str(), kRegSam); + base::win::RegKey key(HKEY_CURRENT_USER, CLIENT_STATE_KEY, kRegSam); return key.DeleteKey(subkey.c_str()) == ERROR_SUCCESS; }
diff --git a/chrome/updater/win/setup/setup_util.cc b/chrome/updater/win/setup/setup_util.cc index 73a438d..1fc19745 100644 --- a/chrome/updater/win/setup/setup_util.cc +++ b/chrome/updater/win/setup/setup_util.cc
@@ -220,7 +220,7 @@ list->AddWorkItem(new installer::InstallServiceWorkItem( GetServiceName(internal_service).c_str(), GetServiceDisplayName(internal_service).c_str(), com_service_command, - base::ASCIIToWide(UPDATER_KEY), + UPDATER_KEY, internal_service ? GetSideBySideServers(UpdaterScope::kSystem) : GetActiveServers(UpdaterScope::kSystem), {}));
diff --git a/chrome/updater/win/setup/uninstall.cc b/chrome/updater/win/setup/uninstall.cc index 79d181d..c545543 100644 --- a/chrome/updater/win/setup/uninstall.cc +++ b/chrome/updater/win/setup/uninstall.cc
@@ -17,7 +17,6 @@ #include "base/process/launch.h" #include "base/process/process.h" #include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" #include "base/win/scoped_com_initializer.h" #include "chrome/installer/util/install_service_work_item.h" #include "chrome/installer/util/install_util.h" @@ -61,7 +60,7 @@ for (const bool is_internal_service : {true, false}) { const std::wstring service_name = GetServiceName(is_internal_service); if (!installer::InstallServiceWorkItem::DeleteService( - service_name.c_str(), base::ASCIIToWide(UPDATER_KEY), {}, {})) { + service_name.c_str(), UPDATER_KEY, {}, {})) { LOG(WARNING) << "DeleteService [" << service_name << "] failed."; } } @@ -139,7 +138,7 @@ updater::UnregisterWakeTask(); std::unique_ptr<WorkItemList> uninstall_list(WorkItem::CreateWorkItemList()); - uninstall_list->AddDeleteRegKeyWorkItem(key, base::ASCIIToWide(UPDATER_KEY), + uninstall_list->AddDeleteRegKeyWorkItem(key, UPDATER_KEY, WorkItem::kWow64Default); if (!uninstall_list->Do()) { LOG(ERROR) << "Failed to delete the registry keys.";
diff --git a/chrome/updater/win/win_constants.h b/chrome/updater/win/win_constants.h index 295b2d6..a92fe19 100644 --- a/chrome/updater/win/win_constants.h +++ b/chrome/updater/win/win_constants.h
@@ -19,13 +19,13 @@ extern const wchar_t kPrefsAccessMutex[]; // Registry keys and value names. -#define COMPANY_KEY "Software\\" COMPANY_SHORTNAME_STRING "\\" +#define COMPANY_KEY L"Software\\" COMPANY_SHORTNAME_STRING L"\\" // Use |Update| instead of PRODUCT_FULLNAME_STRING for the registry key name // to be backward compatible with Google Update / Omaha. -#define UPDATER_KEY COMPANY_KEY "Update\\" -#define CLIENTS_KEY UPDATER_KEY "Clients\\" -#define CLIENT_STATE_KEY UPDATER_KEY "ClientState\\" +#define UPDATER_KEY COMPANY_KEY L"Update\\" +#define CLIENTS_KEY UPDATER_KEY L"Clients\\" +#define CLIENT_STATE_KEY UPDATER_KEY L"ClientState\\" #define COMPANY_POLICIES_KEY \ L"Software\\Policies\\" COMPANY_SHORTNAME_STRING L"\\"
diff --git a/chrome/updater/win/win_util.cc b/chrome/updater/win/win_util.cc index 5fbc7c5..1a134b0 100644 --- a/chrome/updater/win/win_util.cc +++ b/chrome/updater/win/win_util.cc
@@ -412,11 +412,11 @@ } std::wstring GetRegistryKeyClientsUpdater() { - return base::ASCIIToWide(base::StrCat({CLIENTS_KEY, kUpdaterAppId})); + return base::StrCat({CLIENTS_KEY, base::ASCIIToWide(kUpdaterAppId)}); } std::wstring GetRegistryKeyClientStateUpdater() { - return base::ASCIIToWide(base::StrCat({CLIENT_STATE_KEY, kUpdaterAppId})); + return base::StrCat({CLIENT_STATE_KEY, base::ASCIIToWide(kUpdaterAppId)}); } int GetDownloadProgress(int64_t downloaded_bytes, int64_t total_bytes) {
diff --git a/chromecast/browser/cast_media_blocker_unittest.cc b/chromecast/browser/cast_media_blocker_unittest.cc index 5f5b33fe..47e6fc9 100644 --- a/chromecast/browser/cast_media_blocker_unittest.cc +++ b/chromecast/browser/cast_media_blocker_unittest.cc
@@ -61,6 +61,7 @@ MOCK_METHOD0(ToggleCamera, void()); MOCK_METHOD0(HangUp, void()); MOCK_METHOD0(Raise, void()); + MOCK_METHOD1(SetMute, void(bool)); private: DISALLOW_COPY_AND_ASSIGN(MockMediaSession);
diff --git a/chromeos/components/multidevice/logging/log_buffer.cc b/chromeos/components/multidevice/logging/log_buffer.cc index 5d5f93f..1896380 100644 --- a/chromeos/components/multidevice/logging/log_buffer.cc +++ b/chromeos/components/multidevice/logging/log_buffer.cc
@@ -4,7 +4,7 @@ #include "chromeos/components/multidevice/logging/log_buffer.h" -#include "base/lazy_instance.h" +#include "base/no_destructor.h" namespace chromeos { @@ -15,9 +15,6 @@ // The maximum number of logs that can be stored in the buffer. const size_t kMaxBufferSize = 1000; -// The global instance returned by LogBuffer::GetInstance(). -base::LazyInstance<LogBuffer>::Leaky g_log_buffer = LAZY_INSTANCE_INITIALIZER; - } // namespace LogBuffer::LogMessage::LogMessage(const std::string& text, @@ -33,7 +30,8 @@ // static LogBuffer* LogBuffer::GetInstance() { - return &g_log_buffer.Get(); + static base::NoDestructor<LogBuffer> log_buffer; + return log_buffer.get(); } void LogBuffer::AddObserver(Observer* observer) {
diff --git a/chromeos/components/personalization_app/resources/common/styles.js b/chromeos/components/personalization_app/resources/common/styles.js index b5c2c79c..4098920 100644 --- a/chromeos/components/personalization_app/resources/common/styles.js +++ b/chromeos/components/personalization_app/resources/common/styles.js
@@ -200,6 +200,7 @@ } .photo-empty .photo-text-container > p { color: var(--cros-button-label-color-secondary); + text-shadow: none; } .photo-gradient-mask { border-radius: 12px;
diff --git a/chromeos/metrics/login_event_recorder.cc b/chromeos/metrics/login_event_recorder.cc index 0ad641e1..13a7d95 100644 --- a/chromeos/metrics/login_event_recorder.cc +++ b/chromeos/metrics/login_event_recorder.cc
@@ -14,6 +14,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/sequenced_task_runner.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/system/sys_info.h" #include "base/task/current_thread.h"
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt index 8e096538..5afd77d 100644 --- a/chromeos/profiles/orderfile.newest.txt +++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@ -chromeos-chrome-orderfile-field-93-4577.22-1628502876-benchmark-93.0.4577.47-r1.orderfile.xz +chromeos-chrome-orderfile-field-93-4577.36-1629108064-benchmark-93.0.4577.48-r1.orderfile.xz
diff --git a/chromeos/services/assistant/media_host_unittest.cc b/chromeos/services/assistant/media_host_unittest.cc index ae4b071..fe3eab59 100644 --- a/chromeos/services/assistant/media_host_unittest.cc +++ b/chromeos/services/assistant/media_host_unittest.cc
@@ -100,6 +100,7 @@ MOCK_METHOD(void, ToggleCamera, ()); MOCK_METHOD(void, HangUp, ()); MOCK_METHOD(void, Raise, ()); + MOCK_METHOD(void, SetMute, (bool mute)); void AddObserver( mojo::PendingRemote<media_session::mojom::MediaControllerObserver> remote) override {
diff --git a/chromeos/services/assistant/media_session/assistant_media_session.h b/chromeos/services/assistant/media_session/assistant_media_session.h index 6025d21..954f2f37 100644 --- a/chromeos/services/assistant/media_session/assistant_media_session.h +++ b/chromeos/services/assistant/media_session/assistant_media_session.h
@@ -58,6 +58,7 @@ void ToggleCamera() override {} void HangUp() override {} void Raise() override {} + void SetMute(bool mute) override {} // Requests/abandons audio focus to the AudioFocusManager. void RequestAudioFocus(media_session::mojom::AudioFocusType audio_focus_type);
diff --git a/components/arc/session/arc_container_client_adapter.cc b/components/arc/session/arc_container_client_adapter.cc index 1981642..27015fff 100644 --- a/components/arc/session/arc_container_client_adapter.cc +++ b/components/arc/session/arc_container_client_adapter.cc
@@ -16,7 +16,6 @@ #include "chromeos/dbus/dbus_method_call_status.h" #include "chromeos/dbus/login_manager/arc.pb.h" #include "chromeos/dbus/session_manager/session_manager_client.h" -#include "components/arc/arc_util.h" #include "components/arc/session/arc_session.h" namespace arc { @@ -125,6 +124,7 @@ request.set_disable_media_store_maintenance( params.disable_media_store_maintenance); request.set_disable_download_provider(params.disable_download_provider); + request.set_disable_ureadahead(params.disable_ureadahead); request.set_arc_generate_pai(params.arc_generate_play_auto_install); switch (params.usap_profile) { @@ -137,10 +137,6 @@ break; } - // TODO(b:196390269): Enable handling after arc.proto is uprev-ed. - if (IsUreadaheadDisabled()) - LOG(ERROR) << "Disabling ureadahead is not supported in container yet."; - chromeos::SessionManagerClient::Get()->StartArcMiniContainer( request, std::move(callback)); }
diff --git a/components/arc/session/arc_container_client_adapter_unittest.cc b/components/arc/session/arc_container_client_adapter_unittest.cc index 5195ff1..7ddbeea 100644 --- a/components/arc/session/arc_container_client_adapter_unittest.cc +++ b/components/arc/session/arc_container_client_adapter_unittest.cc
@@ -154,6 +154,27 @@ EXPECT_TRUE(request.disable_download_provider()); } +TEST_F(ArcContainerClientAdapterTest, StartArc_UreadaheadByDefault) { + StartParams start_params; + client_adapter()->StartMiniArc(std::move(start_params), + base::BindOnce(&OnMiniInstanceStarted)); + const auto& request = chromeos::FakeSessionManagerClient::Get() + ->last_start_arc_mini_container_request(); + EXPECT_TRUE(request.has_disable_ureadahead()); + EXPECT_FALSE(request.disable_ureadahead()); +} + +TEST_F(ArcContainerClientAdapterTest, StartArc_DisableUreadahead) { + StartParams start_params; + start_params.disable_ureadahead = true; + client_adapter()->StartMiniArc(std::move(start_params), + base::BindOnce(&OnMiniInstanceStarted)); + const auto& request = chromeos::FakeSessionManagerClient::Get() + ->last_start_arc_mini_container_request(); + EXPECT_TRUE(request.has_disable_ureadahead()); + EXPECT_TRUE(request.disable_ureadahead()); +} + struct DalvikMemoryProfileTestParam { // Requested profile. StartParams::DalvikMemoryProfile profile;
diff --git a/components/autofill/android/BUILD.gn b/components/autofill/android/BUILD.gn index a8dd599..054c13c5 100644 --- a/components/autofill/android/BUILD.gn +++ b/components/autofill/android/BUILD.gn
@@ -36,6 +36,13 @@ ] } +java_cpp_features("java_features_srcjar") { + visibility = [ ":*" ] + sources = [ "//components/autofill/core/common/autofill_features.cc" ] + template = + "//components/autofill/android/java_templates/AutofillFeatures.java.tmpl" +} + android_library("full_autofill_java") { deps = [ ":autofill_java_resources", @@ -59,6 +66,11 @@ resources_package = "org.chromium.components.autofill" } +# A minimal library used to expose autofill features to webview. +android_library("autofill_features_java") { + srcjar_deps = [ ":java_features_srcjar" ] +} + # A library containing the minimal deps for payments, so that ui_java_resources # doesn't have to be pulled in. android_library("payments_autofill_java") {
diff --git a/components/autofill/android/java_templates/AutofillFeatures.java.tmpl b/components/autofill/android/java_templates/AutofillFeatures.java.tmpl new file mode 100644 index 0000000..cddfb80 --- /dev/null +++ b/components/autofill/android/java_templates/AutofillFeatures.java.tmpl
@@ -0,0 +1,16 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.autofill; + +/** + * Contains features that are specific to the autofill component. + */ +public final class AutofillFeatures {{ + +{NATIVE_FEATURES} + + // Prevents instantiation. + private AutofillFeatures() {{}} +}}
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc index 9001db7f..0083aa0 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -75,6 +75,7 @@ #endif using base::ASCIIToUTF16; +using testing::NiceMock; namespace autofill { namespace { @@ -174,7 +175,7 @@ /*is_off_the_record=*/false); personal_data_manager_.SetPrefService(autofill_client_.GetPrefs()); autocomplete_history_manager_ = - std::make_unique<MockAutocompleteHistoryManager>(); + std::make_unique<NiceMock<MockAutocompleteHistoryManager>>(); accessor_ = std::make_unique<TestAccessor>(); autofill_driver_ = std::make_unique<TestAutofillDriver>(); @@ -1035,11 +1036,11 @@ histogram_tester.ExpectTotalCount( "Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn." "Duration", - int(user_is_opted_in)); + static_cast<int>(user_is_opted_in)); histogram_tester.ExpectTotalCount( "Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn." "TimedOutCvcFallback", - int(user_is_opted_in)); + static_cast<int>(user_is_opted_in)); } {
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc index 4531089..2f9aae25 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -62,6 +62,7 @@ using base::ASCIIToUTF16; using testing::_; using testing::AtLeast; +using testing::NiceMock; using testing::Return; using testing::SaveArg; using testing::UnorderedElementsAre; @@ -345,7 +346,7 @@ std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_; scoped_refptr<AutofillWebDataService> database_; MockPersonalDataManager personal_data_; - MockAutocompleteHistoryManager autocomplete_history_manager_; + NiceMock<MockAutocompleteHistoryManager> autocomplete_history_manager_; syncer::TestSyncService sync_service_; // Ends up getting owned (and destroyed) by TestFormDataImporter: TestCreditCardSaveManager* credit_card_save_manager_;
diff --git a/components/autofill/core/browser/payments/full_card_request_unittest.cc b/components/autofill/core/browser/payments/full_card_request_unittest.cc index 248743f..3824e0cb 100644 --- a/components/autofill/core/browser/payments/full_card_request_unittest.cc +++ b/components/autofill/core/browser/payments/full_card_request_unittest.cc
@@ -5,7 +5,6 @@ #include "components/autofill/core/browser/payments/full_card_request.h" #include "base/command_line.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" #include "base/test/scoped_feature_list.h" @@ -34,6 +33,7 @@ namespace payments { using testing::_; +using testing::NiceMock; // The consumer of the full card request API. class MockResultDelegate : public FullCardRequest::ResultDelegate, @@ -114,7 +114,10 @@ "sync-url", "https://google.com"); } - ~FullCardRequestTest() override {} + FullCardRequestTest(const FullCardRequestTest&) = delete; + FullCardRequestTest& operator=(const FullCardRequestTest&) = delete; + + ~FullCardRequestTest() override = default; MockPersonalDataManager* personal_data() { return &personal_data_; } @@ -155,7 +158,7 @@ base::test::SingleThreadTaskEnvironment task_environment_; variations::ScopedVariationsIdsProvider scoped_variations_ids_provider_{ variations::VariationsIdsProvider::Mode::kUseSignedInState}; - MockPersonalDataManager personal_data_; + NiceMock<MockPersonalDataManager> personal_data_; MockResultDelegate result_delegate_; MockUIDelegate ui_delegate_; TestAutofillClient autofill_client_; @@ -164,8 +167,6 @@ scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_; std::unique_ptr<PaymentsClient> payments_client_; std::unique_ptr<FullCardRequest> request_; - - DISALLOW_COPY_AND_ASSIGN(FullCardRequestTest); }; // Matches the |arg| credit card to the given |record_type| and |card_number|.
diff --git a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc index 5bf60a7..623d861 100644 --- a/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc +++ b/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc
@@ -58,6 +58,7 @@ using base::ASCIIToUTF16; using testing::_; +using testing::NiceMock; namespace autofill { @@ -320,7 +321,7 @@ std::unique_ptr<TestAutofillDriver> autofill_driver_; std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_; TestPersonalDataManager personal_data_; - MockAutocompleteHistoryManager autocomplete_history_manager_; + NiceMock<MockAutocompleteHistoryManager> autocomplete_history_manager_; syncer::TestSyncService sync_service_; base::test::ScopedFeatureList scoped_feature_list_; // Ends up getting owned (and destroyed) by TestAutofillClient:
diff --git a/components/autofill_assistant/browser/metrics.cc b/components/autofill_assistant/browser/metrics.cc index a4c2f9a3..c50d788 100644 --- a/components/autofill_assistant/browser/metrics.cc +++ b/components/autofill_assistant/browser/metrics.cc
@@ -223,4 +223,14 @@ base::UmaHistogramEnumeration(kFeatureModuleInstallationEnumName, event); } +// static +void Metrics::RecordTriggerConditionEvaluationTime( + ukm::UkmRecorder* ukm_recorder, + ukm::SourceId source_id, + base::TimeDelta evaluation_time) { + ukm::builders::AutofillAssistant_Timing(source_id) + .SetTriggerConditionEvaluationMs(evaluation_time.InMilliseconds()) + .Record(ukm_recorder); +} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/metrics.h b/components/autofill_assistant/browser/metrics.h index 4c7c30c..bcd0b49 100644 --- a/components/autofill_assistant/browser/metrics.h +++ b/components/autofill_assistant/browser/metrics.h
@@ -6,6 +6,7 @@ #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_METRICS_H_ #include <ostream> +#include "base/time/time.h" #include "components/autofill_assistant/browser/service.pb.h" #include "components/autofill_assistant/browser/startup_util.h" #include "services/metrics/public/cpp/ukm_recorder.h" @@ -402,8 +403,13 @@ InChromeTriggerAction event); static void RecordOnboardingResult(OnBoarding event); static void RecordFeatureModuleInstallation(FeatureModuleInstallation event); + static void RecordTriggerConditionEvaluationTime( + ukm::UkmRecorder* ukm_recorder, + ukm::SourceId source_id, + base::TimeDelta evaluation_time); - // Intended for debugging: writes string representation of |reason| to |out|. + // Intended for debugging: writes string representation of |reason| to + // |out|. friend std::ostream& operator<<(std::ostream& out, const DropOutReason& reason) { #ifdef NDEBUG
diff --git a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc index 6092b6e..da5a18b 100644 --- a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc +++ b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc
@@ -467,7 +467,8 @@ base::BindOnce( &TriggerScriptCoordinator::OnDynamicTriggerConditionsEvaluated, weak_ptr_factory_.GetWeakPtr(), - /* is_out_of_schedule = */ false)); + /* is_out_of_schedule = */ false, + /* start_time = */ base::TimeTicks::Now())); } void TriggerScriptCoordinator::StopCheckingTriggerConditions() { @@ -510,7 +511,8 @@ } void TriggerScriptCoordinator::OnDynamicTriggerConditionsEvaluated( - bool is_out_of_schedule) { + bool is_out_of_schedule, + absl::optional<base::TimeTicks> start_time) { if (!web_contents_visible_ || !is_checking_trigger_conditions_) { return; } @@ -520,6 +522,11 @@ return; } + if (start_time.has_value()) { + Metrics::RecordTriggerConditionEvaluationTime( + ukm_recorder_, ukm_source_id_, base::TimeTicks::Now() - *start_time); + } + VLOG(3) << "Evaluating trigger conditions..."; std::vector<bool> evaluated_trigger_conditions; for (const auto& trigger_script : trigger_scripts_) { @@ -593,7 +600,8 @@ } void TriggerScriptCoordinator::RunOutOfScheduleTriggerConditionCheck() { - OnDynamicTriggerConditionsEvaluated(/* is_out_of_schedule = */ true); + OnDynamicTriggerConditionsEvaluated(/* is_out_of_schedule = */ true, + /* start_time = */ absl::nullopt); } void TriggerScriptCoordinator::RunCallback(
diff --git a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h index 65784bc..92c6bc5 100644 --- a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h +++ b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h
@@ -136,7 +136,9 @@ void ShowTriggerScript(int index); void HideTriggerScript(); void CheckDynamicTriggerConditions(); - void OnDynamicTriggerConditionsEvaluated(bool is_out_of_schedule); + void OnDynamicTriggerConditionsEvaluated( + bool is_out_of_schedule, + absl::optional<base::TimeTicks> start_time); void OnGetTriggerScripts(int http_status, const std::string& response); GURL GetCurrentURL() const; void OnEffectiveVisibilityChanged();
diff --git a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc index 59e65d3..ccd2cc6 100644 --- a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc +++ b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
@@ -42,6 +42,7 @@ using ::testing::Return; using ::testing::UnorderedElementsAre; using ::testing::UnorderedElementsAreArray; +using ::testing::WithArg; std::unique_ptr<base::test::ScopedFeatureList> CreateScopedFeatureList( bool dialog_onboarding) { @@ -1415,4 +1416,43 @@ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE}}}))); } +TEST_F(TriggerScriptCoordinatorTest, RecordTriggerConditionEvaluationTime) { + GetTriggerScriptsResponseProto response; + response.set_trigger_condition_check_interval_ms(1000); + response.add_trigger_scripts(); + std::string serialized_response; + response.SerializeToString(&serialized_response); + + EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _)) + .WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response)); + + EXPECT_CALL(*mock_dynamic_trigger_conditions_, OnUpdate) + .WillOnce(WithArg<1>([&](auto& callback) { + task_environment()->FastForwardBy( + base::TimeDelta::FromMilliseconds(700)); + std::move(callback).Run(); + })) + .WillOnce(WithArg<1>([&](auto& callback) { + task_environment()->FastForwardBy( + base::TimeDelta::FromMilliseconds(300)); + std::move(callback).Run(); + })); + + // Start will immediately run the first trigger condition evaluation. + coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(), + mock_callback_.Get()); + + // Run the second scheduled trigger condition evaluation. + task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1)); + + // Run out-of-schedule trigger condition evaluation (should not be recorded). + coordinator_->OnKeyboardVisibilityChanged(true); + + EXPECT_THAT( + GetUkmTriggerConditionEvaluationTime(ukm_recorder_), + ElementsAreArray(std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry>{ + {navigation_ids_[0], {{kTriggerConditionTimingMs, 700}}}, + {navigation_ids_[0], {{kTriggerConditionTimingMs, 300}}}})); +} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/ukm_test_util.cc b/components/autofill_assistant/browser/ukm_test_util.cc index 411a9a90..108ef20 100644 --- a/components/autofill_assistant/browser/ukm_test_util.cc +++ b/components/autofill_assistant/browser/ukm_test_util.cc
@@ -37,6 +37,13 @@ {kInChromeTriggerAction}); } +std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> +GetUkmTriggerConditionEvaluationTime( + ukm::TestAutoSetUkmRecorder& ukm_recorder) { + return ukm_recorder.GetEntries(kAutofillAssistantTimingEntry, + {kTriggerConditionTimingMs}); +} + std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> ToHumanReadableMetrics( const std::vector<std::pair<ukm::SourceId, std::vector<UkmEnumVariant>>>& input) {
diff --git a/components/autofill_assistant/browser/ukm_test_util.h b/components/autofill_assistant/browser/ukm_test_util.h index 5e21ee8..b19c5e95 100644 --- a/components/autofill_assistant/browser/ukm_test_util.h +++ b/components/autofill_assistant/browser/ukm_test_util.h
@@ -27,6 +27,7 @@ const char kTriggerScriptOnboardingEntry[] = "AutofillAssistant.LiteScriptOnboarding"; const char kInChromeTriggeringEntry[] = "AutofillAssistant.InChromeTriggering"; +const char kAutofillAssistantTimingEntry[] = "AutofillAssistant.Timing"; // The identifiers for all UKM metrics that we currently record/test. const char kTriggerUiType[] = "TriggerUIType"; @@ -35,6 +36,7 @@ const char kTriggerScriptFinished[] = "LiteScriptFinished"; const char kTriggerScriptOnboarding[] = "LiteScriptOnboarding"; const char kInChromeTriggerAction[] = "InChromeTriggerAction"; +const char kTriggerConditionTimingMs[] = "TriggerConditionEvaluationMs"; // Convenience accessors for UKM metrics. std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> @@ -47,6 +49,8 @@ GetUkmTriggerScriptOnboarding(ukm::TestAutoSetUkmRecorder& ukm_recorder); std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> GetUkmInChromeTriggering(ukm::TestAutoSetUkmRecorder& ukm_recorder); +std::vector<ukm::TestUkmRecorder::HumanReadableUkmEntry> +GetUkmTriggerConditionEvaluationTime(ukm::TestAutoSetUkmRecorder& ukm_recorder); // Variant containing all UKM enums that we currently record/test. // NOTE: When adding entries, remember to also modify kUkmEnumMetricNames!
diff --git a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java index d523482..b671f22a 100644 --- a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java +++ b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java
@@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; +import android.text.method.LinkMovementMethod; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -89,6 +90,7 @@ mPositiveButton.setOnClickListener(this); mNegativeButton.setOnClickListener(this); + mMessageView.setMovementMethod(LinkMovementMethod.getInstance()); updateContentVisibility(); updateButtonVisibility(); @@ -247,7 +249,7 @@ } /** @param message The message in the dialog content. */ - void setMessage(String message) { + void setMessage(CharSequence message) { mMessageView.setText(message); updateContentVisibility(); }
diff --git a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java index 0b0b703..9c79f57a6 100644 --- a/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java +++ b/components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogViewTest.java
@@ -21,6 +21,9 @@ import android.app.Activity; import android.content.res.Resources; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; @@ -199,8 +202,8 @@ @Feature({"ModalDialog"}) public void testMessage() { // Verify that the message set from builder is displayed. - PropertyModel model = createModel( - mModelBuilder.with(ModalDialogProperties.MESSAGE, sResources, R.string.more)); + String msg = sResources.getString(R.string.more); + PropertyModel model = createModel(mModelBuilder.with(ModalDialogProperties.MESSAGE, msg)); onView(withId(R.id.title_container)).check(matches(not(isDisplayed()))); onView(withId(R.id.scrollable_title_container)).check(matches(not(isDisplayed()))); onView(withId(R.id.modal_dialog_scroll_view)).check(matches(isDisplayed())); @@ -212,6 +215,15 @@ onView(withId(R.id.scrollable_title_container)).check(matches(not(isDisplayed()))); onView(withId(R.id.modal_dialog_scroll_view)).check(matches(not(isDisplayed()))); onView(withId(R.id.message)).check(matches(not(isDisplayed()))); + + // Use CharSequence for the message. + SpannableStringBuilder sb = new SpannableStringBuilder(msg); + sb.setSpan(new ForegroundColorSpan(0xffff0000), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + TestThreadUtils.runOnUiThreadBlocking(() -> model.set(ModalDialogProperties.MESSAGE, sb)); + onView(withId(R.id.title_container)).check(matches(not(isDisplayed()))); + onView(withId(R.id.scrollable_title_container)).check(matches(not(isDisplayed()))); + onView(withId(R.id.modal_dialog_scroll_view)).check(matches(isDisplayed())); + onView(withId(R.id.message)).check(matches(allOf(isDisplayed(), withText(R.string.more)))); } @Test
diff --git a/components/cast_streaming/browser/cast_message_port_impl.cc b/components/cast_streaming/browser/cast_message_port_impl.cc index c9cbd3b7..ef443285 100644 --- a/components/cast_streaming/browser/cast_message_port_impl.cc +++ b/components/cast_streaming/browser/cast_message_port_impl.cc
@@ -15,6 +15,42 @@ namespace cast_streaming { +namespace { + +const char kKeyMediaSessionId[] = "mediaSessionId"; +const char kKeyPlaybackRate[] = "playbackRate"; +const char kKeyPlayerState[] = "playerState"; +const char kKeyCurrentTime[] = "currentTime"; +const char kKeySupportedMediaCommands[] = "supportedMediaCommands"; +const char kKeyDisableStreamGrouping[] = "disableStreamGrouping"; +const char kKeyMedia[] = "media"; +const char kKeyContentId[] = "contentId"; +const char kKeyStreamType[] = "streamType"; +const char kKeyContentType[] = "contentType"; +const char kValuePlaying[] = "PLAYING"; +const char kValueLive[] = "LIVE"; +const char kValueVideoWebm[] = "video/webm"; + +base::Value GetMediaCurrentStatusValue() { + base::Value media(base::Value::Type::DICTIONARY); + media.SetKey(kKeyContentId, base::Value("")); + media.SetKey(kKeyStreamType, base::Value(kValueLive)); + media.SetKey(kKeyContentType, base::Value(kValueVideoWebm)); + + base::Value media_current_status(base::Value::Type::DICTIONARY); + media_current_status.SetKey(kKeyMediaSessionId, base::Value(0)); + media_current_status.SetKey(kKeyPlaybackRate, base::Value(1.0)); + media_current_status.SetKey(kKeyPlayerState, base::Value(kValuePlaying)); + media_current_status.SetKey(kKeyCurrentTime, base::Value(0)); + media_current_status.SetKey(kKeySupportedMediaCommands, base::Value(0)); + media_current_status.SetKey(kKeyDisableStreamGrouping, base::Value(true)); + media_current_status.SetKey(kKeyMedia, std::move(media)); + + return media_current_status; +} + +} // namespace + CastMessagePortImpl::CastMessagePortImpl( std::unique_ptr<cast_api_bindings::MessagePort> message_port, base::OnceClosure on_close) @@ -104,6 +140,59 @@ PostMessage(sender_id, kInjectNamespace, json_message); } +void CastMessagePortImpl::HandleMediaMessage(const std::string& sender_id, + const std::string& message) { + absl::optional<base::Value> value = base::JSONReader::Read(message); + if (!value) { + LOG(ERROR) << "Malformed message from sender " << sender_id + << ": not a json payload: " << message; + return; + } + + if (!value->is_dict()) { + LOG(ERROR) << "Malformed message from sender " << sender_id + << ": non-dictionary json payload: " << message; + return; + } + + const std::string* type = value->FindStringKey(kKeyType); + if (!type) { + LOG(ERROR) << "Malformed message from sender " << sender_id + << ": no message type: " << message; + return; + } + + if (*type == kValueMediaPlay || *type == kValueMediaPause) { + // Not supported. Just ignore. + return; + } + + if (*type != kValueMediaGetStatus) { + LOG(ERROR) << "Malformed message from sender " << sender_id + << ": unknown message type: " << *type; + return; + } + + absl::optional<int> request_id = value->FindIntKey(kKeyRequestId); + if (!request_id.has_value()) { + LOG(ERROR) << "Malformed message from sender " << sender_id + << ": no request id: " << message; + return; + } + + base::Value message_status_list(base::Value::Type::LIST); + message_status_list.Append(GetMediaCurrentStatusValue()); + + base::Value response_value(base::Value::Type::DICTIONARY); + response_value.SetKey(kKeyRequestId, base::Value(request_id.value())); + response_value.SetKey(kKeyType, base::Value(kValueMediaStatus)); + response_value.SetKey(kKeyStatus, std::move(message_status_list)); + + std::string json_message; + CHECK(base::JSONWriter::Write(response_value, &json_message)); + PostMessage(sender_id, kMediaNamespace, json_message); +} + void CastMessagePortImpl::PostMessage(const std::string& sender_id, const std::string& message_namespace, const std::string& message) { @@ -151,6 +240,8 @@ client_->OnMessage(sender_id, message_namespace, str_message); } else if (message_namespace == kInjectNamespace) { SendInjectResponse(sender_id, str_message); + } else if (message_namespace == kMediaNamespace) { + HandleMediaMessage(sender_id, str_message); } else if (message_namespace != kSystemNamespace) { // System messages are ignored, log messages from unknown namespaces. DVLOG(2) << "Unknown message from " << sender_id
diff --git a/components/cast_streaming/browser/cast_message_port_impl.h b/components/cast_streaming/browser/cast_message_port_impl.h index da32d88..71c5ca16 100644 --- a/components/cast_streaming/browser/cast_message_port_impl.h +++ b/components/cast_streaming/browser/cast_message_port_impl.h
@@ -44,6 +44,11 @@ void SendInjectResponse(const std::string& sender_id, const std::string& message); + // Handles messages from the media namespace. Ignores play/pause requests and + // sends the media status as continuously playing. + void HandleMediaMessage(const std::string& sender_id, + const std::string& message); + // cast_api_bindings::MessagePort::Receiver implementation. bool OnMessage(base::StringPiece message, std::vector<std::unique_ptr<cast_api_bindings::MessagePort>>
diff --git a/components/cast_streaming/browser/cast_message_port_impl_unittest.cc b/components/cast_streaming/browser/cast_message_port_impl_unittest.cc index c8c175b..b71d4159 100644 --- a/components/cast_streaming/browser/cast_message_port_impl_unittest.cc +++ b/components/cast_streaming/browser/cast_message_port_impl_unittest.cc
@@ -209,4 +209,135 @@ RunUntilCastChannelClosed(); } +// Tests the media status namespace is properly handled. +TEST_F(CastMessagePortImplTest, MediaStatus) { + const int kRequestId = 42; + base::Value media_value(base::Value::Type::DICTIONARY); + media_value.SetKey(kKeyType, base::Value(kValueMediaGetStatus)); + media_value.SetKey(kKeyRequestId, base::Value(kRequestId)); + std::string media_message; + ASSERT_TRUE(base::JSONWriter::Write(media_value, &media_message)); + + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + sender_message_port_receiver_.RunUntilMessageCountEqual(2u); + ASSERT_EQ(sender_message_port_receiver_.buffer().size(), 2u); + + std::string sender_id; + std::string message_namespace; + std::string message; + ASSERT_TRUE( + DeserializeCastMessage(sender_message_port_receiver_.buffer().at(1).first, + &sender_id, &message_namespace, &message)); + EXPECT_EQ(sender_id, kSenderId); + EXPECT_EQ(message_namespace, kMediaNamespace); + + absl::optional<base::Value> return_value = base::JSONReader::Read(message); + ASSERT_TRUE(return_value); + ASSERT_TRUE(return_value->is_dict()); + + const std::string* type_value = return_value->FindStringKey(kKeyType); + ASSERT_TRUE(type_value); + EXPECT_EQ(*type_value, kValueMediaStatus); + + absl::optional<int> request_id_value = + return_value->FindIntKey(kKeyRequestId); + ASSERT_TRUE(request_id_value); + EXPECT_EQ(request_id_value.value(), kRequestId); + + const base::Value* status_value = return_value->FindListKey(kKeyStatus); + ASSERT_TRUE(status_value); + EXPECT_EQ(status_value->GetList().size(), 1u); +} + +// Checks sending invalid media messages results in no response. +TEST_F(CastMessagePortImplTest, InvalidMediaMessages) { + const int kRequestId = 42; + + { + // Send an invalid message value. + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, "not a json")); + } + + { + // Send a non-dictionary value. + std::string media_message; + ASSERT_TRUE( + base::JSONWriter::Write(base::Value("string value"), &media_message)); + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + } + + { + // Send a message with no type. + base::Value media_value(base::Value::Type::DICTIONARY); + media_value.SetKey(kKeyRequestId, base::Value(kRequestId)); + std::string media_message; + ASSERT_TRUE(base::JSONWriter::Write(media_value, &media_message)); + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + } + + { + // Send a PLAY message. This is not incorrect but should be ignored. + base::Value media_value(base::Value::Type::DICTIONARY); + media_value.SetKey(kKeyType, base::Value(kValueMediaPlay)); + media_value.SetKey(kKeyRequestId, base::Value(kRequestId)); + std::string media_message; + ASSERT_TRUE(base::JSONWriter::Write(media_value, &media_message)); + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + } + + { + // Send a PAUSE message. This is not incorrect but should be ignored. + base::Value media_value(base::Value::Type::DICTIONARY); + media_value.SetKey(kKeyType, base::Value(kValueMediaPause)); + media_value.SetKey(kKeyRequestId, base::Value(kRequestId)); + std::string media_message; + ASSERT_TRUE(base::JSONWriter::Write(media_value, &media_message)); + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + } + + { + // Send a message with an invalid type. + base::Value media_value(base::Value::Type::DICTIONARY); + media_value.SetKey(kKeyType, base::Value("INVALID_TYPE")); + media_value.SetKey(kKeyRequestId, base::Value(kRequestId)); + std::string media_message; + ASSERT_TRUE(base::JSONWriter::Write(media_value, &media_message)); + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + } + + { + // Send a GET_STATUS message with no request ID. + base::Value media_value(base::Value::Type::DICTIONARY); + media_value.SetKey(kKeyType, base::Value(kValueMediaGetStatus)); + std::string media_message; + ASSERT_TRUE(base::JSONWriter::Write(media_value, &media_message)); + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + } + + { + // Send a message with a non-integer request ID. + base::Value media_value(base::Value::Type::DICTIONARY); + media_value.SetKey(kKeyType, base::Value(kValueMediaGetStatus)); + media_value.SetKey(kKeyRequestId, base::Value("not an integer")); + std::string media_message; + ASSERT_TRUE(base::JSONWriter::Write(media_value, &media_message)); + sender_message_port_->PostMessage( + SerializeCastMessage(kSenderId, kMediaNamespace, media_message)); + } + + // Process all the things. There should be a single message (the original + // system message), since none of the other messages sent will trigger a + // response. + base::RunLoop().RunUntilIdle(); + ASSERT_EQ(sender_message_port_receiver_.buffer().size(), 1u); +} + } // namespace cast_streaming
diff --git a/components/cast_streaming/browser/message_serialization.cc b/components/cast_streaming/browser/message_serialization.cc index f7b5550..10a7095 100644 --- a/components/cast_streaming/browser/message_serialization.cc +++ b/components/cast_streaming/browser/message_serialization.cc
@@ -15,6 +15,7 @@ const char kRemotingNamespace[] = "urn:x-cast:com.google.cast.remoting"; const char kSystemNamespace[] = "urn:x-cast:com.google.cast.system"; const char kInjectNamespace[] = "urn:x-cast:com.google.cast.inject"; +const char kMediaNamespace[] = "urn:x-cast:com.google.cast.media"; const char kKeySenderId[] = "senderId"; const char kKeyNamespace[] = "namespace"; @@ -22,11 +23,17 @@ const char kKeyType[] = "type"; const char kKeyRequestId[] = "requestId"; const char kKeyCode[] = "code"; +const char kKeyStatus[] = "status"; const char kValueSystemSenderId[] = "SystemSender"; const char kValueWrapped[] = "WRAPPED"; const char kValueError[] = "ERROR"; const char kValueWrappedError[] = "WRAPPED_ERROR"; +const char kValueMediaPlay[] = "PLAY"; +const char kValueMediaPause[] = "PAUSE"; +const char kValueMediaGetStatus[] = "GET_STATUS"; +const char kValueMediaStatus[] = "MEDIA_STATUS"; + const char kValueInjectNotSupportedError[] = R"({"code":"NOT_SUPPORTED","type":"ERROR"})"; @@ -36,7 +43,8 @@ "activeNamespaces": [ "urn:x-cast:com.google.cast.webrtc", "urn:x-cast:com.google.cast.remoting", - "urn:x-cast:com.google.cast.inject" + "urn:x-cast:com.google.cast.inject", + "urn:x-cast:com.google.cast.media" ], "version": "2.0.0", "messagesVersion": "1.0"
diff --git a/components/cast_streaming/browser/message_serialization.h b/components/cast_streaming/browser/message_serialization.h index 6b5dc6e..1f2673c 100644 --- a/components/cast_streaming/browser/message_serialization.h +++ b/components/cast_streaming/browser/message_serialization.h
@@ -17,6 +17,7 @@ extern const char kRemotingNamespace[]; extern const char kSystemNamespace[]; extern const char kInjectNamespace[]; +extern const char kMediaNamespace[]; extern const char kKeySenderId[]; extern const char kKeyNamespace[]; @@ -24,10 +25,16 @@ extern const char kKeyType[]; extern const char kKeyRequestId[]; extern const char kKeyCode[]; +extern const char kKeyStatus[]; extern const char kValueSystemSenderId[]; extern const char kValueWrapped[]; extern const char kValueError[]; +extern const char kValueMediaPlay[]; +extern const char kValueMediaPause[]; +extern const char kValueMediaGetStatus[]; +extern const char kValueMediaStatus[]; + extern const char kValueWrappedError[]; extern const char kValueInjectNotSupportedError[];
diff --git a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc index a7d40da7..3ed4179 100644 --- a/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc +++ b/components/content_settings/core/browser/content_settings_origin_identifier_value_map.cc
@@ -23,16 +23,14 @@ // |resource_identifier| in the precedence order of the rules. class RuleIteratorImpl : public RuleIterator { public: - // |RuleIteratorImpl| takes the ownership of |auto_lock|. RuleIteratorImpl( const OriginIdentifierValueMap::Rules::const_iterator& current_rule, const OriginIdentifierValueMap::Rules::const_iterator& rule_end, - base::AutoLock* auto_lock) + std::unique_ptr<base::AutoLock> auto_lock) : current_rule_(current_rule), rule_end_(rule_end), - auto_lock_(auto_lock) { - } - ~RuleIteratorImpl() override {} + auto_lock_(std::move(auto_lock)) {} + ~RuleIteratorImpl() override = default; bool HasNext() const override { return (current_rule_ != rule_end_); } @@ -71,9 +69,9 @@ std::tie(other.primary_pattern, other.secondary_pattern); } -OriginIdentifierValueMap::ValueEntry::ValueEntry() {} +OriginIdentifierValueMap::ValueEntry::ValueEntry() = default; -OriginIdentifierValueMap::ValueEntry::~ValueEntry() {} +OriginIdentifierValueMap::ValueEntry::~ValueEntry() = default; std::unique_ptr<RuleIterator> OriginIdentifierValueMap::GetRuleIterator( ContentSettingsType content_type, @@ -88,8 +86,8 @@ auto it = entries_.find(content_type); if (it == entries_.end()) return nullptr; - return std::unique_ptr<RuleIterator>(new RuleIteratorImpl( - it->second.begin(), it->second.end(), auto_lock.release())); + return std::make_unique<RuleIteratorImpl>( + it->second.begin(), it->second.end(), std::move(auto_lock)); } size_t OriginIdentifierValueMap::size() const { @@ -99,9 +97,9 @@ return size; } -OriginIdentifierValueMap::OriginIdentifierValueMap() {} +OriginIdentifierValueMap::OriginIdentifierValueMap() = default; -OriginIdentifierValueMap::~OriginIdentifierValueMap() {} +OriginIdentifierValueMap::~OriginIdentifierValueMap() = default; const base::Value* OriginIdentifierValueMap::GetValue( const GURL& primary_url,
diff --git a/components/exo/extended_drag_source.cc b/components/exo/extended_drag_source.cc index 9876c5b..ab8ec93 100644 --- a/components/exo/extended_drag_source.cc +++ b/components/exo/extended_drag_source.cc
@@ -247,10 +247,12 @@ auto move_source = drag_event_source_ == ui::mojom::DragEventSource::kTouch ? ::wm::WINDOW_MOVE_SOURCE_TOUCH : ::wm::WINDOW_MOVE_SOURCE_MOUSE; + // TODO(crbug.com/1167581): Experiment setting |update_gesture_target| back + // to true when capture is removed from drag and drop. toplevel_handler->AttemptToStartDrag( toplevel, pointer_location, HTCAPTION, move_source, ash::ToplevelWindowEventHandler::EndClosure(), - /*update_gesture_target=*/true, /*grab_capture=*/false); + /*update_gesture_target=*/false, /*grab_capture=*/false); } void ExtendedDragSource::OnDraggedWindowVisibilityChanging(bool visible) {
diff --git a/components/exo/extended_drag_source_unittest.cc b/components/exo/extended_drag_source_unittest.cc index 89eef958..8a771f8 100644 --- a/components/exo/extended_drag_source_unittest.cc +++ b/components/exo/extended_drag_source_unittest.cc
@@ -23,10 +23,13 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/drag_drop_client.h" #include "ui/aura/client/drag_drop_delegate.h" +#include "ui/aura/window_tree_host.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h" #include "ui/base/dragdrop/os_exchange_data.h" +#include "ui/events/event_utils.h" #include "ui/events/test/event_generator.h" +#include "ui/events/test/events_test_utils.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/vector2d.h" @@ -34,6 +37,18 @@ namespace exo { namespace { +void DispatchGesture(ui::EventType gesture_type, gfx::Point location) { + ui::GestureEventDetails event_details(gesture_type); + ui::GestureEvent gesture_event(location.x(), location.y(), 0, + ui::EventTimeForNow(), event_details); + ui::EventSource* event_source = + ash::Shell::GetPrimaryRootWindow()->GetHost()->GetEventSource(); + ui::EventSourceTestApi event_source_test(event_source); + ui::EventDispatchDetails details = + event_source_test.SendEventToSink(&gesture_event); + CHECK(!details.dispatcher_destroyed); +} + class TestDataSourceDelegate : public DataSourceDelegate { public: TestDataSourceDelegate() {} @@ -256,6 +271,57 @@ EXPECT_EQ(gfx::Point(140, 140), window->GetBoundsInScreen().origin()); } +TEST_F(ExtendedDragSourceTest, DragSurfaceNotMappedYetWithTouch) { + // Create and Map the drag origin surface + auto surface = std::make_unique<Surface>(); + auto shell_surface = std::make_unique<ShellSurface>(surface.get()); + auto buffer = CreateBuffer({32, 32}); + surface->Attach(buffer.get()); + surface->Commit(); + + // Start the DND + extended-drag session. + StartExtendedDragSession(shell_surface->GetWidget()->GetNativeWindow(), + gfx::Point(0, 0), ui::DragDropTypes::DRAG_MOVE, + ui::mojom::DragEventSource::kTouch); + + // Create a new surface to emulate a "detachment" process. + auto detached_surface = std::make_unique<Surface>(); + auto detached_shell_surface = + std::make_unique<ShellSurface>(detached_surface.get()); + + // Set |surface| as the dragged surface while it's still unmapped/invisible. + // This can be used to implement tab detaching in Chrome's tab drag use case, + // for example. Extended drag source will monitor surface mapping and it's + // expected to position it correctly using the provided drag offset here + // relative to the current pointer location. + extended_drag_source_->Drag(detached_surface.get(), gfx::Vector2d(10, 10)); + EXPECT_FALSE(extended_drag_source_->GetDraggedWindowForTesting()); + EXPECT_TRUE(extended_drag_source_->GetDragOffsetForTesting().has_value()); + EXPECT_EQ(gfx::Vector2d(10, 10), + *extended_drag_source_->GetDragOffsetForTesting()); + + // Initiate the gesture sequence. + DispatchGesture(ui::ET_GESTURE_BEGIN, gfx::Point(10, 10)); + + // Map the |detached_surface|. + auto detached_buffer = CreateBuffer({50, 50}); + detached_surface->Attach(detached_buffer.get()); + detached_surface->Commit(); + + // Ensure the toplevel window for the dragged surface set above, is correctly + // detected, after it's mapped. + aura::Window* window = detached_shell_surface->GetWidget()->GetNativeWindow(); + EXPECT_TRUE(extended_drag_source_->GetDraggedWindowForTesting()); + EXPECT_EQ(window, extended_drag_source_->GetDraggedWindowForTesting()); + + // Verify that dragging it by 100,100, with drag offset 10,10 and current + // pointer location 50,50 will set the dragged window bounds as expected. + ui::test::EventGenerator generator(GetContext()); + generator.set_current_screen_location(gfx::Point(100, 100)); + generator.PressMoveAndReleaseTouchBy(50, 50); + EXPECT_EQ(gfx::Point(140, 140), window->GetBoundsInScreen().origin()); +} + TEST_F(ExtendedDragSourceTest, DestroyDraggedSurfaceWhileDragging) { // Create and map a toplevel shell surface. gfx::Size buffer_size(32, 32);
diff --git a/components/feed/core/proto/v2/wire/chrome_client_info.proto b/components/feed/core/proto/v2/wire/chrome_client_info.proto index 97edd3a..7b7939b 100644 --- a/components/feed/core/proto/v2/wire/chrome_client_info.proto +++ b/components/feed/core/proto/v2/wire/chrome_client_info.proto
@@ -10,4 +10,5 @@ message ChromeClientInfo { optional string session_id = 3; + optional bool start_surface = 4; }
diff --git a/components/feed/core/v2/api_test/feed_api_stream_unittest.cc b/components/feed/core/v2/api_test/feed_api_stream_unittest.cc index 3664a6c0..2f37ae9d 100644 --- a/components/feed/core/v2/api_test/feed_api_stream_unittest.cc +++ b/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
@@ -1959,7 +1959,8 @@ .empty()); EXPECT_FALSE(network_.query_request_sent->feed_request() .client_info() - .has_chrome_client_info()); + .chrome_client_info() + .has_session_id()); EXPECT_EQ(kSessionToken1, stream_->GetMetadata().session_id().token()); const base::Time kSessionToken1ExpiryTime = feedstore::GetSessionIdExpiryTime(stream_->GetMetadata()); @@ -2074,7 +2075,8 @@ ASSERT_EQ(1, network_.send_query_call_count); EXPECT_FALSE(network_.query_request_sent->feed_request() .client_info() - .has_chrome_client_info()); + .chrome_client_info() + .has_session_id()); EXPECT_EQ(kSessionToken1, stream_->GetMetadata().session_id().token()); // (2) Reload the stream from the network: @@ -2114,7 +2116,8 @@ ASSERT_EQ(3, network_.send_query_call_count); EXPECT_FALSE(network_.query_request_sent->feed_request() .client_info() - .has_chrome_client_info()); + .chrome_client_info() + .has_session_id()); EXPECT_EQ(kSessionToken2, stream_->GetMetadata().session_id().token()); } @@ -2537,6 +2540,38 @@ EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates()); } +TEST_F(FeedApiTest, StartSurface) { + CreateStream(/*wait_for_initialization=*/true, /*start_surface=*/true); + TestForYouSurface surface(stream_.get()); + WaitForIdleTaskQueue(); + response_translator_.InjectResponse(MakeTypicalRefreshModelState()); + CallbackReceiver<bool> callback; + stream_->ManualRefresh(surface.GetStreamType(), callback.Bind()); + WaitForIdleTaskQueue(); + + ASSERT_TRUE(network_.query_request_sent.has_value()); + EXPECT_TRUE(network_.query_request_sent->feed_request() + .client_info() + .chrome_client_info() + .start_surface()); +} + +TEST_F(FeedApiTest, NoStartSurface) { + CreateStream(/*wait_for_initialization=*/true, /*start_surface=*/false); + TestForYouSurface surface(stream_.get()); + WaitForIdleTaskQueue(); + response_translator_.InjectResponse(MakeTypicalRefreshModelState()); + CallbackReceiver<bool> callback; + stream_->ManualRefresh(surface.GetStreamType(), callback.Bind()); + WaitForIdleTaskQueue(); + + ASSERT_TRUE(network_.query_request_sent.has_value()); + EXPECT_FALSE(network_.query_request_sent->feed_request() + .client_info() + .chrome_client_info() + .start_surface()); +} + TEST_F(FeedStreamTestForAllStreamTypes, ContentOrderIsGroupedByDefault) { response_translator_.InjectResponse(MakeTypicalInitialModelState()); TestWebFeedSurface surface(stream_.get());
diff --git a/components/feed/core/v2/api_test/feed_api_test.cc b/components/feed/core/v2/api_test/feed_api_test.cc index 8a1dab0f..4f23ae7 100644 --- a/components/feed/core/v2/api_test/feed_api_test.cc +++ b/components/feed/core/v2/api_test/feed_api_test.cc
@@ -815,10 +815,12 @@ prefetch_image_call_count_++; } -void FeedApiTest::CreateStream(bool wait_for_initialization) { +void FeedApiTest::CreateStream(bool wait_for_initialization, + bool start_surface) { ChromeInfo chrome_info; chrome_info.channel = version_info::Channel::STABLE; chrome_info.version = base::Version({99, 1, 9911, 2}); + chrome_info.start_surface = start_surface; stream_ = std::make_unique<FeedStream>( &refresh_scheduler_, metrics_reporter_.get(), this, &profile_prefs_, &network_, image_fetcher_.get(), store_.get(),
diff --git a/components/feed/core/v2/api_test/feed_api_test.h b/components/feed/core/v2/api_test/feed_api_test.h index e6bc0ec..6c17c07 100644 --- a/components/feed/core/v2/api_test/feed_api_test.h +++ b/components/feed/core/v2/api_test/feed_api_test.h
@@ -443,7 +443,8 @@ // For tests. // Replace stream_. - void CreateStream(bool wait_for_initialization = true); + void CreateStream(bool wait_for_initialization = true, + bool start_surface = false); std::unique_ptr<StreamModel> CreateStreamModel(); bool IsTaskQueueIdle() const; void WaitForIdleTaskQueue();
diff --git a/components/feed/core/v2/proto_util.cc b/components/feed/core/v2/proto_util.cc index 40882f7d..8214d394 100644 --- a/components/feed/core/v2/proto_util.cc +++ b/components/feed/core/v2/proto_util.cc
@@ -258,6 +258,8 @@ request_metadata.session_id); } + client_info.mutable_chrome_client_info()->set_start_surface( + request_metadata.chrome_info.start_surface); return client_info; }
diff --git a/components/feed/core/v2/proto_util_unittest.cc b/components/feed/core/v2/proto_util_unittest.cc index 6770a895..940992b 100644 --- a/components/feed/core/v2/proto_util_unittest.cc +++ b/components/feed/core/v2/proto_util_unittest.cc
@@ -48,6 +48,13 @@ EXPECT_EQ("en-US", result.locale()); } +TEST(ProtoUtilTest, ClientInfoStartSurface) { + RequestMetadata request_metadata; + request_metadata.chrome_info.start_surface = true; + feedwire::ClientInfo result = CreateClientInfo(request_metadata); + EXPECT_TRUE(result.chrome_client_info().start_surface()); +} + TEST(ProtoUtilTest, DefaultCapabilities) { feedwire::FeedRequest request = CreateFeedQueryRefreshRequest(kForYouStream,
diff --git a/components/feed/core/v2/public/types.h b/components/feed/core/v2/public/types.h index 5e18416..ff5b0b15 100644 --- a/components/feed/core/v2/public/types.h +++ b/components/feed/core/v2/public/types.h
@@ -26,10 +26,11 @@ kRefreshWebFeed, }; -// Information about the Chrome build. +// Information about the Chrome build and feature flags. struct ChromeInfo { version_info::Channel channel{}; base::Version version; + bool start_surface; }; // Device display metrics. struct DisplayMetrics {
diff --git a/components/flags_ui/flags_test_helpers.cc b/components/flags_ui/flags_test_helpers.cc index f5b2ac1..ff11d5c 100644 --- a/components/flags_ui/flags_test_helpers.cc +++ b/components/flags_ui/flags_test_helpers.cc
@@ -291,7 +291,8 @@ FlagFile::kFlagNeverExpire); } -// TODO(ellyjones): Does this / should this run on iOS as well? +// TODO(https://crbug.com/1241068): Call this from the iOS flags unittests once +// flag expiration is supported there. void EnsureRecentUnexpireFlagsArePresent( const base::span<const flags_ui::FeatureEntry>& entries, int current_milestone) {
diff --git a/components/media_message_center/media_notification_view_impl.cc b/components/media_message_center/media_notification_view_impl.cc index 9e949e6..56b9538 100644 --- a/components/media_message_center/media_notification_view_impl.cc +++ b/components/media_message_center/media_notification_view_impl.cc
@@ -104,6 +104,7 @@ case MediaSessionAction::kToggleCamera: case MediaSessionAction::kHangUp: case MediaSessionAction::kRaise: + case MediaSessionAction::kSetMute: NOTREACHED(); break; }
diff --git a/components/media_message_center/media_notification_view_modern_impl.cc b/components/media_message_center/media_notification_view_modern_impl.cc index 8beda3e..30f4b6a 100644 --- a/components/media_message_center/media_notification_view_modern_impl.cc +++ b/components/media_message_center/media_notification_view_modern_impl.cc
@@ -111,6 +111,7 @@ case MediaSessionAction::kToggleCamera: case MediaSessionAction::kHangUp: case MediaSessionAction::kRaise: + case MediaSessionAction::kSetMute: NOTREACHED(); break; } @@ -154,6 +155,7 @@ case MediaSessionAction::kToggleCamera: case MediaSessionAction::kHangUp: case MediaSessionAction::kRaise: + case MediaSessionAction::kSetMute: NOTREACHED(); break; } @@ -439,20 +441,19 @@ volume_slider->SetPreferredSize(kVolumeSliderSize); volume_slider_ = util_buttons_container->AddChildView(std::move(volume_slider)); - - auto mute_button = - std::make_unique<views::ToggleImageButton>(base::BindRepeating( - &MediaNotificationViewModernImpl::OnMuteButtonClicked, - base::Unretained(this))); - mute_button->SetPreferredSize(kMuteButtonSize); - mute_button->SetImageHorizontalAlignment( - views::ImageButton::HorizontalAlignment::ALIGN_CENTER); - mute_button->SetImageVerticalAlignment( - views::ImageButton::VerticalAlignment::ALIGN_MIDDLE); - mute_button_ = - util_buttons_container->AddChildView(std::move(mute_button)); } + auto mute_button = + std::make_unique<views::ToggleImageButton>(base::BindRepeating( + &MediaNotificationViewModernImpl::OnMuteButtonClicked, + base::Unretained(this))); + mute_button->SetPreferredSize(kMuteButtonSize); + mute_button->SetImageHorizontalAlignment( + views::ImageButton::HorizontalAlignment::ALIGN_CENTER); + mute_button->SetImageVerticalAlignment( + views::ImageButton::VerticalAlignment::ALIGN_MIDDLE); + mute_button_ = util_buttons_container->AddChildView(std::move(mute_button)); + AddChildView(std::move(util_buttons_container)); }
diff --git a/components/metrics/field_trials_provider_unittest.cc b/components/metrics/field_trials_provider_unittest.cc index 9182c50..e379789 100644 --- a/components/metrics/field_trials_provider_unittest.cc +++ b/components/metrics/field_trials_provider_unittest.cc
@@ -5,6 +5,7 @@ #include "components/metrics/field_trials_provider.h" #include "base/cxx17_backports.h" +#include "base/threading/platform_thread.h" #include "components/variations/active_field_trials.h" #include "components/variations/synthetic_trial_registry.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/mirroring/mojom/BUILD.gn b/components/mirroring/mojom/BUILD.gn index bcee9163..4b2ce67 100644 --- a/components/mirroring/mojom/BUILD.gn +++ b/components/mirroring/mojom/BUILD.gn
@@ -34,6 +34,7 @@ "//media/capture/mojom:video_capture", "//media/mojo/mojom", "//media/mojo/mojom:remoting", + "//sandbox/policy/mojom", "//services/network/public/mojom", "//services/viz/public/mojom", "//ui/gfx/geometry/mojom",
diff --git a/components/mirroring/mojom/mirroring_service.mojom b/components/mirroring/mojom/mirroring_service.mojom index df85bc3..ae64d9a9 100644 --- a/components/mirroring/mojom/mirroring_service.mojom +++ b/components/mirroring/mojom/mirroring_service.mojom
@@ -8,9 +8,17 @@ import "components/mirroring/mojom/resource_provider.mojom"; import "components/mirroring/mojom/session_observer.mojom"; import "components/mirroring/mojom/session_parameters.mojom"; +import "sandbox/policy/mojom/sandbox.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; -// This interface is used to control a mirroring session. +[EnableIf=is_mac] +const sandbox.mojom.Sandbox kMirroringSandbox + = sandbox.mojom.Sandbox.kMirroring; +[EnableIfNot=is_mac] +const sandbox.mojom.Sandbox kMirroringSandbox = sandbox.mojom.Sandbox.kUtility; + +// This interface is used to control a Cast mirroring session. +[ServiceSandbox=kMirroringSandbox] interface MirroringService { // Starts a mirroring session. |max_resolution| is the maximium video // capturing resolution. |observer| will get notifications about lifecycle
diff --git a/components/optimization_guide/core/optimization_guide_features.cc b/components/optimization_guide/core/optimization_guide_features.cc index 1e4edfc..c56f3fa 100644 --- a/components/optimization_guide/core/optimization_guide_features.cc +++ b/components/optimization_guide/core/optimization_guide_features.cc
@@ -25,8 +25,14 @@ // Enables the syncing of the Optimization Hints component, which provides // hints for what optimizations can be applied on a page load. -const base::Feature kOptimizationHints{"OptimizationHints", - base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kOptimizationHints { + "OptimizationHints", +#if defined(OS_IOS) + base::FEATURE_DISABLED_BY_DEFAULT +#else // !defined(OS_IOS) + base::FEATURE_ENABLED_BY_DEFAULT +#endif // defined(OS_IOS) +}; // Feature flag that contains a feature param that specifies the field trials // that are allowed to be sent up to the Optimization Guide Server.
diff --git a/components/optimization_guide/core/optimization_hints_component_update_listener.h b/components/optimization_guide/core/optimization_hints_component_update_listener.h index a4c5bda..314249f30 100644 --- a/components/optimization_guide/core/optimization_hints_component_update_listener.h +++ b/components/optimization_guide/core/optimization_hints_component_update_listener.h
@@ -12,6 +12,8 @@ #include "components/optimization_guide/core/optimization_hints_component_observer.h" #include "third_party/abseil-cpp/absl/types/optional.h" +class OptimizationGuideServiceTest; + namespace optimization_guide { // Tracks the info for the current Optimization Hints component and notifies @@ -51,6 +53,7 @@ friend class base::NoDestructor<OptimizationHintsComponentUpdateListener>; friend class OptimizationHintsComponentUpdateListenerTest; + friend class ::OptimizationGuideServiceTest; void ResetStateForTesting();
diff --git a/components/paint_preview/player/player_compositor_delegate.h b/components/paint_preview/player/player_compositor_delegate.h index a0c4ca6..6f6b7e5 100644 --- a/components/paint_preview/player/player_compositor_delegate.h +++ b/components/paint_preview/player/player_compositor_delegate.h
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/cancelable_callback.h" #include "base/containers/flat_map.h" +#include "base/containers/queue.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/weak_ptr.h" #include "base/unguessable_token.h"
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java index afb2267..20af7d1c 100644 --- a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java +++ b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java
@@ -232,8 +232,9 @@ .with(ModalDialogProperties.TITLE, context.getString(R.string.overlay_detected_dialog_title, BuildInfo.getInstance().hostPackageLabel)) - .with(ModalDialogProperties.MESSAGE, context.getResources(), - R.string.overlay_detected_dialog_message) + .with(ModalDialogProperties.MESSAGE, + context.getResources().getString( + R.string.overlay_detected_dialog_message)) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, context.getResources(), R.string.cancel) .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, context.getResources(),
diff --git a/components/policy/core/browser/BUILD.gn b/components/policy/core/browser/BUILD.gn index 604dcbd..43414401 100644 --- a/components/policy/core/browser/BUILD.gn +++ b/components/policy/core/browser/BUILD.gn
@@ -34,8 +34,6 @@ "policy_conversions_client.h", "policy_error_map.cc", "policy_error_map.h", - "proxy_policy_handler.cc", - "proxy_policy_handler.h", "url_allowlist_policy_handler.cc", "url_allowlist_policy_handler.h", "url_blocklist_manager.cc", @@ -86,7 +84,6 @@ public_deps += [ "//components/policy/core/common:internal" ] deps += [ - "//components/proxy_config", "//google_apis", "//net", "//third_party/icu", @@ -138,7 +135,6 @@ "configuration_policy_handler_unittest.cc", "configuration_policy_pref_store_unittest.cc", "policy_error_map_unittest.cc", - "proxy_policy_handler_unittest.cc", "url_allowlist_policy_handler_unittest.cc", "url_blocklist_manager_unittest.cc", "url_blocklist_policy_handler_unittest.cc", @@ -150,7 +146,6 @@ "//base", "//components/policy:generated", "//components/prefs:test_support", - "//components/proxy_config", "//components/url_formatter", "//google_apis", "//net",
diff --git a/components/policy/core/browser/DEPS b/components/policy/core/browser/DEPS index 15fc70d9..0c52c59b 100644 --- a/components/policy/core/browser/DEPS +++ b/components/policy/core/browser/DEPS
@@ -1,7 +1,6 @@ include_rules = [ "+components/google/core", "+components/pref_registry", - "+components/proxy_config", "+components/reporting", "+components/strings/grit/components_strings.h", "+components/url_formatter",
diff --git a/components/policy/core/common/policy_service_impl.cc b/components/policy/core/common/policy_service_impl.cc index 8d95230d..c25412e3 100644 --- a/components/policy/core/common/policy_service_impl.cc +++ b/components/policy/core/common/policy_service_impl.cc
@@ -39,48 +39,6 @@ namespace { -const char* kProxyPolicies[] = { - key::kProxyMode, key::kProxyServerMode, key::kProxyServer, - key::kProxyPacUrl, kProxyPacMandatory, key::kProxyBypassList, -}; - -// Maps the separate policies for proxy settings into a single Dictionary -// policy. This allows to keep the logic of merging policies from different -// sources simple, as all separate proxy policies should be considered as a -// single whole during merging. -void RemapProxyPolicies(PolicyMap* policies) { - // The highest (level, scope) pair for an existing proxy policy is determined - // first, and then only policies with those exact attributes are merged. - PolicyMap::Entry current_priority; // Defaults to the lowest priority. - PolicySource inherited_source = POLICY_SOURCE_ENTERPRISE_DEFAULT; - base::Value proxy_settings(base::Value::Type::DICTIONARY); - for (size_t i = 0; i < base::size(kProxyPolicies); ++i) { - const PolicyMap::Entry* entry = policies->Get(kProxyPolicies[i]); - if (entry) { - if (entry->has_higher_priority_than(current_priority)) { - proxy_settings = base::Value(base::Value::Type::DICTIONARY); - current_priority = entry->DeepCopy(); - if (entry->source > inherited_source) // Higher priority? - inherited_source = entry->source; - } - if (!entry->has_higher_priority_than(current_priority) && - !current_priority.has_higher_priority_than(*entry)) { - proxy_settings.SetKey(kProxyPolicies[i], entry->value()->Clone()); - } - policies->Erase(kProxyPolicies[i]); - } - } - // Sets the new |proxy_settings| if kProxySettings isn't set yet, or if the - // new priority is higher. - const PolicyMap::Entry* existing = policies->Get(key::kProxySettings); - if (!proxy_settings.DictEmpty() && - (!existing || current_priority.has_higher_priority_than(*existing))) { - policies->Set(key::kProxySettings, current_priority.level, - current_priority.scope, inherited_source, - std::move(proxy_settings), nullptr); - } -} - // Maps the separate renamed policies into a single Dictionary policy. This // allows to keep the logic of merging policies from different sources simple, // as all separate renamed policies should be considered as a single whole @@ -377,7 +335,6 @@ for (auto* provider : providers_) { PolicyBundle provided_bundle; provided_bundle.CopyFrom(provider->policies()); - RemapProxyPolicies(&provided_bundle.Get(chrome_namespace)); RemapRenamedPolicies(&provided_bundle.Get(chrome_namespace)); DowngradeMetricsReportingToRecommendedPolicy( &provided_bundle.Get(chrome_namespace));
diff --git a/components/policy/core/common/policy_service_impl_unittest.cc b/components/policy/core/common/policy_service_impl_unittest.cc index 6358a41a..9a8cabd 100644 --- a/components/policy/core/common/policy_service_impl_unittest.cc +++ b/components/policy/core/common/policy_service_impl_unittest.cc
@@ -1212,54 +1212,6 @@ policy_service_->RemoveObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer); } -TEST_F(PolicyServiceTest, SeparateProxyPoliciesMerging) { - const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string()); - const PolicyNamespace extension_namespace(POLICY_DOMAIN_EXTENSIONS, "xyz"); - - std::unique_ptr<PolicyBundle> policy_bundle(new PolicyBundle()); - PolicyMap& policy_map = policy_bundle->Get(chrome_namespace); - // Individual proxy policy values in the Chrome namespace should be collected - // into a dictionary. - policy_map.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, - POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(3), - nullptr); - - // Both these policies should be ignored, since there's a higher priority - // policy available. - policy_map.Set(key::kProxyMode, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, - POLICY_SOURCE_CLOUD, base::Value("pac_script"), nullptr); - policy_map.Set(key::kProxyPacUrl, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, - POLICY_SOURCE_CLOUD, - base::Value("http://example.com/wpad.dat"), nullptr); - - // Add a value to a non-Chrome namespace. - policy_bundle->Get(extension_namespace) - .Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - POLICY_SOURCE_CLOUD, base::Value(3), nullptr); - - // The resulting Chrome namespace map should have the collected policy. - PolicyMap expected_chrome; - base::Value expected_value(base::Value::Type::DICTIONARY); - expected_value.SetIntKey(key::kProxyServerMode, 3); - expected_chrome.Set(key::kProxySettings, POLICY_LEVEL_MANDATORY, - POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, - std::move(expected_value), nullptr); - expected_chrome.Set("migrated", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - POLICY_SOURCE_PLATFORM, base::Value(15), nullptr); - - // The resulting Extensions namespace map shouldn't have been modified. - PolicyMap expected_extension; - expected_extension.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, - POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(3), - nullptr); - - provider0_.UpdatePolicy(std::move(policy_bundle)); - RunUntilIdle(); - - EXPECT_TRUE(VerifyPolicies(chrome_namespace, expected_chrome)); - EXPECT_TRUE(VerifyPolicies(extension_namespace, expected_extension)); -} - TEST_F(PolicyServiceTest, DictionaryPoliciesMerging) { const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
diff --git a/components/power_scheduler/power_scheduler.cc b/components/power_scheduler/power_scheduler.cc index 794234b..4a16a25 100644 --- a/components/power_scheduler/power_scheduler.cc +++ b/components/power_scheduler/power_scheduler.cc
@@ -15,6 +15,7 @@ #include "base/no_destructor.h" #include "base/process/process_handle.h" #include "base/process/process_metrics.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/task/current_thread.h" #include "base/task/thread_pool.h"
diff --git a/components/proxy_config/BUILD.gn b/components/proxy_config/BUILD.gn index 9a0386e0..4e09932 100644 --- a/components/proxy_config/BUILD.gn +++ b/components/proxy_config/BUILD.gn
@@ -15,6 +15,8 @@ "proxy_config_export.h", "proxy_config_pref_names.cc", "proxy_config_pref_names.h", + "proxy_policy_handler.cc", + "proxy_policy_handler.h", "proxy_prefs.cc", "proxy_prefs.h", ] @@ -23,7 +25,11 @@ deps = [ "//base", + "//components/policy:generated", + "//components/policy/core/browser", + "//components/policy/core/common", "//components/prefs", + "//components/strings", "//net", "//url", ] @@ -44,16 +50,22 @@ sources = [ "pref_proxy_config_tracker_impl_unittest.cc", "proxy_config_dictionary_unittest.cc", + "proxy_policy_handler_unittest.cc", "proxy_prefs_unittest.cc", ] deps = [ ":proxy_config", "//base", "//base/test:test_support", + "//components/policy:generated", + "//components/policy/core/browser", + "//components/policy/core/browser:test_support", + "//components/policy/core/common", "//components/prefs:test_support", "//net", "//net:test_support", "//testing/gmock", "//testing/gtest", + "//third_party/abseil-cpp:absl", ] }
diff --git a/components/proxy_config/DEPS b/components/proxy_config/DEPS index 069741e..9bf5de8ad 100644 --- a/components/proxy_config/DEPS +++ b/components/proxy_config/DEPS
@@ -1,5 +1,9 @@ include_rules = [ + "+components/policy", + "+components/policy/core/browser", + "+components/policy/core/common", "+components/pref_registry", "+components/prefs", + "+components/strings/grit/components_strings.h", "+net" ]
diff --git a/components/policy/core/browser/proxy_policy_handler.cc b/components/proxy_config/proxy_policy_handler.cc similarity index 62% rename from components/policy/core/browser/proxy_policy_handler.cc rename to components/proxy_config/proxy_policy_handler.cc index 406b8a9..9f0c7ea 100644 --- a/components/policy/core/browser/proxy_policy_handler.cc +++ b/components/proxy_config/proxy_policy_handler.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 "components/policy/core/browser/proxy_policy_handler.h" +#include "components/proxy_config/proxy_policy_handler.h" #include <stddef.h> @@ -23,6 +23,16 @@ namespace { +using policy::kProxyPacMandatory; +using policy::PolicyErrorMap; +using policy::PolicyMap; +using policy::key::kProxyBypassList; +using policy::key::kProxyMode; +using policy::key::kProxyPacUrl; +using policy::key::kProxyServer; +using policy::key::kProxyServerMode; +using policy::key::kProxySettings; + // This is used to check whether for a given ProxyMode value, the ProxyPacUrl, // the ProxyBypassList and the ProxyServer policies are allowed to be specified. // |error_message_id| is the message id of the localized error message to show @@ -52,9 +62,53 @@ IDS_POLICY_PROXY_MODE_SYSTEM_ERROR}, }; +const char* kDeprecatedProxyPolicies[] = { + kProxyMode, kProxyServerMode, kProxyServer, kProxyPacUrl, kProxyBypassList, +}; + +// Maps the separate deprecated policies for proxy settings into a single +// Dictionary policy. This allows to keep the logic of merging policies from +// different sources simple, as all separate proxy policies should be considered +// as a single whole during merging. Returns proxy_settings value. +base::Value RemapProxyPolicies(const PolicyMap& policies) { + // The highest (level, scope) pair for an existing proxy policy is determined + // first, and then only policies with those exact attributes are merged. + PolicyMap::Entry current_priority; // Defaults to the lowest priority. + policy::PolicySource inherited_source = + policy::POLICY_SOURCE_ENTERPRISE_DEFAULT; + base::Value proxy_settings(base::Value::Type::DICTIONARY); + for (size_t i = 0; i < base::size(kDeprecatedProxyPolicies); ++i) { + const PolicyMap::Entry* entry = policies.Get(kDeprecatedProxyPolicies[i]); + if (!entry) + continue; + if (entry->has_higher_priority_than(current_priority)) { + proxy_settings = base::Value(base::Value::Type::DICTIONARY); + current_priority = entry->DeepCopy(); + if (entry->source > inherited_source) // Higher priority? + inherited_source = entry->source; + } + // If two priorities are the same. + if (!entry->has_higher_priority_than(current_priority) && + !current_priority.has_higher_priority_than(*entry)) { + proxy_settings.SetKey(kDeprecatedProxyPolicies[i], + entry->value()->Clone()); + } + } + // Sets the new |proxy_settings| if kProxySettings isn't set yet, or if the + // new priority is higher. + const PolicyMap::Entry* existing = policies.Get(kProxySettings); + if (!proxy_settings.DictEmpty() && + (!existing || current_priority.has_higher_priority_than(*existing))) { + return proxy_settings; + } else if (existing && existing->value()) { + return existing->value()->Clone(); + } + return base::Value(); +} + } // namespace -namespace policy { +namespace proxy_config { // The proxy policies have the peculiarity that they are loaded from individual // policies, but the providers then expose them through a unified @@ -62,30 +116,31 @@ ProxyPolicyHandler::ProxyPolicyHandler() {} -ProxyPolicyHandler::~ProxyPolicyHandler() { -} +ProxyPolicyHandler::~ProxyPolicyHandler() {} bool ProxyPolicyHandler::CheckPolicySettings(const PolicyMap& policies, PolicyErrorMap* errors) { - const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode); - const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer); + base::Value proxy_settings = RemapProxyPolicies(policies); + const base::Value* mode = GetProxyPolicyValue(&proxy_settings, kProxyMode); + const base::Value* server = + GetProxyPolicyValue(&proxy_settings, kProxyServer); const base::Value* server_mode = - GetProxyPolicyValue(policies, key::kProxyServerMode); - const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl); + GetProxyPolicyValue(&proxy_settings, kProxyServerMode); + const base::Value* pac_url = + GetProxyPolicyValue(&proxy_settings, kProxyPacUrl); const base::Value* pac_mandatory = - GetProxyPolicyValue(policies, kProxyPacMandatory); + GetProxyPolicyValue(&proxy_settings, kProxyPacMandatory); const base::Value* bypass_list = - GetProxyPolicyValue(policies, key::kProxyBypassList); + GetProxyPolicyValue(&proxy_settings, kProxyBypassList); if ((server || pac_url || bypass_list) && !(mode || server_mode)) { - errors->AddError(key::kProxySettings, - key::kProxyMode, + errors->AddError(kProxySettings, kProxyMode, IDS_POLICY_NOT_SPECIFIED_ERROR); return false; } std::string mode_value; - if (!CheckProxyModeAndServerMode(policies, errors, &mode_value)) + if (!CheckProxyModeAndServerMode(&proxy_settings, errors, &mode_value)) return false; // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be @@ -102,23 +157,18 @@ is_valid_mode = true; if (!entry.pac_url_allowed && pac_url) { - errors->AddError(key::kProxySettings, - key::kProxyPacUrl, - entry.error_message_id); + errors->AddError(kProxySettings, kProxyPacUrl, entry.error_message_id); } if (!entry.pac_mandatory_allowed && pac_mandatory) { - errors->AddError(key::kProxySettings, kProxyPacMandatory, + errors->AddError(kProxySettings, kProxyPacMandatory, entry.error_message_id); } if (!entry.bypass_list_allowed && bypass_list) { - errors->AddError(key::kProxySettings, - key::kProxyBypassList, + errors->AddError(kProxySettings, kProxyBypassList, entry.error_message_id); } if (!entry.server_allowed && server) { - errors->AddError(key::kProxySettings, - key::kProxyServer, - entry.error_message_id); + errors->AddError(kProxySettings, kProxyServer, entry.error_message_id); } if ((!entry.pac_url_allowed && pac_url) || @@ -130,10 +180,8 @@ } if (!is_valid_mode) { - errors->AddError(key::kProxySettings, - mode ? key::kProxyMode : key::kProxyServerMode, - IDS_POLICY_OUT_OF_RANGE_ERROR, - mode_value); + errors->AddError(kProxySettings, mode ? kProxyMode : kProxyServerMode, + IDS_POLICY_OUT_OF_RANGE_ERROR, mode_value); return false; } return true; @@ -141,15 +189,18 @@ void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap& policies, PrefValueMap* prefs) { - const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode); - const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer); + base::Value proxy_settings = RemapProxyPolicies(policies); + const base::Value* mode = GetProxyPolicyValue(&proxy_settings, kProxyMode); + const base::Value* server = + GetProxyPolicyValue(&proxy_settings, kProxyServer); const base::Value* server_mode = - GetProxyPolicyValue(policies, key::kProxyServerMode); - const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl); + GetProxyPolicyValue(&proxy_settings, kProxyServerMode); + const base::Value* pac_url = + GetProxyPolicyValue(&proxy_settings, kProxyPacUrl); const base::Value* pac_mandatory = - GetProxyPolicyValue(policies, kProxyPacMandatory); + GetProxyPolicyValue(&proxy_settings, kProxyPacMandatory); const base::Value* bypass_list = - GetProxyPolicyValue(policies, key::kProxyBypassList); + GetProxyPolicyValue(&proxy_settings, kProxyBypassList); ProxyPrefs::ProxyMode proxy_mode; if (mode) { @@ -221,9 +272,8 @@ } const base::Value* ProxyPolicyHandler::GetProxyPolicyValue( - const PolicyMap& policies, const char* policy_name) { - // See note on the ProxyPolicyHandler implementation above. - const base::Value* value = policies.GetValue(key::kProxySettings); + const base::Value* value, + const char* policy_name) { const base::DictionaryValue* settings; if (!value || !value->GetAsDictionary(&settings)) return nullptr; @@ -237,27 +287,26 @@ return policy_value; } -bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap& policies, - PolicyErrorMap* errors, - std::string* mode_value) { - const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode); - const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer); +bool ProxyPolicyHandler::CheckProxyModeAndServerMode( + const base::Value* proxy_settings, + PolicyErrorMap* errors, + std::string* mode_value) { + const base::Value* mode = GetProxyPolicyValue(proxy_settings, kProxyMode); + const base::Value* server = GetProxyPolicyValue(proxy_settings, kProxyServer); const base::Value* server_mode = - GetProxyPolicyValue(policies, key::kProxyServerMode); - const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl); + GetProxyPolicyValue(proxy_settings, kProxyServerMode); + const base::Value* pac_url = + GetProxyPolicyValue(proxy_settings, kProxyPacUrl); // If there's a server mode, convert it into a mode. // When both are specified, the mode takes precedence. if (mode) { if (server_mode) { - errors->AddError(key::kProxySettings, - key::kProxyServerMode, - IDS_POLICY_OVERRIDDEN, - key::kProxyMode); + errors->AddError(kProxySettings, kProxyServerMode, IDS_POLICY_OVERRIDDEN, + kProxyMode); } if (!mode->is_string()) { - errors->AddError(key::kProxySettings, key::kProxyMode, - IDS_POLICY_TYPE_ERROR, + errors->AddError(kProxySettings, kProxyMode, IDS_POLICY_TYPE_ERROR, base::Value::GetTypeName(base::Value::Type::BOOLEAN)); return false; } @@ -265,28 +314,24 @@ ProxyPrefs::ProxyMode mode; if (!ProxyPrefs::StringToProxyMode(*mode_value, &mode)) { - errors->AddError(key::kProxySettings, - key::kProxyMode, + errors->AddError(kProxySettings, kProxyMode, IDS_POLICY_INVALID_PROXY_MODE_ERROR); return false; } if (mode == ProxyPrefs::MODE_PAC_SCRIPT && !pac_url) { - errors->AddError(key::kProxySettings, - key::kProxyPacUrl, + errors->AddError(kProxySettings, kProxyPacUrl, IDS_POLICY_NOT_SPECIFIED_ERROR); return false; } if (mode == ProxyPrefs::MODE_FIXED_SERVERS && !server) { - errors->AddError(key::kProxySettings, - key::kProxyServer, + errors->AddError(kProxySettings, kProxyServer, IDS_POLICY_NOT_SPECIFIED_ERROR); return false; } } else if (server_mode) { if (!server_mode->is_int()) { - errors->AddError(key::kProxySettings, key::kProxyServerMode, - IDS_POLICY_TYPE_ERROR, + errors->AddError(kProxySettings, kProxyServerMode, IDS_POLICY_TYPE_ERROR, base::Value::GetTypeName(base::Value::Type::INTEGER)); return false; } @@ -301,22 +346,14 @@ case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE: if (server && pac_url) { int message_id = IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR; - errors->AddError(key::kProxySettings, - key::kProxyServer, - message_id); - errors->AddError(key::kProxySettings, - key::kProxyPacUrl, - message_id); + errors->AddError(kProxySettings, kProxyServer, message_id); + errors->AddError(kProxySettings, kProxyPacUrl, message_id); return false; } if (!server && !pac_url) { int message_id = IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR; - errors->AddError(key::kProxySettings, - key::kProxyServer, - message_id); - errors->AddError(key::kProxySettings, - key::kProxyPacUrl, - message_id); + errors->AddError(kProxySettings, kProxyServer, message_id); + errors->AddError(kProxySettings, kProxyPacUrl, message_id); return false; } *mode_value = pac_url ? ProxyPrefs::kPacScriptProxyModeName @@ -326,7 +363,7 @@ *mode_value = ProxyPrefs::kSystemProxyModeName; break; default: - errors->AddError(key::kProxySettings, key::kProxyServerMode, + errors->AddError(kProxySettings, kProxyServerMode, IDS_POLICY_OUT_OF_RANGE_ERROR, base::NumberToString(server_mode->GetInt())); return false; @@ -335,4 +372,4 @@ return true; } -} // namespace policy +} // namespace proxy_config
diff --git a/components/policy/core/browser/proxy_policy_handler.h b/components/proxy_config/proxy_policy_handler.h similarity index 67% rename from components/policy/core/browser/proxy_policy_handler.h rename to components/proxy_config/proxy_policy_handler.h index 90749a0..c8ca2b0e 100644 --- a/components/policy/core/browser/proxy_policy_handler.h +++ b/components/proxy_config/proxy_policy_handler.h
@@ -2,17 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_POLICY_CORE_BROWSER_PROXY_POLICY_HANDLER_H_ -#define COMPONENTS_POLICY_CORE_BROWSER_PROXY_POLICY_HANDLER_H_ +#ifndef COMPONENTS_PROXY_CONFIG_PROXY_POLICY_HANDLER_H_ +#define COMPONENTS_PROXY_CONFIG_PROXY_POLICY_HANDLER_H_ #include <string> #include "components/policy/core/browser/configuration_policy_handler.h" +#include "components/proxy_config/proxy_config_export.h" -namespace policy { +namespace proxy_config { // ConfigurationPolicyHandler for the proxy policies. -class POLICY_EXPORT ProxyPolicyHandler : public ConfigurationPolicyHandler { +class PROXY_CONFIG_EXPORT ProxyPolicyHandler + : public policy::ConfigurationPolicyHandler { public: // Constants for the "Proxy Server Mode" defined in the policies. // Note that these diverge from internal presentation defined in @@ -38,23 +40,23 @@ ~ProxyPolicyHandler() override; // ConfigurationPolicyHandler methods: - bool CheckPolicySettings(const PolicyMap& policies, - PolicyErrorMap* errors) override; - void ApplyPolicySettings(const PolicyMap& policies, + bool CheckPolicySettings(const policy::PolicyMap& policies, + policy::PolicyErrorMap* errors) override; + void ApplyPolicySettings(const policy::PolicyMap& policies, PrefValueMap* prefs) override; private: - const base::Value* GetProxyPolicyValue(const PolicyMap& policies, + const base::Value* GetProxyPolicyValue(const base::Value* value, const char* policy_name); // Converts the deprecated ProxyServerMode policy value to a ProxyMode value // and places the result in |mode_value|. Returns whether the conversion // succeeded. - bool CheckProxyModeAndServerMode(const PolicyMap& policies, - PolicyErrorMap* errors, + bool CheckProxyModeAndServerMode(const base::Value* proxy_settings, + policy::PolicyErrorMap* errors, std::string* mode_value); }; -} // namespace policy +} // namespace proxy_config -#endif // COMPONENTS_POLICY_CORE_BROWSER_PROXY_POLICY_HANDLER_H_ +#endif // COMPONENTS_PROXY_CONFIG_PROXY_POLICY_HANDLER_H_
diff --git a/components/policy/core/browser/proxy_policy_handler_unittest.cc b/components/proxy_config/proxy_policy_handler_unittest.cc similarity index 67% rename from components/policy/core/browser/proxy_policy_handler_unittest.cc rename to components/proxy_config/proxy_policy_handler_unittest.cc index d544dd1..4c8b0dd0 100644 --- a/components/policy/core/browser/proxy_policy_handler_unittest.cc +++ b/components/proxy_config/proxy_policy_handler_unittest.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 "components/policy/core/browser/proxy_policy_handler.h" +#include "components/proxy_config/proxy_policy_handler.h" #include <memory> #include <string> @@ -20,11 +20,27 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" -namespace policy { +using policy::ConfigurationPolicyHandler; +using policy::ConfigurationPolicyPrefStore; +using policy::ConfigurationPolicyPrefStoreTest; +using policy::kProxyPacMandatory; +using policy::POLICY_LEVEL_MANDATORY; +using policy::POLICY_LEVEL_RECOMMENDED; +using policy::POLICY_SCOPE_USER; +using policy::POLICY_SOURCE_CLOUD; +using policy::PolicyMap; +using policy::PolicyServiceImpl; +using policy::key::kProxyBypassList; +using policy::key::kProxyMode; +using policy::key::kProxyPacUrl; +using policy::key::kProxyServer; +using policy::key::kProxyServerMode; +using policy::key::kProxySettings; + +namespace proxy_config { // Test cases for the proxy policy settings. -class ProxyPolicyHandlerTest - : public ConfigurationPolicyPrefStoreTest { +class ProxyPolicyHandlerTest : public ConfigurationPolicyPrefStoreTest { public: void SetUp() override { ConfigurationPolicyPrefStoreTest::SetUp(); @@ -84,13 +100,13 @@ TEST_F(ProxyPolicyHandlerTest, ManualOptions) { PolicyMap policy; - policy.Set(key::kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("http://chromium.org/override"), nullptr); - policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("chromium.org"), nullptr); policy.Set( - key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value( ProxyPolicyHandler::PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE), @@ -105,15 +121,15 @@ TEST_F(ProxyPolicyHandlerTest, ManualOptionsReversedApplyOrder) { PolicyMap policy; policy.Set( - key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value( ProxyPolicyHandler::PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE), nullptr); - policy.Set(key::kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("http://chromium.org/override"), nullptr); - policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("chromium.org"), nullptr); UpdateProviderPolicy(policy); @@ -125,7 +141,7 @@ TEST_F(ProxyPolicyHandlerTest, ManualOptionsInvalid) { PolicyMap policy; policy.Set( - key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value( ProxyPolicyHandler::PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE), @@ -138,7 +154,7 @@ TEST_F(ProxyPolicyHandlerTest, NoProxyServerMode) { PolicyMap policy; - policy.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPolicyHandler::PROXY_SERVER_MODE), nullptr); UpdateProviderPolicy(policy); @@ -148,7 +164,7 @@ TEST_F(ProxyPolicyHandlerTest, NoProxyModeName) { PolicyMap policy; - policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPrefs::kDirectProxyModeName), nullptr); UpdateProviderPolicy(policy); @@ -159,7 +175,7 @@ TEST_F(ProxyPolicyHandlerTest, AutoDetectProxyServerMode) { PolicyMap policy; policy.Set( - key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPolicyHandler::PROXY_AUTO_DETECT_PROXY_SERVER_MODE), nullptr); @@ -170,7 +186,7 @@ TEST_F(ProxyPolicyHandlerTest, AutoDetectProxyModeName) { PolicyMap policy; - policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPrefs::kAutoDetectProxyModeName), nullptr); UpdateProviderPolicy(policy); @@ -180,22 +196,37 @@ TEST_F(ProxyPolicyHandlerTest, PacScriptProxyMode) { PolicyMap policy; - policy.Set(key::kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("http://short.org/proxy.pac"), nullptr); - policy.Set(kProxyPacMandatory, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - POLICY_SOURCE_CLOUD, base::Value(true), nullptr); - policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPrefs::kPacScriptProxyModeName), nullptr); UpdateProviderPolicy(policy); - VerifyProxyPrefs(std::string(), "http://short.org/proxy.pac", true, - std::string(), ProxyPrefs::MODE_PAC_SCRIPT); + VerifyProxyPrefs(std::string(), "http://short.org/proxy.pac", + /* expected_proxy_pac_mandatory */ false, std::string(), + ProxyPrefs::MODE_PAC_SCRIPT); +} + +// ProxyPacMandatory can be set only via ProxySettings. +TEST_F(ProxyPolicyHandlerTest, PacScriptProxyModeWithPacMandatory) { + base::Value proxy_settings(base::Value::Type::DICTIONARY); + proxy_settings.SetStringKey(kProxyPacUrl, "http://short.org/proxy.pac"); + proxy_settings.SetStringKey(kProxyMode, ProxyPrefs::kPacScriptProxyModeName); + proxy_settings.SetBoolKey(kProxyPacMandatory, true); + + PolicyMap policy; + policy.Set(kProxySettings, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + POLICY_SOURCE_CLOUD, std::move(proxy_settings), nullptr); + UpdateProviderPolicy(policy); + VerifyProxyPrefs(std::string(), "http://short.org/proxy.pac", + /* expected_proxy_pac_mandatory */ true, std::string(), + ProxyPrefs::MODE_PAC_SCRIPT); } TEST_F(ProxyPolicyHandlerTest, PacScriptProxyModeInvalid) { PolicyMap policy; - policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPrefs::kPacScriptProxyModeName), nullptr); UpdateProviderPolicy(policy); @@ -207,12 +238,12 @@ // empty strings for unset properties. TEST_F(ProxyPolicyHandlerTest, PacScriptProxyModeBug78016) { PolicyMap policy; - policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(std::string()), nullptr); - policy.Set(key::kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("http://short.org/proxy.pac"), nullptr); - policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPrefs::kPacScriptProxyModeName), nullptr); UpdateProviderPolicy(policy); @@ -223,7 +254,7 @@ TEST_F(ProxyPolicyHandlerTest, UseSystemProxyServerMode) { PolicyMap policy; policy.Set( - key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPolicyHandler::PROXY_USE_SYSTEM_PROXY_SERVER_MODE), nullptr); @@ -234,7 +265,7 @@ TEST_F(ProxyPolicyHandlerTest, UseSystemProxyMode) { PolicyMap policy; - policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPrefs::kSystemProxyModeName), nullptr); UpdateProviderPolicy(policy); @@ -242,13 +273,12 @@ ProxyPrefs::MODE_SYSTEM); } -TEST_F(ProxyPolicyHandlerTest, - ProxyModeOverridesProxyServerMode) { +TEST_F(ProxyPolicyHandlerTest, ProxyModeOverridesProxyServerMode) { PolicyMap policy; - policy.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPolicyHandler::PROXY_SERVER_MODE), nullptr); - policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(ProxyPrefs::kAutoDetectProxyModeName), nullptr); UpdateProviderPolicy(policy); @@ -259,16 +289,16 @@ TEST_F(ProxyPolicyHandlerTest, ProxyInvalid) { // No mode expects all three parameters being set. PolicyMap policy; - policy.Set(key::kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("http://short.org/proxy.pac"), nullptr); - policy.Set(key::kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("http://chromium.org/override"), nullptr); - policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value("chromium.org"), nullptr); for (int i = 0; i < ProxyPolicyHandler::MODE_COUNT; ++i) { - policy.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + policy.Set(kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(i), nullptr); UpdateProviderPolicy(policy); const base::Value* value = nullptr; @@ -276,4 +306,25 @@ } } -} // namespace policy +TEST_F(ProxyPolicyHandlerTest, SeparateProxyPoliciesMerging) { + PolicyMap policy; + // Individual proxy policy values should be collected into a dictionary. + policy.Set( + kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, + POLICY_SOURCE_CLOUD, + base::Value(ProxyPolicyHandler::PROXY_USE_SYSTEM_PROXY_SERVER_MODE), + nullptr); + // Both these policies should be ignored, since there's a higher priority + // policy available. + policy.Set(kProxyMode, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, + POLICY_SOURCE_CLOUD, base::Value("pac_script"), nullptr); + policy.Set(kProxyPacUrl, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, + POLICY_SOURCE_CLOUD, base::Value("http://example.com/wpad.dat"), + nullptr); + + UpdateProviderPolicy(policy); + VerifyProxyPrefs(std::string(), std::string(), absl::nullopt, std::string(), + ProxyPrefs::MODE_SYSTEM); +} + +} // namespace proxy_config
diff --git a/components/safe_browsing/core/common/features_unittest.cc b/components/safe_browsing/core/common/features_unittest.cc index 3fa3ee8..4d9d973 100644 --- a/components/safe_browsing/core/common/features_unittest.cc +++ b/components/safe_browsing/core/common/features_unittest.cc
@@ -4,6 +4,7 @@ #include "components/safe_browsing/core/common/features.h" +#include "base/strings/string_number_conversions.h" #include "base/system/sys_info.h" #include "base/test/scoped_feature_list.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc index a443f5c..ff0c6ff 100644 --- a/components/search/ntp_features.cc +++ b/components/search/ntp_features.cc
@@ -123,6 +123,7 @@ "NtpChromeCartModuleAbandonedCartDiscountUseUtmParam"; const char kNtpChromeCartModuleHeuristicsImprovementParam[] = "NtpChromeCartModuleHeuristicsImprovementParam"; +const char kNtpChromeCartModuleCouponParam[] = "NtpChromeCartModuleCouponParam"; const char kNtpDriveModuleDataParam[] = "NtpDriveModuleDataParam"; const char kNtpDriveModuleManagedUsersOnlyParam[] = "NtpDriveModuleManagedUsersOnlyParam";
diff --git a/components/search/ntp_features.h b/components/search/ntp_features.h index cd60b6d..f0d0f5c 100644 --- a/components/search/ntp_features.h +++ b/components/search/ntp_features.h
@@ -62,6 +62,8 @@ extern const char NtpChromeCartModuleAbandonedCartDiscountUseUtmParam[]; // Parameter for enabling the cart heuristics improvement. extern const char kNtpChromeCartModuleHeuristicsImprovementParam[]; +// Parameter for enabling coupons on the Cart module. +extern const char kNtpChromeCartModuleCouponParam[]; // Parameter determining the type of Drive data to render. extern const char kNtpDriveModuleDataParam[]; // Parameter for enabling the Drive module for managed users only.
diff --git a/components/segmentation_platform/internal/signals/histogram_signal_handler.cc b/components/segmentation_platform/internal/signals/histogram_signal_handler.cc index f5d570f..933794c 100644 --- a/components/segmentation_platform/internal/signals/histogram_signal_handler.cc +++ b/components/segmentation_platform/internal/signals/histogram_signal_handler.cc
@@ -4,6 +4,7 @@ #include "components/segmentation_platform/internal/signals/histogram_signal_handler.h" +#include "base/callback_helpers.h" #include "base/metrics/metrics_hashes.h" #include "components/segmentation_platform/internal/database/signal_database.h"
diff --git a/components/services/storage/BUILD.gn b/components/services/storage/BUILD.gn index 3882cbec..007edf0 100644 --- a/components/services/storage/BUILD.gn +++ b/components/services/storage/BUILD.gn
@@ -215,6 +215,5 @@ "//base", "//mojo/public/cpp/bindings", "//testing/gmock", - "//third_party/blink/public/mojom/dom_storage", ] }
diff --git a/components/session_manager/core/session_manager.cc b/components/session_manager/core/session_manager.cc index 8d7eff9a..b3245b6 100644 --- a/components/session_manager/core/session_manager.cc +++ b/components/session_manager/core/session_manager.cc
@@ -107,6 +107,11 @@ observer.OnUserProfileLoaded(account_id); } +void SessionManager::NotifyNetworkErrorScreenShown() { + for (auto& observer : observers_) + observer.OnNetworkErrorScreenShown(); +} + void SessionManager::NotifyUserLoggedIn(const AccountId& user_account_id, const std::string& user_id_hash, bool browser_restart,
diff --git a/components/session_manager/core/session_manager.h b/components/session_manager/core/session_manager.h index 27a7bfad..985a876e 100644 --- a/components/session_manager/core/session_manager.h +++ b/components/session_manager/core/session_manager.h
@@ -64,6 +64,7 @@ // Various helpers to notify observers. void NotifyUserProfileLoaded(const AccountId& account_id); + void NotifyNetworkErrorScreenShown(); SessionState session_state() const { return session_state_; } const std::vector<Session>& sessions() const { return sessions_; }
diff --git a/components/session_manager/core/session_manager_observer.h b/components/session_manager/core/session_manager_observer.h index a7516f2..8c9fe08 100644 --- a/components/session_manager/core/session_manager_observer.h +++ b/components/session_manager/core/session_manager_observer.h
@@ -28,6 +28,10 @@ // UserSessionStateObserver::OnActiveUserChanged() is invoked immediately // after the user has logged in. virtual void OnUserSessionStarted(bool is_primary_user) {} + + // Invoked when a network error message is displayed on the WebUI login + // screen. + virtual void OnNetworkErrorScreenShown() {} }; } // namespace session_manager
diff --git a/components/signin/internal/identity_manager/BUILD.gn b/components/signin/internal/identity_manager/BUILD.gn index e04392e9..18e582e 100644 --- a/components/signin/internal/identity_manager/BUILD.gn +++ b/components/signin/internal/identity_manager/BUILD.gn
@@ -98,6 +98,7 @@ } if (is_chromeos_ash) { + deps += [ "//ash/constants" ] public_deps += [ "//ash/components/account_manager" ] } else { sources += [ @@ -183,7 +184,10 @@ if (is_chromeos_ash) { sources += [ "profile_oauth2_token_service_delegate_chromeos_unittest.cc" ] - deps += [ "//ash/components/account_manager" ] + deps += [ + "//ash/components/account_manager", + "//ash/constants", + ] } else { sources += [ "primary_account_policy_manager_impl_unittest.cc" ] }
diff --git a/components/signin/internal/identity_manager/DEPS b/components/signin/internal/identity_manager/DEPS index ab4e4b1..dff6bbc 100644 --- a/components/signin/internal/identity_manager/DEPS +++ b/components/signin/internal/identity_manager/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+ash/constants", "+components/signin/internal/base", "+components/signin/public/base", "+components/signin/public/identity_manager",
diff --git a/components/signin/internal/identity_manager/account_fetcher_service.cc b/components/signin/internal/identity_manager/account_fetcher_service.cc index dd9261f..390383a 100644 --- a/components/signin/internal/identity_manager/account_fetcher_service.cc +++ b/components/signin/internal/identity_manager/account_fetcher_service.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/command_line.h" -#include "base/feature_list.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_functions.h" #include "base/trace_event/trace_event.h" @@ -32,6 +31,10 @@ #include "net/http/http_status_code.h" #include "services/network/public/cpp/shared_url_loader_factory.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_features.h" +#endif + #if defined(OS_ANDROID) #include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h" #include "components/signin/public/identity_manager/tribool.h" @@ -238,7 +241,7 @@ return true; #if BUILDFLAG(IS_CHROMEOS_ASH) - return base::FeatureList::IsEnabled(switches::kMinorModeSupport); + return ash::features::IsMinorModeRestrictionEnabled(); #else return false; #endif
diff --git a/components/signin/internal/identity_manager/account_tracker_service_unittest.cc b/components/signin/internal/identity_manager/account_tracker_service_unittest.cc index 4a203fa..c5e7f17 100644 --- a/components/signin/internal/identity_manager/account_tracker_service_unittest.cc +++ b/components/signin/internal/identity_manager/account_tracker_service_unittest.cc
@@ -41,6 +41,10 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_features.h" +#endif + #if defined(OS_ANDROID) #include "components/signin/public/identity_manager/identity_test_utils.h" #endif @@ -705,7 +709,8 @@ TokenAvailable_AccountCapabilitiesFetcherDisabled) { #if BUILDFLAG(IS_CHROMEOS_ASH) base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature(switches::kMinorModeSupport); + scoped_feature_list.InitAndDisableFeature( + ash::features::kMinorModeRestriction); #endif account_fetcher()->EnableAccountCapabilitiesFetcherForTest(false);
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc index 016f849..75854e7 100644 --- a/components/signin/public/base/signin_switches.cc +++ b/components/signin/public/base/signin_switches.cc
@@ -37,8 +37,10 @@ base::FEATURE_DISABLED_BY_DEFAULT}; #endif +#if !BUILDFLAG(IS_CHROMEOS_ASH) const base::Feature kMinorModeSupport{"MinorModeSupport", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif const base::Feature kForceDisableExtendedSyncPromos{ "ForceDisableExtendedSyncPromos", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/signin/public/base/signin_switches.h b/components/signin/public/base/signin_switches.h index fc346a63..ea3b3ee 100644 --- a/components/signin/public/base/signin_switches.h +++ b/components/signin/public/base/signin_switches.h
@@ -38,8 +38,10 @@ extern const base::Feature kForceStartupSigninPromo; #endif +#if !BUILDFLAG(IS_CHROMEOS_ASH) // Support for the minor mode. extern const base::Feature kMinorModeSupport; +#endif // This feature disables all extended sync promos. extern const base::Feature kForceDisableExtendedSyncPromos;
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc b/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc index 6868f90..6baf476b 100644 --- a/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc +++ b/components/sync/trusted_vault/standalone_trusted_vault_backend_unittest.cc
@@ -9,6 +9,7 @@ #include <utility> #include <vector> +#include "base/callback_helpers.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/test/bind.h"
diff --git a/components/tracing/common/graphics_memory_dump_provider_android.cc b/components/tracing/common/graphics_memory_dump_provider_android.cc index bf0c58f4..4249d18 100644 --- a/components/tracing/common/graphics_memory_dump_provider_android.cc +++ b/components/tracing/common/graphics_memory_dump_provider_android.cc
@@ -11,6 +11,7 @@ #include <sys/time.h> #include <sys/types.h> #include <sys/un.h> +#include <unistd.h> #include "base/files/scoped_file.h" #include "base/logging.h"
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc index f5f8eaa..a86a2f0 100644 --- a/components/translate/core/browser/translate_manager.cc +++ b/components/translate/core/browser/translate_manager.cc
@@ -278,7 +278,14 @@ } const std::string source_language = language_state_.source_language(); - + if (source_language.empty()) { + if (!menuLogging) + return false; + TranslateBrowserMetrics::ReportMenuTranslationUnavailableReason( + TranslateBrowserMetrics::MenuTranslationUnavailableReason:: + kSourceLangUnknown); + can_translate = false; + } // Translation of unknown source language pages is supported on Desktop // platforms, experimentally supported on Android and not supported on iOS. bool unknown_source_supported = true; @@ -289,8 +296,7 @@ unknown_source_supported = false; #endif if (!unknown_source_supported && - (source_language == translate::kUnknownLanguageCode || - source_language.empty())) { + source_language == translate::kUnknownLanguageCode) { if (!menuLogging) return false; TranslateBrowserMetrics::ReportMenuTranslationUnavailableReason(
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc index 89fbff8..ee6a19b 100644 --- a/components/translate/core/browser/translate_manager_unittest.cc +++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -1101,19 +1101,8 @@ translate_manager_->GetLanguageState()->LanguageDetermined("", true); - // Translation before language detection is complete is not supported on iOS. - // Experiment in place for supporting it on Android. - bool unknown_source_supported = true; -#if defined(OS_ANDROID) - if (!base::FeatureList::IsEnabled(language::kDetectedSourceLanguageOption)) - unknown_source_supported = false; -#elif defined(OS_IOS) - unknown_source_supported = false; -#endif - EXPECT_EQ(translate_manager_->CanManuallyTranslate(), - unknown_source_supported); - EXPECT_EQ(translate_manager_->CanManuallyTranslate(true), - unknown_source_supported); + EXPECT_FALSE(translate_manager_->CanManuallyTranslate()); + EXPECT_FALSE(translate_manager_->CanManuallyTranslate(true)); } TEST_F(TranslateManagerTest, CanManuallyTranslate_UndefinedSourceLanguage) { @@ -1140,8 +1129,6 @@ #endif EXPECT_EQ(translate_manager_->CanManuallyTranslate(), unknown_source_supported); - EXPECT_EQ(translate_manager_->CanManuallyTranslate(true), - unknown_source_supported); } TEST_F(TranslateManagerTest, PredefinedTargetLanguage) {
diff --git a/components/viz/client/DEPS b/components/viz/client/DEPS index ee810d9..509fd138 100644 --- a/components/viz/client/DEPS +++ b/components/viz/client/DEPS
@@ -1,7 +1,6 @@ # Please consult components/viz/README.md about allowable dependencies. include_rules = [ - "-components/viz/common/switches.h", "+components/viz/client", "+gpu/GLES2/gl2extchromium.h", "+gpu/command_buffer/client",
diff --git a/components/viz/common/switches.cc b/components/viz/common/switches.cc index 0b28190..14db420 100644 --- a/components/viz/common/switches.cc +++ b/components/viz/common/switches.cc
@@ -5,6 +5,7 @@ #include "components/viz/common/switches.h" #include "base/command_line.h" +#include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "build/chromeos_buildflags.h" #include "components/viz/common/constants.h" @@ -24,6 +25,10 @@ // Also implies --disable-gpu-vsync (see //ui/gl/gl_switches.h). const char kDisableFrameRateLimit[] = "disable-frame-rate-limit"; +// Slows down animations during a DocumentTransition for debugging. +const char kDocumentTransitionSlowdownFactor[] = + "document-transition-slowdown-factor"; + // Sets the number of max pending frames in the GL buffer queue to 1. const char kDoubleBufferCompositing[] = "double-buffer-compositing"; @@ -89,4 +94,17 @@ return activation_deadline_in_frames; } +int GetDocumentTransitionSlowDownFactor() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(kDocumentTransitionSlowdownFactor)) + return 1; + + auto factor_str = + command_line->GetSwitchValueASCII(kDocumentTransitionSlowdownFactor); + int factor = 0; + LOG_IF(ERROR, !base::StringToInt(factor_str, &factor)) + << "Error parsing document transition slow down factor " << factor_str; + return std::max(1, factor); +} + } // namespace switches
diff --git a/components/viz/common/switches.h b/components/viz/common/switches.h index 9ed30ac6..64490ee 100644 --- a/components/viz/common/switches.h +++ b/components/viz/common/switches.h
@@ -17,6 +17,7 @@ VIZ_COMMON_EXPORT extern const char kDeJellyScreenWidth[]; VIZ_COMMON_EXPORT extern const char kDeadlineToSynchronizeSurfaces[]; VIZ_COMMON_EXPORT extern const char kDisableFrameRateLimit[]; +VIZ_COMMON_EXPORT extern const char kDocumentTransitionSlowdownFactor[]; VIZ_COMMON_EXPORT extern const char kDoubleBufferCompositing[]; VIZ_COMMON_EXPORT extern const char kEnableDeJelly[]; VIZ_COMMON_EXPORT extern const char kEnableHardwareOverlays[]; @@ -39,6 +40,7 @@ VIZ_COMMON_EXPORT extern const char kShowDCLayerDebugBorders[]; VIZ_COMMON_EXPORT absl::optional<uint32_t> GetDeadlineToSynchronizeSurfaces(); +VIZ_COMMON_EXPORT int GetDocumentTransitionSlowDownFactor(); } // namespace switches
diff --git a/components/viz/host/DEPS b/components/viz/host/DEPS index 5beac85..17d1490 100644 --- a/components/viz/host/DEPS +++ b/components/viz/host/DEPS
@@ -2,7 +2,6 @@ include_rules = [ "+components/discardable_memory/public/mojom", - "-components/viz/common/switches.h", "+media/base/video_types.h", "+gpu/command_buffer/client", "+gpu/command_buffer/common",
diff --git a/components/viz/service/DEPS b/components/viz/service/DEPS index 72b1bd39..53f869e 100644 --- a/components/viz/service/DEPS +++ b/components/viz/service/DEPS
@@ -3,7 +3,6 @@ include_rules = [ "+cc", "+components/power_scheduler", - "-components/viz/common/switches.h", "-components/viz/service", "+components/viz/service/debugger/viz_debugger.h", "+components/viz/service/gl/gpu_service_impl.h",
diff --git a/components/viz/service/transitions/surface_animation_manager.cc b/components/viz/service/transitions/surface_animation_manager.cc index 187824f..d3577243 100644 --- a/components/viz/service/transitions/surface_animation_manager.cc +++ b/components/viz/service/transitions/surface_animation_manager.cc
@@ -20,6 +20,7 @@ #include "components/viz/common/resources/resource_id.h" #include "components/viz/common/resources/returned_resource.h" #include "components/viz/common/resources/transferable_resource.h" +#include "components/viz/common/switches.h" #include "components/viz/common/transition_utils.h" #include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_saved_frame_storage.h" @@ -39,16 +40,14 @@ namespace viz { namespace { -constexpr int kAnimationSlowDownFactor = 1; - constexpr base::TimeDelta kDefaultAnimationDuration = - base::TimeDelta::FromMilliseconds(250) * kAnimationSlowDownFactor; + base::TimeDelta::FromMilliseconds(250); constexpr base::TimeDelta kSharedOpacityAnimationDuration = - base::TimeDelta::FromMilliseconds(60) * kAnimationSlowDownFactor; + base::TimeDelta::FromMilliseconds(60); constexpr base::TimeDelta kSharedOpacityAnimationDelay = - base::TimeDelta::FromMilliseconds(60) * kAnimationSlowDownFactor; + base::TimeDelta::FromMilliseconds(60); // Scale the overall duration to produce the opacity duration. Opacity // transitions which reveal an element (i.e., transition opacity from 0 -> 1) @@ -141,45 +140,49 @@ std::unique_ptr<gfx::AnimationCurve> CreateOpacityCurve( float start_opacity, float end_opacity, + base::TimeDelta opacity_duration, + base::TimeDelta opacity_delay, + base::TimeDelta total_duration, gfx::FloatAnimationCurve::Target* target) { auto float_curve = gfx::KeyframedFloatAnimationCurve::Create(); // The curve starts at opacity delay and runs for opacity animation, so it // potentially has 4 points: // time 0 == start opacity - // time 'delay' == start opacity - // time 'delay' + 'duration' == end opacity - // time end of animation == end opacity + // time 'opacity_delay' == start opacity + // time 'opacity_delay' + 'opacity_duration' == end opacity + // time 'total_duration' == end opacity float_curve->AddKeyframe( gfx::FloatKeyframe::Create(base::TimeDelta(), start_opacity, nullptr)); - if (!kSharedOpacityAnimationDelay.is_zero()) { - float_curve->AddKeyframe(gfx::FloatKeyframe::Create( - kSharedOpacityAnimationDelay, start_opacity, nullptr)); + if (!opacity_delay.is_zero()) { + float_curve->AddKeyframe( + gfx::FloatKeyframe::Create(opacity_delay, start_opacity, nullptr)); } float_curve->AddKeyframe(gfx::FloatKeyframe::Create( - kSharedOpacityAnimationDuration + kSharedOpacityAnimationDelay, - end_opacity, nullptr)); - float_curve->AddKeyframe(gfx::FloatKeyframe::Create(kDefaultAnimationDuration, - end_opacity, nullptr)); + opacity_duration + opacity_delay, end_opacity, nullptr)); + float_curve->AddKeyframe( + gfx::FloatKeyframe::Create(total_duration, end_opacity, nullptr)); float_curve->set_target(target); return float_curve; } std::unique_ptr<gfx::AnimationCurve> CreateSizeCurve( const gfx::SizeF& start_size, + base::TimeDelta duration, std::unique_ptr<gfx::TimingFunction> timing_function, gfx::SizeAnimationCurve::Target* target) { auto size_curve = gfx::KeyframedSizeAnimationCurve::Create(); size_curve->AddKeyframe(gfx::SizeKeyframe::Create( base::TimeDelta(), start_size, timing_function->Clone())); size_curve->AddKeyframe(gfx::SizeKeyframe::Create( - kDefaultAnimationDuration, start_size, std::move(timing_function))); + duration, start_size, std::move(timing_function))); size_curve->set_target(target); return size_curve; } std::unique_ptr<gfx::AnimationCurve> CreateTransformCurve( const gfx::Transform& transform, + base::TimeDelta duration, std::unique_ptr<gfx::TimingFunction> timing_function, gfx::TransformAnimationCurve::Target* target) { gfx::TransformOperations transform_ops; @@ -189,7 +192,7 @@ transform_curve->AddKeyframe(gfx::TransformKeyframe::Create( base::TimeDelta(), transform_ops, timing_function->Clone())); transform_curve->AddKeyframe(gfx::TransformKeyframe::Create( - kDefaultAnimationDuration, transform_ops, std::move(timing_function))); + duration, transform_ops, std::move(timing_function))); transform_curve->set_target(target); return transform_curve; } @@ -198,7 +201,9 @@ SurfaceAnimationManager::SurfaceAnimationManager( SharedBitmapManager* shared_bitmap_manager) - : transferable_resource_tracker_(shared_bitmap_manager) {} + : animation_slowdown_factor_( + switches::GetDocumentTransitionSlowDownFactor()), + transferable_resource_tracker_(shared_bitmap_manager) {} SurfaceAnimationManager::~SurfaceAnimationManager() = default; @@ -855,7 +860,8 @@ : gfx::CubicBezierTimingFunction::EaseType::EASE_OUT); // Create the transform curve. - base::TimeDelta transform_duration = kDefaultAnimationDuration; + base::TimeDelta transform_duration = + ApplySlowdownFactor(kDefaultAnimationDuration); std::unique_ptr<gfx::KeyframedTransformAnimationCurve> transform_curve( gfx::KeyframedTransformAnimationCurve::Create()); @@ -912,6 +918,11 @@ shared_animations_.resize( animate_directive_->shared_render_pass_ids().size()); + const auto opacity_duration = + ApplySlowdownFactor(kSharedOpacityAnimationDuration); + const auto opacity_delay = ApplySlowdownFactor(kSharedOpacityAnimationDelay); + const auto total_duration = ApplySlowdownFactor(kDefaultAnimationDuration); + // Since we don't have a target state yet, create animations as if all of the // shared elements are targeted to stay in place with opacity going to 0. for (size_t i = 0; i < saved_textures_->shared.size(); ++i) { @@ -928,7 +939,9 @@ // element to gradually fade out. // The animation is re-targeted once the dest element values are known. float start_opacity = has_src_element ? shared->draw_data.opacity : 0.f; - auto opacity_curve = CreateOpacityCurve(start_opacity, 1.f, &state); + auto opacity_curve = + CreateOpacityCurve(start_opacity, 1.f, opacity_duration, opacity_delay, + total_duration, &state); state.driver().AddKeyframeModel(gfx::KeyframeModel::Create( std::move(opacity_curve), gfx::KeyframeEffect::GetNextKeyframeModelId(), SharedAnimationState::kCombinedOpacity)); @@ -943,14 +956,16 @@ // Interpolation between the 2 textures involves an opacity animation (to // cross-fade the content) and a scale animation to transition the content // size. - auto content_size_curve = CreateSizeCurve( - gfx::SizeF(shared->draw_data.size), ease_timing->Clone(), &state); + auto content_size_curve = + CreateSizeCurve(gfx::SizeF(shared->draw_data.size), total_duration, + ease_timing->Clone(), &state); state.driver().AddKeyframeModel(gfx::KeyframeModel::Create( std::move(content_size_curve), gfx::KeyframeEffect::GetNextKeyframeModelId(), SharedAnimationState::kContentSize)); - auto content_opacity_curve = - CreateOpacityCurve(/*start_opacity=*/0.f, /*end_opacity=*/1.f, &state); + auto content_opacity_curve = CreateOpacityCurve( + /*start_opacity=*/0.f, /*end_opacity=*/1.f, opacity_duration, + opacity_delay, total_duration, &state); state.driver().AddKeyframeModel(gfx::KeyframeModel::Create( std::move(content_opacity_curve), gfx::KeyframeEffect::GetNextKeyframeModelId(), @@ -959,8 +974,9 @@ // The screen space transform for the interpolated texture is animated from // src element to dest element value. The animation is re-targeted once the // dest element values are known. - auto transform_curve = CreateTransformCurve( - shared->draw_data.target_transform, ease_timing->Clone(), &state); + auto transform_curve = + CreateTransformCurve(shared->draw_data.target_transform, total_duration, + ease_timing->Clone(), &state); state.driver().AddKeyframeModel(gfx::KeyframeModel::Create( std::move(transform_curve), gfx::KeyframeEffect::GetNextKeyframeModelId(), @@ -968,6 +984,11 @@ } } +base::TimeDelta SurfaceAnimationManager::ApplySlowdownFactor( + base::TimeDelta original) const { + return original * animation_slowdown_factor_; +} + // RootAnimationState SurfaceAnimationManager::RootAnimationState::RootAnimationState() = default; SurfaceAnimationManager::RootAnimationState::RootAnimationState(
diff --git a/components/viz/service/transitions/surface_animation_manager.h b/components/viz/service/transitions/surface_animation_manager.h index f5230ae..ef73269a1 100644 --- a/components/viz/service/transitions/surface_animation_manager.h +++ b/components/viz/service/transitions/surface_animation_manager.h
@@ -134,12 +134,15 @@ // Tick both the root and shared animations. void TickAnimations(base::TimeTicks new_time); + base::TimeDelta ApplySlowdownFactor(base::TimeDelta original) const; + enum class State { kIdle, kAnimating, kLastFrame }; TransitionDirectiveCompleteCallback sequence_id_finished_callback_; uint32_t last_processed_sequence_id_ = 0; + const int animation_slowdown_factor_ = 1; TransferableResourceTracker transferable_resource_tracker_; absl::optional<TransferableResourceTracker::ResourceFrame> saved_textures_;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index f4db68a..5aa7e0c 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -212,8 +212,6 @@ "//third_party/blink/public:scaled_resources", "//third_party/blink/public/common", "//third_party/blink/public/common:font_enumeration_table_proto", - "//third_party/blink/public/mojom/dom_storage", - "//third_party/blink/public/mojom/frame", "//third_party/blink/public/strings", "//third_party/boringssl", "//third_party/brotli:dec", @@ -1069,8 +1067,6 @@ "interest_group/interest_group_manager.h", "interest_group/interest_group_storage.cc", "interest_group/interest_group_storage.h", - "interest_group/restricted_interest_group_store_impl.cc", - "interest_group/restricted_interest_group_store_impl.h", "isolated_origin_util.cc", "isolated_origin_util.h", "isolation_context.cc",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_android.cc b/content/browser/accessibility/accessibility_tree_formatter_android.cc index 9d0a6ed..176bbfe 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_android.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -265,8 +265,8 @@ for (unsigned i = 0; i < base::size(BOOL_ATTRIBUTES); i++) { const char* attribute_name = BOOL_ATTRIBUTES[i]; - bool value; - if (dict.GetBoolean(attribute_name, &value) && value) + absl::optional<bool> value = dict.FindBoolPath(attribute_name); + if (value && *value) WriteAttribute(true, attribute_name, &line); } @@ -289,8 +289,8 @@ for (unsigned i = 0; i < base::size(ACTION_ATTRIBUTES); i++) { const char* attribute_name = ACTION_ATTRIBUTES[i]; - bool value; - if (dict.GetBoolean(attribute_name, &value) && value) { + absl::optional<bool> value = dict.FindBoolPath(attribute_name); + if (value && *value) { WriteAttribute(false /* Exclude actions by default */, attribute_name, &line); }
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc index 3e9a1bf..7c6fc9d 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -635,13 +635,9 @@ } // Offscreen and Focused states are not in the state list. - bool offscreen = false; - dict.GetBoolean(STATE_OFFSCREEN, &offscreen); - if (offscreen) + if (dict.FindBoolPath(STATE_OFFSCREEN).value_or(false)) WriteAttribute(false, STATE_OFFSCREEN, &line); - bool focused = false; - dict.GetBoolean(STATE_FOCUSED, &focused); - if (focused) + if (dict.FindBoolPath(STATE_FOCUSED).value_or(false)) WriteAttribute(false, STATE_FOCUSED, &line); if (dict.FindKey("boundsX") && dict.FindKey("boundsY")) { @@ -656,9 +652,7 @@ &line); } - bool ignored = false; - dict.GetBoolean("ignored", &ignored); - if (!ignored) { + if (!dict.FindBoolPath("ignored").value_or(false)) { if (dict.FindKey("pageBoundsX") && dict.FindKey("pageBoundsY")) { WriteAttribute( false, @@ -687,8 +681,7 @@ } } - bool transform; - if (dict.GetBoolean("transform", &transform) && transform) + if (dict.FindBoolPath("transform").value_or(false)) WriteAttribute(false, "transform", &line); for (int attr_index = static_cast<int32_t>(ax::mojom::StringAttribute::kNone); @@ -722,12 +715,12 @@ attr_index <= static_cast<int32_t>(ax::mojom::BoolAttribute::kMaxValue); ++attr_index) { auto attr = static_cast<ax::mojom::BoolAttribute>(attr_index); - bool bool_value; - if (!dict.GetBoolean(ui::ToString(attr), &bool_value)) + absl::optional<bool> bool_value = dict.FindBoolPath(ui::ToString(attr)); + if (!bool_value) continue; WriteAttribute(false, base::StringPrintf("%s=%s", ui::ToString(attr), - bool_value ? "true" : "false"), + *bool_value ? "true" : "false"), &line); }
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index 3933cf02..728abdc 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -288,6 +288,7 @@ case ui::AXEventGenerator::Event::ATOMIC_CHANGED: case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED: case ui::AXEventGenerator::Event::BUSY_CHANGED: + case ui::AXEventGenerator::Event::CARET_BOUNDS_CHANGED: case ui::AXEventGenerator::Event::CHECKED_STATE_DESCRIPTION_CHANGED: case ui::AXEventGenerator::Event::CHILDREN_CHANGED: case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc index 5fb4e974..935559e 100644 --- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc +++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -277,6 +277,7 @@ case ui::AXEventGenerator::Event::ATOMIC_CHANGED: case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED: case ui::AXEventGenerator::Event::BUSY_CHANGED: + case ui::AXEventGenerator::Event::CARET_BOUNDS_CHANGED: case ui::AXEventGenerator::Event::CHECKED_STATE_DESCRIPTION_CHANGED: case ui::AXEventGenerator::Event::CHILDREN_CHANGED: case ui::AXEventGenerator::Event::CONTROLS_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm index 91e7c04..8f70e52 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.mm +++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -368,6 +368,7 @@ case ui::AXEventGenerator::Event::ATOMIC_CHANGED: case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED: case ui::AXEventGenerator::Event::BUSY_CHANGED: + case ui::AXEventGenerator::Event::CARET_BOUNDS_CHANGED: case ui::AXEventGenerator::Event::CHECKED_STATE_DESCRIPTION_CHANGED: case ui::AXEventGenerator::Event::CHILDREN_CHANGED: case ui::AXEventGenerator::Event::CONTROLS_CHANGED:
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc index 4ce35f1..1a5d63f 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -492,6 +492,7 @@ // Currently unused events on this platform. case ui::AXEventGenerator::Event::ATK_TEXT_OBJECT_ATTRIBUTE_CHANGED: case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED: + case ui::AXEventGenerator::Event::CARET_BOUNDS_CHANGED: case ui::AXEventGenerator::Event::CHECKED_STATE_DESCRIPTION_CHANGED: case ui::AXEventGenerator::Event::DETAILS_CHANGED: case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 7170e9d..68e131d 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -25,7 +25,6 @@ #include "content/browser/handwriting/handwriting_recognition_service_factory.h" #include "content/browser/image_capture/image_capture_impl.h" #include "content/browser/interest_group/ad_auction_service_impl.h" -#include "content/browser/interest_group/restricted_interest_group_store_impl.h" #include "content/browser/keyboard_lock/keyboard_lock_service_impl.h" #include "content/browser/loader/content_security_notifier.h" #include "content/browser/media/midi_host.h" @@ -977,8 +976,6 @@ if (base::FeatureList::IsEnabled(blink::features::kFledgeInterestGroups)) { map->Add<blink::mojom::AdAuctionService>( base::BindRepeating(&AdAuctionServiceImpl::CreateMojoService)); - map->Add<blink::mojom::RestrictedInterestGroupStore>(base::BindRepeating( - &RestrictedInterestGroupStoreImpl::CreateMojoService)); } map->Add<blink::mojom::MediaSessionService>( base::BindRepeating(&MediaSessionServiceImpl::Create));
diff --git a/content/browser/conversions/conversion_manager_impl.cc b/content/browser/conversions/conversion_manager_impl.cc index 668861b..ddaa9e3d 100644 --- a/content/browser/conversions/conversion_manager_impl.cc +++ b/content/browser/conversions/conversion_manager_impl.cc
@@ -11,6 +11,7 @@ #include "base/callback_helpers.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_functions.h" #include "base/task/lazy_thread_pool_task_runner.h" #include "base/threading/sequence_bound.h" #include "base/time/default_clock.h" @@ -68,6 +69,10 @@ return info.should_retry && !past_max_allowed_age; } +void RecordCreateReportStatus(ConversionStorage::CreateReportStatus result) { + base::UmaHistogramEnumeration("Conversions.CreateReportStatus", result); +} + } // namespace const constexpr base::TimeDelta kConversionManagerQueueReportsInterval = @@ -172,12 +177,10 @@ } void ConversionManagerImpl::HandleConversion(StorableConversion conversion) { - // TODO(https://crbug.com/1043345): Add UMA for the number of conversions we - // are logging to storage, and the number of new reports logged to storage. conversion_storage_ .AsyncCall(&ConversionStorage::MaybeCreateAndStoreConversionReport) .WithArgs(std::move(conversion)) - .Then(base::DoNothing::Once<bool>()); + .Then(base::BindOnce(&RecordCreateReportStatus)); // If we are running in debug mode, we should also schedule a task to // gather and send any new reports.
diff --git a/content/browser/conversions/conversion_manager_impl_unittest.cc b/content/browser/conversions/conversion_manager_impl_unittest.cc index d779043..9b8e702 100644 --- a/content/browser/conversions/conversion_manager_impl_unittest.cc +++ b/content/browser/conversions/conversion_manager_impl_unittest.cc
@@ -17,6 +17,7 @@ #include "base/run_loop.h" #include "base/sequenced_task_runner.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" #include "base/time/clock.h" #include "base/time/time.h" #include "build/build_config.h" @@ -664,4 +665,13 @@ EXPECT_EQ(3u, test_reporter_->num_reports()); } +TEST_F(ConversionManagerImplTest, HandleConversion_RecordsMetric) { + base::HistogramTester histograms; + conversion_manager_->HandleConversion(DefaultConversion()); + ExpectNumStoredReports(0); + histograms.ExpectUniqueSample( + "Conversions.CreateReportStatus", + ConversionStorage::CreateReportStatus::kNoMatchingImpressions, 1); +} + } // namespace content
diff --git a/content/browser/conversions/conversion_storage.h b/content/browser/conversions/conversion_storage.h index eba4bd8..5caad566 100644 --- a/content/browser/conversions/conversion_storage.h +++ b/content/browser/conversions/conversion_storage.h
@@ -120,12 +120,29 @@ // reporting. Unconverted matching impressions are not modified. virtual void StoreImpression(const StorableImpression& impression) = 0; + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class CreateReportStatus { + kSuccess = 0, + // The report was stored successfully, but it replaced an existing report + // with a lower priority. + kSuccessDroppedLowerPriority = 1, + kInternalError = 2, + kNoCapacityForConversionDestination = 3, + kNoMatchingImpressions = 4, + kDeduplicated = 5, + kRateLimited = 6, + kPriorityTooLow = 7, + kDroppedForNoise = 8, + kMaxValue = kDroppedForNoise, + }; + // Finds all stored impressions matching a given `conversion`, and stores the // new associated conversion report. The delegate will receive a call to // `Delegate::ProcessNewConversionReports()` before the report is added to // storage. Only active impressions will receive new conversions. Returns // whether a new conversion report has been scheduled/added to storage. - virtual bool MaybeCreateAndStoreConversionReport( + virtual CreateReportStatus MaybeCreateAndStoreConversionReport( const StorableConversion& conversion) = 0; // Returns all of the conversion reports that should be sent before
diff --git a/content/browser/conversions/conversion_storage_sql.cc b/content/browser/conversions/conversion_storage_sql.cc index 9739efc..ec5a7e92 100644 --- a/content/browser/conversions/conversion_storage_sql.cc +++ b/content/browser/conversions/conversion_storage_sql.cc
@@ -35,6 +35,8 @@ namespace { +using CreateReportStatus = ::content::ConversionStorage::CreateReportStatus; + const base::FilePath::CharType kInMemoryPath[] = FILE_PATH_LITERAL(":memory"); const base::FilePath::CharType kDatabasePath[] = @@ -440,20 +442,20 @@ kError; } -bool ConversionStorageSql::MaybeCreateAndStoreConversionReport( +CreateReportStatus ConversionStorageSql::MaybeCreateAndStoreConversionReport( const StorableConversion& conversion) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) - return false; + // We don't bother creating the DB here if it doesn't exist, because it's not + // possible for there to be a matching impression if there's no DB. + if (!LazyInit(DbCreationPolicy::kIgnoreIfAbsent)) { + return CreateReportStatus::kNoMatchingImpressions; + } const net::SchemefulSite& conversion_destination = conversion.conversion_destination(); const std::string serialized_conversion_destination = conversion_destination.Serialize(); - if (!HasCapacityForStoringConversion(serialized_conversion_destination)) - return false; - const url::Origin& reporting_origin = conversion.reporting_origin(); DCHECK(!conversion_destination.opaque()); DCHECK(!reporting_origin.opaque()); @@ -480,8 +482,12 @@ matching_impressions_statement.BindTime(2, current_time); // If there are no matching impressions, return early. - if (!matching_impressions_statement.Step()) - return false; + if (!matching_impressions_statement.Step()) { + return matching_impressions_statement.Succeeded() + ? CreateReportStatus::kNoMatchingImpressions + : CreateReportStatus::kInternalError; + } + // The first one returned will be attributed; it has the highest priority. int64_t impression_id_to_attribute = matching_impressions_statement.ColumnInt64(0); @@ -494,17 +500,33 @@ } // Exit early if the last statement wasn't valid. if (!matching_impressions_statement.Succeeded()) - return false; + return CreateReportStatus::kInternalError; - if (IsReportAlreadyStored(impression_id_to_attribute, conversion.dedup_key())) - return false; + switch ( + ReportAlreadyStored(impression_id_to_attribute, conversion.dedup_key())) { + case ReportAlreadyStoredStatus::kNotStored: + break; + case ReportAlreadyStoredStatus::kStored: + return CreateReportStatus::kDeduplicated; + case ReportAlreadyStoredStatus::kError: + return CreateReportStatus::kInternalError; + } + + switch (CapacityForStoringConversion(serialized_conversion_destination)) { + case ConversionCapacityStatus::kHasCapacity: + break; + case ConversionCapacityStatus::kNoCapacity: + return CreateReportStatus::kNoCapacityForConversionDestination; + case ConversionCapacityStatus::kError: + return CreateReportStatus::kInternalError; + } absl::optional<ImpressionToAttribute> impression_to_attribute = ReadImpressionToAttribute(db_.get(), impression_id_to_attribute, reporting_origin); // This is only possible if there is a corrupt DB. if (!impression_to_attribute.has_value()) - return false; + return CreateReportStatus::kInternalError; const uint64_t conversion_data = impression_to_attribute->impression.source_type() == @@ -520,12 +542,19 @@ report.report_time = delegate_->GetReportTime(report); - if (!rate_limit_table_.IsAttributionAllowed(db_.get(), report, current_time)) - return false; + switch ( + rate_limit_table_.AttributionAllowed(db_.get(), report, current_time)) { + case RateLimitTable::AttributionAllowedStatus::kAllowed: + break; + case RateLimitTable::AttributionAllowedStatus::kNotAllowed: + return CreateReportStatus::kRateLimited; + case RateLimitTable::AttributionAllowedStatus::kError: + return CreateReportStatus::kInternalError; + } sql::Transaction transaction(db_.get()); if (!transaction.Begin()) - return false; + return CreateReportStatus::kInternalError; const auto maybe_replace_lower_priority_report_result = MaybeReplaceLowerPriorityReport(report, @@ -533,14 +562,14 @@ conversion.priority()); if (maybe_replace_lower_priority_report_result == ConversionStorageSql::MaybeReplaceLowerPriorityReportResult::kError) { - return false; + return CreateReportStatus::kInternalError; } if (maybe_replace_lower_priority_report_result == ConversionStorageSql::MaybeReplaceLowerPriorityReportResult:: kDropNewReport) { - transaction.Commit(); - return false; + return transaction.Commit() ? CreateReportStatus::kPriorityTooLow + : CreateReportStatus::kInternalError; } // Reports with `AttributionLogic::kNever` should be included in all @@ -553,7 +582,7 @@ DCHECK(report.impression.impression_id().has_value()); if (!StoreConversionReport(report, *report.impression.impression_id(), conversion.priority())) { - return false; + return CreateReportStatus::kInternalError; } } @@ -568,7 +597,7 @@ insert_dedup_key_statement.BindInt64(0, *report.impression.impression_id()); insert_dedup_key_statement.BindInt64(1, *conversion.dedup_key()); if (!insert_dedup_key_statement.Run()) - return false; + return CreateReportStatus::kInternalError; } // Only increment the number of conversions associated with the impression if @@ -586,12 +615,12 @@ impression_update_statement.BindInt64(0, *report.impression.impression_id()); if (!impression_update_statement.Run()) - return false; + return CreateReportStatus::kInternalError; } // Delete all unattributed impressions. if (!DeleteImpressions(impression_ids_to_delete)) - return false; + return CreateReportStatus::kInternalError; // Based on the deletion logic here and the fact that we delete impressions // with |num_conversions > 1| when there is a new matching impression in @@ -601,12 +630,19 @@ // |RateLimitTable::ClearDataForImpressionIds()| here. if (create_report && !rate_limit_table_.AddRateLimit(db_.get(), report)) - return false; + return CreateReportStatus::kInternalError; if (!transaction.Commit()) - return false; + return CreateReportStatus::kInternalError; - return create_report; + if (!create_report) + return CreateReportStatus::kDroppedForNoise; + + return maybe_replace_lower_priority_report_result == + ConversionStorageSql::MaybeReplaceLowerPriorityReportResult:: + kReplaceOldReport + ? CreateReportStatus::kSuccessDroppedLowerPriority + : CreateReportStatus::kSuccess; } bool ConversionStorageSql::StoreConversionReport(const ConversionReport& report, @@ -1016,11 +1052,11 @@ return count < delegate_->GetMaxImpressionsPerOrigin(); } -bool ConversionStorageSql::IsReportAlreadyStored( - int64_t impression_id, - absl::optional<int64_t> dedup_key) { +ConversionStorageSql::ReportAlreadyStoredStatus +ConversionStorageSql::ReportAlreadyStored(int64_t impression_id, + absl::optional<int64_t> dedup_key) { if (!dedup_key.has_value()) - return false; + return ReportAlreadyStoredStatus::kNotStored; static constexpr char kCountConversionsSql[] = "SELECT COUNT(*)FROM dedup_keys " @@ -1033,13 +1069,15 @@ // If there's an error, return true so `MaybeCreateAndStoreConversionReport()` // returns early. if (!statement.Step()) - return true; + return ReportAlreadyStoredStatus::kError; int64_t count = statement.ColumnInt64(0); - return count > 0; + return count > 0 ? ReportAlreadyStoredStatus::kStored + : ReportAlreadyStoredStatus::kNotStored; } -bool ConversionStorageSql::HasCapacityForStoringConversion( +ConversionStorageSql::ConversionCapacityStatus +ConversionStorageSql::CapacityForStoringConversion( const std::string& serialized_origin) { // This query should be reasonably optimized via // `kConversionDestinationIndexSql`. The conversion origin is the second @@ -1058,9 +1096,11 @@ db_->GetCachedStatement(SQL_FROM_HERE, kCountConversionsSql)); statement.BindString(0, serialized_origin); if (!statement.Step()) - return false; + return ConversionCapacityStatus::kError; int64_t count = statement.ColumnInt64(0); - return count < delegate_->GetMaxConversionsPerOrigin(); + return count < delegate_->GetMaxConversionsPerOrigin() + ? ConversionCapacityStatus::kHasCapacity + : ConversionCapacityStatus::kNoCapacity; } std::vector<StorableImpression> ConversionStorageSql::GetActiveImpressions(
diff --git a/content/browser/conversions/conversion_storage_sql.h b/content/browser/conversions/conversion_storage_sql.h index e6fef72..821897a 100644 --- a/content/browser/conversions/conversion_storage_sql.h +++ b/content/browser/conversions/conversion_storage_sql.h
@@ -82,7 +82,7 @@ // ConversionStorage void StoreImpression(const StorableImpression& impression) override; - bool MaybeCreateAndStoreConversionReport( + CreateReportStatus MaybeCreateAndStoreConversionReport( const StorableConversion& conversion) override; std::vector<ConversionReport> GetConversionsToReport(base::Time expiry_time, int limit = -1) override; @@ -115,10 +115,26 @@ bool HasCapacityForStoringImpression(const std::string& serialized_origin) VALID_CONTEXT_REQUIRED(sequence_checker_) WARN_UNUSED_RESULT; - bool IsReportAlreadyStored(int64_t impression_id, - absl::optional<int64_t> dedup_key) + + enum class ReportAlreadyStoredStatus { + kNotStored, + kStored, + kError, + }; + + ReportAlreadyStoredStatus ReportAlreadyStored( + int64_t impression_id, + absl::optional<int64_t> dedup_key) VALID_CONTEXT_REQUIRED(sequence_checker_) WARN_UNUSED_RESULT; - bool HasCapacityForStoringConversion(const std::string& serialized_origin) + + enum class ConversionCapacityStatus { + kHasCapacity, + kNoCapacity, + kError, + }; + + ConversionCapacityStatus CapacityForStoringConversion( + const std::string& serialized_origin) VALID_CONTEXT_REQUIRED(sequence_checker_) WARN_UNUSED_RESULT; enum class MaybeReplaceLowerPriorityReportResult {
diff --git a/content/browser/conversions/conversion_storage_sql_unittest.cc b/content/browser/conversions/conversion_storage_sql_unittest.cc index e754d51d..3032570 100644 --- a/content/browser/conversions/conversion_storage_sql_unittest.cc +++ b/content/browser/conversions/conversion_storage_sql_unittest.cc
@@ -25,6 +25,10 @@ namespace content { +namespace { + +using CreateReportStatus = ::content::ConversionStorage::CreateReportStatus; + class ConversionStorageSqlTest : public testing::Test { public: ConversionStorageSqlTest() = default; @@ -91,6 +95,8 @@ base::SimpleTestClock clock_; }; +} // namespace + TEST_F(ConversionStorageSqlTest, DatabaseInitialized_TablesAndIndexesLazilyInitialized) { base::HistogramTester histograms; @@ -182,11 +188,13 @@ storage()->StoreImpression(impression); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // Use a time range that only intersects the last conversion. @@ -218,11 +226,13 @@ storage()->StoreImpression(impression); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // Use a time range that only intersects the last conversion. @@ -256,10 +266,12 @@ clock()->Advance(base::TimeDelta::FromDays(1)); } - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); auto null_filter = base::RepeatingCallback<bool(const url::Origin&)>(); @@ -283,7 +295,8 @@ storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); CloseDatabase(); @@ -301,11 +314,14 @@ OpenDatabase(); delegate()->set_max_conversions_per_origin(2); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoCapacityForConversionDestination, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); CloseDatabase(); @@ -341,21 +357,25 @@ .Build()); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite(conversion_origin)) - .SetReportingOrigin(reporting_origin) - .Build())); + EXPECT_EQ( + CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite(conversion_origin)) + .SetReportingOrigin(reporting_origin) + .Build())); EXPECT_EQ(1u, storage()->GetActiveImpressions().size()); // Force the impression to be deactivated by ensuring that the next report is // in a different window. delegate()->set_report_time_ms(1); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite(conversion_origin)) - .SetReportingOrigin(reporting_origin) - .Build())); + EXPECT_EQ( + CreateReportStatus::kPriorityTooLow, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite(conversion_origin)) + .SetReportingOrigin(reporting_origin) + .Build())); EXPECT_EQ(0u, storage()->GetActiveImpressions().size()); clock()->Advance(base::TimeDelta::FromDays(1)); @@ -397,21 +417,25 @@ .Build()); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite(conversion_origin)) - .SetReportingOrigin(reporting_origin) - .Build())); + EXPECT_EQ( + CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite(conversion_origin)) + .SetReportingOrigin(reporting_origin) + .Build())); EXPECT_EQ(1u, storage()->GetActiveImpressions().size()); // Force the impression to be deactivated by ensuring that the next report is // in a different window. delegate()->set_report_time_ms(1); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite(conversion_origin)) - .SetReportingOrigin(reporting_origin) - .Build())); + EXPECT_EQ( + CreateReportStatus::kPriorityTooLow, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite(conversion_origin)) + .SetReportingOrigin(reporting_origin) + .Build())); EXPECT_EQ(0u, storage()->GetActiveImpressions().size()); clock()->Advance(base::TimeDelta::FromDays(1)); @@ -443,8 +467,8 @@ // These calls should be no-ops. storage->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_FALSE( - storage->MaybeCreateAndStoreConversionReport(DefaultConversion())); + EXPECT_EQ(CreateReportStatus::kNoMatchingImpressions, + storage->MaybeCreateAndStoreConversionReport(DefaultConversion())); } TEST_F(ConversionStorageSqlTest, DatabaseDirDoesExist_CreateDirAndOpenDB) { @@ -457,8 +481,8 @@ // The directory should be created, and the database opened. storage->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( - storage->MaybeCreateAndStoreConversionReport(DefaultConversion())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage->MaybeCreateAndStoreConversionReport(DefaultConversion())); } TEST_F(ConversionStorageSqlTest, DBinitializationSucceeds_HistogramRecorded) { @@ -489,10 +513,12 @@ EXPECT_EQ(1u, impressions.size()); EXPECT_EQ(kMaxUint64, impressions[0].impression_data()); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(StorableConversion( - /*conversion_data=*/kMaxUint64, impression.ConversionDestination(), - impression.reporting_origin(), /*event_source_trigger_data=*/0, - /*priority=*/0, /*dedup_key=*/absl::nullopt))); + EXPECT_EQ( + CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(StorableConversion( + /*conversion_data=*/kMaxUint64, impression.ConversionDestination(), + impression.reporting_origin(), /*event_source_trigger_data=*/0, + /*priority=*/0, /*dedup_key=*/absl::nullopt))); std::vector<ConversionReport> reports = storage()->GetConversionsToReport(clock()->Now()); @@ -564,7 +590,8 @@ ImpressionBuilder(clock()->Now()) .SetExpiry(base::TimeDelta::FromMilliseconds(3)) .Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(3)); @@ -611,7 +638,8 @@ ImpressionBuilder(clock()->Now()) .SetExpiry(base::TimeDelta::FromMilliseconds(3)) .Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(3));
diff --git a/content/browser/conversions/conversion_storage_unittest.cc b/content/browser/conversions/conversion_storage_unittest.cc index 8135a63b..0c33e11 100644 --- a/content/browser/conversions/conversion_storage_unittest.cc +++ b/content/browser/conversions/conversion_storage_unittest.cc
@@ -33,6 +33,8 @@ namespace { +using CreateReportStatus = ::content::ConversionStorage::CreateReportStatus; + using ::testing::ElementsAre; using ::testing::IsEmpty; @@ -112,8 +114,8 @@ // Test all public methods on ConversionStorage. EXPECT_NO_FATAL_FAILURE( storage->StoreImpression(ImpressionBuilder(clock()->Now()).Build())); - EXPECT_FALSE( - storage->MaybeCreateAndStoreConversionReport(DefaultConversion())); + EXPECT_EQ(CreateReportStatus::kNoMatchingImpressions, + storage->MaybeCreateAndStoreConversionReport(DefaultConversion())); EXPECT_TRUE(storage->GetConversionsToReport(clock()->Now()).empty()); EXPECT_TRUE(storage->GetActiveImpressions().empty()); EXPECT_EQ(0, storage->DeleteConversion(0)); @@ -149,21 +151,24 @@ TEST_F(ConversionStorageTest, GetWithNoMatchingImpressions_NoImpressionsReturned) { - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoMatchingImpressions, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); EXPECT_TRUE(storage()->GetConversionsToReport(clock()->Now()).empty()); } TEST_F(ConversionStorageTest, GetWithMatchingImpression_ImpressionReturned) { storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } TEST_F(ConversionStorageTest, MultipleImpressionsForConversion_OneConverts) { storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -174,11 +179,13 @@ .SetConversionOrigin(url::Origin::Create(GURL("https://sub.a.test"))) .Build(); storage()->StoreImpression(impression); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite(GURL("https://a.test"))) - .SetReportingOrigin(impression.reporting_origin()) - .Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination( + net::SchemefulSite(GURL("https://a.test"))) + .SetReportingOrigin(impression.reporting_origin()) + .Build())); } TEST_F(ConversionStorageTest, EventSourceImpressionsForConversion_Converts) { @@ -186,8 +193,9 @@ ImpressionBuilder(clock()->Now()) .SetSourceType(StorableImpression::SourceType::kEvent) .Build()); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetEventSourceTriggerData(456).Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetEventSourceTriggerData(456).Build())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -204,7 +212,8 @@ .Build()); clock()->Advance(base::TimeDelta::FromMilliseconds(2)); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoMatchingImpressions, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -216,12 +225,14 @@ clock()->Advance(base::TimeDelta::FromMilliseconds(3)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(5)); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoMatchingImpressions, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -230,12 +241,14 @@ storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); for (int i = 0; i < kMaxConversions; i++) { - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } // No additional conversion reports should be created. - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kPriorityTooLow, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -244,7 +257,8 @@ auto conversion = DefaultConversion(); storage()->StoreImpression(impression); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); ConversionReport expected_report = GetExpectedReport(impression, conversion); @@ -262,7 +276,8 @@ url::Origin::Create(GURL("https://different.test"))) .Build(); storage()->StoreImpression(impression); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoMatchingImpressions, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -277,7 +292,8 @@ url::Origin::Create(GURL("https://different.test"))) .Build(); storage()->StoreImpression(impression); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoMatchingImpressions, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -287,7 +303,8 @@ TEST_F(ConversionStorageTest, ConversionReportDeleted_RemovedFromStorage) { storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -310,13 +327,15 @@ } for (int i = 0; i < kMaxConversions; i++) { - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } // No additional conversion reports should be created for any of the // impressions. - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kPriorityTooLow, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -333,7 +352,8 @@ // The first impression should be active because even though // <reporting_origin, conversion_origin> matches, it has not converted yet. EXPECT_EQ(2u, storage()->GetActiveImpressions().size()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); EXPECT_EQ(1u, storage()->GetActiveImpressions().size()); } @@ -346,7 +366,8 @@ NewImpressionForConvertedImpression_MarkedInactive) { storage()->StoreImpression( ImpressionBuilder(clock()->Now()).SetData(0).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -360,7 +381,8 @@ // Only the new impression should convert. auto conversion = DefaultConversion(); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); ConversionReport expected_report = GetExpectedReport(new_impression, conversion); @@ -377,7 +399,8 @@ storage()->StoreImpression(first_impression); auto conversion = DefaultConversion(); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -393,7 +416,8 @@ storage()->StoreImpression(new_impression); // The first impression should still be active and able to convert. - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); ConversionReport expected_report = GetExpectedReport(first_impression, conversion); @@ -423,7 +447,8 @@ ConversionReport third_expected_conversion = GetExpectedReport(third_impression, conversion); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -445,7 +470,8 @@ clock()->Advance(base::TimeDelta::FromMilliseconds(3)); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // Advance to the first impression's report time and verify only its report is @@ -462,7 +488,8 @@ TEST_F(ConversionStorageTest, GetConversionsToReportMultipleTimes_SameResult) { storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -543,10 +570,12 @@ delegate()->set_max_conversions_per_origin(1); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // Verify that MaxConversionsPerOrigin is enforced. - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoCapacityForConversionDestination, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -556,7 +585,8 @@ storage()->StoreImpression(impression); storage()->ClearData( now, now, GetMatcher(url::Origin::Create(GURL("https://no-match.com")))); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -568,7 +598,8 @@ storage()->ClearData(now + base::TimeDelta::FromMinutes(10), now + base::TimeDelta::FromMinutes(20), GetMatcher(impression.impression_origin())); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -580,7 +611,8 @@ storage()->StoreImpression(impression); storage()->ClearData(now, now + base::TimeDelta::FromMinutes(20), GetMatcher(impression.conversion_origin())); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoMatchingImpressions, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } } @@ -591,7 +623,8 @@ auto conversion = DefaultConversion(); storage()->StoreImpression(impression); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); storage()->ClearData(now - base::TimeDelta::FromMinutes(20), now + base::TimeDelta::FromMinutes(20), @@ -620,21 +653,23 @@ for (int i = 0; i < 5; i++) { auto origin = url::Origin::Create(GURL(base::StringPrintf("https://%d.com/", i))); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite(origin)) - .SetReportingOrigin(origin) - .Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite(origin)) + .SetReportingOrigin(origin) + .Build())); } clock()->Advance(base::TimeDelta::FromDays(1)); for (int i = 5; i < 10; i++) { auto origin = url::Origin::Create(GURL(base::StringPrintf("https://%d.com/", i))); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite(origin)) - .SetReportingOrigin(origin) - .Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite(origin)) + .SetReportingOrigin(origin) + .Build())); } auto null_filter = base::RepeatingCallback<bool(const url::Origin&)>(); @@ -650,7 +685,8 @@ storage()->StoreImpression(impression); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); storage()->ClearData(clock()->Now(), clock()->Now(), GetMatcher(impression.impression_origin())); EXPECT_TRUE(storage()->GetConversionsToReport(base::Time::Max()).empty()); @@ -671,7 +707,8 @@ const ConversionReport expected_report = GetExpectedReport(impression, conversion); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); storage()->ClearData(start + base::TimeDelta::FromMinutes(1), start + base::TimeDelta::FromMinutes(10), @@ -700,7 +737,8 @@ storage()->StoreImpression(impression2); storage()->StoreImpression(impression3); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // Only the first impression should overlap with this time range, but all the @@ -721,10 +759,12 @@ clock()->Advance(base::TimeDelta::FromDays(1)); } - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); auto null_filter = base::RepeatingCallback<bool(const url::Origin&)>(); @@ -746,10 +786,12 @@ clock()->Advance(base::TimeDelta::FromDays(1)); } - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromDays(1)); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); auto null_filter = base::RepeatingCallback<bool(const url::Origin&)>(); @@ -769,9 +811,12 @@ auto conversion = DefaultConversion(); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kRateLimited, + storage()->MaybeCreateAndStoreConversionReport(conversion)); const ConversionReport expected_report = GetExpectedReport(impression, conversion); @@ -792,7 +837,8 @@ ImpressionBuilder(clock()->Now()) .SetSourceType(StorableImpression::SourceType::kNavigation) .Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); storage()->StoreImpression( @@ -801,21 +847,24 @@ .Build()); // This would fail if the source types had a combined limit or the incorrect // source type were stored. - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); storage()->StoreImpression( ImpressionBuilder(clock()->Now()) .SetSourceType(StorableImpression::SourceType::kEvent) .Build()); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kRateLimited, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); storage()->StoreImpression( ImpressionBuilder(clock()->Now()) .SetSourceType(StorableImpression::SourceType::kNavigation) .Build()); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kRateLimited, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); } @@ -825,7 +874,8 @@ delegate()->set_max_conversions_per_impression(1); storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kDroppedForNoise, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -842,7 +892,8 @@ storage()->StoreImpression( ImpressionBuilder(clock()->Now()).SetData(3).Build()); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kDroppedForNoise, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); delegate()->set_attribution_logic( @@ -850,8 +901,9 @@ storage()->StoreImpression( ImpressionBuilder(clock()->Now()).SetData(5).Build()); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetConversionData(7).Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetConversionData(7).Build())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -874,17 +926,20 @@ ImpressionBuilder(clock()->Now()).SetData(5).Build()); const auto conversion = DefaultConversion(); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kDroppedForNoise, + storage()->MaybeCreateAndStoreConversionReport(conversion)); delegate()->set_attribution_logic( StorableImpression::AttributionLogic::kTruthfully); const auto impression = ImpressionBuilder(clock()->Now()).SetData(7).Build(); storage()->StoreImpression(impression); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport(conversion)); storage()->StoreImpression( ImpressionBuilder(clock()->Now()).SetData(9).Build()); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kRateLimited, + storage()->MaybeCreateAndStoreConversionReport(conversion)); const ConversionReport expected_report = GetExpectedReport(impression, conversion); @@ -909,8 +964,10 @@ storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); const auto conversion = DefaultConversion(); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport(conversion)); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kDroppedForNoise, + storage()->MaybeCreateAndStoreConversionReport(conversion)); + EXPECT_EQ(CreateReportStatus::kDroppedForNoise, + storage()->MaybeCreateAndStoreConversionReport(conversion)); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -1035,14 +1092,16 @@ .Build()); EXPECT_EQ(1u, storage()->GetActiveImpressions().size()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); EXPECT_EQ(1u, storage()->GetActiveImpressions().size()); // Force the impression to be deactivated by ensuring that the next report is // in a different window. delegate()->set_report_time_ms(kReportTime + 1); - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kPriorityTooLow, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); EXPECT_EQ(0u, storage()->GetActiveImpressions().size()); @@ -1092,7 +1151,8 @@ ImpressionBuilder(clock()->Now()).SetData(5).Build()); EXPECT_EQ(3u, storage()->GetActiveImpressions().size()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -1117,7 +1177,8 @@ ImpressionBuilder(clock()->Now()).SetPriority(200).SetData(7).Build()); EXPECT_EQ(3u, storage()->GetActiveImpressions().size()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -1135,7 +1196,8 @@ ImpressionBuilder(clock()->Now()).SetData(5).SetPriority(1).Build()); EXPECT_EQ(2u, storage()->GetActiveImpressions().size()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // Because the impression with data 5 has the highest priority, it is selected @@ -1178,7 +1240,8 @@ // The falsely attributed impression should not be eligible for further // attribution. - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kNoMatchingImpressions, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); actual_reports = storage()->GetConversionsToReport(clock()->Now()); @@ -1193,22 +1256,28 @@ storage()->StoreImpression( ImpressionBuilder(clock()->Now()).SetData(5).SetPriority(1).Build()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // This conversion should replace the one above because it has a higher // priority. - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(2).SetConversionData(21).Build())); + EXPECT_EQ( + CreateReportStatus::kSuccessDroppedLowerPriority, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(2).SetConversionData(21).Build())); storage()->StoreImpression( ImpressionBuilder(clock()->Now()).SetData(7).SetPriority(2).Build()); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(1).SetConversionData(22).Build())); + EXPECT_EQ( + CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(1).SetConversionData(22).Build())); // This conversion should be dropped because it has a lower priority than the // one above. - EXPECT_FALSE( + EXPECT_EQ( + CreateReportStatus::kPriorityTooLow, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -1229,9 +1298,18 @@ storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - for (int i = 0; i < 10; i++) { - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(i).SetConversionData(i).Build())); + int i = 0; + EXPECT_EQ( + CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(i).SetConversionData(i).Build())); + i++; + + for (; i < 10; i++) { + EXPECT_EQ( + CreateReportStatus::kSuccessDroppedLowerPriority, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(i).SetConversionData(i).Build())); } clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -1247,24 +1325,32 @@ storage()->StoreImpression(ImpressionBuilder(clock()->Now()).Build()); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(1).SetConversionData(3).Build())); + EXPECT_EQ( + CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(1).SetConversionData(3).Build())); clock()->Advance(base::TimeDelta::FromMilliseconds(1)); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(1).SetConversionData(2).Build())); + EXPECT_EQ( + CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(1).SetConversionData(2).Build())); // This report should not be stored, as even though it has the same priority // as the previous two, it is the most recent. clock()->Advance(base::TimeDelta::FromMilliseconds(1)); - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(1).SetConversionData(8).Build())); + EXPECT_EQ( + CreateReportStatus::kPriorityTooLow, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(1).SetConversionData(8).Build())); // This report should be stored by replacing the one with `conversion_data == // 2`, which is the most recent of the two with `priority == 1`. clock()->Advance(base::TimeDelta::FromMilliseconds(1)); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(2).SetConversionData(5).Build())); + EXPECT_EQ( + CreateReportStatus::kSuccessDroppedLowerPriority, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(2).SetConversionData(5).Build())); std::vector<ConversionReport> actual_reports = storage()->GetConversionsToReport(base::Time::Max()); @@ -1282,7 +1368,8 @@ ImpressionBuilder(clock()->Now()).SetData(5).SetPriority(1).Build()); EXPECT_EQ(2u, storage()->GetActiveImpressions().size()); - EXPECT_TRUE( + EXPECT_EQ( + CreateReportStatus::kSuccess, storage()->MaybeCreateAndStoreConversionReport(DefaultConversion())); // Because the impression with data 5 has the highest priority, it is selected @@ -1298,8 +1385,9 @@ // This conversion should not be stored because all reports for the attributed // impression were in an earlier window. - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder().SetPriority(2).Build())); + EXPECT_EQ(CreateReportStatus::kPriorityTooLow, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder().SetPriority(2).Build())); // As a result, the impression with data 5 should also be deactivated. EXPECT_TRUE(storage()->GetActiveImpressions().empty()); @@ -1321,51 +1409,56 @@ EXPECT_THAT(active_impressions[0].dedup_keys(), IsEmpty()); EXPECT_THAT(active_impressions[1].dedup_keys(), IsEmpty()); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite( - url::Origin::Create(GURL("https://a.example")))) - .SetDedupKey(11) - .SetConversionData(71) - .Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite( + url::Origin::Create(GURL("https://a.example")))) + .SetDedupKey(11) + .SetConversionData(71) + .Build())); // Should be stored because dedup key doesn't match even though conversion // destination does. - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite( - url::Origin::Create(GURL("https://a.example")))) - .SetDedupKey(12) - .SetConversionData(72) - .Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite( + url::Origin::Create(GURL("https://a.example")))) + .SetDedupKey(12) + .SetConversionData(72) + .Build())); // Should be stored because conversion destination doesn't match even though // dedup key does. - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite( - url::Origin::Create(GURL("https://b.example")))) - .SetDedupKey(12) - .SetConversionData(73) - .Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite( + url::Origin::Create(GURL("https://b.example")))) + .SetDedupKey(12) + .SetConversionData(73) + .Build())); // Shouldn't be stored because conversion destination and dedup key match. - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite( - url::Origin::Create(GURL("https://a.example")))) - .SetDedupKey(11) - .SetConversionData(74) - .Build())); + EXPECT_EQ(CreateReportStatus::kDeduplicated, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite( + url::Origin::Create(GURL("https://a.example")))) + .SetDedupKey(11) + .SetConversionData(74) + .Build())); // Shouldn't be stored because conversion destination and dedup key match. - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite( - url::Origin::Create(GURL("https://b.example")))) - .SetDedupKey(12) - .SetConversionData(75) - .Build())); + EXPECT_EQ(CreateReportStatus::kDeduplicated, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite( + url::Origin::Create(GURL("https://b.example")))) + .SetDedupKey(12) + .SetConversionData(75) + .Build())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); std::vector<ConversionReport> actual_reports = @@ -1391,13 +1484,14 @@ clock()->Advance(base::TimeDelta::FromMilliseconds(1)); - EXPECT_TRUE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite( - url::Origin::Create(GURL("https://a.example")))) - .SetDedupKey(2) - .SetConversionData(3) - .Build())); + EXPECT_EQ(CreateReportStatus::kSuccess, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite( + url::Origin::Create(GURL("https://a.example")))) + .SetDedupKey(2) + .SetConversionData(3) + .Build())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); @@ -1413,13 +1507,14 @@ // This report shouldn't be stored, as it should be deduped against the // previously stored one even though that previous one is no longer in the DB. - EXPECT_FALSE(storage()->MaybeCreateAndStoreConversionReport( - ConversionBuilder() - .SetConversionDestination(net::SchemefulSite( - url::Origin::Create(GURL("https://a.example")))) - .SetDedupKey(2) - .SetConversionData(5) - .Build())); + EXPECT_EQ(CreateReportStatus::kDeduplicated, + storage()->MaybeCreateAndStoreConversionReport( + ConversionBuilder() + .SetConversionDestination(net::SchemefulSite( + url::Origin::Create(GURL("https://a.example")))) + .SetDedupKey(2) + .SetConversionData(5) + .Build())); clock()->Advance(base::TimeDelta::FromMilliseconds(kReportTime)); EXPECT_THAT(storage()->GetConversionsToReport(clock()->Now()), IsEmpty());
diff --git a/content/browser/conversions/conversion_test_utils.cc b/content/browser/conversions/conversion_test_utils.cc index b8ac3533..54d70787 100644 --- a/content/browser/conversions/conversion_test_utils.cc +++ b/content/browser/conversions/conversion_test_utils.cc
@@ -22,6 +22,8 @@ namespace { +using CreateReportStatus = ::content::ConversionStorage::CreateReportStatus; + const char kDefaultImpressionOrigin[] = "https://impression.test/"; const char kDefaultConversionOrigin[] = "https://sub.conversion.test/"; const char kDefaultConversionDestination[] = "https://conversion.test/"; @@ -372,6 +374,39 @@ return tie(a) == tie(b); } +std::ostream& operator<<(std::ostream& out, CreateReportStatus result) { + switch (result) { + case CreateReportStatus::kSuccess: + out << "kSuccess"; + break; + case CreateReportStatus::kSuccessDroppedLowerPriority: + out << "kSuccessDroppedLowerPriority"; + break; + case CreateReportStatus::kInternalError: + out << "kInternalError"; + break; + case CreateReportStatus::kNoCapacityForConversionDestination: + out << "kNoCapacityForConversionDestination"; + break; + case CreateReportStatus::kNoMatchingImpressions: + out << "kNoMatchingImpressions"; + break; + case CreateReportStatus::kDeduplicated: + out << "kDeduplicated"; + break; + case CreateReportStatus::kRateLimited: + out << "kRateLimited"; + break; + case CreateReportStatus::kPriorityTooLow: + out << "kPriorityTooLow"; + break; + case CreateReportStatus::kDroppedForNoise: + out << "kDroppedForNoise"; + break; + } + return out; +} + std::vector<ConversionReport> GetConversionsToReportForTesting( ConversionManagerImpl* manager, base::Time max_report_time) {
diff --git a/content/browser/conversions/conversion_test_utils.h b/content/browser/conversions/conversion_test_utils.h index b74b438..310939d3 100644 --- a/content/browser/conversions/conversion_test_utils.h +++ b/content/browser/conversions/conversion_test_utils.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <iosfwd> #include <vector> #include "base/containers/circular_deque.h" @@ -329,6 +330,9 @@ bool operator==(const SentReportInfo& a, const SentReportInfo& b); +std::ostream& operator<<(std::ostream& out, + ConversionStorage::CreateReportStatus result); + std::vector<ConversionReport> GetConversionsToReportForTesting( ConversionManagerImpl* manager, base::Time max_report_time) WARN_UNUSED_RESULT;
diff --git a/content/browser/conversions/rate_limit_table.cc b/content/browser/conversions/rate_limit_table.cc index 1e10265..3adc7f1 100644 --- a/content/browser/conversions/rate_limit_table.cc +++ b/content/browser/conversions/rate_limit_table.cc
@@ -53,7 +53,7 @@ if (!db->Execute(kRateLimitTableSql)) return false; - // Optimizes calls to |IsAttributionAllowed()|. + // Optimizes calls to |AttributionAllowed()|. static constexpr char kRateLimitImpressionSiteTypeIndexSql[] = "CREATE INDEX IF NOT EXISTS rate_limit_impression_site_type_idx " "ON rate_limits(attribution_type,conversion_destination," @@ -111,9 +111,10 @@ return statement.Run(); } -bool RateLimitTable::IsAttributionAllowed(sql::Database* db, - const ConversionReport& report, - base::Time now) { +RateLimitTable::AttributionAllowedStatus RateLimitTable::AttributionAllowed( + sql::Database* db, + const ConversionReport& report, + base::Time now) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ConversionStorage::Delegate::RateLimitConfig rate_limits = @@ -136,10 +137,12 @@ report.impression.ConversionDestination().Serialize()); statement.BindTime(3, min_timestamp); if (!statement.Step()) - return false; + return AttributionAllowedStatus::kError; int64_t count = statement.ColumnInt64(0); - return count < rate_limits.max_attributions_per_window; + return count < rate_limits.max_attributions_per_window + ? AttributionAllowedStatus::kAllowed + : AttributionAllowedStatus::kNotAllowed; } bool RateLimitTable::ClearAllDataInRange(sql::Database* db,
diff --git a/content/browser/conversions/rate_limit_table.h b/content/browser/conversions/rate_limit_table.h index 7517e48..7770170 100644 --- a/content/browser/conversions/rate_limit_table.h +++ b/content/browser/conversions/rate_limit_table.h
@@ -53,11 +53,18 @@ bool AddRateLimit(sql::Database* db, const ConversionReport& report) WARN_UNUSED_RESULT; + enum class AttributionAllowedStatus { + kAllowed, + kNotAllowed, + kError, + }; + // Checks if the given attribution is allowed according to the data in the // table and policy as specified by the delegate. - bool IsAttributionAllowed(sql::Database* db, - const ConversionReport& report, - base::Time now) WARN_UNUSED_RESULT; + AttributionAllowedStatus AttributionAllowed(sql::Database* db, + const ConversionReport& report, + base::Time now) + WARN_UNUSED_RESULT; // These should be 1:1 with |ConversionStorageSql|'s |ClearData| functions. // Returns false on failure.
diff --git a/content/browser/conversions/rate_limit_table_unittest.cc b/content/browser/conversions/rate_limit_table_unittest.cc index f7cf2ab..bacddd2d 100644 --- a/content/browser/conversions/rate_limit_table_unittest.cc +++ b/content/browser/conversions/rate_limit_table_unittest.cc
@@ -24,6 +24,8 @@ namespace { +using AttributionAllowedStatus = + ::content::RateLimitTable::AttributionAllowedStatus; using ::testing::ElementsAre; class RateLimitTableTest : public testing::Test { @@ -133,7 +135,7 @@ EXPECT_EQ(1u, GetRateLimitRows(&db)); } -TEST_F(RateLimitTableTest, IsAttributionAllowed) { +TEST_F(RateLimitTableTest, AttributionAllowed) { sql::Database db; EXPECT_TRUE(db.Open(db_path())); EXPECT_TRUE(table()->CreateTable(&db)); @@ -175,25 +177,35 @@ const auto report_b_a = NewConversionReport(example_b, example_a); base::Time now = clock()->Now(); - EXPECT_FALSE(table()->IsAttributionAllowed(&db, report_a_c, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_a_d, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_b_c, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_a_b, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_b_a, now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed(&db, report_a_c, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_a_d, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_b_c, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_a_b, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_b_a, now)); // Expire the first row above by advancing to +10d. clock()->Advance(base::TimeDelta::FromDays(4)); now = clock()->Now(); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_a_c, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_a_d, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_b_c, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_a_b, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_b_a, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_a_c, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_a_d, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_b_c, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_a_b, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_b_a, now)); EXPECT_EQ(3u, GetRateLimitRows(&db)); } -TEST_F(RateLimitTableTest, IsAttributionAllowed_SourceTypesIndependent) { +TEST_F(RateLimitTableTest, CheckAttributionAllowed_SourceTypesIndependent) { // Tests that limits are calculated independently for each // `StorableImpression::SourceType`. In the future, we may change this so that // there is a combined calculation but each source type is weighted @@ -224,22 +236,28 @@ EXPECT_EQ(2u, GetRateLimitRows(&db)); base::Time now = clock()->Now(); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_navigation, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_event, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_navigation, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_event, now)); EXPECT_TRUE(table()->AddRateLimit(&db, report_navigation)); EXPECT_EQ(3u, GetRateLimitRows(&db)); - EXPECT_FALSE(table()->IsAttributionAllowed(&db, report_navigation, now)); - EXPECT_TRUE(table()->IsAttributionAllowed(&db, report_event, now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed(&db, report_navigation, now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed(&db, report_event, now)); EXPECT_TRUE(table()->AddRateLimit(&db, report_event)); EXPECT_EQ(4u, GetRateLimitRows(&db)); - EXPECT_FALSE(table()->IsAttributionAllowed(&db, report_navigation, now)); - EXPECT_FALSE(table()->IsAttributionAllowed(&db, report_event, now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed(&db, report_navigation, now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed(&db, report_event, now)); } TEST_F(RateLimitTableTest, - IsAttributionAllowed_ConversionDestinationSubdomains) { + CheckAttributionAllowed_ConversionDestinationSubdomains) { sql::Database db; EXPECT_TRUE(db.Open(db_path())); EXPECT_TRUE(table()->CreateTable(&db)); @@ -265,15 +283,18 @@ &db, NewConversionReport(example_a, example_c_sub_b))); base::Time now = clock()->Now(); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_c_sub_a), now)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_c_sub_b), now)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_c), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_c_sub_a), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_c_sub_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_c), now)); } -TEST_F(RateLimitTableTest, IsAttributionAllowed_ImpressionSiteSubdomains) { +TEST_F(RateLimitTableTest, CheckAttributionAllowed_ImpressionSiteSubdomains) { sql::Database db; EXPECT_TRUE(db.Open(db_path())); EXPECT_TRUE(table()->CreateTable(&db)); @@ -299,12 +320,15 @@ &db, NewConversionReport(example_c_sub_b, example_a))); base::Time now = clock()->Now(); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_c_sub_a, example_a), now)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_c_sub_b, example_a), now)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_c, example_a), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_c_sub_a, example_a), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_c_sub_b, example_a), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_c, example_a), now)); } TEST_F(RateLimitTableTest, ClearAllDataAllTime) { @@ -354,10 +378,12 @@ base::Time now = clock()->Now(); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_b), now)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_b, example_c), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_b, example_c), now)); // Delete the first row: attribution should now be allowed for the site, // but the other rows should not be deleted. @@ -365,10 +391,12 @@ now - base::TimeDelta::FromDays(7), now - base::TimeDelta::FromDays(6))); EXPECT_EQ(3u, GetRateLimitRows(&db)); - EXPECT_TRUE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_b), now)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_b, example_c), now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_b, example_c), now)); } TEST_F(RateLimitTableTest, ClearDataForOriginsInRange) { @@ -402,24 +430,27 @@ EXPECT_EQ(3u, GetRateLimitRows(&db)); base::Time now = clock()->Now(); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_b), now)); // Should delete nothing, because (example_d, example_c) is at now. EXPECT_TRUE(table()->ClearDataForOriginsInRange( &db, base::Time(), now - base::TimeDelta::FromDays(1), base::BindRepeating(std::equal_to<url::Origin>(), example_c))); EXPECT_EQ(3u, GetRateLimitRows(&db)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_b), now)); // Should delete (example_a, example_ba). EXPECT_TRUE(table()->ClearDataForOriginsInRange( &db, base::Time(), base::Time::Max(), base::BindRepeating(std::equal_to<url::Origin>(), example_ba))); EXPECT_EQ(2u, GetRateLimitRows(&db)); - EXPECT_TRUE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_b), now)); // Should delete (example_d, example_c), the only report >= now. EXPECT_TRUE(table()->ClearDataForOriginsInRange( @@ -511,17 +542,21 @@ EXPECT_TRUE(table()->AddRateLimit( &db, NewConversionReport(example_c, example_d, /*impression_id=*/4))); EXPECT_EQ(4u, GetRateLimitRows(&db)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_b), now)); - EXPECT_FALSE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_c, example_d), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kNotAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_c, example_d), now)); EXPECT_TRUE(table()->ClearDataForImpressionIds(&db, {1, 4})); EXPECT_EQ(2u, GetRateLimitRows(&db)); - EXPECT_TRUE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_a, example_b), now)); - EXPECT_TRUE(table()->IsAttributionAllowed( - &db, NewConversionReport(example_c, example_d), now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_a, example_b), now)); + EXPECT_EQ(AttributionAllowedStatus::kAllowed, + table()->AttributionAllowed( + &db, NewConversionReport(example_c, example_d), now)); } } // namespace content
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 1704804..73a105bd 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -1367,9 +1367,9 @@ SendCommand("Page.handleJavaScriptDialog", std::move(params), false); params = WaitForNotification("Page.javascriptDialogClosed", true); - bool result = false; - EXPECT_TRUE(params->GetBoolean("result", &result)); + absl::optional<bool> result = params->FindBoolPath("result"); EXPECT_TRUE(result); + EXPECT_TRUE(*result); EXPECT_TRUE(dialog_manager.is_handled()); @@ -1500,12 +1500,13 @@ // TODO(eseckler): Since the RenderView is closed asynchronously, we currently // don't verify that the command actually closes the shell. - bool success; params = std::make_unique<base::DictionaryValue>(); params->SetString("targetId", target_id); SendCommand("Target.closeTarget", std::move(params), true); - EXPECT_TRUE(result_->GetBoolean("success", &success)); + + absl::optional<bool> success = result_->FindBoolPath("success"); EXPECT_TRUE(success); + EXPECT_TRUE(*success); } IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, BrowserGetTargets) { @@ -1788,7 +1789,7 @@ std::set<std::string> ids; std::unique_ptr<base::DictionaryValue> command_params; std::unique_ptr<base::DictionaryValue> params; - bool is_attached; + absl::optional<bool> is_attached; ASSERT_TRUE(embedded_test_server()->Start()); GURL first_url = embedded_test_server()->GetURL("/devtools/navigation.html"); @@ -1806,16 +1807,18 @@ params = WaitForNotification("Target.targetCreated", true); EXPECT_TRUE(params->GetString("targetInfo.type", &temp)); EXPECT_EQ("page", temp); - EXPECT_TRUE(params->GetBoolean("targetInfo.attached", &is_attached)); - attached_count += is_attached ? 1 : 0; + is_attached = params->FindBoolPath("targetInfo.attached"); + EXPECT_TRUE(is_attached); + attached_count += *is_attached ? 1 : 0; EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp)); EXPECT_TRUE(ids.find(temp) == ids.end()); ids.insert(temp); params = WaitForNotification("Target.targetCreated", true); EXPECT_TRUE(params->GetString("targetInfo.type", &temp)); EXPECT_EQ("page", temp); - EXPECT_TRUE(params->GetBoolean("targetInfo.attached", &is_attached)); - attached_count += is_attached ? 1 : 0; + is_attached = params->FindBoolPath("targetInfo.attached"); + EXPECT_TRUE(is_attached); + attached_count += *is_attached ? 1 : 0; EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp)); EXPECT_TRUE(ids.find(temp) == ids.end()); ids.insert(temp); @@ -1831,8 +1834,9 @@ EXPECT_EQ("page", temp); EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp)); EXPECT_TRUE(ids.find(temp) == ids.end()); - EXPECT_TRUE(params->GetBoolean("targetInfo.attached", &is_attached)); - EXPECT_FALSE(is_attached); + is_attached = params->FindBoolPath("targetInfo.attached"); + EXPECT_TRUE(is_attached); + EXPECT_FALSE(*is_attached); std::string attached_id = temp; ids.insert(temp); @@ -1859,8 +1863,9 @@ params = WaitForNotification("Target.targetInfoChanged", true); EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp)); EXPECT_EQ(attached_id, temp); - EXPECT_TRUE(params->GetBoolean("targetInfo.attached", &is_attached)); + is_attached = params->FindBoolPath("targetInfo.attached"); EXPECT_TRUE(is_attached); + EXPECT_TRUE(*is_attached); params = WaitForNotification("Target.attachedToTarget", true); std::string session_id; EXPECT_TRUE(params->GetString("sessionId", &session_id));
diff --git a/content/browser/devtools/protocol/devtools_protocol_test_support.cc b/content/browser/devtools/protocol/devtools_protocol_test_support.cc index 68e0aac..bec1e8b6 100644 --- a/content/browser/devtools/protocol/devtools_protocol_test_support.cc +++ b/content/browser/devtools/protocol/devtools_protocol_test_support.cc
@@ -201,8 +201,9 @@ std::string interception_id; ASSERT_TRUE(params->GetString("interceptionId", &interception_id)); bool is_redirect = params->HasKey("redirectUrl"); - bool is_navigation; - ASSERT_TRUE(params->GetBoolean("isNavigationRequest", &is_navigation)); + absl::optional<bool> is_navigation = + params->FindBoolPath("isNavigationRequest"); + ASSERT_TRUE(is_navigation); std::string resource_type; ASSERT_TRUE(params->GetString("resourceType", &resource_type)); std::string url; @@ -212,7 +213,7 @@ // The url will typically have a random port which we want to remove. url = RemovePort(GURL(url)); - if (!is_navigation) { + if (*is_navigation) { params = std::make_unique<base::DictionaryValue>(); params->SetString("interceptionId", interception_id); SendCommand("Network.continueInterceptedRequest", std::move(params),
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 20c70c6..8d0e6bc8 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -254,6 +254,7 @@ switches::kEnableLogging, switches::kEnableDeJelly, switches::kDeJellyScreenWidth, + switches::kDocumentTransitionSlowdownFactor, switches::kDoubleBufferCompositing, switches::kHeadless, switches::kLoggingLevel,
diff --git a/content/browser/interest_group/ad_auction_service_impl.cc b/content/browser/interest_group/ad_auction_service_impl.cc index b7712e80..6d1eed72a 100644 --- a/content/browser/interest_group/ad_auction_service_impl.cc +++ b/content/browser/interest_group/ad_auction_service_impl.cc
@@ -10,8 +10,10 @@ #include "base/check.h" #include "base/containers/contains.h" #include "base/strings/stringprintf.h" +#include "base/time/time.h" #include "content/browser/devtools/devtools_instrumentation.h" #include "content/browser/interest_group/auction_runner.h" +#include "content/browser/interest_group/interest_group_manager.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/storage_partition_impl.h" #include "content/public/browser/browser_context.h" @@ -29,6 +31,7 @@ #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/interest_group/interest_group.h" #include "url/gurl.h" #include "url/origin.h" #include "url/url_constants.h" @@ -37,6 +40,8 @@ namespace { +constexpr base::TimeDelta kMaxExpiry = base::TimeDelta::FromDays(30); + constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = net::DefineNetworkTrafficAnnotation("auction_report_sender", R"( semantics { @@ -151,6 +156,59 @@ new AdAuctionServiceImpl(render_frame_host, std::move(receiver)); } +void AdAuctionServiceImpl::JoinInterestGroup( + const blink::InterestGroup& group) { + // If the interest group API is not allowed for this origin do nothing. + if (!GetContentClient()->browser()->IsInterestGroupAPIAllowed( + render_frame_host()->GetBrowserContext(), origin(), + group.owner.GetURL())) { + return; + } + + // Disallow setting interest groups for another origin. Eventually, this will + // need to perform a fetch to check for cross-origin permissions to add an + // interest group. + if (origin() != group.owner) + return; + + RenderFrameHost* main_frame = render_frame_host()->GetMainFrame(); + GURL main_frame_url = main_frame->GetLastCommittedURL(); + + blink::InterestGroup updated_group = group; + base::Time max_expiry = base::Time::Now() + kMaxExpiry; + if (updated_group.expiry > max_expiry) + updated_group.expiry = max_expiry; + GetInterestGroupManager().JoinInterestGroup(std::move(updated_group), + main_frame_url); +} + +void AdAuctionServiceImpl::LeaveInterestGroup(const url::Origin& owner, + const std::string& name) { + // If the interest group API is not allowed for this origin do nothing. + if (!GetContentClient()->browser()->IsInterestGroupAPIAllowed( + render_frame_host()->GetBrowserContext(), origin(), owner.GetURL())) { + return; + } + + if (origin().scheme() != url::kHttpsScheme) + return; + + if (owner != origin()) + return; + + GetInterestGroupManager().LeaveInterestGroup(owner, name); +} + +void AdAuctionServiceImpl::UpdateAdInterestGroups() { + // If the interest group API is not allowed for this origin do nothing. + if (!GetContentClient()->browser()->IsInterestGroupAPIAllowed( + render_frame_host()->GetBrowserContext(), origin(), + origin().GetURL())) { + return; + } + GetInterestGroupManager().UpdateInterestGroupsOfOwner(origin()); +} + void AdAuctionServiceImpl::RunAdAuction(blink::mojom::AuctionAdConfigPtr config, RunAdAuctionCallback callback) { if (!IsAuctionValid(*config)) { @@ -196,12 +254,8 @@ std::move(top_frame_origin), config->seller); std::unique_ptr<AuctionRunner> auction = AuctionRunner::CreateAndStart( - this, - static_cast<StoragePartitionImpl*>( - render_frame_host()->GetStoragePartition()) - ->GetInterestGroupManager(), - std::move(config), std::move(filtered_buyers), std::move(browser_signals), - frame_origin, + this, &GetInterestGroupManager(), std::move(config), + std::move(filtered_buyers), std::move(browser_signals), frame_origin, base::BindOnce(&AdAuctionServiceImpl::OnAuctionComplete, base::Unretained(this), std::move(callback))); auctions_.insert(std::move(auction)); @@ -285,4 +339,10 @@ FetchReport(factory, *seller_report_url, origin()); } +InterestGroupManager& AdAuctionServiceImpl::GetInterestGroupManager() const { + return *static_cast<StoragePartitionImpl*>( + render_frame_host()->GetStoragePartition()) + ->GetInterestGroupManager(); +} + } // namespace content
diff --git a/content/browser/interest_group/ad_auction_service_impl.h b/content/browser/interest_group/ad_auction_service_impl.h index 90a448a..5b600b9fc 100644 --- a/content/browser/interest_group/ad_auction_service_impl.h +++ b/content/browser/interest_group/ad_auction_service_impl.h
@@ -10,7 +10,6 @@ #include "base/containers/unique_ptr_adapters.h" #include "content/browser/interest_group/auction_runner.h" -#include "content/browser/interest_group/interest_group_manager.h" #include "content/common/content_export.h" #include "content/public/browser/document_service_base.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -24,6 +23,7 @@ namespace content { class AuctionRunner; +class InterestGroupManager; class RenderFrameHost; class RenderFrameHostImpl; @@ -39,6 +39,10 @@ mojo::PendingReceiver<blink::mojom::AdAuctionService> receiver); // blink::mojom::AdAuctionService. + void JoinInterestGroup(const blink::InterestGroup& group) override; + void LeaveInterestGroup(const url::Origin& owner, + const std::string& name) override; + void UpdateAdInterestGroups() override; void RunAdAuction(blink::mojom::AuctionAdConfigPtr config, RunAdAuctionCallback callback) override; @@ -68,6 +72,8 @@ absl::optional<GURL> seller_report_url, std::vector<std::string> errors); + InterestGroupManager& GetInterestGroupManager() const; + // This must be above `auction_worklet_service_`, since auctions may own // callbacks over the AuctionWorkletService pipe, and mojo pipes must be // destroyed before any callbacks that are bound to them.
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc index 129e1991..51ae19b 100644 --- a/content/browser/interest_group/interest_group_browsertest.cc +++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -21,7 +21,6 @@ #include "components/network_session_configurator/common/network_switches.h" #include "content/browser/interest_group/ad_auction_service_impl.h" #include "content/browser/interest_group/interest_group_manager.h" -#include "content/browser/interest_group/restricted_interest_group_store_impl.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/storage_partition_impl.h" #include "content/public/browser/browser_context.h" @@ -51,7 +50,6 @@ #include "third_party/blink/public/common/interest_group/interest_group.h" #include "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom.h" #include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h" -#include "third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom.h" #include "url/gurl.h" #include "url/origin.h" @@ -1646,6 +1644,74 @@ EXPECT_EQ(bidding_interest_groups2.front().group->signals->bid_count, 3); } +// Adding an interest group and then immediately running the ad acution, without +// waiting in between, should always work because although adding the interest +// group is async (and intentionally without completion notification), it should +// complete before the auction runs. +// +// On regression, this test will likely only fail with very low frequency. +IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, + AddInterestGroupRunAuctionWithWinnerWithoutWaiting) { + GURL test_url = https_server_->GetURL("a.test", "/echo"); + ASSERT_TRUE(NavigateToURL(shell(), test_url)); + + std::string ads = + "[{renderUrl : 'https://example.com/render'," + "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; + + // Use JoinInterestGroupInJS() instead of JoinInterestGroupAndWaitInJs(). + + EXPECT_TRUE(JoinInterestGroupInJS( + blink::InterestGroup( + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ + https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/ + https_server_->GetURL("a.test", + "/interest_group/trusted_bidding_signals.json"), + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), + ads, "['key1']")); + + EXPECT_EQ( + "https://example.com/render", + RunAuctionAndWait(JsReplace( + R"({ + seller: $1, + decisionLogicUrl: $2, + interestGroupBuyers: [$1], + auctionSignals: {x: 1}, + sellerSignals: {yet: 'more', info: 1}, + perBuyerSignals: {$1: {even: 'more', x: 4.5}} + })", + test_url.GetOrigin().spec(), + https_server_->GetURL("a.test", "/interest_group/decision_logic.js") + .spec()))); + + // Leave the interest group, then re-run the auction. We shouldn't get a + // result. + LeaveInterestGroupInJS(/*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars"); + EXPECT_EQ( + nullptr, + RunAuctionAndWait(JsReplace( + R"({ + seller: $1, + decisionLogicUrl: $2, + interestGroupBuyers: [$1], + auctionSignals: {x: 1}, + sellerSignals: {yet: 'more', info: 1}, + perBuyerSignals: {$1: {even: 'more', x: 4.5}} + })", + test_url.GetOrigin().spec(), + https_server_->GetURL("a.test", "/interest_group/decision_logic.js") + .spec()))); +} + // The winning ad's render url is invalid (invalid url or has http scheme). IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionWithInvalidAdUrl) { GURL test_url = https_server_->GetURL("a.test", "/echo"); @@ -2114,8 +2180,8 @@ ASSERT_TRUE(test_url_a.SchemeIs(url::kHttpsScheme)); ASSERT_TRUE(NavigateToURL(shell(), test_url_a)); - mojo::Remote<blink::mojom::RestrictedInterestGroupStore> interest_service; - RestrictedInterestGroupStoreImpl::CreateMojoService( + mojo::Remote<blink::mojom::AdAuctionService> interest_service; + AdAuctionServiceImpl::CreateMojoService( shell()->web_contents()->GetMainFrame(), interest_service.BindNewPipeAndPassReceiver());
diff --git a/content/browser/interest_group/restricted_interest_group_store_impl.cc b/content/browser/interest_group/restricted_interest_group_store_impl.cc deleted file mode 100644 index 33002d2..0000000 --- a/content/browser/interest_group/restricted_interest_group_store_impl.cc +++ /dev/null
@@ -1,101 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/interest_group/restricted_interest_group_store_impl.h" - -#include "base/time/time.h" -#include "content/browser/interest_group/interest_group_manager.h" -#include "content/browser/renderer_host/render_frame_host_impl.h" -#include "content/browser/storage_partition_impl.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/common/content_client.h" -#include "third_party/blink/public/common/interest_group/interest_group.h" -#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h" - -namespace content { - -namespace { - -constexpr base::TimeDelta kMaxExpiry = base::TimeDelta::FromDays(30); - -} // namespace - -RestrictedInterestGroupStoreImpl::RestrictedInterestGroupStoreImpl( - RenderFrameHost* render_frame_host, - mojo::PendingReceiver<blink::mojom::RestrictedInterestGroupStore> receiver) - : DocumentServiceBase(render_frame_host, std::move(receiver)), - interest_group_manager_(*static_cast<StoragePartitionImpl*>( - render_frame_host->GetStoragePartition()) - ->GetInterestGroupManager()) {} - -// static -void RestrictedInterestGroupStoreImpl::CreateMojoService( - RenderFrameHost* render_frame_host, - mojo::PendingReceiver<blink::mojom::RestrictedInterestGroupStore> - receiver) { - DCHECK(render_frame_host); - - // The object is bound to the lifetime of |render_frame_host| and the mojo - // connection. See DocumentServiceBase for details. - new RestrictedInterestGroupStoreImpl(render_frame_host, std::move(receiver)); -} - -void RestrictedInterestGroupStoreImpl::JoinInterestGroup( - const blink::InterestGroup& group) { - // If the interest group API is not allowed for this origin do nothing. - if (!GetContentClient()->browser()->IsInterestGroupAPIAllowed( - render_frame_host()->GetBrowserContext(), origin(), - group.owner.GetURL())) { - return; - } - - // Disallow setting interest groups for another origin. Eventually, this will - // need to perform a fetch to check for cross-origin permissions to add an - // interest group. - if (origin() != group.owner) - return; - - RenderFrameHost* main_frame = render_frame_host()->GetMainFrame(); - GURL main_frame_url = main_frame->GetLastCommittedURL(); - - blink::InterestGroup updated_group = group; - base::Time max_expiry = base::Time::Now() + kMaxExpiry; - if (updated_group.expiry > max_expiry) - updated_group.expiry = max_expiry; - interest_group_manager_.JoinInterestGroup(std::move(updated_group), - main_frame_url); -} - -void RestrictedInterestGroupStoreImpl::LeaveInterestGroup( - const url::Origin& owner, - const std::string& name) { - // If the interest group API is not allowed for this origin do nothing. - if (!GetContentClient()->browser()->IsInterestGroupAPIAllowed( - render_frame_host()->GetBrowserContext(), origin(), owner.GetURL())) { - return; - } - - if (origin().scheme() != url::kHttpsScheme) - return; - - if (owner != origin()) - return; - - interest_group_manager_.LeaveInterestGroup(owner, name); -} - -void RestrictedInterestGroupStoreImpl::UpdateAdInterestGroups() { - // If the interest group API is not allowed for this origin do nothing. - if (!GetContentClient()->browser()->IsInterestGroupAPIAllowed( - render_frame_host()->GetBrowserContext(), origin(), - origin().GetURL())) { - return; - } - interest_group_manager_.UpdateInterestGroupsOfOwner(origin()); -} - -RestrictedInterestGroupStoreImpl::~RestrictedInterestGroupStoreImpl() = default; - -} // namespace content
diff --git a/content/browser/interest_group/restricted_interest_group_store_impl.h b/content/browser/interest_group/restricted_interest_group_store_impl.h deleted file mode 100644 index 10956d2f..0000000 --- a/content/browser/interest_group/restricted_interest_group_store_impl.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_INTEREST_GROUP_RESTRICTED_INTEREST_GROUP_STORE_IMPL_H_ -#define CONTENT_BROWSER_INTEREST_GROUP_RESTRICTED_INTEREST_GROUP_STORE_IMPL_H_ - -#include "content/browser/interest_group/interest_group_manager.h" -#include "content/common/content_export.h" -#include "content/public/browser/document_service_base.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom.h" - -namespace content { - -class RenderFrameHost; - -// Implements the RestrictedInterestGroupStore service called by Blink code. -class CONTENT_EXPORT RestrictedInterestGroupStoreImpl final - : public DocumentServiceBase<blink::mojom::RestrictedInterestGroupStore> { - public: - // Factory method for creating an instance of this interface that is bound - // to the lifetime of the frame or receiver (whichever is shorter). - static void CreateMojoService( - RenderFrameHost* render_frame_host, - mojo::PendingReceiver<blink::mojom::RestrictedInterestGroupStore> - receiver); - - // blink::mojom::RestrictedInterestGroupStore. - void JoinInterestGroup(const blink::InterestGroup& group) override; - void LeaveInterestGroup(const url::Origin& owner, - const std::string& name) override; - void UpdateAdInterestGroups() override; - - private: - // `render_frame_host` must not be null, and DocumentServiceBase guarantees - // `this` will not outlive the `render_frame_host`. - RestrictedInterestGroupStoreImpl( - RenderFrameHost* render_frame_host, - mojo::PendingReceiver<blink::mojom::RestrictedInterestGroupStore> - receiver); - - // `this` can only be destroyed by DocumentServiceBase. - ~RestrictedInterestGroupStoreImpl() override; - - InterestGroupManager& interest_group_manager_; -}; - -} // namespace content - -#endif // CONTENT_BROWSER_INTEREST_GROUP_RESTRICTED_INTEREST_GROUP_STORE_IMPL_H_
diff --git a/content/browser/interest_group/restricted_interest_group_store_impl_unittest.cc b/content/browser/interest_group/restricted_interest_group_store_impl_unittest.cc index 3893ac5..0ba2b48 100644 --- a/content/browser/interest_group/restricted_interest_group_store_impl_unittest.cc +++ b/content/browser/interest_group/restricted_interest_group_store_impl_unittest.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/interest_group/restricted_interest_group_store_impl.h" +#include "content/browser/interest_group/ad_auction_service_impl.h" #include <memory> #include <string> @@ -29,8 +29,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/interest_group/interest_group.h" +#include "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom.h" #include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h" -#include "third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom.h" #include "url/gurl.h" #include "url/origin.h" @@ -144,6 +144,10 @@ } // namespace +// Tests the interest group management functionality of AdAuctionService -- this +// particular functionality used to be in a separate interface called +// RestrictedInterestStore. The interfaces were combined so so that they'd share +// a Mojo pipe (for message ordering consistency). class RestrictedInterestGroupStoreImplTest : public RenderViewHostTestHarness { public: RestrictedInterestGroupStoreImplTest() @@ -199,18 +203,18 @@ return 0; } - // Create a new RestrictedInterestGroupStoreImpl and use it to try and join + // Create a new AdAuctionServiceImpl and use it to try and join // `interest_group`. Flushes the Mojo pipe to force the Mojo message to be // handled before returning. // - // Creates a new RestrictedInterestGroupStoreImpl with each call so the RFH + // Creates a new AdAuctionServiceImpl with each call so the RFH // can be navigated between different sites. And - // RestrictedInterestGroupStoreImpl only handles one site (cross site navs use + // AdAuctionServiceImpl only handles one site (cross site navs use // different RestrictedInterestGroupStoreImpls, and generally use different // RFHs as well). void JoinInterestGroupAndFlush(const blink::InterestGroup& interest_group) { - mojo::Remote<blink::mojom::RestrictedInterestGroupStore> interest_service; - RestrictedInterestGroupStoreImpl::CreateMojoService( + mojo::Remote<blink::mojom::AdAuctionService> interest_service; + AdAuctionServiceImpl::CreateMojoService( web_contents()->GetMainFrame(), interest_service.BindNewPipeAndPassReceiver()); @@ -222,8 +226,8 @@ // instead of joining one. void LeaveInterestGroupAndFlush(const url::Origin& owner, const std::string& name) { - mojo::Remote<blink::mojom::RestrictedInterestGroupStore> interest_service; - RestrictedInterestGroupStoreImpl::CreateMojoService( + mojo::Remote<blink::mojom::AdAuctionService> interest_service; + AdAuctionServiceImpl::CreateMojoService( web_contents()->GetMainFrame(), interest_service.BindNewPipeAndPassReceiver()); @@ -235,8 +239,8 @@ // URL. Doesn't flush since the update operation requires a sequence of // asynchronous operations. void UpdateInterestGroupNoFlush() { - mojo::Remote<blink::mojom::RestrictedInterestGroupStore> interest_service; - RestrictedInterestGroupStoreImpl::CreateMojoService( + mojo::Remote<blink::mojom::AdAuctionService> interest_service; + AdAuctionServiceImpl::CreateMojoService( web_contents()->GetMainFrame(), interest_service.BindNewPipeAndPassReceiver());
diff --git a/content/browser/loader/cross_origin_read_blocking_checker.cc b/content/browser/loader/cross_origin_read_blocking_checker.cc index c6a819af..7be352b 100644 --- a/content/browser/loader/cross_origin_read_blocking_checker.cc +++ b/content/browser/loader/cross_origin_read_blocking_checker.cc
@@ -159,7 +159,7 @@ return; } base::StringPiece data(buffer->data(), bytes_read); - corb_analyzer_->SniffResponseBody(data, 0); + corb_analyzer_->SniffResponseBody(data); if (corb_analyzer_->ShouldBlock()) { OnBlocked(); return;
diff --git a/content/browser/media/active_media_session_controller.cc b/content/browser/media/active_media_session_controller.cc index 3e5a986..04026af 100644 --- a/content/browser/media/active_media_session_controller.cc +++ b/content/browser/media/active_media_session_controller.cc
@@ -199,6 +199,7 @@ case MediaSessionAction::kToggleCamera: case MediaSessionAction::kHangUp: case MediaSessionAction::kRaise: + case MediaSessionAction::kSetMute: NOTREACHED(); return; } @@ -251,6 +252,7 @@ case MediaSessionAction::kToggleCamera: case MediaSessionAction::kHangUp: case MediaSessionAction::kRaise: + case MediaSessionAction::kSetMute: return absl::nullopt; } }
diff --git a/content/browser/media/media_web_contents_observer.cc b/content/browser/media/media_web_contents_observer.cc index 180d5b8..6bc9670 100644 --- a/content/browser/media/media_web_contents_observer.cc +++ b/content/browser/media/media_web_contents_observer.cc
@@ -337,6 +337,9 @@ media_web_contents_observer_->web_contents_impl()->MediaMutedStatusChanged( media_player_id_, muted); + media_web_contents_observer_->session_controllers_manager() + ->OnMediaMutedStatusChanged(media_player_id_, muted); + PlayerInfo* player_info = GetPlayerInfo(); if (!player_info) return;
diff --git a/content/browser/media/session/media_session_controller.cc b/content/browser/media/session/media_session_controller.cc index 0d8e483..5ece795 100644 --- a/content/browser/media/session/media_session_controller.cc +++ b/content/browser/media/session/media_session_controller.cc
@@ -141,6 +141,14 @@ ->SetAudioSinkId(hashed_sink_id); } +void MediaSessionController::OnSetMute(int player_id, bool mute) { + DCHECK_EQ(player_id_, player_id); + + web_contents_->media_web_contents_observer() + ->GetMediaPlayerRemote(id_) + ->RequestMute(mute); +} + RenderFrameHost* MediaSessionController::render_frame_host() const { return RenderFrameHost::FromID(id_.frame_routing_id); } @@ -185,6 +193,10 @@ media_session_->RebuildAndNotifyMediaPositionChanged(); } +void MediaSessionController::OnMediaMutedStatusChanged(bool mute) { + media_session_->OnMediaMutedStatusChanged(mute); +} + void MediaSessionController::OnPictureInPictureAvailabilityChanged( bool available) { is_picture_in_picture_available_ = available;
diff --git a/content/browser/media/session/media_session_controller.h b/content/browser/media/session/media_session_controller.h index 907f2a0..ae06260 100644 --- a/content/browser/media/session/media_session_controller.h +++ b/content/browser/media/session/media_session_controller.h
@@ -60,6 +60,7 @@ void OnExitPictureInPicture(int player_id) override; void OnSetAudioSinkId(int player_id, const std::string& raw_device_id) override; + void OnSetMute(int player_id, bool mute) override; RenderFrameHost* render_frame_host() const override; absl::optional<media_session::MediaPosition> GetPosition( int player_id) const override; @@ -82,6 +83,8 @@ void OnMediaPositionStateChanged( const media_session::MediaPosition& position); + void OnMediaMutedStatusChanged(bool mute); + // Called when the media picture-in-picture availability has changed. void OnPictureInPictureAvailabilityChanged(bool available);
diff --git a/content/browser/media/session/media_session_controller_unittest.cc b/content/browser/media/session/media_session_controller_unittest.cc index d6a3a9d..75c92ab 100644 --- a/content/browser/media/session/media_session_controller_unittest.cc +++ b/content/browser/media/session/media_session_controller_unittest.cc
@@ -138,6 +138,8 @@ void RequestExitPictureInPicture() override {} + void RequestMute(bool mute) override {} + void SetVolumeMultiplier(double multiplier) override { received_volume_multiplier_ = multiplier; if (run_loop_for_volume_)
diff --git a/content/browser/media/session/media_session_controllers_manager.cc b/content/browser/media/session/media_session_controllers_manager.cc index 39a20474..15f877e 100644 --- a/content/browser/media/session/media_session_controllers_manager.cc +++ b/content/browser/media/session/media_session_controllers_manager.cc
@@ -104,6 +104,16 @@ entry.second->WebContentsMutedStateChanged(muted); } +void MediaSessionControllersManager::OnMediaMutedStatusChanged( + const MediaPlayerId& id, + bool mute) { + if (!IsMediaSessionEnabled()) + return; + + MediaSessionController* const controller = FindOrCreateController(id); + controller->OnMediaMutedStatusChanged(mute); +} + void MediaSessionControllersManager::OnPictureInPictureAvailabilityChanged( const MediaPlayerId& id, bool available) {
diff --git a/content/browser/media/session/media_session_controllers_manager.h b/content/browser/media/session/media_session_controllers_manager.h index e3490c4c..59db437 100644 --- a/content/browser/media/session/media_session_controllers_manager.h +++ b/content/browser/media/session/media_session_controllers_manager.h
@@ -67,6 +67,9 @@ // Called when the WebContents was muted or unmuted. void WebContentsMutedStateChanged(bool muted); + // Called when the player's mute status changed. + void OnMediaMutedStatusChanged(const MediaPlayerId& id, bool mute); + // Called when picture-in-picture availability for the player |id| has // changed. void OnPictureInPictureAvailabilityChanged(const MediaPlayerId& id,
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc index 83da123..202ae27c 100644 --- a/content/browser/media/session/media_session_impl.cc +++ b/content/browser/media/session/media_session_impl.cc
@@ -149,6 +149,8 @@ return MediaSessionUserAction::kHangUp; case media_session::mojom::MediaSessionAction::kRaise: return MediaSessionUserAction::kRaise; + case media_session::mojom::MediaSessionAction::kSetMute: + return MediaSessionUserAction::kSetMute; } NOTREACHED(); return MediaSessionUserAction::kPlay; @@ -1013,6 +1015,8 @@ info->camera_state = media_session::mojom::CameraState::kUnknown; } + info->muted = is_muted_; + return info; } @@ -1173,6 +1177,12 @@ delegate->ActivateContents(web_contents()); } +void MediaSessionImpl::SetMute(bool mute) { + DCHECK_EQ(normal_players_.size(), 1u); + normal_players_.begin()->first.observer->OnSetMute( + normal_players_.begin()->first.player_id, mute); +} + void MediaSessionImpl::GetMediaImageBitmap( const media_session::MediaImage& image, int minimum_size_px, @@ -1481,6 +1491,11 @@ return best_frame ? services_[best_frame->GetGlobalId()] : nullptr; } +void MediaSessionImpl::OnMediaMutedStatusChanged(bool mute) { + is_muted_ = mute; + RebuildAndNotifyMediaSessionInfoChanged(); +} + void MediaSessionImpl::OnPictureInPictureAvailabilityChanged() { if (normal_players_.size() != 1) return;
diff --git a/content/browser/media/session/media_session_impl.h b/content/browser/media/session/media_session_impl.h index 5b1693b..67e5f9a 100644 --- a/content/browser/media/session/media_session_impl.h +++ b/content/browser/media/session/media_session_impl.h
@@ -279,6 +279,9 @@ // Brings the associated tab into focus. void Raise() override; + // Mute or unmute the media player. + void SetMute(bool mute) override; + // Downloads the bitmap version of a MediaImage at least |minimum_size_px| // and closest to |desired_size_px|. If the download failed, was too small or // the image did not come from the media session then returns a null image. @@ -292,6 +295,8 @@ return audio_focus_group_id_; } + void OnMediaMutedStatusChanged(bool mute); + void OnPictureInPictureAvailabilityChanged(); // Called when any of the normal players have switched to a different audio @@ -481,6 +486,8 @@ // True if the WebContents associated with this MediaSessionImpl is focused. bool focused_ = false; + bool is_muted_ = false; + // Used to persist audio device selection between navigations on the same // origin. url::Origin origin_;
diff --git a/content/browser/media/session/media_session_impl_service_routing_unittest.cc b/content/browser/media/session/media_session_impl_service_routing_unittest.cc index 4479f297..3f23f7e 100644 --- a/content/browser/media/session/media_session_impl_service_routing_unittest.cc +++ b/content/browser/media/session/media_session_impl_service_routing_unittest.cc
@@ -58,6 +58,7 @@ MOCK_METHOD1(OnExitPictureInPicture, void(int player_id)); MOCK_METHOD2(OnSetAudioSinkId, void(int player_id, const std::string& raw_device_id)); + MOCK_METHOD2(OnSetMute, void(int player_id, bool mute)); absl::optional<media_session::MediaPosition> GetPosition( int player_id) const override {
diff --git a/content/browser/media/session/media_session_impl_uma_unittest.cc b/content/browser/media/session/media_session_impl_uma_unittest.cc index 468039d..c08ab9d 100644 --- a/content/browser/media/session/media_session_impl_uma_unittest.cc +++ b/content/browser/media/session/media_session_impl_uma_unittest.cc
@@ -44,6 +44,7 @@ void OnExitPictureInPicture(int player_id) override {} void OnSetAudioSinkId(int player_id, const std::string& raw_device_id) override {} + void OnSetMute(int player_id, bool mute) override {} absl::optional<media_session::MediaPosition> GetPosition( int player_id) const override {
diff --git a/content/browser/media/session/media_session_player_observer.h b/content/browser/media/session/media_session_player_observer.h index b327e59..f45351d 100644 --- a/content/browser/media/session/media_session_player_observer.h +++ b/content/browser/media/session/media_session_player_observer.h
@@ -52,6 +52,9 @@ virtual void OnSetAudioSinkId(int player_id, const std::string& raw_device_id) = 0; + // The given |player_id| has been requested to mute or unmute. + virtual void OnSetMute(int player_id, bool mute) = 0; + // Returns the position for |player_id|. virtual absl::optional<media_session::MediaPosition> GetPosition( int player_id) const = 0;
diff --git a/content/browser/media/session/media_session_service_impl_browsertest.cc b/content/browser/media/session/media_session_service_impl_browsertest.cc index 0229ad6..c047c6e 100644 --- a/content/browser/media/session/media_session_service_impl_browsertest.cc +++ b/content/browser/media/session/media_session_service_impl_browsertest.cc
@@ -61,6 +61,7 @@ void OnExitPictureInPicture(int player_id) override {} void OnSetAudioSinkId(int player_id, const std::string& raw_device_id) override {} + void OnSetMute(int player_id, bool mute) override {} absl::optional<media_session::MediaPosition> GetPosition( int player_id) const override {
diff --git a/content/browser/media/session/media_session_uma_helper.h b/content/browser/media/session/media_session_uma_helper.h index fada329..b8de023 100644 --- a/content/browser/media/session/media_session_uma_helper.h +++ b/content/browser/media/session/media_session_uma_helper.h
@@ -50,7 +50,8 @@ kToggleCamera = 17, kHangUp = 18, kRaise = 19, - kMaxValue = kRaise, + kSetMute = 20, + kMaxValue = kSetMute, }; MediaSessionUmaHelper();
diff --git a/content/browser/media/session/mock_media_session_player_observer.cc b/content/browser/media/session/mock_media_session_player_observer.cc index 2a7e548..2ef49f4 100644 --- a/content/browser/media/session/mock_media_session_player_observer.cc +++ b/content/browser/media/session/mock_media_session_player_observer.cc
@@ -89,6 +89,11 @@ players_[player_id].audio_sink_id_ = raw_device_id; } +void MockMediaSessionPlayerObserver::OnSetMute(int player_id, bool mute) { + EXPECT_GE(player_id, 0); + EXPECT_GT(players_.size(), static_cast<size_t>(player_id)); +} + absl::optional<media_session::MediaPosition> MockMediaSessionPlayerObserver::GetPosition(int player_id) const { EXPECT_GE(player_id, 0);
diff --git a/content/browser/media/session/mock_media_session_player_observer.h b/content/browser/media/session/mock_media_session_player_observer.h index 09b0747..dfd3890 100644 --- a/content/browser/media/session/mock_media_session_player_observer.h +++ b/content/browser/media/session/mock_media_session_player_observer.h
@@ -34,6 +34,7 @@ void OnExitPictureInPicture(int player_id) override; void OnSetAudioSinkId(int player_id, const std::string& raw_device_id) override; + void OnSetMute(int player_id, bool mute) override; absl::optional<media_session::MediaPosition> GetPosition( int player_id) const override; bool IsPictureInPictureAvailable(int player_id) const override;
diff --git a/content/browser/media/session/pepper_player_delegate.cc b/content/browser/media/session/pepper_player_delegate.cc index e50b05f..95734aea 100644 --- a/content/browser/media/session/pepper_player_delegate.cc +++ b/content/browser/media/session/pepper_player_delegate.cc
@@ -80,6 +80,8 @@ NOTREACHED(); } +void PepperPlayerDelegate::OnSetMute(int player_id, bool mute) {} + absl::optional<media_session::MediaPosition> PepperPlayerDelegate::GetPosition( int player_id) const { // Pepper does not support position data.
diff --git a/content/browser/media/session/pepper_player_delegate.h b/content/browser/media/session/pepper_player_delegate.h index a5991aa..2e595a1c 100644 --- a/content/browser/media/session/pepper_player_delegate.h +++ b/content/browser/media/session/pepper_player_delegate.h
@@ -34,6 +34,7 @@ void OnExitPictureInPicture(int player_id) override; void OnSetAudioSinkId(int player_id, const std::string& raw_device_id) override; + void OnSetMute(int player_id, bool mute) override; absl::optional<media_session::MediaPosition> GetPosition( int player_id) const override; bool IsPictureInPictureAvailable(int player_id) const override;
diff --git a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc index 8643b5f..3245e7a2e 100644 --- a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc +++ b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
@@ -130,6 +130,7 @@ void RequestSeekTo(base::TimeDelta seek_time) override {} void RequestEnterPictureInPicture() override {} void RequestExitPictureInPicture() override {} + void RequestMute(bool mute) override {} void SetVolumeMultiplier(double multiplier) override {} void SetPersistentState(bool persistent) override {} void SetPowerExperimentState(bool enabled) override {}
diff --git a/content/browser/service_worker/service_worker_internals_ui.cc b/content/browser/service_worker/service_worker_internals_ui.cc index 72f6472..b1f0aa2a 100644 --- a/content/browser/service_worker/service_worker_internals_ui.cc +++ b/content/browser/service_worker/service_worker_internals_ui.cc
@@ -492,14 +492,23 @@ } void ServiceWorkerInternalsHandler::HandleSetOption(const ListValue* args) { - std::string option_name; - bool option_boolean; - if (!args->GetString(0, &option_name) || option_name != "debug_on_start" || - !args->GetBoolean(1, &option_boolean)) { + auto args_list = args->GetList(); + if (args_list.size() < 2) { + return; + } + + if (!args_list[0].is_string()) { + return; + } + if (args_list[0].GetString() != "debug_on_start") { + return; + } + + if (!args_list[1].is_bool()) { return; } ServiceWorkerDevToolsManager::GetInstance() - ->set_debug_service_worker_on_start(option_boolean); + ->set_debug_service_worker_on_start(args_list[1].GetBool()); } void ServiceWorkerInternalsHandler::HandleGetAllRegistrations(
diff --git a/content/browser/service_worker/service_worker_test_utils.h b/content/browser/service_worker/service_worker_test_utils.h index 73b16604..274d28d 100644 --- a/content/browser/service_worker/service_worker_test_utils.h +++ b/content/browser/service_worker/service_worker_test_utils.h
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/containers/queue.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "components/services/storage/public/mojom/service_worker_storage_control.mojom.h"
diff --git a/content/browser/tracing/background_tracing_config_impl.cc b/content/browser/tracing/background_tracing_config_impl.cc index 5761ebb..c998ce4 100644 --- a/content/browser/tracing/background_tracing_config_impl.cc +++ b/content/browser/tracing/background_tracing_config_impl.cc
@@ -224,10 +224,9 @@ if (config) { dict->GetString(kConfigScenarioName, &config->scenario_name_); config->SetBufferSizeLimits(dict); - bool value = false; - if (dict->GetBoolean(kConfigTraceBrowserProcessOnly, &value)) { - config->trace_browser_process_only_ = value; - } + config->trace_browser_process_only_ = + dict->FindBoolPath(kConfigTraceBrowserProcessOnly) + .value_or(config->trace_browser_process_only_); } return config;
diff --git a/content/browser/tracing/background_tracing_rule.cc b/content/browser/tracing/background_tracing_rule.cc index ae231ae2..7cc273b 100644 --- a/content/browser/tracing/background_tracing_rule.cc +++ b/content/browser/tracing/background_tracing_rule.cc
@@ -120,14 +120,15 @@ void BackgroundTracingRule::Setup(const base::DictionaryValue* dict) { dict->GetDouble(kConfigRuleTriggerChance, &trigger_chance_); dict->GetInteger(kConfigRuleTriggerDelay, &trigger_delay_); - dict->GetBoolean(kConfigRuleStopTracingOnRepeatedReactive, - &stop_tracing_on_repeated_reactive_); + stop_tracing_on_repeated_reactive_ = + dict->FindBoolPath(kConfigRuleStopTracingOnRepeatedReactive) + .value_or(stop_tracing_on_repeated_reactive_); if (dict->HasKey(kConfigRuleIdKey)) { dict->GetString(kConfigRuleIdKey, &rule_id_); } else { rule_id_ = GetDefaultRuleId(); } - dict->GetBoolean(kConfigIsCrashKey, &is_crash_); + is_crash_ = dict->FindBoolPath(kConfigIsCrashKey).value_or(is_crash_); } namespace { @@ -212,8 +213,8 @@ return nullptr; // Optional parameter, so we don't need to check if the key exists. - bool repeat = true; - dict->GetBoolean(kConfigRuleHistogramRepeatKey, &repeat); + bool repeat = + dict->FindBoolPath(kConfigRuleHistogramRepeatKey).value_or(true); int histogram_lower_value; int histogram_upper_value = std::numeric_limits<int>::max();
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index c993ec371..df67db0 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -886,6 +886,7 @@ test_case.inputs.client_id, test_case.inputs.nonce, test_case.inputs.mode, test_case.inputs.prefer_auto_sign_in); + ASSERT_FALSE(displayed_accounts.empty()); EXPECT_EQ(displayed_accounts[0].login_state, LoginState::kSignUp); EXPECT_EQ(auth_response.second.value(), kToken); }
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index e442953..2dbf5376 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -353,6 +353,13 @@ crbug.com/1170369 [ linux skia-renderer-dawn ] Pixel_WebGLPreservedAfterTabSwitch [ Failure ] crbug.com/1170369 [ win skia-renderer-dawn ] Pixel_WebGLPreservedAfterTabSwitch [ Failure ] +# Failure on dawn_pixel_skia_gold_test on Linux. However they are currently detecting +# skia-renderer-disabled. We will need to update these expectations after fixing the detections. +crbug.com/1240840 [ linux skia-renderer-disabled ] Pixel_OffscreenCanvasWebGLSoftwareCompositing [ Failure ] +crbug.com/1240840 [ linux skia-renderer-disabled ] Pixel_OffscreenCanvasWebGLSoftwareCompositingWorker [ Failure ] +crbug.com/1240840 [ linux skia-renderer-disabled ] Pixel_RepeatedWebGLTo2D_SoftwareCompositing [ Failure ] +crbug.com/1240840 [ linux skia-renderer-disabled ] Pixel_WebGLReadPixelsTabSwitch_SoftwareCompositing [ Failure ] + # Failure of dawn_pixel_skia_gold_test on win dawn crbug.com/1228694 [ win skia-renderer-dawn ] Pixel_CSS3DBlueBox [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 0bc3aa7..91e6609 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -872,6 +872,7 @@ crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/resize_01.html [ Failure ] crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/resize_02.html [ Failure ] crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/resize_03.html [ Failure ] +crbug.com/1215698 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/fborender/shared_depth_stencil.html [ Failure ] crbug.com/1218157 [ chromeos chromeos-board-kevin no-passthrough ] conformance/offscreencanvas/context-lost-restored.html [ Failure ] crbug.com/1218157 [ chromeos chromeos-board-kevin no-passthrough ] conformance/offscreencanvas/context-lost-restored-worker.html [ Failure ] crbug.com/1218162 [ chromeos chromeos-board-kevin no-passthrough ] deqp/functional/gles3/uniformbuffers/instance_array_basic_type.html [ Failure ] @@ -896,6 +897,28 @@ crbug.com/1219024 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/rendering/framebuffer-render-to-layer.html [ Failure ] crbug.com/1219055 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/misc/generate-mipmap-with-large-base-level.html [ Failure ] crbug.com/1219057 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/buffers/uniform-buffers.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/canvas/webgl-to-2d-canvas.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/context/context-attribute-preserve-drawing-buffer.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/context/context-creation-and-destruction.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/atan/atan_001_to_008.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/struct/struct_049_to_056.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/ogles/GL/swizzlers/swizzlers_009_to_016.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/rendering/color-mask-preserved-during-implicit-clears.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance/textures/webgl_canvas/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/rendering/clear-func-buffer-type-match.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/image_bitmap_from_video/tex-2d-r32f-red-float.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/image_bitmap_from_video/tex-2d-rgba16f-rgba-half_float.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/image_bitmap_from_video/tex-2d-srgb8-rgb-unsigned_byte.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-r16f-red-half_float.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-r8ui-red_integer-unsigned_byte.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgb16f-rgb-half_float.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgb32f-rgb-float.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html [ Failure ] +crbug.com/1212917 [ chromeos chromeos-board-kevin no-passthrough ] conformance2/textures/video/tex-2d-rgba4-rgba-unsigned_byte.html [ Failure ] ############################## # Lacros-like Linux Failures # @@ -908,7 +931,13 @@ crbug.com/1215700 [ linux intel display-server-wayland no-passthrough ] deqp/functional/gles3/negativetextureapi.html [ Failure ] crbug.com/1218607 [ linux intel display-server-wayland no-passthrough ] conformance2/reading/read-pixels-from-fbo-test.html [ Failure ] crbug.com/1231736 [ linux intel display-server-wayland no-passthrough ] deqp/functional/gles3/clipping.html [ Failure ] - +crbug.com/1240707 [ linux intel display-server-wayland no-passthrough ] conformance2/textures/video/tex-2d-rg8ui-rg_integer-unsigned_byte.html [ RetryOnFailure ] +crbug.com/1240707 [ linux intel display-server-wayland no-passthrough ] conformance2/textures/video/tex-2d-rgb10_a2-rgba-unsigned_int_2_10_10_10_rev.html [ RetryOnFailure ] +crbug.com/1240707 [ linux intel display-server-wayland no-passthrough ] conformance2/textures/video/tex-2d-rgb565-rgb-unsigned_byte.html [ RetryOnFailure ] +crbug.com/1240707 [ linux intel display-server-wayland no-passthrough ] conformance2/textures/video/tex-2d-rgba16f-rgba-float.html [ RetryOnFailure ] +crbug.com/1240707 [ linux intel display-server-wayland no-passthrough ] conformance2/textures/video/tex-3d-r32f-red-float.html [ RetryOnFailure ] +crbug.com/1240707 [ linux intel display-server-wayland no-passthrough ] conformance2/textures/video/tex-3d-rg16f-rg-float.html [ RetryOnFailure ] +crbug.com/1240707 [ linux intel display-server-wayland no-passthrough ] conformance2/textures/video/tex-3d-rg16f-rg-half_float.html [ RetryOnFailure ] # Conflicting expectations to test that the # "Expectations have no collisions" unittest works.
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index b2bf2a8..d9ea6bd2 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -541,6 +541,8 @@ # Introduced by upstreaming Apple's direct-to-metal backend crbug.com/angleproject/5505 [ mac apple-angle-metal-renderer:-apple-m1 angle-metal ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ] crbug.com/angleproject/5505 [ mac apple-angle-metal-renderer:-apple-m1 angle-metal ] conformance/rendering/multisample-corruption.html [ Failure ] +# No active browser window, but no crash stack. +crbug.com/1240443 [ mac apple-apple-m1 passthrough angle-opengl ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ RetryOnFailure ] #################### # Linux failures #
diff --git a/content/web_test/common/web_test_runtime_flags.h b/content/web_test/common/web_test_runtime_flags.h index e83871d..fcd6e8e 100644 --- a/content/web_test/common/web_test_runtime_flags.h +++ b/content/web_test/common/web_test_runtime_flags.h
@@ -26,13 +26,12 @@ TrackedDictionary& tracked_dictionary() { return dict_; } -#define DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(name) \ - bool name() const { \ - bool result; \ - bool found = dict_.current_values().GetBoolean(#name, &result); \ - DCHECK(found); \ - return result; \ - } \ +#define DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(name) \ + bool name() const { \ + absl::optional<bool> result = dict_.current_values().FindBoolPath(#name); \ + DCHECK(result); \ + return *result; \ + } \ void set_##name(bool new_value) { dict_.SetBoolean(#name, new_value); } #define DEFINE_STRING_WEB_TEST_RUNTIME_FLAG(name) \
diff --git a/device/BUILD.gn b/device/BUILD.gn index c39566b..ef0f077 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -258,6 +258,7 @@ "bluetooth/bluez/bluetooth_socket_bluez_unittest.cc", "bluetooth/dbus/bluetooth_gatt_application_service_provider_unittest.cc", "bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_unittest.cc", + "bluetooth/floss/floss_manager_client_unittest.cc", "bluetooth/test/bluetooth_test_bluez.cc", "bluetooth/test/bluetooth_test_bluez.h", ]
diff --git a/device/bluetooth/floss/floss_dbus_client.cc b/device/bluetooth/floss/floss_dbus_client.cc index a9a96d8..e73dadc 100644 --- a/device/bluetooth/floss/floss_dbus_client.cc +++ b/device/bluetooth/floss/floss_dbus_client.cc
@@ -39,7 +39,7 @@ const char kGetFlossEnabled[] = "GetFlossEnabled"; const char kSetFlossEnabled[] = "SetFlossEnabled"; const char kGetState[] = "GetState"; -const char kListHciDevices[] = "ListHciDevices"; +const char kGetAvailableAdapters[] = "GetAvailableAdapters"; const char kRegisterCallback[] = "RegisterCallback"; const char kCallbackInterface[] = "org.chromium.bluetooth.ManagerCallback"; const char kOnHciDeviceChanged[] = "OnHciDeviceChanged"; @@ -89,4 +89,27 @@ return result; } +void FlossDBusClient::DefaultResponseWithCallback( + ResponseCallback callback, + dbus::Response* response, + dbus::ErrorResponse* error_response) { + if (response) { + std::move(callback).Run(absl::nullopt); + return; + } + + std::move(callback).Run(ErrorResponseToError( + kErrorNoResponse, /*default_message=*/std::string(), error_response)); +} + +void FlossDBusClient::DefaultResponse(const std::string& caller, + dbus::Response* response, + dbus::ErrorResponse* error_response) { + if (error_response) { + FlossDBusClient::LogErrorResponse(caller, error_response); + } else { + DVLOG(1) << caller << "::OnResponse"; + } +} + } // namespace floss
diff --git a/device/bluetooth/floss/floss_dbus_client.h b/device/bluetooth/floss/floss_dbus_client.h index dfce9ef..7b63957 100644 --- a/device/bluetooth/floss/floss_dbus_client.h +++ b/device/bluetooth/floss/floss_dbus_client.h
@@ -8,48 +8,50 @@ #include <string> #include "base/callback.h" +#include "device/bluetooth/bluetooth_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace dbus { class Bus; +class Response; class ErrorResponse; } // namespace dbus namespace floss { // TODO(b/189499077) - Expose via floss package -extern const char kAdapterService[]; -extern const char kAdapterInterface[]; -extern const char kManagerInterface[]; -extern const char kManagerObject[]; -extern const char kAdapterObjectFormat[]; +extern DEVICE_BLUETOOTH_EXPORT const char kAdapterService[]; +extern DEVICE_BLUETOOTH_EXPORT const char kAdapterInterface[]; +extern DEVICE_BLUETOOTH_EXPORT const char kManagerInterface[]; +extern DEVICE_BLUETOOTH_EXPORT const char kManagerObject[]; +extern DEVICE_BLUETOOTH_EXPORT const char kAdapterObjectFormat[]; namespace adapter { -extern const char kGetAddress[]; -extern const char kStartDiscovery[]; -extern const char kCancelDiscovery[]; -extern const char kCreateBond[]; -extern const char kRegisterCallback[]; -extern const char kCallbackInterface[]; +extern DEVICE_BLUETOOTH_EXPORT const char kGetAddress[]; +extern DEVICE_BLUETOOTH_EXPORT const char kStartDiscovery[]; +extern DEVICE_BLUETOOTH_EXPORT const char kCancelDiscovery[]; +extern DEVICE_BLUETOOTH_EXPORT const char kCreateBond[]; +extern DEVICE_BLUETOOTH_EXPORT const char kRegisterCallback[]; +extern DEVICE_BLUETOOTH_EXPORT const char kCallbackInterface[]; -extern const char kOnAddressChanged[]; -extern const char kOnDeviceFound[]; -extern const char kOnDiscoveringChanged[]; -extern const char kOnSspRequest[]; +extern DEVICE_BLUETOOTH_EXPORT const char kOnAddressChanged[]; +extern DEVICE_BLUETOOTH_EXPORT const char kOnDeviceFound[]; +extern DEVICE_BLUETOOTH_EXPORT const char kOnDiscoveringChanged[]; +extern DEVICE_BLUETOOTH_EXPORT const char kOnSspRequest[]; } // namespace adapter namespace manager { -extern const char kStart[]; -extern const char kStop[]; -extern const char kGetFlossEnabled[]; -extern const char kSetFlossEnabled[]; -extern const char kGetState[]; -extern const char kListHciDevices[]; -extern const char kRegisterCallback[]; -extern const char kCallbackInterface[]; +extern DEVICE_BLUETOOTH_EXPORT const char kStart[]; +extern DEVICE_BLUETOOTH_EXPORT const char kStop[]; +extern DEVICE_BLUETOOTH_EXPORT const char kGetFlossEnabled[]; +extern DEVICE_BLUETOOTH_EXPORT const char kSetFlossEnabled[]; +extern DEVICE_BLUETOOTH_EXPORT const char kGetState[]; +extern DEVICE_BLUETOOTH_EXPORT const char kGetAvailableAdapters[]; +extern DEVICE_BLUETOOTH_EXPORT const char kRegisterCallback[]; +extern DEVICE_BLUETOOTH_EXPORT const char kCallbackInterface[]; -extern const char kOnHciDeviceChanged[]; -extern const char kOnHciEnabledChanged[]; +extern DEVICE_BLUETOOTH_EXPORT const char kOnHciDeviceChanged[]; +extern DEVICE_BLUETOOTH_EXPORT const char kOnHciEnabledChanged[]; } // namespace manager // BluetoothDevice structure for DBus apis. @@ -81,6 +83,11 @@ FlossDBusClient(const FlossDBusClient&) = delete; FlossDBusClient& operator=(const FlossDBusClient&) = delete; + // Common init signature for all clients. + virtual void Init(dbus::Bus* bus, + const std::string& bluetooth_service_name, + const std::string& bluetooth_adapter_path) = 0; + protected: // Convert a dbus::ErrorResponse into a floss::Error struct. static Error ErrorResponseToError(const std::string& default_name, @@ -90,15 +97,21 @@ FlossDBusClient(); virtual ~FlossDBusClient(); - virtual void Init(dbus::Bus* bus, - const std::string& bluetooth_service_name, - const std::string& bluetooth_adapter_path) = 0; - // Log a dbus::ErrorResponse. void LogErrorResponse(const std::string& message, dbus::ErrorResponse* error); - private: - friend class FlossDBusManager; + // Default handler that runs |callback| with the callback with an optional + // error. + void DefaultResponseWithCallback(ResponseCallback callback, + dbus::Response* response, + dbus::ErrorResponse* error_response); + + // Default handler for a response. It will either log the error response or + // print |caller| to VLOG. |caller| should be the name of the DBus method that + // is being called. + void DefaultResponse(const std::string& caller, + dbus::Response* response, + dbus::ErrorResponse* error_response); }; } // namespace floss
diff --git a/device/bluetooth/floss/floss_manager_client.cc b/device/bluetooth/floss/floss_manager_client.cc index a17b670..5e5275e08 100644 --- a/device/bluetooth/floss/floss_manager_client.cc +++ b/device/bluetooth/floss/floss_manager_client.cc
@@ -13,394 +13,71 @@ #include "base/callback.h" #include "base/callback_helpers.h" #include "base/containers/contains.h" -#include "base/containers/flat_map.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "dbus/bus.h" #include "dbus/exported_object.h" #include "dbus/message.h" -#include "dbus/object_manager.h" #include "dbus/object_proxy.h" #include "device/bluetooth/floss/floss_dbus_client.h" namespace floss { namespace { -constexpr char kExportedManagerPath[] = "/org/chromium/bluetooth/managerclient"; constexpr char kUnknownManagerError[] = "org.chromium.Error.UnknownManager"; -constexpr char kObjectManagerPath[] = "/"; +constexpr char kHciInterfaceKey[] = "hci_interface"; +constexpr char kEnabledKey[] = "enabled"; + +bool ParseAdapterWithEnabled(dbus::MessageReader& array, + int* adapter, + bool* enabled) { + dbus::MessageReader dict(nullptr); + bool found_adapter = false; + bool found_enabled = false; + + while (array.PopDictEntry(&dict)) { + std::string key; + dict.PopString(&key); + + if (key == kHciInterfaceKey) { + found_adapter = dict.PopVariantOfInt32(adapter); + } else if (key == kEnabledKey) { + found_enabled = dict.PopVariantOfBool(enabled); + } + } + + return found_adapter && found_enabled; +} + +void HandleExported(const std::string& method_name, + const std::string& interface_name, + const std::string& object_path, + bool success) { + DVLOG(1) << (success ? "Successfully exported " : "Failed to export ") + << method_name << " on interface = " << interface_name + << ", object = " << object_path; +} + } // namespace -class FlossManagerClientImpl : public FlossManagerClient, - public dbus::ObjectManager::Interface { - public: - FlossManagerClientImpl() = default; - ~FlossManagerClientImpl() override { - if (object_manager_) { - object_manager_->UnregisterInterface(kManagerInterface); - } +// static +const char FlossManagerClient::kExportedCallbacksPath[] = + "/org/chromium/bluetooth/managerclient"; - if (bus_) { - bus_->UnregisterExportedObject(dbus::ObjectPath(kExportedManagerPath)); - } - } - - std::vector<int> GetAdapters() const override { - std::vector<int> adapters; - for (auto kv : adapter_to_powered_) { - adapters.push_back(kv.first); - } - - return adapters; - } - - int GetDefaultAdapter() const override { return default_adapter_; } - - bool GetAdapterPresent(int adapter) const override { - return base::Contains(adapter_to_powered_, adapter); - } - - bool GetAdapterEnabled(int adapter) const override { - auto iter = adapter_to_powered_.find(adapter); - if (iter != adapter_to_powered_.end()) { - return iter->second; - } - - return false; - } - - void SetFlossEnabled(bool enabled) override { - dbus::ObjectProxy* object_proxy = - bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); - if (!object_proxy) { - return; - } - - DVLOG(1) << __func__; - - dbus::MethodCall method_call(kManagerInterface, manager::kSetFlossEnabled); - dbus::MessageWriter writer(&method_call); - writer.AppendBool(enabled); - - object_proxy->CallMethodWithErrorResponse( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::BindOnce(&FlossManagerClientImpl::OnResponse, - weak_ptr_factory_.GetWeakPtr(), - "FlossManagerClient::SetFlossEnabled")); - } - - void SetAdapterEnabled(int adapter, - bool enabled, - ResponseCallback callback) override { - dbus::ObjectProxy* object_proxy = - bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); - if (!object_proxy) { - std::move(callback).Run(Error(kUnknownManagerError, std::string())); - return; - } - - DVLOG(1) << __func__; - - auto* command = enabled ? manager::kStart : manager::kStop; - dbus::MethodCall method_call(kManagerInterface, command); - dbus::MessageWriter writer(&method_call); - writer.AppendInt32(adapter); - - object_proxy->CallMethodWithErrorResponse( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::BindOnce(&FlossManagerClientImpl::OnResponseWithCallback, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); - } - - protected: - // Register manager client against manager. - void RegisterWithManager() { - DCHECK(!manager_available_); - - dbus::ObjectProxy* object_proxy = - bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); - - // Get all hci devices available. - dbus::MethodCall method_call(kManagerInterface, manager::kListHciDevices); - object_proxy->CallMethodWithErrorResponse( - &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::BindOnce(&FlossManagerClientImpl::OnListHciDevices, - weak_ptr_factory_.GetWeakPtr())); - - // Register for callbacks. - dbus::MethodCall register_callback(kManagerInterface, - manager::kRegisterCallback); - dbus::MessageWriter writer(®ister_callback); - writer.AppendObjectPath(dbus::ObjectPath(kExportedManagerPath)); - - object_proxy->CallMethodWithErrorResponse( - ®ister_callback, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, - base::BindOnce(&FlossManagerClientImpl::OnResponse, - weak_ptr_factory_.GetWeakPtr(), - manager::kRegisterCallback)); - - manager_available_ = true; - } - - // Remove manager client (no longer available). - void RemoveManager() { - manager_available_ = false; - - // Make copy of old adapters and clear existing ones. - auto previous_adapters = std::move(adapter_to_powered_); - - // All old adapters need to be sent a `present = false` notification. - for (auto& kv : previous_adapters) { - for (auto& observer : observers_) { - observer.AdapterPresent(kv.first, false); - } - } - } - - // The manager can manage multiple adapters so ignore the adapter path given - // here. It is unused. - void Init(dbus::Bus* bus, - const std::string& service_name, - const std::string& adapter_path) override { - bus_ = bus; - service_name_ = service_name; - - dbus::ObjectProxy* object_proxy = - bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); - - // We should always have object proxy since the client initialization is - // gated on ObjectManager marking the manager interface as available. - if (!object_proxy) { - LOG(ERROR) << "FlossManagerClient couldn't init. Object proxy was null."; - return; - } - - DVLOG(1) << __func__; - - // Register callback object. - dbus::ExportedObject* callbacks = - bus_->GetExportedObject(dbus::ObjectPath(kExportedManagerPath)); - - if (!callbacks) { - LOG(ERROR) << "FlossManagerClient couldn't export client callbacks."; - return; - } - - // Register callbacks for OnHciDeviceChanged and OnHciEnabledChanged. - callbacks->ExportMethod( - manager::kCallbackInterface, manager::kOnHciDeviceChanged, - base::BindRepeating(&FlossManagerClientImpl::OnHciDeviceChange, - weak_ptr_factory_.GetWeakPtr()), - base::BindOnce(&FlossManagerClientImpl::OnExported, - weak_ptr_factory_.GetWeakPtr(), - manager::kOnHciDeviceChanged)); - - callbacks->ExportMethod( - manager::kCallbackInterface, manager::kOnHciEnabledChanged, - base::BindRepeating(&FlossManagerClientImpl::OnHciEnabledChange, - weak_ptr_factory_.GetWeakPtr()), - base::BindOnce(&FlossManagerClientImpl::OnExported, - weak_ptr_factory_.GetWeakPtr(), - manager::kOnHciEnabledChanged)); - - // Register object manager for Manager. - object_manager_ = bus_->GetObjectManager( - service_name, dbus::ObjectPath(kObjectManagerPath)); - object_manager_->RegisterInterface(kManagerInterface, this); - - // Get manager ready. - RegisterWithManager(); - } - - void OnListHciDevices(dbus::Response* response, - dbus::ErrorResponse* error_response) { - if (!response) { - FlossDBusClient::LogErrorResponse( - "FlossManagerClientImpl::OnListHciDevices", error_response); - return; - } - - dbus::MessageReader msg(response); - dbus::MessageReader arr(nullptr); - - if (msg.PopArray(&arr)) { - auto previous_adapters = std::move(adapter_to_powered_); - - // Clear existing adapters. - adapter_to_powered_.clear(); - - int adapter = 0; - while (arr.PopInt32(&adapter)) { - DCHECK(adapter >= 0); - adapter_to_powered_.insert({adapter, false}); - } - - // Trigger the observers for adapter present on any new ones we listed. - for (auto& observer : observers_) { - // Emit present for new adapters that weren't in old list. - for (auto& kv : adapter_to_powered_) { - if (!base::Contains(previous_adapters, kv.first)) - observer.AdapterPresent(kv.first, true); - } - - // Emit not present for adapters that aren't in new list. - for (auto& kv : previous_adapters) { - if (!base::Contains(adapter_to_powered_, kv.first)) - observer.AdapterPresent(kv.first, false); - } - } - } - } - - void OnHciDeviceChange(dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - dbus::MessageReader msg(method_call); - int adapter; - bool present; - - if (!msg.PopInt32(&adapter) || !msg.PopBool(&present)) { - std::move(response_sender) - .Run(dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidParameters, std::string())); - return; - } - - for (auto& observer : observers_) { - observer.AdapterPresent(adapter, present); - } - - // Update the cached list of available adapters. - auto iter = adapter_to_powered_.find(adapter); - if (present && iter == adapter_to_powered_.end()) { - adapter_to_powered_.insert({adapter, false}); - } else if (!present && iter != adapter_to_powered_.end()) { - adapter_to_powered_.erase(iter); - } - - std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call)); - } - - void OnHciEnabledChange( - dbus::MethodCall* method_call, - dbus::ExportedObject::ResponseSender response_sender) { - dbus::MessageReader msg(method_call); - int adapter; - bool enabled; - - if (!msg.PopInt32(&adapter) || !msg.PopBool(&enabled)) { - std::move(response_sender) - .Run(dbus::ErrorResponse::FromMethodCall( - method_call, kErrorInvalidParameters, std::string())); - return; - } - - adapter_to_powered_[adapter] = enabled; - - for (auto& observer : observers_) { - observer.AdapterEnabledChanged(adapter, enabled); - } - - std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call)); - } - - void OnExported(const std::string& method_name, - const std::string& interface_name, - const std::string& object_path, - bool success) { - DVLOG(1) << (success ? "Successfully exported " : "Failed to export ") - << method_name << " on interface = " << interface_name - << ", object = " << object_path; - } - - void OnResponseWithCallback(ResponseCallback callback, - dbus::Response* response, - dbus::ErrorResponse* error_response) { - if (response) { - std::move(callback).Run(absl::nullopt); - return; - } - - std::move(callback).Run( - ErrorResponseToError(kErrorNoResponse, std::string(), error_response)); - } - - void OnResponse(const std::string& caller, - dbus::Response* response, - dbus::ErrorResponse* error_response) { - if (error_response) { - FlossDBusClient::LogErrorResponse(caller, error_response); - } else { - DVLOG(1) << caller << "::OnResponse"; - } - } - - dbus::PropertySet* CreateProperties( - dbus::ObjectProxy* object_proxy, - const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - return new dbus::PropertySet(object_proxy, interface_name, - base::DoNothing()); - } - - // Manager interface is available. - void ObjectAdded(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - // TODO(b/193839304) - When manager exits, we're not getting the - // ObjectRemoved notification. So remove the manager - // before re-adding it here. - if (manager_available_) { - RemoveManager(); - } - - DVLOG(0) << __func__ << ": " << object_path.value() << ", " - << interface_name; - - RegisterWithManager(); - } - - // Manager interface is gone (no longer present). - void ObjectRemoved(const dbus::ObjectPath& object_path, - const std::string& interface_name) override { - if (!manager_available_) - return; - - DVLOG(0) << __func__ << ": " << object_path.value() << ", " - << interface_name; - - RemoveManager(); - } - - private: - // Is there a manager available? - bool manager_available_ = false; - - // Managed by FlossDBusManager - we keep local pointer to access object proxy. - dbus::Bus* bus_ = nullptr; - - // Cached list of available adapters and their powered state indexed by hci - // index. - base::flat_map<int, bool> adapter_to_powered_; - - // Default adapter to use. - // TODO(b/191906229) - Default adapter should be taken via manager api. - int default_adapter_ = 0; - - // Name of service that implements manager interface. - std::string service_name_; - - // Exported path. The actual exported object is managed by the bus connection - // itself and will be cleared when the bus is unregistered. - dbus::ObjectPath exported_path_; - - // Keep track of the object manager so we can keep track of when the manager - // disappears. Managed by the bus object (do not delete). - dbus::ObjectManager* object_manager_ = nullptr; - - base::WeakPtrFactory<FlossManagerClientImpl> weak_ptr_factory_{this}; -}; +// static +const char FlossManagerClient::kObjectManagerPath[] = "/"; FlossManagerClient::FlossManagerClient() = default; -FlossManagerClient::~FlossManagerClient() = default; + +FlossManagerClient::~FlossManagerClient() { + if (object_manager_) { + object_manager_->UnregisterInterface(kManagerInterface); + } + + if (bus_) { + bus_->UnregisterExportedObject(dbus::ObjectPath(kExportedCallbacksPath)); + } +} void FlossManagerClient::AddObserver(FlossManagerClient::Observer* observer) { observers_.AddObserver(observer); @@ -411,6 +88,314 @@ observers_.RemoveObserver(observer); } +std::vector<int> FlossManagerClient::GetAdapters() const { + std::vector<int> adapters; + for (auto kv : adapter_to_powered_) { + adapters.push_back(kv.first); + } + + return adapters; +} + +int FlossManagerClient::GetDefaultAdapter() const { + return default_adapter_; +} + +bool FlossManagerClient::GetAdapterPresent(int adapter) const { + return base::Contains(adapter_to_powered_, adapter); +} + +bool FlossManagerClient::GetAdapterEnabled(int adapter) const { + auto iter = adapter_to_powered_.find(adapter); + if (iter != adapter_to_powered_.end()) { + return iter->second; + } + + return false; +} + +void FlossManagerClient::SetFlossEnabled(bool enabled) { + dbus::ObjectProxy* object_proxy = + bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); + if (!object_proxy) { + return; + } + + DVLOG(1) << __func__; + + dbus::MethodCall method_call(kManagerInterface, manager::kSetFlossEnabled); + dbus::MessageWriter writer(&method_call); + writer.AppendBool(enabled); + + object_proxy->CallMethodWithErrorResponse( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::BindOnce(&FlossManagerClient::DefaultResponse, + weak_ptr_factory_.GetWeakPtr(), + "FlossManagerClient::SetFlossEnabled")); +} + +void FlossManagerClient::SetAdapterEnabled(int adapter, + bool enabled, + ResponseCallback callback) { + dbus::ObjectProxy* object_proxy = + bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); + if (!object_proxy) { + std::move(callback).Run(Error(kUnknownManagerError, std::string())); + return; + } + + DVLOG(1) << __func__; + + auto* command = enabled ? manager::kStart : manager::kStop; + dbus::MethodCall method_call(kManagerInterface, command); + dbus::MessageWriter writer(&method_call); + writer.AppendInt32(adapter); + + object_proxy->CallMethodWithErrorResponse( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::BindOnce(&FlossManagerClient::DefaultResponseWithCallback, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +// Register manager client against manager. +void FlossManagerClient::RegisterWithManager() { + DCHECK(!manager_available_); + + dbus::ObjectProxy* object_proxy = + bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); + + // Get all hci devices available. + dbus::MethodCall method_call(kManagerInterface, + manager::kGetAvailableAdapters); + object_proxy->CallMethodWithErrorResponse( + &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::BindOnce(&FlossManagerClient::HandleGetAvailableAdapters, + weak_ptr_factory_.GetWeakPtr())); + + // Register for callbacks. + dbus::MethodCall register_callback(kManagerInterface, + manager::kRegisterCallback); + dbus::MessageWriter writer(®ister_callback); + writer.AppendObjectPath(dbus::ObjectPath(kExportedCallbacksPath)); + + object_proxy->CallMethodWithErrorResponse( + ®ister_callback, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::BindOnce(&FlossManagerClient::DefaultResponse, + weak_ptr_factory_.GetWeakPtr(), + manager::kRegisterCallback)); + + manager_available_ = true; + for (auto& observer : observers_) { + observer.ManagerPresent(manager_available_); + } +} + +// Remove manager client (no longer available). +void FlossManagerClient::RemoveManager() { + // Make copy of old adapters and clear existing ones. + auto previous_adapters = std::move(adapter_to_powered_); + adapter_to_powered_.clear(); + + // All old adapters need to be sent a `present = false` notification. + for (auto& kv : previous_adapters) { + for (auto& observer : observers_) { + observer.AdapterPresent(kv.first, false); + } + } + + manager_available_ = false; + for (auto& observer : observers_) { + observer.ManagerPresent(manager_available_); + } +} + +// The manager can manage multiple adapters so ignore the adapter path given +// here. It is unused. +void FlossManagerClient::Init(dbus::Bus* bus, + const std::string& service_name, + const std::string& adapter_path) { + bus_ = bus; + service_name_ = service_name; + + dbus::ObjectProxy* object_proxy = + bus_->GetObjectProxy(service_name_, dbus::ObjectPath(kManagerObject)); + + // We should always have object proxy since the client initialization is + // gated on ObjectManager marking the manager interface as available. + if (!object_proxy) { + LOG(ERROR) << "FlossManagerClient couldn't init. Object proxy was null."; + return; + } + + DVLOG(1) << __func__; + + // Register callback object. + dbus::ExportedObject* callbacks = + bus_->GetExportedObject(dbus::ObjectPath(kExportedCallbacksPath)); + + if (!callbacks) { + LOG(ERROR) << "FlossManagerClient couldn't export client callbacks."; + return; + } + + // Register callbacks for OnHciDeviceChanged and OnHciEnabledChanged. + callbacks->ExportMethod( + manager::kCallbackInterface, manager::kOnHciDeviceChanged, + base::BindRepeating(&FlossManagerClient::OnHciDeviceChange, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&HandleExported, manager::kOnHciDeviceChanged)); + + callbacks->ExportMethod( + manager::kCallbackInterface, manager::kOnHciEnabledChanged, + base::BindRepeating(&FlossManagerClient::OnHciEnabledChange, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&HandleExported, manager::kOnHciEnabledChanged)); + + // Register object manager for Manager. + object_manager_ = bus_->GetObjectManager( + service_name, dbus::ObjectPath(kObjectManagerPath)); + object_manager_->RegisterInterface(kManagerInterface, this); + + // Get manager ready. + RegisterWithManager(); +} + +void FlossManagerClient::HandleGetAvailableAdapters( + dbus::Response* response, + dbus::ErrorResponse* error_response) { + if (!response) { + FlossDBusClient::LogErrorResponse( + "FlossManagerClient::HandleGetAvailableAdapters", error_response); + return; + } + + dbus::MessageReader msg(response); + dbus::MessageReader arr(nullptr); + + if (msg.PopArray(&arr)) { + auto previous_adapters = std::move(adapter_to_powered_); + + // Clear existing adapters. + adapter_to_powered_.clear(); + + dbus::MessageReader propmap(nullptr); + while (arr.PopArray(&propmap)) { + int adapter = -1; + bool enabled = false; + + if (ParseAdapterWithEnabled(propmap, &adapter, &enabled)) { + DCHECK(adapter >= 0); + adapter_to_powered_.emplace(adapter, enabled); + } + } + + // Trigger the observers for adapter present on any new ones we listed. + for (auto& observer : observers_) { + // Emit present for new adapters that weren't in old list. Also emit the + // powered changed for them. + for (auto& kv : adapter_to_powered_) { + if (!base::Contains(previous_adapters, kv.first)) { + observer.AdapterPresent(kv.first, true); + observer.AdapterEnabledChanged(kv.first, kv.second); + } + } + + // Emit not present for adapters that aren't in new list. + // We don't need to emit AdapterEnabledChanged since we emit + // AdapterPresent is false + for (auto& kv : previous_adapters) { + if (!base::Contains(adapter_to_powered_, kv.first)) + observer.AdapterPresent(kv.first, false); + } + } + } +} + +void FlossManagerClient::OnHciDeviceChange( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + dbus::MessageReader msg(method_call); + int adapter; + bool present; + + if (!msg.PopInt32(&adapter) || !msg.PopBool(&present)) { + std::move(response_sender) + .Run(dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidParameters, std::string())); + return; + } + + for (auto& observer : observers_) { + observer.AdapterPresent(adapter, present); + } + + // Update the cached list of available adapters. + auto iter = adapter_to_powered_.find(adapter); + if (present && iter == adapter_to_powered_.end()) { + adapter_to_powered_.insert({adapter, false}); + } else if (!present && iter != adapter_to_powered_.end()) { + adapter_to_powered_.erase(iter); + } + + std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call)); +} + +void FlossManagerClient::OnHciEnabledChange( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender) { + dbus::MessageReader msg(method_call); + int adapter; + bool enabled; + + if (!msg.PopInt32(&adapter) || !msg.PopBool(&enabled)) { + std::move(response_sender) + .Run(dbus::ErrorResponse::FromMethodCall( + method_call, kErrorInvalidParameters, std::string())); + return; + } + + adapter_to_powered_[adapter] = enabled; + + for (auto& observer : observers_) { + observer.AdapterEnabledChanged(adapter, enabled); + } + + std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call)); +} + +dbus::PropertySet* FlossManagerClient::CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) { + return new dbus::PropertySet(object_proxy, interface_name, base::DoNothing()); +} + +// Manager interface is available. +void FlossManagerClient::ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) { + // TODO(b/193839304) - When manager exits, we're not getting the + // ObjectRemoved notification. So remove the manager + // before re-adding it here. + if (manager_available_) { + RemoveManager(); + } + + DVLOG(0) << __func__ << ": " << object_path.value() << ", " << interface_name; + + RegisterWithManager(); +} + +// Manager interface is gone (no longer present). +void FlossManagerClient::ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) { + if (!manager_available_) + return; + + DVLOG(0) << __func__ << ": " << object_path.value() << ", " << interface_name; + + RemoveManager(); +} + // static dbus::ObjectPath FlossManagerClient::GenerateAdapterPath(int adapter) { return dbus::ObjectPath(base::StringPrintf(kAdapterObjectFormat, adapter)); @@ -418,6 +403,6 @@ // static std::unique_ptr<FlossManagerClient> FlossManagerClient::Create() { - return std::make_unique<FlossManagerClientImpl>(); + return std::make_unique<FlossManagerClient>(); } } // namespace floss
diff --git a/device/bluetooth/floss/floss_manager_client.h b/device/bluetooth/floss/floss_manager_client.h index 21a89ed..9695812 100644 --- a/device/bluetooth/floss/floss_manager_client.h +++ b/device/bluetooth/floss/floss_manager_client.h
@@ -9,11 +9,21 @@ #include <vector> #include "base/callback.h" +#include "base/containers/flat_map.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "dbus/exported_object.h" +#include "dbus/object_manager.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_export.h" #include "device/bluetooth/floss/floss_dbus_client.h" +namespace dbus { +class ErrorResponse; +class PropertySet; +class Response; +} // namespace dbus + namespace floss { // The adapter manager client observes the Manager interface which lists all @@ -23,7 +33,9 @@ // Only the manager interface implements ObjectManager so it should be the first // point of interaction with the platform adapters. It will also be used to // select the default adapter. -class DEVICE_BLUETOOTH_EXPORT FlossManagerClient : public FlossDBusClient { +class DEVICE_BLUETOOTH_EXPORT FlossManagerClient + : public FlossDBusClient, + public dbus::ObjectManager::Interface { public: class Observer : public base::CheckedObserver { public: @@ -47,6 +59,7 @@ FlossManagerClient(const FlossManagerClient&) = delete; FlossManagerClient& operator=(const FlossManagerClient&) = delete; + FlossManagerClient(); ~FlossManagerClient() override; // Add observers on this client. @@ -56,33 +69,99 @@ void RemoveObserver(Observer* observer); // Get a list of adapters available on the system. - virtual std::vector<int> GetAdapters() const = 0; + virtual std::vector<int> GetAdapters() const; // Get the default adapter (index) to use. - virtual int GetDefaultAdapter() const = 0; + virtual int GetDefaultAdapter() const; // Check whether the given adapter is present on the system. - virtual bool GetAdapterPresent(int adapter) const = 0; + virtual bool GetAdapterPresent(int adapter) const; // Enable or disable Floss at the platform level. This will only be used while // Floss is being developed behind a feature flag. This api will be called on // the manager to stop Bluez from running and let Floss manage the adapters // instead. - virtual void SetFlossEnabled(bool enable) = 0; + virtual void SetFlossEnabled(bool enable); // Check whether an adapter is enabled. - virtual bool GetAdapterEnabled(int adapter) const = 0; + virtual bool GetAdapterEnabled(int adapter) const; // Enable or disable an adapter. virtual void SetAdapterEnabled(int adapter, bool enabled, - ResponseCallback callback) = 0; + ResponseCallback callback); + + // Initializes the manager client. + void Init(dbus::Bus* bus, + const std::string& service_name, + const std::string& adapter_path) override; protected: - FlossManagerClient(); + friend class FlossManagerClientTest; + + // Handle response to |GetAvailableAdapters| DBus method call. + virtual void HandleGetAvailableAdapters(dbus::Response* response, + dbus::ErrorResponse* error); + + // Handle callback |OnHciDeviceChange| on exported object path. + virtual void OnHciDeviceChange( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender); + + // Handle callback |OnHciEnabledChange| on exported object path. + virtual void OnHciEnabledChange( + dbus::MethodCall* method_call, + dbus::ExportedObject::ResponseSender response_sender); + + // Get active adapters and register for callbacks with manager object. + void RegisterWithManager(); + + // Remove active adapters after manager is no longer available. + void RemoveManager(); + + // dbus::ObjectManager::Interface overrides + dbus::PropertySet* CreateProperties( + dbus::ObjectProxy* object_proxy, + const dbus::ObjectPath& object_path, + const std::string& interface_name) override; + + void ObjectAdded(const dbus::ObjectPath& object_path, + const std::string& interface_name) override; + void ObjectRemoved(const dbus::ObjectPath& object_path, + const std::string& interface_name) override; + + // Managed by FlossDBusManager - we keep local pointer to access object proxy. + dbus::Bus* bus_ = nullptr; + + // Keep track of the object manager so we can keep track of when the manager + // disappears. Managed by the bus object (do not delete). + dbus::ObjectManager* object_manager_ = nullptr; + + // Is there a manager available? + bool manager_available_ = false; + + // Default adapter to use. + // TODO(b/191906229) - Default adapter should be taken via manager api. + int default_adapter_ = 0; + + // Cached list of available adapters and their powered state indexed by hci + // index. + base::flat_map<int, bool> adapter_to_powered_; + + // Name of service that implements manager interface. + std::string service_name_; // List of observers interested in event notifications from this client. base::ObserverList<Observer> observers_; + + private: + // Object path for exported callbacks registered against manager interface. + static const char kExportedCallbacksPath[]; + + // Floss Manager registers ObjectManager at this path. + static const char kObjectManagerPath[]; + + base::WeakPtrFactory<FlossManagerClient> weak_ptr_factory_{this}; }; } // namespace floss
diff --git a/device/bluetooth/floss/floss_manager_client_unittest.cc b/device/bluetooth/floss/floss_manager_client_unittest.cc new file mode 100644 index 0000000..d464cdf --- /dev/null +++ b/device/bluetooth/floss/floss_manager_client_unittest.cc
@@ -0,0 +1,385 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/floss/floss_manager_client.h" + +#include <utility> +#include <vector> + +#include "base/memory/ref_counted.h" +#include "base/run_loop.h" +#include "base/test/task_environment.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/mock_bus.h" +#include "dbus/mock_exported_object.h" +#include "dbus/mock_object_proxy.h" +#include "dbus/object_manager.h" +#include "dbus/object_path.h" +#include "device/bluetooth/floss/floss_dbus_client.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace floss { +namespace { +const std::vector<std::pair<int, bool>> kMockAdaptersAvailable = {{0, false}, + {5, true}}; + +class TestManagerObserver : public FlossManagerClient::Observer { + public: + explicit TestManagerObserver(FlossManagerClient* client) : client_(client) { + client_->AddObserver(this); + } + + ~TestManagerObserver() override { client_->RemoveObserver(this); } + + void ManagerPresent(bool present) override { + manager_present_count_++; + manager_present_ = present; + } + + void AdapterPresent(int adapter, bool present) override { + adapter_present_count_++; + adapter_present_[adapter] = present; + } + + void AdapterEnabledChanged(int adapter, bool enabled) override { + adapter_enabled_changed_count_++; + adapter_enabled_[adapter] = enabled; + } + + int manager_present_count_ = 0; + int adapter_present_count_ = 0; + int adapter_enabled_changed_count_ = 0; + + bool manager_present_ = false; + std::map<int, bool> adapter_present_; + std::map<int, bool> adapter_enabled_; + + private: + FlossManagerClient* client_ = nullptr; +}; + +} // namespace + +class FlossManagerClientTest : public testing::Test { + public: + FlossManagerClientTest() = default; + + void SetUpMocks() { + auto obj_mgr_path = + ::dbus::ObjectPath(FlossManagerClient::kObjectManagerPath); + + manager_object_proxy_ = base::MakeRefCounted<::dbus::MockObjectProxy>( + bus_.get(), kManagerInterface, ::dbus::ObjectPath(kManagerObject)); + + exported_callbacks_ = base::MakeRefCounted<::dbus::MockExportedObject>( + bus_.get(), + ::dbus::ObjectPath(FlossManagerClient::kExportedCallbacksPath)); + + // Make sure a valid object manager is returned + EXPECT_CALL(*bus_.get(), GetObjectProxy(kManagerInterface, obj_mgr_path)) + .WillOnce(::testing::Return(manager_object_proxy_.get())); + EXPECT_CALL(*bus_.get(), GetDBusTaskRunner()) + .WillOnce( + ::testing::Return(::base::SequencedTaskRunnerHandle::Get().get())); + object_manager_ = ::dbus::ObjectManager::Create( + bus_.get(), kManagerInterface, obj_mgr_path); + EXPECT_CALL(*bus_.get(), + GetObjectManager(kManagerInterface, dbus::ObjectPath("/"))) + .WillOnce(::testing::Return(object_manager_.get())); + + // Set up expects for remaining interfaces + EXPECT_CALL(*bus_.get(), GetObjectProxy(kManagerInterface, + ::dbus::ObjectPath(kManagerObject))) + .WillRepeatedly(::testing::Return(manager_object_proxy_.get())); + EXPECT_CALL(*bus_.get(), GetExportedObject) + .WillRepeatedly(::testing::Return(exported_callbacks_.get())); + EXPECT_CALL(*exported_callbacks_.get(), ExportMethod).Times(2); + + // Handle method calls on the object proxy + ON_CALL(*manager_object_proxy_.get(), DoCallMethodWithErrorResponse) + .WillByDefault( + [this](::dbus::MethodCall* method_call, int timeout_ms, + ::dbus::ObjectProxy::ResponseOrErrorCallback* cb) { + if (method_call->GetMember() == manager::kGetAvailableAdapters) { + HandleGetAvailableAdapters(method_call, timeout_ms, cb); + } + + method_called_[method_call->GetMember()]++; + }); + } + + void SendHciDeviceCallback(int adapter, + bool present, + dbus::ExportedObject::ResponseSender response) { + dbus::MethodCall method_call(manager::kCallbackInterface, + manager::kOnHciDeviceChanged); + method_call.SetSerial(serial_++); + dbus::MessageWriter writer(&method_call); + writer.AppendInt32(adapter); + writer.AppendBool(present); + + client_->OnHciDeviceChange(&method_call, std::move(response)); + } + + void SendInvalidHciDeviceCallback(dbus::ExportedObject::ResponseSender rsp) { + dbus::MethodCall method_call(manager::kCallbackInterface, + manager::kOnHciDeviceChanged); + method_call.SetSerial(serial_++); + client_->OnHciDeviceChange(&method_call, std::move(rsp)); + } + + void SendHciEnabledCallback(int adapter, + bool enabled, + dbus::ExportedObject::ResponseSender response) { + dbus::MethodCall method_call(manager::kCallbackInterface, + manager::kOnHciEnabledChanged); + method_call.SetSerial(serial_++); + dbus::MessageWriter writer(&method_call); + writer.AppendInt32(adapter); + writer.AppendBool(enabled); + + client_->OnHciEnabledChange(&method_call, std::move(response)); + } + + void SendInvalidHciEnabledCallback(dbus::ExportedObject::ResponseSender rsp) { + dbus::MethodCall method_call(manager::kCallbackInterface, + manager::kOnHciEnabledChanged); + method_call.SetSerial(serial_++); + client_->OnHciEnabledChange(&method_call, std::move(rsp)); + } + + void SetUp() override { + ::dbus::Bus::Options options; + options.bus_type = ::dbus::Bus::BusType::SYSTEM; + bus_ = base::MakeRefCounted<::dbus::MockBus>(options); + client_ = FlossManagerClient::Create(); + + SetUpMocks(); + } + + void TearDown() override { + // Clean up the client first so it gets rid of all its references to the + // various buses, object proxies, etc. + client_.reset(); + method_called_.clear(); + } + + void HandleGetAvailableAdapters( + ::dbus::MethodCall* method_call, + int timeout_ms, + ::dbus::ObjectProxy::ResponseOrErrorCallback* cb) { + // Return that there are 2 adapter objects + auto response = ::dbus::Response::CreateEmpty(); + + ::dbus::MessageWriter msg(response.get()); + ::dbus::MessageWriter outer(nullptr); + msg.OpenArray("a{sv}", &outer); + for (auto kv : kMockAdaptersAvailable) { + ::dbus::MessageWriter inner(nullptr); + ::dbus::MessageWriter dict(nullptr); + outer.OpenArray("{sv}", &inner); + + inner.OpenDictEntry(&dict); + dict.AppendString("hci_interface"); + dict.AppendVariantOfInt32(kv.first); + inner.CloseContainer(&dict); + + inner.OpenDictEntry(&dict); + dict.AppendString("enabled"); + dict.AppendVariantOfBool(kv.second); + inner.CloseContainer(&dict); + + outer.CloseContainer(&inner); + } + msg.CloseContainer(&outer); + + std::move(*cb).Run(response.get(), nullptr); + } + + void ExpectErrorResponse(std::unique_ptr<dbus::Response> response) { + EXPECT_EQ(response->GetMessageType(), + dbus::Message::MessageType::MESSAGE_ERROR); + } + + void ExpectNormalResponse(std::unique_ptr<dbus::Response> response) { + EXPECT_NE(response->GetMessageType(), + dbus::Message::MessageType::MESSAGE_ERROR); + } + + void TriggerObjectAdded(dbus::ObjectPath& path, + const std::string& interface) { + client_->ObjectAdded(path, interface); + } + + void TriggerObjectRemoved(dbus::ObjectPath& path, + const std::string& interface) { + client_->ObjectRemoved(path, interface); + } + + bool IsInterfaceRegisteredOnObjectManager(const std::string& interface) { + return client_->object_manager_ != nullptr && + client_->object_manager_->IsInterfaceRegisteredForTesting(interface); + } + + protected: + // DBus messages require an increasing serial number or the dbus libraries + // assert. + int serial_ = 1; + std::unique_ptr<FlossManagerClient> client_; + scoped_refptr<::dbus::MockBus> bus_; + scoped_refptr<::dbus::MockExportedObject> exported_callbacks_; + scoped_refptr<::dbus::MockObjectProxy> manager_object_proxy_; + scoped_refptr<::dbus::ObjectManager> object_manager_; + std::map<std::string, int> method_called_; + + base::test::TaskEnvironment task_environment_; + base::WeakPtrFactory<FlossManagerClientTest> weak_ptr_factory_{this}; +}; + +// Make sure adapter presence is updated on init +TEST_F(FlossManagerClientTest, QueriesAdapterPresenceOnInit) { + TestManagerObserver observer(client_.get()); + client_->Init(bus_.get(), kManagerInterface, /*adapter_path=*/std::string()); + EXPECT_EQ(observer.manager_present_count_, 1); + EXPECT_TRUE(observer.manager_present_); + + EXPECT_THAT(client_->GetAdapters(), ::testing::ElementsAre(0, 5)); + EXPECT_TRUE(client_->GetAdapterPresent(0)); + EXPECT_TRUE(client_->GetAdapterPresent(5)); + EXPECT_FALSE(client_->GetAdapterPresent(1)); + + EXPECT_EQ(observer.adapter_present_count_, 2); + EXPECT_TRUE(observer.adapter_present_[0]); + EXPECT_TRUE(observer.adapter_present_[5]); +} + +// Make sure adapter presence is plumbed through callbacks +TEST_F(FlossManagerClientTest, VerifyAdapterPresent) { + TestManagerObserver observer(client_.get()); + client_->Init(bus_.get(), kManagerInterface, /*adapter_path=*/std::string()); + EXPECT_EQ(observer.adapter_present_count_, 2); + EXPECT_EQ(observer.adapter_enabled_changed_count_, 2); + EXPECT_TRUE(observer.adapter_present_[0]); + + SendInvalidHciDeviceCallback( + base::BindOnce(&FlossManagerClientTest::ExpectErrorResponse, + weak_ptr_factory_.GetWeakPtr())); + + SendHciDeviceCallback( + 0, false, + base::BindOnce(&FlossManagerClientTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + + EXPECT_THAT(client_->GetAdapters(), ::testing::ElementsAre(5)); + EXPECT_TRUE(client_->GetAdapterPresent(5)); + EXPECT_FALSE(client_->GetAdapterPresent(0)); + EXPECT_FALSE(client_->GetAdapterEnabled(0)); + + // 2 to start and 1 to remove "0" + EXPECT_EQ(observer.adapter_present_count_, 3); + EXPECT_FALSE(observer.adapter_present_[0]); + + // On present = false, the client may not be sent an additional enabled + // = false. It is implied and the client must act accordingly. + EXPECT_EQ(observer.adapter_enabled_changed_count_, 2); +} + +// Make sure adapter powered is plumbed through callbacks +TEST_F(FlossManagerClientTest, VerifyAdapterEnabled) { + TestManagerObserver observer(client_.get()); + client_->Init(bus_.get(), kManagerInterface, /*adapter_path=*/std::string()); + // Pre-conditions + EXPECT_FALSE(client_->GetAdapterEnabled(0)); + EXPECT_TRUE(client_->GetAdapterEnabled(5)); + EXPECT_EQ(observer.adapter_enabled_changed_count_, 2); + + // Adapter 1 is not present at the beginning + EXPECT_FALSE(client_->GetAdapterEnabled(1)); + EXPECT_FALSE(client_->GetAdapterPresent(1)); + + SendInvalidHciEnabledCallback( + base::BindOnce(&FlossManagerClientTest::ExpectErrorResponse, + weak_ptr_factory_.GetWeakPtr())); + + SendHciEnabledCallback( + 0, true, + base::BindOnce(&FlossManagerClientTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + + EXPECT_TRUE(client_->GetAdapterEnabled(0)); + EXPECT_EQ(observer.adapter_enabled_changed_count_, 3); + EXPECT_TRUE(observer.adapter_enabled_[0]); + + // Enabled implies presence too + SendHciEnabledCallback( + 1, true, + base::BindOnce(&FlossManagerClientTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_TRUE(client_->GetAdapterPresent(1)); + EXPECT_TRUE(client_->GetAdapterEnabled(1)); + + EXPECT_EQ(observer.adapter_enabled_changed_count_, 4); + EXPECT_TRUE(observer.adapter_enabled_[1]); + // On enabled = true, present = true is implied. The platform should emit both + // but the client shouldn't depend on it. + EXPECT_FALSE(observer.adapter_present_[1]); + + // 5 was unchanged + EXPECT_TRUE(client_->GetAdapterEnabled(5)); + EXPECT_TRUE(observer.adapter_enabled_[5]); +} + +// Make sure manager presence is correctly detected +TEST_F(FlossManagerClientTest, HandleManagerPresence) { + TestManagerObserver observer(client_.get()); + client_->Init(bus_.get(), kManagerInterface, /*adapter_path=*/std::string()); + dbus::ObjectPath opath = dbus::ObjectPath(kManagerObject); + EXPECT_EQ(observer.manager_present_count_, 1); + + // Make sure we registered against ObjectManager + EXPECT_TRUE(IsInterfaceRegisteredOnObjectManager(kManagerInterface)); + + // By default, the manager should be available + EXPECT_TRUE(observer.manager_present_); + + // Triggering an ObjectRemoved should clear all present adapters + TriggerObjectRemoved(opath, kManagerInterface); + EXPECT_THAT(client_->GetAdapters(), ::testing::ElementsAre()); + EXPECT_FALSE(observer.manager_present_); + + // Triggering ObjectRemoved while already unavailable should do nothing + TriggerObjectRemoved(opath, kManagerInterface); + EXPECT_THAT(client_->GetAdapters(), ::testing::ElementsAre()); + EXPECT_FALSE(observer.manager_present_); + + method_called_.clear(); + // Triggering ObjectAdded should refill available hci devices and register + // callbacks + TriggerObjectAdded(opath, kManagerInterface); + EXPECT_TRUE(method_called_[manager::kGetAvailableAdapters] > 0); + EXPECT_TRUE(method_called_[manager::kRegisterCallback] > 0); + EXPECT_TRUE(observer.manager_present_); + + // Clear present count to confirm a RemoveManager + RegisterManager occurred + observer.manager_present_count_ = 0; + + // TODO(b/193839304) - Triggering ObjectAdded on an already added object + // should trigger a remove and then re-add + method_called_.clear(); + SendHciDeviceCallback( + 1, true, + base::BindOnce(&FlossManagerClientTest::ExpectNormalResponse, + weak_ptr_factory_.GetWeakPtr())); + EXPECT_TRUE(client_->GetAdapterPresent(1)); + TriggerObjectAdded(opath, kManagerInterface); + // ManagerPresent should be called once for remove and once for register. + EXPECT_EQ(observer.manager_present_count_, 2); + EXPECT_FALSE(client_->GetAdapterPresent(1)); // Cleared previous adapter list + EXPECT_TRUE(method_called_[manager::kGetAvailableAdapters] > 0); + EXPECT_TRUE(method_called_[manager::kRegisterCallback] > 0); +} +} // namespace floss
diff --git a/device/gamepad/gamepad_id_list.h b/device/gamepad/gamepad_id_list.h index 751b7618..e73e31b 100644 --- a/device/gamepad/gamepad_id_list.h +++ b/device/gamepad/gamepad_id_list.h
@@ -12,6 +12,7 @@ #include <vector> #include "base/lazy_instance.h" +#include "base/strings/string_piece.h" #include "device/gamepad/gamepad_export.h" namespace device {
diff --git a/docs/android_dynamic_feature_modules.md b/docs/android_dynamic_feature_modules.md index ff2c2281d..1d4440a 100644 --- a/docs/android_dynamic_feature_modules.md +++ b/docs/android_dynamic_feature_modules.md
@@ -213,12 +213,14 @@ ```shell $ autoninja -C $OUTDIR monochrome_public_bundle -$ $OUTDIR/bin/monochrome_public_bundle install -m base -m foo +$ $OUTDIR/bin/monochrome_public_bundle install -m foo ``` -This will install Foo alongside the rest of Chrome. The rest of Chrome is called -_base_ module in the bundle world. The base module will always be put on the -device when initially installing Chrome. +This will install the `Foo` module, the `base` module, and all modules with an +`AndroidManifest.xml` that: + * Sets `<module dist:onDemand="false">`, or + * Has `<dist:delivery>` conditions that are satisfied by the device being + installed to. *** note **Note:** The install script may install more modules than you specify, e.g. @@ -237,7 +239,7 @@ installed modules: ```shell -$ $OUTDIR/bin/monochrome_public_bundle install -m base +$ $OUTDIR/bin/monochrome_public_bundle install $ adb shell dumpsys package org.chromium.chrome | grep splits > splits=[base, config.en] ``` @@ -871,7 +873,7 @@ Fake-install and launch Chrome with the following command: ```shell -$ $OUTDIR/bin/monochrome_public_bundle install -m base -f foo +$ $OUTDIR/bin/monochrome_public_bundle install -f foo $ $OUTDIR/bin/monochrome_public_bundle launch ```
diff --git a/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc b/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc index fc70bb8..c5afe4fc 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc +++ b/extensions/browser/api/feedback_private/feedback_private_api_chromeos_unittest.cc
@@ -127,8 +127,7 @@ EXPECT_TRUE(values.is_list()); std::unique_ptr<api::feedback_private::SendFeedback::Params> params = - api::feedback_private::SendFeedback::Params::Create( - base::Value::AsListValue(values)); + api::feedback_private::SendFeedback::Params::Create(values.GetList()); EXPECT_TRUE(params); scoped_refptr<FeedbackData> actual_feedback_data;
diff --git a/extensions/common/api/automation.idl b/extensions/common/api/automation.idl index 59004ba..d8e50a3 100644 --- a/extensions/common/api/automation.idl +++ b/extensions/common/api/automation.idl
@@ -23,6 +23,7 @@ autocorrectionOccured, blur, busyChanged, + caretBoundsChanged, checkedStateChanged, checkedStateDescriptionChanged, childrenChanged, @@ -910,6 +911,9 @@ // The level of a heading or tree item. long? hierarchicalLevel; + // The current caret bounds in screen coordinates. + Rect? caretBounds; + // The start and end index of each word in an inline text box. long[]? wordStarts; long[]? wordEnds;
diff --git a/extensions/common/api/storage.json b/extensions/common/api/storage.json index b235a594..e6fb5658 100644 --- a/extensions/common/api/storage.json +++ b/extensions/common/api/storage.json
@@ -58,20 +58,21 @@ ], "description": "A single key to get, list of keys to get, or a dictionary specifying default values (see description of the object). An empty list or object will return an empty result object. Pass in <code>null</code> to get the entire contents of storage.", "optional": true + }, + { + "name": "callback", + "type": "function", + "description": "Callback with storage items, or on failure (in which case $(ref:runtime.lastError) will be set).", + "parameters": [ + { + "name": "items", + "type": "object", + "additionalProperties": { "type": "any" }, + "description": "Object with items in their key-value mappings." + } + ] } - ], - "returns_async": { - "name": "callback", - "description": "Callback with storage items, or on failure (in which case $(ref:runtime.lastError) will be set).", - "parameters": [ - { - "name": "items", - "type": "object", - "additionalProperties": { "type": "any" }, - "description": "Object with items in their key-value mappings." - } - ] - } + ] }, { "name": "getBytesInUse", @@ -86,19 +87,20 @@ ], "description": "A single key or list of keys to get the total usage for. An empty list will return 0. Pass in <code>null</code> to get the total usage of all of storage.", "optional": true + }, + { + "name": "callback", + "type": "function", + "description": "Callback with the amount of space being used by storage, or on failure (in which case $(ref:runtime.lastError) will be set).", + "parameters": [ + { + "name": "bytesInUse", + "type": "integer", + "description": "Amount of space being used in storage, in bytes." + } + ] } - ], - "returns_async": { - "name": "callback", - "description": "Callback with the amount of space being used by storage, or on failure (in which case $(ref:runtime.lastError) will be set).", - "parameters": [ - { - "name": "bytesInUse", - "type": "integer", - "description": "Amount of space being used in storage, in bytes." - } - ] - } + ] }, { "name": "set", @@ -111,14 +113,15 @@ "additionalProperties": { "type": "any", "preserveNull": true }, "preserveNull": true, "description": "<p>An object which gives each key/value pair to update storage with. Any other key/value pairs in storage will not be affected.</p><p>Primitive values such as numbers will serialize as expected. Values with a <code>typeof</code> <code>\"object\"</code> and <code>\"function\"</code> will typically serialize to <code>{}</code>, with the exception of <code>Array</code> (serializes as expected), <code>Date</code>, and <code>Regex</code> (serialize using their <code>String</code> representation).</p>" + }, + { + "name": "callback", + "type": "function", + "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", + "parameters": [], + "optional": true } - ], - "returns_async": { - "name": "callback", - "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", - "parameters": [], - "optional": true - } + ] }, { "name": "remove", @@ -132,26 +135,29 @@ {"type": "array", "items": {"type": "string"}} ], "description": "A single key or a list of keys for items to remove." + }, + { + "name": "callback", + "type": "function", + "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", + "parameters": [], + "optional": true } - ], - "returns_async": { - "name": "callback", - "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", - "parameters": [], - "optional": true - } + ] }, { "name": "clear", "type": "function", "description": "Removes all items from storage.", - "parameters": [], - "returns_async": { - "name": "callback", - "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", - "parameters": [], - "optional": true - } + "parameters": [ + { + "name": "callback", + "type": "function", + "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", + "parameters": [], + "optional": true + } + ] }, { "name": "setAccessLevel", "nodoc": true, @@ -167,14 +173,15 @@ "description": "The access level of the storage area." } } + }, + { + "name": "callback", + "type": "function", + "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", + "parameters": [], + "optional": true } - ], - "returns_async": { - "name": "callback", - "description": "Callback on success, or on failure (in which case $(ref:runtime.lastError) will be set).", - "parameters": [], - "optional": true - } + ] } ], "events": [
diff --git a/extensions/renderer/api/automation/automation_api_util.cc b/extensions/renderer/api/automation/automation_api_util.cc index e5b3e1e8..6b6b4cc 100644 --- a/extensions/renderer/api/automation/automation_api_util.cc +++ b/extensions/renderer/api/automation/automation_api_util.cc
@@ -108,6 +108,7 @@ case ui::AXEventGenerator::Event::ATOMIC_CHANGED: case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED: case ui::AXEventGenerator::Event::BUSY_CHANGED: + case ui::AXEventGenerator::Event::CARET_BOUNDS_CHANGED: case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED: case ui::AXEventGenerator::Event::CHECKED_STATE_DESCRIPTION_CHANGED: case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
diff --git a/extensions/renderer/resources/automation/automation_node.js b/extensions/renderer/resources/automation/automation_node.js index 0800310..2acc007f 100644 --- a/extensions/renderer/resources/automation/automation_node.js +++ b/extensions/renderer/resources/automation/automation_node.js
@@ -656,6 +656,19 @@ return GetChecked(this.treeID, this.id); }, + get caretBounds() { + const data = GetIntListAttribute(this.treeID, this.id, 'caretBounds'); + if (!data) { + return; + } + + if (data.length !== 4) { + throw 'Internal encoding error for caret bounds.'; + } + + return {left: data[0], top: data[1], width: data[2], height: data[3]}; + }, + get location() { return GetLocation(this.treeID, this.id); }, @@ -2049,6 +2062,7 @@ [ 'ariaCurrentState', 'bold', + 'caretBounds', 'checked', 'children', 'customActions',
diff --git a/fuchsia/base/mem_buffer_util.cc b/fuchsia/base/mem_buffer_util.cc index 4e2e7db..f3cc1e8 100644 --- a/fuchsia/base/mem_buffer_util.cc +++ b/fuchsia/base/mem_buffer_util.cc
@@ -14,6 +14,7 @@ #include "base/files/file_util.h" #include "base/files/memory_mapped_file.h" #include "base/fuchsia/fuchsia_logging.h" +#include "base/notreached.h" #include "base/threading/thread_restrictions.h" namespace cr_fuchsia {
diff --git a/fuchsia/engine/browser/media_player_impl.cc b/fuchsia/engine/browser/media_player_impl.cc index 8461e41a..d4284f2 100644 --- a/fuchsia/engine/browser/media_player_impl.cc +++ b/fuchsia/engine/browser/media_player_impl.cc
@@ -55,6 +55,8 @@ return {}; // PlayerControl does not support hanging up. case MediaSessionAction::kRaise: return {}; // PlayerControl does not support raising. + case MediaSessionAction::kSetMute: + return {}; // TODO(crbug.com/1240811): implement set mute. } }
diff --git a/fuchsia/engine/browser/media_player_impl_unittest.cc b/fuchsia/engine/browser/media_player_impl_unittest.cc index 9cf2ab5db1..e0d5540e 100644 --- a/fuchsia/engine/browser/media_player_impl_unittest.cc +++ b/fuchsia/engine/browser/media_player_impl_unittest.cc
@@ -41,6 +41,7 @@ MOCK_METHOD0(ToggleCamera, void()); MOCK_METHOD0(HangUp, void()); MOCK_METHOD0(Raise, void()); + MOCK_METHOD1(SetMute, void(bool)); // content::MediaSession APIs faked to implement testing behaviour. MOCK_METHOD1(DidReceiveAction,
diff --git a/fuchsia/engine/browser/navigation_controller_impl.cc b/fuchsia/engine/browser/navigation_controller_impl.cc index 42d0e39..355a4cf7 100644 --- a/fuchsia/engine/browser/navigation_controller_impl.cc +++ b/fuchsia/engine/browser/navigation_controller_impl.cc
@@ -4,6 +4,7 @@ #include "fuchsia/engine/browser/navigation_controller_impl.h" +#include "base/bits.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/memory/page_size.h" #include "base/strings/strcat.h"
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index 00eacdf9..74b35fb 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -248,6 +248,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -3794,12 +3798,10 @@ ' "use_luci_auth": true' ' },' ' "$build/reclient": {' + ' "cache_silo": "Comparison Linux - cache siloed",' ' "instance": "rbe-chromium-trusted",' ' "jobs": 250,' - ' "metrics_project": "chromium-reclient-metrics",' - ' "rewrapper_env": {' - ' "RBE_cache_silo": "Comparison Linux - cache siloed"' - ' }' + ' "metrics_project": "chromium-reclient-metrics"' ' },' ' "$kitchen": {' ' "devshell": true,' @@ -3823,6 +3825,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -10173,6 +10179,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -10259,6 +10269,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -10345,6 +10359,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -10611,6 +10629,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -10697,6 +10719,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -10786,6 +10812,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -10875,6 +10905,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -13310,6 +13344,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -13398,6 +13436,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -14017,6 +14059,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -14966,6 +15012,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -16479,6 +16529,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -16562,6 +16616,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18022,6 +18080,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18197,6 +18259,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18371,6 +18437,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18460,6 +18530,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18548,6 +18622,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18636,6 +18714,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18725,6 +18807,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18813,6 +18899,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -18898,6 +18988,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -22103,6 +22197,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -22275,6 +22373,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -22361,6 +22463,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -22804,6 +22910,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -23501,6 +23611,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -23588,6 +23702,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -24857,6 +24975,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -26933,6 +27055,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -27019,6 +27145,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -27292,6 +27422,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -27385,6 +27519,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -30852,6 +30990,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -30938,6 +31080,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -31469,6 +31615,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -31557,6 +31707,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -31646,6 +31800,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -31732,6 +31890,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -32265,6 +32427,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -32351,6 +32517,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -32437,6 +32607,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -32523,6 +32697,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -32609,6 +32787,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -32695,6 +32877,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -33221,6 +33407,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -33502,6 +33692,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -33590,6 +33784,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -33770,6 +33968,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -33950,6 +34152,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34038,6 +34244,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34126,6 +34336,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34214,6 +34428,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34302,6 +34520,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34390,6 +34612,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34679,6 +34905,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34767,6 +34997,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -34853,6 +35087,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -35526,6 +35764,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -35821,6 +36063,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -36012,6 +36258,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -36278,6 +36528,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -36364,6 +36618,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -36450,6 +36708,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -36536,6 +36798,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -36882,6 +37148,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -37060,6 +37330,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -37235,6 +37509,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -37321,6 +37599,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -37414,6 +37696,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -37670,6 +37956,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -37763,6 +38053,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -37939,6 +38233,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38108,6 +38406,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38283,6 +38585,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38371,6 +38677,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38464,6 +38774,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38639,6 +38953,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38725,6 +39043,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38811,6 +39133,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -38986,6 +39312,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -39505,6 +39835,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -40127,6 +40461,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -40298,6 +40636,10 @@ service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experimental: YES experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -40385,6 +40727,10 @@ service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experimental: YES experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -40472,6 +40818,10 @@ service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experimental: YES experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -41647,6 +41997,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -42080,6 +42434,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -42164,6 +42522,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -42420,6 +42782,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -42504,6 +42870,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -42588,6 +42958,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -42924,6 +43298,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -44558,6 +44936,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -44910,6 +45292,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -44996,6 +45382,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -45347,6 +45737,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -45433,6 +45827,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -46314,6 +46712,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -46731,6 +47133,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 } @@ -47251,6 +47657,10 @@ build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" experiments { + key: "chromium.chromium_tests.use_rdb_results" + value: 5 + } + experiments { key: "luci.use_realms" value: 100 }
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star index f3cf33e..7fff581 100644 --- a/infra/config/lib/builders.star +++ b/infra/config/lib/builders.star
@@ -289,7 +289,7 @@ return isolated or None -def _reclient_property(*, instance, service, jobs, rewrapper_env, profiler_service, publish_trace): +def _reclient_property(*, instance, service, jobs, rewrapper_env, profiler_service, publish_trace, cache_silo): reclient = {} instance = defaults.get_value("reclient_instance", instance) if instance: @@ -314,6 +314,8 @@ publish_trace = defaults.get_value("reclient_publish_trace", publish_trace) if publish_trace: reclient["publish_trace"] = True + if cache_silo: + reclient["cache_silo"] = cache_silo return reclient or None ################################################################################ @@ -359,6 +361,7 @@ reclient_rewrapper_env = None, reclient_profiler_service = None, reclient_publish_trace = None, + reclient_cache_silo = None, # Provide vars for bucket and executable so users don't have to # unnecessarily make wrapper functions @@ -410,6 +413,7 @@ reclient_rewrapper_env = args.DEFAULT, reclient_profiler_service = args.DEFAULT, reclient_publish_trace = args.DEFAULT, + reclient_cache_silo = None, **kwargs): """Define a builder. @@ -558,6 +562,8 @@ * reclient_profiler_service - a string indicating service name for re-client's cloud profiler. * reclient_publish_trace - If True, it publish trace by rpl2cloudtrace. + * reclient_cache_silo - A string indicating a cache siling key to use for + remote caching. * kwargs - Additional keyword arguments to forward on to `luci.builder`. """ @@ -706,6 +712,7 @@ rewrapper_env = reclient_rewrapper_env, profiler_service = reclient_profiler_service, publish_trace = reclient_publish_trace, + cache_silo = reclient_cache_silo, ) if reclient != None: properties["$build/reclient"] = reclient
diff --git a/infra/config/lib/ci.star b/infra/config/lib/ci.star index c15a78b..161f92b 100644 --- a/infra/config/lib/ci.star +++ b/infra/config/lib/ci.star
@@ -420,6 +420,10 @@ goma_backend = builders.goma.backend.RBE_PROD, **kwargs): kwargs.setdefault("os", os.LINUX_BIONIC_REMOVE) + + # TODO(crbug.com/1135718): Promote out of experiment for all builders. + kwargs.setdefault("experiments", {}) + kwargs["experiments"].setdefault("chromium.chromium_tests.use_rdb_results", 5) return ci.builder( name = name, builder_group = "chromium.fyi",
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star index 5fa6669..e004fb6 100644 --- a/infra/config/subprojects/chromium/ci.star +++ b/infra/config/subprojects/chromium/ci.star
@@ -3891,7 +3891,7 @@ goma_jobs = 250, executable = "recipe:reclient_goma_comparison", execution_timeout = 6 * time.hour, - reclient_rewrapper_env = {"RBE_cache_silo": "Comparison Linux - cache siloed"}, + reclient_cache_silo = "Comparison Linux - cache siloed", reclient_instance = rbe_instance.DEFAULT, reclient_jobs = 250, configure_kitchen = True,
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index a9aa9fa8..c185f1b8 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -21,6 +21,7 @@ #include "components/component_updater/crl_set_remover.h" #include "components/component_updater/installer_policies/autofill_states_component_installer.h" #include "components/component_updater/installer_policies/on_device_head_suggest_component_installer.h" +#import "components/component_updater/installer_policies/optimization_hints_component_installer.h" #include "components/component_updater/installer_policies/safety_tips_component_installer.h" #include "components/feature_engagement/public/event_constants.h" #include "components/feature_engagement/public/tracker.h" @@ -200,6 +201,7 @@ RegisterSafetyTipsComponent(cus); RegisterAutofillStatesComponent(cus, GetApplicationContext()->GetLocalState()); + RegisterOptimizationHintsComponent(cus); } // The delay, in seconds, for cleaning external files.
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_service_accessor.h b/ios/chrome/browser/metrics/ios_chrome_metrics_service_accessor.h index 15c3d11..517ac73a 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_service_accessor.h +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_service_accessor.h
@@ -12,7 +12,7 @@ #include "base/macros.h" #include "components/metrics/metrics_service_accessor.h" -class IOSChromeDataReductionProxySettings; +class OptimizationGuideService; namespace { class CrashesDOMHandler; @@ -32,7 +32,7 @@ friend class IOSChromeMetricsServicesManagerClient; friend class CrashesDOMHandler; - friend class IOSChromeDataReductionProxySettings; + friend class OptimizationGuideService; friend class IOSChromeMainParts; FRIEND_TEST_ALL_PREFIXES(IOSChromeMetricsServiceAccessorTest,
diff --git a/ios/chrome/browser/optimization_guide/BUILD.gn b/ios/chrome/browser/optimization_guide/BUILD.gn index 26ffe14..6f7cfb3 100644 --- a/ios/chrome/browser/optimization_guide/BUILD.gn +++ b/ios/chrome/browser/optimization_guide/BUILD.gn
@@ -4,10 +4,12 @@ source_set("optimization_guide") { sources = [ - "optimization_guide_service.cc", + "ios_chrome_hints_manager.h", + "ios_chrome_hints_manager.mm", "optimization_guide_service.h", - "optimization_guide_service_factory.cc", + "optimization_guide_service.mm", "optimization_guide_service_factory.h", + "optimization_guide_service_factory.mm", "tab_url_provider_impl.h", "tab_url_provider_impl.mm", ] @@ -15,10 +17,13 @@ "//base", "//components/keyed_service/core", "//components/keyed_service/ios", + "//components/leveldb_proto", "//components/optimization_guide/core", + "//components/optimization_guide/proto:optimization_guide_proto", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/main:public", + "//ios/chrome/browser/metrics", "//ios/chrome/browser/web_state_list", "//ios/web", ] @@ -30,18 +35,26 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ - "optimization_guide_service_factory_unittest.cc", + "optimization_guide_service_factory_unittest.mm", + "optimization_guide_service_unittest.mm", "tab_url_provider_impl_unittest.mm", ] deps = [ ":optimization_guide", "//base/test:test_support", "//components/optimization_guide/core", + "//components/optimization_guide/core:test_support", + "//components/sync_preferences", + "//components/sync_preferences:test_support", + "//components/ukm:test_support", + "//components/unified_consent", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/main:public", "//ios/chrome/browser/main:test_support", + "//ios/chrome/browser/prefs:browser_prefs", "//ios/chrome/browser/web_state_list", "//ios/web/public/test/fakes", + "//services/metrics/public/cpp:ukm_builders", "//testing/gtest", ] }
diff --git a/ios/chrome/browser/optimization_guide/DEPS b/ios/chrome/browser/optimization_guide/DEPS new file mode 100644 index 0000000..05eea6c --- /dev/null +++ b/ios/chrome/browser/optimization_guide/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+components/optimization_guide/core", + "+components/optimization_guide/proto", + "+ios/web/public", +]
diff --git a/ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.h b/ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.h new file mode 100644 index 0000000..da92908 --- /dev/null +++ b/ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.h
@@ -0,0 +1,35 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_IOS_CHROME_HINTS_MANAGER_H_ +#define IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_IOS_CHROME_HINTS_MANAGER_H_ + +#include "components/optimization_guide/core/hints_manager.h" + +namespace web { +class BrowserState; +} // namespace web + +namespace optimization_guide { + +class IOSChromeHintsManager : public HintsManager { + public: + IOSChromeHintsManager( + web::BrowserState* browser_state, + PrefService* pref_service, + optimization_guide::OptimizationGuideStore* hint_store, + optimization_guide::TopHostProvider* top_host_provider, + optimization_guide::TabUrlProvider* tab_url_provider, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + network::NetworkConnectionTracker* network_connection_tracker); + + ~IOSChromeHintsManager() override = default; + + IOSChromeHintsManager(const IOSChromeHintsManager&) = delete; + IOSChromeHintsManager& operator=(const IOSChromeHintsManager&) = delete; +}; + +} // namespace optimization_guide + +#endif // IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_IOS_CHROME_HINTS_MANAGER_H_
diff --git a/ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.mm b/ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.mm new file mode 100644 index 0000000..fcba3cb --- /dev/null +++ b/ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.mm
@@ -0,0 +1,35 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.h" + +#import "ios/chrome/browser/application_context.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "services/network/public/cpp/shared_url_loader_factory.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace optimization_guide { + +IOSChromeHintsManager::IOSChromeHintsManager( + web::BrowserState* browser_state, + PrefService* pref_service, + optimization_guide::OptimizationGuideStore* hint_store, + optimization_guide::TopHostProvider* top_host_provider, + optimization_guide::TabUrlProvider* tab_url_provider, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + network::NetworkConnectionTracker* network_connection_tracker) + : HintsManager(browser_state->IsOffTheRecord(), + GetApplicationContext()->GetApplicationLocale(), + pref_service, + hint_store, + top_host_provider, + tab_url_provider, + url_loader_factory, + network_connection_tracker, + /*push_notification_manager=*/nullptr) {} + +} // namespace optimization_guide
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service.cc b/ios/chrome/browser/optimization_guide/optimization_guide_service.cc deleted file mode 100644 index bd93a08d..0000000 --- a/ios/chrome/browser/optimization_guide/optimization_guide_service.cc +++ /dev/null
@@ -1,8 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ios/chrome/browser/optimization_guide/optimization_guide_service.h" - -OptimizationGuideService::OptimizationGuideService() = default; -OptimizationGuideService::~OptimizationGuideService() = default;
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service.h b/ios/chrome/browser/optimization_guide/optimization_guide_service.h index 35ed2f3..b01854e 100644 --- a/ios/chrome/browser/optimization_guide/optimization_guide_service.h +++ b/ios/chrome/browser/optimization_guide/optimization_guide_service.h
@@ -5,17 +5,101 @@ #ifndef IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SERVICE_H_ #define IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SERVICE_H_ +#include <vector> + +#include "base/callback_forward.h" +#include "base/sequence_checker.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/optimization_guide/core/optimization_guide_decision.h" +#include "components/optimization_guide/core/optimization_metadata.h" +#include "components/optimization_guide/proto/hints.pb.h" +#include "url/gurl.h" + +namespace optimization_guide { +class TabUrlProvider; +class TopHostProvider; +class OptimizationGuideStore; +class HintsManager; +} // namespace optimization_guide + +class OptimizationGuideNavigationData; + +namespace web { +class BrowserState; +class NavigationContext; +} // namespace web // A BrowserState keyed service that is used to own the underlying Optimization -// Guide components. +// Guide components. This is a rough copy of the OptimizationGuideKeyedService +// in //chrome/browser that is used for non-iOS. It cannot be directly used due +// to the platform differences of the common data structures - +// NavigationContext vs NavigationHandle, BrowserState vs Profile, etc. +// TODO(crbug.com/1240907): Add support for clearing the hints when browsing +// data is cleared. class OptimizationGuideService : public KeyedService { public: - OptimizationGuideService(); + explicit OptimizationGuideService(web::BrowserState* browser_state); ~OptimizationGuideService() override; OptimizationGuideService(const OptimizationGuideService&) = delete; OptimizationGuideService& operator=(const OptimizationGuideService&) = delete; + + // Registers the optimization types that intend to be queried during the + // session. It is expected for this to be called right after the browser has + // been initialized. + void RegisterOptimizationTypes( + const std::vector<optimization_guide::proto::OptimizationType>& + optimization_types); + + // Returns whether |optimization_type| can be applied for |url|. This should + // only be called for main frame navigations or future main frame navigations. + optimization_guide::OptimizationGuideDecision CanApplyOptimization( + const GURL& url, + optimization_guide::proto::OptimizationType optimization_type, + optimization_guide::OptimizationMetadata* optimization_metadata); + + // Invokes |callback| with the decision for the URL contained in + // |navigation_context| and |optimization_type|, when sufficient information + // has been collected to make the decision. This should only be called for + // main frame navigations. + void CanApplyOptimizationAsync( + web::NavigationContext* navigation_context, + optimization_guide::proto::OptimizationType optimization_type, + optimization_guide::OptimizationGuideDecisionCallback callback); + + private: + friend class OptimizationGuideServiceTest; + + // Notifies |hints_manager_| that the navigation associated with + // |navigation_data| has started or redirected. + void OnNavigationStartOrRedirect( + OptimizationGuideNavigationData* navigation_data); + + // Notifies |hints_manager_| that the navigation associated with + // |navigation_redirect_chain| has finished. + void OnNavigationFinish(const std::vector<GURL>& navigation_redirect_chain); + + // KeyedService implementation: + void Shutdown() override; + + optimization_guide::HintsManager* GetHintsManager(); + + // The store of hints. + std::unique_ptr<optimization_guide::OptimizationGuideStore> hint_store_; + + // Manages the storing, loading, and fetching of hints. + std::unique_ptr<optimization_guide::HintsManager> hints_manager_; + + // The top host provider to use for fetching information for the user's top + // hosts. Will be null if the user has not consented to this type of browser + // behavior. + std::unique_ptr<optimization_guide::TopHostProvider> top_host_provider_; + + // The tab URL provider to use for fetching information for the user's active + // tabs. Will be null if the user is off the record. + std::unique_ptr<optimization_guide::TabUrlProvider> tab_url_provider_; + + SEQUENCE_CHECKER(sequence_checker_); }; #endif // IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SERVICE_H_
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service.mm b/ios/chrome/browser/optimization_guide/optimization_guide_service.mm new file mode 100644 index 0000000..360ce4d3 --- /dev/null +++ b/ios/chrome/browser/optimization_guide/optimization_guide_service.mm
@@ -0,0 +1,158 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/optimization_guide/optimization_guide_service.h" + +#import "base/callback.h" +#import "base/metrics/histogram_functions.h" +#import "base/task/thread_pool.h" +#import "base/time/default_clock.h" +#import "components/optimization_guide/core/command_line_top_host_provider.h" +#import "components/optimization_guide/core/hints_processing_util.h" +#import "components/optimization_guide/core/optimization_guide_constants.h" +#import "components/optimization_guide/core/optimization_guide_features.h" +#import "components/optimization_guide/core/optimization_guide_navigation_data.h" +#import "components/optimization_guide/core/optimization_guide_permissions_util.h" +#import "components/optimization_guide/core/optimization_guide_store.h" +#import "components/optimization_guide/core/optimization_guide_util.h" +#import "components/optimization_guide/core/top_host_provider.h" +#import "ios/chrome/browser/application_context.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/metrics/ios_chrome_metrics_service_accessor.h" +#import "ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.h" +#import "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h" +#import "ios/chrome/browser/optimization_guide/tab_url_provider_impl.h" +#import "ios/web/public/navigation/navigation_context.h" +#import "services/network/public/cpp/shared_url_loader_factory.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +OptimizationGuideService::OptimizationGuideService( + web::BrowserState* browser_state) { + DCHECK(optimization_guide::features::IsOptimizationHintsEnabled()); + + ChromeBrowserState* chrome_browser_state = + ChromeBrowserState::FromBrowserState(browser_state); + DCHECK(chrome_browser_state); + + // TODO(crbug.com/1239388): Handle incognito profile in IOS, the same way its + // handled in other platforms. + DCHECK(!browser_state->IsOffTheRecord()); + + // Regardless of whether the profile is off the record or not, initialize the + // Optimization Guide with the database associated with the original profile. + auto* proto_db_provider = + chrome_browser_state->GetOriginalChromeBrowserState() + ->GetProtoDatabaseProvider(); + base::FilePath profile_path = + chrome_browser_state->GetOriginalChromeBrowserState()->GetStatePath(); + + // Only create a top host provider from the command line if provided. + top_host_provider_ = + optimization_guide::CommandLineTopHostProvider::CreateIfEnabled(); + tab_url_provider_ = std::make_unique<TabUrlProviderImpl>( + chrome_browser_state, base::DefaultClock::GetInstance()); + + hint_store_ = + optimization_guide::features::ShouldPersistHintsToDisk() + ? std::make_unique<optimization_guide::OptimizationGuideStore>( + proto_db_provider, + profile_path.Append( + optimization_guide::kOptimizationGuideHintStore), + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT})) + : nullptr; + + hints_manager_ = std::make_unique<optimization_guide::IOSChromeHintsManager>( + browser_state, chrome_browser_state->GetPrefs(), hint_store_.get(), + top_host_provider_.get(), tab_url_provider_.get(), + browser_state->GetSharedURLLoaderFactory(), + GetApplicationContext()->GetNetworkConnectionTracker()); + + bool optimization_guide_fetching_enabled = + optimization_guide::IsUserPermittedToFetchFromRemoteOptimizationGuide( + browser_state->IsOffTheRecord(), chrome_browser_state->GetPrefs()); + base::UmaHistogramBoolean("OptimizationGuide.RemoteFetchingEnabled", + optimization_guide_fetching_enabled); + IOSChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial( + "SyntheticOptimizationGuideRemoteFetching", + optimization_guide_fetching_enabled ? "Enabled" : "Disabled"); +} + +OptimizationGuideService::~OptimizationGuideService() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +optimization_guide::HintsManager* OptimizationGuideService::GetHintsManager() { + return hints_manager_.get(); +} + +void OptimizationGuideService::OnNavigationStartOrRedirect( + OptimizationGuideNavigationData* navigation_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(navigation_data); + + base::flat_set<optimization_guide::proto::OptimizationType> + registered_optimization_types = + hints_manager_->registered_optimization_types(); + if (!registered_optimization_types.empty()) { + hints_manager_->OnNavigationStartOrRedirect(navigation_data, + base::DoNothing()); + } + + navigation_data->set_registered_optimization_types( + hints_manager_->registered_optimization_types()); +} + +void OptimizationGuideService::OnNavigationFinish( + const std::vector<GURL>& navigation_redirect_chain) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + hints_manager_->OnNavigationFinish(navigation_redirect_chain); +} + +void OptimizationGuideService::RegisterOptimizationTypes( + const std::vector<optimization_guide::proto::OptimizationType>& + optimization_types) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + hints_manager_->RegisterOptimizationTypes(optimization_types); +} + +optimization_guide::OptimizationGuideDecision +OptimizationGuideService::CanApplyOptimization( + const GURL& url, + optimization_guide::proto::OptimizationType optimization_type, + optimization_guide::OptimizationMetadata* optimization_metadata) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + optimization_guide::OptimizationTypeDecision optimization_type_decision = + hints_manager_->CanApplyOptimization(url, /*navigation_id=*/absl::nullopt, + optimization_type, + optimization_metadata); + base::UmaHistogramEnumeration( + "OptimizationGuide.ApplyDecision." + + optimization_guide::GetStringNameForOptimizationType( + optimization_type), + optimization_type_decision); + return optimization_guide::HintsManager:: + GetOptimizationGuideDecisionFromOptimizationTypeDecision( + optimization_type_decision); +} + +void OptimizationGuideService::CanApplyOptimizationAsync( + web::NavigationContext* navigation_context, + optimization_guide::proto::OptimizationType optimization_type, + optimization_guide::OptimizationGuideDecisionCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + hints_manager_->CanApplyOptimizationAsync( + navigation_context->GetUrl(), navigation_context->GetNavigationId(), + optimization_type, std::move(callback)); +} + +void OptimizationGuideService::Shutdown() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + hints_manager_->Shutdown(); +}
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.cc b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.cc deleted file mode 100644 index 0cd5f537..0000000 --- a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h" - -#include "components/keyed_service/ios/browser_state_dependency_manager.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/main/browser_list_factory.h" -#include "ios/chrome/browser/optimization_guide/optimization_guide_service.h" - -// static -OptimizationGuideService* OptimizationGuideServiceFactory::GetForBrowserState( - ChromeBrowserState* context) { - return static_cast<OptimizationGuideService*>( - GetInstance()->GetServiceForBrowserState(context, /*create=*/true)); -} - -// static -OptimizationGuideServiceFactory* -OptimizationGuideServiceFactory::GetInstance() { - static base::NoDestructor<OptimizationGuideServiceFactory> instance; - return instance.get(); -} - -OptimizationGuideServiceFactory::OptimizationGuideServiceFactory() - : BrowserStateKeyedServiceFactory( - "OptimizationGuideService", - BrowserStateDependencyManager::GetInstance()) { - DependsOn(BrowserListFactory::GetInstance()); -} - -OptimizationGuideServiceFactory::~OptimizationGuideServiceFactory() = default; - -std::unique_ptr<KeyedService> -OptimizationGuideServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return std::make_unique<OptimizationGuideService>(); -}
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h index 6ba3d36..5cf2fc95 100644 --- a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h +++ b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h
@@ -37,6 +37,7 @@ // BrowserStateKeyedServiceFactory: std::unique_ptr<KeyedService> BuildServiceInstanceFor( web::BrowserState* context) const override; + bool ServiceIsCreatedWithBrowserState() const override; }; #endif // IOS_CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.mm b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.mm new file mode 100644 index 0000000..f2d0ab2 --- /dev/null +++ b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory.mm
@@ -0,0 +1,51 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h" + +#import "base/feature_list.h" +#import "components/keyed_service/ios/browser_state_dependency_manager.h" +#import "components/optimization_guide/core/optimization_guide_features.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/main/browser_list_factory.h" +#import "ios/chrome/browser/optimization_guide/optimization_guide_service.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// static +OptimizationGuideService* OptimizationGuideServiceFactory::GetForBrowserState( + ChromeBrowserState* context) { + if (!optimization_guide::features::IsOptimizationHintsEnabled()) + return nullptr; + return static_cast<OptimizationGuideService*>( + GetInstance()->GetServiceForBrowserState(context, /*create=*/true)); +} + +// static +OptimizationGuideServiceFactory* +OptimizationGuideServiceFactory::GetInstance() { + static base::NoDestructor<OptimizationGuideServiceFactory> instance; + return instance.get(); +} + +OptimizationGuideServiceFactory::OptimizationGuideServiceFactory() + : BrowserStateKeyedServiceFactory( + "OptimizationGuideService", + BrowserStateDependencyManager::GetInstance()) { + DependsOn(BrowserListFactory::GetInstance()); +} + +OptimizationGuideServiceFactory::~OptimizationGuideServiceFactory() = default; + +std::unique_ptr<KeyedService> +OptimizationGuideServiceFactory::BuildServiceInstanceFor( + web::BrowserState* context) const { + return std::make_unique<OptimizationGuideService>(context); +} + +bool OptimizationGuideServiceFactory::ServiceIsCreatedWithBrowserState() const { + return optimization_guide::features::IsOptimizationHintsEnabled(); +}
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory_unittest.cc b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory_unittest.cc deleted file mode 100644 index 09834d5..0000000 --- a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory_unittest.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h" - -#include "base/test/task_environment.h" -#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#include "ios/chrome/browser/optimization_guide/optimization_guide_service.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -namespace { - -class OptimizationGuideServiceFactoryTest : public PlatformTest { - public: - OptimizationGuideServiceFactoryTest() { - TestChromeBrowserState::Builder builder; - browser_state_ = builder.Build(); - } - - ChromeBrowserState* browser_state() { return browser_state_.get(); } - - private: - base::test::TaskEnvironment task_environment_; - std::unique_ptr<ChromeBrowserState> browser_state_; -}; - -TEST_F(OptimizationGuideServiceFactoryTest, CheckNormalServiceNotNull) { - EXPECT_NE(nullptr, OptimizationGuideServiceFactory::GetForBrowserState( - browser_state())); -} - -TEST_F(OptimizationGuideServiceFactoryTest, CheckIncogitoServiceNull) { - EXPECT_EQ(nullptr, OptimizationGuideServiceFactory::GetForBrowserState( - browser_state()->GetOffTheRecordChromeBrowserState())); -} - -} // namespace
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service_factory_unittest.mm b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory_unittest.mm new file mode 100644 index 0000000..9897f2c2 --- /dev/null +++ b/ios/chrome/browser/optimization_guide/optimization_guide_service_factory_unittest.mm
@@ -0,0 +1,75 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h" + +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#import "components/optimization_guide/core/optimization_guide_features.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/chrome/browser/optimization_guide/optimization_guide_service.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +class OptimizationGuideServiceFactoryTest : public PlatformTest { + public: + OptimizationGuideServiceFactoryTest() = default; + ~OptimizationGuideServiceFactoryTest() override = default; + + void SetUp() override { + PlatformTest::SetUp(); + scoped_feature_list_.InitWithFeatures( + {optimization_guide::features::kOptimizationHints}, {}); + TestChromeBrowserState::Builder builder; + browser_state_ = builder.Build(); + } + + protected: + base::test::TaskEnvironment task_environment_; + std::unique_ptr<ChromeBrowserState> browser_state_; + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(OptimizationGuideServiceFactoryTest, CheckNormalServiceNotNull) { + EXPECT_NE(nullptr, OptimizationGuideServiceFactory::GetForBrowserState( + browser_state_.get())); +} + +TEST_F(OptimizationGuideServiceFactoryTest, CheckIncogitoServiceNull) { + EXPECT_EQ(nullptr, OptimizationGuideServiceFactory::GetForBrowserState( + browser_state_->GetOffTheRecordChromeBrowserState())); +} + +class OptimizationGuideServiceFactoryFeatureDisabledTest : public PlatformTest { + public: + OptimizationGuideServiceFactoryFeatureDisabledTest() = default; + ~OptimizationGuideServiceFactoryFeatureDisabledTest() override = default; + + void SetUp() override { + PlatformTest::SetUp(); + scoped_feature_list_.InitAndDisableFeature( + {optimization_guide::features::kOptimizationHints}); + TestChromeBrowserState::Builder builder; + browser_state_ = builder.Build(); + } + + protected: + base::test::TaskEnvironment task_environment_; + std::unique_ptr<ChromeBrowserState> browser_state_; + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(OptimizationGuideServiceFactoryFeatureDisabledTest, + CheckServiceNullWithoutOptimizationGuideHintsFeature) { + EXPECT_EQ(nullptr, OptimizationGuideServiceFactory::GetForBrowserState( + browser_state_.get())); +} + +} // namespace
diff --git a/ios/chrome/browser/optimization_guide/optimization_guide_service_unittest.mm b/ios/chrome/browser/optimization_guide/optimization_guide_service_unittest.mm new file mode 100644 index 0000000..29ce0947 --- /dev/null +++ b/ios/chrome/browser/optimization_guide/optimization_guide_service_unittest.mm
@@ -0,0 +1,512 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/optimization_guide/optimization_guide_service.h" + +#import "base/test/ios/wait_util.h" +#import "base/test/metrics/histogram_tester.h" +#import "base/test/scoped_feature_list.h" +#import "base/test/task_environment.h" +#import "components/optimization_guide/core/hints_component_util.h" +#import "components/optimization_guide/core/optimization_guide_features.h" +#import "components/optimization_guide/core/optimization_guide_navigation_data.h" +#import "components/optimization_guide/core/optimization_guide_switches.h" +#import "components/optimization_guide/core/optimization_guide_test_util.h" +#import "components/optimization_guide/core/optimization_hints_component_update_listener.h" +#import "components/optimization_guide/core/test_hints_component_creator.h" +#import "components/sync_preferences/pref_service_syncable.h" +#import "components/sync_preferences/testing_pref_service_syncable.h" +#import "components/ukm/test_ukm_recorder.h" +#import "components/unified_consent/pref_names.h" +#import "components/unified_consent/unified_consent_service.h" +#import "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/optimization_guide/ios_chrome_hints_manager.h" +#import "ios/chrome/browser/optimization_guide/optimization_guide_service_factory.h" +#import "ios/chrome/browser/prefs/browser_prefs.h" +#import "ios/web/public/navigation/navigation_manager.h" +#import "ios/web/public/test/fakes/fake_navigation_context.h" +#import "services/metrics/public/cpp/ukm_builders.h" +#import "services/metrics/public/cpp/ukm_source.h" +#import "testing/gtest/include/gtest/gtest.h" +#import "testing/platform_test.h" +#import "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// These tests are roughly similarly to the tests in +// optimization_guide_keyed_service_browsertest.cc + +namespace { + +constexpr char kHintsURL[] = "https://hints.com/with_hints.html"; +constexpr char kNoHintsURL[] = "https://nohints.com/no_hints.html"; +constexpr char kRedirectURL[] = "https://hints.com/redirect.html"; + +// Wraps the NavigationContext and OptimizationGuideNavigationData together for +// tests. +class NavigationContextAndData { + public: + explicit NavigationContextAndData(const std::string& url) { + navigation_context_ = std::make_unique<web::FakeNavigationContext>(); + navigation_context_->SetUrl(GURL(url)); + navigation_data_ = std::make_unique<OptimizationGuideNavigationData>( + navigation_context_->GetNavigationId(), + /*navigation_start=*/base::TimeTicks::Now()); + navigation_data_->set_navigation_url(navigation_context_->GetUrl()); + } + + std::unique_ptr<web::FakeNavigationContext> navigation_context_; + std::unique_ptr<OptimizationGuideNavigationData> navigation_data_; +}; + +void RetryForHistogramUntilCountReached( + const base::HistogramTester* histogram_tester, + const std::string& histogram_name, + int count) { + EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForPageLoadTimeout, ^{ + base::RunLoop().RunUntilIdle(); + int total = 0; + for (const auto& bucket : + histogram_tester->GetAllSamples(histogram_name)) { + total += bucket.count; + } + return total >= count; + })); +} + +} // namespace + +class OptimizationGuideServiceTest : public PlatformTest { + public: + OptimizationGuideServiceTest() { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + optimization_guide::switches::kPurgeHintsStore); + + // The tests are run in the same process and share the same + // OptimizationHintsComponentUpdateListener due to the global object usage + // in GetInstance(). So reset the state for each test. + optimization_guide::OptimizationHintsComponentUpdateListener::GetInstance() + ->ResetStateForTesting(); + } + + ~OptimizationGuideServiceTest() override = default; + + void SetUp() override { + PlatformTest::SetUp(); + auto testing_prefs = + std::make_unique<sync_preferences::TestingPrefServiceSyncable>(); + RegisterBrowserStatePrefs(testing_prefs->registry()); + + std::vector<base::Feature> enabled_features; + enabled_features.push_back( + optimization_guide::features::kOptimizationHints); + if (url_keyed_anonymized_data_collection_enabled_) { + enabled_features.push_back( + optimization_guide::features:: + kRemoteOptimizationGuideFetchingAnonymousDataConsent); + testing_prefs->SetBoolean( + unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, + true); + } + scoped_feature_list_.InitWithFeatures(enabled_features, {}); + + TestChromeBrowserState::Builder builder; + builder.SetPrefService(std::move(testing_prefs)); + browser_state_ = builder.Build(); + optimization_guide_service_ = + OptimizationGuideServiceFactory::GetForBrowserState( + browser_state_.get()); + } + + void PushHintsComponentAndWaitForCompletion() { + base::RunLoop run_loop; + optimization_guide_service() + ->GetHintsManager() + ->ListenForNextUpdateForTesting(run_loop.QuitClosure()); + GURL hints_url(kHintsURL); + + const optimization_guide::HintsComponentInfo& component_info = + test_hints_component_creator_.CreateHintsComponentInfoWithPageHints( + optimization_guide::proto::NOSCRIPT, {hints_url.host()}, + hints_url.path().substr(1)); + + optimization_guide::OptimizationHintsComponentUpdateListener::GetInstance() + ->MaybeUpdateHintsComponent(component_info); + + run_loop.Run(); + RunUntilIdle(); + } + + void SimulateNavigation( + NavigationContextAndData* context_and_data, + const absl::optional<GURL> redirect_url = absl::nullopt) { + std::vector<GURL> navigation_redirect_chain; + navigation_redirect_chain.push_back( + context_and_data->navigation_context_->GetUrl()); + + optimization_guide_service_->OnNavigationStartOrRedirect( + context_and_data->navigation_data_.get()); + RunUntilIdle(); + + if (redirect_url) { + context_and_data->navigation_data_->set_navigation_url(*redirect_url); + optimization_guide_service_->OnNavigationStartOrRedirect( + context_and_data->navigation_data_.get()); + navigation_redirect_chain.push_back(*redirect_url); + RunUntilIdle(); + } + + optimization_guide_service_->OnNavigationFinish(navigation_redirect_chain); + RunUntilIdle(); + } + + void RegisterWithKeyedService() { + optimization_guide_service()->RegisterOptimizationTypes( + {optimization_guide::proto::NOSCRIPT}); + } + + // Calls the |CanApplyOptimizationAsync| and expects |expected_decision| when + // the decision is returned. |on_decision_callback| is called when the + // decision is called. + void VerifyCanApplyOptimizationAsyncDecision( + NavigationContextAndData* context_and_data, + base::OnceClosure on_decision_callback, + optimization_guide::OptimizationGuideDecision expected_decision) { + optimization_guide_service()->CanApplyOptimizationAsync( + context_and_data->navigation_context_.get(), + optimization_guide::proto::NOSCRIPT, + base::BindOnce( + [](base::OnceClosure on_decision_callback, + optimization_guide::OptimizationGuideDecision expected_decision, + optimization_guide::OptimizationGuideDecision decision, + const optimization_guide::OptimizationMetadata& metadata) { + EXPECT_EQ(expected_decision, decision); + std::move(on_decision_callback).Run(); + }, + std::move(on_decision_callback), expected_decision)); + } + + void SetUrlKeyedAnonymizedDataCollectionEnabled(bool enabled) { + url_keyed_anonymized_data_collection_enabled_ = enabled; + } + + void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } + + OptimizationGuideService* optimization_guide_service() { + return optimization_guide_service_; + } + + base::HistogramTester* histogram_tester() { return &histogram_tester_; } + + TestChromeBrowserState* browser_state() { return browser_state_.get(); } + + protected: + base::test::TaskEnvironment task_environment_; + base::HistogramTester histogram_tester_; + std::unique_ptr<TestChromeBrowserState> browser_state_; + OptimizationGuideService* optimization_guide_service_; + base::test::ScopedFeatureList scoped_feature_list_; + optimization_guide::testing::TestHintsComponentCreator + test_hints_component_creator_; + bool url_keyed_anonymized_data_collection_enabled_ = false; +}; + +TEST_F(OptimizationGuideServiceTest, RemoteFetchingDisabled) { + histogram_tester()->ExpectUniqueSample( + "OptimizationGuide.RemoteFetchingEnabled", false, 1); + // TODO(crbug.com/1240912): Verify the optimization guide fetching synthetic + // field trial is recorded. +} + +TEST_F(OptimizationGuideServiceTest, + NavigateToPageWithHintsButNoRegistrationDoesNotAttemptToLoadHint) { + ukm::TestAutoSetUkmRecorder ukm_recorder; + + PushHintsComponentAndWaitForCompletion(); + + NavigationContextAndData context_and_data(kHintsURL); + SimulateNavigation(&context_and_data); + + histogram_tester()->ExpectTotalCount("OptimizationGuide.LoadedHint.Result", + 0); + + // Navigate away so UKM get recorded. + context_and_data = NavigationContextAndData(kHintsURL); + SimulateNavigation(&context_and_data); + + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::OptimizationGuide::kEntryName); + EXPECT_EQ(0u, entries.size()); +} + +TEST_F(OptimizationGuideServiceTest, + NavigateToPageWithAsyncCallbackReturnsAnswerRedirect) { + PushHintsComponentAndWaitForCompletion(); + RegisterWithKeyedService(); + + auto run_loop = std::make_unique<base::RunLoop>(); + NavigationContextAndData context_and_data(kRedirectURL); + + VerifyCanApplyOptimizationAsyncDecision( + &context_and_data, run_loop->QuitClosure(), + optimization_guide::OptimizationGuideDecision::kFalse); + + SimulateNavigation(&context_and_data, + /*redirect_url=*/GURL(kNoHintsURL)); + run_loop->Run(); +} + +TEST_F(OptimizationGuideServiceTest, + NavigateToPageWithAsyncCallbackReturnsAnswer) { + PushHintsComponentAndWaitForCompletion(); + RegisterWithKeyedService(); + + auto run_loop = std::make_unique<base::RunLoop>(); + NavigationContextAndData context_and_data(kHintsURL); + + VerifyCanApplyOptimizationAsyncDecision( + &context_and_data, run_loop->QuitClosure(), + optimization_guide::OptimizationGuideDecision::kTrue); + + SimulateNavigation(&context_and_data); + run_loop->Run(); +} + +TEST_F(OptimizationGuideServiceTest, + NavigateToPageWithAsyncCallbackReturnsAnswerEventually) { + PushHintsComponentAndWaitForCompletion(); + RegisterWithKeyedService(); + + auto run_loop = std::make_unique<base::RunLoop>(); + NavigationContextAndData context_and_data(kNoHintsURL); + + VerifyCanApplyOptimizationAsyncDecision( + &context_and_data, run_loop->QuitClosure(), + optimization_guide::OptimizationGuideDecision::kFalse); + + SimulateNavigation(&context_and_data); + run_loop->Run(); +} + +TEST_F(OptimizationGuideServiceTest, NavigateToPageWithHintsLoadsHint) { + PushHintsComponentAndWaitForCompletion(); + RegisterWithKeyedService(); + + ukm::TestAutoSetUkmRecorder ukm_recorder; + base::HistogramTester histogram_tester; + + NavigationContextAndData context_and_data(kHintsURL); + SimulateNavigation(&context_and_data); + + auto decision = optimization_guide_service()->CanApplyOptimization( + GURL(kHintsURL), optimization_guide::proto::NOSCRIPT, + /*optimization_metadata=*/nullptr); + RetryForHistogramUntilCountReached(&histogram_tester, + "OptimizationGuide.LoadedHint.Result", 1); + + // There is a hint that matches this URL, so there should be an attempt to + // load a hint that succeeds. + histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result", + true, 1); + // We had a hint and it was loaded. + EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue, decision); + + // Navigate away so UKM get recorded. + context_and_data = NavigationContextAndData(kHintsURL); + SimulateNavigation(&context_and_data); + + // Expect that UKM is recorded. + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::OptimizationGuide::kEntryName); + ASSERT_EQ(1u, entries.size()); + auto* entry = entries[0]; + EXPECT_TRUE(ukm_recorder.EntryHasMetric( + entry, + ukm::builders::OptimizationGuide::kRegisteredOptimizationTypesName)); + // NOSCRIPT = 1, so bit mask is 10, which equals 2. + ukm_recorder.ExpectEntryMetric( + entry, ukm::builders::OptimizationGuide::kRegisteredOptimizationTypesName, + 2); +} + +TEST_F(OptimizationGuideServiceTest, + RecordsMetricsWhenNavigationDataDestroyed) { + PushHintsComponentAndWaitForCompletion(); + RegisterWithKeyedService(); + + ukm::TestAutoSetUkmRecorder ukm_recorder; + base::HistogramTester histogram_tester; + + auto context_and_data = std::make_unique<NavigationContextAndData>(kHintsURL); + SimulateNavigation(context_and_data.get()); + auto decision = optimization_guide_service()->CanApplyOptimization( + GURL(kHintsURL), optimization_guide::proto::NOSCRIPT, + /*optimization_metadata=*/nullptr); + + RetryForHistogramUntilCountReached(&histogram_tester, + "OptimizationGuide.LoadedHint.Result", 1); + + // There is a hint that matches this URL, so there should be an attempt to + // load a hint that succeeds. + histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result", + true, 1); + // We had a hint and it was loaded. + EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue, decision); + + // Make sure metrics get recorded when navigation data is destroyed. + context_and_data.reset(); + RunUntilIdle(); + + // Expect that the optimization guide UKM is recorded. + auto entries = ukm_recorder.GetEntriesByName( + ukm::builders::OptimizationGuide::kEntryName); + EXPECT_EQ(1u, entries.size()); + auto* entry = entries[0]; + EXPECT_TRUE(ukm_recorder.EntryHasMetric( + entry, + ukm::builders::OptimizationGuide::kRegisteredOptimizationTypesName)); + // NOSCRIPT = 1, so bit mask is 10, which equals 2. + ukm_recorder.ExpectEntryMetric( + entry, ukm::builders::OptimizationGuide::kRegisteredOptimizationTypesName, + 2); +} + +TEST_F(OptimizationGuideServiceTest, + NavigateToPageThatRedirectsToUrlWithHintsShouldAttemptTwoLoads) { + PushHintsComponentAndWaitForCompletion(); + RegisterWithKeyedService(); + + base::HistogramTester histogram_tester; + + NavigationContextAndData context_and_data(kRedirectURL); + SimulateNavigation(&context_and_data, + /*redirect_url=*/GURL(kHintsURL)); + auto decision = optimization_guide_service()->CanApplyOptimization( + GURL(kHintsURL), optimization_guide::proto::NOSCRIPT, + /*optimization_metadata=*/nullptr); + + RetryForHistogramUntilCountReached(&histogram_tester, + "OptimizationGuide.LoadedHint.Result", 2); + + // Should attempt and succeed to load a hint once for the initial navigation + // and redirect. + histogram_tester.ExpectBucketCount("OptimizationGuide.LoadedHint.Result", + true, 2); + // Hint is still applicable so we expect it to be allowed to be applied. + EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kTrue, decision); +} + +TEST_F(OptimizationGuideServiceTest, NavigateToPageWithoutHint) { + PushHintsComponentAndWaitForCompletion(); + RegisterWithKeyedService(); + + base::HistogramTester histogram_tester; + + NavigationContextAndData context_and_data(kNoHintsURL); + SimulateNavigation(&context_and_data); + auto decision = optimization_guide_service()->CanApplyOptimization( + GURL(kNoHintsURL), optimization_guide::proto::NOSCRIPT, + /*optimization_metadata=*/nullptr); + + RetryForHistogramUntilCountReached(&histogram_tester, + "OptimizationGuide.LoadedHint.Result", 1); + + // There were no hints that match this URL, but there should still be an + // attempt to load a hint but still fail. + histogram_tester.ExpectUniqueSample("OptimizationGuide.LoadedHint.Result", + false, 1); + EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse, decision); + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.ApplyDecision.NoScript", + static_cast<int>( + optimization_guide::OptimizationTypeDecision::kNoHintAvailable), + 1); +} + +TEST_F(OptimizationGuideServiceTest, CheckForBlocklistFilter) { + PushHintsComponentAndWaitForCompletion(); + + OptimizationGuideService* ogks = + OptimizationGuideServiceFactory::GetForBrowserState(browser_state()); + + { + base::HistogramTester histogram_tester; + + // Register an optimization type with an optimization filter. + ogks->RegisterOptimizationTypes( + {optimization_guide::proto::FAST_HOST_HINTS}); + // Wait until filter is loaded. This histogram will record twice: once when + // the config is found and once when the filter is created. + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.OptimizationFilterStatus.FastHostHints", 2); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.OptimizationFilterStatus.FastHostHints", + optimization_guide::OptimizationFilterStatus::kFoundServerFilterConfig, + 1); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.OptimizationFilterStatus.FastHostHints", + optimization_guide::OptimizationFilterStatus::kCreatedServerFilter, 1); + + EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse, + ogks->CanApplyOptimization( + GURL("https://blockedhost.com/whatever"), + optimization_guide::proto::FAST_HOST_HINTS, nullptr)); + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.ApplyDecision.FastHostHints", + static_cast<int>(optimization_guide::OptimizationTypeDecision:: + kNotAllowedByOptimizationFilter), + 1); + } + + // Register another type with optimization filter. + { + base::HistogramTester histogram_tester; + ogks->RegisterOptimizationTypes( + {optimization_guide::proto::LITE_PAGE_REDIRECT}); + // Wait until filter is loaded. This histogram will record twice: once when + // the config is found and once when the filter is created. + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.OptimizationFilterStatus.LitePageRedirect", 2); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.OptimizationFilterStatus.LitePageRedirect", + optimization_guide::OptimizationFilterStatus::kCreatedServerFilter, 1); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.OptimizationFilterStatus.LitePageRedirect", + optimization_guide::OptimizationFilterStatus::kFoundServerFilterConfig, + 1); + + // The previously loaded filter should still be loaded and give the same + // result. + EXPECT_EQ(optimization_guide::OptimizationGuideDecision::kFalse, + ogks->CanApplyOptimization( + GURL("https://blockedhost.com/whatever"), + optimization_guide::proto::FAST_HOST_HINTS, nullptr)); + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.ApplyDecision.FastHostHints", + static_cast<int>(optimization_guide::OptimizationTypeDecision:: + kNotAllowedByOptimizationFilter), + 1); + } +} + +class OptimizationGuideServiceMSBBUserTest + : public OptimizationGuideServiceTest { + public: + void SetUp() override { + SetUrlKeyedAnonymizedDataCollectionEnabled(true); + OptimizationGuideServiceTest::SetUp(); + } +}; + +TEST_F(OptimizationGuideServiceMSBBUserTest, RemoteFetchingEnabled) { + histogram_tester()->ExpectUniqueSample( + "OptimizationGuide.RemoteFetchingEnabled", true, 1); + // TODO(crbug.com/1240912): Verify the optimization guide fetching synthetic + // field trial is recorded. +}
diff --git a/ios/chrome/browser/prefs/BUILD.gn b/ios/chrome/browser/prefs/BUILD.gn index f614c2bf..0525a67 100644 --- a/ios/chrome/browser/prefs/BUILD.gn +++ b/ios/chrome/browser/prefs/BUILD.gn
@@ -50,6 +50,7 @@ "//components/ntp_snippets", "//components/ntp_tiles", "//components/omnibox/browser", + "//components/optimization_guide/core", "//components/password_manager/core/browser", "//components/payments/core", "//components/policy/core/browser",
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index d0facd07..c3fb222 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -30,6 +30,7 @@ #include "components/ntp_tiles/most_visited_sites.h" #include "components/ntp_tiles/popular_sites_impl.h" #include "components/omnibox/browser/zero_suggest_provider.h" +#import "components/optimization_guide/core/optimization_guide_prefs.h" #include "components/password_manager/core/browser/password_manager.h" #include "components/payments/core/payment_prefs.h" #include "components/policy/core/browser/browser_policy_connector.h" @@ -204,6 +205,7 @@ ntp_snippets::UserClassifier::RegisterProfilePrefs(registry); ntp_tiles::MostVisitedSites::RegisterProfilePrefs(registry); ntp_tiles::PopularSitesImpl::RegisterProfilePrefs(registry); + optimization_guide::prefs::RegisterProfilePrefs(registry); password_manager::PasswordManager::RegisterProfilePrefs(registry); payments::RegisterProfilePrefs(registry); policy::URLBlocklistManager::RegisterProfilePrefs(registry);
diff --git a/ios/chrome/browser/providers/chromium_browser_provider.h b/ios/chrome/browser/providers/chromium_browser_provider.h index 4a68801..c1efae9 100644 --- a/ios/chrome/browser/providers/chromium_browser_provider.h +++ b/ios/chrome/browser/providers/chromium_browser_provider.h
@@ -14,9 +14,6 @@ // ChromeBrowserProvider implementation ios::SigninResourcesProvider* GetSigninResourcesProvider() override; - void SetChromeIdentityServiceForTesting( - std::unique_ptr<ios::ChromeIdentityService> service) override; - ios::ChromeIdentityService* GetChromeIdentityService() override; UITextField* CreateStyledTextField() const override NS_RETURNS_RETAINED; VoiceSearchProvider* GetVoiceSearchProvider() const override; @@ -25,10 +22,11 @@ UserFeedbackProvider* GetUserFeedbackProvider() const override; OverridesProvider* GetOverridesProvider() const override; DiscoverFeedProvider* GetDiscoverFeedProvider() const override; + std::unique_ptr<ios::ChromeIdentityService> CreateChromeIdentityService() + override; private: std::unique_ptr<ios::SigninResourcesProvider> signin_resources_provider_; - std::unique_ptr<ios::ChromeIdentityService> chrome_identity_service_; std::unique_ptr<UserFeedbackProvider> user_feedback_provider_; std::unique_ptr<VoiceSearchProvider> voice_search_provider_; std::unique_ptr<OverridesProvider> overrides_provider_;
diff --git a/ios/chrome/browser/providers/chromium_browser_provider.mm b/ios/chrome/browser/providers/chromium_browser_provider.mm index 7f7dd1f..edfa63c 100644 --- a/ios/chrome/browser/providers/chromium_browser_provider.mm +++ b/ios/chrome/browser/providers/chromium_browser_provider.mm
@@ -33,20 +33,6 @@ return signin_resources_provider_.get(); } -void ChromiumBrowserProvider::SetChromeIdentityServiceForTesting( - std::unique_ptr<ios::ChromeIdentityService> service) { - chrome_identity_service_ = std::move(service); - FireChromeIdentityServiceDidChange(chrome_identity_service_.get()); -} - -ios::ChromeIdentityService* -ChromiumBrowserProvider::GetChromeIdentityService() { - if (!chrome_identity_service_) { - chrome_identity_service_ = std::make_unique<ios::ChromeIdentityService>(); - } - return chrome_identity_service_.get(); -} - UITextField* ChromiumBrowserProvider::CreateStyledTextField() const { return [[UITextField alloc] initWithFrame:CGRectZero]; } @@ -72,3 +58,8 @@ DiscoverFeedProvider* ChromiumBrowserProvider::GetDiscoverFeedProvider() const { return discover_feed_provider_.get(); } + +std::unique_ptr<ios::ChromeIdentityService> +ChromiumBrowserProvider::CreateChromeIdentityService() { + return std::make_unique<ios::ChromeIdentityService>(); +}
diff --git a/ios/chrome/browser/signin/BUILD.gn b/ios/chrome/browser/signin/BUILD.gn index 14ff068..4d9ed0d2 100644 --- a/ios/chrome/browser/signin/BUILD.gn +++ b/ios/chrome/browser/signin/BUILD.gn
@@ -138,6 +138,7 @@ "gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm", "gaia_auth_fetcher_ios_unittest.mm", "pattern_account_restriction_unittest.mm", + "resized_avatar_cache_unittest.mm", "signin_browser_state_info_updater_unittest.mm", "user_approved_account_list_manager_unittest.mm", ]
diff --git a/ios/chrome/browser/signin/authentication_service.h b/ios/chrome/browser/signin/authentication_service.h index 3587990..80ee50c 100644 --- a/ios/chrome/browser/signin/authentication_service.h +++ b/ios/chrome/browser/signin/authentication_service.h
@@ -34,6 +34,7 @@ // authentication library. class AuthenticationService : public KeyedService, public signin::IdentityManager::Observer, + public ios::ChromeBrowserProvider::Observer, public ios::ChromeIdentityService::Observer, public ChromeAccountManagerService::Observer { public: @@ -127,11 +128,6 @@ // error. Returns true if |identity| had an associated error, false otherwise. bool ShowMDMErrorDialogForIdentity(ChromeIdentity* identity); - // Resets the ChromeIdentityService observer to the one available in the - // ChromeBrowserProvider. Used for testing when changing the - // ChromeIdentityService to or from a fake one. - void ResetChromeIdentityServiceObserverForTesting(); - // Returns a weak pointer of this. base::WeakPtr<AuthenticationService> GetWeakPtr(); @@ -139,6 +135,11 @@ // sync the accounts between the IdentityManager and the SSO library. void OnApplicationWillEnterForeground(); + // ChromeBrowserProvider implementation. + void OnChromeIdentityServiceDidChange( + ios::ChromeIdentityService* new_service) override; + void OnChromeBrowserProviderWillBeDestroyed() override; + private: friend class AuthenticationServiceTest; friend class AuthenticationServiceFake;
diff --git a/ios/chrome/browser/signin/authentication_service.mm b/ios/chrome/browser/signin/authentication_service.mm index b09eb067..c2601c9 100644 --- a/ios/chrome/browser/signin/authentication_service.mm +++ b/ios/chrome/browser/signin/authentication_service.mm
@@ -201,6 +201,16 @@ current_accounts_info); } +void AuthenticationService::OnChromeIdentityServiceDidChange( + ios::ChromeIdentityService* new_service) { + identity_service_observation_.Observe( + ios::GetChromeBrowserProvider().GetChromeIdentityService()); +} + +void AuthenticationService::OnChromeBrowserProviderWillBeDestroyed() { + identity_service_observation_.Reset(); +} + void AuthenticationService::MigrateAccountsStoredInPrefsIfNeeded() { if (identity_manager_->GetAccountIdMigrationState() == signin::IdentityManager::AccountIdMigrationState::MIGRATION_NOT_STARTED) { @@ -412,12 +422,6 @@ return true; } -void AuthenticationService::ResetChromeIdentityServiceObserverForTesting() { - DCHECK(!identity_service_observation_.IsObserving()); - identity_service_observation_.Observe( - ios::GetChromeBrowserProvider().GetChromeIdentityService()); -} - base::WeakPtr<AuthenticationService> AuthenticationService::GetWeakPtr() { return weak_pointer_factory_.GetWeakPtr(); }
diff --git a/ios/chrome/browser/signin/resized_avatar_cache.mm b/ios/chrome/browser/signin/resized_avatar_cache.mm index 664090c..6f092457 100644 --- a/ios/chrome/browser/signin/resized_avatar_cache.mm +++ b/ios/chrome/browser/signin/resized_avatar_cache.mm
@@ -16,18 +16,21 @@ #endif @interface ResizedAvatarCache () + // Size of resized avatar. @property(nonatomic, assign) CGSize expectedSize; +// Default avatar at |self.expectedSize| size. +@property(nonatomic, strong) UIImage* defaultResizedAvatar; +// Retains resized images. Key is Chrome Identity. +@property(nonatomic, strong) NSCache<ChromeIdentity*, UIImage*>* resizedImages; +// Holds weak references to the cached avatar image from the +// ChromeIdentityService. Key is Chrome Identity. +@property(nonatomic, strong) + NSMapTable<ChromeIdentity*, UIImage*>* originalImages; + @end -@implementation ResizedAvatarCache { - // Retains resized images. Key is Chrome Identity. - NSCache<ChromeIdentity*, UIImage*>* _resizedImages; - - // Holds weak references to the cached avatar image from the - // ChromeIdentityService. Key is Chrome Identity. - NSMapTable<ChromeIdentity*, UIImage*>* _originalImages; -} +@implementation ResizedAvatarCache - (instancetype)initWithSize:(CGSize)size { self = [super init]; @@ -35,6 +38,11 @@ _expectedSize = size; _resizedImages = [[NSCache alloc] init]; _originalImages = [NSMapTable strongToWeakObjectsMapTable]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(notificicationReceived:) + name:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; } return self; } @@ -49,12 +57,11 @@ .GetChromeIdentityService() ->GetCachedAvatarForIdentity(identity); if (!image) { - image = ios::provider::GetSigninDefaultAvatar(); - // No cached image, trigger a fetch, which will notify all observers. ios::GetChromeBrowserProvider() .GetChromeIdentityService() ->GetAvatarForIdentity(identity, nil); + return self.defaultResizedAvatar; } // If the currently used image has already been resized, use it. @@ -72,4 +79,22 @@ return image; } +- (void)notificicationReceived:(NSNotification*)notification { + if ([notification.name + isEqual:UIApplicationDidReceiveMemoryWarningNotification]) { + self.defaultResizedAvatar = nil; + } +} + +#pragma mark - Properties + +- (UIImage*)defaultResizedAvatar { + if (!_defaultResizedAvatar) { + UIImage* image = ios::provider::GetSigninDefaultAvatar(); + _defaultResizedAvatar = + ResizeImage(image, self.expectedSize, ProjectionMode::kAspectFit); + } + return _defaultResizedAvatar; +} + @end
diff --git a/ios/chrome/browser/signin/resized_avatar_cache_unittest.mm b/ios/chrome/browser/signin/resized_avatar_cache_unittest.mm new file mode 100644 index 0000000..8e52ec5 --- /dev/null +++ b/ios/chrome/browser/signin/resized_avatar_cache_unittest.mm
@@ -0,0 +1,92 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/signin/resized_avatar_cache.h" + +#import "base/values.h" +#import "ios/chrome/browser/signin/signin_util.h" +#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h" +#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h" +#import "testing/gtest_mac.h" +#import "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Test fixture for testing ResizedAvatarCache class. +class ResizedAvatarCacheTest : public PlatformTest { + protected: + void SetUp() override { + PlatformTest::SetUp(); + identity_service_ = + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider(); + resized_avatar_cache_ = [[ResizedAvatarCache alloc] + initWithIdentityAvatarSize:IdentityAvatarSize::TableViewIcon]; + identity1_ = [FakeChromeIdentity identityWithEmail:@"test1@email.com" + gaiaID:@"gaiaID1" + name:@"Test Name1"]; + identity2_ = [FakeChromeIdentity identityWithEmail:@"test2@email.com" + gaiaID:@"gaiaID2" + name:@"Test Name2"]; + } + + ios::FakeChromeIdentityService* identity_service_ = nil; + ResizedAvatarCache* resized_avatar_cache_ = nil; + ChromeIdentity* identity1_ = nil; + ChromeIdentity* identity2_ = nil; +}; + +// Tests that the default avatar is the same between 2 identities. +TEST_F(ResizedAvatarCacheTest, DefaultAvatarSize) { + UIImage* avatar1 = + [resized_avatar_cache_ resizedAvatarForIdentity:identity1_]; + EXPECT_NE(nil, avatar1); + // Check the size. + CGSize expected_size = + GetSizeForIdentityAvatarSize(IdentityAvatarSize::TableViewIcon); + EXPECT_TRUE(CGSizeEqualToSize(expected_size, avatar1.size)); + // Asking for an avatar on another identity should return the same image: + // the default avatar. + UIImage* avatar2 = + [resized_avatar_cache_ resizedAvatarForIdentity:identity2_]; + EXPECT_EQ(avatar1, avatar2); +} + +// Tests that the avatar is updated after waiting for the fetch. +TEST_F(ResizedAvatarCacheTest, FetchAvatar) { + UIImage* default_avatar = + [resized_avatar_cache_ resizedAvatarForIdentity:identity1_]; + EXPECT_NE(nil, default_avatar); + // Asking again for the avatar, the same image is expected again (default + // avatar). + UIImage* same_default_avatar = + [resized_avatar_cache_ resizedAvatarForIdentity:identity1_]; + EXPECT_EQ(default_avatar, same_default_avatar); + // Wait for the end of the fetch. + identity_service_->WaitForServiceCallbacksToComplete(); + // Asking again, the fecthed avatar is expected (instead of the default + // avatar) + UIImage* identity_avatar = + [resized_avatar_cache_ resizedAvatarForIdentity:identity1_]; + EXPECT_NE(default_avatar, identity_avatar); + // Check the size. + CGSize expected_size = + GetSizeForIdentityAvatarSize(IdentityAvatarSize::TableViewIcon); + EXPECT_TRUE(CGSizeEqualToSize(expected_size, identity_avatar.size)); +} + +// Tests that the default avatar is forgotten after a memory warning +// notification. +TEST_F(ResizedAvatarCacheTest, MemoryWarning) { + UIImage* first_default_avatar = + [resized_avatar_cache_ resizedAvatarForIdentity:identity1_]; + EXPECT_NE(nil, first_default_avatar); + [[NSNotificationCenter defaultCenter] + postNotificationName:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; + UIImage* second_default_avatar = + [resized_avatar_cache_ resizedAvatarForIdentity:identity2_]; + EXPECT_NE(first_default_avatar, second_default_avatar); +}
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm index 256e5be..86fc28d 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm
@@ -39,7 +39,6 @@ using chrome_test_util::ClearBrowsingDataButton; using chrome_test_util::ConfirmClearBrowsingDataButton; using chrome_test_util::GoogleServicesSettingsButton; -using chrome_test_util::GoogleServicesSettingsView; using chrome_test_util::IdentityCellMatcherForEmail; using chrome_test_util::PrimarySignInButton; using chrome_test_util::SecondarySignInButton; @@ -50,10 +49,8 @@ using chrome_test_util::SettingsImportDataImportButton; using chrome_test_util::SettingsImportDataKeepSeparateButton; using chrome_test_util::SettingsLink; -using chrome_test_util::SettingsMenuBackButton; using chrome_test_util::SettingsMenuPrivacyButton; using chrome_test_util::StaticTextWithAccessibilityLabelId; -using chrome_test_util::SyncSettingsConfirmButton; using l10n_util::GetNSString; using testing::ButtonWithAccessibilityLabel; @@ -68,13 +65,6 @@ NSString* const kPassphrase = @"hello"; -// Returns a matcher for |userEmail| in IdentityChooserViewController. -id<GREYMatcher> identityChooserButtonMatcherWithEmail(NSString* userEmail) { - return grey_allOf(grey_accessibilityID(userEmail), - grey_kindOfClassName(@"TableViewIdentityCell"), - grey_sufficientlyVisible(), nil); -} - void ChooseImportOrKeepDataSepareteDialog(id<GREYMatcher> choiceButtonMatcher) { // Set up the fake identities. FakeChromeIdentity* fakeIdentity1 = [SigninEarlGrey fakeIdentity1]; @@ -552,14 +542,14 @@ // Open the identity chooser. [ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI tapSettingsMenuButton:SecondarySignInButton()]; - [ChromeEarlGrey waitForMatcher:identityChooserButtonMatcherWithEmail( - fakeIdentity.userEmail)]; + [ChromeEarlGrey + waitForMatcher:IdentityCellMatcherForEmail(fakeIdentity.userEmail)]; // Remove the fake identity. [SigninEarlGrey forgetFakeIdentity:fakeIdentity]; // Check that the identity has been removed. - [[EarlGrey selectElementWithMatcher:identityChooserButtonMatcherWithEmail( + [[EarlGrey selectElementWithMatcher:IdentityCellMatcherForEmail( fakeIdentity.userEmail)] assertWithMatcher:grey_notVisible()]; } @@ -626,7 +616,7 @@ // progress this test will likely be flaky. [SigninEarlGrey forgetFakeIdentity:fakeIdentity]; // Check that the identity has been removed. - [[EarlGrey selectElementWithMatcher:identityChooserButtonMatcherWithEmail( + [[EarlGrey selectElementWithMatcher:IdentityCellMatcherForEmail( fakeIdentity.userEmail)] assertWithMatcher:grey_notVisible()]; }
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h index cc84dba..57157ee 100644 --- a/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h
@@ -61,11 +61,6 @@ // directly the current SceneController. + (void)triggerConsistencyPromoSigninDialog; -// Sign-in matchers - -// Returns a matcher for an identity picker cell for |email|. -+ (id<GREYMatcher>)identityCellMatcherForEmail:(NSString*)email; - @end #endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARL_GREY_APP_INTERFACE_H_
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 4ef8bdd..957586c 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
@@ -142,10 +142,4 @@ URL:gURL]; } -+ (id<GREYMatcher>)identityCellMatcherForEmail:(NSString*)email { - return grey_allOf(grey_accessibilityID(email), - grey_kindOfClass([TableViewIdentityCell class]), - grey_sufficientlyVisible(), nil); -} - @end
diff --git a/ios/chrome/browser/ui/authentication/signin_matchers.mm b/ios/chrome/browser/ui/authentication/signin_matchers.mm index fa83a305..8dbf0baf 100644 --- a/ios/chrome/browser/ui/authentication/signin_matchers.mm +++ b/ios/chrome/browser/ui/authentication/signin_matchers.mm
@@ -5,7 +5,6 @@ #import "ios/chrome/browser/ui/authentication/signin_matchers.h" #import "ios/chrome/browser/ui/authentication/signin/signin_constants.h" -#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h" #import "ios/testing/earl_grey/earl_grey_test.h" @@ -16,7 +15,9 @@ namespace chrome_test_util { id<GREYMatcher> IdentityCellMatcherForEmail(NSString* email) { - return [SigninEarlGreyAppInterface identityCellMatcherForEmail:email]; + return grey_allOf(grey_accessibilityID(email), + grey_kindOfClassName(@"TableViewIdentityCell"), + grey_sufficientlyVisible(), nil); } id<GREYMatcher> SettingsLink() {
diff --git a/ios/chrome/browser/ui/download/download_manager_egtest.mm b/ios/chrome/browser/ui/download/download_manager_egtest.mm index a014ffa..d01f381 100644 --- a/ios/chrome/browser/ui/download/download_manager_egtest.mm +++ b/ios/chrome/browser/ui/download/download_manager_egtest.mm
@@ -54,7 +54,7 @@ return base::test::ios::WaitUntilConditionOrTimeout(kLongDownloadTimeout, ^{ NSError* error = nil; [[EarlGrey selectElementWithMatcher:chrome_test_util::OpenInButton()] - assertWithMatcher:grey_notNil() + assertWithMatcher:grey_interactable() error:&error]; return (error == nil); }); @@ -67,7 +67,7 @@ base::test::ios::kWaitForPageLoadTimeout, ^{ NSError* error = nil; [[EarlGrey selectElementWithMatcher:DownloadButton()] - assertWithMatcher:grey_notNil() + assertWithMatcher:grey_interactable() error:&error]; return (error == nil); }); @@ -81,7 +81,7 @@ NSError* error = nil; [[EarlGrey selectElementWithMatcher:grey_text(l10n_util::GetNSString( IDS_IOS_OPEN_IN_DOWNLOADS))] - assertWithMatcher:grey_notNil() + assertWithMatcher:grey_interactable() error:&error]; return (error == nil); });
diff --git a/ios/chrome/browser/web/stop_loading_egtest.mm b/ios/chrome/browser/web/stop_loading_egtest.mm index 4cbab4af..31eee077 100644 --- a/ios/chrome/browser/web/stop_loading_egtest.mm +++ b/ios/chrome/browser/web/stop_loading_egtest.mm
@@ -6,6 +6,7 @@ #include "base/strings/stringprintf.h" #import "base/test/ios/wait_util.h" +#include "base/threading/platform_thread.h" #include "base/time/time.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
diff --git a/ios/chrome/credential_provider_extension/ui/credential_list_view_controller.mm b/ios/chrome/credential_provider_extension/ui/credential_list_view_controller.mm index 2ade6024..c2000b7 100644 --- a/ios/chrome/credential_provider_extension/ui/credential_list_view_controller.mm +++ b/ios/chrome/credential_provider_extension/ui/credential_list_view_controller.mm
@@ -198,6 +198,7 @@ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kNewPasswordCellIdentifier]; } + cell.backgroundColor = [UIColor colorNamed:kBackgroundColor]; cell.textLabel.text = NSLocalizedString(@"IDS_IOS_CREDENTIAL_PROVIDER_CREATE_PASSWORD_ROW", @"Add New Password");
diff --git a/ios/chrome/test/app/signin_test_util.mm b/ios/chrome/test/app/signin_test_util.mm index b7e23c5..cac62c6 100644 --- a/ios/chrome/test/app/signin_test_util.mm +++ b/ios/chrome/test/app/signin_test_util.mm
@@ -58,14 +58,10 @@ service->SetUpForIntegrationTests(); ios::GetChromeBrowserProvider().SetChromeIdentityServiceForTesting( std::move(service)); - AuthenticationServiceFactory::GetForBrowserState(GetOriginalBrowserState()) - ->ResetChromeIdentityServiceObserverForTesting(); } void TearDownMockAuthentication() { ios::GetChromeBrowserProvider().SetChromeIdentityServiceForTesting(nullptr); - AuthenticationServiceFactory::GetForBrowserState(GetOriginalBrowserState()) - ->ResetChromeIdentityServiceObserverForTesting(); } void SignOutAndClearIdentities() {
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 index e7354b1e..5eca3d53 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -170744c1f11964742db733949e702bd5b4baa4c8 \ No newline at end of file +11e34792e5ab4ec16234904b43fa59f708ead394 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 index 9008f09..1764b9d 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -0564d4eeb73adc08736aef8eb6cec191c967299b \ No newline at end of file +1db08e9ae5923684d35414865e91247494559e81 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 index bb3a0da..3eaef8a 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -754b125a13cbb941e1a273ddf07aa95a6fcffac8 \ No newline at end of file +fa4b83563309080ca4d3d0ae39f7afc907e3280f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 index c25307e1..8b307c4c 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -1d993091ee125ce83c35e9e1f924161de40d28c2 \ No newline at end of file +5e16e07fe274694f5da3e2c0589182a7574a8893 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 index cb8b5a4..849c6a78 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -c3b5af92dd4ef8a50d8e9f5e3f6b1ca2a0c936fa \ No newline at end of file +9951ebcc572254751eb298b6d4b78a5003143b98 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 index 9eda69d..3dcca30 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -3503512fb7c3ffa8e5a923ad6cb166eb3b866d63 \ No newline at end of file +1e0b792beeb5d053172c1435636a96b73fa441ab \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 index fbd0ff1..48ddb93 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -96a366fdbe7b97142f9ff695eb919783652db0a6 \ No newline at end of file +87a367f7f5472ea9915f4cd85d1cc0227bfc29c9 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 index 1b4e8ab1..0d465b8b 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -a25c9809a6fc83b0f986e31e26a8fa737cb90d5b \ No newline at end of file +cfeb6d5e83e6a6c36be50b3472bbbff2e98684bc \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 index 9307e84..39d467f 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -26a8a7049a36e3cee21195274d52f924a1065aed \ No newline at end of file +7b1df26f08c78ff4bf0153edde82ca5d9a54602f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 index faacb76..a3fccd2 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -d8422582a5a3dcbcf29642813b54c8e635d0ad8c \ No newline at end of file +358668bffa04f15d66dad655e62a93e20956ba55 \ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h index a97c569..a95dbaa 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -146,9 +146,15 @@ // Fires |OnChromeIdentityServiceDidChange| on all observers. void FireChromeIdentityServiceDidChange(ChromeIdentityService* new_service); + // Creates a ChromeIdentityService. This methods has to be be implemented + // in subclasses. + virtual std::unique_ptr<ios::ChromeIdentityService> + CreateChromeIdentityService(); + private: base::ObserverList<Observer, true>::Unchecked observer_list_; std::unique_ptr<MailtoHandlerProvider> mailto_handler_provider_; + std::unique_ptr<ios::ChromeIdentityService> chrome_identity_service_; }; } // namespace ios
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.mm b/ios/public/provider/chrome/browser/chrome_browser_provider.mm index 066855f..5b4f12d 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.mm +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
@@ -40,6 +40,7 @@ : mailto_handler_provider_(std::make_unique<MailtoHandlerProvider>()) {} ChromeBrowserProvider::~ChromeBrowserProvider() { + chrome_identity_service_.reset(); for (auto& observer : observer_list_) observer.OnChromeBrowserProviderWillBeDestroyed(); } @@ -55,10 +56,16 @@ } void ChromeBrowserProvider::SetChromeIdentityServiceForTesting( - std::unique_ptr<ChromeIdentityService> service) {} + std::unique_ptr<ChromeIdentityService> service) { + chrome_identity_service_ = std::move(service); + FireChromeIdentityServiceDidChange(chrome_identity_service_.get()); +} ChromeIdentityService* ChromeBrowserProvider::GetChromeIdentityService() { - return nullptr; + if (!chrome_identity_service_) { + chrome_identity_service_ = CreateChromeIdentityService(); + } + return chrome_identity_service_.get(); } ChromeTrustedVaultService* @@ -125,4 +132,9 @@ observer.OnChromeIdentityServiceDidChange(new_service); } +std::unique_ptr<ios::ChromeIdentityService> +ChromeBrowserProvider::CreateChromeIdentityService() { + return nullptr; +} + } // namespace ios
diff --git a/ios/public/provider/chrome/browser/test_chrome_browser_provider.h b/ios/public/provider/chrome/browser/test_chrome_browser_provider.h index 8f2c41c..a1cdde82 100644 --- a/ios/public/provider/chrome/browser/test_chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/test_chrome_browser_provider.h
@@ -25,9 +25,6 @@ // ChromeBrowserProvider: SigninResourcesProvider* GetSigninResourcesProvider() override; - void SetChromeIdentityServiceForTesting( - std::unique_ptr<ChromeIdentityService> service) override; - ChromeIdentityService* GetChromeIdentityService() override; ChromeTrustedVaultService* GetChromeTrustedVaultService() override; UITextField* CreateStyledTextField() const override NS_RETURNS_RETAINED; VoiceSearchProvider* GetVoiceSearchProvider() const override; @@ -37,7 +34,9 @@ DiscoverFeedProvider* GetDiscoverFeedProvider() const override; private: - std::unique_ptr<ChromeIdentityService> chrome_identity_service_; + // ChromeBrowserProvider: + std::unique_ptr<ChromeIdentityService> CreateChromeIdentityService() override; + std::unique_ptr<ChromeTrustedVaultService> chrome_trusted_vault_service_; std::unique_ptr<OmahaServiceProvider> omaha_service_provider_; std::unique_ptr<SigninResourcesProvider> signin_resources_provider_;
diff --git a/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm b/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm index 69f7236..61bb242 100644 --- a/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm +++ b/ios/public/provider/chrome/browser/test_chrome_browser_provider.mm
@@ -45,19 +45,6 @@ return signin_resources_provider_.get(); } -void TestChromeBrowserProvider::SetChromeIdentityServiceForTesting( - std::unique_ptr<ChromeIdentityService> service) { - chrome_identity_service_ = std::move(service); - FireChromeIdentityServiceDidChange(chrome_identity_service_.get()); -} - -ChromeIdentityService* TestChromeBrowserProvider::GetChromeIdentityService() { - if (!chrome_identity_service_) { - chrome_identity_service_.reset(new FakeChromeIdentityService()); - } - return chrome_identity_service_.get(); -} - ChromeTrustedVaultService* TestChromeBrowserProvider::GetChromeTrustedVaultService() { if (!chrome_trusted_vault_service_) { @@ -94,4 +81,9 @@ return discover_feed_provider_.get(); } +std::unique_ptr<ChromeIdentityService> +TestChromeBrowserProvider::CreateChromeIdentityService() { + return std::make_unique<FakeChromeIdentityService>(); +} + } // namespace ios
diff --git a/media/base/use_after_free_checker.h b/media/base/use_after_free_checker.h index aefcaae2..1ffde9b 100644 --- a/media/base/use_after_free_checker.h +++ b/media/base/use_after_free_checker.h
@@ -5,6 +5,7 @@ #ifndef MEDIA_BASE_USE_AFTER_FREE_CHECKER_H_ #define MEDIA_BASE_USE_AFTER_FREE_CHECKER_H_ +#include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/location.h" #include "media/base/media_export.h"
diff --git a/media/capture/video/linux/v4l2_capture_delegate.cc b/media/capture/video/linux/v4l2_capture_delegate.cc index 26e6348..3a0ef10 100644 --- a/media/capture/video/linux/v4l2_capture_delegate.cc +++ b/media/capture/video/linux/v4l2_capture_delegate.cc
@@ -974,7 +974,9 @@ bool V4L2CaptureDelegate::StopStream() { DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); - DCHECK(is_capturing_); + if (!is_capturing_) + return false; + is_capturing_ = false; // The order is important: stop streaming, clear |buffer_pool_|, @@ -1003,7 +1005,6 @@ const base::Location& from_here, const std::string& reason) { DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); - is_capturing_ = false; client_->OnError(error, from_here, reason); }
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc index 05584fe..6b20378 100644 --- a/media/cast/sender/video_sender_unittest.cc +++ b/media/cast/sender/video_sender_unittest.cc
@@ -11,6 +11,7 @@ #include <vector> #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h"
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc index eae227d..d8ad38a 100644 --- a/media/cast/test/sender.cc +++ b/media/cast/test/sender.cc
@@ -13,6 +13,7 @@ #include "base/at_exit.h" #include "base/base_paths.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/json/json_writer.h"
diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc index 6c0cb79..1bafff9 100644 --- a/media/cast/test/simulator.cc +++ b/media/cast/test/simulator.cc
@@ -43,6 +43,7 @@ #include "base/at_exit.h" #include "base/base_paths.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/containers/queue.h" #include "base/containers/span.h"
diff --git a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc index 687f21c6..a7bdf11 100644 --- a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc +++ b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
@@ -19,6 +19,7 @@ using media::v4l2_test::Vp9Decoder; namespace { +static const char* kDecodeDevice = "/dev/video-dec0"; constexpr char kUsageMsg[] = "usage: v4l2_stateless_decoder\n" @@ -42,11 +43,25 @@ } // namespace +// For stateless API, fourcc |VP9F| is needed instead of |VP90| for VP9 codec. +// https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt-compressed.html +// Converts fourcc |VP90| from file header to fourcc |VP9F|, which is +// a format supported on driver. +uint32_t FileFourccToDriverFourcc(uint32_t header_fourcc) { + if (header_fourcc == V4L2_PIX_FMT_VP9) { + LOG(INFO) << "OUTPUT format mapped from VP90 to VP9F."; + return V4L2_PIX_FMT_VP9_FRAME; + } + + return header_fourcc; +} + // Creates the appropriate decoder for |stream|, which points to IVF data. // Returns nullptr on failure. -std::unique_ptr<Vp9Decoder> CreateDecoder( - const base::MemoryMappedFile& stream) { +std::unique_ptr<Vp9Decoder> CreateDecoder(const base::MemoryMappedFile& stream, + base::File& v4l_fd) { CHECK(stream.IsValid()); + CHECK(v4l_fd.IsValid()); // Set up video parser. auto ivf_parser = std::make_unique<media::IvfParser>(); @@ -66,7 +81,13 @@ << " not supported.\n" << kUsageMsg; - return std::make_unique<Vp9Decoder>(std::move(ivf_parser)); + const auto driver_codec_fourcc = FileFourccToDriverFourcc(file_header.fourcc); + + CHECK_EQ(driver_codec_fourcc, V4L2_PIX_FMT_VP9_FRAME) + << "Only VP9 is supported, got: " + << media::FourccToString(driver_codec_fourcc); + + return Vp9Decoder::Create(std::move(ivf_parser), v4l_fd); } int main(int argc, char** argv) { @@ -107,7 +128,12 @@ return EXIT_FAILURE; } - const std::unique_ptr<Vp9Decoder> dec = CreateDecoder(stream); + auto v4l_fd = base::File( + base::FilePath::FromUTF8Unsafe(kDecodeDevice), + base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE); + PCHECK(v4l_fd.IsValid()) << "Failed to open " << kDecodeDevice; + + const std::unique_ptr<Vp9Decoder> dec = CreateDecoder(stream, v4l_fd); if (!dec) { LOG(ERROR) << "Failed to create decoder for file: " << video_path; return EXIT_FAILURE;
diff --git a/media/gpu/v4l2/test/vp9_decoder.cc b/media/gpu/v4l2/test/vp9_decoder.cc index c550a98..23909dbf 100644 --- a/media/gpu/v4l2/test/vp9_decoder.cc +++ b/media/gpu/v4l2/test/vp9_decoder.cc
@@ -4,6 +4,12 @@ #include "media/gpu/v4l2/test/vp9_decoder.h" +#include <sys/ioctl.h> + +#include "base/files/memory_mapped_file.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "media/base/video_types.h" #include "media/filters/ivf_parser.h" #include "media/filters/vp9_parser.h" @@ -11,12 +17,85 @@ namespace v4l2_test { -Vp9Decoder::Vp9Decoder(std::unique_ptr<IvfParser> ivf_parser) +Vp9Decoder::Vp9Decoder(std::unique_ptr<IvfParser> ivf_parser, + base::File& v4l2_dev_file) : vp9_parser_( std::make_unique<Vp9Parser>(/*parsing_compressed_header=*/false)) {} Vp9Decoder::~Vp9Decoder() = default; +// static +std::unique_ptr<Vp9Decoder> Vp9Decoder::Create( + std::unique_ptr<IvfParser> ivf_parser, + base::File& v4l2_dev_file) { + DCHECK(v4l2_dev_file.IsValid()); + + constexpr uint32_t kDriverCodecFourcc = V4L2_PIX_FMT_VP9_FRAME; + + // MM21 is an uncompressed opaque format that is produced by MediaTek + // video decoders. + const uint32_t kUncompressedFourcc = v4l2_fourcc('M', 'M', '2', '1'); + + if (!VerifyCapabilities(v4l2_dev_file.GetPlatformFile(), kDriverCodecFourcc, + kUncompressedFourcc)) { + LOG(ERROR) << "Device doesn't support the provided FourCCs."; + return nullptr; + } + + return base::WrapUnique(new Vp9Decoder(std::move(ivf_parser), v4l2_dev_file)); +} + +// static +bool Vp9Decoder::QueryFormat(base::PlatformFile v4l_fd, + enum v4l2_buf_type type, + uint32_t fourcc) { + struct v4l2_fmtdesc fmtdesc; + memset(&fmtdesc, 0, sizeof(fmtdesc)); + + fmtdesc.type = type; + + while (ioctl(v4l_fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { + if (fourcc == fmtdesc.pixelformat) + return true; + + fmtdesc.index++; + } + + return false; +} + +// static +bool Vp9Decoder::VerifyCapabilities(base::PlatformFile v4l_fd, + uint32_t compressed_format, + uint32_t uncompressed_format) { + struct v4l2_capability cap; + memset(&cap, 0, sizeof(cap)); + + if (ioctl(v4l_fd, VIDIOC_QUERYCAP, &cap) != 0) { + PLOG(ERROR) << "VIDIOC_QUERYCAP failed"; + return false; + } + + LOG(INFO) << "Driver=\"" << cap.driver << "\" bus_info=\"" << cap.bus_info + << "\" card=\"" << cap.card << "\" fd=0x" << std::hex << v4l_fd; + + const bool is_compressed_format_supported = + QueryFormat(v4l_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, compressed_format); + + LOG_IF(ERROR, !is_compressed_format_supported) + << media::FourccToString(compressed_format) + << " is not a supported compressed OUTPUT format."; + + const bool is_uncompressed_format_supported = QueryFormat( + v4l_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, uncompressed_format); + + LOG_IF(ERROR, !is_uncompressed_format_supported) + << media::FourccToString(uncompressed_format) + << " is not a supported uncompressed CAPTURE format."; + + return is_compressed_format_supported && is_uncompressed_format_supported; +} + Vp9Parser::Result Vp9Decoder::ReadNextFrame(Vp9FrameHeader* vp9_frame_header, gfx::Size& size) { DCHECK(vp9_frame_header);
diff --git a/media/gpu/v4l2/test/vp9_decoder.h b/media/gpu/v4l2/test/vp9_decoder.h index ee146375..80d12e2 100644 --- a/media/gpu/v4l2/test/vp9_decoder.h +++ b/media/gpu/v4l2/test/vp9_decoder.h
@@ -5,6 +5,9 @@ #ifndef MEDIA_GPU_V4L2_TEST_VP9_DECODER_H_ #define MEDIA_GPU_V4L2_TEST_VP9_DECODER_H_ +#include <linux/videodev2.h> + +#include "base/files/memory_mapped_file.h" #include "media/filters/vp9_parser.h" namespace media { @@ -16,12 +19,31 @@ // A Vp9Decoder decodes VP9-encoded IVF streams using v4l2 ioctl calls. class Vp9Decoder { public: - explicit Vp9Decoder(std::unique_ptr<IvfParser> ivf_parser); Vp9Decoder(const Vp9Decoder&) = delete; Vp9Decoder& operator=(const Vp9Decoder&) = delete; ~Vp9Decoder(); + // Creates |Vp9Decoder| after calling VerifyCapabilities() function to make + // sure provided OUTPUT and CAPTURE formats are supported. + static std::unique_ptr<Vp9Decoder> Create( + std::unique_ptr<IvfParser> ivf_parser, + base::File& v4l2_dev_file); + private: + Vp9Decoder(std::unique_ptr<IvfParser> ivf_parser, base::File& v4l2_dev_file); + + // Queries |v4l_fd| to see if it can use the specified |fourcc| format + // for the given buffer |type|. + static bool QueryFormat(base::PlatformFile v4l_fd, + enum v4l2_buf_type type, + uint32_t fourcc); + + // Verifies |v4l_fd| supports |compressed_format| for OUTPUT queues + // and |uncompressed_format| for CAPTURE queues, respectively. + static bool VerifyCapabilities(base::PlatformFile v4l_fd, + uint32_t compressed_format, + uint32_t uncompressed_format); + // Reads next frame from IVF stream and its size into |vp9_frame_header| // and |size| respectively. Vp9Parser::Result ReadNextFrame(Vp9FrameHeader* vp9_frame_header,
diff --git a/media/gpu/video_decode_accelerator_tests.cc b/media/gpu/video_decode_accelerator_tests.cc index 11188b2a..b1c5c8f3 100644 --- a/media/gpu/video_decode_accelerator_tests.cc +++ b/media/gpu/video_decode_accelerator_tests.cc
@@ -4,6 +4,7 @@ #include <limits> +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/files/file_util.h" #include "base/numerics/safe_conversions.h"
diff --git a/media/gpu/video_encode_accelerator_perf_tests.cc b/media/gpu/video_encode_accelerator_perf_tests.cc index d431d432e..02930ef 100644 --- a/media/gpu/video_encode_accelerator_perf_tests.cc +++ b/media/gpu/video_encode_accelerator_perf_tests.cc
@@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/json/json_writer.h" +#include "base/strings/string_number_conversions.h" #include "media/base/bitstream_buffer.h" #include "media/base/media_util.h" #include "media/base/test_data_util.h"
diff --git a/media/mojo/mojom/media_player.mojom b/media/mojo/mojom/media_player.mojom index 2d7ce73..fe8f5ee 100644 --- a/media/mojo/mojom/media_player.mojom +++ b/media/mojo/mojom/media_player.mojom
@@ -9,7 +9,8 @@ import "services/media_session/public/mojom/media_session.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; -// Implemented by HTMLMediaElement in the renderer process. +// Implemented by HTMLMediaElement in the renderer process to allow the +// browser to control media playback. interface MediaPlayer { // Requests the media player to start or resume media playback. RequestPlay(); @@ -32,6 +33,9 @@ // Requests the media player to exit the Picture-in-Picture mode. RequestExitPictureInPicture(); + // Requests the media player to mute or unmute. + RequestMute(bool mute); + // Set the volume multiplier to control audio ducking. // Output volume should be set to |player_volume| * |multiplier|. The range // of |multiplier| is [0, 1], where 1 indicates normal (non-ducked) playback.
diff --git a/net/base/host_port_pair.cc b/net/base/host_port_pair.cc index 5e4c2d3a..32e48c53 100644 --- a/net/base/host_port_pair.cc +++ b/net/base/host_port_pair.cc
@@ -5,6 +5,7 @@ #include "net/base/host_port_pair.h" #include "base/logging.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" @@ -12,8 +13,7 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/memory_usage_estimator.h" #include "net/base/ip_endpoint.h" -#include "net/base/parse_number.h" -#include "net/base/port_util.h" +#include "net/base/url_util.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -50,20 +50,30 @@ } // static -HostPortPair HostPortPair::FromString(const std::string& str) { - std::vector<base::StringPiece> key_port = base::SplitStringPiece( - str, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - if (key_port.size() != 2) +HostPortPair HostPortPair::FromString(base::StringPiece str) { + // Input with more than one ':' is ambiguous unless it contains an IPv6 + // literal (signified by starting with a '['). ParseHostAndPort() allows such + // input and always uses the last ':' as the host/port delimiter, but because + // HostPortPair often deals with IPv6 literals without brackets, disallow such + // input here to prevent a common error. + if (base::SplitStringPiece(str, ":", base::KEEP_WHITESPACE, + base::SPLIT_WANT_ALL) + .size() > 2 && + str.front() != '[') { return HostPortPair(); + } + + std::string host; int port; - if (!ParseInt32(key_port[1], ParseIntFormat::NON_NEGATIVE, &port)) + if (!ParseHostAndPort(str, &host, &port)) return HostPortPair(); - if (!IsPortValid(port)) + + // Require a valid port. + if (port == -1) return HostPortPair(); - HostPortPair host_port_pair; - host_port_pair.set_host(std::string(key_port[0])); - host_port_pair.set_port(static_cast<uint16_t>(port)); - return host_port_pair; + DCHECK(base::IsValueInRangeForNumericType<uint16_t>(port)); + + return HostPortPair(host, port); } std::string HostPortPair::ToString() const {
diff --git a/net/base/host_port_pair.h b/net/base/host_port_pair.h index 6a006da..ae37263 100644 --- a/net/base/host_port_pair.h +++ b/net/base/host_port_pair.h
@@ -40,7 +40,7 @@ // Creates a HostPortPair from a string formatted in same manner as // ToString(). - static HostPortPair FromString(const std::string& str); + static HostPortPair FromString(base::StringPiece str); // TODO(willchan): Define a functor instead. // Comparator function so this can be placed in a std::map.
diff --git a/net/base/host_port_pair_unittest.cc b/net/base/host_port_pair_unittest.cc index 99e7c89..f50de395 100644 --- a/net/base/host_port_pair_unittest.cc +++ b/net/base/host_port_pair_unittest.cc
@@ -37,13 +37,24 @@ EXPECT_TRUE(foo.Equals(bar)); } +TEST(HostPortPairTest, ParsingIpv6) { + HostPortPair foo("2001:db8::42", 100); + string foo_str = foo.ToString(); + EXPECT_EQ("[2001:db8::42]:100", foo_str); + HostPortPair bar = HostPortPair::FromString(foo_str); + EXPECT_TRUE(foo.Equals(bar)); +} + TEST(HostPortPairTest, BadString) { - const char* kBadStrings[] = { - "foo.com:2:3", "bar.com:two", "www.google.com:-1", - "www.google.com:+1", "127.0.0.1:65536", "[2001:db8::42]:65536", - }; + const char* kBadStrings[] = {"foo.com", "foo.com:", + "foo.com:2:3", "bar.com:two", + "www.google.com:-1", "www.google.com:+1", + "127.0.0.1:65536", "[2001:db8::42]:65536", + "[2001:db8::42", "2001:db8::42", + "2001:db8::42:100", "[2001:db8::42]"}; for (const auto* const test : kBadStrings) { + SCOPED_TRACE(test); HostPortPair foo = HostPortPair::FromString(test); EXPECT_TRUE(foo.host().empty()); EXPECT_EQ(0, foo.port());
diff --git a/net/quic/test_task_runner.cc b/net/quic/test_task_runner.cc index a91b285d..e7ca259 100644 --- a/net/quic/test_task_runner.cc +++ b/net/quic/test_task_runner.cc
@@ -33,7 +33,7 @@ EXPECT_GE(delay, base::TimeDelta()); tasks_.push_back(PostedTask(from_here, std::move(task), NowInTicks(*clock_), delay, base::TestPendingTask::NESTABLE)); - return false; + return true; } bool TestTaskRunner::PostNonNestableDelayedTask(const base::Location& from_here,
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 341b1839..847038f7 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -25,6 +25,7 @@ #include "base/location.h" #include "base/notreached.h" #include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h"
diff --git a/remoting/client/jni/jni_directory_service.cc b/remoting/client/jni/jni_directory_service.cc index 711645fb..75d706b 100644 --- a/remoting/client/jni/jni_directory_service.cc +++ b/remoting/client/jni/jni_directory_service.cc
@@ -34,14 +34,11 @@ switch (status_code) { case ProtobufHttpStatus::Code::UNAVAILABLE: return JniDirectoryService::RequestError::SERVICE_UNAVAILABLE; - break; case ProtobufHttpStatus::Code::PERMISSION_DENIED: case ProtobufHttpStatus::Code::UNAUTHENTICATED: return JniDirectoryService::RequestError::AUTH_FAILED; - break; default: return JniDirectoryService::RequestError::UNKNOWN; - break; } }
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc index d58569d..6485bf4 100644 --- a/remoting/protocol/webrtc_transport.cc +++ b/remoting/protocol/webrtc_transport.cc
@@ -15,6 +15,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h"
diff --git a/sandbox/policy/mojom/sandbox.mojom b/sandbox/policy/mojom/sandbox.mojom index b0cddf3e..891e924 100644 --- a/sandbox/policy/mojom/sandbox.mojom +++ b/sandbox/policy/mojom/sandbox.mojom
@@ -55,6 +55,10 @@ [EnableIf=is_win] kNoSandboxAndElevatedPrivileges, + // Like kUtility, but patches GDI during child startup in pdf_child_init. + [EnableIf=is_win] + kPdfConversion, + // Like kUtility but also disables dynamic code. [EnableIf=is_win] kProxyResolver, @@ -75,4 +79,8 @@ // Chrome branded builds. [EnableIf=is_chromeos_ash] kLibassistant, + + // Like kUtility but allows access to IOSurface on macOS. + [EnableIf=is_mac] + kMirroring, };
diff --git a/sandbox/policy/sandbox_type.h b/sandbox/policy/sandbox_type.h index 5db2845..1d48c21 100644 --- a/sandbox/policy/sandbox_type.h +++ b/sandbox/policy/sandbox_type.h
@@ -142,11 +142,17 @@ return sandbox::policy::SandboxType::kMediaFoundationCdm; case sandbox::mojom::Sandbox::kNoSandboxAndElevatedPrivileges: return sandbox::policy::SandboxType::kNoSandboxAndElevatedPrivileges; + case sandbox::mojom::Sandbox::kPdfConversion: + return sandbox::policy::SandboxType::kPdfConversion; case sandbox::mojom::Sandbox::kProxyResolver: return sandbox::policy::SandboxType::kProxyResolver; case sandbox::mojom::Sandbox::kXrCompositing: return sandbox::policy::SandboxType::kXrCompositing; #endif // OS_WIN +#if defined(OS_MAC) + case sandbox::mojom::Sandbox::kMirroring: + return sandbox::policy::SandboxType::kMirroring; +#endif // defined(OS_MAC) #if BUILDFLAG(IS_CHROMEOS_ASH) case sandbox::mojom::Sandbox::kIme: return sandbox::policy::SandboxType::kIme;
diff --git a/sandbox/win/src/app_container_test.cc b/sandbox/win/src/app_container_test.cc index 29d83ed..05164b71 100644 --- a/sandbox/win/src/app_container_test.cc +++ b/sandbox/win/src/app_container_test.cc
@@ -21,6 +21,7 @@ #include "base/rand_util.h" #include "base/scoped_native_library.h" #include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h"
diff --git a/services/cert_verifier/trial_comparison_cert_verifier_mojo.h b/services/cert_verifier/trial_comparison_cert_verifier_mojo.h index 9b5b0a0..49adbc6 100644 --- a/services/cert_verifier/trial_comparison_cert_verifier_mojo.h +++ b/services/cert_verifier/trial_comparison_cert_verifier_mojo.h
@@ -28,7 +28,7 @@ // Wrapper around TrialComparisonCertVerifier that does trial configuration and // reporting over Mojo pipes. -class COMPONENT_EXPORT(NETWORK_SERVICE) TrialComparisonCertVerifierMojo +class TrialComparisonCertVerifierMojo : public net::CertVerifier, public mojom::TrialComparisonCertVerifierConfigClient { public:
diff --git a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc index ad1e6c7..05b36db 100644 --- a/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc +++ b/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
@@ -167,7 +167,6 @@ // error and data changes notifications. class LinuxMockPlatformSensorClient : public PlatformSensor::Client { public: - LinuxMockPlatformSensorClient() = default; explicit LinuxMockPlatformSensorClient(scoped_refptr<PlatformSensor> sensor) : sensor_(sensor) { if (sensor_)
diff --git a/services/device/usb/usb_descriptors.cc b/services/device/usb/usb_descriptors.cc index 498e855..54962c2 100644 --- a/services/device/usb/usb_descriptors.cc +++ b/services/device/usb/usb_descriptors.cc
@@ -199,27 +199,52 @@ size_t length) { std::u16string string; if (status == UsbTransferStatus::COMPLETED && - ParseUsbStringDescriptor( - std::vector<uint8_t>(buffer->front(), buffer->front() + length), - &string)) { + ParseUsbStringDescriptor(base::make_span(buffer->front(), length), + &string)) { std::move(callback).Run(string); } else { std::move(callback).Run(std::u16string()); } } +void OnReadStringDescriptorHeader( + scoped_refptr<UsbDeviceHandle> device_handle, + uint8_t index, + uint16_t language_id, + base::OnceCallback<void(const std::u16string&)> callback, + UsbTransferStatus status, + scoped_refptr<base::RefCountedBytes> header, + size_t length) { + if (status == UsbTransferStatus::COMPLETED && length == 2) { + const uint8_t* data = header->front(); + uint8_t actual_length = data[0]; + auto buffer = base::MakeRefCounted<base::RefCountedBytes>(actual_length); + device_handle->ControlTransfer( + UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, + UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, + kStringDescriptorType << 8 | index, language_id, buffer, + kControlTransferTimeoutMs, + base::BindOnce(&OnReadStringDescriptor, std::move(callback))); + } else { + LOG(ERROR) << "Failed to read length for string " << static_cast<int>(index) + << "."; + std::move(callback).Run(std::u16string()); + } +} + void ReadStringDescriptor( scoped_refptr<UsbDeviceHandle> device_handle, uint8_t index, uint16_t language_id, base::OnceCallback<void(const std::u16string&)> callback) { - auto buffer = base::MakeRefCounted<base::RefCountedBytes>(255); + auto buffer = base::MakeRefCounted<base::RefCountedBytes>(2); device_handle->ControlTransfer( UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD, UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest, kStringDescriptorType << 8 | index, language_id, buffer, kControlTransferTimeoutMs, - base::BindOnce(&OnReadStringDescriptor, std::move(callback))); + base::BindOnce(&OnReadStringDescriptorHeader, device_handle, index, + language_id, std::move(callback))); } void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle, @@ -361,7 +386,7 @@ std::move(callback))); } -bool ParseUsbStringDescriptor(const std::vector<uint8_t>& descriptor, +bool ParseUsbStringDescriptor(base::span<const uint8_t> descriptor, std::u16string* output) { if (descriptor.size() < 2 || descriptor[1] != kStringDescriptorType) return false;
diff --git a/services/device/usb/usb_descriptors.h b/services/device/usb/usb_descriptors.h index eca03af1..6bd9267 100644 --- a/services/device/usb/usb_descriptors.h +++ b/services/device/usb/usb_descriptors.h
@@ -10,9 +10,9 @@ #include <map> #include <memory> #include <string> -#include <vector> #include "base/callback_forward.h" +#include "base/containers/span.h" #include "base/memory/ref_counted.h" #include "services/device/public/mojom/usb_device.mojom.h" @@ -54,7 +54,7 @@ scoped_refptr<UsbDeviceHandle> device_handle, base::OnceCallback<void(std::unique_ptr<UsbDeviceDescriptor>)> callback); -bool ParseUsbStringDescriptor(const std::vector<uint8_t>& descriptor, +bool ParseUsbStringDescriptor(base::span<const uint8_t> descriptor, std::u16string* output); void ReadUsbStringDescriptors(
diff --git a/services/device/usb/usb_descriptors_unittest.cc b/services/device/usb/usb_descriptors_unittest.cc index 19602b40..8137ce0 100644 --- a/services/device/usb/usb_descriptors_unittest.cc +++ b/services/device/usb/usb_descriptors_unittest.cc
@@ -427,7 +427,9 @@ UsbControlTransferType::STANDARD, UsbControlTransferRecipient::DEVICE, 0x06, 0x0300, 0x0000, _, _, _)) + .WillOnce(InvokeCallback(kStringDescriptor0, size_t{2})) .WillOnce(InvokeCallback(kStringDescriptor0, sizeof(kStringDescriptor0))); + static const uint8_t kStringDescriptor1[] = {0x12, 0x03, 'S', 0, 't', 0, 'r', 0, 'i', 0, 'n', 0, 'g', 0, ' ', 0, '1', 0}; @@ -436,7 +438,9 @@ UsbControlTransferType::STANDARD, UsbControlTransferRecipient::DEVICE, 0x06, 0x0301, 0x4321, _, _, _)) + .WillOnce(InvokeCallback(kStringDescriptor1, size_t{2})) .WillOnce(InvokeCallback(kStringDescriptor1, sizeof(kStringDescriptor1))); + static const uint8_t kStringDescriptor2[] = {0x12, 0x03, 'S', 0, 't', 0, 'r', 0, 'i', 0, 'n', 0, 'g', 0, ' ', 0, '2', 0}; @@ -445,7 +449,9 @@ UsbControlTransferType::STANDARD, UsbControlTransferRecipient::DEVICE, 0x06, 0x0302, 0x4321, _, _, _)) + .WillOnce(InvokeCallback(kStringDescriptor2, size_t{2})) .WillOnce(InvokeCallback(kStringDescriptor2, sizeof(kStringDescriptor2))); + static const uint8_t kStringDescriptor3[] = {0x12, 0x03, 'S', 0, 't', 0, 'r', 0, 'i', 0, 'n', 0, 'g', 0, ' ', 0, '3', 0}; @@ -454,6 +460,7 @@ UsbControlTransferType::STANDARD, UsbControlTransferRecipient::DEVICE, 0x06, 0x0303, 0x4321, _, _, _)) + .WillOnce(InvokeCallback(kStringDescriptor3, size_t{2})) .WillOnce(InvokeCallback(kStringDescriptor3, sizeof(kStringDescriptor3))); ReadUsbStringDescriptors(device_handle, std::move(string_map),
diff --git a/services/media_session/media_controller.cc b/services/media_session/media_controller.cc index 19b8ef46..a07d15e9 100644 --- a/services/media_session/media_controller.cc +++ b/services/media_session/media_controller.cc
@@ -328,6 +328,13 @@ session_->ipc()->Raise(); } +void MediaController::SetMute(bool mute) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (session_) + session_->ipc()->SetMute(mute); +} + void MediaController::SetMediaSession(AudioFocusRequest* session) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/services/media_session/media_controller.h b/services/media_session/media_controller.h index 0177aac..3e3ece08 100644 --- a/services/media_session/media_controller.h +++ b/services/media_session/media_controller.h
@@ -57,6 +57,7 @@ void ToggleCamera() override; void HangUp() override; void Raise() override; + void SetMute(bool mute) override; // mojom::MediaSessionObserver overrides. void MediaSessionInfoChanged(
diff --git a/services/media_session/public/cpp/test/mock_media_session.h b/services/media_session/public/cpp/test/mock_media_session.h index 53e4605..265ab41a 100644 --- a/services/media_session/public/cpp/test/mock_media_session.h +++ b/services/media_session/public/cpp/test/mock_media_session.h
@@ -168,6 +168,7 @@ void ToggleCamera() override {} void HangUp() override {} void Raise() override {} + void SetMute(bool mute) override {} void SetIsControllable(bool value); void SetPreferStop(bool value) { prefer_stop_ = value; }
diff --git a/services/media_session/public/cpp/test/test_media_controller.h b/services/media_session/public/cpp/test/test_media_controller.h index 9d31b635..9a89eb76 100644 --- a/services/media_session/public/cpp/test/test_media_controller.h +++ b/services/media_session/public/cpp/test/test_media_controller.h
@@ -160,6 +160,7 @@ void ToggleCamera() override {} void HangUp() override {} void Raise() override {} + void SetMute(bool mute) override {} int toggle_suspend_resume_count() const { return toggle_suspend_resume_count_;
diff --git a/services/media_session/public/cpp/util.cc b/services/media_session/public/cpp/util.cc index 9954917..0aba3467 100644 --- a/services/media_session/public/cpp/util.cc +++ b/services/media_session/public/cpp/util.cc
@@ -58,6 +58,7 @@ case mojom::MediaSessionAction::kRaise: media_controller_remote->Raise(); break; + case mojom::MediaSessionAction::kSetMute: case mojom::MediaSessionAction::kSkipAd: case mojom::MediaSessionAction::kSeekTo: case mojom::MediaSessionAction::kScrubTo:
diff --git a/services/media_session/public/mojom/media_controller.mojom b/services/media_session/public/mojom/media_controller.mojom index 9e5ddef..b312a33 100644 --- a/services/media_session/public/mojom/media_controller.mojom +++ b/services/media_session/public/mojom/media_controller.mojom
@@ -33,7 +33,7 @@ // session, otherwise media sessions will be associated with a particular media // session provided to the service when creating the media controller. If the // media session is not controllable then the commands will be no-ops. -// Next Method ID: 18 +// Next Method ID: 19 [Stable] interface MediaController { // Suspend the media session. @@ -109,6 +109,9 @@ // Display the source of the MediaSession (e.g. show the tab or the // application). [MinVersion=2] Raise@17(); + + // Mute or unmute the media player. + [MinVersion=3] SetMute@18(bool mute); }; // The observer for observing media controller events. This is different to a
diff --git a/services/media_session/public/mojom/media_session.mojom b/services/media_session/public/mojom/media_session.mojom index 4658fcd..b376d2a 100644 --- a/services/media_session/public/mojom/media_session.mojom +++ b/services/media_session/public/mojom/media_session.mojom
@@ -36,6 +36,7 @@ [MinVersion=11] kToggleCamera, [MinVersion=11] kHangUp, [MinVersion=12] kRaise, + [MinVersion=13] kSetMute, }; [Stable, Extensible] @@ -189,6 +190,9 @@ // Tracks whether the camera is turned on in WebRTC sessions. [MinVersion=11] CameraState camera_state; + + // Tracks whether the media player is muted. + [MinVersion=12] bool muted; }; // Contains debugging information about a MediaSession. This will be displayed @@ -331,4 +335,7 @@ // Display the source of the MediaSession (e.g. show the tab or the // application). [MinVersion=12] Raise@21(); + + // Mute or unmute the media player. + [MinVersion=13] SetMute@22(bool mute); };
diff --git a/services/network/public/cpp/cross_origin_read_blocking.cc b/services/network/public/cpp/cross_origin_read_blocking.cc index 391f488..2a2991e7 100644 --- a/services/network/public/cpp/cross_origin_read_blocking.cc +++ b/services/network/public/cpp/cross_origin_read_blocking.cc
@@ -551,11 +551,8 @@ virtual ~ConfirmationSniffer() = default; // Called after data is read from the network. |sniffing_buffer| contains the - // entire response body delivered thus far. To support streaming, - // |new_data_offset| gives the offset into |sniffing_buffer| at which new data - // was appended since the last read. - virtual void OnDataAvailable(base::StringPiece sniffing_buffer, - size_t new_data_offset) = 0; + // entire response body delivered thus far. + virtual void OnDataAvailable(base::StringPiece sniffing_buffer) = 0; // Returns true if the return value of IsConfirmedContentType() might change // with the addition of more data. Returns false if a final decision is @@ -581,13 +578,7 @@ : sniffer_function_(sniffer_function) {} ~SimpleConfirmationSniffer() override = default; - void OnDataAvailable(base::StringPiece sniffing_buffer, - size_t new_data_offset) final { - DCHECK_LE(new_data_offset, sniffing_buffer.length()); - if (new_data_offset == sniffing_buffer.length()) { - // No new data -- do nothing. This happens at end-of-stream. - return; - } + void OnDataAvailable(base::StringPiece sniffing_buffer) final { // The sniffing functions don't support streaming, so with each new chunk of // data, call the sniffer on the whole buffer. last_sniff_result_ = (*sniffer_function_)(sniffing_buffer); @@ -964,19 +955,15 @@ } void CrossOriginReadBlocking::ResponseAnalyzer::SniffResponseBody( - base::StringPiece data, - size_t new_data_offset) { + base::StringPiece data) { DCHECK(needs_sniffing()); DCHECK(!sniffers_.empty()); DCHECK(!found_blockable_content_); DCHECK_LE(data.size(), static_cast<size_t>(net::kMaxBytesToSniff)); - DCHECK_LE(new_data_offset, data.size()); - bool has_new_data = (new_data_offset < data.size()); for (size_t i = 0; i < sniffers_.size();) { - if (has_new_data) - sniffers_[i]->OnDataAvailable(data, new_data_offset); + sniffers_[i]->OnDataAvailable(data); if (sniffers_[i]->WantsMoreData()) { i++;
diff --git a/services/network/public/cpp/cross_origin_read_blocking.h b/services/network/public/cpp/cross_origin_read_blocking.h index be43e7b..ecef7e1 100644 --- a/services/network/public/cpp/cross_origin_read_blocking.h +++ b/services/network/public/cpp/cross_origin_read_blocking.h
@@ -151,7 +151,7 @@ } // Allows ResponseAnalyzer to sniff the response body. - void SniffResponseBody(base::StringPiece data, size_t new_data_offset); + void SniffResponseBody(base::StringPiece data); class ConfirmationSniffer; class SimpleConfirmationSniffer;
diff --git a/services/network/public/cpp/cross_origin_read_blocking_unittest.cc b/services/network/public/cpp/cross_origin_read_blocking_unittest.cc index 4f2b0d5..50780568 100644 --- a/services/network/public/cpp/cross_origin_read_blocking_unittest.cc +++ b/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
@@ -1953,9 +1953,8 @@ bytes_to_append = net::kMaxBytesToSniff - data_offset; data_buffer.append(packets_vector[packet_index], bytes_to_append); - // Hand |analyzer_| the data and an offset indicating what point it last - // read to. - analyzer_->SniffResponseBody(data_buffer, data_offset); + // Hand |analyzer_| the data to sniff. + analyzer_->SniffResponseBody(data_buffer); data_offset += bytes_to_append; // If the latest packet was empty, or we reached net::kMaxBytesToSniff
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 0c0f52fd..2b6e06e7 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -1531,8 +1531,10 @@ response_->did_mime_sniff = true; } - if (is_more_corb_sniffing_needed_) { - corb_analyzer_->SniffResponseBody(data, new_data_offset); + // `has_new_data_to_sniff` can be false at the end-of-stream. + bool has_new_data_to_sniff = new_data_offset < data.length(); + if (is_more_corb_sniffing_needed_ && has_new_data_to_sniff) { + corb_analyzer_->SniffResponseBody(data); if (corb_analyzer_->ShouldBlock()) { corb_analyzer_->LogBlockedResponse(); is_more_corb_sniffing_needed_ = false;
diff --git a/storage/browser/file_system/file_system_quota_client.cc b/storage/browser/file_system/file_system_quota_client.cc index 0e6e601e..195e211 100644 --- a/storage/browser/file_system/file_system_quota_client.cc +++ b/storage/browser/file_system/file_system_quota_client.cc
@@ -4,12 +4,17 @@ #include "storage/browser/file_system/file_system_quota_client.h" +#include <numeric> #include <string> #include <utility> #include <vector> +#include "base/barrier_callback.h" +#include "base/barrier_closure.h" #include "base/bind.h" #include "base/check.h" +#include "base/containers/span.h" +#include "base/feature_list.h" #include "base/files/file.h" #include "base/location.h" #include "base/sequence_checker.h" @@ -18,6 +23,7 @@ #include "storage/browser/file_system/file_system_context.h" #include "storage/common/file_system/file_system_types.h" #include "storage/common/file_system/file_system_util.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/origin.h" @@ -26,6 +32,14 @@ namespace { +static const FileSystemType kTemporaryAndPersistent[] = { + kFileSystemTypeTemporary, + kFileSystemTypePersistent, +}; +static const FileSystemType kTemporary[] = {kFileSystemTypeTemporary}; +static const FileSystemType kPersistent[] = {kFileSystemTypePersistent}; +static const FileSystemType kSyncable[] = {kFileSystemTypeSyncable}; + std::vector<blink::StorageKey> ToStorageKeys( const std::vector<url::Origin>& origins) { std::vector<blink::StorageKey> storage_keys; @@ -35,13 +49,53 @@ return storage_keys; } +template <typename T> +std::vector<T> MergeWithoutDuplicates(const std::vector<std::vector<T>>& tss) { + if (tss.size() == 1) { + // We assume that each vector contains no duplicates, already. + return tss[0]; + } + std::vector<T> merged; + merged.reserve(std::accumulate( + tss.begin(), tss.end(), 0U, + [](size_t acc, const std::vector<T>& ts) { return acc + ts.size(); })); + for (const auto& ts : tss) { + merged.insert(merged.end(), ts.begin(), ts.end()); + } + base::ranges::sort(merged); + merged.erase(base::ranges::unique(merged), merged.end()); + return merged; +} + +// Converts StorageType to the FileSystemTypes that are used for that quota +// type. +base::span<const FileSystemType> QuotaStorageTypeToFileSystemTypes( + blink::mojom::StorageType storage_type) { + using StorageType = blink::mojom::StorageType; + + if (base::FeatureList::IsEnabled( + blink::features::kPersistentQuotaIsTemporaryQuota)) { + DCHECK_NE(storage_type, StorageType::kPersistent); + if (storage_type == StorageType::kTemporary) + return kTemporaryAndPersistent; + } + switch (storage_type) { + case StorageType::kTemporary: + return kTemporary; + case StorageType::kPersistent: + return kPersistent; + case StorageType::kSyncable: + return kSyncable; + case StorageType::kQuotaNotManaged: + case StorageType::kUnknown: + NOTREACHED(); + return {}; + } +} + std::vector<blink::StorageKey> GetStorageKeysForTypeOnFileTaskRunner( FileSystemContext* context, - blink::mojom::StorageType storage_type) { - FileSystemType type = - FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); - + FileSystemType type) { FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); if (!quota_util) return {}; @@ -50,12 +104,8 @@ std::vector<blink::StorageKey> GetStorageKeysForHostOnFileTaskRunner( FileSystemContext* context, - blink::mojom::StorageType storage_type, + FileSystemType type, const std::string& host) { - FileSystemType type = - FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); - FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); if (!quota_util) return {}; @@ -107,24 +157,31 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); - FileSystemType type = - FileSystemQuotaClient::QuotaStorageTypeToFileSystemType(storage_type); - DCHECK(type != kFileSystemTypeUnknown); + base::span<const FileSystemType> types = + QuotaStorageTypeToFileSystemTypes(storage_type); - FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type); - if (!quota_util) { - std::move(callback).Run(0); - return; + base::RepeatingCallback<void(int64_t)> barrier = + base::BarrierCallback<int64_t>( + types.size(), base::BindOnce([](std::vector<int64_t> usages) { + return std::accumulate(usages.begin(), usages.end(), + 0U); + }).Then(std::move(callback))); + + for (auto type : types) { + FileSystemQuotaUtil* quota_util = file_system_context_->GetQuotaUtil(type); + if (quota_util) { + file_task_runner()->PostTaskAndReplyWithResult( + FROM_HERE, + // It is safe to pass Unretained(quota_util) since context owns it. + base::BindOnce(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner, + base::Unretained(quota_util), + base::RetainedRef(file_system_context_), + storage_key.origin(), type), + barrier); + } else { + barrier.Run(0); + } } - - file_task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, - // It is safe to pass Unretained(quota_util) since context owns it. - base::BindOnce(&FileSystemQuotaUtil::GetOriginUsageOnFileTaskRunner, - base::Unretained(quota_util), - base::RetainedRef(file_system_context_), - storage_key.origin(), type), - std::move(callback)); } void FileSystemQuotaClient::GetStorageKeysForType( @@ -133,11 +190,22 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); - file_task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&GetStorageKeysForTypeOnFileTaskRunner, - base::RetainedRef(file_system_context_), storage_type), - std::move(callback)); + base::span<const FileSystemType> types = + QuotaStorageTypeToFileSystemTypes(storage_type); + + base::RepeatingCallback<void(std::vector<blink::StorageKey>)> barrier = + base::BarrierCallback<std::vector<blink::StorageKey>>( + types.size(), + base::BindOnce(&MergeWithoutDuplicates<blink::StorageKey>) + .Then(std::move(callback))); + + for (auto type : types) { + file_task_runner()->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&GetStorageKeysForTypeOnFileTaskRunner, + base::RetainedRef(file_system_context_), type), + barrier); + } } void FileSystemQuotaClient::GetStorageKeysForHost( @@ -147,12 +215,22 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); - file_task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&GetStorageKeysForHostOnFileTaskRunner, - base::RetainedRef(file_system_context_), storage_type, - host), - std::move(callback)); + base::span<const FileSystemType> types = + QuotaStorageTypeToFileSystemTypes(storage_type); + + base::RepeatingCallback<void(std::vector<blink::StorageKey>)> barrier = + base::BarrierCallback<std::vector<blink::StorageKey>>( + types.size(), + base::BindOnce(&MergeWithoutDuplicates<blink::StorageKey>) + .Then(std::move(callback))); + + for (auto type : types) { + file_task_runner()->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&GetStorageKeysForHostOnFileTaskRunner, + base::RetainedRef(file_system_context_), type, host), + barrier); + } } void FileSystemQuotaClient::DeleteStorageKeyData( @@ -162,15 +240,29 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); - FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type); - DCHECK(fs_type != kFileSystemTypeUnknown); + base::span<const FileSystemType> fs_types = + QuotaStorageTypeToFileSystemTypes(type); - file_task_runner()->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&DeleteStorageKeyOnFileTaskRunner, - base::RetainedRef(file_system_context_), storage_key, - fs_type), - std::move(callback)); + base::RepeatingCallback<void(blink::mojom::QuotaStatusCode)> barrier = + base::BarrierCallback<blink::mojom::QuotaStatusCode>( + fs_types.size(), + base::BindOnce([](const std::vector<blink::mojom::QuotaStatusCode>& + statuses) { + for (auto status : statuses) { + if (status != blink::mojom::QuotaStatusCode::kOk) + return status; + } + return blink::mojom::QuotaStatusCode::kOk; + }).Then(std::move(callback))); + + for (const auto fs_type : fs_types) { + file_task_runner()->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&DeleteStorageKeyOnFileTaskRunner, + base::RetainedRef(file_system_context_), storage_key, + fs_type), + barrier); + } } void FileSystemQuotaClient::PerformStorageCleanup( @@ -179,30 +271,19 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!callback.is_null()); - FileSystemType fs_type = QuotaStorageTypeToFileSystemType(type); - DCHECK(fs_type != kFileSystemTypeUnknown); - file_task_runner()->PostTaskAndReply( - FROM_HERE, - base::BindOnce(&PerformStorageCleanupOnFileTaskRunner, - base::RetainedRef(file_system_context_), fs_type), - std::move(callback)); -} + base::span<const FileSystemType> fs_types = + QuotaStorageTypeToFileSystemTypes(type); -// static -FileSystemType FileSystemQuotaClient::QuotaStorageTypeToFileSystemType( - blink::mojom::StorageType storage_type) { - switch (storage_type) { - case blink::mojom::StorageType::kTemporary: - return kFileSystemTypeTemporary; - case blink::mojom::StorageType::kPersistent: - return kFileSystemTypePersistent; - case blink::mojom::StorageType::kSyncable: - return kFileSystemTypeSyncable; - case blink::mojom::StorageType::kQuotaNotManaged: - case blink::mojom::StorageType::kUnknown: - return kFileSystemTypeUnknown; + base::RepeatingClosure barrier = + base::BarrierClosure(fs_types.size(), std::move(callback)); + + for (auto fs_type : fs_types) { + file_task_runner()->PostTaskAndReply( + FROM_HERE, + base::BindOnce(&PerformStorageCleanupOnFileTaskRunner, + base::RetainedRef(file_system_context_), fs_type), + barrier); } - return kFileSystemTypeUnknown; } base::SequencedTaskRunner* FileSystemQuotaClient::file_task_runner() const {
diff --git a/storage/browser/file_system/file_system_quota_client.h b/storage/browser/file_system/file_system_quota_client.h index fee07e6..f686c0e 100644 --- a/storage/browser/file_system/file_system_quota_client.h +++ b/storage/browser/file_system/file_system_quota_client.h
@@ -55,14 +55,6 @@ void PerformStorageCleanup(blink::mojom::StorageType type, PerformStorageCleanupCallback callback) override; - // Converts FileSystemType `type` to/from the StorageType `storage_type` that - // is used for the unified quota system. - // (Basically this naively maps TEMPORARY storage type to TEMPORARY filesystem - // type, PERSISTENT storage type to PERSISTENT filesystem type and vice - // versa.) - static FileSystemType QuotaStorageTypeToFileSystemType( - blink::mojom::StorageType storage_type); - private: base::SequencedTaskRunner* file_task_runner() const;
diff --git a/storage/browser/file_system/file_system_quota_client_unittest.cc b/storage/browser/file_system/file_system_quota_client_unittest.cc index cb8bdfd..e5c2086 100644 --- a/storage/browser/file_system/file_system_quota_client_unittest.cc +++ b/storage/browser/file_system/file_system_quota_client_unittest.cc
@@ -13,6 +13,7 @@ #include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "components/services/storage/public/mojom/quota_client.mojom.h" #include "storage/browser/file_system/file_system_context.h" @@ -27,6 +28,7 @@ #include "storage/common/file_system/file_system_util.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" @@ -48,17 +50,26 @@ } // namespace -class FileSystemQuotaClientTest : public testing::Test { +class FileSystemQuotaClientTest : public testing::TestWithParam<bool> { public: FileSystemQuotaClientTest() = default; ~FileSystemQuotaClientTest() override = default; void SetUp() override { + if (persistent_quota_is_temporary_quota()) { + feature_list_.InitAndEnableFeature( + blink::features::kPersistentQuotaIsTemporaryQuota); + } else { + feature_list_.InitAndDisableFeature( + blink::features::kPersistentQuotaIsTemporaryQuota); + } ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); file_system_context_ = CreateFileSystemContextForTesting( /*quota_manager_proxy=*/nullptr, data_dir_.GetPath()); } + bool persistent_quota_is_temporary_quota() const { return GetParam(); } + struct TestFile { bool isDirectory; const char* name; @@ -169,9 +180,8 @@ // create it later, this will fail due to a quota mismatch. If we // call this before we create the root, it succeeds, but hasn't // actually created the cache. - ASSERT_EQ(0, GetStorageKeyUsage( - quota_client, file.origin_url, - FileSystemTypeToQuotaStorageType(file.type))); + GetStorageKeyUsage(quota_client, file.origin_url, + FileSystemTypeToQuotaStorageType(file.type)); } } else { ASSERT_TRUE( @@ -232,6 +242,7 @@ deletion_status_ = status; } + base::test::ScopedFeatureList feature_list_; base::ScopedTempDir data_dir_; base::test::TaskEnvironment task_environment_; scoped_refptr<FileSystemContext> file_system_context_; @@ -243,13 +254,13 @@ base::WeakPtrFactory<FileSystemQuotaClientTest> weak_factory_{this}; }; -TEST_F(FileSystemQuotaClientTest, NoFileSystemTest) { +TEST_P(FileSystemQuotaClientTest, NoFileSystemTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); EXPECT_EQ(0, GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); } -TEST_F(FileSystemQuotaClientTest, NoFileTest) { +TEST_P(FileSystemQuotaClientTest, NoFileTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); InitializeOriginFiles(quota_client, @@ -260,7 +271,7 @@ } } -TEST_F(FileSystemQuotaClientTest, OneFileTest) { +TEST_P(FileSystemQuotaClientTest, OneFileTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, @@ -276,7 +287,7 @@ } } -TEST_F(FileSystemQuotaClientTest, TwoFilesTest) { +TEST_P(FileSystemQuotaClientTest, TwoFilesTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, @@ -293,7 +304,7 @@ } } -TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) { +TEST_P(FileSystemQuotaClientTest, EmptyFilesTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, @@ -311,7 +322,7 @@ } } -TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) { +TEST_P(FileSystemQuotaClientTest, SubDirectoryTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, @@ -329,7 +340,7 @@ } } -TEST_F(FileSystemQuotaClientTest, MultiTypeTest) { +TEST_P(FileSystemQuotaClientTest, MultiTypeTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, @@ -350,14 +361,20 @@ kFileSystemTypePersistent); for (int i = 0; i < 2; i++) { - EXPECT_EQ(133 + 14 + file_paths_cost_temporary, - GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); - EXPECT_EQ(193 + 9 + file_paths_cost_persistent, - GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent)); + if (persistent_quota_is_temporary_quota()) { + EXPECT_EQ(133 + 14 + file_paths_cost_temporary + 193 + 9 + + file_paths_cost_persistent, + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); + } else { + EXPECT_EQ(133 + 14 + file_paths_cost_temporary, + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); + EXPECT_EQ(193 + 9 + file_paths_cost_persistent, + GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent)); + } } } -TEST_F(FileSystemQuotaClientTest, MultiDomainTest) { +TEST_P(FileSystemQuotaClientTest, MultiDomainTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, @@ -392,18 +409,27 @@ kFileSystemTypePersistent); for (int i = 0; i < 2; i++) { - EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1, - GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); - EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1, - GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent)); - EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2, - GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary)); - EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2, - GetStorageKeyUsage(quota_client, kDummyURL2, kPersistent)); + if (persistent_quota_is_temporary_quota()) { + EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1 + 1903 + 19 + + file_paths_cost_persistent1, + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); + EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2 + 2013 + 18 + + file_paths_cost_persistent2, + GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary)); + } else { + EXPECT_EQ(1331 + 134 + file_paths_cost_temporary1, + GetStorageKeyUsage(quota_client, kDummyURL1, kTemporary)); + EXPECT_EQ(1903 + 19 + file_paths_cost_persistent1, + GetStorageKeyUsage(quota_client, kDummyURL1, kPersistent)); + EXPECT_EQ(1319 + 113 + file_paths_cost_temporary2, + GetStorageKeyUsage(quota_client, kDummyURL2, kTemporary)); + EXPECT_EQ(2013 + 18 + file_paths_cost_persistent2, + GetStorageKeyUsage(quota_client, kDummyURL2, kPersistent)); + } } } -TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) { +TEST_P(FileSystemQuotaClientTest, GetUsage_MultipleTasks) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, kDummyURL1, kFileSystemTypeTemporary}, @@ -433,7 +459,7 @@ EXPECT_EQ(2, additional_callback_count()); } -TEST_F(FileSystemQuotaClientTest, GetStorageKeysForType) { +TEST_P(FileSystemQuotaClientTest, GetStorageKeysForType) { FileSystemQuotaClient quota_client(GetFileSystemContext()); InitializeOriginFiles( quota_client, { @@ -442,13 +468,21 @@ {true, "", 0, kDummyURL3, kFileSystemTypePersistent}, }); - EXPECT_THAT(GetStorageKeysForType(quota_client, kTemporary), - testing::UnorderedElementsAre( - StorageKey::CreateFromStringForTesting(kDummyURL1), - StorageKey::CreateFromStringForTesting(kDummyURL2))); + if (persistent_quota_is_temporary_quota()) { + EXPECT_THAT(GetStorageKeysForType(quota_client, kTemporary), + testing::UnorderedElementsAre( + StorageKey::CreateFromStringForTesting(kDummyURL1), + StorageKey::CreateFromStringForTesting(kDummyURL2), + StorageKey::CreateFromStringForTesting(kDummyURL3))); + } else { + EXPECT_THAT(GetStorageKeysForType(quota_client, kTemporary), + testing::UnorderedElementsAre( + StorageKey::CreateFromStringForTesting(kDummyURL1), + StorageKey::CreateFromStringForTesting(kDummyURL2))); + } } -TEST_F(FileSystemQuotaClientTest, GetStorageKeysForHost) { +TEST_P(FileSystemQuotaClientTest, GetStorageKeysForHost) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const char* kURL1 = "http://foo.com/"; const char* kURL2 = "https://foo.com/"; @@ -464,14 +498,23 @@ {true, "", 0, kURL5, kFileSystemTypePersistent}, }); - EXPECT_THAT(GetStorageKeysForHost(quota_client, kTemporary, "foo.com"), - testing::UnorderedElementsAre( - StorageKey::CreateFromStringForTesting(kURL1), - StorageKey::CreateFromStringForTesting(kURL2), - StorageKey::CreateFromStringForTesting(kURL3))); + if (persistent_quota_is_temporary_quota()) { + EXPECT_THAT(GetStorageKeysForHost(quota_client, kTemporary, "foo.com"), + testing::UnorderedElementsAre( + StorageKey::CreateFromStringForTesting(kURL1), + StorageKey::CreateFromStringForTesting(kURL2), + StorageKey::CreateFromStringForTesting(kURL3), + StorageKey::CreateFromStringForTesting(kURL5))); + } else { + EXPECT_THAT(GetStorageKeysForHost(quota_client, kTemporary, "foo.com"), + testing::UnorderedElementsAre( + StorageKey::CreateFromStringForTesting(kURL1), + StorageKey::CreateFromStringForTesting(kURL2), + StorageKey::CreateFromStringForTesting(kURL3))); + } } -TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) { +TEST_P(FileSystemQuotaClientTest, DeleteOriginTest) { FileSystemQuotaClient quota_client(GetFileSystemContext()); const std::vector<TestFile> kFiles = { {true, "", 0, "http://foo.com/", kFileSystemTypeTemporary}, @@ -499,6 +542,9 @@ const int64_t file_paths_cost_temporary_bar = ComputeFilePathsCostForOriginAndType(kFiles, "http://bar.com/", kFileSystemTypeTemporary); + const int64_t file_paths_cost_persistent_bar = + ComputeFilePathsCostForOriginAndType(kFiles, "http://bar.com/", + kFileSystemTypePersistent); const int64_t file_paths_cost_temporary_bar_https = ComputeFilePathsCostForOriginAndType(kFiles, "https://bar.com/", kFileSystemTypeTemporary); @@ -510,29 +556,44 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status()); - DeleteStorageKeyData("a_client, "http://bar.com/", kPersistent); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status()); + if (!persistent_quota_is_temporary_quota()) { + DeleteStorageKeyData("a_client, "http://bar.com/", kPersistent); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status()); + } DeleteStorageKeyData("a_client, "http://buz.com/", kTemporary); base::RunLoop().RunUntilIdle(); EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk, status()); EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://foo.com/", kTemporary)); - EXPECT_EQ(0, - GetStorageKeyUsage(quota_client, "http://bar.com/", kPersistent)); EXPECT_EQ(0, GetStorageKeyUsage(quota_client, "http://buz.com/", kTemporary)); - EXPECT_EQ(2 + file_paths_cost_temporary_foo_https, GetStorageKeyUsage(quota_client, "https://foo.com/", kTemporary)); - EXPECT_EQ(4 + file_paths_cost_persistent_foo, - GetStorageKeyUsage(quota_client, "http://foo.com/", kPersistent)); - EXPECT_EQ(8 + file_paths_cost_temporary_bar, + EXPECT_EQ(8 + file_paths_cost_temporary_bar + + (persistent_quota_is_temporary_quota() + ? 16 + file_paths_cost_persistent_bar + : 0), GetStorageKeyUsage(quota_client, "http://bar.com/", kTemporary)); - EXPECT_EQ(32 + file_paths_cost_persistent_bar_https, - GetStorageKeyUsage(quota_client, "https://bar.com/", kPersistent)); - EXPECT_EQ(64 + file_paths_cost_temporary_bar_https, + EXPECT_EQ(64 + file_paths_cost_temporary_bar_https + + (persistent_quota_is_temporary_quota() + ? 32 + file_paths_cost_persistent_bar_https + : 0), GetStorageKeyUsage(quota_client, "https://bar.com/", kTemporary)); + + if (!persistent_quota_is_temporary_quota()) { + EXPECT_EQ(0, + GetStorageKeyUsage(quota_client, "http://bar.com/", kPersistent)); + EXPECT_EQ(4 + file_paths_cost_persistent_foo, + GetStorageKeyUsage(quota_client, "http://foo.com/", kPersistent)); + EXPECT_EQ( + 32 + file_paths_cost_persistent_bar_https, + GetStorageKeyUsage(quota_client, "https://bar.com/", kPersistent)); + } } +INSTANTIATE_TEST_SUITE_P(FileSystemQuotaClientTests, + FileSystemQuotaClientTest, + testing::Bool()); + } // namespace storage
diff --git a/storage/browser/file_system/file_system_util.cc b/storage/browser/file_system/file_system_util.cc index 95b190f..a32a53f 100644 --- a/storage/browser/file_system/file_system_util.cc +++ b/storage/browser/file_system/file_system_util.cc
@@ -4,13 +4,20 @@ #include "storage/browser/file_system/file_system_util.h" +#include "base/feature_list.h" #include "storage/common/file_system/file_system_types.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" namespace storage { blink::mojom::StorageType FileSystemTypeToQuotaStorageType( FileSystemType type) { + if (base::FeatureList::IsEnabled( + blink::features::kPersistentQuotaIsTemporaryQuota) && + (type == kFileSystemTypeTemporary || type == kFileSystemTypePersistent)) { + return blink::mojom::StorageType::kTemporary; + } switch (type) { case kFileSystemTypeTemporary: return blink::mojom::StorageType::kTemporary;
diff --git a/storage/browser/quota/quota_features.cc b/storage/browser/quota/quota_features.cc index cfb874fb..04985ab 100644 --- a/storage/browser/quota/quota_features.cc +++ b/storage/browser/quota/quota_features.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "storage/browser/quota/quota_features.h" +#include "base/feature_list.h" namespace storage {
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 31900497..4fa5198 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -3197,30 +3197,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -4937,30 +4913,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -29011,28 +28963,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -30308,28 +30238,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -31573,28 +31481,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -33386,30 +33272,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -35281,30 +35143,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -37176,30 +37014,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -39092,28 +38906,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -40374,28 +40166,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -42172,30 +41942,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high", - "os": "Windows-10", - "pool": "chrome.tests" - } - ], - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -44067,30 +43813,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high", - "os": "Windows-10", - "pool": "chrome.tests" - } - ], - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -47615,29 +47337,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 952bdfd..1378213 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -1668,22 +1668,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -3600,31 +3584,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "isolate_profile_data": true, "merge": { "args": [], @@ -94907,30 +94866,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-18363" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -96505,29 +96440,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "isolate_profile_data": true, "merge": { "args": [],
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 570d14b..6c7fd1d 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -19092,29 +19092,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 7cd92fbc..64e32195 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -1110,28 +1110,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -3309,31 +3287,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-18363" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "isolate_profile_data": true, "merge": { "args": [], @@ -5525,30 +5478,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "integrity": "high", - "os": "Windows-10-19042" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -7165,28 +7094,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -8684,28 +8591,6 @@ "test_id_prefix": "ninja://chrome/updater:updater_tests/" }, { - "args": [ - "--test-launcher-timeout=90000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "integrity": "high" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "updater_tests_system", - "test_id_prefix": "ninja://chrome/updater:updater_tests_system/" - }, - { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/internal.chrome.fyi.json b/testing/buildbot/internal.chrome.fyi.json index f77a52f..8c34d978 100644 --- a/testing/buildbot/internal.chrome.fyi.json +++ b/testing/buildbot/internal.chrome.fyi.json
@@ -31,5 +31,35 @@ "test_id_prefix": "ninja://chrome/test:variations_smoke_tests/" } ] + }, + "win-chrome-finch-fyi": { + "additional_compile_targets": [ + "chrome" + ], + "isolated_scripts": [ + { + "isolate_name": "variations_smoke_tests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "variations_smoke_tests", + "resultdb": { + "enable": true, + "result_format": "single" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Windows-10-15063", + "pool": "chrome.tests" + } + ], + "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:variations_smoke_tests/" + } + ] } }
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 6a21635..2f82cbfd 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -1106,6 +1106,13 @@ }, }, }, + 'win10-1703' : { + 'swarming': { + 'dimensions': { + 'os': 'Windows-10-15063', + }, + }, + }, 'win10-20h2': { 'swarming': { 'dimensions': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 8be7360..5662d7dc 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -5579,21 +5579,6 @@ '--ui-test-action-timeout=40000', ], }, - 'updater_tests_system': { - 'args': [ - # Timeouts based on empirical observations of test runtimes, 2021-07. - '--test-launcher-timeout=90000', - '--ui-test-action-max-timeout=45000', - '--ui-test-action-timeout=40000', - ], - 'swarming': { - 'dimension_sets': [ - { - 'integrity': 'high', - } - ], - }, - }, 'zucchini_unittests': {}, },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index e498517..f8349656 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -6494,6 +6494,18 @@ 'isolated_scripts': 'variations_smoke_tests', }, }, + 'win-chrome-finch-fyi': { + 'additional_compile_targets': [ + 'chrome', + ], + 'mixins': [ + 'chrome-swarming-pool', + 'win10-1703', + ], + 'test_suites': { + 'isolated_scripts': 'variations_smoke_tests', + }, + }, }, }, {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index dd3b5a9..86cc0045 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2474,27 +2474,6 @@ ] } ], - "CopyLinkToTextDesktop": [ - { - "platforms": [ - "chromeos", - "chromeos_lacros", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "CopyLinkToText", - "PreemptiveLinkToTextGeneration", - "SharedHighlightingV2" - ] - } - ] - } - ], "CrOSAutoSelect": [ { "platforms": [ @@ -3669,6 +3648,31 @@ ] } ], + "FeedPullToRefresh": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "EnabledWithIph", + "enable_features": [ + "FeedInteractiveRefresh", + "IPH_FeedSwipeRefresh" + ] + }, + { + "name": "EnabledWithoutIph", + "enable_features": [ + "FeedInteractiveRefresh" + ], + "disable_features": [ + "IPH_FeedSwipeRefresh" + ] + } + ] + } + ], "FillingAcrossAffiliatedWebsites": [ { "platforms": [ @@ -5703,30 +5707,120 @@ ], "experiments": [ { - "name": "Adaptive_AlwaysNewTab_20210428", + "name": "Segmentation_AutoNoWait_20210811", + "params": { + "default_segment": "new-tab", + "disable_ui": "false", + "ignore_segmentation_results": "false", + "min_version_adaptive": "2", + "segment_selection_ttl_days": "14", + "show_ui_only_after_ready": "false" + }, + "enable_features": [ + "AdaptiveButtonInTopToolbarCustomizationV2", + "SegmentationPlatform" + ], + "disable_features": [ + "AdaptiveButtonInTopToolbar" + ] + }, + { + "name": "Segmentation_Auto_20210811", + "params": { + "default_segment": "new-tab", + "disable_ui": "false", + "ignore_segmentation_results": "false", + "min_version_adaptive": "2", + "segment_selection_ttl_days": "14", + "show_ui_only_after_ready": "true" + }, + "enable_features": [ + "AdaptiveButtonInTopToolbarCustomizationV2", + "SegmentationPlatform" + ], + "disable_features": [ + "AdaptiveButtonInTopToolbar" + ] + }, + { + "name": "Segmentation_Default_Segment_20210811", + "params": { + "default_segment": "new-tab", + "disable_ui": "false", + "ignore_segmentation_results": "true", + "min_version_adaptive": "2", + "segment_selection_ttl_days": "14", + "show_ui_only_after_ready": "true" + }, + "enable_features": [ + "AdaptiveButtonInTopToolbarCustomizationV2", + "SegmentationPlatform" + ], + "disable_features": [ + "AdaptiveButtonInTopToolbar" + ] + }, + { + "name": "Segmentation_Control_20210811", + "params": { + "default_segment": "new-tab", + "disable_ui": "false", + "ignore_segmentation_results": "false", + "segment_selection_ttl_days": "14", + "show_ui_only_after_ready": "true" + }, + "disable_features": [ + "AdaptiveButtonInTopToolbar", + "AdaptiveButtonInTopToolbarCustomizationV2", + "SegmentationPlatform" + ] + }, + { + "name": "Adaptive_AlwaysNewTab_20210730", "params": { "mode": "always-new-tab" }, "enable_features": [ "AdaptiveButtonInTopToolbar" + ], + "disable_features": [ + "AdaptiveButtonInTopToolbarCustomizationV2" ] }, { - "name": "Adaptive_AlwaysShare_20210428", + "name": "Adaptive_AlwaysShare_20210730", "params": { "mode": "always-share" }, "enable_features": [ "AdaptiveButtonInTopToolbar" + ], + "disable_features": [ + "AdaptiveButtonInTopToolbarCustomizationV2" ] }, { - "name": "Adaptive_AlwaysVoice_20210428", + "name": "Adaptive_AlwaysVoice_20210730", "params": { "mode": "always-voice" }, "enable_features": [ "AdaptiveButtonInTopToolbar" + ], + "disable_features": [ + "AdaptiveButtonInTopToolbarCustomizationV2" + ] + }, + { + "name": "Adaptive_Control_20210730", + "params": { + "mode": "always-none" + }, + "enable_features": [ + "AdaptiveButtonInTopToolbar" + ], + "disable_features": [ + "AdaptiveButtonInTopToolbarCustomizationV2" ] }, { @@ -7738,6 +7832,25 @@ ] } ], + "SharedHighlightingDesktopV2": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "SharedHighlightingV2" + ] + } + ] + } + ], "SharedHighlightingIOS": [ { "platforms": [ @@ -8266,6 +8379,28 @@ ] } ], + "TransformInterop": [ + { + "platforms": [ + "android", + "android_weblayer", + "android_webview", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "TransformInterop" + ] + } + ] + } + ], "TranslateRankerModel": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 7878b143..45905c380 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1028,5 +1028,8 @@ const base::Feature kSyncLoadDataUrlFonts{"SyncLoadDataUrlFonts", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kPersistentQuotaIsTemporaryQuota{ + "PersistentQuotaIsTemporaryQuota", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index c332d6aa..0bb61b6 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -446,6 +446,10 @@ // Synchronously load web fonts inlined as data urls. See crbug.com/1236283 BLINK_COMMON_EXPORT extern const base::Feature kSyncLoadDataUrlFonts; +// Makes Persistent quota the same as Temporary quota. +BLINK_COMMON_EXPORT +extern const base::Feature kPersistentQuotaIsTemporaryQuota; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 6fb5282..c0a231f9 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -58,6 +58,9 @@ "devtools/devtools_frontend.mojom", "devtools/inspector_issue.mojom", "disk_allocator.mojom", + "dom_storage/dom_storage.mojom", + "dom_storage/session_storage_namespace.mojom", + "dom_storage/storage_area.mojom", "favicon/favicon_url.mojom", "feature_observer/feature_observer.mojom", "federated_learning/floc.mojom", @@ -92,7 +95,6 @@ "input/touch_event.mojom", "interest_group/ad_auction_service.mojom", "interest_group/interest_group_types.mojom", - "interest_group/restricted_interest_group_store.mojom", "keyboard_lock/keyboard_lock.mojom", "leak_detector/leak_detector.mojom", "link_to_text/link_to_text.mojom", @@ -253,7 +255,6 @@ "//services/service_manager/public/mojom", "//services/viz/public/mojom", "//skia/public/mojom", - "//third_party/blink/public/mojom/dom_storage", "//third_party/blink/public/mojom/frame", "//third_party/blink/public/mojom/gpu", "//third_party/blink/public/mojom/service_worker:storage",
diff --git a/third_party/blink/public/mojom/dom_storage/BUILD.gn b/third_party/blink/public/mojom/dom_storage/BUILD.gn deleted file mode 100644 index baae1310..0000000 --- a/third_party/blink/public/mojom/dom_storage/BUILD.gn +++ /dev/null
@@ -1,27 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") - -mojom_component("dom_storage") { - output_prefix = "dom_storage_mojom" - macro_prefix = "DOM_STORAGE_MOJOM" - - sources = [ - "dom_storage.mojom", - "session_storage_namespace.mojom", - "storage_area.mojom", - ] - - public_deps = [ "//url/mojom:url_mojom_origin" ] - - # The Blink variant is linked directly into the private platform - # implementation and so it requires the corresponding export configuration to - # override the normal mojom_component() target exports. - export_class_attribute_blink = "PLATFORM_EXPORT" - export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" - export_header_blink = "third_party/blink/renderer/platform/platform_export.h" - - generate_java = true -}
diff --git a/third_party/blink/public/mojom/interest_group/ad_auction_service.mojom b/third_party/blink/public/mojom/interest_group/ad_auction_service.mojom index c52b9ba..ad18b27 100644 --- a/third_party/blink/public/mojom/interest_group/ad_auction_service.mojom +++ b/third_party/blink/public/mojom/interest_group/ad_auction_service.mojom
@@ -5,10 +5,10 @@ module blink.mojom; import "third_party/blink/public/mojom/interest_group/interest_group_types.mojom"; +import "url/mojom/origin.mojom"; import "url/mojom/url.mojom"; -// API to initiate on-device ad auction, using interest groups specified with -// the RestrictedInterestGroupStore service. +// Per-frame API to initiate on-device ad auction and add interest groups. // https://github.com/WICG/turtledove/blob/main/FLEDGE.md interface AdAuctionService { // Triggers the ad auction to run in a sandboxed JavaScript process. The @@ -18,4 +18,26 @@ // winning ad creative, which the publisher page loads into a page or iframe // in the owner's domain. If no ad wins the auction, null is returned. RunAdAuction(AuctionAdConfig config) => (url.mojom.Url? ad_display_url); + + // Requests that the browser process create or overwrite persisted interest + // group keyed by `owner` and `name` with information from `group`. The + // browser verifies that the owner origin matches that of the frame's origin + // (in the future, a mechanism will allow delegating to other origins). The + // caller cannot observe the status or results of this operation. + JoinInterestGroup(InterestGroup group); + + // Deletes the interest group stored in the browser as indicated by the + // (`origin`, `name`) tuple. `origin` must use https. + LeaveInterestGroup(url.mojom.Origin owner, string name); + + // Requests the browser update stored interest groups owned by the current + // frame's origin *only* (interest groups not owned by the frame origin aren't + // modified) using the last `update_url` registered for each owned interest + // group. JSON is downloaded from each interest group's URL, parsed safely + // using //services/data_decoder/public/cpp/data_decoder.h, and the interest + // group store is updated. Unlike the JoinInterestGroup() operation, this + // operation doesn't clear fields that weren't present in the server JSON + // response. The JSON `name`, `owner`, `userBiddingSignals` and other unknown + // fields will be ignored. + UpdateAdInterestGroups(); };
diff --git a/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom b/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom deleted file mode 100644 index eacbb1f..0000000 --- a/third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2021 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. - -module blink.mojom; - -import "third_party/blink/public/mojom/interest_group/interest_group_types.mojom"; -import "url/mojom/origin.mojom"; -import "url/mojom/url.mojom"; - -// APIs to add/leave interest groups and to initiate on-device auction. Exposed -// to the renderer on a per-frame basis. -// https://github.com/WICG/turtledove/blob/main/FLEDGE.md -interface RestrictedInterestGroupStore { - // Requests that the browser process create or overwrite persisted interest - // group keyed by `owner` and `name` with information from `group`. The - // browser verifies that the owner origin matches that of the frame's origin - // (in the future, a mechanism will allow delegating to other origins). The - // caller cannot observe the status or results of this operation. - JoinInterestGroup(InterestGroup group); - - // Deletes the interest group stored in the browser as indicated by the - // (`origin`, `name`) tuple. `origin` must use https. - LeaveInterestGroup(url.mojom.Origin owner, string name); - - // Requests the browser update stored interest groups owned by the current - // frame's origin *only* (interest groups not owned by the frame origin aren't - // modified) using the last `update_url` registered for each owned interest - // group. JSON is downloaded from each interest group's URL, parsed safely - // using //services/data_decoder/public/cpp/data_decoder.h, and the interest - // group store is updated. Unlike the JoinInterestGroup() operation, this - // operation doesn't clear fields that weren't present in the server JSON - // response. The JSON `name`, `owner`, `userBiddingSignals` and other unknown - // fields will be ignored. - UpdateAdInterestGroups(); -};
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index 74dd120d..fb231df5 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -3293,6 +3293,7 @@ kV8NavigatorManagedData_GetAnnotatedLocation_Method = 3981, kUserDataFieldFilledPreviously = 3982, kTableCollapsedBorderDifferentToVisual = 3983, + kHighlightAPIRegisterHighlight = 3984, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_media_player.h b/third_party/blink/public/platform/web_media_player.h index 306f13a..22a7222 100644 --- a/third_party/blink/public/platform/web_media_player.h +++ b/third_party/blink/public/platform/web_media_player.h
@@ -179,9 +179,6 @@ // calls are still made periodically. virtual void OnTimeUpdate() {} - virtual void RequestRemotePlayback() {} - virtual void RequestRemotePlaybackControl() {} - virtual void RequestRemotePlaybackStop() {} virtual void RequestRemotePlaybackDisabled(bool disabled) {} virtual void FlingingStarted() {} virtual void FlingingStopped() {}
diff --git a/third_party/blink/renderer/core/app_history/app_history.cc b/third_party/blink/renderer/core/app_history/app_history.cc index 06d695b..d151741 100644 --- a/third_party/blink/renderer/core/app_history/app_history.cc +++ b/third_party/blink/renderer/core/app_history/app_history.cc
@@ -37,15 +37,18 @@ public: AppHistoryApiNavigation(ScriptState* script_state, AppHistoryNavigationOptions* options, - const String& key = String()) + const String& key, + scoped_refptr<SerializedScriptValue> state = nullptr) : info(options->getInfoOr( ScriptValue(script_state->GetIsolate(), v8::Undefined(script_state->GetIsolate())))), + serialized_state(std::move(state)), resolver(MakeGarbageCollected<ScriptPromiseResolver>(script_state)), returned_promise(resolver->Promise()), key(key) {} ScriptValue info; + scoped_refptr<SerializedScriptValue> serialized_state; Member<ScriptPromiseResolver> resolver; ScriptPromise returned_promise; String key; @@ -99,12 +102,13 @@ ScriptValue Call(ScriptValue value) final { DCHECK(window_); - if (signal_ && signal_->aborted()) { + if (signal_->aborted()) { window_ = nullptr; return ScriptValue(); } AppHistory* app_history = AppHistory::appHistory(*window_); + app_history->ongoing_navigation_signal_ = nullptr; if (type_ == ResolveType::kFulfill) { if (navigation_) { navigation_->resolver->Resolve(); @@ -200,7 +204,6 @@ // A same-document navigation (e.g., a document.open()) in a newly created // iframe will try to operate on an empty |entries_|. appHistory considers // this a no-op. - post_navigate_event_ongoing_navigation_signal_ = nullptr; if (entries_.IsEmpty()) return; @@ -330,11 +333,10 @@ frame_load_type == WebFrameLoadType::kStandard); AppHistoryApiNavigation* navigation = - MakeGarbageCollected<AppHistoryApiNavigation>(script_state, options); + MakeGarbageCollected<AppHistoryApiNavigation>( + script_state, options, String(), std::move(serialized_state)); upcoming_non_traversal_navigation_ = navigation; - to_be_set_serialized_state_ = serialized_state; - GetSupplementable()->GetFrame()->MaybeLogAdClickNavigation(); FrameLoadRequest request(GetSupplementable(), ResourceRequest(url)); @@ -351,9 +353,9 @@ return ScriptPromise(); } - if (to_be_set_serialized_state_) { + if (navigation->serialized_state) { current()->GetItem()->SetAppHistoryState( - std::move(to_be_set_serialized_state_)); + std::move(navigation->serialized_state)); } return navigation->returned_promise; } @@ -532,8 +534,8 @@ SerializedScriptValue* destination_state = nullptr; if (destination_item) destination_state = destination_item->GetAppHistoryState(); - else if (to_be_set_serialized_state_) - destination_state = to_be_set_serialized_state_.get(); + else if (navigation && navigation->serialized_state) + destination_state = navigation->serialized_state.get(); AppHistoryDestination* destination = MakeGarbageCollected<AppHistoryDestination>( url, event_type != NavigateEventType::kCrossDocument, @@ -570,17 +572,20 @@ navigate_event->SetUrl(url); DCHECK(!ongoing_navigate_event_); + DCHECK(!ongoing_navigation_signal_); ongoing_navigate_event_ = navigate_event; + ongoing_navigation_signal_ = navigate_event->signal(); DispatchEvent(*navigate_event); ongoing_navigate_event_ = nullptr; - if (!GetSupplementable()->GetFrame()) { - DCHECK(navigate_event->signal()->aborted()); + if (navigate_event->defaultPrevented()) { + if (!navigate_event->signal()->aborted()) + FinalizeWithAbortedNavigationError(script_state, navigation); return DispatchResult::kAbort; } auto promise_list = navigate_event->GetNavigationActionPromisesList(); - if (!promise_list.IsEmpty() && !navigate_event->defaultPrevented()) { + if (!promise_list.IsEmpty()) { // The spec says that at this point we should either run the URL and history // update steps (for non-traverse cases) or we should do a same-document // history traversal. In our implementation it's easier for the caller to do @@ -593,25 +598,17 @@ state_object, type); } } - post_navigate_event_ongoing_navigation_signal_ = navigate_event->signal(); - - if (navigate_event->defaultPrevented()) { - if (!navigate_event->signal()->aborted()) - FinalizeWithAbortedNavigationError(script_state, navigation); - return DispatchResult::kAbort; - } if (!promise_list.IsEmpty() || event_type != NavigateEventType::kCrossDocument) { NavigateReaction::React(script_state, ScriptPromise::All(script_state, promise_list), navigation, navigate_event->signal()); - } else { - to_be_set_serialized_state_.reset(); + } else if (navigation) { + navigation->serialized_state.reset(); // The spec assumes it's ok to leave a promise permanently unresolved, but // ScriptPromiseResolver requires either resolution or explicit detach. - if (navigation) - navigation->resolver->Detach(); + navigation->resolver->Detach(); } return promise_list.IsEmpty() ? DispatchResult::kContinue @@ -619,13 +616,18 @@ } void AppHistory::InformAboutCanceledNavigation() { - if (ongoing_navigate_event_ || - post_navigate_event_ongoing_navigation_signal_) { + if (ongoing_navigation_signal_) { auto* script_state = ToScriptStateForMainWorld(GetSupplementable()->GetFrame()); ScriptState::Scope scope(script_state); - FinalizeWithAbortedNavigationError(script_state, - ongoing_non_traversal_navigation_); + AppHistoryApiNavigation* navigation = ongoing_non_traversal_navigation_; + if (!navigation && ongoing_navigate_event_) { + auto it = ongoing_traversals_.find( + ongoing_navigate_event_->destination()->key()); + if (it != ongoing_traversals_.end()) + navigation = it->value; + } + FinalizeWithAbortedNavigationError(script_state, navigation); } // If this function is being called as part of frame detach, also cleanup any @@ -680,18 +682,17 @@ void AppHistory::FinalizeWithAbortedNavigationError( ScriptState* script_state, AppHistoryApiNavigation* navigation) { - DCHECK(!ongoing_navigate_event_ || - !post_navigate_event_ongoing_navigation_signal_); if (ongoing_navigate_event_) { ongoing_navigate_event_->preventDefault(); - ongoing_navigate_event_->signal()->SignalAbort(); ongoing_navigate_event_ = nullptr; - } else if (post_navigate_event_ongoing_navigation_signal_) { - post_navigate_event_ongoing_navigation_signal_->SignalAbort(); - post_navigate_event_ongoing_navigation_signal_ = nullptr; + } + if (ongoing_navigation_signal_) { + ongoing_navigation_signal_->SignalAbort(); + ongoing_navigation_signal_ = nullptr; } - to_be_set_serialized_state_ = nullptr; + if (navigation) + navigation->serialized_state.reset(); RejectPromiseAndFireNavigateErrorEvent( navigation, ScriptValue::From(script_state, MakeGarbageCollected<DOMException>( @@ -718,7 +719,7 @@ visitor->Trace(ongoing_traversals_); visitor->Trace(upcoming_non_traversal_navigation_); visitor->Trace(ongoing_navigate_event_); - visitor->Trace(post_navigate_event_ongoing_navigation_signal_); + visitor->Trace(ongoing_navigation_signal_); } } // namespace blink
diff --git a/third_party/blink/renderer/core/app_history/app_history.h b/third_party/blink/renderer/core/app_history/app_history.h index ac0b39c2..4e1f8ec 100644 --- a/third_party/blink/renderer/core/app_history/app_history.h +++ b/third_party/blink/renderer/core/app_history/app_history.h
@@ -137,9 +137,7 @@ Member<AppHistoryApiNavigation> upcoming_non_traversal_navigation_; Member<AppHistoryNavigateEvent> ongoing_navigate_event_; - Member<AbortSignal> post_navigate_event_ongoing_navigation_signal_; - - scoped_refptr<SerializedScriptValue> to_be_set_serialized_state_; + Member<AbortSignal> ongoing_navigation_signal_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl b/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl index 36c7cb8..e2d0910 100644 --- a/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl +++ b/third_party/blink/renderer/core/app_history/app_history_navigate_event.idl
@@ -7,7 +7,7 @@ Exposed=Window, RuntimeEnabled=AppHistory ] interface AppHistoryNavigateEvent : Event { - [CallWith=ExecutionContext] constructor(DOMString type, optional AppHistoryNavigateEventInit eventInit = {}); + [CallWith=ExecutionContext] constructor(DOMString type, AppHistoryNavigateEventInit eventInit); readonly attribute AppHistoryNavigationType navigationType; readonly attribute AppHistoryDestination destination;
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index 3cfc916..f14a046 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -163,8 +163,8 @@ LocalFrame* frame = node_->GetDocument().GetFrame(); if (frame && frame->DomWindow()) { eventTiming = EventTiming::Create(frame->DomWindow(), *event_); - // TODO(hbsong): Calculate First Input Delay for filtered events. - EventTiming::HandleInputDelay(frame->DomWindow(), *event_); + if (!base::FeatureList::IsEnabled(kFirstInputDelayWithoutEventListener)) + EventTiming::HandleInputDelay(frame->DomWindow(), *event_); } if (event_->type() == event_type_names::kChange && event_->isTrusted() &&
diff --git a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc index 953acec..24a14fd 100644 --- a/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc +++ b/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
@@ -138,14 +138,20 @@ kPseudoIdFirstLetter) { first_letter_text_layout_object = first_letter_text_layout_object->NextSibling(); - } else if (first_letter_text_layout_object->IsText()) { + } else if (auto* layout_text = + DynamicTo<LayoutText>(first_letter_text_layout_object)) { + // Don't apply first letter styling to passwords and other elements + // obfuscated by -webkit-text-security. Also, see + // ShouldUpdateLayoutByReattaching() in text.cc. + if (layout_text->IsSecure()) + return nullptr; // FIXME: If there is leading punctuation in a different LayoutText than // the first letter, we'll not apply the correct style to it. scoped_refptr<StringImpl> str = - To<LayoutText>(first_letter_text_layout_object)->IsTextFragment() + layout_text->IsTextFragment() ? To<LayoutTextFragment>(first_letter_text_layout_object) ->CompleteText() - : To<LayoutText>(first_letter_text_layout_object)->OriginalText(); + : layout_text->OriginalText(); if (FirstLetterLength(str.get()) || IsInvalidFirstLetterLayoutObject(first_letter_text_layout_object)) break;
diff --git a/third_party/blink/renderer/core/dom/text.cc b/third_party/blink/renderer/core/dom/text.cc index d759e6ea..fe357798 100644 --- a/third_party/blink/renderer/core/dom/text.cc +++ b/third_party/blink/renderer/core/dom/text.cc
@@ -447,6 +447,17 @@ return text_fragment_layout_object.GetFirstLetterPseudoElement() || !text_fragment_layout_object.IsRemainingTextLayoutObject(); } + // If we force a re-attach for password inputs and other elements hiding text + // input via -webkit-text-security, the last character input will be hidden + // immediately, even if the passwordEchoEnabled setting is enabled. + // ::first-letter do not seem to apply to text inputs, so for those skipping + // the re-attachment should be safe. + // We can possibly still cause DCHECKs for mismatch of first letter text in + // editing with the combination of -webkit-text-security in author styles on + // other elements in combination with ::first-letter. + // See crbug.com/1240988 + if (text_layout_object->IsSecure()) + return false; if (!FirstLetterPseudoElement::FirstLetterLength( text_layout_object->GetText()) && FirstLetterPseudoElement::FirstLetterLength(text_node.data())) {
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.cc b/third_party/blink/renderer/core/editing/finder/text_finder.cc index cb8e8e22..07f826f 100644 --- a/third_party/blink/renderer/core/editing/finder/text_finder.cc +++ b/third_party/blink/renderer/core/editing/finder/text_finder.cc
@@ -108,39 +108,14 @@ // If the active match is hidden inside a <details> element, then we should // expand it so find-in-page can scroll to it. - if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled()) { - bool details_opened = false; - - for (Node& parent : FlatTreeTraversal::AncestorsOf(first_node)) { - if (HTMLDetailsElement* details = DynamicTo<HTMLDetailsElement>(parent)) { - // If the active match is inside the <summary> of a <details>, then we - // shouldn't expand the <details> because the active match is already - // visible. - bool inside_summary = false; - Element& summary = *details->FindMainSummary(); - for (Node& ancestor : FlatTreeTraversal::AncestorsOf(first_node)) { - if (&ancestor == &summary) { - inside_summary = true; - break; - } - } - - if (!inside_summary && - !details->FastHasAttribute(html_names::kOpenAttr)) { - details->setAttribute(html_names::kOpenAttr, g_empty_atom); - details_opened = true; - } - } - } - - if (details_opened) { - // If we opened any details elements, we need to update style and layout - // to account for the new content to render inside the now-expanded - // details element before we scroll to it. The added open attribute may - // also affect style. - first_node.GetDocument().UpdateStyleAndLayoutForNode( - &first_node, DocumentUpdateReason::kFindInPage); - } + if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled() && + HTMLDetailsElement::ExpandDetailsAncestors(first_node)) { + // If we opened any details elements, we need to update style and layout + // to account for the new content to render inside the now-expanded + // details element before we scroll to it. The added open attribute may + // also affect style and have fired mutation events. + first_node.GetDocument().UpdateStyleAndLayoutForNode( + &first_node, DocumentUpdateReason::kFindInPage); } // We don't always have a LayoutObject for the node we're trying to scroll to
diff --git a/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc b/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc index 1cff8b3..52a580c 100644 --- a/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc +++ b/third_party/blink/renderer/core/exported/web_media_player_impl_unittest.cc
@@ -2363,9 +2363,10 @@ // Video is always paused when suspension is on and only if matches the // optimization criteria if the optimization is on. - bool should_pause = !IsBackgroundVideoPlaybackEnabled() || - IsMediaSuspendOn() || - (IsBackgroundPauseOn() && matches_requirements); + bool should_pause = + (!IsBackgroundVideoPlaybackEnabled() || IsMediaSuspendOn() || + (IsBackgroundPauseOn() && matches_requirements)) && + !(IsPictureInPictureOn() && IsAndroid()); EXPECT_EQ(should_pause, ShouldPausePlaybackWhenHidden()); } @@ -2385,8 +2386,9 @@ // videos is on and background video playback is disabled. Background video // playback is enabled by default. Both media suspend and resume background // videos are on by default on Android and off on desktop. - EXPECT_EQ(!IsBackgroundVideoPlaybackEnabled() || - (IsMediaSuspendOn() && IsResumeBackgroundVideoEnabled()), + EXPECT_EQ((!IsBackgroundVideoPlaybackEnabled() || + (IsMediaSuspendOn() && IsResumeBackgroundVideoEnabled())) && + !(IsPictureInPictureOn() && IsAndroid()), ShouldPausePlaybackWhenHidden()); if (!matches_requirements || !ShouldDisableVideoWhenHidden() ||
diff --git a/third_party/blink/renderer/core/highlight/highlight_registry.cc b/third_party/blink/renderer/core/highlight/highlight_registry.cc index 54fb8aba..ed992329 100644 --- a/third_party/blink/renderer/core/highlight/highlight_registry.cc +++ b/third_party/blink/renderer/core/highlight/highlight_registry.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/platform/instrumentation/use_counter.h" namespace blink { @@ -76,6 +77,8 @@ AtomicString highlight_name, Member<Highlight> highlight, ExceptionState& exception_state) { + UseCounter::Count(ExecutionContext::From(script_state), + WebFeature::kHighlightAPIRegisterHighlight); auto highlights_iterator = GetMapIterator(highlight_name); if (highlights_iterator != highlights_.end()) { highlights_iterator->Get()->highlight->DeregisterFrom(this);
diff --git a/third_party/blink/renderer/core/html/html_details_element.cc b/third_party/blink/renderer/core/html/html_details_element.cc index 1b8de6b..d11fee4 100644 --- a/third_party/blink/renderer/core/html/html_details_element.cc +++ b/third_party/blink/renderer/core/html/html_details_element.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/events/event.h" +#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/dom/text.h" #include "third_party/blink/renderer/core/frame/web_feature.h" @@ -185,4 +186,39 @@ return true; } +// static +bool HTMLDetailsElement::ExpandDetailsAncestors(const Node& node) { + // Since setting the open attribute fires mutation events which could mess + // with the FlatTreeTraversal iterator, we should first iterate details + // elements to open and then open them all. + VectorOf<HTMLDetailsElement> details_to_open; + + for (Node& parent : FlatTreeTraversal::AncestorsOf(node)) { + if (HTMLDetailsElement* details = DynamicTo<HTMLDetailsElement>(parent)) { + // If the active match is inside the <summary> of a <details>, then we + // shouldn't expand the <details> because the active match is already + // visible. + bool inside_summary = false; + Element& summary = *details->FindMainSummary(); + for (Node& ancestor : FlatTreeTraversal::AncestorsOf(node)) { + if (&ancestor == &summary) { + inside_summary = true; + break; + } + } + + if (!inside_summary && + !details->FastHasAttribute(html_names::kOpenAttr)) { + details_to_open.push_back(details); + } + } + } + + for (HTMLDetailsElement* details : details_to_open) { + details->setAttribute(html_names::kOpenAttr, g_empty_atom); + } + + return details_to_open.size(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_details_element.h b/third_party/blink/renderer/core/html/html_details_element.h index 972a4f63..c0724ebf 100644 --- a/third_party/blink/renderer/core/html/html_details_element.h +++ b/third_party/blink/renderer/core/html/html_details_element.h
@@ -40,6 +40,12 @@ // Used for slot assignment. static bool IsFirstSummary(const Node&); + // Walks up the ancestor chain and expands all <details> elements found along + // the way by setting the open attribute. If any were expanded, returns true. + // This method may run script because of the mutation events fired when + // setting the open attribute. + static bool ExpandDetailsAncestors(const Node&); + private: void DispatchPendingEvent(const AttributeModificationReason);
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 7592c5dd..4fe2c62 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -4644,6 +4644,10 @@ setCurrentTime(seek_time.InSecondsF()); } +void HTMLMediaElement::RequestMute(bool mute) { + setMuted(mute); +} + void HTMLMediaElement::SetVolumeMultiplier(double multiplier) { if (web_media_player_) web_media_player_->SetVolumeMultiplier(multiplier);
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index 4af2fe7..6280204 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -518,6 +518,7 @@ void RequestSeekTo(base::TimeDelta seek_time) override; void RequestEnterPictureInPicture() override {} void RequestExitPictureInPicture() override {} + void RequestMute(bool mute) override; void SetVolumeMultiplier(double multiplier) override; void SetPersistentState(bool persistent) override {} void SetPowerExperimentState(bool enabled) override;
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc index 326a8bf..7edecec 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc
@@ -286,8 +286,8 @@ void InspectorDOMDebuggerAgent::DidInsertDOMNode(Node* node) { if (dom_breakpoints_.size()) { - uint32_t mask = dom_breakpoints_.DeprecatedAtOrEmptyValue( - InspectorDOMAgent::InnerParentNode(node)); + uint32_t mask = + FindBreakpointMask(InspectorDOMAgent::InnerParentNode(node)); uint32_t inheritable_types_mask = (mask | (mask >> domBreakpointDerivedTypeShift)) & inheritableDOMBreakpointTypesMask; @@ -390,8 +390,7 @@ return response; uint32_t root_bit = 1 << type; - dom_breakpoints_.Set( - node, dom_breakpoints_.DeprecatedAtOrEmptyValue(node) | root_bit); + dom_breakpoints_.Set(node, FindBreakpointMask(node) | root_bit); if (root_bit & inheritableDOMBreakpointTypesMask) { for (Node* child = InspectorDOMAgent::InnerFirstChild(node); child; child = InspectorDOMAgent::InnerNextSibling(child)) @@ -415,7 +414,7 @@ return response; uint32_t root_bit = 1 << type; - uint32_t mask = dom_breakpoints_.DeprecatedAtOrEmptyValue(node) & ~root_bit; + uint32_t mask = FindBreakpointMask(node) & ~root_bit; if (mask) dom_breakpoints_.Set(node, mask); else @@ -567,8 +566,7 @@ if (!insertion) breakpoint_owner = InspectorDOMAgent::InnerParentNode(target); DCHECK(breakpoint_owner); - while (!(dom_breakpoints_.DeprecatedAtOrEmptyValue(breakpoint_owner) & - (1 << breakpoint_type))) { + while (!(FindBreakpointMask(breakpoint_owner) & (1 << breakpoint_type))) { Node* parent_node = InspectorDOMAgent::InnerParentNode(breakpoint_owner); if (!parent_node) break; @@ -591,19 +589,23 @@ v8_inspector::StringView(json.data(), json.size())); } -bool InspectorDOMDebuggerAgent::HasBreakpoint(Node* node, int type) { +bool InspectorDOMDebuggerAgent::HasBreakpoint(Node* node, int type) const { if (!dom_agent_->Enabled()) return false; uint32_t root_bit = 1 << type; uint32_t derived_bit = root_bit << domBreakpointDerivedTypeShift; - return dom_breakpoints_.DeprecatedAtOrEmptyValue(node) & - (root_bit | derived_bit); + return FindBreakpointMask(node) & (root_bit | derived_bit); +} + +uint32_t InspectorDOMDebuggerAgent::FindBreakpointMask(Node* node) const { + auto it = dom_breakpoints_.find(node); + return it != dom_breakpoints_.end() ? it->value : 0; } void InspectorDOMDebuggerAgent::UpdateSubtreeBreakpoints(Node* node, uint32_t root_mask, bool set) { - uint32_t old_mask = dom_breakpoints_.DeprecatedAtOrEmptyValue(node); + uint32_t old_mask = FindBreakpointMask(node); uint32_t derived_mask = root_mask << domBreakpointDerivedTypeShift; uint32_t new_mask = set ? old_mask | derived_mask : old_mask & ~derived_mask; if (new_mask)
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h index 484c72a9..5f66429 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h
@@ -162,7 +162,9 @@ int breakpoint_type, bool insertion); void UpdateSubtreeBreakpoints(Node*, uint32_t root_mask, bool set); - bool HasBreakpoint(Node*, int type); + bool HasBreakpoint(Node*, int type) const; + // Returns value if node is in `dom_breakpoints_`, otherwise zero. + uint32_t FindBreakpointMask(Node*) const; protocol::Response SetBreakpoint(const String& event_name, const String& target_name); protocol::Response RemoveBreakpoint(const String& event_name,
diff --git a/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc b/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc index 4457f0ea..678c11e3 100644 --- a/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc +++ b/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
@@ -10,6 +10,7 @@ #include "base/unguessable_token.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/probe/core_probes.h" +#include "third_party/blink/renderer/platform/wtf/hash_map.h" namespace blink { @@ -51,8 +52,7 @@ Vector<WebString> MediaInspectorContextImpl::AllPlayerIdsAndMarkSent() { Vector<WebString> existing_players; - const auto& keys = players_.Keys(); - existing_players.AppendRange(keys.begin(), keys.end()); + WTF::CopyKeysToVector(players_, existing_players); unsent_players_.clear(); return existing_players; } @@ -193,9 +193,7 @@ if (player != players_.end()) { for (const auto& property : props) player->value->properties.Set(property.name, property); - - properties.AppendRange(player->value->properties.Values().begin(), - player->value->properties.Values().end()); + WTF::CopyValuesToVector(player->value->properties, properties); } probe::PlayerPropertiesChanged(GetSupplementable(), playerId, properties); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_session_state.h b/third_party/blink/renderer/core/inspector/inspector_session_state.h index 8ca82b4..ef5fb0c0 100644 --- a/third_party/blink/renderer/core/inspector/inspector_session_state.h +++ b/third_party/blink/renderer/core/inspector/inspector_session_state.h
@@ -10,6 +10,7 @@ #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/inspector_protocol/crdtp/span.h" @@ -177,8 +178,7 @@ // TODO(johannes): It'd be nice to avoid copying; unfortunately // it didn't seem easy to return map_.Keys(). Vector<WTF::String> keys; - for (const WTF::String& s : map_.Keys()) - keys.push_back(s); + WTF::CopyKeysToVector(map_, keys); return keys; }
diff --git a/third_party/blink/renderer/core/inspector/inspector_session_state_test.cc b/third_party/blink/renderer/core/inspector/inspector_session_state_test.cc index 99dccbf..d86321a 100644 --- a/third_party/blink/renderer/core/inspector/inspector_session_state_test.cc +++ b/third_party/blink/renderer/core/inspector/inspector_session_state_test.cc
@@ -7,6 +7,7 @@ #include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/wtf/hash_map.h" namespace blink { using mojom::blink::DevToolsSessionState; @@ -236,8 +237,7 @@ // passed to AgentState so that the stored values won't collide. DevToolsSessionStatePtr cookie = dev_tools_session.CloneCookie(); Vector<WTF::String> keys; - for (const WTF::String& k : cookie->entries.Keys()) - keys.push_back(k); + WTF::CopyKeysToVector(cookie->entries, keys); EXPECT_THAT(keys, UnorderedElementsAre("map_agents.1/Pi", "simple_agent.4/"));
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 25db76c8..23e98cf 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1473,6 +1473,10 @@ NOT_DESTROYED(); return bitfields_.IsAtomicInlineLevel(); } + bool IsBlockInInline() const { + return IsAnonymous() && !IsInline() && !IsFloatingOrOutOfFlowPositioned() && + Parent() && Parent()->IsLayoutInline(); + } bool IsHorizontalWritingMode() const { NOT_DESTROYED(); return bitfields_.HorizontalWritingMode();
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc index 43b8c8d..5e5012e 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -89,6 +89,17 @@ return current_line_items_; } +const NGLogicalLineItems& NGFragmentItemsBuilder::LogicalLineItems( + const NGPhysicalLineBoxFragment& line_fragment) const { + if (&line_fragment == current_line_fragment_) { + DCHECK(current_line_items_); + return *current_line_items_; + } + const NGLogicalLineItems* items = line_items_map_.at(&line_fragment); + DCHECK(items); + return *items; +} + void NGFragmentItemsBuilder::AssociateLogicalLineItems( NGLogicalLineItems* line_items, const NGPhysicalFragment& line_fragment) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h index 17596d09..cde3196 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
@@ -71,6 +71,8 @@ // them alive until |AddLine|. NGLogicalLineItems* AcquireLogicalLineItems(); void ReleaseCurrentLogicalLineItems(); + const NGLogicalLineItems& LogicalLineItems( + const NGPhysicalLineBoxFragment&) const; void AssociateLogicalLineItems(NGLogicalLineItems* line_items, const NGPhysicalFragment& line_fragment); void AddLine(const NGPhysicalLineBoxFragment& line,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc index 0feb74d..d771d70 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -612,6 +612,7 @@ // Setup |container_builder_|. Set it up here instead of in |CreateLine|, // because there should be only one block-in-inline, and we need data from the // |NGLayoutResult|. + container_builder_.SetIsBlockInInline(); container_builder_.SetBaseDirection(line_info.BaseDirection()); if (absl::optional<LayoutUnit> block_offset = result.BfcBlockOffset()) { container_builder_.SetBfcBlockOffset(*block_offset);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc index c1c0546..d05d1b2 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.cc
@@ -71,6 +71,15 @@ return nullptr; } +const NGLayoutResult* NGLogicalLineItems::BlockInInlineLayoutResult() const { + for (const NGLogicalLineItem& item : *this) { + if (item.layout_result && + item.layout_result->PhysicalFragment().IsBlockInInline()) + return item.layout_result.get(); + } + return nullptr; +} + void NGLogicalLineItems::WillInsertChild(unsigned insert_before) { unsigned index = 0; for (NGLogicalLineItem& child : children_) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h index 0d4b2554..59d0e30 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h
@@ -16,6 +16,7 @@ namespace blink { class LayoutObject; +class NGLayoutResult; // This class represents an item in a line, after line break, but still mutable // and in the logical coordinate system. @@ -287,6 +288,8 @@ NGLogicalLineItem* FirstInFlowChild(); NGLogicalLineItem* LastInFlowChild(); + const NGLayoutResult* BlockInInlineLayoutResult() const; + // Add a child. Accepts all constructor arguments for |NGLogicalLineItem|. template <class... Args> void AddChild(Args&&... args) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc index f8beaa4e..d4ee6ed 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -97,9 +97,21 @@ absl::optional<LogicalOffset> relative_offset, bool propagate_oof_descendants) { const auto& fragment = child_layout_result.PhysicalFragment(); - if (items_builder_) { + const NGLayoutResult* child_box_layout_result = nullptr; + if (fragment.IsBox()) { + child_box_layout_result = &child_layout_result; + } else if (items_builder_) { if (const NGPhysicalLineBoxFragment* line = DynamicTo<NGPhysicalLineBoxFragment>(&fragment)) { + if (UNLIKELY(line->IsBlockInInline() && has_block_fragmentation_)) { + // If this line box contains a block-in-inline, propagate break data + // from the block-in-inline. + const NGLogicalLineItems& line_items = + items_builder_->LogicalLineItems(*line); + child_box_layout_result = line_items.BlockInInlineLayoutResult(); + DCHECK(child_box_layout_result); + } + items_builder_->AddLine(*line, offset); // TODO(kojii): We probably don't need to AddChild this line, but there // maybe OOF objects. Investigate how to handle them. @@ -117,8 +129,9 @@ AddChild(fragment, offset, /* inline_container */ nullptr, &end_margin_strut, child_layout_result.IsSelfCollapsing(), relative_offset, adjustment_for_oof_propagation); - if (fragment.IsBox()) - PropagateBreak(child_layout_result); + + if (child_box_layout_result) + PropagateBreak(*child_box_layout_result); } void NGBoxFragmentBuilder::AddChild( @@ -386,6 +399,10 @@ } #endif + if (UNLIKELY(box_type_ == NGPhysicalFragment::kNormalBox && node_ && + node_.IsBlockInInline())) + SetIsBlockInInline(); + if (UNLIKELY(has_block_fragmentation_ && !break_token_ && node_)) { if (last_inline_break_token_) child_break_tokens_.push_back(std::move(last_inline_break_token_));
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h index 985fc950..248e648 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -245,6 +245,8 @@ return adjoining_object_types_; } + void SetIsBlockInInline() { is_block_in_inline_ = true; } + void SetHasBlockFragmentation() { has_block_fragmentation_ = true; } // Set for any node that establishes a fragmentation context, such as multicol @@ -371,6 +373,7 @@ bool is_self_collapsing_ = false; bool is_pushed_by_floats_ = false; bool is_legacy_layout_root_ = false; + bool is_block_in_inline_ = false; bool has_floating_descendants_for_paint_ = false; bool has_descendant_that_depends_on_percentage_block_size_ = false;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h index c511de7..a9a01e65 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
@@ -77,6 +77,7 @@ bool IsBlock() const { return type_ == kBlock; } bool IsBlockFlow() const { return IsBlock() && box_->IsLayoutBlockFlow(); } + bool IsBlockInInline() const { return box_->IsBlockInInline(); } bool IsLayoutNGCustom() const { return IsBlock() && box_->IsLayoutNGCustom(); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index 2721b9cc..970608f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -1592,6 +1592,8 @@ DCHECK_EQ(sub_type_, other.sub_type_); DCHECK_EQ(style_variant_, other.style_variant_); DCHECK_EQ(is_hidden_for_paint_, other.is_hidden_for_paint_); + DCHECK_EQ(is_opaque_, other.is_opaque_); + DCHECK_EQ(is_block_in_inline_, other.is_block_in_inline_); DCHECK_EQ(is_math_fraction_, other.is_math_fraction_); DCHECK_EQ(is_math_operator_, other.is_math_operator_);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc index 03887b1..d30d4a86 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -343,6 +343,7 @@ style_variant_((unsigned)builder->style_variant_), is_hidden_for_paint_(builder->is_hidden_for_paint_), is_opaque_(builder->is_opaque_), + is_block_in_inline_(builder->is_block_in_inline_), is_fieldset_container_(false), is_table_ng_part_(false), is_legacy_layout_root_(false), @@ -401,6 +402,7 @@ style_variant_(other.style_variant_), is_hidden_for_paint_(other.is_hidden_for_paint_), is_opaque_(other.is_opaque_), + is_block_in_inline_(other.is_block_in_inline_), is_math_fraction_(other.is_math_fraction_), is_math_operator_(other.is_math_operator_), may_have_descendant_above_block_start_(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h index 18081ed..c73ea6a 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -126,10 +126,9 @@ bool IsAtomicInline() const { return IsBox() && BoxType() == NGBoxType::kAtomicInline; } - bool IsBlockInInline() const { - return IsBox() && BoxType() == NGBoxType::kNormalBox && GetLayoutObject() && - IsA<LayoutInline>(GetLayoutObject()->Parent()); - } + // True if this box is a block-in-inline, or if this line contains a + // block-in-inline. + bool IsBlockInInline() const { return is_block_in_inline_; } // True if this fragment is in-flow in an inline formatting context. bool IsInline() const { return IsInlineBox() || IsAtomicInline(); } bool IsFloating() const { @@ -651,6 +650,7 @@ const unsigned style_variant_ : 2; // NGStyleVariant const unsigned is_hidden_for_paint_ : 1; unsigned is_opaque_ : 1; + unsigned is_block_in_inline_ : 1; unsigned is_math_fraction_ : 1; unsigned is_math_operator_ : 1; unsigned may_have_descendant_above_block_start_ : 1;
diff --git a/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc b/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc index 65c9a1b4..d5f752b 100644 --- a/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc +++ b/third_party/blink/renderer/core/page/scrolling/element_fragment_anchor.cc
@@ -14,6 +14,7 @@ #include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/html/html_details_element.h" #include "third_party/blink/renderer/core/svg/svg_svg_element.h" #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" @@ -102,11 +103,22 @@ boundary_local_frame->View()->SetSafeToPropagateScrollToParent(false); } - auto* element_to_scroll = DynamicTo<Element>(anchor_node_.Get()); + Member<Element> element_to_scroll = DynamicTo<Element>(anchor_node_.Get()); if (!element_to_scroll) element_to_scroll = doc.documentElement(); if (element_to_scroll) { + // Expand <details> elements so we can make |element_to_scroll| visible. + if (RuntimeEnabledFeatures::AutoExpandDetailsElementEnabled() && + HTMLDetailsElement::ExpandDetailsAncestors(*element_to_scroll)) { + // If we opened any details elements, we need to update style and layout + // to account for the new content to render inside the now-expanded + // details element before we scroll to it. The added open attribute may + // also affect style. + doc.UpdateStyleAndLayoutForNode(element_to_scroll, + DocumentUpdateReason::kFindInPage); + } + ScrollIntoViewOptions* options = ScrollIntoViewOptions::Create(); options->setBlock("start"); options->setInlinePosition("nearest");
diff --git a/third_party/blink/renderer/core/timing/event_timing.cc b/third_party/blink/renderer/core/timing/event_timing.cc index 95143ba..cd2487b 100644 --- a/third_party/blink/renderer/core/timing/event_timing.cc +++ b/third_party/blink/renderer/core/timing/event_timing.cc
@@ -43,6 +43,10 @@ } // namespace +// Record FID even when there's no event listener. +const base::Feature kFirstInputDelayWithoutEventListener{ + "FirstInputDelayWithoutEventListener", base::FEATURE_DISABLED_BY_DEFAULT}; + EventTiming::EventTiming(base::TimeTicks processing_start, WindowPerformance* performance, const Event& event) @@ -112,6 +116,9 @@ if (!should_report_for_event_timing && !should_log_event) return nullptr; + if (base::FeatureList::IsEnabled(kFirstInputDelayWithoutEventListener)) + HandleInputDelay(window, event); + base::TimeTicks processing_start = Now(); return should_report_for_event_timing ? std::make_unique<EventTiming>(processing_start, performance,
diff --git a/third_party/blink/renderer/core/timing/event_timing.h b/third_party/blink/renderer/core/timing/event_timing.h index 59a8627..aa47db44 100644 --- a/third_party/blink/renderer/core/timing/event_timing.h +++ b/third_party/blink/renderer/core/timing/event_timing.h
@@ -13,6 +13,8 @@ namespace blink { +CORE_EXPORT extern const base::Feature kFirstInputDelayWithoutEventListener; + class Event; // Event timing collects and records the event start time, processing start time
diff --git a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc index 956a70b..5b4910d49 100644 --- a/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc +++ b/third_party/blink/renderer/modules/ad_auction/navigator_auction.cc
@@ -373,16 +373,11 @@ NavigatorAuction::NavigatorAuction(Navigator& navigator) : Supplement(navigator), - ad_auction_service_(navigator.GetExecutionContext()), - interest_group_store_(navigator.GetExecutionContext()) { + ad_auction_service_(navigator.GetExecutionContext()) { navigator.GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface( ad_auction_service_.BindNewPipeAndPassReceiver( navigator.GetExecutionContext()->GetTaskRunner( TaskType::kMiscPlatformAPI))); - navigator.GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface( - interest_group_store_.BindNewPipeAndPassReceiver( - navigator.GetExecutionContext()->GetTaskRunner( - TaskType::kMiscPlatformAPI))); } NavigatorAuction& NavigatorAuction::From(ExecutionContext* context, @@ -442,7 +437,7 @@ return; } - interest_group_store_->JoinInterestGroup(std::move(mojo_group)); + ad_auction_service_->JoinInterestGroup(std::move(mojo_group)); } /* static */ @@ -467,7 +462,7 @@ "' must be a valid https origin."); return; } - interest_group_store_->LeaveInterestGroup(owner, group->name()); + ad_auction_service_->LeaveInterestGroup(owner, group->name()); } /* static */ @@ -480,7 +475,7 @@ } void NavigatorAuction::updateAdInterestGroups() { - interest_group_store_->UpdateAdInterestGroups(); + ad_auction_service_->UpdateAdInterestGroups(); } /* static */
diff --git a/third_party/blink/renderer/modules/ad_auction/navigator_auction.h b/third_party/blink/renderer/modules/ad_auction/navigator_auction.h index ee8d74d..b7f40635 100644 --- a/third_party/blink/renderer/modules/ad_auction/navigator_auction.h +++ b/third_party/blink/renderer/modules/ad_auction/navigator_auction.h
@@ -6,7 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_AD_AUCTION_NAVIGATOR_AUCTION_H_ #include "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom-blink.h" -#include "third_party/blink/public/mojom/interest_group/restricted_interest_group_store.mojom-blink.h" #include "third_party/blink/renderer/core/frame/navigator.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -58,7 +57,6 @@ ExceptionState&); void Trace(Visitor* visitor) const override { - visitor->Trace(interest_group_store_); visitor->Trace(ad_auction_service_); Supplement<Navigator>::Trace(visitor); } @@ -68,8 +66,6 @@ void AuctionComplete(ScriptPromiseResolver*, const absl::optional<KURL>&); HeapMojoRemote<mojom::blink::AdAuctionService> ad_auction_service_; - HeapMojoRemote<mojom::blink::RestrictedInterestGroupStore> - interest_group_store_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc index 4f08b2afd..3af96849 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" @@ -590,8 +591,17 @@ EXPECT_FALSE(Context2D()->IdentifiabilityEncounteredPartiallyDigestedImage()); } +// TODO(crbug.com/1239374): Fix test on Android L and re-enable. +#if defined(OS_ANDROID) +#define MAYBE_IdentifiabilityStudyDigest_putImageData \ + DISABLED_IdentifiabilityStudyDigest_putImageData +#else +#define MAYBE_IdentifiabilityStudyDigest_putImageData \ + IdentifiabilityStudyDigest_putImageData +#endif // defined(OS_ANDROID) + TEST_F(CanvasRenderingContext2DAPITest, - IdentifiabilityStudyDigest_putImageData) { + MAYBE_IdentifiabilityStudyDigest_putImageData) { StudyParticipationRaii study_participation_raii; CreateContext(kNonOpaque); NonThrowableExceptionState exception_state;
diff --git a/third_party/blink/renderer/modules/presentation/presentation_connection_close_event.cc b/third_party/blink/renderer/modules/presentation/presentation_connection_close_event.cc index c1355d0f..467dc6e3 100644 --- a/third_party/blink/renderer/modules/presentation/presentation_connection_close_event.cc +++ b/third_party/blink/renderer/modules/presentation/presentation_connection_close_event.cc
@@ -21,7 +21,8 @@ const PresentationConnectionCloseEventInit* initializer) : Event(event_type, initializer), reason_(initializer->reason()), - message_(initializer->message()) {} + message_(initializer->hasMessage() ? initializer->message() + : g_empty_string) {} const AtomicString& PresentationConnectionCloseEvent::InterfaceName() const { return event_interface_names::kPresentationConnectionCloseEvent;
diff --git a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc index 0f7db968..88e4a9f 100644 --- a/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/response_body_loader_test.cc
@@ -7,6 +7,7 @@ #include <memory> #include <string> #include <utility> +#include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" #include "services/network/public/cpp/features.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.cc b/third_party/blink/renderer/platform/media/web_media_player_impl.cc index 4e02831..ce567284 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl.cc +++ b/third_party/blink/renderer/platform/media/web_media_player_impl.cc
@@ -3498,6 +3498,11 @@ return false; } +#if defined(OS_ANDROID) + if (IsInPictureInPicture()) + return false; +#endif + if (!is_background_video_playback_enabled_) return true;
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations index 1e704f2d..d7600b5 100644 --- a/third_party/blink/web_tests/WebDriverExpectations +++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -77,12 +77,7 @@ crbug.com/1020018 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_sucess_input [ Failure ] crbug.com/1020018 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_sucess_input_non_interactable [ Failure ] -crbug.com/1167321 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/find.py>>test_no_browsing_context [ Failure ] -crbug.com/1167321 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/find.py>>test_find_elements[tag-name-a] [ Failure ] -crbug.com/1167321 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/find.py>>test_find_elements[xpath-//a] [ Failure ] -crbug.com/1167321 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/find.py>>test_no_browsing_context [ Failure ] -crbug.com/1167321 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/find.py>>test_find_element[tag-name-a] [ Failure ] -crbug.com/1167321 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/find.py>>test_find_element[xpath-//a] [ Failure ] +crbug.com/1167321 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/find.py [ Failure ] crbug.com/1240985 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ] crbug.com/1240985 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ] @@ -114,7 +109,29 @@ crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_cross_origin[capabilities0] [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/navigate.py>>test_link_cross_origin[capabilities0] [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/create_alwaysMatch.py>>test_valid[timeouts-value12] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_default[alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_default[prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/get.py>>test_no_top_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_default[confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/get.py>>test_element_not_found [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_shadow_root/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/get.py>>test_no_shadow_root [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/get.py>>test_get_shadow_root [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/get.py>>test_element_stale [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/get.py>>test_no_browsing_context [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_null [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_parent_frame/switch.py>>test_switch_from_iframe [ Failure ] @@ -291,3 +308,40 @@ crbug.com/1123907 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[4] [ Failure Pass ] crbug.com/1123907 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress [ Failure Pass ] crbug.com/1128104 [ Linux ] external/wpt/webdriver/tests/release_actions/sequence.py>>test_no_release_mouse_sequence_keeps_dblclick_state [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_default[alert-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_default[confirm-False] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_default[prompt-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ] +crbug.com/1168659 [ Linux ] external/wpt/webdriver/tests/get_element_shadow_root/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ] + +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_default[alert-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_default[confirm-False] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_default[prompt-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ] +crbug.com/1189610 [ Linux ] external/wpt/webdriver/tests/find_element_from_shadow_root/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
diff --git a/third_party/blink/web_tests/editing/input/password-echo-passnode-expected.txt b/third_party/blink/web_tests/editing/input/password-echo-passnode-expected.txt index c2f53df..e517912 100644 --- a/third_party/blink/web_tests/editing/input/password-echo-passnode-expected.txt +++ b/third_party/blink/web_tests/editing/input/password-echo-passnode-expected.txt
@@ -1,6 +1,6 @@ Tests if input chars are secured correctly -Success: secured right after. expected=true, actual=true +Success: secured right after. expected=false, actual=false Success: secured after delay. expected=true, actual=true -Success: secured right after. expected=true, actual=true +Success: secured right after. expected=false, actual=false Success: secured after delay. expected=true, actual=true
diff --git a/third_party/blink/web_tests/editing/input/password-echo-passnode.html b/third_party/blink/web_tests/editing/input/password-echo-passnode.html index 7f703040..c9141f4d 100644 --- a/third_party/blink/web_tests/editing/input/password-echo-passnode.html +++ b/third_party/blink/web_tests/editing/input/password-echo-passnode.html
@@ -3,8 +3,8 @@ <script language="javascript" type="text/javascript"> var mytests = [ //format: [preedit1, preedit2,...,commit_text], secured_right_after?, secured_after_delay? check? - [['a'], true, true, true], // test password (when only 1 char) is always secured(regular). - [['2','2','b'], true, true, true], // test password (when only 1 char) is always secured(ime). + [['a'], false, true, true], // test password (when only 1 char) is only secured after a delay(regular). + [['2','2','b'], false, true, true], // test password (when only 1 char) is only secured after a delay(ime). ]; </script> <body onload=init(mytests)>
diff --git a/third_party/blink/web_tests/editing/input/password-echo-passnode2-expected.txt b/third_party/blink/web_tests/editing/input/password-echo-passnode2-expected.txt index c2f53df..e517912 100644 --- a/third_party/blink/web_tests/editing/input/password-echo-passnode2-expected.txt +++ b/third_party/blink/web_tests/editing/input/password-echo-passnode2-expected.txt
@@ -1,6 +1,6 @@ Tests if input chars are secured correctly -Success: secured right after. expected=true, actual=true +Success: secured right after. expected=false, actual=false Success: secured after delay. expected=true, actual=true -Success: secured right after. expected=true, actual=true +Success: secured right after. expected=false, actual=false Success: secured after delay. expected=true, actual=true
diff --git a/third_party/blink/web_tests/editing/input/password-echo-passnode2.html b/third_party/blink/web_tests/editing/input/password-echo-passnode2.html index 5ed6d07a..d20a20b 100644 --- a/third_party/blink/web_tests/editing/input/password-echo-passnode2.html +++ b/third_party/blink/web_tests/editing/input/password-echo-passnode2.html
@@ -3,9 +3,9 @@ <script language="javascript" type="text/javascript"> var mytests = [ //format: [preedit1, preedit2,...,commit_text], secured_right_after?, secured_after_delay? check? - [['a'], true, true, false], - [['f'], true, true, true], // test password (when more than 1 char) is always secured(regular). - [['3','3','3','f'], true, true, true], // test password (when more than 1 char) is always secured(ime). + [['a'], false, true, false], + [['f'], false, true, true], // test password (when more than 1 char) is only secured after a delay(regular). + [['3','3','3','f'], false, true, true], // test password (when more than 1 char) is only secured after a delay(ime). ]; </script> <body onload=init(mytests)>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/navigate-event/event-constructor.html b/third_party/blink/web_tests/external/wpt/app-history/navigate-event/event-constructor.html index f580e77..7a8803fa 100644 --- a/third_party/blink/web_tests/external/wpt/app-history/navigate-event/event-constructor.html +++ b/third_party/blink/web_tests/external/wpt/app-history/navigate-event/event-constructor.html
@@ -4,6 +4,12 @@ <script> test(() => { assert_throws_js(TypeError, () => { + new AppHistoryNavigateEvent("navigate"); + }); +}, "can't bypass required members by omitting the dictionary entirely"); + +test(() => { + assert_throws_js(TypeError, () => { new AppHistoryNavigateEvent("navigate", { navigationType: "push", canTransition: false,
diff --git a/third_party/blink/web_tests/external/wpt/app-history/navigate-event/transitionWhile-on-synthetic-event.html b/third_party/blink/web_tests/external/wpt/app-history/navigate-event/transitionWhile-on-synthetic-event.html index d912e38..a3bb80f 100644 --- a/third_party/blink/web_tests/external/wpt/app-history/navigate-event/transitionWhile-on-synthetic-event.html +++ b/third_party/blink/web_tests/external/wpt/app-history/navigate-event/transitionWhile-on-synthetic-event.html
@@ -2,7 +2,16 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script> -test(() => { - assert_throws_dom("SecurityError", () => new AppHistoryNavigateEvent("navigate").transitionWhile(Promise.resolve())); +async_test(t => { + // We need to grab an AppHistoryDestination to construct the event. + appHistory.onnavigate = t.step_func_done(e => { + const event = new AppHistoryNavigateEvent("navigate", { + destination: e.destination, + signal: (new AbortController()).signal + }); + + assert_throws_dom("SecurityError", () => event.transitionWhile(Promise.resolve())); + }); + history.pushState(1, null, "#1"); }, "AppHistoryNavigateEvent's transitionWhile() throws if invoked on a synthetic event"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/navigate/disambigaute-goto-forward-multiple.html b/third_party/blink/web_tests/external/wpt/app-history/navigate/disambigaute-goto-forward-multiple.html index b1378b66..213b717 100644 --- a/third_party/blink/web_tests/external/wpt/app-history/navigate/disambigaute-goto-forward-multiple.html +++ b/third_party/blink/web_tests/external/wpt/app-history/navigate/disambigaute-goto-forward-multiple.html
@@ -3,41 +3,37 @@ <script src="/resources/testharnessreport.js"></script> <iframe id="i" src="/common/blank.html"></iframe> <script> -async_test(t => { +promise_test(async t => { // Wait for after the load event so that the navigation doesn't get converted // into a replace navigation. - window.onload = () => t.step_timeout(() => { - assert_equals(appHistory.entries().length, 1); - assert_equals(i.contentWindow.appHistory.entries().length, 1); - let initial_key = appHistory.current.key; - appHistory.navigate("#top1"); - appHistory.navigate("#top2"); - assert_equals(appHistory.entries().length, 3); - assert_equals(i.contentWindow.appHistory.entries().length, 1); - i.contentWindow.appHistory.navigate("#1"); - assert_equals(appHistory.entries().length, 3); - assert_equals(i.contentWindow.appHistory.entries().length, 2); - assert_equals(appHistory.current.index, 2); - assert_equals(i.contentWindow.appHistory.current.index, 1); - assert_true(appHistory.canGoBack); - assert_true(i.contentWindow.appHistory.canGoBack); - let final_key = appHistory.current.key; + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + assert_equals(appHistory.entries().length, 1); + assert_equals(i.contentWindow.appHistory.entries().length, 1); + let initial_key = appHistory.current.key; + await appHistory.navigate("#top1"); + await appHistory.navigate("#top2"); + assert_equals(appHistory.entries().length, 3); + assert_equals(i.contentWindow.appHistory.entries().length, 1); + await i.contentWindow.appHistory.navigate("#1"); + assert_equals(appHistory.entries().length, 3); + assert_equals(i.contentWindow.appHistory.entries().length, 2); + assert_equals(appHistory.current.index, 2); + assert_equals(i.contentWindow.appHistory.current.index, 1); + assert_true(appHistory.canGoBack); + assert_true(i.contentWindow.appHistory.canGoBack); + let final_key = appHistory.current.key; - i.contentWindow.appHistory.back().then(t.step_func(() => { - assert_equals(appHistory.current.index, 2); - assert_equals(i.contentWindow.appHistory.current.index, 0); - appHistory.goTo(initial_key).then(t.step_func(() => { - assert_equals(appHistory.current.index, 0); - assert_equals(i.contentWindow.appHistory.current.index, 0); - // There are 2 joint session history entries containing the top window's - // final key. Navigate to the nearest one (which navigates only the - // top window). - appHistory.goTo(final_key).then(t.step_func_done(() => { - assert_equals(appHistory.current.index, 2); - assert_equals(i.contentWindow.appHistory.current.index, 0); - })); - })); - })); - }, 0); + await i.contentWindow.appHistory.back(); + assert_equals(appHistory.current.index, 2); + assert_equals(i.contentWindow.appHistory.current.index, 0); + await appHistory.goTo(initial_key) + assert_equals(appHistory.current.index, 0); + assert_equals(i.contentWindow.appHistory.current.index, 0); + // There are 2 joint session history entries containing the top window's + // final key. Navigate to the nearest one (which navigates only the + // top window). + await appHistory.goTo(final_key); + assert_equals(appHistory.current.index, 2); + assert_equals(i.contentWindow.appHistory.current.index, 0); }, "appHistory.goTo() goes to the nearest entry when going forward"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-detach-in-onnavigate.html b/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-detach-in-onnavigate.html index 34bebca..c245da9 100644 --- a/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-detach-in-onnavigate.html +++ b/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-detach-in-onnavigate.html
@@ -7,7 +7,7 @@ await new Promise(resolve => window.onload = resolve); let iframe_constructor = i.contentWindow.DOMException; let i_win = i.contentWindow; - i.contentWindow.history.pushState(1, "", "#1"); + await i.contentWindow.appHistory.navigate("#1"); assert_equals(i.contentWindow.appHistory.entries().length, 2); let key = i.contentWindow.appHistory.entries()[0].key; @@ -15,6 +15,7 @@ let onnavigateerror_error; i.contentWindow.appHistory.onnavigate = t.step_func(() => i.remove()); i.contentWindow.appHistory.onnavigateerror = t.step_func(e => { + assert_false(onnavigateerror_called); onnavigateerror_called = true; onnavigateerror_error = e.error; assert_equals(e.filename, location.href);
diff --git a/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-multiple-steps.html b/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-multiple-steps.html index c827fef0..9b8c5ac9 100644 --- a/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-multiple-steps.html +++ b/third_party/blink/web_tests/external/wpt/app-history/navigate/goTo-multiple-steps.html
@@ -2,29 +2,24 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script> -async_test(t => { +promise_test(async t => { // Wait for after the load event so that the navigation doesn't get converted // into a replace navigation. - window.onload = () => t.step_timeout(() => { - assert_equals(appHistory.entries().length, 1); - let key0 = appHistory.current.key; - appHistory.navigate("#1"); - appHistory.navigate("#2"); - let key2 = appHistory.current.key; - assert_equals(appHistory.entries().length, 3); + await new Promise(resolve => window.onload = () => t.step_timeout(resolve, 0)); + assert_equals(appHistory.entries().length, 1); + let key0 = appHistory.current.key; + await appHistory.navigate("#1"); + await appHistory.navigate("#2"); + let key2 = appHistory.current.key; + assert_equals(appHistory.entries().length, 3); - appHistory.goTo(key0) - .then(t.step_func(() => { - assert_equals(appHistory.entries().length, 3); - assert_equals(appHistory.current, appHistory.entries()[0]); - assert_equals(key0, appHistory.current.key); - return appHistory.goTo(key2); - })) - .then(t.step_func_done(() => { - assert_equals(appHistory.entries().length, 3); - assert_equals(appHistory.current, appHistory.entries()[2]); - assert_equals(key2, appHistory.current.key); - })); - }, 0); + await appHistory.goTo(key0); + assert_equals(appHistory.entries().length, 3); + assert_equals(appHistory.current, appHistory.entries()[0]); + assert_equals(key0, appHistory.current.key); + await appHistory.goTo(key2); + assert_equals(appHistory.entries().length, 3); + assert_equals(appHistory.current, appHistory.entries()[2]); + assert_equals(key2, appHistory.current.key); }, "goto() can precisely traverse multiple steps in the joint session history"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/navigate/navigate-state-repeated-await.html b/third_party/blink/web_tests/external/wpt/app-history/navigate/navigate-state-repeated-await.html new file mode 100644 index 0000000..6b647492 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/navigate/navigate-state-repeated-await.html
@@ -0,0 +1,13 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + appHistory.onnavigate = e => e.transitionWhile(Promise.resolve()); + + await appHistory.navigate('/foo', {state: {foo: 1}}); + assert_equals(appHistory.current.getState().foo, 1); + await appHistory.navigate('/foo', {state: {foo: 2}}); + assert_equals(appHistory.current.getState().foo, 2); +}, "navigate() with state should work correctly when called repeatedly - with awaits"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/app-history/navigate/navigate-state-repeated.html b/third_party/blink/web_tests/external/wpt/app-history/navigate/navigate-state-repeated.html new file mode 100644 index 0000000..8d33860 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/app-history/navigate/navigate-state-repeated.html
@@ -0,0 +1,15 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +promise_test(async t => { + appHistory.onnavigate = e => e.transitionWhile(Promise.resolve()); + + let p1 = promise_rejects_dom(t, 'AbortError', appHistory.navigate('/foo', {state: {foo: 1}})); + assert_equals(appHistory.current.getState().foo, 1); + let p2 = appHistory.navigate('/foo', {state: {foo: 2}}); + assert_equals(appHistory.current.getState().foo, 2); + await p1; + await p2; +}, "navigate() with state should work correctly when called repeatedly"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/contain-paint-026.html b/third_party/blink/web_tests/external/wpt/css/css-contain/contain-paint-026.html new file mode 100644 index 0000000..f6da867 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/contain-paint-026.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Paint containment and box-shadow</title> +<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-paint"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<meta name=assert content="Paint containment should clip box-shadow effect on child."> +<style> +#contain-paint { + contain: paint; + width: 100px; + height: 100px; + background: red; +} + +#child { + background: green; + box-shadow: 0 0 100px 100px red; + width: 100px; + height: 100px; +} +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div id="contain-paint"> + <div id="child"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/auto-expand-details-element-fragment-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/auto-expand-details-element-fragment-expected.txt new file mode 100644 index 0000000..23533fd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/auto-expand-details-element-fragment-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL auto-expand-details-element-fragment assert_true: <details> should be opened by navigating to an element inside it. expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/auto-expand-details-element-fragment.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/auto-expand-details-element-fragment.html new file mode 100644 index 0000000..d3d04f0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-details-element/auto-expand-details-element-fragment.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org"> +<link rel="help" href="https://github.com/whatwg/html/pull/6466"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div style="height:2000px">spacer</div> + +<details id=details> + <div id=target>target</div> +</details> + +<script> +async_test(t => { + assert_false(details.hasAttribute('open'), + `The <details> should be closed at the start of the test.`); + assert_equals(window.pageYOffset, 0, + `The page should be scrolled to the top at the start of the test.`); + + window.location.hash = '#target'; + + requestAnimationFrame(t.step_func_done(() => { + assert_true(details.hasAttribute('open'), + `<details> should be opened by navigating to an element inside it.`); + assert_not_equals(window.pageYOffset, 0, + `The page should be scrolled down to the <details> element.`); + })); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/media-capabilities/decodingInfo.webrtc.html b/third_party/blink/web_tests/external/wpt/media-capabilities/decodingInfo.webrtc.html index d5399d7..f2839561 100644 --- a/third_party/blink/web_tests/external/wpt/media-capabilities/decodingInfo.webrtc.html +++ b/third_party/blink/web_tests/external/wpt/media-capabilities/decodingInfo.webrtc.html
@@ -6,7 +6,7 @@ // Minimal VideoConfiguration that will be allowed per spec. All optional // properties are missing. -var minimalVideoConfiguration = { +const minimalVideoConfiguration = { contentType: 'video/VP9; profile-level="0"', width: 800, height: 600, @@ -16,7 +16,7 @@ // Minimal AudioConfiguration that will be allowed per spec. All optional // properties are missing. -var minimalAudioConfiguration = { +const minimalAudioConfiguration = { contentType: 'audio/opus', }; @@ -149,11 +149,11 @@ }); }, "Test that decodingInfo returns supported, smooth, and powerEfficient set to false for non-webrtc audio content type."); -var validAudioCodecs = (() => { +const validAudioCodecs = (() => { // Some codecs that are returned by getCapabilities() are not real codecs, // exclude these from the test. - var excludeList = [ 'audio/CN', 'audio/telephone-event', 'audio/red' ]; - var audioCodecs = []; + const excludeList = [ 'audio/CN', 'audio/telephone-event', 'audio/red' ]; + const audioCodecs = []; RTCRtpReceiver.getCapabilities("audio")['codecs'].forEach(codec => { if (excludeList.indexOf(codec.mimeType) < 0 && audioCodecs.indexOf(codec.mimeType) < 0) { @@ -176,16 +176,16 @@ }, "Test that decodingInfo returns supported true for the codec " + codec + " returned by RTCRtpReceiver.getCapabilities()")} ); -var validVideoCodecs = (() => { +const validVideoCodecs = (() => { // Some codecs that are returned by getCapabilities() are not real codecs but // only used for error correction, exclude these from the test. - var excludeList = [ 'video/rtx', 'video/red', 'video/ulpfec', + const excludeList = [ 'video/rtx', 'video/red', 'video/ulpfec', 'video/flexfec-03' ]; - var videoCodecs = []; + const videoCodecs = []; RTCRtpReceiver.getCapabilities("video")['codecs'].forEach(codec => { if (excludeList.indexOf(codec.mimeType) < 0) { - var mimeType = codec.mimeType; + let mimeType = codec.mimeType; if ('sdpFmtpLine' in codec) { mimeType += "; " + codec.sdpFmtpLine; }
diff --git a/third_party/blink/web_tests/external/wpt/media-capabilities/encodingInfo.webrtc.html b/third_party/blink/web_tests/external/wpt/media-capabilities/encodingInfo.webrtc.html index 3f29919..414b794 100644 --- a/third_party/blink/web_tests/external/wpt/media-capabilities/encodingInfo.webrtc.html +++ b/third_party/blink/web_tests/external/wpt/media-capabilities/encodingInfo.webrtc.html
@@ -6,7 +6,7 @@ // Minimal VideoConfiguration that will be allowed per spec. All optional // properties are missing. -var minimalVideoConfiguration = { +const minimalVideoConfiguration = { contentType: 'video/VP9; profile-level="0"', width: 800, height: 600, @@ -16,7 +16,7 @@ // Minimal AudioConfiguration that will be allowed per spec. All optional // properties are missing. -var minimalAudioConfiguration = { +const minimalAudioConfiguration = { contentType: 'audio/opus', }; @@ -149,11 +149,11 @@ }); }, "Test that encodingInfo returns supported, smooth, and powerEfficient set to false for non-webrtc audio content type."); -var validAudioCodecs = (() => { +const validAudioCodecs = (() => { // Some codecs that are returned by getCapabilities() are not real codecs, // exclude these from the test. - var excludeList = [ 'audio/CN', 'audio/telephone-event', 'audio/red' ]; - var audioCodecs = []; + const excludeList = [ 'audio/CN', 'audio/telephone-event', 'audio/red' ]; + const audioCodecs = []; RTCRtpSender.getCapabilities("audio")['codecs'].forEach(codec => { if (excludeList.indexOf(codec.mimeType) < 0 && audioCodecs.indexOf(codec.mimeType) < 0) { @@ -176,16 +176,16 @@ }, "Test that encodingInfo returns supported true for the codec " + codec + " returned by RTCRtpSender.getCapabilities()")} ); -var validVideoCodecs = (() => { +const validVideoCodecs = (() => { // Some codecs that are returned by getCapabilities() are not real codecs but // only used for error correction, exclude these from the test. - var excludeList = [ 'video/rtx', 'video/red', 'video/ulpfec', + const excludeList = [ 'video/rtx', 'video/red', 'video/ulpfec', 'video/flexfec-03' ]; - var videoCodecs = []; + const videoCodecs = []; RTCRtpSender.getCapabilities("video")['codecs'].forEach(codec => { if (excludeList.indexOf(codec.mimeType) < 0) { - var mimeType = codec.mimeType; + let mimeType = codec.mimeType; if ('sdpFmtpLine' in codec) { mimeType += "; " + codec.sdpFmtpLine; }
diff --git a/third_party/blink/web_tests/external/wpt/presentation-api/controlling-ua/PresentationConnectionCloseEvent.https.html b/third_party/blink/web_tests/external/wpt/presentation-api/controlling-ua/PresentationConnectionCloseEvent.https.html new file mode 100644 index 0000000..34c935a6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/presentation-api/controlling-ua/PresentationConnectionCloseEvent.https.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Constructing a PresentationConnectionCloseEvent</title> +<link rel="author" title="mark a. foltz" href="https://github.com/mfoltzgoogle"> +<link rel="help" href="http://w3c.github.io/presentation-api/#controlling-user-agent"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + test(() => { + let eventWithMessage, eventWithoutMessage; + for (let reason of ["error", "closed", "wentaway"]) { + eventWithMessage = new PresentationConnectionCloseEvent("close", {reason: reason, message: "A message" }); + assert_equals(eventWithMessage.type, "close"); + assert_equals(eventWithMessage.reason, reason); + assert_equals(eventWithMessage.message, "A message"); + + eventWithoutMessage = new PresentationConnectionCloseEvent("close", {reason: reason}); + assert_equals(eventWithoutMessage.type, "close"); + assert_equals(eventWithoutMessage.reason, reason); + assert_equals(eventWithoutMessage.message, ""); + } + }); +</script>
diff --git a/third_party/blink/web_tests/fast/css/containment/paint-containment-with-box-shadow.html b/third_party/blink/web_tests/fast/css/containment/paint-containment-with-box-shadow.html deleted file mode 100644 index ffa0f31..0000000 --- a/third_party/blink/web_tests/fast/css/containment/paint-containment-with-box-shadow.html +++ /dev/null
@@ -1,16 +0,0 @@ -<!DOCTYPE html> -<style> -div { - width: 100px; - height: 100px; -} -#container { - contain: paint; -} -#child { - background-color: green; - -webkit-box-shadow: 0 0 100px 100px red; -} -</style> -<body> -<div id="container"><div id="child"></div></div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/css/webkit-text-security/first-letter-ref.html b/third_party/blink/web_tests/wpt_internal/css/webkit-text-security/first-letter-ref.html new file mode 100644 index 0000000..3cc2a849 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/webkit-text-security/first-letter-ref.html
@@ -0,0 +1,2 @@ +<!doctype html> +<div style="-webkit-text-security:circle">PASS</div>
diff --git a/third_party/blink/web_tests/wpt_internal/css/webkit-text-security/first-letter.html b/third_party/blink/web_tests/wpt_internal/css/webkit-text-security/first-letter.html new file mode 100644 index 0000000..ca18a2d --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/webkit-text-security/first-letter.html
@@ -0,0 +1,8 @@ +<!doctype html> +<title>Do not apply ::first-letter to -webkit-text-security</title> +<link rel="match" href="first-letter-ref.html"> +<style> + #obfuscated { -webkit-text-security: circle; } + #obfuscated::first-letter { font-size: 100px; } +</style> +<div id="obfuscated">PASS</div>
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js index 832952b..5ec8918 100644 --- a/third_party/closure_compiler/externs/automation.js +++ b/third_party/closure_compiler/externs/automation.js
@@ -1264,6 +1264,13 @@ chrome.automation.AutomationNode.prototype.hierarchicalLevel; /** + * An array of ints of the current caret bounds in screen coordinates. (x, y, width, height). + * @type {(!Array<number>|undefined)} + * @see https://developer.chrome.com/extensions/automation#type-caretBounds + */ +chrome.automation.AutomationNode.prototype.caretBounds; + +/** * The start and end index of each word in an inline text box. * @type {(!Array<number>|undefined)} * @see https://developer.chrome.com/extensions/automation#type-wordStarts
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 2eb00391..12fbeba 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-11-0-26-gf44c2d586 -Revision: f44c2d586064bcccdb504bf098b9dc78e660269e +Version: VER-2-11-0-27-ge2cceed85 +Revision: e2cceed857f0b4f3f3fd48681d2f3009e62d1194 CPEPrefix: cpe:/a:freetype:freetype:2.10.4 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/jinja2/OWNERS b/third_party/jinja2/OWNERS index 05a4a96..c4b81d8 100644 --- a/third_party/jinja2/OWNERS +++ b/third_party/jinja2/OWNERS
@@ -1,3 +1,4 @@ timloh@chromium.org haraken@chromium.org +wnwen@chromium.org yukishiino@chromium.org
diff --git a/third_party/jinja2/lexer.py b/third_party/jinja2/lexer.py index 6fd135d..1f79025 100644 --- a/third_party/jinja2/lexer.py +++ b/third_party/jinja2/lexer.py
@@ -45,12 +45,6 @@ from jinja2 import _identifier name_re = re.compile(r'[\w{0}]+'.format(_identifier.pattern)) check_ident = True - # remove the pattern from memory after building the regex - import sys - del sys.modules['jinja2._identifier'] - import jinja2 - del jinja2._identifier - del _identifier float_re = re.compile(r'(?<!\.)\d+\.\d+') newline_re = re.compile(r'(\r\n|\r|\n)')
diff --git a/third_party/jinja2/patches/0002-jinja2-add-_identifier-to-pydeps-for-py3.patch b/third_party/jinja2/patches/0002-jinja2-add-_identifier-to-pydeps-for-py3.patch new file mode 100644 index 0000000..a979bed7 --- /dev/null +++ b/third_party/jinja2/patches/0002-jinja2-add-_identifier-to-pydeps-for-py3.patch
@@ -0,0 +1,34 @@ +From c07882fb6ea8a02869c84fd79e48855229ca5985 Mon Sep 17 00:00:00 2001 +From: Peter Wen <wnwen@chromium.org> +Date: Wed, 18 Aug 2021 09:53:11 -0400 +Subject: [PATCH] [PATCH] jinja2: add _identifier to pydeps for py3 + +If _identifier is deleted then build/print_python_deps.py fails to +detect _identifier.py as a pydep for jinja, resulting in the isolate +files missing third_party/jinja2/_identifier.py as a necessary file. + +Bug: 1228231 +--- + third_party/jinja2/lexer.py | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/third_party/jinja2/lexer.py b/third_party/jinja2/lexer.py +index 6fd135dd5b0a..1f790259d671 100644 +--- a/third_party/jinja2/lexer.py ++++ b/third_party/jinja2/lexer.py +@@ -45,12 +45,6 @@ else: + from jinja2 import _identifier + name_re = re.compile(r'[\w{0}]+'.format(_identifier.pattern)) + check_ident = True +- # remove the pattern from memory after building the regex +- import sys +- del sys.modules['jinja2._identifier'] +- import jinja2 +- del jinja2._identifier +- del _identifier + + float_re = re.compile(r'(?<!\.)\d+\.\d+') + newline_re = re.compile(r'(\r\n|\r|\n)') +-- +2.33.0.rc1.237.g0d66db33f3-goog +
diff --git a/third_party/r8/3pp/3pp.pb b/third_party/r8/3pp/3pp.pb index ef9c4ba..b1962ba 100644 --- a/third_party/r8/3pp/3pp.pb +++ b/third_party/r8/3pp/3pp.pb
@@ -3,8 +3,13 @@ git { repo: "https://r8.googlesource.com/r8" tag_pattern: "%s-dev" + version_restriction { + op: EQ + val: "3.1.16" + } } patch_dir: "patches" + patch_version: "crbug1214915" } build {
diff --git a/third_party/r8/3pp/patches/0004-Disable-useDexPcAsDebugInformation.patch b/third_party/r8/3pp/patches/0004-Disable-useDexPcAsDebugInformation.patch deleted file mode 100644 index 0781a3e..0000000 --- a/third_party/r8/3pp/patches/0004-Disable-useDexPcAsDebugInformation.patch +++ /dev/null
@@ -1,28 +0,0 @@ -From ca66a211ce82c330257d9ca94dcca4c644cb4674 Mon Sep 17 00:00:00 2001 -From: Andrew Grieve <agrieve@chromium.org> -Date: Wed, 23 Jun 2021 21:53:35 -0400 -Subject: [PATCH 4/4] Disable useDexPcAsDebugInformation - -useDexPcAsDebugInformation breaks deobfuscation, but would be great to turn on. - -See crbug.com/1214915 for more information. ---- - src/main/java/com/android/tools/r8/utils/InternalOptions.java | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java -index e82e04d90..03bab9255 100644 ---- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java -+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java -@@ -1704,7 +1704,7 @@ public class InternalOptions implements GlobalKeepInfoConfiguration { - } - - public boolean canUseDexPcAsDebugInformation() { -- return lineNumberOptimization == LineNumberOptimization.ON && hasMinApi(AndroidApiLevel.O); -+ return false && lineNumberOptimization == LineNumberOptimization.ON && hasMinApi(AndroidApiLevel.O); - } - - public boolean isInterfaceMethodDesugaringEnabled() { --- -2.32.0.288.g62a8d224e6-goog -
diff --git a/third_party/r8/README.chromium b/third_party/r8/README.chromium index dc99df65..ee05f7e 100644 --- a/third_party/r8/README.chromium +++ b/third_party/r8/README.chromium
@@ -1,6 +1,6 @@ Name: R8 URL: https://r8.googlesource.com/r8 -Version: 3.1.13.alpha +Version: 3.1.16-dev License: BSD 3-Clause License File: NOT_SHIPPED Security Critical: no
diff --git a/tools/android/adb_reboot/adb_reboot.c b/tools/android/adb_reboot/adb_reboot.c index d414dd5..f382391c 100644 --- a/tools/android/adb_reboot/adb_reboot.c +++ b/tools/android/adb_reboot/adb_reboot.c
@@ -38,6 +38,4 @@ system("su -c reboot"); } } - - return 0; }
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py index 7da1896b..42184ca5 100644 --- a/tools/json_schema_compiler/cc_generator.py +++ b/tools/json_schema_compiler/cc_generator.py
@@ -854,24 +854,12 @@ def _GenerateFunctionParamsCreate(self, function): """Generate function to create an instance of Params. The generated - function takes a base::Value::ConstListView of arguments. A deprecated - function that takes a base::ListValue is also provided. + function takes a base::Value::ConstListView of arguments. E.g for function "Bar", generate Bar::Params::Create() """ c = Code() - # Temporary wrapper for base::ListValue - # TODO(crbug.com/1187001): Remove once all callers have been converted over. - (c.Append('// static') - .Sblock('std::unique_ptr<Params> Params::Create(%s) {' % - self._GenerateParams(['const base::ListValue& args'])) - .Append('return Params::Create(%s);' % - self._GenerateArgs(['args.GetList()'])) - .Eblock('}') - .Append() - ) - (c.Append('// static') .Sblock('std::unique_ptr<Params> Params::Create(%s) {' % self._GenerateParams([
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py index eff6471..97edbfe3 100644 --- a/tools/json_schema_compiler/h_generator.py +++ b/tools/json_schema_compiler/h_generator.py
@@ -344,10 +344,6 @@ .Append('static std::unique_ptr<Params> Create(%s);' % self._GenerateParams( ('const base::Value::ConstListView& args',))) - .Append() - .Append('// Deprecated') - .Append('static std::unique_ptr<Params> Create(%s);' % - self._GenerateParams(('const base::ListValue& args',))) .Append('Params(const Params&) = delete;') .Append('Params& operator=(const Params&) = delete;') .Append('~Params();')
diff --git a/tools/json_schema_compiler/test/additional_properties_unittest.cc b/tools/json_schema_compiler/test/additional_properties_unittest.cc index 94d3ded..15df873f 100644 --- a/tools/json_schema_compiler/test/additional_properties_unittest.cc +++ b/tools/json_schema_compiler/test/additional_properties_unittest.cc
@@ -40,10 +40,10 @@ auto param_object_value = std::make_unique<base::DictionaryValue>(); param_object_value->SetString("str", "a"); param_object_value->SetInteger("num", 1); - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(param_object_value->CreateDeepCopy()); + std::vector<base::Value> params_value; + params_value.push_back(param_object_value->Clone()); std::unique_ptr<ap::AdditionalProperties::Params> params( - ap::AdditionalProperties::Params::Create(*params_value)); + ap::AdditionalProperties::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_TRUE(params->param_object.additional_properties.Equals( param_object_value.get()));
diff --git a/tools/json_schema_compiler/test/any_unittest.cc b/tools/json_schema_compiler/test/any_unittest.cc index 668966b..169f7e55 100644 --- a/tools/json_schema_compiler/test/any_unittest.cc +++ b/tools/json_schema_compiler/test/any_unittest.cc
@@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> +#include <vector> + +#include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" #include "tools/json_schema_compiler/test/any.h" @@ -26,30 +30,30 @@ TEST(JsonSchemaCompilerAnyTest, OptionalAnyParamsCreate) { { - auto params_value = std::make_unique<base::ListValue>(); + std::vector<base::Value> params_value; std::unique_ptr<test::api::any::OptionalAny::Params> params( - test::api::any::OptionalAny::Params::Create(*params_value)); + test::api::any::OptionalAny::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_FALSE(params->any_name.get()); } { - auto params_value = std::make_unique<base::ListValue>(); - auto param = std::make_unique<base::Value>("asdf"); - params_value->Append(param->CreateDeepCopy()); + std::vector<base::Value> params_value; + base::Value param("asdf"); + params_value.push_back(param.Clone()); std::unique_ptr<test::api::any::OptionalAny::Params> params( - test::api::any::OptionalAny::Params::Create(*params_value)); + test::api::any::OptionalAny::Params::Create(params_value)); ASSERT_TRUE(params); ASSERT_TRUE(params->any_name); - EXPECT_TRUE(params->any_name->Equals(param.get())); + EXPECT_TRUE(params->any_name->Equals(¶m)); } { - auto params_value = std::make_unique<base::ListValue>(); - auto param = std::make_unique<base::Value>(true); - params_value->Append(param->CreateDeepCopy()); + std::vector<base::Value> params_value; + base::Value param(true); + params_value.push_back(param.Clone()); std::unique_ptr<test::api::any::OptionalAny::Params> params( - test::api::any::OptionalAny::Params::Create(*params_value)); + test::api::any::OptionalAny::Params::Create(params_value)); ASSERT_TRUE(params); ASSERT_TRUE(params->any_name); - EXPECT_TRUE(params->any_name->Equals(param.get())); + EXPECT_TRUE(params->any_name->Equals(¶m)); } }
diff --git a/tools/json_schema_compiler/test/arrays_unittest.cc b/tools/json_schema_compiler/test/arrays_unittest.cc index c063421b..fb357168 100644 --- a/tools/json_schema_compiler/test/arrays_unittest.cc +++ b/tools/json_schema_compiler/test/arrays_unittest.cc
@@ -194,8 +194,7 @@ integer_array.Append(8); params_value.Append(std::move(integer_array)); std::unique_ptr<arrays::IntegerArray::Params> params( - arrays::IntegerArray::Params::Create( - base::Value::AsListValue(params_value))); + arrays::IntegerArray::Params::Create(params_value.GetList())); EXPECT_TRUE(params.get()); ASSERT_EQ(3u, params->nums.size()); EXPECT_EQ(2, params->nums[0]); @@ -211,7 +210,7 @@ any_array.Append(CreateItemValue(2)); params_value.Append(std::move(any_array)); std::unique_ptr<arrays::AnyArray::Params> params( - arrays::AnyArray::Params::Create(base::Value::AsListValue(params_value))); + arrays::AnyArray::Params::Create(params_value.GetList())); EXPECT_TRUE(params.get()); ASSERT_EQ(3u, params->anys.size()); ASSERT_TRUE(params->anys[0]->is_int()); @@ -225,8 +224,7 @@ item_array.Append(CreateItemValue(2)); params_value.Append(std::move(item_array)); std::unique_ptr<arrays::ObjectArray::Params> params( - arrays::ObjectArray::Params::Create( - base::Value::AsListValue(params_value))); + arrays::ObjectArray::Params::Create(params_value.GetList())); EXPECT_TRUE(params.get()); ASSERT_EQ(2u, params->objects.size()); EXPECT_EQ(1, params->objects[0].additional_properties["val"]); @@ -240,7 +238,7 @@ item_array.Append(CreateItemValue(2)); params_value.Append(std::move(item_array)); std::unique_ptr<arrays::RefArray::Params> params( - arrays::RefArray::Params::Create(base::Value::AsListValue(params_value))); + arrays::RefArray::Params::Create(params_value.GetList())); EXPECT_TRUE(params.get()); ASSERT_EQ(2u, params->refs.size()); EXPECT_EQ(1, params->refs[0].val);
diff --git a/tools/json_schema_compiler/test/choices_unittest.cc b/tools/json_schema_compiler/test/choices_unittest.cc index a4772ef..4f95d23 100644 --- a/tools/json_schema_compiler/test/choices_unittest.cc +++ b/tools/json_schema_compiler/test/choices_unittest.cc
@@ -26,21 +26,22 @@ TEST(JsonSchemaCompilerChoicesTest, TakesIntegersParamsCreate) { { std::unique_ptr<TakesIntegers::Params> params(TakesIntegers::Params::Create( - *List(std::make_unique<base::Value>(true)))); + List(std::make_unique<base::Value>(true))->GetList())); EXPECT_FALSE(params); } { - std::unique_ptr<TakesIntegers::Params> params( - TakesIntegers::Params::Create(*List(std::make_unique<base::Value>(6)))); + std::unique_ptr<TakesIntegers::Params> params(TakesIntegers::Params::Create( + List(std::make_unique<base::Value>(6))->GetList())); ASSERT_TRUE(params); EXPECT_FALSE(params->nums.as_integers); EXPECT_EQ(6, *params->nums.as_integer); } { - std::unique_ptr<TakesIntegers::Params> params( - TakesIntegers::Params::Create(*List(List( - std::make_unique<base::Value>(2), std::make_unique<base::Value>(6), - std::make_unique<base::Value>(8))))); + std::unique_ptr<TakesIntegers::Params> params(TakesIntegers::Params::Create( + List(List(std::make_unique<base::Value>(2), + std::make_unique<base::Value>(6), + std::make_unique<base::Value>(8))) + ->GetList())); ASSERT_TRUE(params); ASSERT_TRUE(params->nums.as_integers); EXPECT_EQ(Vector(2, 6, 8), *params->nums.as_integers); @@ -50,8 +51,9 @@ TEST(JsonSchemaCompilerChoicesTest, ObjectWithChoicesParamsCreate) { { std::unique_ptr<choices::ObjectWithChoices::Params> params( - choices::ObjectWithChoices::Params::Create(*List( - Dictionary("strings", std::make_unique<base::Value>("asdf"))))); + choices::ObjectWithChoices::Params::Create( + List(Dictionary("strings", std::make_unique<base::Value>("asdf"))) + ->GetList())); ASSERT_TRUE(params); EXPECT_FALSE(params->string_info.strings.as_strings); EXPECT_EQ("asdf", *params->string_info.strings.as_string); @@ -60,8 +62,9 @@ { std::unique_ptr<choices::ObjectWithChoices::Params> params( choices::ObjectWithChoices::Params::Create( - *List(Dictionary("strings", std::make_unique<base::Value>("asdf"), - "integers", std::make_unique<base::Value>(6))))); + List(Dictionary("strings", std::make_unique<base::Value>("asdf"), + "integers", std::make_unique<base::Value>(6))) + ->GetList())); ASSERT_TRUE(params); EXPECT_FALSE(params->string_info.strings.as_strings); EXPECT_EQ("asdf", *params->string_info.strings.as_string); @@ -81,7 +84,7 @@ std::unique_ptr<base::ListValue> params_value(new base::ListValue()); params_value->Append(std::move(object_param)); std::unique_ptr<choices::ObjectWithChoices::Params> params( - choices::ObjectWithChoices::Params::Create(*params_value)); + choices::ObjectWithChoices::Params::Create(params_value->GetList())); EXPECT_FALSE(params.get()); } { @@ -91,7 +94,7 @@ std::unique_ptr<base::ListValue> params_value(new base::ListValue()); params_value->Append(std::move(object_param)); std::unique_ptr<choices::ObjectWithChoices::Params> params( - choices::ObjectWithChoices::Params::Create(*params_value)); + choices::ObjectWithChoices::Params::Create(params_value->GetList())); EXPECT_FALSE(params.get()); } { @@ -100,7 +103,7 @@ std::unique_ptr<base::ListValue> params_value(new base::ListValue()); params_value->Append(std::move(object_param)); std::unique_ptr<choices::ObjectWithChoices::Params> params( - choices::ObjectWithChoices::Params::Create(*params_value)); + choices::ObjectWithChoices::Params::Create(params_value->GetList())); EXPECT_FALSE(params.get()); } }
diff --git a/tools/json_schema_compiler/test/crossref_unittest.cc b/tools/json_schema_compiler/test/crossref_unittest.cc index e8df02e..96aaab4 100644 --- a/tools/json_schema_compiler/test/crossref_unittest.cc +++ b/tools/json_schema_compiler/test/crossref_unittest.cc
@@ -57,7 +57,7 @@ auto params_value = std::make_unique<base::ListValue>(); params_value->Append(CreateTestTypeValue()); std::unique_ptr<crossref::TestTypeOptionalParam::Params> params( - crossref::TestTypeOptionalParam::Params::Create(*params_value)); + crossref::TestTypeOptionalParam::Params::Create(params_value->GetList())); EXPECT_TRUE(params.get()); EXPECT_TRUE(params->test_type.get()); EXPECT_TRUE( @@ -71,7 +71,7 @@ test_type_value->RemoveKey("number"); params_value->Append(std::move(test_type_value)); std::unique_ptr<crossref::TestTypeOptionalParam::Params> params( - crossref::TestTypeOptionalParam::Params::Create(*params_value)); + crossref::TestTypeOptionalParam::Params::Create(params_value->GetList())); EXPECT_FALSE(params.get()); } @@ -95,7 +95,7 @@ param_object_value->SetBoolean("boolean", true); params_value->Append(std::move(param_object_value)); std::unique_ptr<crossref::TestTypeInObject::Params> params( - crossref::TestTypeInObject::Params::Create(*params_value)); + crossref::TestTypeInObject::Params::Create(params_value->GetList())); EXPECT_TRUE(params.get()); EXPECT_TRUE(params->param_object.test_type.get()); EXPECT_TRUE(params->param_object.boolean); @@ -108,7 +108,7 @@ param_object_value->SetBoolean("boolean", true); params_value->Append(std::move(param_object_value)); std::unique_ptr<crossref::TestTypeInObject::Params> params( - crossref::TestTypeInObject::Params::Create(*params_value)); + crossref::TestTypeInObject::Params::Create(params_value->GetList())); EXPECT_TRUE(params.get()); EXPECT_FALSE(params->param_object.test_type.get()); EXPECT_TRUE(params->param_object.boolean); @@ -120,7 +120,7 @@ param_object_value->SetBoolean("boolean", true); params_value->Append(std::move(param_object_value)); std::unique_ptr<crossref::TestTypeInObject::Params> params( - crossref::TestTypeInObject::Params::Create(*params_value)); + crossref::TestTypeInObject::Params::Create(params_value->GetList())); EXPECT_FALSE(params.get()); } { @@ -130,7 +130,7 @@ "testType", base::Value::FromUniquePtrValue(CreateTestTypeValue())); params_value->Append(std::move(param_object_value)); std::unique_ptr<crossref::TestTypeInObject::Params> params( - crossref::TestTypeInObject::Params::Create(*params_value)); + crossref::TestTypeInObject::Params::Create(params_value->GetList())); EXPECT_FALSE(params.get()); } }
diff --git a/tools/json_schema_compiler/test/enums_unittest.cc b/tools/json_schema_compiler/test/enums_unittest.cc index 5507b42..8a014ce4 100644 --- a/tools/json_schema_compiler/test/enums_unittest.cc +++ b/tools/json_schema_compiler/test/enums_unittest.cc
@@ -4,6 +4,8 @@ #include "tools/json_schema_compiler/test/enums.h" +#include <vector> + #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" #include "tools/json_schema_compiler/test/test_util.h" @@ -30,16 +32,16 @@ TEST(JsonSchemaCompilerEnumsTest, EnumsAsTypes) { { - base::ListValue args; - args.Append("one"); + std::vector<base::Value> args; + args.emplace_back("one"); std::unique_ptr<enums::TakesEnumAsType::Params> params( enums::TakesEnumAsType::Params::Create(args)); ASSERT_TRUE(params.get()); EXPECT_EQ(enums::ENUMERATION_ONE, params->enumeration); - EXPECT_EQ(args, base::Value(enums::ReturnsEnumAsType::Results::Create( - enums::ENUMERATION_ONE))); + EXPECT_EQ(args, enums::ReturnsEnumAsType::Results::Create( + enums::ENUMERATION_ONE)); } { enums::HasEnumeration enumeration; @@ -72,9 +74,10 @@ TEST(JsonSchemaCompilerEnumsTest, EnumsArrayAsType) { { - base::ListValue params_value; - params_value.Append(List(std::make_unique<base::Value>("one"), - std::make_unique<base::Value>("two"))); + std::vector<base::Value> params_value; + params_value.push_back(base::Value::FromUniquePtrValue( + List(std::make_unique<base::Value>("one"), + std::make_unique<base::Value>("two")))); std::unique_ptr<enums::TakesEnumArrayAsType::Params> params( enums::TakesEnumArrayAsType::Params::Create(params_value)); ASSERT_TRUE(params); @@ -83,8 +86,9 @@ EXPECT_EQ(enums::ENUMERATION_TWO, params->values[1]); } { - base::ListValue params_value; - params_value.Append(List(std::make_unique<base::Value>("invalid"))); + std::vector<base::Value> params_value; + params_value.push_back(base::Value::FromUniquePtrValue( + List(std::make_unique<base::Value>("invalid")))); std::unique_ptr<enums::TakesEnumArrayAsType::Params> params( enums::TakesEnumArrayAsType::Params::Create(params_value)); EXPECT_FALSE(params); @@ -144,16 +148,16 @@ TEST(JsonSchemaCompilerEnumsTest, TakesEnumParamsCreate) { { - base::ListValue params_value; - params_value.Append("two"); + std::vector<base::Value> params_value; + params_value.emplace_back("two"); std::unique_ptr<enums::TakesEnum::Params> params( enums::TakesEnum::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_EQ(enums::ENUMERATION_TWO, params->state); } { - base::ListValue params_value; - params_value.Append("invalid"); + std::vector<base::Value> params_value; + params_value.emplace_back("invalid"); std::unique_ptr<enums::TakesEnum::Params> params( enums::TakesEnum::Params::Create(params_value)); EXPECT_FALSE(params.get()); @@ -162,9 +166,10 @@ TEST(JsonSchemaCompilerEnumsTest, TakesEnumArrayParamsCreate) { { - base::ListValue params_value; - params_value.Append(List(std::make_unique<base::Value>("one"), - std::make_unique<base::Value>("two"))); + std::vector<base::Value> params_value; + params_value.push_back(base::Value::FromUniquePtrValue( + List(std::make_unique<base::Value>("one"), + std::make_unique<base::Value>("two")))); std::unique_ptr<enums::TakesEnumArray::Params> params( enums::TakesEnumArray::Params::Create(params_value)); ASSERT_TRUE(params); @@ -173,8 +178,9 @@ EXPECT_EQ(enums::ENUMERATION_TWO, params->values[1]); } { - base::ListValue params_value; - params_value.Append(List(std::make_unique<base::Value>("invalid"))); + std::vector<base::Value> params_value; + params_value.push_back(base::Value::FromUniquePtrValue( + List(std::make_unique<base::Value>("invalid")))); std::unique_ptr<enums::TakesEnumArray::Params> params( enums::TakesEnumArray::Params::Create(params_value)); EXPECT_FALSE(params); @@ -183,23 +189,23 @@ TEST(JsonSchemaCompilerEnumsTest, TakesOptionalEnumParamsCreate) { { - base::ListValue params_value; - params_value.Append("three"); + std::vector<base::Value> params_value; + params_value.emplace_back("three"); std::unique_ptr<enums::TakesOptionalEnum::Params> params( enums::TakesOptionalEnum::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_EQ(enums::ENUMERATION_THREE, params->state); } { - base::ListValue params_value; + std::vector<base::Value> params_value; std::unique_ptr<enums::TakesOptionalEnum::Params> params( enums::TakesOptionalEnum::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_EQ(enums::ENUMERATION_NONE, params->state); } { - base::ListValue params_value; - params_value.Append("invalid"); + std::vector<base::Value> params_value; + params_value.emplace_back("invalid"); std::unique_ptr<enums::TakesOptionalEnum::Params> params( enums::TakesOptionalEnum::Params::Create(params_value)); EXPECT_FALSE(params.get()); @@ -208,9 +214,9 @@ TEST(JsonSchemaCompilerEnumsTest, TakesMultipleOptionalEnumsParamsCreate) { { - base::ListValue params_value; - params_value.Append("one"); - params_value.Append("ham"); + std::vector<base::Value> params_value; + params_value.emplace_back("one"); + params_value.emplace_back("ham"); std::unique_ptr<enums::TakesMultipleOptionalEnums::Params> params( enums::TakesMultipleOptionalEnums::Params::Create(params_value)); EXPECT_TRUE(params.get()); @@ -218,8 +224,8 @@ EXPECT_EQ(enums::OTHER_ENUMERATION_HAM, params->type); } { - base::ListValue params_value; - params_value.Append("one"); + std::vector<base::Value> params_value; + params_value.emplace_back("one"); std::unique_ptr<enums::TakesMultipleOptionalEnums::Params> params( enums::TakesMultipleOptionalEnums::Params::Create(params_value)); EXPECT_TRUE(params.get()); @@ -227,7 +233,7 @@ EXPECT_EQ(enums::OTHER_ENUMERATION_NONE, params->type); } { - base::ListValue params_value; + std::vector<base::Value> params_value; std::unique_ptr<enums::TakesMultipleOptionalEnums::Params> params( enums::TakesMultipleOptionalEnums::Params::Create(params_value)); EXPECT_TRUE(params.get()); @@ -235,9 +241,9 @@ EXPECT_EQ(enums::OTHER_ENUMERATION_NONE, params->type); } { - base::ListValue params_value; - params_value.Append("three"); - params_value.Append("invalid"); + std::vector<base::Value> params_value; + params_value.emplace_back("three"); + params_value.emplace_back("invalid"); std::unique_ptr<enums::TakesMultipleOptionalEnums::Params> params( enums::TakesMultipleOptionalEnums::Params::Create(params_value)); EXPECT_FALSE(params.get());
diff --git a/tools/json_schema_compiler/test/error_generation_unittest.cc b/tools/json_schema_compiler/test/error_generation_unittest.cc index 41fd18d..cd5ffe9c 100644 --- a/tools/json_schema_compiler/test/error_generation_unittest.cc +++ b/tools/json_schema_compiler/test/error_generation_unittest.cc
@@ -5,6 +5,7 @@ #include "tools/json_schema_compiler/test/error_generation.h" #include <memory> +#include <vector> #include "base/json/json_writer.h" #include "base/logging.h" @@ -81,16 +82,17 @@ TEST(JsonSchemaCompilerErrorTest, TooManyParameters) { { - std::unique_ptr<base::ListValue> params_value = - List(std::make_unique<Value>(5)); + std::vector<Value> params_value; + params_value.emplace_back(5); std::u16string error; - EXPECT_TRUE(errors::TestFunction::Params::Create(*params_value, &error)); + EXPECT_TRUE(errors::TestFunction::Params::Create(params_value, &error)); } { - std::unique_ptr<base::ListValue> params_value = - List(std::make_unique<Value>(5), std::make_unique<Value>(5)); + std::vector<Value> params_value; + params_value.emplace_back(5); + params_value.emplace_back(5); std::u16string error; - EXPECT_FALSE(errors::TestFunction::Params::Create(*params_value, &error)); + EXPECT_FALSE(errors::TestFunction::Params::Create(params_value, &error)); EXPECT_TRUE(EqualsUtf16("expected 1 arguments, got 2", error)); } } @@ -99,16 +101,16 @@ TEST(JsonSchemaCompilerErrorTest, ParamIsRequired) { { - std::unique_ptr<base::ListValue> params_value = - List(std::make_unique<Value>(5)); + std::vector<Value> params_value; + params_value.emplace_back(5); std::u16string error; - EXPECT_TRUE(errors::TestFunction::Params::Create(*params_value, &error)); + EXPECT_TRUE(errors::TestFunction::Params::Create(params_value, &error)); } { - std::unique_ptr<base::ListValue> params_value = - List(std::make_unique<Value>()); + std::vector<Value> params_value; + params_value.emplace_back(); std::u16string error; - EXPECT_FALSE(errors::TestFunction::Params::Create(*params_value, &error)); + EXPECT_FALSE(errors::TestFunction::Params::Create(params_value, &error)); EXPECT_TRUE(EqualsUtf16("'num' is required", error)); } } @@ -132,16 +134,16 @@ TEST(JsonSchemaCompilerErrorTest, WrongParameterCreationType) { { std::u16string error; - std::unique_ptr<base::ListValue> params_value = - List(std::make_unique<Value>("Yeah!")); - EXPECT_TRUE(errors::TestString::Params::Create(*params_value, &error)); + std::vector<Value> params_value; + params_value.emplace_back("Yeah!"); + EXPECT_TRUE(errors::TestString::Params::Create(params_value, &error)); } { - std::unique_ptr<base::ListValue> params_value = - List(std::make_unique<Value>(5)); + std::vector<Value> params_value; + params_value.emplace_back(5); std::u16string error; EXPECT_FALSE( - errors::TestTypeInObject::Params::Create(*params_value, &error)); + errors::TestTypeInObject::Params::Create(params_value, &error)); EXPECT_TRUE(EqualsUtf16("'paramObject': expected dictionary, got integer", error)); }
diff --git a/tools/json_schema_compiler/test/functions_on_types_unittest.cc b/tools/json_schema_compiler/test/functions_on_types_unittest.cc index 321bc69..9029f19 100644 --- a/tools/json_schema_compiler/test/functions_on_types_unittest.cc +++ b/tools/json_schema_compiler/test/functions_on_types_unittest.cc
@@ -5,6 +5,7 @@ #include "tools/json_schema_compiler/test/functions_on_types.h" #include <utility> +#include <vector> #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,40 +14,40 @@ TEST(JsonSchemaCompilerFunctionsOnTypesTest, StorageAreaGetParamsCreate) { { - auto params_value = std::make_unique<base::ListValue>(); + std::vector<base::Value> params_value; std::unique_ptr<functions_on_types::StorageArea::Get::Params> params( - functions_on_types::StorageArea::Get::Params::Create(*params_value)); + functions_on_types::StorageArea::Get::Params::Create(params_value)); ASSERT_TRUE(params); EXPECT_FALSE(params->keys); } { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(9); + std::vector<base::Value> params_value; + params_value.emplace_back(9); std::unique_ptr<functions_on_types::StorageArea::Get::Params> params( - functions_on_types::StorageArea::Get::Params::Create(*params_value)); + functions_on_types::StorageArea::Get::Params::Create(params_value)); EXPECT_FALSE(params); } { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append("test"); + std::vector<base::Value> params_value; + params_value.emplace_back("test"); std::unique_ptr<functions_on_types::StorageArea::Get::Params> params( - functions_on_types::StorageArea::Get::Params::Create(*params_value)); + functions_on_types::StorageArea::Get::Params::Create(params_value)); ASSERT_TRUE(params); ASSERT_TRUE(params->keys); EXPECT_EQ("test", *params->keys->as_string); } { - auto keys_object_value = std::make_unique<base::DictionaryValue>(); - keys_object_value->SetInteger("integer", 5); - keys_object_value->SetString("string", "string"); - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(keys_object_value->CreateDeepCopy()); + base::Value keys_object_value(base::Value::Type::DICTIONARY); + keys_object_value.SetIntKey("integer", 5); + keys_object_value.SetStringKey("string", "string"); + std::vector<base::Value> params_value; + params_value.push_back(keys_object_value.Clone()); std::unique_ptr<functions_on_types::StorageArea::Get::Params> params( - functions_on_types::StorageArea::Get::Params::Create(*params_value)); + functions_on_types::StorageArea::Get::Params::Create(params_value)); ASSERT_TRUE(params); ASSERT_TRUE(params->keys); - EXPECT_TRUE(keys_object_value->Equals( - ¶ms->keys->as_object->additional_properties)); + EXPECT_EQ(keys_object_value, + params->keys->as_object->additional_properties); } } @@ -62,12 +63,12 @@ } TEST(JsonSchemaCompilerFunctionsOnTypesTest, ChromeSettingGetParamsCreate) { - auto details_value = std::make_unique<base::DictionaryValue>(); - details_value->SetBoolean("incognito", true); - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(std::move(details_value)); + base::Value details_value(base::Value::Type::DICTIONARY); + details_value.SetBoolKey("incognito", true); + std::vector<base::Value> params_value; + params_value.push_back(std::move(details_value)); std::unique_ptr<functions_on_types::ChromeSetting::Get::Params> params( - functions_on_types::ChromeSetting::Get::Params::Create(*params_value)); + functions_on_types::ChromeSetting::Get::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_TRUE(*params->details.incognito); }
diff --git a/tools/json_schema_compiler/test/idl_schemas_unittest.cc b/tools/json_schema_compiler/test/idl_schemas_unittest.cc index f58be79..5f5ecdfa 100644 --- a/tools/json_schema_compiler/test/idl_schemas_unittest.cc +++ b/tools/json_schema_compiler/test/idl_schemas_unittest.cc
@@ -4,6 +4,7 @@ #include <memory> #include <utility> +#include <vector> #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" @@ -39,22 +40,22 @@ EXPECT_EQ(a.y, b.y); // Test Function2, which takes an integer parameter. - base::ListValue list; - list.Append(5); + std::vector<base::Value> list; + list.emplace_back(5); std::unique_ptr<Function2::Params> f2_params = Function2::Params::Create(list); EXPECT_EQ(5, f2_params->x); // Test Function3, which takes a MyType1 parameter. - list.ClearList(); - std::unique_ptr<base::DictionaryValue> tmp(new base::DictionaryValue()); - tmp->SetInteger("x", 17); - tmp->SetString("y", "hello"); - tmp->SetString("z", "zstring"); - tmp->SetString("a", "astring"); - tmp->SetString("b", "bstring"); - tmp->SetString("c", "cstring"); - list.Append(std::move(tmp)); + list.clear(); + base::DictionaryValue tmp; + tmp.SetInteger("x", 17); + tmp.SetString("y", "hello"); + tmp.SetString("z", "zstring"); + tmp.SetString("a", "astring"); + tmp.SetString("b", "bstring"); + tmp.SetString("c", "cstring"); + list.emplace_back(std::move(tmp)); std::unique_ptr<Function3::Params> f3_params = Function3::Params::Create(list); EXPECT_EQ(17, f3_params->arg.x); @@ -62,20 +63,18 @@ // Test functions that take a callback function as a parameter, with varying // callback signatures. - base::Value f4_results(Function4::Results::Create()); - base::ListValue expected; + std::vector<base::Value> f4_results(Function4::Results::Create()); + std::vector<base::Value> expected; EXPECT_EQ(expected, f4_results); - base::Value f5_results(Function5::Results::Create(13)); - ASSERT_TRUE(f5_results.is_list()); - ASSERT_EQ(1u, f5_results.GetList().size()); - EXPECT_TRUE(f5_results.GetList()[0].is_int()); + std::vector<base::Value> f5_results(Function5::Results::Create(13)); + ASSERT_EQ(1u, f5_results.size()); + EXPECT_TRUE(f5_results[0].is_int()); - base::Value f6_results(Function6::Results::Create(a)); - ASSERT_TRUE(f6_results.is_list()); - ASSERT_EQ(1u, f6_results.GetList().size()); + std::vector<base::Value> f6_results(Function6::Results::Create(a)); + ASSERT_EQ(1u, f6_results.size()); MyType1 c; - EXPECT_TRUE(MyType1::Populate(f6_results.GetList()[0], &c)); + EXPECT_TRUE(MyType1::Populate(f6_results[0], &c)); EXPECT_EQ(a.x, c.x); EXPECT_EQ(a.y, c.y); } @@ -83,41 +82,41 @@ TEST(IdlCompiler, OptionalArguments) { // Test a function that takes one optional argument, both without and with // that argument. - base::ListValue list; + std::vector<base::Value> list; std::unique_ptr<Function7::Params> f7_params = Function7::Params::Create(list); EXPECT_EQ(nullptr, f7_params->arg.get()); - list.Append(7); + list.emplace_back(7); f7_params = Function7::Params::Create(list); EXPECT_EQ(7, *(f7_params->arg)); // Similar to above, but a function with one required and one optional // argument. - list.ClearList(); - list.Append(8); + list.clear(); + list.emplace_back(8); std::unique_ptr<Function8::Params> f8_params = Function8::Params::Create(list); EXPECT_EQ(8, f8_params->arg1); EXPECT_EQ(nullptr, f8_params->arg2.get()); - list.Append("foo"); + list.emplace_back("foo"); f8_params = Function8::Params::Create(list); EXPECT_EQ(8, f8_params->arg1); EXPECT_EQ("foo", *(f8_params->arg2)); // Test a function with an optional argument of custom type. - list.ClearList(); + list.clear(); std::unique_ptr<Function9::Params> f9_params = Function9::Params::Create(list); EXPECT_EQ(nullptr, f9_params->arg.get()); - list.ClearList(); - std::unique_ptr<base::DictionaryValue> tmp(new base::DictionaryValue()); - tmp->SetInteger("x", 17); - tmp->SetString("y", "hello"); - tmp->SetString("z", "zstring"); - tmp->SetString("a", "astring"); - tmp->SetString("b", "bstring"); - tmp->SetString("c", "cstring"); - list.Append(std::move(tmp)); + list.clear(); + base::DictionaryValue tmp; + tmp.SetInteger("x", 17); + tmp.SetString("y", "hello"); + tmp.SetString("z", "zstring"); + tmp.SetString("a", "astring"); + tmp.SetString("b", "bstring"); + tmp.SetString("c", "cstring"); + list.emplace_back(std::move(tmp)); f9_params = Function9::Params::Create(list); ASSERT_TRUE(f9_params->arg.get() != nullptr); MyType1* t1 = f9_params->arg.get(); @@ -128,9 +127,9 @@ TEST(IdlCompiler, ArrayTypes) { // Tests of a function that takes an integer and an array of integers. First // use an empty array. - base::ListValue list; - list.Append(33); - list.Append(std::make_unique<base::ListValue>()); + std::vector<base::Value> list; + list.emplace_back(33); + list.emplace_back(std::vector<base::Value>()); std::unique_ptr<Function10::Params> f10_params = Function10::Params::Create(list); ASSERT_TRUE(f10_params != nullptr); @@ -138,12 +137,12 @@ EXPECT_TRUE(f10_params->y.empty()); // Same function, but this time with 2 values in the array. - list.ClearList(); - list.Append(33); - std::unique_ptr<base::ListValue> sublist(new base::ListValue); - sublist->Append(34); - sublist->Append(35); - list.Append(std::move(sublist)); + list.clear(); + list.emplace_back(33); + std::vector<base::Value> sublist; + sublist.emplace_back(34); + sublist.emplace_back(35); + list.emplace_back(std::move(sublist)); f10_params = Function10::Params::Create(list); ASSERT_TRUE(f10_params != nullptr); EXPECT_EQ(33, f10_params->x); @@ -152,17 +151,17 @@ EXPECT_EQ(35, f10_params->y[1]); // Now test a function which takes an array of a defined type. - list.ClearList(); + list.clear(); MyType1 a; MyType1 b; a.x = 5; b.x = 6; a.y = std::string("foo"); b.y = std::string("bar"); - std::unique_ptr<base::ListValue> sublist2(new base::ListValue); - sublist2->Append(a.ToValue()); - sublist2->Append(b.ToValue()); - list.Append(std::move(sublist2)); + std::vector<base::Value> sublist2; + sublist2.push_back(base::Value::FromUniquePtrValue(a.ToValue())); + sublist2.push_back(base::Value::FromUniquePtrValue(b.ToValue())); + list.emplace_back(std::move(sublist2)); std::unique_ptr<Function11::Params> f11_params = Function11::Params::Create(list); ASSERT_TRUE(f11_params != nullptr); @@ -192,14 +191,12 @@ EXPECT_EQ(7, b2.x->GetInt()); // Test the params to the ObjectFunction1 function. - std::unique_ptr<base::DictionaryValue> icon_props( - new base::DictionaryValue()); - icon_props->SetString("hello", "world"); + base::DictionaryValue icon_props; + icon_props.SetString("hello", "world"); ObjectFunction1::Params::Icon icon; - EXPECT_TRUE(ObjectFunction1::Params::Icon::Populate(*(icon_props.get()), - &icon)); - base::ListValue list; - list.Append(std::move(icon_props)); + EXPECT_TRUE(ObjectFunction1::Params::Icon::Populate(icon_props, &icon)); + std::vector<base::Value> list; + list.push_back(std::move(icon_props)); std::unique_ptr<ObjectFunction1::Params> params = ObjectFunction1::Params::Create(list); ASSERT_TRUE(params.get() != nullptr);
diff --git a/tools/json_schema_compiler/test/objects_unittest.cc b/tools/json_schema_compiler/test/objects_unittest.cc index f6f4b9c..cbd332a 100644 --- a/tools/json_schema_compiler/test/objects_unittest.cc +++ b/tools/json_schema_compiler/test/objects_unittest.cc
@@ -8,6 +8,7 @@ #include <memory> #include <utility> +#include <vector> #include "base/json/json_writer.h" #include "base/values.h" @@ -27,11 +28,10 @@ info_value.SetIntPath("integer", 5); info_value.SetBoolPath("boolean", true); - base::Value params_value(base::Value::Type::LIST); - params_value.Append(std::move(info_value)); + std::vector<base::Value> params_value; + params_value.push_back(std::move(info_value)); std::unique_ptr<test::api::objects::ObjectParam::Params> params( - test::api::objects::ObjectParam::Params::Create( - base::Value::AsListValue(params_value))); + test::api::objects::ObjectParam::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_EQ((size_t) 2, params->info.strings.size()); EXPECT_EQ("one", params->info.strings[0]); @@ -47,11 +47,10 @@ info_value.SetKey("strings", std::move(strings)); info_value.SetIntPath("integer", 5); - base::Value params_value(base::Value::Type::LIST); - params_value.Append(std::move(info_value)); + std::vector<base::Value> params_value; + params_value.push_back(std::move(info_value)); std::unique_ptr<test::api::objects::ObjectParam::Params> params( - test::api::objects::ObjectParam::Params::Create( - base::Value::AsListValue(params_value))); + test::api::objects::ObjectParam::Params::Create(params_value)); EXPECT_FALSE(params.get()); } }
diff --git a/tools/json_schema_compiler/test/simple_api_unittest.cc b/tools/json_schema_compiler/test/simple_api_unittest.cc index 44cea060..41212b4 100644 --- a/tools/json_schema_compiler/test/simple_api_unittest.cc +++ b/tools/json_schema_compiler/test/simple_api_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> #include <string> +#include <vector> #include "base/json/json_reader.h" #include "base/logging.h" @@ -66,44 +67,44 @@ } TEST(JsonSchemaCompilerSimpleTest, IncrementIntegerParamsCreate) { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(6); + std::vector<base::Value> params_value; + params_value.emplace_back(6); std::unique_ptr<simple_api::IncrementInteger::Params> params( - simple_api::IncrementInteger::Params::Create(*params_value)); + simple_api::IncrementInteger::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_EQ(6, params->num); } TEST(JsonSchemaCompilerSimpleTest, NumberOfParams) { { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append("text"); - params_value->Append("text"); + std::vector<base::Value> params_value; + params_value.emplace_back("text"); + params_value.emplace_back("text"); std::unique_ptr<simple_api::OptionalString::Params> params( - simple_api::OptionalString::Params::Create(*params_value)); + simple_api::OptionalString::Params::Create(params_value)); EXPECT_FALSE(params.get()); } { - auto params_value = std::make_unique<base::ListValue>(); + std::vector<base::Value> params_value; std::unique_ptr<simple_api::IncrementInteger::Params> params( - simple_api::IncrementInteger::Params::Create(*params_value)); + simple_api::IncrementInteger::Params::Create(params_value)); EXPECT_FALSE(params.get()); } } TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsCreate) { { - auto params_value = std::make_unique<base::ListValue>(); + std::vector<base::Value> params_value; std::unique_ptr<simple_api::OptionalString::Params> params( - simple_api::OptionalString::Params::Create(*params_value)); + simple_api::OptionalString::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_FALSE(params->str.get()); } { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append("asdf"); + std::vector<base::Value> params_value; + params_value.emplace_back("asdf"); std::unique_ptr<simple_api::OptionalString::Params> params( - simple_api::OptionalString::Params::Create(*params_value)); + simple_api::OptionalString::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_TRUE(params->str.get()); EXPECT_EQ("asdf", *params->str); @@ -112,10 +113,10 @@ TEST(JsonSchemaCompilerSimpleTest, OptionalParamsTakingNull) { { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(std::make_unique<base::Value>()); + std::vector<base::Value> params_value; + params_value.emplace_back(); std::unique_ptr<simple_api::OptionalString::Params> params( - simple_api::OptionalString::Params::Create(*params_value)); + simple_api::OptionalString::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_FALSE(params->str.get()); } @@ -123,21 +124,21 @@ TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsWrongType) { { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(5); + std::vector<base::Value> params_value; + params_value.emplace_back(5); std::unique_ptr<simple_api::OptionalString::Params> params( - simple_api::OptionalString::Params::Create(*params_value)); + simple_api::OptionalString::Params::Create(params_value)); EXPECT_FALSE(params.get()); } } TEST(JsonSchemaCompilerSimpleTest, OptionalBeforeRequired) { { - auto params_value = std::make_unique<base::ListValue>(); - params_value->Append(std::make_unique<base::Value>()); - params_value->Append("asdf"); + std::vector<base::Value> params_value; + params_value.emplace_back(); + params_value.emplace_back("asdf"); std::unique_ptr<simple_api::OptionalBeforeRequired::Params> params( - simple_api::OptionalBeforeRequired::Params::Create(*params_value)); + simple_api::OptionalBeforeRequired::Params::Create(params_value)); EXPECT_TRUE(params.get()); EXPECT_FALSE(params->first.get()); EXPECT_EQ("asdf", params->second);
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index cd44693d..ec9eb246 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -738,6 +738,7 @@ 'mac-autofill-captured-sites-rel': 'release_bot', 'win-autofill-captured-sites-rel': 'release_bot', 'win-celab-rel': 'official_celab_release_bot', + 'win-chrome-finch-fyi': 'official_goma', 'win-password-manager-captured-sites-rel': 'release_bot', }, @@ -913,6 +914,7 @@ 'win-celab-try-rel': 'official_celab_release_bot', 'win-chrome': 'official_goma_x86', 'win-chrome-beta': 'official_goma_x86', + 'win-chrome-finch-fyi': 'official_goma', 'win-chrome-stable': 'official_goma_x86', 'win64-chrome': 'official_goma_x64', 'win64-chrome-beta': 'official_goma_x64',
diff --git a/tools/mb/mb_config_expectations/internal.chrome.fyi.json b/tools/mb/mb_config_expectations/internal.chrome.fyi.json index 847079e..d0953a5 100644 --- a/tools/mb/mb_config_expectations/internal.chrome.fyi.json +++ b/tools/mb/mb_config_expectations/internal.chrome.fyi.json
@@ -75,6 +75,13 @@ "use_goma": true } }, + "win-chrome-finch-fyi": { + "gn_args": { + "is_chrome_branded": true, + "is_official_build": true, + "use_goma": true + } + }, "win-password-manager-captured-sites-rel": { "gn_args": { "dcheck_always_on": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chrome.json b/tools/mb/mb_config_expectations/tryserver.chrome.json index 382514cd..4896e35 100644 --- a/tools/mb/mb_config_expectations/tryserver.chrome.json +++ b/tools/mb/mb_config_expectations/tryserver.chrome.json
@@ -252,6 +252,13 @@ "use_goma": true } }, + "win-chrome-finch-fyi": { + "gn_args": { + "is_chrome_branded": true, + "is_official_build": true, + "use_goma": true + } + }, "win-chrome-stable": { "gn_args": { "is_chrome_branded": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index ab21932..12eb5b1e 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2528,7 +2528,8 @@ <enum name="AndroidWebViewSafeModeResult"> <int value="0" label="Success"/> - <int value="1" label="Unknown error"/> + <int value="1" label="Unknown error (Java Exception)"/> + <int value="2" label="At least one action indiciates failure"/> </enum> <enum name="AndroidWebViewSingleOrMultiProcess"> @@ -14650,6 +14651,18 @@ <int value="2" label="External non-200 HTTP error"/> </enum> +<enum name="ConversionStorageCreateReportStatus"> + <int value="0" label="Success"/> + <int value="1" label="Success, but dropped lower-priority report"/> + <int value="2" label="Internal error"/> + <int value="3" label="No capacity for conversion destination"/> + <int value="4" label="No matching impressions"/> + <int value="5" label="Deduplicated against existing report"/> + <int value="6" label="Rate-limited"/> + <int value="7" label="Priority lower than existing reports"/> + <int value="8" label="Dropped for noise"/> +</enum> + <enum name="ConversionStorageSqlInitStatus"> <int value="0" label="Success"/> <int value="1" label="Failed to open DB in memory"/> @@ -34191,6 +34204,7 @@ <int value="3981" label="V8NavigatorManagedData_GetAnnotatedLocation_Method"/> <int value="3982" label="UserDataFieldFilledPreviously"/> <int value="3983" label="TableCollapsedBorderDifferentToVisual"/> + <int value="3984" label="HighlightAPIRegisterHighlight"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -48435,6 +48449,8 @@ <int value="-832561975" label="enable-picture-in-picture"/> <int value="-831066457" label="IncognitoBrandConsistencyForDesktop:disabled"/> <int value="-825942229" label="tab-management-experiment-type-elderberry"/> + <int value="-825747847" + label="AutofillEnableSupportForMoreStructureInAddresses:enabled"/> <int value="-824199802" label="ContextualSearchSimplifiedServer:enabled"/> <int value="-823394398" label="TargetEmbeddingLookalikes:enabled"/> <int value="-823165021" label="MaterialDesignUserMenu:enabled"/> @@ -48604,6 +48620,8 @@ <int value="-695687521" label="double-buffer-compositing"/> <int value="-694622753" label="VizHitTest:disabled"/> <int value="-694187898" label="MashOopViz:disabled"/> + <int value="-693881124" + label="AutofillEnableSupportForMoreStructureInNames:disabled"/> <int value="-688003116" label="FocusFollowsCursor:enabled"/> <int value="-687302378" label="BluetoothFixA2dpPacketSize:enabled"/> <int value="-686788480" label="OsSettingsAppNotificationsPage:enabled"/> @@ -49104,6 +49122,7 @@ <int value="-270261701" label="WebRtcEnableCaptureMultiChannelApm:disabled"/> <int value="-269440655" label="AutofillDownstreamCvcPromptUseGooglePayLogo:disabled"/> + <int value="-269227049" label="PersistentQuotaIsTemporaryQuota:enabled"/> <int value="-268897347" label="DisableCameraFrameRotationAtSource:disabled"/> <int value="-268549184" label="AutofillSaveCreditCardUsesStrikeSystemV2:enabled"/> @@ -49714,6 +49733,7 @@ <int value="246106068" label="HandwritingLegacyRecognition:disabled"/> <int value="247200195" label="EnhancedProtectionPromoCard:enabled"/> <int value="250855010" label="WebAssemblyBaseline:disabled"/> + <int value="251367892" label="PersistentQuotaIsTemporaryQuota:disabled"/> <int value="254497185" label="VideoPlayerJsModules:enabled"/> <int value="255375615" label="stop-non-timers-in-background:enabled"/> <int value="258621334" @@ -50741,6 +50761,8 @@ <int value="1070449228" label="ContextualSuggestionsCarousel:enabled"/> <int value="1070840417" label="ChromeColors:enabled"/> <int value="1071520357" label="WebAuthenticationTouchId:enabled"/> + <int value="1071962531" + label="AutofillEnableSupportForMoreStructureInAddresses:disabled"/> <int value="1072010558" label="NTPModernLayout:disabled"/> <int value="1072517479" label="ImprovedCookieControls:enabled"/> <int value="1074359194" label="UseSuggestionsEvenIfFew:enabled"/> @@ -51215,6 +51237,7 @@ <int value="1434515920" label="ReaderModeInCCT:enabled"/> <int value="1435251818" label="AutofillNoLocalSaveOnUploadSuccess:enabled"/> <int value="1436454450" label="InterestFeedV2:disabled"/> + <int value="1436693426" label="document-transition-slowdown-factor"/> <int value="1437413720" label="CooperativeScheduling:disabled"/> <int value="1438417722" label="MessagesForAndroidReaderMode:enabled"/> <int value="1440618113" label="EnableNetworkingInDiagnosticsApp:disabled"/> @@ -51545,6 +51568,8 @@ <int value="1707873180" label="OmniboxOnFocusSuggestionsContextualWebAllowSRP:disabled"/> <int value="1708118086" label="TextFragmentAnchor:disabled"/> + <int value="1710630380" + label="AutofillEnableSupportForMoreStructureInNames:enabled"/> <int value="1711286384" label="ContextMenuCopyImage:disabled"/> <int value="1712622545" label="Memories:disabled"/> <int value="1712697097" label="QuickAnswersV2:disabled"/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index c03c950..86c4dc67 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -198,7 +198,10 @@ </histogram> <histogram name="Android.AppNotificationStatus" enum="NotificationAppStatus" - expires_after="2020-11-15"> + expires_after="never"> +<!-- expires-never: Indicates whether Chrome has notification permission. --> + + <owner>dtrainor@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> Records whether notifications are enabled for Chrome, as the Android app,
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml index 6bc1ae6..1cbdde6 100644 --- a/tools/metrics/histograms/metadata/chromeos/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1122,10 +1122,10 @@ </histogram> <histogram name="ChromeOS.Settings.Device.KeyboardFunctionKeys" - enum="BooleanToggled" expires_after="2021-09-30"> - <owner>khorimoto@chromium.org</owner> - <owner>hsuregan@chromium.org</owner> - <owner>cros-customization@google.com</owner> + enum="BooleanToggled" expires_after="2022-03-15"> + <owner>jimmyxgong@chromium.org</owner> + <owner>zentaro@chromium.org</owner> + <owner>cros-peripherals@google.com</owner> <summary> Records when a user changes the kKeyboardFunctionKeys setting on the Device page. @@ -1321,7 +1321,7 @@ </histogram> <histogram name="ChromeOS.Settings.People.AddAccountCount" units="accounts" - expires_after="2021-09-30"> + expires_after="2022-03-15"> <owner>khorimoto@chromium.org</owner> <owner>hsuregan@chromium.org</owner> <owner>cros-customization@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/holding_space/histograms.xml b/tools/metrics/histograms/metadata/holding_space/histograms.xml index 218dd335..9fac9e1 100644 --- a/tools/metrics/histograms/metadata/holding_space/histograms.xml +++ b/tools/metrics/histograms/metadata/holding_space/histograms.xml
@@ -67,7 +67,7 @@ </histogram> <histogram name="HoldingSpace.Animation.PodResize.Smoothness" units="%" - expires_after="2021-09-24"> + expires_after="2022-01-30"> <owner>dmblack@google.com</owner> <owner>gzadina@google.com</owner> <summary> @@ -109,7 +109,7 @@ </histogram> <histogram name="HoldingSpace.Item.Action.{action}" enum="HoldingSpaceItemType" - expires_after="2021-09-24"> + expires_after="2022-01-30"> <owner>dmblack@google.com</owner> <owner>gzadina@google.com</owner> <summary> @@ -120,7 +120,7 @@ </histogram> <histogram name="HoldingSpace.Item.Action.{action}.Extension" - enum="HoldingSpaceExtension" expires_after="2021-09-24"> + enum="HoldingSpaceExtension" expires_after="2022-01-30"> <owner>dmblack@google.com</owner> <owner>gzadina@google.com</owner> <summary> @@ -131,7 +131,7 @@ </histogram> <histogram name="HoldingSpace.Item.Count.{type}" units="items" - expires_after="2021-09-24"> + expires_after="2022-01-30"> <owner>dmblack@google.com</owner> <owner>gzadina@google.com</owner> <summary> @@ -142,7 +142,7 @@ </histogram> <histogram name="HoldingSpace.Item.FailureToLaunch" enum="HoldingSpaceItemType" - expires_after="2021-09-24"> + expires_after="2022-01-30"> <owner>dmblack@google.com</owner> <owner>gzadina@google.com</owner> <summary> @@ -152,7 +152,7 @@ </histogram> <histogram name="HoldingSpace.Item.FailureToLaunch.Extension" - enum="HoldingSpaceExtension" expires_after="2021-09-24"> + enum="HoldingSpaceExtension" expires_after="2022-01-30"> <owner>dmblack@google.com</owner> <owner>gzadina@google.com</owner> <summary> @@ -172,7 +172,7 @@ </histogram> <histogram name="HoldingSpace.TimeFromFirstAvailabilityToFirstAdd" units="ms" - expires_after="2021-09-24"> + expires_after="2022-01-30"> <owner>dmblack@google.com</owner> <owner>gzadina@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 44457f6..db453125 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -3703,6 +3703,18 @@ </summary> </histogram> +<histogram name="Conversions.CreateReportStatus" + enum="ConversionStorageCreateReportStatus" expires_after="M98"> + <owner>apaseltiner@chromium.org</owner> + <owner>johnidel@chromium.org</owner> + <owner>measurement-api-dev+metrics@google.com</owner> + <summary> + Measures how often conversions are stored successfully or rejected and why. + Recorded once for each conversion event processed by the attribution storage + layer. + </summary> +</histogram> + <histogram name="Conversions.ExtraReportDelay" units="ms" expires_after="2021-12-19"> <obsolete>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml index 61e7bf54..89964fa 100644 --- a/tools/metrics/histograms/metadata/stability/histograms.xml +++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -228,7 +228,7 @@ </histogram> <histogram name="Stability.ChildFrameCrash.ShownAfterCrashingReason" - enum="ShownAfterCrashingReason" expires_after="2021-12-05"> + enum="ShownAfterCrashingReason" expires_after="2022-08-18"> <owner>alexmos@chromium.org</owner> <owner>boliu@chromium.org</owner> <owner>lukasza@chromium.org</owner> @@ -240,7 +240,7 @@ </histogram> <histogram name="Stability.ChildFrameCrash.TabMarkedForReload" - enum="BooleanMarkedForReload" expires_after="2021-09-30"> + enum="BooleanMarkedForReload" expires_after="2022-08-18"> <owner>alexmos@chromium.org</owner> <owner>boliu@chromium.org</owner> <summary> @@ -250,7 +250,7 @@ </histogram> <histogram name="Stability.ChildFrameCrash.TabMarkedForReload.Visibility" - enum="FrameVisibility" expires_after="2021-09-30"> + enum="FrameVisibility" expires_after="2022-08-18"> <owner>alexmos@chromium.org</owner> <owner>boliu@chromium.org</owner> <summary> @@ -261,7 +261,7 @@ </histogram> <histogram name="Stability.ChildFrameCrash.Visibility" enum="CrashVisibility" - expires_after="2022-02-06"> + expires_after="2022-08-18"> <owner>alexmos@chromium.org</owner> <owner>boliu@chromium.org</owner> <owner>lfg@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index f3c510a..06f57221 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -2031,6 +2031,25 @@ </metric> </event> +<event name="AutofillAssistant.Timing"> + <owner>arbesser@google.com</owner> + <owner>hluca@google.com</owner> + <owner>sandromaggi@google.com</owner> + <metric name="TriggerConditionEvaluationMs"> + <summary> + The time it took to evaluate the trigger conditions, in milliseconds. Only + successful evaluations are recorded. + </summary> + <aggregation> + <history> + <statistics> + <quantiles type="std-percentiles"/> + </statistics> + </history> + </aggregation> + </metric> +</event> + <event name="BackForwardCacheDisabledForRenderFrameHostReason"> <owner>altimin@chromium.org</owner> <owner>hajimehoshi@chromium.org</owner>
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc index f4dfc6df..ef74ff4f 100644 --- a/ui/accessibility/ax_enum_util.cc +++ b/ui/accessibility/ax_enum_util.cc
@@ -1046,6 +1046,8 @@ return "characterOffsets"; case ax::mojom::IntListAttribute::kCachedLineStarts: return "cachedLineStarts"; + case ax::mojom::IntListAttribute::kCaretBounds: + return "caretBounds"; case ax::mojom::IntListAttribute::kWordStarts: return "wordStarts"; case ax::mojom::IntListAttribute::kWordEnds:
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom index 5ae7a04..79a5322 100644 --- a/ui/accessibility/ax_enums.mojom +++ b/ui/accessibility/ax_enums.mojom
@@ -810,7 +810,8 @@ kTouchPassthrough = 20, }; -// Next value: 16 +// Next version: 2 +// Next value: 17 [Extensible, Stable, Uuid="6d1f823f-28a9-4263-bc4a-69fb19a4ef46"] enum IntListAttribute { [Default]kNone = 0, @@ -859,6 +860,9 @@ // items. Developer can expose those actions as custom actions. Currently // custom actions are used only in Android window. kCustomActionIds = 15, + + // Caret bounds in screen coordinates - [left, top, width, height]. + [MinVersion=1] kCaretBounds = 16, }; // Next value: 2
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc index d890e03..179c165d 100644 --- a/ui/accessibility/ax_event_generator.cc +++ b/ui/accessibility/ax_event_generator.cc
@@ -688,6 +688,9 @@ AddEvent(node, Event::TEXT_ATTRIBUTE_CHANGED); } break; + case ax::mojom::IntListAttribute::kCaretBounds: + AddEvent(node, Event::CARET_BOUNDS_CHANGED); + break; default: AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED); break; @@ -1177,6 +1180,8 @@ return "autoCompleteChanged"; case AXEventGenerator::Event::BUSY_CHANGED: return "busyChanged"; + case AXEventGenerator::Event::CARET_BOUNDS_CHANGED: + return "caretBoundsChanged"; case AXEventGenerator::Event::CHECKED_STATE_CHANGED: return "checkedStateChanged"; case AXEventGenerator::Event::CHECKED_STATE_DESCRIPTION_CHANGED:
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h index 026ecdf..6464b4a 100644 --- a/ui/accessibility/ax_event_generator.h +++ b/ui/accessibility/ax_event_generator.h
@@ -42,6 +42,7 @@ ATOMIC_CHANGED, AUTO_COMPLETE_CHANGED, BUSY_CHANGED, + CARET_BOUNDS_CHANGED, CHECKED_STATE_CHANGED, CHECKED_STATE_DESCRIPTION_CHANGED, CHILDREN_CHANGED,
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 6dc61bf..7ca7e69 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -200,6 +200,7 @@ case ax::mojom::IntListAttribute::kMarkerEnds: case ax::mojom::IntListAttribute::kCharacterOffsets: case ax::mojom::IntListAttribute::kCachedLineStarts: + case ax::mojom::IntListAttribute::kCaretBounds: case ax::mojom::IntListAttribute::kWordStarts: case ax::mojom::IntListAttribute::kWordEnds: case ax::mojom::IntListAttribute::kCustomActionIds: @@ -1731,6 +1732,9 @@ case ax::mojom::IntListAttribute::kCachedLineStarts: result += " cached_line_start_offsets=" + IntVectorToString(values); break; + case ax::mojom::IntListAttribute::kCaretBounds: + result += " caret_bounds=" + IntVectorToString(values); + break; case ax::mojom::IntListAttribute::kWordStarts: result += " word_starts=" + IntVectorToString(values); break;
diff --git a/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java b/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java index 25104a3..ae79e2b 100644 --- a/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java +++ b/ui/android/java/src/org/chromium/ui/modaldialog/ModalDialogProperties.java
@@ -71,7 +71,7 @@ new WritableObjectPropertyKey<>(); /** The message of the dialog. */ - public static final WritableObjectPropertyKey<String> MESSAGE = + public static final WritableObjectPropertyKey<CharSequence> MESSAGE = new WritableObjectPropertyKey<>(); /** The customized content view of the dialog. */
diff --git a/ui/base/cocoa/controls/button_utils.h b/ui/base/cocoa/controls/button_utils.h index d9b039f..f7df9c51 100644 --- a/ui/base/cocoa/controls/button_utils.h +++ b/ui/base/cocoa/controls/button_utils.h
@@ -14,8 +14,7 @@ // These methods are a polyfill for convenience constructors that exist on // NSButton in macOS 10.12+. -// TODO(ellyjones): once we target only 10.12+, delete these and migrate callers -// over to NSButton directly. +// TODO(https://crbug.com/1241080): once we target only 10.12+, delete these. + (NSButton*)buttonWithTitle:(NSString*)title action:(SEL)action target:(id)target;
diff --git a/ui/base/cocoa/controls/textfield_utils.h b/ui/base/cocoa/controls/textfield_utils.h index 4fd54c6..ff684b1 100644 --- a/ui/base/cocoa/controls/textfield_utils.h +++ b/ui/base/cocoa/controls/textfield_utils.h
@@ -13,8 +13,7 @@ @interface TextFieldUtils : NSObject // This method is a polyfill for a method on NSTextField on macOS 10.12+. -// TODO(ellyjones): Once we target only 10.12+, delete this and convert uses -// over to NSTextField. +// TODO(https://crbug.com/1241080): Once we only support 10.12+, delete this. + (NSTextField*)labelWithString:(NSString*)text; @end
diff --git a/ui/compositor/test/layer_animator_test_controller.cc b/ui/compositor/test/layer_animator_test_controller.cc index d271f08..344068c 100644 --- a/ui/compositor/test/layer_animator_test_controller.cc +++ b/ui/compositor/test/layer_animator_test_controller.cc
@@ -28,7 +28,8 @@ return NULL; } -void LayerAnimatorTestController::StartThreadedAnimationsIfNeeded() { +void LayerAnimatorTestController::StartThreadedAnimationsIfNeeded( + base::TimeTicks started_time) { std::vector<cc::TargetProperty::Type> threaded_properties; threaded_properties.push_back(cc::TargetProperty::OPACITY); threaded_properties.push_back(cc::TargetProperty::TRANSFORM); @@ -48,8 +49,7 @@ element->effective_start_time() != base::TimeTicks()) continue; - animator_->OnThreadedAnimationStarted(base::TimeTicks::Now(), - threaded_properties[i], + animator_->OnThreadedAnimationStarted(started_time, threaded_properties[i], element->animation_group_id()); } }
diff --git a/ui/compositor/test/layer_animator_test_controller.h b/ui/compositor/test/layer_animator_test_controller.h index 92798f3..ca64b08 100644 --- a/ui/compositor/test/layer_animator_test_controller.h +++ b/ui/compositor/test/layer_animator_test_controller.h
@@ -23,7 +23,8 @@ LayerAnimationElement::AnimatableProperty property); // Starts threaded animations that are waiting for an effective start time. - void StartThreadedAnimationsIfNeeded(); + void StartThreadedAnimationsIfNeeded( + base::TimeTicks started_time = base::TimeTicks::Now()); // Progresses all running animations by the given |duration|. void Step(const base::TimeDelta& duration);
diff --git a/ui/events/platform/platform_event_source.cc b/ui/events/platform/platform_event_source.cc index c80a92e..b3dc00c 100644 --- a/ui/events/platform/platform_event_source.cc +++ b/ui/events/platform/platform_event_source.cc
@@ -5,6 +5,7 @@ #include "ui/events/platform/platform_event_source.h" #include <algorithm> +#include <ostream> #include "base/lazy_instance.h" #include "base/threading/thread_local.h"
diff --git a/ui/gfx/font_list.cc b/ui/gfx/font_list.cc index 502b808..4155b8aba4 100644 --- a/ui/gfx/font_list.cc +++ b/ui/gfx/font_list.cc
@@ -4,6 +4,8 @@ #include "ui/gfx/font_list.h" +#include <ostream> + #include "base/lazy_instance.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h"
diff --git a/ui/message_center/notification_view_controller.cc b/ui/message_center/notification_view_controller.cc index f4038ef..cfab706c 100644 --- a/ui/message_center/notification_view_controller.cc +++ b/ui/message_center/notification_view_controller.cc
@@ -3,8 +3,12 @@ // found in the LICENSE file. #include "ui/message_center/notification_view_controller.h" +#include <iterator> +#include <memory> #include "ash/constants/ash_features.h" +#include "base/debug/stack_trace.h" +#include "base/no_destructor.h" #include "base/time/time.h" #include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/public/cpp/notification.h" @@ -12,7 +16,111 @@ namespace message_center { -NotificationViewController::NotificationViewController() { +namespace { + +class GroupedNotificationList { + public: + GroupedNotificationList() = default; + GroupedNotificationList(const GroupedNotificationList& other) = delete; + GroupedNotificationList& operator=(const GroupedNotificationList& other) = + delete; + ~GroupedNotificationList() = default; + + void AddGroupedNotification(const std::string& notification_id, + const std::string& parent_id) { + if (notifications_in_parent_map_.find(parent_id) == + notifications_in_parent_map_.end()) { + notifications_in_parent_map_[parent_id] = {}; + } + + child_parent_map_[notification_id] = parent_id; + + if (notification_id != parent_id) + notifications_in_parent_map_[parent_id].insert(notification_id); + } + + // Remove a single child notification from a grouped notification. + void RemoveGroupedChildNotification(const std::string& notification_id) { + std::string& parent_id = child_parent_map_[notification_id]; + notifications_in_parent_map_[parent_id].erase(notification_id); + child_parent_map_.erase(notification_id); + } + + // Clear the entire grouped notification with `parent_id` + void ClearGroupedNotification(const std::string& parent_id) { + notifications_in_parent_map_.erase(parent_id); + std::vector<std::string> to_be_deleted; + for (const auto& it : child_parent_map_) { + if (it.second == parent_id) + to_be_deleted.push_back(it.first); + } + for (const auto& child : to_be_deleted) + child_parent_map_.erase(child); + } + + const std::string& GetParentForChild(const std::string& child_id) { + return child_parent_map_[child_id]; + } + + std::set<std::string>& GetGroupedNotificationsForParent( + const std::string& parent_id) { + return notifications_in_parent_map_[parent_id]; + } + + bool GroupedChildNotificationExists(const std::string& child_id) { + return child_parent_map_.find(child_id) != child_parent_map_.end(); + } + + bool ParentNotificationExists(const std::string& parent_id) { + return notifications_in_parent_map_.find(parent_id) != + notifications_in_parent_map_.end(); + } + + // Replaces all instances of `old_parent_id` with `new_parent_id` in + // the `child_parent_map_`. + void ReplaceParentId(const std::string& new_parent_id, + const std::string& old_parent_id) { + // Remove entry with `new_parent_id` as a child id and replace with + // `old_parent_id` as a child id. + child_parent_map_.erase(new_parent_id); + child_parent_map_[old_parent_id] = new_parent_id; + + // Replace all occurrences of `old_parent_id` with `new_parent_id`. + std::vector<std::string> to_be_updated; + for (const auto& child : child_parent_map_) { + if (child.second == old_parent_id) + to_be_updated.push_back(child.first); + } + for (const auto& id : to_be_updated) { + child_parent_map_.erase(child_parent_map_.find(id)); + child_parent_map_[id] = new_parent_id; + } + } + + private: + // Map for looking up the parent `notification_id` for any given notification + // id. + std::map<std::string, std::string> child_parent_map_; + + // Map containing a list of child notification ids per each group parent id. + // Used to keep track of grouped notifications which already have a parent + // notification view. + std::map<std::string, std::set<std::string>> notifications_in_parent_map_; +}; + +// Needs to be a static instance because +// we need a single instance to be shared across MessagePopupCollection and +// UnifiedMessageListView. TODO(crbug/1239033) Refactor +// NotificationViewController so we won't have to do this. +GroupedNotificationList& GetGroupedNotificationListInstance() { + static base::NoDestructor<GroupedNotificationList> instance; + return *instance; +} + +} // namespace + +NotificationViewController::NotificationViewController() + : grouped_notification_list_(&GetGroupedNotificationListInstance()) { observer_.Observe(MessageCenter::Get()); } @@ -30,12 +138,18 @@ for (auto* notification : MessageCenter::Get()->GetNotifications()) { if (notification->notifier_id() == parent_view->notifier_id() && notification->id() != parent_view->notification_id()) { - child_parent_map_[notification->id()] = parent_view->notification_id(); + grouped_notification_list_->AddGroupedNotification(notification->id(), + notification_id); parent_view->AddGroupNotification(*notification, /*newest_first=*/true); } } } +const std::string& NotificationViewController::GetParentIdForChildForTest( + const std::string& notification_id) { + return grouped_notification_list_->GetParentForChild(notification_id); +} + void NotificationViewController::SetupParentNotification( std::string* parent_id) { Notification* parent_notification = @@ -47,7 +161,8 @@ std::string old_parent_id = *parent_id; *parent_id = new_parent_id; - parent_grouped_notification_id_set_.insert(new_parent_id); + grouped_notification_list_->AddGroupedNotification(old_parent_id, + new_parent_id); Notification* new_parent_notification = notification_copy.get(); MessageCenter::Get()->AddNotification(std::move(notification_copy)); @@ -55,8 +170,10 @@ ConvertNotificationViewToGroupedNotificationView( /*ungrouped_notification_id=*/old_parent_id, /*new_grouped_notification_id=*/new_parent_id); - UpdateChildParentMap(/*new_parent_id=*/new_parent_id, - /*old_parent_id=*/old_parent_id); + + grouped_notification_list_->ReplaceParentId( + /*new_parent_id=*/new_parent_id, + /*old_parent_id=*/old_parent_id); // Add the old parent notification as a group child to the // newly created parent notification which will act as a @@ -64,8 +181,33 @@ new_parent_notification->SetGroupParent(); parent_notification->SetGroupChild(); - GetMessageViewForNotificationId(new_parent_id) - ->AddGroupNotification(*parent_notification, /*newest_first=*/false); + auto* parent_view = GetMessageViewForNotificationId(new_parent_id); + if (parent_view) + parent_view->AddGroupNotification(*parent_notification, + /*newest_first=*/false); +} + +void NotificationViewController::SetupSingleNotificationFromGroupedNotification( + const std::string& group_parent_id, + const std::string& new_single_notification_id) { + auto* message_center = MessageCenter::Get(); + MessageView* parent_view = GetMessageViewForNotificationId(group_parent_id); + auto* new_single_notification = + message_center->FindNotificationById(new_single_notification_id); + + parent_view->RemoveGroupNotification(new_single_notification_id); + parent_view->UpdateWithNotification(*new_single_notification); + + ConvertGroupedNotificationViewToNotificationView( + /*grouped_notification_id=*/group_parent_id, + /*new_single_notification_id=*/new_single_notification_id); + + message_center->FindNotificationById(group_parent_id)->ClearGroupParent(); + new_single_notification->ClearGroupChild(); + + grouped_notification_list_->ClearGroupedNotification(group_parent_id); + + message_center->RemoveNotification(group_parent_id, /*by_user=*/false); } std::unique_ptr<Notification> @@ -88,31 +230,40 @@ return child_copy; } -void NotificationViewController::UpdateChildParentMap( - const std::string& new_parent_id, - const std::string& old_parent_id) { - // Remove entry with `new_parent_id` as a child id and replace with - // `old_parent_id` as a child id. - DCHECK(child_parent_map_.find(new_parent_id) != child_parent_map_.end()); - child_parent_map_.erase(child_parent_map_.find(new_parent_id)); - child_parent_map_[old_parent_id] = new_parent_id; - - // Replace all occurrences of `old_parent_id` with `new_parent_id`. - std::vector<std::string> to_be_updated; - for (auto& child : child_parent_map_) { - if (child.second == old_parent_id) - to_be_updated.push_back(child.first); +void NotificationViewController::RemoveGroupedChild( + const std::string& notification_id) { + if (!grouped_notification_list_->GroupedChildNotificationExists( + notification_id)) { + return; } - for (auto id : to_be_updated) { - child_parent_map_.erase(child_parent_map_.find(id)); - child_parent_map_[id] = new_parent_id; + + const std::string parent_id = + grouped_notification_list_->GetParentForChild(notification_id); + + MessageView* parent_view = GetMessageViewForNotificationId(parent_id); + if (parent_view) + parent_view->RemoveGroupNotification(notification_id); + + grouped_notification_list_->RemoveGroupedChildNotification(notification_id); + + // Convert back to a single notification if there is only one + // group child left in the group notification. + auto grouped_notifications = + grouped_notification_list_->GetGroupedNotificationsForParent(parent_id); + if (GetMessageViewForNotificationId(parent_id) && + grouped_notifications.size() == 1) { + SetupSingleNotificationFromGroupedNotification( + /*group_parent_id=*/parent_id, + /*new_single_notification_id=*/*grouped_notifications.begin()); } } void NotificationViewController::OnNotificationAdded( const std::string& notification_id) { + auto* message_center = MessageCenter::Get(); Notification* notification = - MessageCenter::Get()->FindNotificationById(notification_id); + message_center->FindNotificationById(notification_id); + // We only need to process notifications that are children of an // existing group. So do nothing otherwise. if (!notification) @@ -122,7 +273,7 @@ return; Notification* parent_notification = - MessageCenter::Get()->FindOldestNotificationByNotiferId( + message_center->FindOldestNotificationByNotiferId( notification->notifier_id()); std::string parent_id = parent_notification->id(); @@ -130,40 +281,37 @@ // we must create a copy of the designated parent notification and // use it to set up a container notification which will hold all // notifications for this group. - if (!parent_grouped_notification_id_set_.count(parent_id)) + if (!grouped_notification_list_->ParentNotificationExists(parent_id)) SetupParentNotification(&parent_id); - child_parent_map_[notification_id] = parent_id; + grouped_notification_list_->AddGroupedNotification(notification_id, + parent_id); MessageView* parent_view = GetMessageViewForNotificationId(parent_id); if (parent_view) parent_view->AddGroupNotification(*notification, /*newest_first=*/false); else - MessageCenter::Get()->ResetSinglePopup(parent_id); + message_center->ResetSinglePopup(parent_id); } void NotificationViewController::OnNotificationRemoved( const std::string& notification_id, bool by_user) { - auto child_it = child_parent_map_.find(notification_id); - if (child_it != child_parent_map_.end()) { - MessageView* parent_view = - GetMessageViewForNotificationId(child_parent_map_[notification_id]); - - child_parent_map_.erase(child_it); - - if (parent_view) - parent_view->RemoveGroupNotification(notification_id); + if (grouped_notification_list_->GroupedChildNotificationExists( + notification_id)) { + RemoveGroupedChild(notification_id); } - auto parent = parent_grouped_notification_id_set_.find(notification_id); - if (parent != parent_grouped_notification_id_set_.end()) { - std::vector<std::string> to_be_deleted; - for (auto& child : child_parent_map_) { - if (child.second == notification_id) - to_be_deleted.push_back(child.first); - } - for (auto id : to_be_deleted) + if (grouped_notification_list_->ParentNotificationExists(notification_id)) { + std::vector<std::string> to_be_deleted; + auto grouped_notifications = + grouped_notification_list_->GetGroupedNotificationsForParent( + notification_id); + std::copy(grouped_notifications.begin(), grouped_notifications.end(), + std::back_inserter(to_be_deleted)); + grouped_notification_list_->ClearGroupedNotification(notification_id); + + for (const auto& id : to_be_deleted) MessageCenter::Get()->RemoveNotification(id, by_user); } }
diff --git a/ui/message_center/notification_view_controller.h b/ui/message_center/notification_view_controller.h index f273ba54..177526a 100644 --- a/ui/message_center/notification_view_controller.h +++ b/ui/message_center/notification_view_controller.h
@@ -12,6 +12,10 @@ namespace message_center { +namespace { +class GroupedNotificationList; +} // namespace + class MessageView; // A controller class to manage adding, removing and updating group @@ -35,11 +39,16 @@ // view. void PopulateGroupParent(const std::string& notification_id); + const std::string& GetParentIdForChildForTest( + const std::string& notification_id); + private: + friend class MockNotificationViewController; + virtual MessageView* GetMessageViewForNotificationId( const std::string& notification_id) = 0; - // Updates the notification id associated with a message center view and + // Updates the notification id associated with a `MessageCenterView` and // popup if required. We do this to covert an existing message view into // a message view that acts as a container for grouped notifications. // Creating a new view for this would make the code simpler but we need @@ -49,29 +58,39 @@ const std::string& ungrouped_notification_id, const std::string& new_grouped_notification_id) = 0; + // Updates the notification id associated with a `MessageCenterView` and + // popup if needed. This is done to convert an existing grouped notification + // view back into a single notification view. + virtual void ConvertGroupedNotificationViewToNotificationView( + const std::string& grouped_notification_id, + const std::string& new_single_notification_id) = 0; + // Sets up a parent view to hold all message views for // a grouped notification. Does this by creating a copy of the // parent notification and switching the notification_ids of the // current message view associated with the parent notification. void SetupParentNotification(std::string* parent_id); + // Clears all group data for `group_parent_id` and converts + // the existing message view for `group_parent_id` to a single + // ungrouped notification view representing `new_single_notification_id`. + void SetupSingleNotificationFromGroupedNotification( + const std::string& group_parent_id, + const std::string& new_single_notification_id); + // Creates a copy notification that will act as a parent notification // for its group. std::unique_ptr<Notification> CreateCopyForParentNotification( const Notification& parent_notification); - // Replaces all instances of `old_parent_id` with `new_parent_id` in - // the `child_parent_map_`. - void UpdateChildParentMap(const std::string& new_parent_id, - const std::string& old_parent_id); + // Remove `notification_id` from `child_parent_map` and + // `notifications_in_parent_map` Also remove from it's parent notification's + // view if if the view currently exists. + void RemoveGroupedChild(const std::string& notification_id); - // Map for looking up the parent notification_id for any given notification - // id. - std::map<std::string, std::string> child_parent_map_; - - // Set of current parent notification ids. Used to keep track of grouped - // notifications which already have a parent notification view. - std::set<std::string> parent_grouped_notification_id_set_; + // A data structure that holds all grouped notifications along with their + // associations with their parent notifications. + GroupedNotificationList* const grouped_notification_list_; base::ScopedObservation<MessageCenter, MessageCenterObserver> observer_{this}; };
diff --git a/ui/message_center/notification_view_controller_unittest.cc b/ui/message_center/notification_view_controller_unittest.cc index 4b29990..f593bc15 100644 --- a/ui/message_center/notification_view_controller_unittest.cc +++ b/ui/message_center/notification_view_controller_unittest.cc
@@ -30,7 +30,7 @@ MessageView* GetMessageViewForNotificationId( const std::string& notification_id) override { auto it = std::find_if(fake_message_views_.begin(), - fake_message_views_.end(), [&](auto& child) { + fake_message_views_.end(), [&](const auto& child) { return child->notification_id() == notification_id; }); @@ -40,13 +40,31 @@ return it->get(); } void ConvertNotificationViewToGroupedNotificationView( - const std::string& ungrouped_popup_id, - const std::string& new_grouped_popup_id) override {} + const std::string& ungrouped_notification_id, + const std::string& new_grouped_notification_id) override {} + + void ConvertGroupedNotificationViewToNotificationView( + const std::string& ungrouped_notification_id, + const std::string& new_grouped_notification_id) override {} void OnNotificationAdded(const std::string& notification_id) override { - fake_message_views_.push_back(std::make_unique<MockMessageView>( - *MessageCenter::Get()->FindNotificationById(notification_id))); NotificationViewController::OnNotificationAdded(notification_id); + auto* notification = + MessageCenter::Get()->FindNotificationById(notification_id); + fake_message_views_.push_back( + std::make_unique<MockMessageView>(*notification)); + + if (!notification->group_child()) + return; + + std::string parent_id = GetParentIdForChildForTest(notification_id); + auto it = std::find_if( + fake_message_views_.begin(), fake_message_views_.end(), + [&](const auto& view) { return view->notification_id() == parent_id; }); + if (it == fake_message_views_.end()) { + fake_message_views_.push_back(std::make_unique<MockMessageView>( + *MessageCenter::Get()->FindNotificationById(parent_id))); + } } void OnNotificationRemoved(const std::string& notification_id, @@ -58,7 +76,7 @@ void RemoveNotificationViewById(const std::string& id) { auto it = std::find_if( fake_message_views_.begin(), fake_message_views_.end(), - [&](auto& child) { return child->notification_id() == id; }); + [&](const auto& view) { return view->notification_id() == id; }); if (it != fake_message_views_.end()) fake_message_views_.erase(it); } @@ -98,8 +116,9 @@ Notification* GetPopupNotification(const std::string& id) { auto popups = MessageCenter::Get()->GetPopupNotifications(); - auto it = std::find_if(popups.begin(), popups.end(), - [&](auto popup) { return popup->id() == id; }); + auto it = + std::find_if(popups.begin(), popups.end(), + [&](const auto& popup) { return popup->id() == id; }); if (it == popups.end()) return nullptr; @@ -138,17 +157,41 @@ const char NotificationViewControllerTest::kIdFormat[] = "id%ld"; TEST_F(NotificationViewControllerTest, BasicGrouping) { + auto* message_center = MessageCenter::Get(); std::string id0, id1, id2; const char group_id[] = "group"; id0 = AddNotificationWithNotifierId(group_id); id1 = AddNotificationWithNotifierId(group_id); id2 = AddNotificationWithNotifierId(group_id); - EXPECT_TRUE(MessageCenter::Get()->FindNotificationById(id0)->group_child()); - EXPECT_TRUE(MessageCenter::Get()->FindNotificationById(id1)->group_child()); - EXPECT_TRUE(MessageCenter::Get()->FindNotificationById(id2)->group_child()); + EXPECT_TRUE(message_center->FindNotificationById(id0)->group_child()); + EXPECT_TRUE(message_center->FindNotificationById(id1)->group_child()); + EXPECT_TRUE(message_center->FindNotificationById(id2)->group_child()); std::string id_parent = id0 + kIdSuffixForGroupContainerNotification; + EXPECT_TRUE(message_center->FindNotificationById(id_parent)->group_parent()); +} + +TEST_F(NotificationViewControllerTest, BasicRemoval) { + std::string id0, id1, id2; + const char group_id[] = "group"; + id0 = AddNotificationWithNotifierId(group_id); + id1 = AddNotificationWithNotifierId(group_id); + id2 = AddNotificationWithNotifierId(group_id); + + std::string id_parent = id0 + kIdSuffixForGroupContainerNotification; + // Group notification should stay intact if a single group notification is + // removed. + MessageCenter::Get()->RemoveNotification(id1, true); + EXPECT_TRUE( + MessageCenter::Get()->FindNotificationById(id_parent)->group_parent()); + + // Adding and removing a non group notification should have no impact. + std::string tmp = AddNotificationWithNotifierId("tmp"); + MessageCenter::Get()->RemoveNotification(tmp, true); + + EXPECT_TRUE(MessageCenter::Get()->FindNotificationById(id0)->group_child()); + EXPECT_TRUE(MessageCenter::Get()->FindNotificationById(id2)->group_child()); EXPECT_TRUE( MessageCenter::Get()->FindNotificationById(id_parent)->group_parent()); } @@ -190,8 +233,62 @@ ASSERT_FALSE(MessageCenter::Get()->HasPopupNotifications()); } -// TODO(crbug/1223697) Tests TBA: -// * Expected behavior on removal -// * All but 1 child notification removed from group +TEST_F(NotificationViewControllerTest, + ConvertingGroupedNotificationToSingleNotificationAndBack) { + auto* message_center = MessageCenter::Get(); + std::string id0, id1, id2; + const char group_id[] = "group"; + id0 = AddNotificationWithNotifierId(group_id); + id1 = AddNotificationWithNotifierId(group_id); + id2 = AddNotificationWithNotifierId(group_id); + + std::string parent_id = id0 + kIdSuffixForGroupContainerNotification; + EXPECT_TRUE( + MessageCenter::Get()->FindNotificationById(parent_id)->group_parent()); + + // Removing all but 1 notification should convert it back to a single + // notification and result in the removal of the parent notification. + message_center->RemoveNotification(id0, true); + message_center->RemoveNotification(id1, true); + + auto* single_notification = message_center->FindNotificationById(id2); + EXPECT_FALSE(single_notification->group_child() || + single_notification->group_parent()); + EXPECT_FALSE(message_center->FindNotificationById(parent_id)); + + // Adding further notifications should create a new group with the parent id + // being derived from `id2`. + id0 = AddNotificationWithNotifierId(group_id); + id1 = AddNotificationWithNotifierId(group_id); + + parent_id = id2 + kIdSuffixForGroupContainerNotification; + EXPECT_TRUE(message_center->FindNotificationById(parent_id)); +} + +TEST_F(NotificationViewControllerTest, + ConvertingRepopulatedParentToSingleNotification) { + auto* message_center = MessageCenter::Get(); + std::string id0, id1, id2, id3, id4; + const char group_id[] = "group"; + id0 = AddNotificationWithNotifierId(group_id); + id1 = AddNotificationWithNotifierId(group_id); + id2 = AddNotificationWithNotifierId(group_id); + id3 = AddNotificationWithNotifierId(group_id); + + std::string parent_id = id0 + kIdSuffixForGroupContainerNotification; + RemoveAndMarkPopupAsShown(parent_id); + + id4 = AddNotificationWithNotifierId(group_id); + + message_center->RemoveNotification(id0, true); + message_center->RemoveNotification(id1, true); + message_center->RemoveNotification(id2, true); + message_center->RemoveNotification(id3, true); + + auto* single_notification = MessageCenter::Get()->FindNotificationById(id4); + EXPECT_FALSE(single_notification->group_child() || + single_notification->group_parent()); + EXPECT_FALSE(MessageCenter::Get()->FindNotificationById(parent_id)); +} } // namespace message_center
diff --git a/ui/message_center/public/cpp/notification.cc b/ui/message_center/public/cpp/notification.cc index 571a40a..e37ac84d 100644 --- a/ui/message_center/public/cpp/notification.cc +++ b/ui/message_center/public/cpp/notification.cc
@@ -139,6 +139,16 @@ group_parent_ = true; } +void Notification::ClearGroupChild() { + DCHECK(!group_parent_); + group_child_ = false; +} + +void Notification::ClearGroupParent() { + DCHECK(!group_child_); + group_parent_ = false; +} + bool Notification::UseOriginAsContextMessage() const { return optional_fields_.context_message.empty() && origin_url_.is_valid() && origin_url_.SchemeIsHTTPOrHTTPS();
diff --git a/ui/message_center/public/cpp/notification.h b/ui/message_center/public/cpp/notification.h index 8dbc01f..5a19480 100644 --- a/ui/message_center/public/cpp/notification.h +++ b/ui/message_center/public/cpp/notification.h
@@ -475,6 +475,14 @@ // notifications that are part of its group. void SetGroupParent(); + // Set `group_child_` to false so it's back to it's + // default state. + void ClearGroupChild(); + + // Set `group_parent_` to false so it's back to it's + // default state. + void ClearGroupParent(); + #if BUILDFLAG(IS_CHROMEOS_ASH) void set_system_notification_warning_level( SystemNotificationWarningLevel warning_level) {
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc index 57f265c..e421adb 100644 --- a/ui/message_center/views/message_popup_collection.cc +++ b/ui/message_center/views/message_popup_collection.cc
@@ -129,8 +129,8 @@ MessageView* MessagePopupCollection::GetMessageViewForNotificationId( const std::string& notification_id) { - auto it = - std::find_if(popup_items_.begin(), popup_items_.end(), [&](auto child) { + auto it = std::find_if( + popup_items_.begin(), popup_items_.end(), [&](const auto& child) { return child.popup->message_view()->notification_id() == notification_id; }); @@ -146,7 +146,7 @@ const std::string& new_grouped_notification_id) { auto it = std::find_if( popup_items_.begin(), popup_items_.end(), - [&](auto popup) { return popup.id == ungrouped_notification_id; }); + [&](const auto& popup) { return popup.id == ungrouped_notification_id; }); if (it == popup_items_.end()) return; @@ -154,11 +154,26 @@ it->popup->message_view()->set_notification_id(new_grouped_notification_id); } +void MessagePopupCollection::ConvertGroupedNotificationViewToNotificationView( + const std::string& grouped_notification_id, + const std::string& new_single_notification_id) { + auto it = std::find_if( + popup_items_.begin(), popup_items_.end(), + [&](const auto& popup) { return popup.id == grouped_notification_id; }); + if (it == popup_items_.end()) + return; + + it->id = new_single_notification_id; + it->popup->message_view()->set_notification_id(new_single_notification_id); +} + void MessagePopupCollection::OnNotificationAdded( const std::string& notification_id) { #if BUILDFLAG(IS_CHROMEOS_ASH) - if (ash::features::IsNotificationsRefreshEnabled()) + if (ash::features::IsNotificationsRefreshEnabled() && + !MessageCenter::Get()->IsMessageCenterVisible()) { NotificationViewController::OnNotificationAdded(notification_id); + } #endif // Should not call MessagePopupCollection::Update here. Because notification // may be removed before animation which is triggered by the previous @@ -173,8 +188,10 @@ const std::string& notification_id, bool by_user) { #if BUILDFLAG(IS_CHROMEOS_ASH) - if (ash::features::IsNotificationsRefreshEnabled()) + if (ash::features::IsNotificationsRefreshEnabled() && + !MessageCenter::Get()->IsMessageCenterVisible()) { NotificationViewController::OnNotificationRemoved(notification_id, by_user); + } #endif if (by_user) {
diff --git a/ui/message_center/views/message_popup_collection.h b/ui/message_center/views/message_popup_collection.h index 1661b28..c78f0ec 100644 --- a/ui/message_center/views/message_popup_collection.h +++ b/ui/message_center/views/message_popup_collection.h
@@ -63,6 +63,9 @@ void ConvertNotificationViewToGroupedNotificationView( const std::string& ungrouped_notification_id, const std::string& new_grouped_notification_id) override; + void ConvertGroupedNotificationViewToNotificationView( + const std::string& grouped_notification_id, + const std::string& new_single_notification_id) override; void OnNotificationAdded(const std::string& notification_id) override; void OnNotificationRemoved(const std::string& notification_id, bool by_user) override;
diff --git a/ui/views/accessibility/ax_window_obj_wrapper.cc b/ui/views/accessibility/ax_window_obj_wrapper.cc index b1bc358..6607365 100644 --- a/ui/views/accessibility/ax_window_obj_wrapper.cc +++ b/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -18,6 +18,7 @@ #include "ui/aura/client/focus_client.h" #include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host_platform.h" +#include "ui/base/ime/text_input_client.h" #include "ui/compositor/layer.h" #include "ui/platform_window/platform_window.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" @@ -89,6 +90,14 @@ if (is_root_window_) aura_obj_cache_->OnRootWindowObjCreated(window); + + // This is a top level root window. + if (window->IsRootWindow() && !window->parent()) { + // On desktop aura there is one WindowTreeHost per top-level window. + aura::WindowTreeHost* window_tree_host = window->GetHost(); + if (window_tree_host) + ime_observation_.Observe(window_tree_host->GetInputMethod()); + } } AXWindowObjWrapper::~AXWindowObjWrapper() = default; @@ -159,6 +168,18 @@ } } #endif // BUILDFLAG(IS_CHROMEOS_LACROS) + if (window_->IsRootWindow() && !window_->parent() && window_->GetHost()) { + ui::TextInputClient* client = + window_->GetHost()->GetInputMethod()->GetTextInputClient(); + // Only set caret bounds if input caret is in an editable node. + if (client && client->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) { + gfx::Rect caret_bounds_in_screen = client->GetCaretBounds(); + out_node_data->AddIntListAttribute( + ax::mojom::IntListAttribute::kCaretBounds, + {caret_bounds_in_screen.x(), caret_bounds_in_screen.y(), + caret_bounds_in_screen.width(), caret_bounds_in_screen.height()}); + } + } out_node_data->id = GetUniqueId(); ax::mojom::Role role = window_->GetProperty(ui::kAXRoleOverride); @@ -218,6 +239,11 @@ return GetWindowName(window_); } +void AXWindowObjWrapper::OnCaretBoundsChanged( + const ui::TextInputClient* client) { + FireEvent(ax::mojom::Event::kTreeChanged); +} + void AXWindowObjWrapper::OnWindowDestroyed(aura::Window* window) { aura_obj_cache_->Remove(window, nullptr); }
diff --git a/ui/views/accessibility/ax_window_obj_wrapper.h b/ui/views/accessibility/ax_window_obj_wrapper.h index dda56e3..a866bed 100644 --- a/ui/views/accessibility/ax_window_obj_wrapper.h +++ b/ui/views/accessibility/ax_window_obj_wrapper.h
@@ -15,13 +15,20 @@ #include "ui/accessibility/platform/ax_unique_id.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" +#include "ui/base/ime/input_method.h" +#include "ui/base/ime/input_method_observer.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" +namespace ui { +class InputMethod; +} + namespace views { class AXAuraObjCache; // Describes a |Window| for use with other AX classes. class AXWindowObjWrapper : public AXAuraObjWrapper, + public ui::InputMethodObserver, public aura::WindowObserver { public: // |aura_obj_cache| and |window| must outlive this object. @@ -38,6 +45,14 @@ ui::AXNodeID GetUniqueId() const final; std::string ToString() const override; + // InputMethodObserver overrides. + void OnFocus() override {} + void OnBlur() override {} + void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {} + void OnShowVirtualKeyboardIfEnabled() override {} + void OnTextInputStateChanged(const ui::TextInputClient* client) override {} + void OnCaretBoundsChanged(const ui::TextInputClient* client) override; + // WindowObserver overrides. void OnWindowDestroyed(aura::Window* window) override; void OnWindowDestroying(aura::Window* window) override; @@ -58,6 +73,8 @@ // Fires an accessibility event. void FireEvent(ax::mojom::Event event_type); + gfx::Rect GetCaretBounds(const ui::TextInputClient* client); + aura::Window* const window_; const bool is_root_window_; @@ -71,6 +88,9 @@ base::ScopedObservation<aura::Window, aura::WindowObserver> observation_{ this}; + + base::ScopedObservation<ui::InputMethod, ui::InputMethodObserver> + ime_observation_{this}; }; } // namespace views
diff --git a/ui/views/animation/animation_builder.cc b/ui/views/animation/animation_builder.cc index 6089c11..a91c67b 100644 --- a/ui/views/animation/animation_builder.cc +++ b/ui/views/animation/animation_builder.cc
@@ -46,6 +46,9 @@ void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; void OnLayerAnimationScheduled(ui::LayerAnimationSequence* sequence) override; + protected: + void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; + private: using RepeatMap = base::flat_map<ui::LayerAnimationSequence*, int>; RepeatMap repeat_map_; @@ -97,7 +100,6 @@ if (running <= 1) { if (on_ended_) std::move(on_ended_).Run(); - delete this; } } @@ -132,6 +134,12 @@ std::move(on_scheduled_).Run(); } +void AnimationBuilder::Observer::OnDetachedFromSequence( + ui::LayerAnimationSequence* sequence) { + if (attached_sequences().empty()) + delete this; +} + struct AnimationBuilder::Value { base::TimeDelta start; std::unique_ptr<ui::LayerAnimationElement> element;
diff --git a/ui/views/animation/animation_builder_unittest.cc b/ui/views/animation/animation_builder_unittest.cc index 0d90cdec..d32fd21c 100644 --- a/ui/views/animation/animation_builder_unittest.cc +++ b/ui/views/animation/animation_builder_unittest.cc
@@ -9,8 +9,6 @@ #include "ui/compositor/layer.h" #include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_owner.h" -#include "ui/compositor/property_change_reason.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/test/layer_animator_test_controller.h" #include "ui/compositor/test/test_layer_animation_delegate.h" #include "ui/gfx/geometry/rounded_corners_f.h" @@ -46,12 +44,8 @@ void Step(const base::TimeDelta& duration) { DCHECK_GT(duration, base::TimeDelta()); for (const auto& controller : animator_controllers_) { - if (elapsed_.is_zero()) { - controller->StartThreadedAnimationsIfNeeded(); - // We need this because StartThreadedAnimationsIfNeeded() sets sequence - // start time to Now() but does not update animator's step time. - controller->animator()->set_last_step_time(base::TimeTicks::Now()); - } + controller->StartThreadedAnimationsIfNeeded( + controller->animator()->last_step_time()); controller->Step(duration); } elapsed_ += duration; @@ -159,4 +153,54 @@ EXPECT_TRUE(ended); } +TEST_F(AnimationBuilderTest, DelayedStart) { + TestAnimatibleLayerOwner* view = CreateTestLayerOwner(); + ui::LayerAnimationDelegate* delegate = view->delegate(); + + constexpr auto kDelay = base::TimeDelta::FromSeconds(1); + constexpr auto kDuration = base::TimeDelta::FromSeconds(1); + + { + // clang-format off + AnimationBuilder() + .Once() + .At(kDelay) + .SetDuration(kDuration) + .SetOpacity(view, 0.4f); + // clang-format on + } + + // Original value before the animation steps. + EXPECT_FLOAT_EQ(delegate->GetOpacityForAnimation(), 1.0); + Step(kDelay); + // The animation on opacity is not yet started. + EXPECT_FLOAT_EQ(delegate->GetOpacityForAnimation(), 1.0); + Step(kDuration); + EXPECT_FLOAT_EQ(delegate->GetOpacityForAnimation(), 0.4f); +} + +TEST_F(AnimationBuilderTest, TwoKeyFrame) { + TestAnimatibleLayerOwner* view = CreateTestLayerOwner(); + ui::LayerAnimationDelegate* delegate = view->delegate(); + + constexpr auto kDuration = base::TimeDelta::FromSeconds(1); + + { + AnimationBuilder() + .Once() + .SetDuration(kDuration) + .SetOpacity(view, 0.4f) + .Then() + .SetDuration(kDuration) + .SetOpacity(view, 0.9f); + } + + // The animation on opacity is not yet started. + EXPECT_FLOAT_EQ(delegate->GetOpacityForAnimation(), 1.0); + Step(kDuration); + EXPECT_FLOAT_EQ(delegate->GetOpacityForAnimation(), 0.4f); + Step(kDuration); + EXPECT_FLOAT_EQ(delegate->GetOpacityForAnimation(), 0.9f); +} + } // namespace views
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index 2d398138..aa316098 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -48,6 +48,8 @@ "icon.js", "load_time_data.m.js", "plural_string_proxy.js", + "post_message_api_server.js", + "post_message_api_client.js", "search_highlight_utils.js", "test_loader.js", "test_loader_util.js", @@ -98,6 +100,8 @@ "event_tracker.m.js", "load_time_data.js", "parse_html_subset.m.js", + "post_message_api_server.m.js", + "post_message_api_client.m.js", "promise_resolver.m.js", "util.m.js", ] @@ -131,6 +135,8 @@ ":list_property_update_behavior", ":load_time_data", ":parse_html_subset", + ":post_message_api_client", + ":post_message_api_server", ":promise_resolver", ":util", ":web_ui_listener_behavior", @@ -188,6 +194,12 @@ js_library("parse_html_subset") { } +js_library("post_message_api_server") { +} + +js_library("post_message_api_client") { +} + js_library("promise_resolver") { deps = [ ":assert" ] } @@ -221,6 +233,8 @@ "i18n_behavior.js", "list_property_update_behavior.js", "parse_html_subset.js", + "post_message_api_server.js", + "post_message_api_client.js", "promise_resolver.js", "util.js", "web_ui_listener_behavior.js", @@ -256,6 +270,8 @@ ":load_time_data.m", ":parse_html_subset.m", ":plural_string_proxy", + ":post_message_api_client.m", + ":post_message_api_server.m", ":promise_resolver.m", ":search_highlight_utils", ":util.m", @@ -319,6 +335,18 @@ deps = [ ":cr.m" ] } +js_library("post_message_api_server.m") { + sources = + [ "$root_gen_dir/ui/webui/resources/js/post_message_api_server.m.js" ] + extra_deps = [ ":modulize_local" ] +} + +js_library("post_message_api_client.m") { + sources = + [ "$root_gen_dir/ui/webui/resources/js/post_message_api_client.m.js" ] + extra_deps = [ ":modulize_local" ] +} + js_library("promise_resolver.m") { sources = [ "$root_gen_dir/ui/webui/resources/js/promise_resolver.m.js" ] deps = [ ":assert.m" ]
diff --git a/ui/webui/resources/js/post_message_api_client.js b/ui/webui/resources/js/post_message_api_client.js new file mode 100644 index 0000000..b8c2627 --- /dev/null +++ b/ui/webui/resources/js/post_message_api_client.js
@@ -0,0 +1,148 @@ +// Copyright 2021 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. + +/** + * Class that provides the functionality for talking to a PostMessageAPIServer + * over the postMessage API. This should be subclassed and the methods in the + * server that the client needs to access should be provided in methodList. + * + */ +export class PostMessageAPIClient { + /** + * @param {!Array<string>} methodList The list of methods accessible via the + * client. + * @param {!string} serverOriginURLFilter Only messages from this origin + * will be accepted. + */ + constructor(methodList, serverOriginURLFilter) { + /** + * @private @const {!string} Filter to use to validate + * the origin of received messages. The origin of messages + * must exactly match this value. + */ + this.serverOriginURLFilter_ = serverOriginURLFilter; + + /** + * The parent window. + * @private {Window} + */ + this.parentWindow_ = null; + /* + * @private {number} + */ + this.nextMethodId_ = 0; + /** + * Map of methods awaiting a response. + * @private {!Map} + */ + this.methodsAwaitingResponse_ = new Map; + /** + * Function property that tracks whether client has + * been initialized by the server. + * @private {Function} + */ + this.boundOnInitialize_ = this.onInitialize_.bind(this); + + // Wait for an init message from the server. + window.addEventListener('message', this.boundOnInitialize_); + } + + /** + * Virtual method called when the client is initialized and it knows the + * server that it is communicating with. This method should be overwritten by + * subclasses which would like to know when initialization is done. + */ + onInitialized() {} + + // + // Private implementation: + // + + /** + * Handles initialization event sent from the server to establish + * communication. + * @private + * @param {!Event} event An event received when the initialization message is + * sent from the server. + */ + onInitialize_(event) { + if (!this.originMatchesFilter(event.origin)) { + console.error( + 'Initialization event received from non-authorized origin: ' + + event.origin); + return; + } + this.parentWindow_ = event.source; + this.parentWindow_.postMessage('init', this.serverOriginURLFilter_); + window.removeEventListener('message', this.boundOnInitialize_); + this.boundOnInitialize_ = null; + window.addEventListener('message', this.onMessage_.bind(this)); + this.onInitialized(); + } + + /** + * Determine if the specified server origin URL matches the origin filter. + * @param {!string} origin The origin URL to match with the filter. + * @return {boolean} whether the specified origin matches the filter. + */ + originMatchesFilter(origin) { + return (new URL(origin)).toString() === this.serverOriginURLFilter_; + } + + /** + * Handles postMessage events sent from the server. + * @param {Event} event An event received from the server via the postMessage + * API. + */ + onMessage_(event) { + if (!this.originMatchesFilter(event.origin)) { + console.error( + 'Message received from non-authorized origin: ' + event.origin); + return; + } + if (event.source !== this.parentWindow_) { + console.error('discarding event whose source is not the parent window'); + return; + } + if (!this.methodsAwaitingResponse_.has(event.data.methodId)) { + if (event.data === 'init') { + console.log('Received init message after initialization is complete.'); + this.parentWindow_.postMessage('init', this.serverOriginURLFilter_); + return; + } else { + console.error('discarding event method is not waiting for a response'); + return; + } + } + const method = this.methodsAwaitingResponse_.get(event.data.methodId); + this.methodsAwaitingResponse_.delete(event.data.methodId); + method(event.data.result); + } + + /** + * Converts a function call with arguments into a postMessage event + * and sends it to the server via the postMessage API. + * @param {string} fn The function to call. + * @param {!Array<Object>} args The arguments to pass to the function. + * @return {!Promise} A promise capturing the executing of the function. + */ + callApiFn(fn, args) { + const newMethodId = this.nextMethodId_++; + const promise = new Promise((resolve, reject) => { + if (!this.parentWindow_) { + reject('No parent window defined'); + } + this.parentWindow_.postMessage( + { + methodId: newMethodId, + fn: fn, + args: args, + }, + this.serverOriginURLFilter_); + + this.methodsAwaitingResponse_.set(newMethodId, resolve); + }); + return promise; + } +}
diff --git a/ui/webui/resources/js/post_message_api_server.js b/ui/webui/resources/js/post_message_api_server.js new file mode 100644 index 0000000..ffe1159 --- /dev/null +++ b/ui/webui/resources/js/post_message_api_server.js
@@ -0,0 +1,231 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Initialization retry wait in milliseconds (subject to exponential backoff). + */ +const INITIALIZATION_ATTEMPT_RETRY_WAIT_MS = 100; + +/** + * Maximum number of initialization attempts before resetting the + * initialization attempt cycle. With exponential backoff, this works out + * a maximum wait of 25 seconds on the 8th attempt before restarting. + */ +const MAX_INITIALIZATION_ATTEMPTS = 8; + +/** + * Class that provides the functionality for talking to a client + * over the PostMessageAPI. This should be subclassed and the + * methods provided in methodList should be implemented as methods + * of the subclass. + */ +export class PostMessageAPIServer { + constructor(clientElement, methodList, targetURL, messageOriginURLFilter) { + /** + * The Window type element to which this server will listen for messages, + * probably a <webview>, but also could be an <iframe> or a browser window + * object. + * @private @const {!Element} + */ + this.clientElement_ = clientElement; + + /** + * The guest URL embedded in the element above. Used for message targeting. + * This should be same as the URL loaded in the clientElement, i.e. the + * "src" attribute of a <webview>. + * @private @const {!URL} + */ + this.targetURL_ = new URL(targetURL); + + /** + * Incoming messages received from origin URLs without this prefix + * will not be accepted. This should be used to restrict the API access + * to the intended guest content. + * @private @const {!URL} + */ + this.messageOriginURLFilter_ = new URL(messageOriginURLFilter); + + /** + * Map that stores references to the methods implemented by the API. + * @private {!Map<string, function(!Array):?>} + */ + this.apiFns_ = new Map(); + + /** + * The ID of the timeout set before checking whether initialization has + * taken place yet. + * @private {number} + */ + this.initialization_timeout_id_ = 0; + + /** + * Indicates how many attempts have been made to initialize the channel. + * @private {number} + */ + this.numInitializationAttempts_ = 0; + + /** + * Indicates whether the communication channel between this server and the + * WebView has been established. + * @private {boolean} + */ + this.isInitialized_ = false; + + if (this.clientElement_.tagName === 'IFRAME') { + this.clientElement_.onload = this.onLoad_.bind(this); + } else { + this.clientElement_.addEventListener( + 'contentload', this.onLoad_.bind(this)); + } + + // Listen for events. + window.addEventListener('message', (event) => { + this.onMessage_(event); + }); + } + + /** + * Registers the specified method name with the specified + * function. + * + * @param {!string} methodName name of the method to register. + * @param {!function(!Array):?} method The function to associate with the + * name. + */ + registerMethod(methodName, method) { + this.apiFns_.set(methodName, method); + } + + /** + * Send initialization message to client element. + */ + initialize() { + if (this.isInitialized_ || + !this.originMatchesFilter(this.clientElement_.src)) { + return; + } + + if (this.numInitializationAttempts_ < MAX_INITIALIZATION_ATTEMPTS) { + // Tell the embedded webviews whose src matches our origin to initialize + // by sending it a message, which will include a handle for it to use to + // send messages back. + console.log( + 'Sending init message to guest content, attempt # :' + + this.numInitializationAttempts_); + + this.clientElement_.contentWindow.postMessage( + 'init', this.targetURL_.toString()); + + // Set timeout to check if initialization message has been received using + // exponential backoff. + this.initialization_timeout_id_ = setTimeout( + () => { + // If the timeout id is non-zero, that indicates that initialization + // hasn't succeeded yet, so try to initialize again. + this.initialize(); + }, + INITIALIZATION_ATTEMPT_RETRY_WAIT_MS * + (2 ** this.numInitializationAttempts_)); + + this.numInitializationAttempts_++; + } else { + // Exponential backoff has maxed out. Show error page if present. + this.onInitializationError(this.clientElement_.src); + } + } + + /** + * Virtual method to be overridden by implementations of this class to notify + * them that we were unable to initialize communication channel with the + * `clientElement_`. + * + * @param {!string} origin The origin URL that was not able to initialize + * communication. + */ + onInitializationError(origin) {} + + /** + * Determines if the specified origin matches the origin filter. + * @param {!string} origin The origin URL to match with the filter. + * @return {boolean} whether the specified origin matches the filter. + */ + originMatchesFilter(origin) { + const originURL = new URL(origin); + + // We allow the pathname portion of the URL to be a prefix filter, + // to permit for different paths communicating with this server. + return originURL.protocol === this.messageOriginURLFilter_.protocol && + originURL.host === this.messageOriginURLFilter_.host && + originURL.pathname.startsWith(this.messageOriginURLFilter_.pathname); + } + + /** + * Handles postMessage events from the client. + * @private + * @param {Event} event The postMessage event to handle. + */ + onMessage_(event) { + if (!this.originMatchesFilter(event.origin)) { + console.log('Message received from unauthorized origin: ' + event.origin); + return; + } + + if (event.data === 'init') { + if (this.initialization_timeout_id_) { + // Cancel the current init timeout, and signal to the initialization + // polling process that we have received an init message from the guest + // content, so it doesn't reschedule the timer. + clearTimeout(this.initialization_timeout_id_); + this.initialization_timeout_id_ = 0; + } + + this.isInitialized_ = true; + return; + } + // If we have gotten this far, we have received a message from a trusted + // origin, and we should try to process it. We can't gate this on whether + // the channel is initialized, because we can receive events out of order, + // and method calls can be received before the init event. Essentially, we + // should treat the channel as being potentially as soon as we send 'init' + // to the guest content. + const methodId = event.data.methodId; + const fn = event.data.fn; + const args = event.data.args || []; + + if (!this.apiFns_.has(fn)) { + console.error('Unknown function requested: ' + fn); + return; + } + + const sendMessage = (methodId, result) => { + this.clientElement_.contentWindow.postMessage( + { + methodId: methodId, + result: result, + }, + this.targetURL_.toString()); + }; + + // Some methods return a promise and some don't. If we have a promise, + // we resolve it first, otherwise we send the result directly (e.g., for + // void functions we send 'undefined'). + const result = this.apiFns_.get(fn)(args); + if (result instanceof Promise) { + result.then((result) => sendMessage(methodId, result)); + } else { + sendMessage(methodId, result); + } + } + + /** + * Reinitiates the connection when the content inside the clientElement + * reloads. + * @private + */ + onLoad_() { + this.numInitializationAttempts_ = 0; + this.isInitialized_ = false; + this.initialize(); + } +}
diff --git a/weblayer/browser/android/javatests/skew/expectations.txt b/weblayer/browser/android/javatests/skew/expectations.txt index f984a1ef..ab44db6 100644 --- a/weblayer/browser/android/javatests/skew/expectations.txt +++ b/weblayer/browser/android/javatests/skew/expectations.txt
@@ -5,22 +5,17 @@ # with versions less than or equal to $VERSION of the implementation. # # These lines are not comments! They define the set of known tags and other information. -# tags: [ client_lte_94 ] +# tags: [ client_lte_91 client_lte_94 ] # 'all' disables the test from any skew test. # tags: [ all ] # results: [ Skip ] # conflicts_allowed: True -crbug.com/1238481 [ all ] org.chromium.weblayer.test.TabTest#testRotationDoesntChangeVisibility [ Skip ] -crbug.com/1239026 [ all ] org.chromium.weblayer.test.TabCallbackTest#testDismissTransientUi [ Skip ] -crbug.com/1239028 [ all ] org.chromium.weblayer.test.MediaSessionTest#basic [ Skip ] -crbug.com/1239034 [ all ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlay [ Skip ] -crbug.com/1225662 [ all ] org.chromium.weblayer.test.NavigationTest#testDestroyTabWithModalDialog [ Skip ] -crbug.com/1239002 [ all ] org.chromium.weblayer.test.FullscreenSizeTest#testOsk [ Skip ] +# No real changes to weblayer APIs, changes should only affect chrome-internal behavior around +# navigation which the test depends on. +crbug.com/1196803 [ client_lte_91 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentWithNoRedirectInBrowserStartupInIncognitoBlockedWhenBackgroundLaunchesAllowedAndUserForbids [ Skip ] -# This test was flaky, the fix was in the associated html file which landed in -# 94. -crbug.com/1222694 [ client_lte_94 ] org.chromium.weblayer.test.FullscreenCallbackTest* [ Skip ] +crbug.com/1239002 [ all ] org.chromium.weblayer.test.FullscreenSizeTest#testOsk [ Skip ] # These tests were flaky, the fix was in the associated html files which landed # in 94. @@ -33,10 +28,15 @@ crbug.com/1191751 [ client_lte_94 ] org.chromium.weblayer.test.TabListCallbackTest#testDestroyTab [ Skip ] crbug.com/1191751 [ client_lte_94 ] org.chromium.weblayer.test.TabListCallbackTest#testActiveTabChanged [ Skip ] crbug.com/1191751 [ client_lte_94 ] org.chromium.weblayer.test.FindInPageTest#testHideOnNewTab [ Skip ] +crbug.com/1239034 [ client_lte_94 ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlay [ Skip ] +crbug.com/1239026 [ client_lte_94 ] org.chromium.weblayer.test.TabCallbackTest#testDismissTransientUi [ Skip ] +crbug.com/1191751 [ client_lte_94 ] org.chromium.weblayer.test.NavigationTest#testRepostConfirmation [ Skip ] +crbug.com/1225662 [ client_lte_94 ] org.chromium.weblayer.test.NavigationTest#testDestroyTabWithModalDialog [ Skip ] +crbug.com/1238481 [ client_lte_94 ] org.chromium.weblayer.test.TabTest#testRotationDoesntChangeVisibility [ Skip ] +crbug.com/1239028 [ client_lte_94 ] org.chromium.weblayer.test.MediaSessionTest#basic [ Skip ] # Bulk disable to get bot green. crbug.com/1191751 [ all ] org.chromium.weblayer.test.InputTypesTest* [ Skip ] -crbug.com/1191751 [ all ] org.chromium.weblayer.test.NavigationTest#testRepostConfirmation [ Skip ] crbug.com/1191751 [ all ] org.chromium.weblayer.test.TabCallbackTest#testScrollNotificationDirectionChange [ Skip ] crbug.com/1191751 [ all ] org.chromium.weblayer.test.TabTest#testBeforeUnload [ Skip ] crbug.com/1191751 [ all ] org.chromium.weblayer.test.DownloadCallbackTest#testBasic [ Skip ]
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/MediaSessionTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/MediaSessionTest.java index d187ca4..30f6cc6 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/MediaSessionTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/MediaSessionTest.java
@@ -23,7 +23,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.weblayer.shell.InstrumentationActivity; @@ -42,7 +41,6 @@ @Test @MediumTest @MinAndroidSdkLevel(Build.VERSION_CODES.M) - @DisabledTest(message = "crbug.com/1239028") public void basic() throws Throwable { mActivity = mActivityTestRule.launchShellWithUrl( mActivityTestRule.getTestDataURL("media_session.html"));
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java index 4df8bde..86317ab7 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java
@@ -1169,7 +1169,6 @@ // This is a regression test for https://crbug.com/1121388. @Test @SmallTest - @DisabledTest(message = "crbug.com/1225662") public void testDestroyTabWithModalDialog() throws Exception { // Load a page with a form. InstrumentationActivity activity =
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java index cf66eb1..605c730 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java
@@ -20,7 +20,6 @@ import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisableIf; -import org.chromium.base.test.util.DisabledTest; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils; import org.chromium.weblayer.ContextMenuParams; @@ -154,7 +153,6 @@ file.delete(); } - @MinWebLayerVersion(88) @Test @SmallTest @DisableIf. @@ -174,7 +172,6 @@ waitForFileExist(tempDownloadDirectory, "lorem_ipsum.txt"); } - @MinWebLayerVersion(88) @Test @SmallTest @DisableIf. @@ -196,7 +193,6 @@ @Test @SmallTest - @DisabledTest(message = "crbug.com/1239034") public void testTabModalOverlay() throws TimeoutException { String pageUrl = mActivityTestRule.getTestDataURL("alert.html"); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(pageUrl); @@ -230,7 +226,6 @@ @Test @SmallTest - @DisabledTest(message = "crbug.com/1239026") public void testDismissTransientUi() throws TimeoutException { String pageUrl = mActivityTestRule.getTestDataURL("alert.html"); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(pageUrl);
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java index 5791810..e5ead80 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java
@@ -12,7 +12,6 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CallbackHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.weblayer.Browser; import org.chromium.weblayer.Tab; @@ -161,7 +160,6 @@ @Test @SmallTest - @DisabledTest(message = "crbug.com/1239032") public void testCallbackInvokedWhenTabClosedViaWebContents() { initialize("new_tab_then_close.html");
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java index 2636353..6789c8e 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java
@@ -21,7 +21,6 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisabledTest; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.weblayer.ActionModeCallback; import org.chromium.weblayer.ActionModeItemType; @@ -266,8 +265,6 @@ @Test @SmallTest - @MinWebLayerVersion(88) // Bug fix in 88. - @DisabledTest(message = "crbug.com/1238481") // This is a regression test for https://crbug.com/1075744 . public void testRotationDoesntChangeVisibility() throws Exception { String url = mActivityTestRule.getTestDataURL("rotation.html"); @@ -289,7 +286,6 @@ @Test @SmallTest - @MinWebLayerVersion(88) public void setFloatingActionModeOverride() throws Exception { mActivity = mActivityTestRule.launchShellWithUrl("about:blank"); TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -306,7 +302,6 @@ @Test @SmallTest - @MinWebLayerVersion(88) // New API added in 88. public void testWillAutomaticallyReloadAfterCrash() throws Exception { mActivity = mActivityTestRule.launchShellWithUrl("about:blank"); Browser browser2 = TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java index d83b2c3..e2e1000 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java
@@ -512,7 +512,8 @@ .with(ModalDialogProperties.CONTROLLER, dialogController) .with(ModalDialogProperties.TITLE, resources, R.string.http_post_warning_title) - .with(ModalDialogProperties.MESSAGE, resources, R.string.http_post_warning) + .with(ModalDialogProperties.MESSAGE, + resources.getString(R.string.http_post_warning)) .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources, R.string.http_post_warning_resend) .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources,
diff --git a/weblayer/test/data/alert.html b/weblayer/test/data/alert.html index bd547ce..ce622e6 100644 --- a/weblayer/test/data/alert.html +++ b/weblayer/test/data/alert.html
@@ -1,10 +1,5 @@ <html> - <body> + <body onclick="window.alert('tab modal overlay');"> <p id='x'>XXXX</p> </body> - <script> - document.addEventListener('touchend', function(e) { - window.alert('tab modal overlay'); - }, false); - </script> </html>
diff --git a/weblayer/test/data/form.html b/weblayer/test/data/form.html index 4511dcf..a957bd1 100644 --- a/weblayer/test/data/form.html +++ b/weblayer/test/data/form.html
@@ -1,14 +1,9 @@ <html> - <body> + <body onclick="document.forms['form1'].submit();"> <form id="form1" action="simple_page.html" method="post"> <input type="text" name="name" value="Name"><br> <input type="text" name="address" value="Address"><br> <input type="text" name="city" value="City"><br> </form> </body> - <script> - document.addEventListener('touchend', function(e) { - document.forms['form1'].submit(); - }, false); - </script> </html>
diff --git a/weblayer/test/data/media_session.html b/weblayer/test/data/media_session.html index 565b383..23433240 100644 --- a/weblayer/test/data/media_session.html +++ b/weblayer/test/data/media_session.html
@@ -1,13 +1,12 @@ <html> - <body> - <p>Some text so the document is ready for input.</p> - </body> <script> - let audio = document.createElement('audio'); function playAudio() { + let audio = document.createElement('audio'); audio.src = 'test_audio.ogg'; audio.play(); } - document.addEventListener('touchend', function(e) { playAudio(); }, false); </script> + <body onclick="playAudio();"> + <p>Some text so the document is ready for input.</p> + </body> </html>
diff --git a/weblayer/test/data/new_tab_then_close.html b/weblayer/test/data/new_tab_then_close.html index f5c30a00..bc22379 100644 --- a/weblayer/test/data/new_tab_then_close.html +++ b/weblayer/test/data/new_tab_then_close.html
@@ -1,7 +1,4 @@ <html> - <body> - <p>some content</p> - </body> <script> var openedWindow = null; function openNewWindowOrClose() { @@ -12,8 +9,8 @@ openedWindow = null; } } - - document.addEventListener('touchend', - function(e) { openNewWindowOrClose(); }, false); </script> + <body onclick="openNewWindowOrClose();"> + <p>some content</p> + </body> </html>
diff --git a/weblayer/test/data/rotation.html b/weblayer/test/data/rotation.html index 4dbbade6..fc8ab98 100644 --- a/weblayer/test/data/rotation.html +++ b/weblayer/test/data/rotation.html
@@ -1,14 +1,23 @@ <html> - <body style="height:5000px"> - <p>A (mostly) empty page.</p> - </body> <script> var gotHide = false; var gotOrientationChange = false; + var attachedListeners = false; async function doRequestFullscreen() { return document.documentElement.requestFullscreen(); } async function toggleFullscreen() { + if (!attachedListeners) { + attachedListeners = true; + document.addEventListener("visibilitychange", function() { + if (document.visibilityState !== 'visible') { + gotHide = true; + } + }); + window.addEventListener("orientationchange", function() { + gotOrientationChange = true; + }); + } if (!document.fullscreenElement) { await doRequestFullscreen(); await screen.orientation.lock("landscape"); @@ -16,14 +25,8 @@ document.exitFullscreen(); } } - document.addEventListener("visibilitychange", function() { - if (document.visibilityState !== 'visible') { - gotHide = true; - } - }); - window.addEventListener("orientationchange", function() { - gotOrientationChange = true; - }); - document.addEventListener('touchend', function(e) { toggleFullscreen(); }, false); </script> + <body style="height:5000px" onclick="toggleFullscreen();"> + <p>A (mostly) empty page.</p> + </body> </html>