diff --git a/DEPS b/DEPS index 916e697..55086696 100644 --- a/DEPS +++ b/DEPS
@@ -162,11 +162,11 @@ # 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': '6e637472ebf3735e217df25c12d54930485a6e2d', + 'skia_revision': '8203a180ea5dd9b1989e2f99863330fa2df0ce72', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '69d20d247f62a3378d15ce0956ed8bf9665e6a44', + 'v8_revision': 'b2ea4d05947ae3eaa20c1fa9c53f8565cbc1d3b9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -174,7 +174,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '791ad7b8774a06c996467eb9e6e5137b1e4ef452', + 'angle_revision': 'fc58af4797084163af128d41cad22c331c6c1a3b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -213,7 +213,7 @@ # 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': 'cbee985a2bc14750ff850192f9ee8c1efe2bd7c7', + 'freetype_revision': '543a3b939df50e02e52b948f4c9c8ba63bf38059', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -225,7 +225,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '9f64c5cb4902fa548e2b52aba1c44951f9fdc071', + 'catapult_revision': '2b150bb56343878d44d1f846624ac2ae446939f2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -281,7 +281,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. - 'spv_tools_revision': '35d98be3bc87e34da31de5f484c57272078d57e8', + 'spv_tools_revision': '65e362b7ae2acb8aa5bd2ad516fb793961e673ee', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -842,7 +842,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '34facef633272772c11391c91c8ed1cadbe88cc9', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '03119fd61fdbe3a4e7ffe3e710bfa1f79b654322', 'condition': 'checkout_linux', }, @@ -1414,7 +1414,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'abaae129d9a0c6e1e092067e0b105475df43352e', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'ce6a0c8fb3f3a19caa797d5913b7e7c8ecf3ca9b', + Var('webrtc_git') + '/src.git' + '@' + 'a66395e72f9fc86873bf443579ec73c3d78af240', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1455,7 +1455,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0b598b6e8d5bdac89f62b6108f29c6de5e94ffc8', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a21128a7f4117ba7e62d380061011b9f91211719', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 09796532..9505421 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1289,7 +1289,8 @@ 'filepath': 'services/network/', }, 'nfc': { - 'filepath': '/nfc/', + 'filepath': 'services/device/nfc/|'\ + 'third_party/blink/renderer/modules/nfc/' }, 'notification_scheduler': { 'filepath': 'chrome/browser/notifications/proto/|'\ @@ -2335,6 +2336,7 @@ 'generic_sensor': ['juncai+watch@chromium.org', 'mattreynolds+watch@chromium.org', 'raphael.kubo.da.costa@intel.com', + 'rijubrata.bhaumik@intel.com', 'timvolodine@chromium.org', 'wanming.lin@intel.com'], 'geolocation': ['mattreynolds+watch@chromium.org'], @@ -2446,7 +2448,8 @@ 'net_websockets': ['ricea+watch@chromium.org'], 'netinfo': ['jkarlin+watch@chromium.org'], 'network_service': ['network-service-reviews@chromium.org'], - 'nfc': ['mattreynolds+watch@chromium.org'], + 'nfc': ['mattreynolds+watch@chromium.org', + 'rijubrata.bhaumik@intel.com'], 'notification_scheduler': ['xingliu+watch@chromium.org'], 'notifications': ['peter@chromium.org'], 'nqe': ['tbansal+watch-nqe@chromium.org'], @@ -2639,7 +2642,8 @@ 'version_assembly': ['caitkp+watch@chromium.org', 'gab+watch@chromium.org'], 'video': ['posciak+watch@chromium.org'], - 'video_capture': ['chfremer+watch@chromium.org'], + 'video_capture': ['chfremer+watch@chromium.org', + 'rijubrata.bhaumik@intel.com'], 'video_gpu': ['acourbot+watch@chromium.org'], 'virtual_keyboard': ['dfaden+virtualkb@google.com', 'yhanada+watchvk@chromium.org',
diff --git a/ash/accessibility/accessibility_panel_layout_manager.cc b/ash/accessibility/accessibility_panel_layout_manager.cc index 03d2462..0700a9d 100644 --- a/ash/accessibility/accessibility_panel_layout_manager.cc +++ b/ash/accessibility/accessibility_panel_layout_manager.cc
@@ -112,13 +112,6 @@ } else if (panel_state_ == AccessibilityPanelState::FULL_WIDTH) { bounds.set_x(0); bounds.set_width(root_window->bounds().width()); - - // TODO(isandrk, crbug.com/959786): Temporary fix that prevents ChromeVox - // panel from showing up in locked fullscreen mode (the panel was enabling - // an escape from locked mode crbug.com/957950). Remove once a more proper - // fix exists. - if (Shell::Get()->screen_pinning_controller()->IsPinned()) - bounds.set_height(0); } // If a fullscreen browser window is open, give the panel a height of 0
diff --git a/ash/keyboard/ui/keyboard_ui_controller_unittest.cc b/ash/keyboard/ui/keyboard_ui_controller_unittest.cc index 96022ee..bd4d515 100644 --- a/ash/keyboard/ui/keyboard_ui_controller_unittest.cc +++ b/ash/keyboard/ui/keyboard_ui_controller_unittest.cc
@@ -146,7 +146,6 @@ ~KeyboardUIControllerTest() override = default; void SetUp() override { - ui::SetUpInputMethodFactoryForTesting(); aura::test::AuraTestBase::SetUp(); new wm::DefaultActivationClient(root_window()); focus_controller_ = std::make_unique<TestFocusController>(root_window()); @@ -272,6 +271,7 @@ std::unique_ptr<ui::TextInputClient> test_text_input_client_; bool keyboard_disabled_ = false; wm::DefaultScreenPositionClient screen_position_client_; + ui::ScopedTestInputMethodFactory scoped_test_input_method_factory_; DISALLOW_COPY_AND_ASSIGN(KeyboardUIControllerTest); };
diff --git a/base/task/promise/abstract_promise_unittest.cc b/base/task/promise/abstract_promise_unittest.cc index c7f23d8..ea8d31fd 100644 --- a/base/task/promise/abstract_promise_unittest.cc +++ b/base/task/promise/abstract_promise_unittest.cc
@@ -2418,7 +2418,7 @@ })); base::PostTask(FROM_HERE, {base::ThreadPool()}, - base::Bind( + base::BindOnce( [](scoped_refptr<AbstractPromise> p2) { p2->emplace(Rejected<void>()); },
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index ffd6ddcb..4664db4 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8903492066113915536 \ No newline at end of file +8903431735416173664 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index e9fe6869..1657182 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8903489678245509728 \ No newline at end of file +8903432862385356064 \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantSnackbar.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantSnackbar.java index a1de3c8..5c868433 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantSnackbar.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantSnackbar.java
@@ -13,8 +13,6 @@ * A simple UNDO snackbar with a delay. */ class AssistantSnackbar { - private static final int DELAY_MS = 5_000; - interface Callback { /** * Called once the snackbar is gone, after the delay has passed or after the user clicked @@ -26,7 +24,8 @@ } /** Shows the snackbar and reports the result to {@code callback}. */ - static SnackbarController show(ChromeActivity activity, String message, Callback callback) { + static SnackbarController show( + ChromeActivity activity, int delayMs, String message, Callback callback) { SnackbarController controller = new SnackbarController() { @Override public void onAction(Object actionData) { @@ -43,7 +42,7 @@ Snackbar.UMA_AUTOFILL_ASSISTANT_STOP_UNDO) .setAction(activity.getString(R.string.undo), /* actionData= */ null); snackBar.setSingleLine(false); - snackBar.setDuration(DELAY_MS); + snackBar.setDuration(delayMs); activity.getSnackbarManager().showSnackbar(snackBar); return controller; }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index cdb4b685..f3adcd3 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -202,8 +202,9 @@ } @CalledByNative - private void showSnackbar(String message) { - mSnackbarController = AssistantSnackbar.show(mActivity, message, this::safeSnackbarResult); + private void showSnackbar(int delayMs, String message) { + mSnackbarController = + AssistantSnackbar.show(mActivity, delayMs, message, this::safeSnackbarResult); } private void dismissSnackbar() {
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java index a648f8d..d4a629c 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayCoordinator.java
@@ -59,6 +59,12 @@ } else if (AssistantOverlayModel.HIGHLIGHT_BORDER_COLOR == propertyKey) { mDrawable.setHighlightBorderColor( model.get(AssistantOverlayModel.HIGHLIGHT_BORDER_COLOR)); + } else if (AssistantOverlayModel.TAP_TRACKING_COUNT == propertyKey) { + mEventFilter.setTapTrackingCount( + model.get(AssistantOverlayModel.TAP_TRACKING_COUNT)); + } else if (AssistantOverlayModel.TAP_TRACKING_DURATION_MS == propertyKey) { + mEventFilter.setTapTrackingDurationMs( + model.get(AssistantOverlayModel.TAP_TRACKING_DURATION_MS)); } }); }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java index d4d9407..27799bd 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java
@@ -26,13 +26,6 @@ * Filters gestures that happen on the overlay. */ class AssistantOverlayEventFilter extends EventFilter { - /** - * Complain after there's been {@link TAP_TRACKING_COUNT} taps within - * {@link @TAP_TRACKING_DURATION_MS} in the unallowed area. - */ - private static final int TAP_TRACKING_COUNT = 3; - private static final long TAP_TRACKING_DURATION_MS = 5_000; - /** A mode that describes what's happening to the current gesture. */ @Retention(RetentionPolicy.SOURCE) @IntDef({GestureMode.NONE, GestureMode.TRACKING, GestureMode.FORWARDING}) @@ -53,6 +46,19 @@ private View mCompositorView; /** + * Complain after there's been {@link #mTapTrackingCount} taps within + * {@link #mTapTrackingDurationMs} in the unallowed area. + * + * <p>The feature is disabled unless both are positive. + */ + private int mTapTrackingCount; + + /** + * How long to wait before resetting the tracking duration. + */ + private long mTapTrackingDurationMs; + + /** * When in partial mode, let through scroll and pinch/zoom. * * Let through all events in {@link mTouchableArea}. @@ -147,6 +153,14 @@ mDelegate = delegate; } + void setTapTrackingCount(int count) { + mTapTrackingCount = count; + } + + void setTapTrackingDurationMs(long durationMs) { + mTapTrackingDurationMs = durationMs; + } + /** * Set the touchable area. This only applies if current state is AssistantOverlayState.PARTIAL. */ @@ -327,15 +341,17 @@ /** Considers whether to let the client know about unexpected taps. */ private void onUnexpectedTap(MotionEvent e) { + if (mTapTrackingCount <= 0 || mTapTrackingDurationMs <= 0) return; + long eventTimeMs = e.getEventTime(); for (Iterator<Long> iter = mUnexpectedTapTimes.iterator(); iter.hasNext();) { Long timeMs = iter.next(); - if ((eventTimeMs - timeMs) >= TAP_TRACKING_DURATION_MS) { + if ((eventTimeMs - timeMs) >= mTapTrackingDurationMs) { iter.remove(); } } mUnexpectedTapTimes.add(eventTimeMs); - if (mUnexpectedTapTimes.size() == TAP_TRACKING_COUNT && mDelegate != null) { + if (mUnexpectedTapTimes.size() == mTapTrackingCount && mDelegate != null) { mDelegate.onUnexpectedTaps(); mUnexpectedTapTimes.clear(); }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java index 492a744..64f4430a 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java
@@ -40,9 +40,15 @@ public static final WritableObjectPropertyKey<Integer> HIGHLIGHT_BORDER_COLOR = new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<Integer> TAP_TRACKING_COUNT = + new WritableObjectPropertyKey<>(); + + public static final WritableObjectPropertyKey<Long> TAP_TRACKING_DURATION_MS = + new WritableObjectPropertyKey<>(); + public AssistantOverlayModel() { super(STATE, TOUCHABLE_AREA, RESTRICTED_AREA, VISUAL_VIEWPORT, DELEGATE, BACKGROUND_COLOR, - HIGHLIGHT_BORDER_COLOR); + HIGHLIGHT_BORDER_COLOR, TAP_TRACKING_COUNT, TAP_TRACKING_DURATION_MS); } @CalledByNative @@ -89,6 +95,12 @@ return setColor(HIGHLIGHT_BORDER_COLOR, colorString); } + @CalledByNative + private void setTapTracking(int count, long durationMs) { + set(TAP_TRACKING_COUNT, count); + set(TAP_TRACKING_DURATION_MS, durationMs); + } + /** * Sets the given color property. *
diff --git a/chrome/android/java/res/layout/password_entry_editor.xml b/chrome/android/java/res/layout/password_entry_editor.xml index 5bc781d..e0ba7b8e 100644 --- a/chrome/android/java/res/layout/password_entry_editor.xml +++ b/chrome/android/java/res/layout/password_entry_editor.xml
@@ -30,7 +30,8 @@ android:layout_height="wrap_content" android:imeOptions="flagNoExtractUi" android:inputType="text" - android:hint="@string/password_entry_viewer_site_title"/> + android:hint="@string/password_entry_viewer_site_title" + android:enabled="false"/> </org.chromium.chrome.browser.widget.ChromeTextInputLayout> <!-- Username -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/OnboardingDialogBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/OnboardingDialogBridge.java index a94b4fc0..b1e69d4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/OnboardingDialogBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/OnboardingDialogBridge.java
@@ -53,12 +53,16 @@ case DialogDismissalCause.POSITIVE_BUTTON_CLICKED: nativeOnboardingAccepted(mNativeOnboardingDialogView); return; + case DialogDismissalCause.NEGATIVE_BUTTON_CLICKED: + nativeOnboardingRejected(mNativeOnboardingDialogView); + return; default: - nativeOnboardingRejected(mNativeOnboardingDialogView); + nativeOnboardingAborted(mNativeOnboardingDialogView); } } private native void nativeOnboardingAccepted(long nativeOnboardingDialogView); private native void nativeOnboardingRejected(long nativeOnboardingDialogView); + private native void nativeOnboardingAborted(long nativeOnboardingDialogView); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java index f243cabd..fbbe56e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallMessageHandler.java
@@ -47,9 +47,11 @@ try { ContextUtils.getApplicationContext().startActivity(dialIntent); + ClickToCallUma.recordDialerPresent(true); ClickToCallUma.recordDialerShown(TextUtils.isEmpty(phoneNumber)); } catch (ActivityNotFoundException activityNotFound) { // TODO(crbug.com/996644): Add error dialog when no dialer app is available. + ClickToCallUma.recordDialerPresent(false); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java index 0a0fe0b..17008a3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/click_to_call/ClickToCallUma.java
@@ -113,6 +113,11 @@ .record(emptyPhoneNumber); } + public static void recordDialerPresent(boolean isDialerPresent) { + new CachedMetrics.BooleanHistogramSample("Sharing.ClickToCallDialerPresent") + .record(isDialerPresent); + } + public static void recordMessageReceived() { new CachedMetrics .EnumeratedHistogramSample(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java index 17e7dbb..6de0de7f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java
@@ -43,6 +43,7 @@ import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.ProfileDataSource; import org.chromium.components.signin.test.util.AccountHolder; +import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.UiDisableIf; @@ -65,12 +66,12 @@ public final ChromeActivityTestRule<ChromeActivity> mActivityTestRule = new ChromeActivityTestRule<>(ChromeActivity.class); - private final FakeAccountManagerDelegate mAccountManagerDelegate = - new FakeAccountManagerDelegate(FakeAccountManagerDelegate.ENABLE_PROFILE_DATA_SOURCE); + @Rule + public final AccountManagerTestRule mAccountManagerTestRule = + new AccountManagerTestRule(FakeAccountManagerDelegate.ENABLE_PROFILE_DATA_SOURCE); @Before public void setUp() throws Exception { - AccountManagerFacade.overrideAccountManagerFacadeForTests(mAccountManagerDelegate); mActivityTestRule.startMainActivityFromLauncher(); } @@ -172,11 +173,9 @@ private void addTestAccount() { Account account = AccountManagerFacade.createAccountFromName(TEST_ACCOUNT_NAME); AccountHolder.Builder accountHolder = AccountHolder.builder(account).alwaysAccept(true); - mAccountManagerDelegate.addAccountHolderBlocking(accountHolder.build()); ProfileDataSource.ProfileData profileData = new ProfileDataSource.ProfileData(TEST_ACCOUNT_NAME, null, TEST_FULL_NAME, null); - TestThreadUtils.runOnUiThreadBlocking( - () -> mAccountManagerDelegate.setProfileData(TEST_ACCOUNT_NAME, profileData)); + mAccountManagerTestRule.addAccount(accountHolder.build(), profileData); } private static class IntentCallbackHelper implements IntentCallback, Closeable {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogTest.java index 8fd899f..4994c47 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogTest.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.password_manager; import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.Espresso.pressBack; import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.ViewMatchers.assertThat; @@ -90,20 +91,27 @@ @Test @SmallTest - public void testOkPressedCallback() { + public void testAcceptedCallback() { onView(withId(R.id.positive_button)).perform(click()); verify(mOnClick).onResult(DialogDismissalCause.POSITIVE_BUTTON_CLICKED); } @Test @SmallTest - public void testCancelPressedCallback() { + public void testRejectedCallback() { onView(withId(R.id.negative_button)).perform(click()); verify(mOnClick).onResult(DialogDismissalCause.NEGATIVE_BUTTON_CLICKED); } @Test @SmallTest + public void testDismissedCallbackBackButton() { + pressBack(); + verify(mOnClick).onResult(DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE); + } + + @Test + @SmallTest public void testSettingImageVisibility() { TestThreadUtils.runOnUiThreadBlocking(() -> { mModel.set(ILLUSTRATION_VISIBLE, false); }); onView(withId(R.id.password_manager_dialog_illustration))
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java index 4023eec..00addb3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java
@@ -25,7 +25,7 @@ import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.test.util.AccountHolder; -import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; +import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.components.sync.AndroidSyncSettings; import org.chromium.components.sync.test.util.MockSyncContentResolverDelegate; import org.chromium.content_public.browser.test.NativeLibraryTestRule; @@ -42,13 +42,15 @@ @Rule public NativeLibraryTestRule mActivityTestRule = new NativeLibraryTestRule(); + @Rule + public AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule(); + private MainPreferences mMainPreferences; private ChromeBasePreference mPasswordsPref; private Context mContext; private MockSyncContentResolverDelegate mSyncContentResolverDelegate; private String mAuthority; private Account mAccount; - private FakeAccountManagerDelegate mAccountManager; @Before public void setUp() throws Exception { @@ -67,12 +69,9 @@ } private void setupTestAccount() { - mAccountManager = new FakeAccountManagerDelegate( - FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE); - AccountManagerFacade.overrideAccountManagerFacadeForTests(mAccountManager); mAccount = AccountManagerFacade.createAccountFromName("account@example.com"); AccountHolder.Builder accountHolder = AccountHolder.builder(mAccount).alwaysAccept(true); - mAccountManager.addAccountHolderBlocking(accountHolder.build()); + mAccountManagerTestRule.addAccount(accountHolder.build()); } @After
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java index ef468f3..3e6aada2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
@@ -22,7 +22,7 @@ import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.OAuth2TokenService; import org.chromium.components.signin.test.util.AccountHolder; -import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; +import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.content_public.browser.test.NativeLibraryTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -39,6 +39,9 @@ @Rule public NativeLibraryTestRule mActivityTestRule = new NativeLibraryTestRule(); + @Rule + public AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule(); + private static final Account TEST_ACCOUNT1 = AccountManagerFacade.createAccountFromName("foo@gmail.com"); private static final Account TEST_ACCOUNT2 = @@ -49,19 +52,12 @@ AccountHolder.builder(TEST_ACCOUNT2).alwaysAccept(true).build(); private OAuth2TokenService mOAuth2TokenService; - private FakeAccountManagerDelegate mAccountManager; private ChromeSigninController mChromeSigninController; @Before public void setUp() { mapAccountNamesToIds(); - // loadNativeLibraryAndInitBrowserProcess will access AccountManagerFacade, so it should - // be initialized beforehand. - mAccountManager = new FakeAccountManagerDelegate( - FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE); - AccountManagerFacade.overrideAccountManagerFacadeForTests(mAccountManager); - mActivityTestRule.loadNativeLibraryAndInitBrowserProcess(); // Make sure there is no account signed in yet. @@ -113,12 +109,12 @@ } private void addAccount(AccountHolder accountHolder) { - mAccountManager.addAccountHolderBlocking(accountHolder); + mAccountManagerTestRule.addAccount(accountHolder); TestThreadUtils.runOnUiThreadBlocking(this::seedAccountTrackerService); } private void removeAccount(AccountHolder accountHolder) { - mAccountManager.removeAccountHolderBlocking(accountHolder); + mAccountManagerTestRule.removeAccount(accountHolder); TestThreadUtils.runOnUiThreadBlocking(this::seedAccountTrackerService); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java index a872320c..58d314632 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceTest.java
@@ -11,6 +11,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -20,7 +21,7 @@ import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.OAuth2TokenService; import org.chromium.components.signin.test.util.AccountHolder; -import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; +import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.Arrays; @@ -30,11 +31,13 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class OAuth2TokenServiceTest { private AdvancedMockContext mContext; - private FakeAccountManagerDelegate mAccountManager; + + @Rule + public AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule(); /** * Class handling GetAccessToken callbacks and providing a blocking {@link - * getToken}. + * #getToken()}. */ class GetAccessTokenCallbackForTest implements OAuth2TokenService.GetAccessTokenCallback { private String mToken; @@ -69,9 +72,6 @@ @Before public void setUp() throws Exception { mContext = new AdvancedMockContext(InstrumentationRegistry.getTargetContext()); - mAccountManager = new FakeAccountManagerDelegate( - FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE); - AccountManagerFacade.overrideAccountManagerFacadeForTests(mAccountManager); } @After @@ -93,7 +93,7 @@ public void testGetAccountsOneAccountRegistered() { Account account1 = AccountManagerFacade.createAccountFromName("foo@gmail.com"); AccountHolder accountHolder1 = AccountHolder.builder(account1).build(); - mAccountManager.addAccountHolderBlocking(accountHolder1); + mAccountManagerTestRule.addAccount(accountHolder1); String[] sysAccounts = OAuth2TokenService.getSystemAccountNames(); Assert.assertEquals("There should be one registered account", 1, sysAccounts.length); @@ -109,10 +109,10 @@ public void testGetAccountsTwoAccountsRegistered() { Account account1 = AccountManagerFacade.createAccountFromName("foo@gmail.com"); AccountHolder accountHolder1 = AccountHolder.builder(account1).build(); - mAccountManager.addAccountHolderBlocking(accountHolder1); + mAccountManagerTestRule.addAccount(accountHolder1); Account account2 = AccountManagerFacade.createAccountFromName("bar@gmail.com"); AccountHolder accountHolder2 = AccountHolder.builder(account2).build(); - mAccountManager.addAccountHolderBlocking(accountHolder2); + mAccountManagerTestRule.addAccount(accountHolder2); String[] sysAccounts = OAuth2TokenService.getSystemAccountNames(); Assert.assertEquals("There should be one registered account", 2, sysAccounts.length); @@ -152,7 +152,7 @@ .hasBeenAccepted(scope, true) .authToken(scope, expectedToken) .build(); - mAccountManager.addAccountHolderBlocking(accountHolder); + mAccountManagerTestRule.addAccount(accountHolder); GetAccessTokenCallbackForTest callback = new GetAccessTokenCallbackForTest(); TestThreadUtils.runOnUiThreadBlocking( () -> { OAuth2TokenService.getAccessToken(account, scope, callback); });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java index 52373d4..afa1efb3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java
@@ -10,6 +10,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -20,30 +21,26 @@ import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.test.util.AccountHolder; -import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; +import org.chromium.components.signin.test.util.AccountManagerTestRule; /** * Instrumentation tests for {@link SigninHelper}. */ @RunWith(ChromeJUnit4ClassRunner.class) public class SigninHelperTest { - private FakeAccountManagerDelegate mAccountManager; + @Rule + public AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule(); + private MockChangeEventChecker mEventChecker; @Before public void setUp() { - SigninHelper.resetSharedPrefs(); mEventChecker = new MockChangeEventChecker(); - - mAccountManager = new FakeAccountManagerDelegate( - FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE); - AccountManagerFacade.overrideAccountManagerFacadeForTests(mAccountManager); } @After public void tearDown() { AccountManagerFacade.resetAccountManagerFacadeForTests(); - SigninHelper.resetSharedPrefs(); } @Test @@ -146,7 +143,7 @@ mEventChecker.insertRenameEvent("D", "A"); // Looped. Account account = AccountManagerFacade.createAccountFromName("D"); AccountHolder accountHolder = AccountHolder.builder(account).build(); - mAccountManager.addAccountHolderBlocking(accountHolder); + mAccountManagerTestRule.addAccount(accountHolder); SigninHelper.updateAccountRenameData(mEventChecker); Assert.assertEquals("D", getNewSignedInAccountName()); }
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index b799057..df184bb 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -4033,4 +4033,7 @@ <message name="IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_SUBTITLE" desc="Subtitle on the security token PIN input dialog during the SAML user sign-in."> Provide the PIN that’s associated with your smart card. </message> + <message name="IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_TRY_AGAIN" desc="Message asking the user to try again in the security token PIN input dialog during the SAML sign-in."> + Please try again. + </message> </grit-part>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_TRY_AGAIN.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_TRY_AGAIN.png.sha1 new file mode 100644 index 0000000..5e1a607 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_TRY_AGAIN.png.sha1
@@ -0,0 +1 @@ +74fef5f1631f0d9c9015871db3b9d312ca70a345 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 76e0c76..9ec7b9f 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2994,6 +2994,7 @@ "background/background_contents_service_observer.h", "badging/badge_manager.cc", "badging/badge_manager.h", + "badging/badge_manager_delegate.cc", "badging/badge_manager_delegate.h", "badging/badge_manager_factory.cc", "badging/badge_manager_factory.h",
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index a82b7e43..49d1315 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -36,6 +36,7 @@ #include "chrome/common/channel_info.h" #include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill/core/browser/data_model/credit_card.h" +#include "components/autofill_assistant/browser/client_settings.h" #include "components/autofill_assistant/browser/controller.h" #include "components/autofill_assistant/browser/features.h" #include "components/autofill_assistant/browser/metrics.h" @@ -58,10 +59,6 @@ namespace { -// How long to leave the UI showing after AA has stopped. -static constexpr base::TimeDelta kGracefulShutdownDelay = - base::TimeDelta::FromSeconds(5); - std::vector<float> ToFloatVector(const std::vector<RectF>& areas) { std::vector<float> flattened; for (const auto& rect : areas) { @@ -145,6 +142,8 @@ Java_AssistantModel_setWebContents(env, GetModel(), java_web_contents); Java_AssistantCollectUserDataModel_setWebContents( env, GetCollectUserDataModel(), java_web_contents); + OnClientSettingsChanged(ui_delegate_->GetClientSettings()); + if (ui_delegate->GetState() != AutofillAssistantState::INACTIVE) { // The UI was created for an existing Controller. OnStatusMessageChanged(ui_delegate->GetStatusMessage()); @@ -254,16 +253,21 @@ // make sure user sees the error message. ExpandBottomSheet(); - - // Keep showing the current UI for a while, without getting updates from - // the controller, then shut down the UI portion. - // - // A controller might still get attached while the timer is running, - // canceling the destruction. - destroy_timer_ = std::make_unique<base::OneShotTimer>(); - destroy_timer_->Start(FROM_HERE, kGracefulShutdownDelay, - base::BindOnce(&UiControllerAndroid::DestroySelf, - weak_ptr_factory_.GetWeakPtr())); + { + const ClientSettings& settings = ui_delegate_->GetClientSettings(); + if (settings.enable_graceful_shutdown) { + // Keep showing the current UI for a while, without getting updates + // from the controller, then shut down the UI portion. + // + // A controller might still get attached while the timer is running, + // canceling the destruction. + destroy_timer_ = std::make_unique<base::OneShotTimer>(); + destroy_timer_->Start( + FROM_HERE, settings.graceful_shutdown_delay, + base::BindOnce(&UiControllerAndroid::DestroySelf, + weak_ptr_factory_.GetWeakPtr())); + } + } Detach(); return; @@ -367,8 +371,14 @@ client_->Shutdown(reason); } -void UiControllerAndroid::ShowSnackbar(const std::string& message, +void UiControllerAndroid::ShowSnackbar(base::TimeDelta delay, + const std::string& message, base::OnceCallback<void()> action) { + if (delay.is_zero()) { + std::move(action).Run(); + return; + } + JNIEnv* env = AttachCurrentThread(); auto jmodel = GetModel(); if (!Java_AssistantModel_getVisible(env, jmodel)) { @@ -379,7 +389,8 @@ SetVisible(false); snackbar_action_ = std::move(action); Java_AutofillAssistantUiController_showSnackbar( - env, java_object_, base::android::ConvertUTF8ToJavaString(env, message)); + env, java_object_, static_cast<jint>(delay.InMilliseconds()), + base::android::ConvertUTF8ToJavaString(env, message)); } void UiControllerAndroid::SnackbarResult( @@ -569,7 +580,8 @@ } // Cancel, with a snackbar to allow UNDO. - ShowSnackbar(l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_STOPPED), + ShowSnackbar(ui_delegate_->GetClientSettings().cancel_delay, + l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_STOPPED), base::BindOnce(&UiControllerAndroid::OnCancel, weak_ptr_factory_.GetWeakPtr(), action_index, std::move(trigger_context))); @@ -636,7 +648,13 @@ } void UiControllerAndroid::OnUnexpectedTaps() { - ShowSnackbar(l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_MAYBE_GIVE_UP), + if (!ui_delegate_) { + Shutdown(Metrics::DropOutReason::OVERLAY_STOP); + return; + } + + ShowSnackbar(ui_delegate_->GetClientSettings().tap_shutdown_delay, + l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_MAYBE_GIVE_UP), base::BindOnce(&UiControllerAndroid::Shutdown, weak_ptr_factory_.GetWeakPtr(), Metrics::DropOutReason::OVERLAY_STOP)); @@ -872,6 +890,13 @@ } } +void UiControllerAndroid::OnClientSettingsChanged( + const ClientSettings& settings) { + Java_AssistantOverlayModel_setTapTracking( + AttachCurrentThread(), GetOverlayModel(), settings.tap_count, + settings.tap_tracking_duration.InMilliseconds()); +} + void UiControllerAndroid::OnCounterChanged(int input_index, int counter_index, int value) { @@ -899,7 +924,7 @@ return; } - const DetailsProto& proto = details->detailsProto(); + const DetailsProto& proto = details->details_proto(); const DetailsChangesProto& changes = details->changes(); auto jdetails = Java_AssistantDetails_create( @@ -917,7 +942,7 @@ proto.show_image_placeholder(), base::android::ConvertUTF8ToJavaString(env, proto.total_price_label()), base::android::ConvertUTF8ToJavaString(env, proto.total_price()), - base::android::ConvertUTF8ToJavaString(env, details->GetDatetime()), + base::android::ConvertUTF8ToJavaString(env, details->datetime()), proto.datetime().date().year(), proto.datetime().date().month(), proto.datetime().date().day(), proto.datetime().time().hour(), proto.datetime().time().minute(), proto.datetime().time().second(),
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index 6ff3bfc..c317f63 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -27,6 +27,7 @@ #include "components/autofill_assistant/browser/user_action.h" namespace autofill_assistant { +struct ClientSettings; // Starts and owns the UI elements required to display AA. // @@ -101,6 +102,7 @@ ConfigureBottomSheetProto::PeekMode peek_mode) override; void OnOverlayColorsChanged(const UiDelegate::OverlayColors& colors) override; void OnFormChanged(const FormProto* form) override; + void OnClientSettingsChanged(const ClientSettings& settings) override; // Called by AssistantOverlayDelegate: void OnUnexpectedTaps(); @@ -191,7 +193,8 @@ // Hide the UI, show a snackbar with an undo button, and execute the given // action after a short delay unless the user taps the undo button. - void ShowSnackbar(const std::string& message, + void ShowSnackbar(base::TimeDelta delay, + const std::string& message, base::OnceCallback<void()> action); void OnCancel(int action_index, std::unique_ptr<TriggerContext> context);
diff --git a/chrome/browser/badging/badge_manager.cc b/chrome/browser/badging/badge_manager.cc index 5574b38..cdbe10e 100644 --- a/chrome/browser/badging/badge_manager.cc +++ b/chrome/browser/badging/badge_manager.cc
@@ -9,11 +9,13 @@ #include "base/i18n/number_formatting.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "chrome/browser/badging/badge_manager_delegate.h" #include "chrome/browser/badging/badge_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "ui/base/l10n/l10n_util.h" @@ -27,23 +29,15 @@ namespace badging { -std::string GetBadgeString(base::Optional<uint64_t> badge_content) { - if (!badge_content) - return "•"; - - if (badge_content > kMaxBadgeContent) { - return base::UTF16ToUTF8(l10n_util::GetStringFUTF16( - IDS_SATURATED_BADGE_CONTENT, base::FormatNumber(kMaxBadgeContent))); - } - - return base::UTF16ToUTF8(base::FormatNumber(badge_content.value())); -} - BadgeManager::BadgeManager(Profile* profile) { #if defined(OS_MACOSX) - SetDelegate(std::make_unique<BadgeManagerDelegateMac>(profile)); + SetDelegate(std::make_unique<BadgeManagerDelegateMac>( + profile, this, + &web_app::WebAppProviderBase::GetProviderBase(profile)->registrar())); #elif defined(OS_WIN) - SetDelegate(std::make_unique<BadgeManagerDelegateWin>(profile)); + SetDelegate(std::make_unique<BadgeManagerDelegateWin>( + profile, this, + &web_app::WebAppProviderBase::GetProviderBase(profile)->registrar())); #endif } @@ -66,79 +60,107 @@ std::move(context)); } -void BadgeManager::UpdateAppBadge(const base::Optional<std::string>& app_id, - base::Optional<uint64_t> content) { - // Badge content should never be 0 (it should be translated into a clear). - DCHECK_NE(content.value_or(1), 0u); +bool BadgeManager::HasMoreSpecificBadgeForUrl(const GURL& scope, + const GURL& url) { + return MostSpecificBadgeForScope(url).spec().size() > scope.spec().size(); +} - if (!app_id) { - BadgeChangeIgnored(); +base::Optional<BadgeManager::BadgeValue> BadgeManager::GetBadgeValue( + const GURL& scope) { + const GURL& most_specific = MostSpecificBadgeForScope(scope); + if (most_specific == GURL::EmptyGURL()) + return base::nullopt; + + return base::make_optional(badged_scopes_[most_specific]); +} + +void BadgeManager::SetBadgeForTesting(const GURL& scope, BadgeValue value) { + UpdateBadge(scope, value); +} + +void BadgeManager::ClearBadgeForTesting(const GURL& scope) { + UpdateBadge(scope, base::nullopt); +} + +void BadgeManager::UpdateBadge(const GURL& scope, + base::Optional<BadgeValue> value) { + if (!value) + badged_scopes_.erase(scope); + else + badged_scopes_[scope] = value.value(); + + if (!delegate_) + return; + + delegate_->OnBadgeUpdated(scope); +} + +void BadgeManager::SetBadge(const GURL& scope, + blink::mojom::BadgeValuePtr mojo_value) { + if (mojo_value->is_number() && mojo_value->get_number() == 0) { + mojo::ReportBadMessage( + "|value| should not be zero when it is |number| (ClearBadge should be " + "called instead)!"); return; } - badged_apps_[app_id.value()] = content; - - if (!delegate_) + if (!ScopeIsValidBadgeTarget(receivers_.current_context(), scope)) return; - delegate_->OnBadgeSet(app_id.value(), content); + // Convert the mojo badge representation into a BadgeManager::BadgeValue. + BadgeValue value = mojo_value->is_flag() + ? base::nullopt + : base::make_optional(mojo_value->get_number()); + UpdateBadge(scope, base::make_optional(value)); } -void BadgeManager::ClearAppBadge(const base::Optional<std::string>& app_id) { - if (!app_id) { - BadgeChangeIgnored(); +void BadgeManager::ClearBadge(const GURL& scope) { + if (!ScopeIsValidBadgeTarget(receivers_.current_context(), scope)) return; + + UpdateBadge(scope, base::nullopt); +} + +GURL BadgeManager::MostSpecificBadgeForScope(const GURL& scope) { + const std::string& scope_string = scope.spec(); + GURL best_match = GURL::EmptyGURL(); + uint64_t longest_match = 0; + + for (const auto& pair : badged_scopes_) { + const std::string& cur_scope_str = pair.first.spec(); + if (scope_string.find(cur_scope_str) != 0) + continue; + + if (longest_match >= cur_scope_str.size()) + continue; + + longest_match = cur_scope_str.size(); + best_match = pair.first; } - badged_apps_.erase(app_id.value()); - if (!delegate_) - return; - - delegate_->OnBadgeCleared(app_id.value()); + return best_match; } -void BadgeManager::BadgeChangeIgnored() { - if (!delegate_) - return; - - delegate_->OnBadgeChangeIgnoredForTesting(); -} - -void BadgeManager::SetInteger(uint64_t content) { - UpdateAppBadge(GetAppIdToBadge(receivers_.current_context()), content); -} - -void BadgeManager::SetFlag() { - UpdateAppBadge(GetAppIdToBadge(receivers_.current_context()), base::nullopt); -} - -void BadgeManager::ClearBadge() { - ClearAppBadge(GetAppIdToBadge(receivers_.current_context())); -} - -base::Optional<std::string> BadgeManager::GetAppIdToBadge( - const BindingContext& context) { +bool BadgeManager::ScopeIsValidBadgeTarget(const BindingContext& context, + const GURL& scope) { content::RenderFrameHost* frame = content::RenderFrameHost::FromID(context.process_id, context.frame_id); if (!frame) - return base::nullopt; + return false; - content::WebContents* contents = - content::WebContents::FromRenderFrameHost(frame); - Browser* browser = chrome::FindBrowserWithWebContents(contents); - if (!browser) - return base::nullopt; + return url::IsSameOriginWith(frame->GetLastCommittedURL(), scope); +} - web_app::AppBrowserController* app_controller = browser->app_controller(); - if (!app_controller) - return base::nullopt; +std::string GetBadgeString(base::Optional<uint64_t> badge_content) { + if (!badge_content) + return "•"; - // If the frame is not in scope, don't apply a badge. - if (!app_controller->IsUrlInAppScope(frame->GetLastCommittedURL())) { - return base::nullopt; + if (badge_content > kMaxBadgeContent) { + return base::UTF16ToUTF8(l10n_util::GetStringFUTF16( + IDS_SATURATED_BADGE_CONTENT, base::FormatNumber(kMaxBadgeContent))); } - return app_controller->GetAppId(); + return base::UTF16ToUTF8(base::FormatNumber(badge_content.value())); } } // namespace badging
diff --git a/chrome/browser/badging/badge_manager.h b/chrome/browser/badging/badge_manager.h index 114a698..33a2d01b7 100644 --- a/chrome/browser/badging/badge_manager.h +++ b/chrome/browser/badging/badge_manager.h
@@ -11,10 +11,10 @@ #include "base/macros.h" #include "base/optional.h" -#include "chrome/browser/badging/badge_manager_delegate.h" #include "components/keyed_service/core/keyed_service.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "third_party/blink/public/mojom/badging/badging.mojom.h" +#include "url/gurl.h" class Profile; @@ -23,17 +23,19 @@ } // namespace content namespace badging { +class BadgeManagerDelegate; // The maximum value of badge contents before saturation occurs. constexpr uint64_t kMaxBadgeContent = 99u; -// Determines the text to put on the badge based on some badge_content. -std::string GetBadgeString(base::Optional<uint64_t> badge_content); - // Maintains a record of badge contents and dispatches badge changes to a // delegate. class BadgeManager : public KeyedService, public blink::mojom::BadgeService { public: + // The badge being applied to a URL. If the optional is |base::nullopt| then + // the badge is "flag". Otherwise the badge is a non-zero integer. + using BadgeValue = base::Optional<uint64_t>; + explicit BadgeManager(Profile* profile); ~BadgeManager() override; @@ -44,13 +46,16 @@ mojo::PendingReceiver<blink::mojom::BadgeService> receiver, content::RenderFrameHost* frame); - // Sets the badge for |app_id| to be |content|. Note: If content is set, it - // must be non-zero. - void UpdateAppBadge(const base::Optional<std::string>& app_id, - base::Optional<uint64_t> content); + // Returns whether there is a more specific badge for |url| than |scope|. + // Note: This function does not check that there is a badge for |scope|. + bool HasMoreSpecificBadgeForUrl(const GURL& scope, const GURL& url); - // Clears the badge for |app_id|. - void ClearAppBadge(const base::Optional<std::string>& app_id); + // Gets the most specific badge applying to |scope|. This will be + // base::nullopt if the scope is not badged. + base::Optional<BadgeValue> GetBadgeValue(const GURL& scope); + + void SetBadgeForTesting(const GURL& scope, BadgeValue value); + void ClearBadgeForTesting(const GURL& scope); private: // The BindingContext of a mojo request. Allows mojo calls to be tied back to @@ -63,18 +68,23 @@ int frame_id; }; - // Notifies |delegate_| that a badge change was ignored. - void BadgeChangeIgnored(); + // Updates the badge for |scope| to be |value|, if it is not base::nullopt. + // If value is |base::nullopt| then this clears the badge. + void UpdateBadge(const GURL& scope, base::Optional<BadgeValue> value); // blink::mojom::BadgeService: // Note: These are private to stop them being called outside of mojo as they // require a mojo binding context. - void SetInteger(uint64_t content) override; - void SetFlag() override; - void ClearBadge() override; + void SetBadge(const GURL& scope, blink::mojom::BadgeValuePtr value) override; + void ClearBadge(const GURL& scope) override; - // Examines |context| to determine which app, if any, should be badged. - base::Optional<std::string> GetAppIdToBadge(const BindingContext& context); + // Finds the scope URL of the most specific badge for |scope|. Returns + // GURL::EmptyGURL() if no match is found. + GURL MostSpecificBadgeForScope(const GURL& scope); + + // Determines whether |context| is allowed to change the badge for |scope|. + bool ScopeIsValidBadgeTarget(const BindingContext& context, + const GURL& scope); // All the mojo receivers for the BadgeManager. Keeps track of the // render_frame the binding is associated with, so as to not have to rely @@ -85,12 +95,15 @@ // Note: This is currently only set on Windows and MacOS. std::unique_ptr<BadgeManagerDelegate> delegate_; - // Maps app id to badge contents. - std::map<std::string, base::Optional<uint64_t>> badged_apps_; + // Maps scope to badge contents. + std::map<GURL, BadgeValue> badged_scopes_; DISALLOW_COPY_AND_ASSIGN(BadgeManager); }; +// Determines the text to put on the badge based on some badge_content. +std::string GetBadgeString(BadgeManager::BadgeValue badge_content); + } // namespace badging #endif // CHROME_BROWSER_BADGING_BADGE_MANAGER_H_
diff --git a/chrome/browser/badging/badge_manager_delegate.cc b/chrome/browser/badging/badge_manager_delegate.cc new file mode 100644 index 0000000..5dec757 --- /dev/null +++ b/chrome/browser/badging/badge_manager_delegate.cc
@@ -0,0 +1,40 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/badging/badge_manager_delegate.h" + +#include <vector> + +#include "chrome/browser/web_applications/components/app_registrar.h" + +namespace badging { + +void BadgeManagerDelegate::OnBadgeUpdated(const GURL& scope) { + const std::vector<web_app::AppId>& app_ids = + registrar()->FindAppsInScope(scope); + + for (const auto& app_id : app_ids) { + const auto& app_scope = registrar()->GetAppScope(app_id); + if (!app_scope) + continue; + + // If it wasn't the most specific badge for the app that changed, there's no + // need to update it. + if (badge_manager()->HasMoreSpecificBadgeForUrl(scope, app_scope.value())) + continue; + + OnAppBadgeUpdated(app_id); + } +} + +base::Optional<BadgeManager::BadgeValue> BadgeManagerDelegate::GetAppBadgeValue( + const web_app::AppId& app_id) { + const auto& scope = registrar()->GetAppScope(app_id); + if (!scope) + return base::nullopt; + + return badge_manager()->GetBadgeValue(scope.value()); +} + +} // namespace badging
diff --git a/chrome/browser/badging/badge_manager_delegate.h b/chrome/browser/badging/badge_manager_delegate.h index f048d69..fd63a76b 100644 --- a/chrome/browser/badging/badge_manager_delegate.h +++ b/chrome/browser/badging/badge_manager_delegate.h
@@ -5,36 +5,56 @@ #ifndef CHROME_BROWSER_BADGING_BADGE_MANAGER_DELEGATE_H_ #define CHROME_BROWSER_BADGING_BADGE_MANAGER_DELEGATE_H_ -#include <string> - #include "base/optional.h" +#include "chrome/browser/badging/badge_manager.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" +#include "url/gurl.h" class Profile; +namespace web_app { +class AppRegistrar; +} + namespace badging { -// BadgeManagerDelegate is responsible for dispatching badge events that should -// be handled and reflected in the UI. +// A BadgeManagerDelegate is responsible for updating the UI in response to a +// badge change. class BadgeManagerDelegate { public: - explicit BadgeManagerDelegate(Profile* profile) : profile_(profile) {} + explicit BadgeManagerDelegate(Profile* profile, + BadgeManager* badge_manager, + web_app::AppRegistrar* registrar) + : profile_(profile), + badge_manager_(badge_manager), + registrar_(registrar) {} - virtual ~BadgeManagerDelegate() {} + virtual ~BadgeManagerDelegate() = default; - // Called when an app's badge has changed. - virtual void OnBadgeSet(const std::string& app_id, - base::Optional<uint64_t> contents) = 0; - - // Called when a app's badge has been cleared. - virtual void OnBadgeCleared(const std::string& app_id) = 0; - - // Called when a page attempts to set or clear a badge but the badge service - // determines that the page should not able to change the badge. - virtual void OnBadgeChangeIgnoredForTesting() {} + // Called when the badge for |scope| has changed. + virtual void OnBadgeUpdated(const GURL& scope); protected: + // Called when the badge for |app_id| has changed. + virtual void OnAppBadgeUpdated(const web_app::AppId& app_id) = 0; + + // Gets the badge for |app_id|. base::nullopt if the |app_id| is not badged. + base::Optional<BadgeManager::BadgeValue> GetAppBadgeValue( + const web_app::AppId& app_id); + + Profile* profile() { return profile_; } + BadgeManager* badge_manager() { return badge_manager_; } + web_app::AppRegistrar* registrar() { return registrar_; } + + private: // The profile the badge manager delegate is associated with. Profile* profile_; + // The badge manager that owns this delegate. + BadgeManager* badge_manager_; + // The registrar of apps this delegate is concerned with. + web_app::AppRegistrar* registrar_; + + DISALLOW_COPY_AND_ASSIGN(BadgeManagerDelegate); }; } // namespace badging
diff --git a/chrome/browser/badging/badge_manager_delegate_mac.cc b/chrome/browser/badging/badge_manager_delegate_mac.cc index 3c2489b..54253fe 100644 --- a/chrome/browser/badging/badge_manager_delegate_mac.cc +++ b/chrome/browser/badging/badge_manager_delegate_mac.cc
@@ -9,22 +9,21 @@ #include "chrome/browser/badging/badge_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/common/mac/app_shim.mojom.h" -namespace {} // namespace - namespace badging { -BadgeManagerDelegateMac::BadgeManagerDelegateMac(Profile* profile) - : BadgeManagerDelegate(profile) {} +BadgeManagerDelegateMac::BadgeManagerDelegateMac( + Profile* profile, + BadgeManager* badge_manager, + web_app::AppRegistrar* registrar) + : BadgeManagerDelegate(profile, badge_manager, registrar) {} -void BadgeManagerDelegateMac::OnBadgeSet(const std::string& app_id, - base::Optional<uint64_t> contents) { - SetAppBadgeLabel(app_id, badging::GetBadgeString(contents)); -} - -void BadgeManagerDelegateMac::OnBadgeCleared(const std::string& app_id) { - SetAppBadgeLabel(app_id, ""); +void BadgeManagerDelegateMac::OnAppBadgeUpdated(const web_app::AppId& app_id) { + const base::Optional<BadgeManager::BadgeValue>& badge = + GetAppBadgeValue(app_id); + SetAppBadgeLabel(app_id, badge ? badging::GetBadgeString(badge.value()) : ""); } void BadgeManagerDelegateMac::SetAppBadgeLabel(const std::string& app_id, @@ -33,9 +32,9 @@ if (!shim_handler) return; - // On OSX all app instances share a dock icon, so we only need to set the + // On macOS all app instances share a dock icon, so we only need to set the // badge label once. - AppShimHost* shim_host = shim_handler->FindHost(profile_, app_id); + AppShimHost* shim_host = shim_handler->FindHost(profile(), app_id); if (!shim_host) return;
diff --git a/chrome/browser/badging/badge_manager_delegate_mac.h b/chrome/browser/badging/badge_manager_delegate_mac.h index 54ad591..b31eb96 100644 --- a/chrome/browser/badging/badge_manager_delegate_mac.h +++ b/chrome/browser/badging/badge_manager_delegate_mac.h
@@ -12,17 +12,22 @@ class Profile; +namespace web_app { +class AppRegistrar; +} + namespace badging { +class BadgeManager; + // OSX specific implementation of the BadgeManagerDelegate. class BadgeManagerDelegateMac : public BadgeManagerDelegate { public: - explicit BadgeManagerDelegateMac(Profile* profile); + explicit BadgeManagerDelegateMac(Profile* profile, + BadgeManager* badge_manager, + web_app::AppRegistrar* registrar); - void OnBadgeSet(const std::string& app_id, - base::Optional<uint64_t> contents) override; - - void OnBadgeCleared(const std::string& app_id) override; + void OnAppBadgeUpdated(const web_app::AppId& app_id) override; private: void SetAppBadgeLabel(const std::string& app_id,
diff --git a/chrome/browser/badging/badge_manager_delegate_unittest.cc b/chrome/browser/badging/badge_manager_delegate_unittest.cc new file mode 100644 index 0000000..ccd7bed0 --- /dev/null +++ b/chrome/browser/badging/badge_manager_delegate_unittest.cc
@@ -0,0 +1,92 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <utility> + +#include "base/optional.h" +#include "chrome/browser/badging/badge_manager.h" +#include "chrome/browser/badging/badge_manager_factory.h" +#include "chrome/browser/badging/test_badge_manager_delegate.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" +#include "chrome/browser/web_applications/test/test_app_registrar.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace badging { + +class BadgeManagerDelegateUnittest : public ::testing::Test { + public: + BadgeManagerDelegateUnittest() = default; + ~BadgeManagerDelegateUnittest() override = default; + + void SetUp() override { + profile_.reset(new TestingProfile()); + registrar_.reset(new web_app::TestAppRegistrar()); + + badge_manager_ = + BadgeManagerFactory::GetInstance()->GetForProfile(profile_.get()); + + // Delegate lifetime is managed by BadgeManager. + auto owned_delegate = std::make_unique<TestBadgeManagerDelegate>( + profile_.get(), badge_manager_, registrar()); + delegate_ = owned_delegate.get(); + badge_manager_->SetDelegate(std::move(owned_delegate)); + } + + void TearDown() override { profile_.reset(); } + + TestBadgeManagerDelegate* delegate() { return delegate_; } + + web_app::TestAppRegistrar* registrar() const { return registrar_.get(); } + BadgeManager* badge_manager() const { return badge_manager_; } + + private: + std::unique_ptr<web_app::TestAppRegistrar> registrar_; + TestBadgeManagerDelegate* delegate_; + BadgeManager* badge_manager_; + std::unique_ptr<TestingProfile> profile_; + content::BrowserTaskEnvironment task_environment_; + + DISALLOW_COPY_AND_ASSIGN(BadgeManagerDelegateUnittest); +}; + +TEST_F(BadgeManagerDelegateUnittest, InScopeAppsAreBadged) { + const web_app::AppId& kApp1 = "app1"; + const web_app::AppId& kApp2 = "app2"; + + registrar()->AddExternalApp(kApp1, {GURL("https://example.com/app1")}); + registrar()->AddExternalApp(kApp2, {GURL("https://example.com/app2")}); + + badge_manager()->SetBadgeForTesting(GURL("https://example.com/"), + base::nullopt); + + EXPECT_EQ(2UL, delegate()->set_app_badges().size()); + + EXPECT_EQ(kApp1, delegate()->set_app_badges()[0].first); + EXPECT_EQ(base::nullopt, delegate()->set_app_badges()[0].second); + + EXPECT_EQ(kApp2, delegate()->set_app_badges()[1].first); + EXPECT_EQ(base::nullopt, delegate()->set_app_badges()[1].second); +} + +TEST_F(BadgeManagerDelegateUnittest, InScopeAppsAreCleared) { + const web_app::AppId& kApp1 = "app1"; + const web_app::AppId& kApp2 = "app2"; + + registrar()->AddExternalApp(kApp1, {GURL("https://example.com/app1")}); + registrar()->AddExternalApp(kApp2, {GURL("https://example.com/app2")}); + + badge_manager()->SetBadgeForTesting(GURL("https://example.com/"), + base::nullopt); + badge_manager()->ClearBadgeForTesting(GURL("https://example.com/")); + + EXPECT_EQ(2UL, delegate()->cleared_app_badges().size()); + + EXPECT_EQ(kApp1, delegate()->cleared_app_badges()[0]); + EXPECT_EQ(kApp2, delegate()->cleared_app_badges()[1]); +} + +} // namespace badging
diff --git a/chrome/browser/badging/badge_manager_delegate_win.cc b/chrome/browser/badging/badge_manager_delegate_win.cc index a696fb865..01ed79c 100644 --- a/chrome/browser/badging/badge_manager_delegate_win.cc +++ b/chrome/browser/badging/badge_manager_delegate_win.cc
@@ -12,30 +12,37 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/web_applications/components/app_registrar.h" #include "ui/base/l10n/l10n_util.h" #include "ui/strings/grit/ui_strings.h" namespace badging { -BadgeManagerDelegateWin::BadgeManagerDelegateWin(Profile* profile) - : BadgeManagerDelegate(profile) {} +namespace { -void BadgeManagerDelegateWin::OnBadgeSet(const std::string& app_id, - base::Optional<uint64_t> contents) { - auto badge_string = badging::GetBadgeString(contents); - // There are 3 different cases: +// Determines the badge contents and alt text. +// base::nullopt if the badge is not set. +// otherwise a pair (badge_content, badge_alt_text), based on the content of the +// badge. +base::Optional<std::pair<std::string, std::string>> GetBadgeContentAndAlt( + const base::Optional<BadgeManager::BadgeValue>& badge) { + // If there is no badge, there is no contents or alt text. + if (!badge) + return base::nullopt; + + std::string badge_string = badging::GetBadgeString(badge.value()); + // There are 3 different cases when the badge has a value: // 1. |contents| is between 1 and 99 inclusive => Set the accessibility text // to a pluralized notification count (e.g. 4 Unread Notifications). // 2. |contents| is greater than 99 => Set the accessibility text to // More than |kMaxBadgeContent| unread notifications, so the // accessibility text matches what is displayed on the badge (e.g. More // than 99 notifications). - // 3. |contents| doesn't have a value (i.e. the badge is set to 'flag') => Set - // the accessibility text to something less specific (e.g. Unread - // Notifications). + // 3. The badge is set to 'flag' => Set the accessibility text to something + // less specific (e.g. Unread Notifications). std::string badge_alt_string; - if (contents) { - uint64_t value = contents.value(); + if (badge.value()) { + uint64_t value = badge.value().value(); badge_alt_string = value <= badging::kMaxBadgeContent // Case 1. ? l10n_util::GetPluralStringFUTF8( @@ -50,25 +57,31 @@ l10n_util::GetStringUTF8(IDS_BADGE_UNREAD_NOTIFICATIONS_UNSPECIFIED); } + return std::make_pair(badge_string, badge_alt_string); +} + +} // namespace + +BadgeManagerDelegateWin::BadgeManagerDelegateWin( + Profile* profile, + BadgeManager* badge_manager, + web_app::AppRegistrar* registrar) + : BadgeManagerDelegate(profile, badge_manager, registrar) {} + +void BadgeManagerDelegateWin::OnAppBadgeUpdated(const web_app::AppId& app_id) { + const auto& content_and_alt = GetBadgeContentAndAlt(GetAppBadgeValue(app_id)); + for (Browser* browser : *BrowserList::GetInstance()) { if (!IsAppBrowser(browser, app_id)) continue; auto* window = browser->window()->GetNativeWindow(); - taskbar::DrawTaskbarDecorationString(window, badge_string, - badge_alt_string); - } -} - -void BadgeManagerDelegateWin::OnBadgeCleared(const std::string& app_id) { - for (Browser* browser : *BrowserList::GetInstance()) { - if (!IsAppBrowser(browser, app_id)) - continue; - - // Restore the decoration to whatever it is naturally (either nothing or a - // profile picture badge). - taskbar::UpdateTaskbarDecoration(browser->profile(), - browser->window()->GetNativeWindow()); + if (content_and_alt) { + taskbar::DrawTaskbarDecorationString(window, content_and_alt->first, + content_and_alt->second); + } else { + taskbar::UpdateTaskbarDecoration(browser->profile(), window); + } } } @@ -76,7 +89,7 @@ const std::string& app_id) { return browser->app_controller() && browser->app_controller()->GetAppId() == app_id && - browser->profile() == profile_; + browser->profile() == profile(); } } // namespace badging
diff --git a/chrome/browser/badging/badge_manager_delegate_win.h b/chrome/browser/badging/badge_manager_delegate_win.h index 201613ff..dd62482b 100644 --- a/chrome/browser/badging/badge_manager_delegate_win.h +++ b/chrome/browser/badging/badge_manager_delegate_win.h
@@ -13,17 +13,22 @@ class Profile; +namespace web_app { +class AppRegistrar; +} + namespace badging { +class BadgeManager; + // Windows specific implementation of the BadgeManagerDelegate. class BadgeManagerDelegateWin : public BadgeManagerDelegate { public: - explicit BadgeManagerDelegateWin(Profile* profile); + explicit BadgeManagerDelegateWin(Profile* profile, + BadgeManager* badge_manager, + web_app::AppRegistrar* registrar); - void OnBadgeSet(const std::string& app_id, - base::Optional<uint64_t> contents) override; - - void OnBadgeCleared(const std::string& app_id) override; + void OnAppBadgeUpdated(const web_app::AppId& app_id) override; private: // Determines if a browser is for a specific hosted app, on this profile.
diff --git a/chrome/browser/badging/badge_manager_unittest.cc b/chrome/browser/badging/badge_manager_unittest.cc index 3433c95..abdd68a 100644 --- a/chrome/browser/badging/badge_manager_unittest.cc +++ b/chrome/browser/badging/badge_manager_unittest.cc
@@ -11,12 +11,16 @@ #include "base/optional.h" #include "chrome/browser/badging/badge_manager_delegate.h" #include "chrome/browser/badging/badge_manager_factory.h" +#include "chrome/browser/badging/test_badge_manager_delegate.h" +#include "chrome/browser/web_applications/components/web_app_provider_base.h" +#include "chrome/browser/web_applications/test/test_app_registrar.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/browser_task_environment.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/common/extension_id.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" using badging::BadgeManager; using badging::BadgeManagerDelegate; @@ -24,40 +28,15 @@ namespace { -typedef std::pair<std::string, base::Optional<int>> SetBadgeAction; +typedef std::pair<GURL, base::Optional<int>> SetBadgeAction; -const int kBadgeContents = 1; - -const extensions::ExtensionId kExtensionId("1"); +constexpr uint64_t kBadgeContents = 1; +const GURL kAppScope("https://example.com/app"); } // namespace namespace badging { -// Testing delegate that records badge changes. -class TestBadgeManagerDelegate : public BadgeManagerDelegate { - public: - TestBadgeManagerDelegate() : BadgeManagerDelegate(nullptr) {} - - ~TestBadgeManagerDelegate() override = default; - - void OnBadgeSet(const std::string& app_id, - base::Optional<uint64_t> contents) override { - set_badges_.push_back(std::make_pair(app_id, contents)); - } - - void OnBadgeCleared(const std::string& app_id) override { - cleared_badges_.push_back(app_id); - } - - std::vector<std::string>& cleared_badges() { return cleared_badges_; } - std::vector<SetBadgeAction>& set_badges() { return set_badges_; } - - private: - std::vector<std::string> cleared_badges_; - std::vector<SetBadgeAction> set_badges_; -}; - class BadgeManagerUnittest : public ::testing::Test { public: BadgeManagerUnittest() = default; @@ -65,12 +44,15 @@ void SetUp() override { profile_.reset(new TestingProfile()); + registrar_.reset(new web_app::TestAppRegistrar()); - // Delegate lifetime is managed by BadgeManager - auto owned_delegate = std::make_unique<TestBadgeManagerDelegate>(); - delegate_ = owned_delegate.get(); badge_manager_ = BadgeManagerFactory::GetInstance()->GetForProfile(profile_.get()); + + // Delegate lifetime is managed by BadgeManager + auto owned_delegate = std::make_unique<TestBadgeManagerDelegate>( + profile_.get(), badge_manager_, registrar_.get()); + delegate_ = owned_delegate.get(); badge_manager_->SetDelegate(std::move(owned_delegate)); } @@ -81,6 +63,7 @@ BadgeManager* badge_manager() const { return badge_manager_; } private: + std::unique_ptr<web_app::TestAppRegistrar> registrar_; TestBadgeManagerDelegate* delegate_; BadgeManager* badge_manager_; content::BrowserTaskEnvironment task_environment_; @@ -90,58 +73,63 @@ }; TEST_F(BadgeManagerUnittest, SetFlagBadgeForApp) { - badge_manager()->UpdateAppBadge(kExtensionId, base::nullopt); + badge_manager()->SetBadgeForTesting(kAppScope, base::nullopt); - EXPECT_EQ(1UL, delegate()->set_badges().size()); - EXPECT_EQ(kExtensionId, delegate()->set_badges().front().first); - EXPECT_EQ(base::nullopt, delegate()->set_badges().front().second); + EXPECT_EQ(1UL, delegate()->set_scope_badges().size()); + EXPECT_EQ(kAppScope, delegate()->set_scope_badges().front().first); + EXPECT_EQ(base::nullopt, delegate()->set_scope_badges().front().second); } TEST_F(BadgeManagerUnittest, SetBadgeForApp) { - badge_manager()->UpdateAppBadge(kExtensionId, kBadgeContents); + badge_manager()->SetBadgeForTesting(kAppScope, + base::make_optional(kBadgeContents)); - EXPECT_EQ(1UL, delegate()->set_badges().size()); - EXPECT_EQ(kExtensionId, delegate()->set_badges().front().first); - EXPECT_EQ(kBadgeContents, delegate()->set_badges().front().second); + EXPECT_EQ(1UL, delegate()->set_scope_badges().size()); + EXPECT_EQ(kAppScope, delegate()->set_scope_badges().front().first); + EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges().front().second); } TEST_F(BadgeManagerUnittest, SetBadgeForMultipleApps) { - const extensions::ExtensionId otherId("other"); - int otherContents = 2; + const GURL kOtherScope("http://other.app/other"); + constexpr uint64_t kOtherContents = 2; - badge_manager()->UpdateAppBadge(kExtensionId, kBadgeContents); - badge_manager()->UpdateAppBadge(otherId, otherContents); + badge_manager()->SetBadgeForTesting(kAppScope, + base::make_optional(kBadgeContents)); + badge_manager()->SetBadgeForTesting(kOtherScope, + base::make_optional(kOtherContents)); - EXPECT_EQ(2UL, delegate()->set_badges().size()); + EXPECT_EQ(2UL, delegate()->set_scope_badges().size()); - EXPECT_EQ(kExtensionId, delegate()->set_badges()[0].first); - EXPECT_EQ(kBadgeContents, delegate()->set_badges()[0].second); + EXPECT_EQ(kAppScope, delegate()->set_scope_badges()[0].first); + EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges()[0].second); - EXPECT_EQ(otherId, delegate()->set_badges()[1].first); - EXPECT_EQ(otherContents, delegate()->set_badges()[1].second); + EXPECT_EQ(kOtherScope, delegate()->set_scope_badges()[1].first); + EXPECT_EQ(kOtherContents, delegate()->set_scope_badges()[1].second); } TEST_F(BadgeManagerUnittest, SetBadgeForAppAfterClear) { - badge_manager()->UpdateAppBadge(kExtensionId, kBadgeContents); - badge_manager()->ClearAppBadge(kExtensionId); - badge_manager()->UpdateAppBadge(kExtensionId, kBadgeContents); + badge_manager()->SetBadgeForTesting(kAppScope, + base::make_optional(kBadgeContents)); + badge_manager()->ClearBadgeForTesting(kAppScope); + badge_manager()->SetBadgeForTesting(kAppScope, + base::make_optional(kBadgeContents)); - EXPECT_EQ(2UL, delegate()->set_badges().size()); + EXPECT_EQ(2UL, delegate()->set_scope_badges().size()); - EXPECT_EQ(kExtensionId, delegate()->set_badges()[0].first); - EXPECT_EQ(kBadgeContents, delegate()->set_badges()[0].second); + EXPECT_EQ(kAppScope, delegate()->set_scope_badges()[0].first); + EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges()[0].second); - EXPECT_EQ(kExtensionId, delegate()->set_badges()[1].first); - EXPECT_EQ(kBadgeContents, delegate()->set_badges()[1].second); + EXPECT_EQ(kAppScope, delegate()->set_scope_badges()[1].first); + EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges()[1].second); } TEST_F(BadgeManagerUnittest, ClearBadgeForBadgedApp) { - badge_manager()->UpdateAppBadge(kExtensionId, kBadgeContents); + badge_manager()->SetBadgeForTesting(kAppScope, + base::make_optional(kBadgeContents)); + badge_manager()->ClearBadgeForTesting(kAppScope); - badge_manager()->ClearAppBadge(kExtensionId); - - EXPECT_EQ(1UL, delegate()->cleared_badges().size()); - EXPECT_EQ(kExtensionId, delegate()->cleared_badges().front()); + EXPECT_EQ(1UL, delegate()->cleared_scope_badges().size()); + EXPECT_EQ(kAppScope, delegate()->cleared_scope_badges().front()); } TEST_F(BadgeManagerUnittest, BadgingMultipleProfiles) { @@ -149,41 +137,75 @@ auto* other_badge_manager = BadgeManagerFactory::GetInstance()->GetForProfile(other_profile.get()); - auto owned_other_delegate = std::make_unique<TestBadgeManagerDelegate>(); + web_app::TestAppRegistrar other_registrar; + auto owned_other_delegate = std::make_unique<TestBadgeManagerDelegate>( + other_profile.get(), other_badge_manager, &other_registrar); auto* other_delegate = owned_other_delegate.get(); other_badge_manager->SetDelegate(std::move(owned_other_delegate)); - other_badge_manager->UpdateAppBadge(kExtensionId, base::nullopt); - other_badge_manager->UpdateAppBadge(kExtensionId, kBadgeContents); - other_badge_manager->UpdateAppBadge(kExtensionId, base::nullopt); - other_badge_manager->ClearAppBadge(kExtensionId); + other_badge_manager->SetBadgeForTesting(kAppScope, base::nullopt); + other_badge_manager->SetBadgeForTesting(kAppScope, + base::make_optional(kBadgeContents)); + other_badge_manager->SetBadgeForTesting(kAppScope, base::nullopt); + other_badge_manager->ClearBadgeForTesting(kAppScope); - badge_manager()->ClearAppBadge(kExtensionId); + badge_manager()->ClearBadgeForTesting(kAppScope); - EXPECT_EQ(3UL, other_delegate->set_badges().size()); - EXPECT_EQ(0UL, delegate()->set_badges().size()); + EXPECT_EQ(3UL, other_delegate->set_scope_badges().size()); + EXPECT_EQ(0UL, delegate()->set_scope_badges().size()); - EXPECT_EQ(1UL, other_delegate->cleared_badges().size()); - EXPECT_EQ(1UL, delegate()->cleared_badges().size()); + EXPECT_EQ(1UL, other_delegate->cleared_scope_badges().size()); + EXPECT_EQ(1UL, delegate()->cleared_scope_badges().size()); - EXPECT_EQ(kExtensionId, other_delegate->set_badges().back().first); - EXPECT_EQ(base::nullopt, other_delegate->set_badges().back().second); + EXPECT_EQ(kAppScope, other_delegate->set_scope_badges().back().first); + EXPECT_EQ(base::nullopt, other_delegate->set_scope_badges().back().second); } // Tests methods which call into the badge manager delegate do not crash when // the delegate is unset. TEST_F(BadgeManagerUnittest, BadgingWithNoDelegateDoesNotCrash) { - const std::string kAppId = "app-id"; - badge_manager()->SetDelegate(nullptr); - badge_manager()->UpdateAppBadge(kAppId, base::nullopt); - badge_manager()->UpdateAppBadge(kAppId, base::Optional<uint64_t>(7u)); - badge_manager()->UpdateAppBadge(base::nullopt, base::nullopt); - badge_manager()->UpdateAppBadge(base::nullopt, base::Optional<uint64_t>(7u)); + badge_manager()->SetBadgeForTesting(kAppScope, base::nullopt); + badge_manager()->SetBadgeForTesting(kAppScope, + base::make_optional(kBadgeContents)); + badge_manager()->SetBadgeForTesting(GURL(), base::nullopt); + badge_manager()->SetBadgeForTesting(GURL(), + base::make_optional(kBadgeContents)); + badge_manager()->ClearBadgeForTesting(GURL()); +} - badge_manager()->ClearAppBadge(kAppId); - badge_manager()->ClearAppBadge(base::nullopt); +TEST_F(BadgeManagerUnittest, MostSpecificBadgeApplies) { + const GURL origin("https://example.com/"); + const GURL app("https://example.com/app"); + const GURL app_page("https://example.com/app/page/1"); + + const base::Optional<BadgeManager::BadgeValue> origin_badge = + base::make_optional(base::Optional<uint64_t>(1U)); + const base::Optional<BadgeManager::BadgeValue> app_badge = + base::make_optional(base::Optional<uint64_t>(1U)); + const base::Optional<BadgeManager::BadgeValue> app_page_badge = + base::make_optional(base::Optional<uint64_t>(1U)); + + badge_manager()->SetBadgeForTesting(origin, origin_badge.value()); + EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app), origin_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), origin_badge); + + badge_manager()->SetBadgeForTesting(app, app_badge.value()); + EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app), app_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), app_badge); + + badge_manager()->SetBadgeForTesting(app_page, app_page_badge.value()); + EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app), app_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), app_page_badge); + + badge_manager()->ClearBadgeForTesting(app); + EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app), origin_badge); + EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), app_page_badge); } } // namespace badging
diff --git a/chrome/browser/badging/test_badge_manager_delegate.cc b/chrome/browser/badging/test_badge_manager_delegate.cc new file mode 100644 index 0000000..1c79864 --- /dev/null +++ b/chrome/browser/badging/test_badge_manager_delegate.cc
@@ -0,0 +1,55 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/badging/test_badge_manager_delegate.h" + +#include "chrome/browser/badging/badge_manager.h" +#include "chrome/browser/badging/badge_manager_delegate.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/components/app_registrar.h" + +namespace badging { + +TestBadgeManagerDelegate::TestBadgeManagerDelegate( + Profile* profile, + BadgeManager* badge_manager, + web_app::AppRegistrar* registrar) + : BadgeManagerDelegate(profile, badge_manager, registrar) {} + +TestBadgeManagerDelegate::~TestBadgeManagerDelegate() = default; + +void TestBadgeManagerDelegate::SetOnBadgeChanged( + base::RepeatingCallback<void()> on_badge_changed) { + on_badge_changed_ = on_badge_changed; +} + +void TestBadgeManagerDelegate::OnBadgeUpdated(const GURL& scope) { + BadgeManagerDelegate::OnBadgeUpdated(scope); + + const auto& value = badge_manager()->GetBadgeValue(scope); + if (!value) + cleared_scope_badges_.push_back(scope); + else + set_scope_badges_.push_back(std::make_pair(scope, value.value())); + + if (on_badge_changed_) + on_badge_changed_.Run(); +} + +void TestBadgeManagerDelegate::OnAppBadgeUpdated(const web_app::AppId& app_id) { + const auto& value = GetAppBadgeValue(app_id); + if (!value) + cleared_app_badges_.push_back(app_id); + else + set_app_badges_.push_back(std::make_pair(app_id, value.value())); +} + +void TestBadgeManagerDelegate::ResetBadges() { + cleared_app_badges_.clear(); + set_app_badges_.clear(); + cleared_scope_badges_.clear(); + set_scope_badges_.clear(); +} + +} // namespace badging
diff --git a/chrome/browser/badging/test_badge_manager_delegate.h b/chrome/browser/badging/test_badge_manager_delegate.h new file mode 100644 index 0000000..fa689c62 --- /dev/null +++ b/chrome/browser/badging/test_badge_manager_delegate.h
@@ -0,0 +1,68 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_BADGING_TEST_BADGE_MANAGER_DELEGATE_H_ +#define CHROME_BROWSER_BADGING_TEST_BADGE_MANAGER_DELEGATE_H_ + +#include <vector> + +#include "base/callback.h" +#include "base/optional.h" +#include "chrome/browser/badging/badge_manager.h" +#include "chrome/browser/badging/badge_manager_delegate.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" + +class Profile; + +namespace web_app { +class AppRegistrar; +} + +namespace badging { + +class BadgeManager; + +using AppBadge = std::pair<web_app::AppId, BadgeManager::BadgeValue>; +using ScopeBadge = std::pair<GURL, BadgeManager::BadgeValue>; + +// Testing delegate that records badge changes for apps. +class TestBadgeManagerDelegate : public BadgeManagerDelegate { + public: + TestBadgeManagerDelegate(Profile* profile, + BadgeManager* badge_manager, + web_app::AppRegistrar* registrar); + ~TestBadgeManagerDelegate() override; + + // Sets a callback to fire when a badge is set or cleared. + void SetOnBadgeChanged(base::RepeatingCallback<void()> on_badge_changed); + + // Resets the lists of cleared and set badges. + void ResetBadges(); + + std::vector<web_app::AppId> cleared_app_badges() { + return cleared_app_badges_; + } + std::vector<AppBadge> set_app_badges() { return set_app_badges_; } + std::vector<GURL> cleared_scope_badges() { return cleared_scope_badges_; } + std::vector<ScopeBadge> set_scope_badges() { return set_scope_badges_; } + + // BadgeManagerDelegate: + void OnBadgeUpdated(const GURL& scope) override; + + protected: + // BadgeManagerDelegate: + void OnAppBadgeUpdated(const web_app::AppId& app_badge) override; + + private: + base::RepeatingCallback<void()> on_badge_changed_; + + std::vector<web_app::AppId> cleared_app_badges_; + std::vector<AppBadge> set_app_badges_; + std::vector<GURL> cleared_scope_badges_; + std::vector<ScopeBadge> set_scope_badges_; +}; + +} // namespace badging + +#endif // CHROME_BROWSER_BADGING_TEST_BADGE_MANAGER_DELEGATE_H_
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 907a8ec..9d44c1b1 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2197,6 +2197,10 @@ "extensions/login_screen/login_screen_ui/login_screen_extension_ui_handler.h", "extensions/login_screen/login_screen_ui/login_screen_ui_api.cc", "extensions/login_screen/login_screen_ui/login_screen_ui_api.h", + "extensions/login_screen/login_state/login_state_api.cc", + "extensions/login_screen/login_state/login_state_api.h", + "extensions/login_screen/login_state/session_state_changed_event_dispatcher.cc", + "extensions/login_screen/login_state/session_state_changed_event_dispatcher.h", "extensions/media_player_api.cc", "extensions/media_player_api.h", "extensions/quick_unlock_private/quick_unlock_private_api.cc", @@ -2498,6 +2502,8 @@ "extensions/install_limiter_unittest.cc", "extensions/login_screen/login/login_api_unittest.cc", "extensions/login_screen/login_screen_ui/login_screen_extension_ui_handler_unittest.cc", + "extensions/login_screen/login_state/login_state_api_unittest.cc", + "extensions/login_screen/login_state/session_state_changed_event_dispatcher_unittest.cc", "extensions/permissions_updater_delegate_chromeos_unittest.cc", "extensions/public_session_permission_helper_unittest.cc", "extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc",
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.cc b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.cc new file mode 100644 index 0000000..77ac761 --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.cc
@@ -0,0 +1,65 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h" + +#include <memory> + +#include "base/values.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "components/session_manager/core/session_manager.h" +#include "content/public/browser/browser_context.h" + +namespace extensions { + +// Not all session states are exposed to the extension. Session states which +// are not exposed will be mapped to the nearest logical state. The mapping is +// as follows: +// UNKNOWN -> UNKNOWN +// OOBE -> IN_OOBE_SCREEN +// LOGIN_PRIMARY -> IN_LOGIN_SCREEN +// LOGIN_SECONDARY -> IN_LOGIN_SCREEN +// LOGGED_IN_NOT_ACTIVE -> IN_LOGIN_SCREEN +// ACTIVE -> IN_SESSION +// LOCKED -> IN_LOCK_SCREEN +api::login_state::SessionState SessionStateToApiEnum( + session_manager::SessionState state) { + switch (state) { + case session_manager::SessionState::UNKNOWN: + return api::login_state::SessionState::SESSION_STATE_UNKNOWN; + case session_manager::SessionState::OOBE: + return api::login_state::SessionState::SESSION_STATE_IN_OOBE_SCREEN; + case session_manager::SessionState::LOGIN_PRIMARY: + case session_manager::SessionState::LOGIN_SECONDARY: + case session_manager::SessionState::LOGGED_IN_NOT_ACTIVE: + return api::login_state::SessionState::SESSION_STATE_IN_LOGIN_SCREEN; + case session_manager::SessionState::ACTIVE: + return api::login_state::SessionState::SESSION_STATE_IN_SESSION; + case session_manager::SessionState::LOCKED: + return api::login_state::SessionState::SESSION_STATE_IN_LOCK_SCREEN; + } + NOTREACHED(); + return api::login_state::SessionState::SESSION_STATE_UNKNOWN; +} + +ExtensionFunction::ResponseAction LoginStateGetProfileTypeFunction::Run() { + bool is_signin_profile = chromeos::ProfileHelper::IsSigninProfile( + Profile::FromBrowserContext(browser_context())); + api::login_state::ProfileType profile_type = + is_signin_profile + ? api::login_state::ProfileType::PROFILE_TYPE_SIGNIN_PROFILE + : api::login_state::ProfileType::PROFILE_TYPE_USER_PROFILE; + return RespondNow(ArgumentList( + api::login_state::GetProfileType::Results::Create(profile_type))); +} + +ExtensionFunction::ResponseAction LoginStateGetSessionStateFunction::Run() { + session_manager::SessionState state = + session_manager::SessionManager::Get()->session_state(); + return RespondNow( + ArgumentList(api::login_state::GetSessionState::Results::Create( + SessionStateToApiEnum(state)))); +} + +} // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h new file mode 100644 index 0000000..a62d367 --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h
@@ -0,0 +1,43 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_STATE_LOGIN_STATE_API_H_ +#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_STATE_LOGIN_STATE_API_H_ + +#include "chrome/common/extensions/api/login_state.h" +#include "extensions/browser/extension_function.h" +#include "extensions/browser/extension_function_histogram_value.h" + +namespace session_manager { +enum class SessionState; +} // namespace session_manager + +namespace extensions { + +api::login_state::SessionState SessionStateToApiEnum( + session_manager::SessionState state); + +class LoginStateGetProfileTypeFunction : public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("loginState.getProfileType", + LOGINSTATE_GETPROFILETYPE) + + protected: + ~LoginStateGetProfileTypeFunction() override {} + ResponseAction Run() override; +}; + +class LoginStateGetSessionStateFunction : public ExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("loginState.getSessionState", + LOGINSTATE_GETSESSIONSTATE) + + protected: + ~LoginStateGetSessionStateFunction() override {} + ResponseAction Run() override; +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_STATE_LOGIN_STATE_API_H_
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api_unittest.cc new file mode 100644 index 0000000..a761866e --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api_unittest.cc
@@ -0,0 +1,106 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h" + +#include <memory> + +#include "base/memory/scoped_refptr.h" +#include "base/values.h" +#include "chrome/browser/extensions/extension_api_unittest.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/test/base/testing_profile.h" +#include "components/session_manager/core/session_manager.h" +#include "components/session_manager/session_manager_types.h" +#include "extensions/browser/api_test_utils.h" +#include "extensions/common/extension.h" +#include "extensions/common/extension_builder.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +constexpr char kExtensionName[] = "loginState API extension"; +constexpr char kExtensionId[] = "abcdefghijklmnopqrstuvwxyzabcdef"; + +} // namespace + +namespace extensions { + +class LoginStateApiUnittest : public ExtensionApiUnittest { + public: + LoginStateApiUnittest() {} + ~LoginStateApiUnittest() override = default; + + void SetUp() override { + ExtensionApiUnittest::SetUp(); + + // |session_manager::SessionManager| is not initialized by default. + // This sets up the static instance of |SessionManager| so + // |session_manager::SessionManager::Get()| will return this particular + // instance. + session_manager_ = std::make_unique<session_manager::SessionManager>(); + + scoped_refptr<const Extension> extension = + ExtensionBuilder(kExtensionName).SetID(kExtensionId).Build(); + set_extension(extension); + } + + protected: + std::unique_ptr<session_manager::SessionManager> session_manager_; + + private: + DISALLOW_COPY_AND_ASSIGN(LoginStateApiUnittest); +}; + +// Test that calling |loginState.getSessionState()| returns the correctly mapped +// session state. +TEST_F(LoginStateApiUnittest, GetSessionState) { + const struct { + const session_manager::SessionState session_state; + const std::string expected; + } kTestCases[] = { + {session_manager::SessionState::UNKNOWN, "UNKNOWN"}, + {session_manager::SessionState::OOBE, "IN_OOBE_SCREEN"}, + {session_manager::SessionState::LOGIN_PRIMARY, "IN_LOGIN_SCREEN"}, + {session_manager::SessionState::LOGGED_IN_NOT_ACTIVE, "IN_LOGIN_SCREEN"}, + {session_manager::SessionState::LOGIN_SECONDARY, "IN_LOGIN_SCREEN"}, + {session_manager::SessionState::ACTIVE, "IN_SESSION"}, + {session_manager::SessionState::LOCKED, "IN_LOCK_SCREEN"}, + }; + + for (const auto& test : kTestCases) { + session_manager_->SetSessionState(test.session_state); + auto function = base::MakeRefCounted<LoginStateGetSessionStateFunction>(); + std::unique_ptr<base::Value> result = + RunFunctionAndReturnValue(function.get(), "[]"); + EXPECT_EQ(test.expected, result->GetString()); + } +} + +// Test that |loginState.getProfileType()| returns |USER_PROFILE| for +// extensions not running in the signin profile. +TEST_F(LoginStateApiUnittest, GetProfileType_UserProfile) { + auto function = base::MakeRefCounted<LoginStateGetProfileTypeFunction>(); + EXPECT_EQ("USER_PROFILE", + RunFunctionAndReturnValue(function.get(), "[]")->GetString()); +} + +// Test that |loginState.getProfileType()| returns |SIGNIN_PROFILE| for +// extensions running in the signin profile. +TEST_F(LoginStateApiUnittest, GetProfileType_SigninProfile) { + // |chromeos::ProfileHelper::GetSigninProfile()| cannot be used as the + // |TestingProfileManager| set up by |BrowserWithTestWindowTest| has an empty + // user data directory. + TestingProfile::Builder builder; + builder.SetPath(base::FilePath(FILE_PATH_LITERAL(chrome::kInitialProfile))); + std::unique_ptr<Profile> profile = builder.Build(); + + auto function = base::MakeRefCounted<LoginStateGetProfileTypeFunction>(); + EXPECT_EQ("SIGNIN_PROFILE", api_test_utils::RunFunctionAndReturnSingleResult( + function.get(), "[]", profile.get()) + ->GetString()); +} + +} // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_apitest.cc b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_apitest.cc new file mode 100644 index 0000000..a2af3d9c --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/login_state_apitest.cc
@@ -0,0 +1,21 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h" + +#include "chrome/browser/extensions/extension_apitest.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +using LoginStateApitest = ExtensionApiTest; + +// Test that |loginState.getProfileType()| returns |USER_PROFILE| for +// extensions not running in the signin profile. +IN_PROC_BROWSER_TEST_F(LoginStateApitest, GetProfileType_UserProfile) { + EXPECT_TRUE(RunExtensionTestWithArg( + "login_screen_apis/login_state/get_profile_type", "USER_PROFILE")); +} + +} // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.cc b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.cc new file mode 100644 index 0000000..2e11f66a --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.cc
@@ -0,0 +1,67 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.h" + +#include "base/logging.h" +#include "base/no_destructor.h" +#include "chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h" +#include "chrome/common/extensions/api/login_state.h" +#include "components/session_manager/core/session_manager.h" +#include "components/session_manager/session_manager_types.h" +#include "content/public/browser/browser_context.h" +#include "extensions/browser/event_router.h" +#include "extensions/browser/extension_event_histogram_value.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/common/extension_set.h" + +namespace extensions { + +BrowserContextKeyedAPIFactory<SessionStateChangedEventDispatcher>* +SessionStateChangedEventDispatcher::GetFactoryInstance() { + static base::NoDestructor< + BrowserContextKeyedAPIFactory<SessionStateChangedEventDispatcher>> + instance; + return instance.get(); +} + +SessionStateChangedEventDispatcher::SessionStateChangedEventDispatcher( + content::BrowserContext* browser_context) + : session_manager_observer_(this), + browser_context_(browser_context), + event_router_(EventRouter::Get(browser_context)), + session_state_(api::login_state::SESSION_STATE_UNKNOWN) { + session_manager_observer_.Add(session_manager::SessionManager::Get()); +} + +SessionStateChangedEventDispatcher::~SessionStateChangedEventDispatcher() = + default; + +void SessionStateChangedEventDispatcher::Shutdown() {} + +void SessionStateChangedEventDispatcher::OnSessionStateChanged() { + api::login_state::SessionState new_state = SessionStateToApiEnum( + session_manager::SessionManager::Get()->session_state()); + + // |session_manager::SessionState| changed but the mapped + // |api::login_state::SessionState| did not. + if (session_state_ == new_state) + return; + + session_state_ = new_state; + + std::unique_ptr<Event> event = std::make_unique<Event>( + events::LOGIN_STATE_ON_SESSION_STATE_CHANGED, + api::login_state::OnSessionStateChanged::kEventName, + api::login_state::OnSessionStateChanged::Create(new_state)); + + event_router_->BroadcastEvent(std::move(event)); +} + +void SessionStateChangedEventDispatcher::SetEventRouterForTesting( + EventRouter* event_router) { + event_router_ = event_router; +} + +} // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.h b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.h new file mode 100644 index 0000000..dad82be8 --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.h
@@ -0,0 +1,79 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_STATE_SESSION_STATE_CHANGED_EVENT_DISPATCHER_H_ +#define CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_STATE_SESSION_STATE_CHANGED_EVENT_DISPATCHER_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/scoped_observer.h" +#include "chrome/common/extensions/api/login_state.h" +#include "components/session_manager/core/session_manager.h" +#include "components/session_manager/core/session_manager_observer.h" +#include "extensions/browser/browser_context_keyed_api_factory.h" +#include "extensions/browser/event_router_factory.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace extensions { + +class EventRouter; + +// |SessionStateChangedEventDispatcher| observes changes in the session state +// and dispatches them to extensions listening on the +// |loginState.onSessionStateChanged| event. +class SessionStateChangedEventDispatcher + : public session_manager::SessionManagerObserver, + public BrowserContextKeyedAPI { + public: + // BrowserContextKeyedAPI implementation. + static BrowserContextKeyedAPIFactory<SessionStateChangedEventDispatcher>* + GetFactoryInstance(); + void Shutdown() override; + + explicit SessionStateChangedEventDispatcher( + content::BrowserContext* browser_context_); + ~SessionStateChangedEventDispatcher() override; + + // SessionManagerObserver implementation. + void OnSessionStateChanged() override; + + void SetEventRouterForTesting(EventRouter* event_router); + + private: + // Needed for BrowserContextKeyedAPI implementation. + friend class BrowserContextKeyedAPIFactory< + SessionStateChangedEventDispatcher>; + + // BrowserContextKeyedAPI implementation. + static const char* service_name() { + return "SessionStateChangedEventDispatcher"; + } + static const bool kServiceIsNULLWhileTesting = true; + + ScopedObserver<session_manager::SessionManager, + session_manager::SessionManagerObserver> + session_manager_observer_; + content::BrowserContext* browser_context_; + EventRouter* event_router_; + api::login_state::SessionState session_state_; + + DISALLOW_COPY_AND_ASSIGN(SessionStateChangedEventDispatcher); +}; + +template <> +struct BrowserContextFactoryDependencies<SessionStateChangedEventDispatcher> { + static void DeclareFactoryDependencies( + BrowserContextKeyedAPIFactory<SessionStateChangedEventDispatcher>* + factory) { + factory->DependsOn(EventRouterFactory::GetInstance()); + } +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_LOGIN_SCREEN_LOGIN_STATE_SESSION_STATE_CHANGED_EVENT_DISPATCHER_H_
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_apitest.cc b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_apitest.cc new file mode 100644 index 0000000..72f99a2b --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_apitest.cc
@@ -0,0 +1,45 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_apitest.h" +#include "components/session_manager/core/session_manager.h" +#include "components/session_manager/session_manager_types.h" +#include "extensions/test/extension_test_message_listener.h" +#include "extensions/test/result_catcher.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +using SessionStateChangedEventDispatcherApitest = ExtensionApiTest; + +IN_PROC_BROWSER_TEST_F(SessionStateChangedEventDispatcherApitest, + OnSessionStateDetailsChanged) { + session_manager::SessionManager* session_manager = + session_manager::SessionManager::Get(); + ASSERT_TRUE(RunExtensionTest( + "login_screen_apis/login_state/on_session_state_changed")); + + // Test cases are rearranged as the event is not fired if the mapped session + // state is the same. + const struct { + const session_manager::SessionState session_state; + const char* expected; + } kTestCases[] = { + {session_manager::SessionState::OOBE, "IN_OOBE_SCREEN"}, + {session_manager::SessionState::LOGIN_PRIMARY, "IN_LOGIN_SCREEN"}, + {session_manager::SessionState::LOCKED, "IN_LOCK_SCREEN"}, + {session_manager::SessionState::LOGGED_IN_NOT_ACTIVE, "IN_LOGIN_SCREEN"}, + {session_manager::SessionState::ACTIVE, "IN_SESSION"}, + {session_manager::SessionState::LOGIN_SECONDARY, "IN_LOGIN_SCREEN"}, + {session_manager::SessionState::UNKNOWN, "UNKNOWN"}, + }; + + for (const auto& test : kTestCases) { + ExtensionTestMessageListener listener(test.expected, /*will_reply=*/false); + session_manager->SetSessionState(test.session_state); + ASSERT_TRUE(listener.WaitUntilSatisfied()); + } +} + +} // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_unittest.cc new file mode 100644 index 0000000..6121faa6 --- /dev/null +++ b/chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_unittest.cc
@@ -0,0 +1,122 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.h" + +#include <memory> +#include <string> + +#include "base/logging.h" +#include "base/values.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/session_manager/session_manager_types.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_service_manager_context.h" +#include "extensions/browser/event_router.h" +#include "extensions/browser/test_event_router_observer.h" +#include "testing/gtest/include/gtest/gtest.h" + +using extensions::api::login_state::OnSessionStateChanged::kEventName; + +namespace { + +bool WasSessionStateChangedEventDispatched( + const extensions::TestEventRouterObserver* observer, + extensions::api::login_state::SessionState expected_state) { + const auto& event_map = observer->events(); + auto iter = event_map.find(kEventName); + if (iter == event_map.end()) { + return false; + } + + const extensions::Event& event = *iter->second; + CHECK(event.event_args); + CHECK_EQ(1u, event.event_args->GetList().size()); + std::string session_state = (event.event_args->GetList())[0].GetString(); + return extensions::api::login_state::ParseSessionState(session_state) == + expected_state; +} + +} // namespace + +namespace extensions { + +class SessionStateChangedEventDispatcherUnittest : public testing::Test { + public: + SessionStateChangedEventDispatcherUnittest() {} + ~SessionStateChangedEventDispatcherUnittest() override = default; + + void SetUp() override { + // |session_manager::SessionManager| is not initialized by default. This + // sets up the static instance of |SessionManager| so + // |session_manager::SessionManager::Get()| will return this particular + // instance. + session_manager_ = std::make_unique<session_manager::SessionManager>(); + profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager_->SetUp()); + testing_profile_ = + profile_manager_->CreateTestingProfile(chrome::kInitialProfile); + dispatcher_ = + std::make_unique<SessionStateChangedEventDispatcher>(testing_profile_); + event_router_ = std::make_unique<EventRouter>(testing_profile_, nullptr); + dispatcher_->SetEventRouterForTesting(event_router_.get()); + observer_ = std::make_unique<TestEventRouterObserver>(event_router_.get()); + } + + void TearDown() override { + testing_profile_ = nullptr; + profile_manager_->DeleteTestingProfile(chrome::kInitialProfile); + } + + protected: + content::TestBrowserThreadBundle thread_bundle_; + content::TestServiceManagerContext service_manager_context_; + TestingProfile* testing_profile_; + std::unique_ptr<session_manager::SessionManager> session_manager_; + std::unique_ptr<SessionStateChangedEventDispatcher> dispatcher_; + std::unique_ptr<TestingProfileManager> profile_manager_; + std::unique_ptr<EventRouter> event_router_; + std::unique_ptr<TestEventRouterObserver> observer_; + + private: + DISALLOW_COPY_AND_ASSIGN(SessionStateChangedEventDispatcherUnittest); +}; + +// Test that |OnSessionStateChanged| is dispatched when the session state +// changes. +TEST_F(SessionStateChangedEventDispatcherUnittest, EventIsDispatched) { + session_manager_->SetSessionState(session_manager::SessionState::ACTIVE); + EXPECT_TRUE(WasSessionStateChangedEventDispatched( + observer_.get(), + api::login_state::SessionState::SESSION_STATE_IN_SESSION)); + + session_manager_->SetSessionState(session_manager::SessionState::LOCKED); + EXPECT_TRUE(WasSessionStateChangedEventDispatched( + observer_.get(), + api::login_state::SessionState::SESSION_STATE_IN_LOCK_SCREEN)); +} + +// Test that the event is not dispatched when the mapped +// |api::login_state::SessionState| is the same even when the +// |session_manager::SessionState| is different. +TEST_F(SessionStateChangedEventDispatcherUnittest, + EventIsNotDispatchedWhenSessionStateIsSame) { + session_manager_->SetSessionState( + session_manager::SessionState::LOGIN_PRIMARY); + + EXPECT_TRUE(WasSessionStateChangedEventDispatched( + observer_.get(), + api::login_state::SessionState::SESSION_STATE_IN_LOGIN_SCREEN)); + observer_->ClearEvents(); + + session_manager_->SetSessionState( + session_manager::SessionState::LOGGED_IN_NOT_ACTIVE); + EXPECT_TRUE(observer_->events().empty()); +} + +} // namespace extensions
diff --git a/chrome/browser/chromeos/input_method/textinput_test_helper.cc b/chrome/browser/chromeos/input_method/textinput_test_helper.cc index 084e59af..457ac346 100644 --- a/chrome/browser/chromeos/input_method/textinput_test_helper.cc +++ b/chrome/browser/chromeos/input_method/textinput_test_helper.cc
@@ -24,9 +24,8 @@ namespace chromeos { -void TextInputTestBase::SetUpInProcessBrowserTestFixture() { - ui::SetUpInputMethodFactoryForTesting(); -} +TextInputTestBase::TextInputTestBase() = default; +TextInputTestBase::~TextInputTestBase() = default; ui::InputMethod* TextInputTestBase::GetInputMethod() const { return browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod();
diff --git a/chrome/browser/chromeos/input_method/textinput_test_helper.h b/chrome/browser/chromeos/input_method/textinput_test_helper.h index eb1ead88..13186c6 100644 --- a/chrome/browser/chromeos/input_method/textinput_test_helper.h +++ b/chrome/browser/chromeos/input_method/textinput_test_helper.h
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "chrome/test/base/in_process_browser_test.h" +#include "ui/base/ime/init/input_method_factory.h" #include "ui/base/ime/input_method.h" #include "ui/base/ime/mock_input_method.h" #include "ui/base/ime/text_input_client.h" @@ -22,14 +23,14 @@ // The base class of text input testing. class TextInputTestBase : public InProcessBrowserTest { public: - TextInputTestBase() {} - ~TextInputTestBase() override {} - - void SetUpInProcessBrowserTestFixture() override; + TextInputTestBase(); + ~TextInputTestBase() override; ui::InputMethod* GetInputMethod() const; private: + ui::ScopedTestInputMethodFactory scoped_test_input_method_factory_; + DISALLOW_COPY_AND_ASSIGN(TextInputTestBase); };
diff --git a/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc b/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc index b1ab2e3..0da80d2 100644 --- a/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc +++ b/chrome/browser/extensions/api/storage/policy_value_store_unittest.cc
@@ -174,7 +174,7 @@ const base::Value value("111"); { ValueStoreChangeList changes; - changes.push_back(ValueStoreChange("aaa", nullptr, value.CreateDeepCopy())); + changes.push_back(ValueStoreChange("aaa", base::nullopt, value.Clone())); EXPECT_CALL(observer_, OnSettingsChanged(kTestExtensionId, settings_namespace::MANAGED, @@ -190,7 +190,7 @@ // Notify when new policies are added. { ValueStoreChangeList changes; - changes.push_back(ValueStoreChange("bbb", nullptr, value.CreateDeepCopy())); + changes.push_back(ValueStoreChange("bbb", base::nullopt, value.Clone())); EXPECT_CALL(observer_, OnSettingsChanged(kTestExtensionId, settings_namespace::MANAGED, @@ -206,8 +206,8 @@ const base::Value new_value("222"); { ValueStoreChangeList changes; - changes.push_back(ValueStoreChange("bbb", value.CreateDeepCopy(), - new_value.CreateDeepCopy())); + changes.push_back( + ValueStoreChange("bbb", value.Clone(), new_value.Clone())); EXPECT_CALL(observer_, OnSettingsChanged(kTestExtensionId, settings_namespace::MANAGED, @@ -224,7 +224,7 @@ { ValueStoreChangeList changes; changes.push_back( - ValueStoreChange("bbb", new_value.CreateDeepCopy(), nullptr)); + ValueStoreChange("bbb", new_value.Clone(), base::nullopt)); EXPECT_CALL(observer_, OnSettingsChanged(kTestExtensionId, settings_namespace::MANAGED,
diff --git a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc index 7088ea82..28d68f7d 100644 --- a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc +++ b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
@@ -191,7 +191,7 @@ std::string key = base::DictionaryValue::Iterator(*local_state).key(); std::unique_ptr<base::Value> value; local_state->RemoveWithoutPathExpansion(key, &value); - changes.push_back(ValueStoreChange(key, nullptr, std::move(value))); + changes.push_back(ValueStoreChange(key, base::nullopt, std::move(*value))); } syncer::SyncError error = sync_processor_->SendChanges(changes); @@ -356,7 +356,8 @@ result.status().message.c_str()), sync_processor_->type()); } - changes->push_back(ValueStoreChange(key, nullptr, std::move(new_value))); + changes->push_back( + ValueStoreChange(key, base::nullopt, std::move(*new_value))); return syncer::SyncError(); } @@ -377,7 +378,7 @@ sync_processor_->type()); } changes->push_back( - ValueStoreChange(key, std::move(old_value), std::move(new_value))); + ValueStoreChange(key, std::move(*old_value), std::move(*new_value))); return syncer::SyncError(); } @@ -394,7 +395,8 @@ result.status().message.c_str()), sync_processor_->type()); } - changes->push_back(ValueStoreChange(key, std::move(old_value), nullptr)); + changes->push_back( + ValueStoreChange(key, std::move(*old_value), base::nullopt)); return syncer::SyncError(); }
diff --git a/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc b/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc index 1377f468..6a0c9a2 100644 --- a/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc +++ b/chrome/browser/extensions/api/tabs/tabs_util_chromeos.cc
@@ -27,14 +27,6 @@ void SetLockedFullscreenState(Browser* browser, bool locked) { UMA_HISTOGRAM_BOOLEAN("Extensions.LockedFullscreenStateRequest", locked); - // Disable ChromeVox before entering locked fullscreen. Quickfix for - // crbug.com/957950. - auto* const accessibility_manager = chromeos::AccessibilityManager::Get(); - if (locked && accessibility_manager && - accessibility_manager->IsSpokenFeedbackEnabled()) { - accessibility_manager->EnableSpokenFeedback(false); - } - aura::Window* window = browser->window()->GetNativeWindow(); // TRUSTED_PINNED is used here because that one locks the window fullscreen // without allowing the user to exit (as opposed to regular PINNED).
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index a0281498..7433228 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2716,7 +2716,7 @@ { "name": "out-of-blink-cors", "owners": [ "toyoshim" ], - "expiry_milestone": 76 + "expiry_milestone": 80 }, { "name": "overlay-new-layout",
diff --git a/chrome/browser/password_manager/password_generation_interactive_uitest.cc b/chrome/browser/password_manager/password_generation_interactive_uitest.cc index efabc0a..44b3b8a 100644 --- a/chrome/browser/password_manager/password_generation_interactive_uitest.cc +++ b/chrome/browser/password_manager/password_generation_interactive_uitest.cc
@@ -19,7 +19,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/common/autofill_features.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_generation_frame_helper.h" #include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/test_password_store.h" @@ -120,7 +120,7 @@ client->SetTestObserver(&observer_); // The base class should enable password generation. ASSERT_NE(password_manager::NOT_SYNCING, client->GetPasswordSyncState()); - password_manager::NewPasswordFormManager:: + password_manager::PasswordFormManager:: set_wait_for_server_predictions_for_filling(false); NavigateToFile("/password/signup_form_new_password.html");
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index a88873b..3780e59 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -46,7 +46,7 @@ #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" #include "components/password_manager/core/browser/http_auth_manager.h" #include "components/password_manager/core/browser/http_auth_observer.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/test_password_store.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/version_info/version_info.h" @@ -84,8 +84,8 @@ PasswordManagerBrowserTest() { // Turn off waiting for server predictions before filing. It makes filling // behaviour more deterministic. Filling with server predictions is tested - // in NewPasswordFormManager unit tests. - password_manager::NewPasswordFormManager:: + // in PasswordFormManager unit tests. + password_manager::PasswordFormManager:: set_wait_for_server_predictions_for_filling(false); }
diff --git a/chrome/browser/password_manager/password_manager_interactive_uitest.cc b/chrome/browser/password_manager/password_manager_interactive_uitest.cc index e84492cc..0efdf04 100644 --- a/chrome/browser/password_manager/password_manager_interactive_uitest.cc +++ b/chrome/browser/password_manager/password_manager_interactive_uitest.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" #include "components/autofill/core/common/autofill_features.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/test_password_store.h" #include "content/public/test/browser_test_utils.h" @@ -32,8 +32,8 @@ PasswordManagerInteractiveTest() { // Turn off waiting for server predictions before filing. It makes filling // behaviour more deterministic. Filling with server predictions is tested - // in NewPasswordFormManager unit tests. - password_manager::NewPasswordFormManager:: + // in PasswordFormManager unit tests. + password_manager::PasswordFormManager:: set_wait_for_server_predictions_for_filling(false); } ~PasswordManagerInteractiveTest() override = default;
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc index 37ce593..6f4bdd720 100644 --- a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc +++ b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
@@ -16,7 +16,7 @@ #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/fake_form_fetcher.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" @@ -29,12 +29,12 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" -using password_manager::NewPasswordFormManager; +using password_manager::PasswordFormManager; using password_manager::PasswordFormMetricsRecorder; namespace { -class MockPasswordFormManager : public NewPasswordFormManager { +class MockPasswordFormManager : public PasswordFormManager { public: MOCK_METHOD0(PermanentlyBlacklist, void()); @@ -44,18 +44,17 @@ const autofill::FormData& form, password_manager::FormFetcher* form_fetcher, scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder) - : NewPasswordFormManager( - client, - driver, - form, - form_fetcher, - std::make_unique<password_manager::StubFormSaver>(), - metrics_recorder) {} + : PasswordFormManager(client, + driver, + form, + form_fetcher, + std::make_unique<password_manager::StubFormSaver>(), + metrics_recorder) {} // Constructor for federation credentials. MockPasswordFormManager(password_manager::PasswordManagerClient* client, const autofill::PasswordForm& form) - : NewPasswordFormManager( + : PasswordFormManager( client, std::make_unique<autofill::PasswordForm>(form), std::make_unique<password_manager::FakeFormFetcher>(), @@ -73,7 +72,7 @@ public: TestSavePasswordInfoBarDelegate( content::WebContents* web_contents, - std::unique_ptr<password_manager::NewPasswordFormManager> form_to_save, + std::unique_ptr<password_manager::PasswordFormManager> form_to_save, bool is_smartlock_branding_enabled) : SavePasswordInfoBarDelegate(web_contents, std::move(form_to_save), @@ -100,7 +99,7 @@ protected: std::unique_ptr<PasswordManagerInfoBarDelegate> CreateDelegate( - std::unique_ptr<password_manager::NewPasswordFormManager> + std::unique_ptr<password_manager::PasswordFormManager> password_form_manager, bool is_smartlock_branding_enabled); @@ -132,8 +131,8 @@ observed_form_.fields.push_back(field); // Turn off waiting for server predictions in order to avoid dealing with - // posted tasks in NewPasswordFormManager. - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); + // posted tasks in PasswordFormManager. + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); } PrefService* SavePasswordInfoBarDelegateTest::prefs() { @@ -161,7 +160,7 @@ std::unique_ptr<PasswordManagerInfoBarDelegate> SavePasswordInfoBarDelegateTest::CreateDelegate( - std::unique_ptr<password_manager::NewPasswordFormManager> + std::unique_ptr<password_manager::PasswordFormManager> password_form_manager, bool is_smartlock_branding_enabled) { std::unique_ptr<PasswordManagerInfoBarDelegate> delegate(
diff --git a/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc b/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc index caf3b39..546557b 100644 --- a/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc +++ b/chrome/browser/password_manager/update_password_infobar_delegate_android_unittest.cc
@@ -13,14 +13,14 @@ #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/fake_form_fetcher.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" -using password_manager::NewPasswordFormManager; +using password_manager::PasswordFormManager; namespace { @@ -28,7 +28,7 @@ public: TestUpdatePasswordInfoBarDelegate( content::WebContents* web_contents, - std::unique_ptr<password_manager::NewPasswordFormManager> form_to_save, + std::unique_ptr<password_manager::PasswordFormManager> form_to_save, bool is_smartlock_branding_enabled) : UpdatePasswordInfoBarDelegate(web_contents, std::move(form_to_save), @@ -49,12 +49,12 @@ void TearDown() override; const autofill::PasswordForm& test_form() { return test_form_; } - std::unique_ptr<password_manager::NewPasswordFormManager> + std::unique_ptr<password_manager::PasswordFormManager> CreateTestFormManager(); protected: std::unique_ptr<PasswordManagerInfoBarDelegate> CreateDelegate( - std::unique_ptr<password_manager::NewPasswordFormManager> + std::unique_ptr<password_manager::PasswordFormManager> password_form_manager, bool is_smartlock_branding_enabled); @@ -86,8 +86,8 @@ observed_form_.fields.push_back(field); // Turn off waiting for server predictions in order to avoid dealing with - // posted tasks in NewPasswordFormManager. - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); + // posted tasks in PasswordFormManager. + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); } void UpdatePasswordInfoBarDelegateTest::SetUp() { @@ -102,9 +102,9 @@ ChromeRenderViewHostTestHarness::TearDown(); } -std::unique_ptr<password_manager::NewPasswordFormManager> +std::unique_ptr<password_manager::PasswordFormManager> UpdatePasswordInfoBarDelegateTest::CreateTestFormManager() { - auto manager = std::make_unique<password_manager::NewPasswordFormManager>( + auto manager = std::make_unique<password_manager::PasswordFormManager>( &client_, driver_.AsWeakPtr(), observed_form_, &fetcher_, std::make_unique<password_manager::StubFormSaver>(), nullptr /* metrics_recorder */); @@ -114,7 +114,7 @@ std::unique_ptr<PasswordManagerInfoBarDelegate> UpdatePasswordInfoBarDelegateTest::CreateDelegate( - std::unique_ptr<password_manager::NewPasswordFormManager> + std::unique_ptr<password_manager::PasswordFormManager> password_form_manager, bool is_smartlock_branding_enabled) { std::unique_ptr<PasswordManagerInfoBarDelegate> delegate( @@ -125,8 +125,8 @@ } TEST_F(UpdatePasswordInfoBarDelegateTest, HasDetailsMessageForSignedIn) { - std::unique_ptr<password_manager::NewPasswordFormManager> - password_form_manager(CreateTestFormManager()); + std::unique_ptr<password_manager::PasswordFormManager> password_form_manager( + CreateTestFormManager()); std::unique_ptr<PasswordManagerInfoBarDelegate> infobar( CreateDelegate(std::move(password_form_manager), true /* is_smartlock_branding_enabled */)); @@ -135,8 +135,8 @@ } TEST_F(UpdatePasswordInfoBarDelegateTest, EmptyDetailsMessageForNotSignedIn) { - std::unique_ptr<password_manager::NewPasswordFormManager> - password_form_manager(CreateTestFormManager()); + std::unique_ptr<password_manager::PasswordFormManager> password_form_manager( + CreateTestFormManager()); std::unique_ptr<PasswordManagerInfoBarDelegate> infobar( CreateDelegate(std::move(password_form_manager), false /* is_smartlock_branding_enabled */));
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index 4a2aaef..888f9e3 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -110,6 +110,7 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/android_sms/android_sms_service_factory.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" #include "chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_factory.h" @@ -271,8 +272,9 @@ chromeos::SyncedPrintersManagerFactory::GetInstance(); chromeos::smb_client::SmbServiceFactory::GetInstance(); crostini::CrostiniRegistryServiceFactory::GetInstance(); - TetherServiceFactory::GetInstance(); + extensions::SessionStateChangedEventDispatcher::GetFactoryInstance(); extensions::VerifyTrustAPI::GetFactoryInstance(); + TetherServiceFactory::GetInstance(); #endif FaviconServiceFactory::GetInstance(); HistoryUiFaviconRequestHandlerFactory::GetInstance();
diff --git a/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js b/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js index 466cdd9..d722859f 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js +++ b/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js
@@ -165,7 +165,7 @@ * @private */ async queryMojoDevicesInfo_() { - const deviceOperator = this.mojoConnector_.getDeviceOperator(); + const deviceOperator = await this.mojoConnector_.getDeviceOperator(); if (!deviceOperator) { return null; }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/main.js b/chrome/browser/resources/chromeos/camera/src/js/main.js index 90e941f7..bf1b2c95 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/main.js +++ b/chrome/browser/resources/chromeos/camera/src/js/main.js
@@ -210,12 +210,6 @@ */ document.addEventListener('DOMContentLoaded', async () => { const mojoConnector = new cca.mojo.MojoConnector(); - try { - await mojoConnector.initDeviceOperator(); - } catch (e) { - console.error(e); - } - if (!cca.App.instance_) { cca.App.instance_ = new cca.App(mojoConnector); }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js index a61e9558..62afa8a6 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js +++ b/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js
@@ -60,7 +60,7 @@ * @return {!Promise<!cca.mojo.PhotoCapabilities>} Promise for the result. */ cca.mojo.ImageCapture.prototype.getPhotoCapabilities = async function() { - const deviceOperator = this.mojoConnector_.getDeviceOperator(); + const deviceOperator = await this.mojoConnector_.getDeviceOperator(); const supportedEffects = [cros.mojom.Effect.NO_EFFECT]; const isPortraitModeSupported = await deviceOperator.isPortraitModeSupported(this.deviceId_); @@ -91,7 +91,7 @@ if (photoEffects) { for (const effect of photoEffects) { const take = (async () => { - const deviceOperator = this.mojoConnector_.getDeviceOperator(); + const deviceOperator = await this.mojoConnector_.getDeviceOperator(); const device = deviceOperator.getDevice(this.deviceId_); const {status, blob} = await device.setReprocessOption(effect); if (status !== 0) {
diff --git a/chrome/browser/resources/chromeos/camera/src/js/mojo/mojo_connector.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/mojo_connector.js index 7c08977..064aea0 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/mojo/mojo_connector.js +++ b/chrome/browser/resources/chromeos/camera/src/js/mojo/mojo_connector.js
@@ -33,6 +33,13 @@ * @private */ this.deviceOperator_ = null; + + /** + * Promise that indicates if the device operator is ready. + * @type {!Promise} + * @private + */ + this.isDeviceOperatorReady_ = this.initDeviceOperator(); } /** @@ -69,19 +76,21 @@ */ async reset() { this.deviceOperator_ = null; - try { - await this.initDeviceOperator(); - } catch (e) { - console.error(e); - } + this.isDeviceOperatorReady_ = this.initDeviceOperator(); } /** * Gets the device operator. - * @return {?cca.mojo.DeviceOperator} The video capture device operator. For - * non-v3 devices, it returns null. + * @return {!Promise<?cca.mojo.DeviceOperator>} The video capture device + * operator. For non-v3 devices, it returns null. */ - getDeviceOperator() { + async getDeviceOperator() { + try { + await this.isDeviceOperatorReady_; + } catch (e) { + console.error(e); + return null; + } return this.deviceOperator_; } };
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js index 7ed7bc8..6765c76 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js +++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
@@ -58,8 +58,8 @@ * @type {cca.views.camera.Options} * @private */ - this.options_ = new cca.views.camera.Options( - infoUpdater, mojoConnector, this.restart.bind(this)); + this.options_ = + new cca.views.camera.Options(infoUpdater, this.restart.bind(this)); /** * @type {HTMLElement} @@ -277,7 +277,7 @@ */ cca.views.Camera.prototype.startWithDevice_ = async function(deviceId) { let supportedModes = null; - const deviceOperator = this.mojoConnector_.getDeviceOperator(); + const deviceOperator = await this.mojoConnector_.getDeviceOperator(); for (const mode of this.modes_.getModeCandidates()) { try { if (!deviceId) {
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js index 608b939..fd97e99 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js +++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
@@ -149,7 +149,7 @@ captureFactory: () => new cca.views.camera.Portrait( this.stream_, doSavePhoto, this.captureResolution_, mojoConnector), isSupported: async (stream) => { - const deviceOperator = mojoConnector.getDeviceOperator(); + const deviceOperator = await mojoConnector.getDeviceOperator(); if (!deviceOperator) { return false; }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js index 37ff9efd..69371f9 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js +++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js
@@ -22,12 +22,10 @@ /** * Creates a controller for the options of Camera view. * @param {cca.device.DeviceInfoUpdater} infoUpdater - * @param {cca.mojo.MojoConnector} mojoConnector * @param {function()} doSwitchDevice Callback to trigger device switching. * @constructor */ -cca.views.camera.Options = function( - infoUpdater, mojoConnector, doSwitchDevice) { +cca.views.camera.Options = function(infoUpdater, doSwitchDevice) { /** * @type {cca.device.DeviceInfoUpdater} * @private @@ -35,12 +33,6 @@ this.infoUpdater_ = infoUpdater; /** - * @type {cca.mojo.MojoConnector} - * @private - */ - this.mojoConnector_ = mojoConnector; - - /** * @type {function()} * @private */ @@ -262,82 +254,6 @@ }; /** - * Updates list of available video devices when changed, including the UI. - * Does nothing if refreshing is already in progress. - * @private - */ -cca.views.camera.Options.prototype.maybeRefreshVideoDeviceIds_ = function() { - if (this.refreshingVideoDeviceIds_) { - return; - } - this.refreshingVideoDeviceIds_ = true; - - this.videoDevices_ = navigator.mediaDevices.enumerateDevices().then( - (devices) => devices.filter((device) => device.kind == 'videoinput')); - - var multi = false; - this.videoDevices_.then((devices) => { - multi = devices.length >= 2; - }).catch(console.error).finally(() => { - cca.state.set('multi-camera', multi); - this.refreshingVideoDeviceIds_ = false; - }); - - this.devicesPrivateInfo_ = (async () => { - const devices = await this.videoDevices_; - - const deviceOperator = this.mojoConnector_.getDeviceOperator(); - if (!deviceOperator) { - cca.state.set('no-resolution-settings', true); - throw new Error('HALv1-api'); - } - return await Promise.all(devices.map( - (d) => cca.device.Camera3DeviceInfo.create(d, deviceOperator))); - })(); - - (async () => { - try { - var devicesPrivateInfo = await this.devicesPrivateInfo_; - } catch (e) { - if (e.message == 'HALv1-api') { - return; - } - throw e; - } - let frontSetting = null; - let backSetting = null; - let externalSettings = []; - devicesPrivateInfo.forEach((info) => { - const setting = [info.deviceId, info.photoResols, info.videoResols]; - switch (info.facing) { - case cros.mojom.CameraFacing.CAMERA_FACING_FRONT: - frontSetting = setting; - break; - case cros.mojom.CameraFacing.CAMERA_FACING_BACK: - backSetting = setting; - break; - case cros.mojom.CameraFacing.CAMERA_FACING_EXTERNAL: - externalSettings.push(setting); - break; - default: - console.error(`Ignore device of unknown facing: ${info.facing}`); - } - }); - this.photoResolPreferrer_.updateResolutions( - frontSetting && [frontSetting[0], frontSetting[1]], - backSetting && [backSetting[0], backSetting[1]], - externalSettings.map(([deviceId, photoRs]) => [deviceId, photoRs])); - this.videoPreferrer_.updateResolutions( - frontSetting && [frontSetting[0], frontSetting[2]], - backSetting && [backSetting[0], backSetting[2]], - externalSettings.map(([deviceId, , videoRs]) => [deviceId, videoRs])); - - this.videoPreferrer_.updateFpses(devicesPrivateInfo.map( - (info) => [info.deviceId, info.videoMaxFps, info.fpsRanges])); - })(); -}; - -/** * Gets the video device ids sorted by preference. * @async * @return {Array<?string>} May contain null for user facing camera on HALv1
diff --git a/chrome/browser/resources/chromeos/login/security_token_pin.html b/chrome/browser/resources/chromeos/login/security_token_pin.html index 9ff5c11..03012d6 100644 --- a/chrome/browser/resources/chromeos/login/security_token_pin.html +++ b/chrome/browser/resources/chromeos/login/security_token_pin.html
@@ -67,7 +67,18 @@ <div id="errorContainer" problem hidden="[[!hasError_(parameters, userEdited_)]]"> <iron-icon id="errorIcon" icon="cr:error-outline"></iron-icon> - [[getErrorText_(parameters, userEdited_)]] + <span hidden="[[!isErrorLabelVisible_( + errorLabelId_, userEdited_)]]"> + [[i18nDynamic(locale, errorLabelId_)]] + </span> + <span hidden="[[!isErrorLabelVisible_( + errorLabelId_, userEdited_)]]"> + [[i18nDynamic(locale, 'securityTokenPinDialogTryAgain')]] + </span> + <span hidden="[[!isAttemptsLeftVisible_(parameters)]]"> + [[i18nDynamic(locale, 'securityTokenPinDialogAttemptsLeft', + parameters.attemptsLeft)]] + </span> </div> </pin-keyboard> </div>
diff --git a/chrome/browser/resources/chromeos/login/security_token_pin.js b/chrome/browser/resources/chromeos/login/security_token_pin.js index 84d4762..3d9cd29 100644 --- a/chrome/browser/resources/chromeos/login/security_token_pin.js +++ b/chrome/browser/resources/chromeos/login/security_token_pin.js
@@ -27,6 +27,16 @@ }, /** + * The i18n string ID containing the error label to be shown to the user. + * Is undefined when there's no error label. + * @private + */ + errorLabelId_: { + type: String, + computed: 'computeErrorLabelId_(parameters)', + }, + + /** * Whether the current state is the wait for the processing completion * (i.e., the backend is verifying the entered PIN). * @private @@ -44,6 +54,31 @@ userEdited_: { type: Boolean, value: false, + }, + }, + + /** + * Returns the i18n string ID for the current error label. + * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters + * @return {string|undefined} + * @private + */ + computeErrorLabelId_: function(parameters) { + if (!parameters) + return; + switch (parameters.errorLabel) { + case OobeTypes.SecurityTokenPinDialogErrorType.NONE: + return; + case OobeTypes.SecurityTokenPinDialogErrorType.UNKNOWN: + return 'securityTokenPinDialogUnknownError'; + case OobeTypes.SecurityTokenPinDialogErrorType.INVALID_PIN: + return 'securityTokenPinDialogUnknownInvalidPin'; + case OobeTypes.SecurityTokenPinDialogErrorType.INVALID_PUK: + return 'securityTokenPinDialogUnknownInvalidPuk'; + case OobeTypes.SecurityTokenPinDialogErrorType.MAX_ATTEMPTS_EXCEEDED: + return 'securityTokenPinDialogUnknownMaxAttemptsExceeded'; + default: + assertNotReached(`Unexpected enum value: ${parameters.errorLabel}`); } }, @@ -107,66 +142,23 @@ }, /** - * Returns the text of the error message to be displayed to the user. - * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters + * Returns whether the error label should be shown. + * @param {string} errorLabelId * @param {boolean} userEdited - * @return {string} + * @return {boolean} * @private */ - getErrorText_: function(parameters, userEdited) { - if (!this.hasError_(parameters, userEdited)) - return ''; - return [ - this.formatErrorLabel_(parameters, userEdited), - this.formatAttemptsLeft_(parameters) - ].join(' '); + isErrorLabelVisible_: function(errorLabelId, userEdited) { + return errorLabelId && !userEdited; }, /** - * Returns the formatted PIN error label to be displayed to the user. + * Returns whether the PIN attempts left count should be shown. * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters - * @param {boolean} userEdited - * @return {string} + * @return {boolean} * @private */ - formatErrorLabel_: function(parameters, userEdited) { - if (!parameters || userEdited) - return ''; - var errorLabel = ''; - // TODO(crbug.com/964069): Make strings localized. - switch (parameters.errorLabel) { - case OobeTypes.SecurityTokenPinDialogErrorType.NONE: - break; - case OobeTypes.SecurityTokenPinDialogErrorType.UNKNOWN: - errorLabel = 'Unknown error.'; - break; - case OobeTypes.SecurityTokenPinDialogErrorType.INVALID_PIN: - errorLabel = 'Invalid PIN.'; - break; - case OobeTypes.SecurityTokenPinDialogErrorType.INVALID_PUK: - errorLabel = 'Invalid PUK.'; - break; - case OobeTypes.SecurityTokenPinDialogErrorType.MAX_ATTEMPTS_EXCEEDED: - errorLabel = 'Maximum allowed attempts exceeded.'; - break; - default: - assertNotReached(`Unexpected enum value: ${parameters.errorLabel}`); - } - if (errorLabel && parameters.enableUserInput) - errorLabel = `${errorLabel} Please try again.`; - return errorLabel; - }, - - /** - * Returns the formatted PIN attempts left count to be displayed to the user. - * @param {OobeTypes.SecurityTokenPinDialogParameters} parameters - * @return {string} - * @private - */ - formatAttemptsLeft_: function(parameters) { - if (!parameters || parameters.attemptsLeft == -1) - return ''; - // TODO(crbug.com/964069): Make the string localized. - return `Attempts left: ${parameters.attemptsLeft}`; + isAttemptsLeftVisible_: function(parameters) { + return parameters && parameters.attemptsLeft != -1; }, });
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html index 9f2ed4a..d015876 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html
@@ -17,7 +17,7 @@ display: flex; flex-direction: row; font-weight: 400; - height: 64px; + height: 48px; } #app-title {
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_permission_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_permission_view.html index 969d123b..6ab9e28 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_permission_view.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/arc_permission_view.html
@@ -35,17 +35,17 @@ <div class="header-text">$i18n{permissions}</div> </div> <app-management-permission-item class="subpermission-row" - icon="cr:location-on" + icon="app-management:location" permission-label="$i18n{location}" permission-type="LOCATION"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" - icon="cr:videocam" + icon="app-management:camera" permission-label="$i18n{camera}" permission-type="CAMERA"> </app-management-permission-item> <app-management-permission-item class="subpermission-row" - icon="cr:mic" + icon="app-management:microphone" permission-label="$i18n{microphone}" permission-type="MICROPHONE"> </app-management-permission-item>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/icons.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/icons.html index ccb1632..8997152 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/icons.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/icons.html
@@ -1,17 +1,19 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> -<iron-iconset-svg name="app-management" size="24"> +<iron-iconset-svg name="app-management" size="20"> <svg> <!-- - These icons are copied from material.io and kept in sorted order. + These icons are custom and kept in sorted order. See http://goo.gl/Y1OdAq for instructions on adding additional icons. + TODO: move these icons to a generic file when other pages need to use them. --> <defs> - <!-- From https://material.io/tools/icons/?icon=account_box&style=baseline --> - <g id="contacts"><path d="M19 3H5c-1.11 0-2 .89-2 2v14a2 2 0 0 0 2 2h14c1.1 0 2-.9 2-2V5a2 2 0 0 0-2-2zm-7 3c1.65 0 3 1.35 3 3 0 1.66-1.35 3-3 3s-3-1.34-3-3c0-1.65 1.35-3 3-3zm6 12H6v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1z"></path><path fill="none" d="M0 0h24v24H0z"></path></g> - <!-- From https://material.io/tools/icons/?icon=storage&style=baseline --> - <g id="storage"><path d="M2 20h20v-4H2v4zm2-3h2v2H4v-2zM2 4v4h20V4H2zm4 3H4V5h2v2zm-4 7h20v-4H2v4zm2-3h2v2H4v-2z"></path></g> + <g id="contacts" viewBox="0 0 20 20"><rect width="20px" height="20px" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"></rect><path d="M5,14.754629 C6.36959794,13.6567183 8.10810658,13 10,13 C11.8918934,13 13.6304021,13.6567183 15,14.754629 L15,6 L5,6 L5,14.754629 Z M14.153574,16 C13.0272557,15.0633182 11.5794129,14.5 10,14.5 C8.42058712,14.5 6.97274425,15.0633182 5.84642599,16 L14.153574,16 Z M10,12 C8.61928813,12 7.5,10.8807119 7.5,9.5 C7.5,8.11928813 8.61928813,7 10,7 C11.3807119,7 12.5,8.11928813 12.5,9.5 C12.5,10.8807119 11.3807119,12 10,12 Z M10,10.5 C10.5522847,10.5 11,10.0522847 11,9.5 C11,8.94771525 10.5522847,8.5 10,8.5 C9.44771525,8.5 9,8.94771525 9,9.5 C9,10.0522847 9.44771525,10.5 10,10.5 Z M5,4 L15,4 C16.1045695,4 17,4.8954305 17,6 L17,16 C17,17.1045695 16.1045695,18 15,18 L5,18 C3.8954305,18 3,17.1045695 3,16 L3,6 C3,4.8954305 3.8954305,4 5,4 Z" id="Combined-Shape" fill="#5F6368"></path><rect id="Rectangle" fill="#5F6368" x="6" y="2" width="2" height="2"></rect><rect id="Rectangle-Copy" fill="#5F6368" x="12" y="2" width="2" height="2"></rect></g> + <g id="storage" viewBox="0 0 20 20"><rect width="20px" height="20px" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"></rect><path fill="#5F6368" d="M16,5 L12,5 L10,3 L4,3 C2.9,3 2.01,3.9 2.01,5 L2,15 C2,16.1 2.9,17 4,17 L16,17 C17.1,17 18,16.1 18,15 L18,7 C18,5.9 17.1,5 16,5 Z M16,15 L4,15 L4,7 L16,7 L16,15 Z"></path></g> + <g id="location" viewBox="0 0 20 20"><rect width="20px" height="20px" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"></rect><path d="M10,18 C6,13.5424723 4,10.209139 4,8 C4,4.6862915 6.6862915,2 10,2 C13.3137085,2 16,4.6862915 16,8 C16,10.209139 14,13.5424723 10,18 Z M6,8 C6,9.32543171 7.3180021,11.7149155 10,14.9435167 C12.6819979,11.7149155 14,9.32543171 14,8 C14,5.790861 12.209139,4 10,4 C7.790861,4 6,5.790861 6,8 Z M10,10 C8.8954305,10 8,9.1045695 8,8 C8,6.8954305 8.8954305,6 10,6 C11.1045695,6 12,6.8954305 12,8 C12,9.1045695 11.1045695,10 10,10 Z" id="Combined-Shape" fill="#5F6368"></path></g> + <g id="camera" viewBox="0 0 20 20"><rect width="20px" height="20px" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"></rect><path d="M2,5.99539757 C2,5.44565467 2.44851311,5 3.00247329,5 L12.9975267,5 C13.5511774,5 14,5.44910619 14,5.99539757 L14,14.0046024 C14,14.5543453 13.5514869,15 12.9975267,15 L3.00247329,15 C2.44882258,15 2,14.5508938 2,14.0046024 L2,5.99539757 Z M14,8.5 L18,5.5 L18,14.5 L14,12 L14,8.5 Z M4,7 L4,13 L12,13 L12,7 L4,7 Z" id="Combined-Shape" fill="#5F6368"></path></g> + <g id="microphone" viewBox="0 0 20 20"><rect width="20px" height="20px" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"></rect><path d="M12.5628571,9.5 C12.5628571,10.8833333 11.4228571,12 10,12 C8.57714286,12 7.42857143,10.8833333 7.42857143,9.5 L7.42857143,4.5 C7.42857143,3.11666667 8.57714286,2 10,2 C11.4228571,2 12.5714286,3.11666667 12.5714286,4.5 L12.5628571,9.5 Z M10.0548096,3.5 C9.5012628,3.5 9.05131398,3.94643954 9.04697987,4.49996935 L9.0078297,9.50003065 C9.00780942,9.50262015 9.00779929,9.50520971 9.00779929,9.50779929 C9.00779929,10.0557766 9.45202268,10.5 10,10.5 C10.5535468,10.5 11.0034956,10.0535605 11.0078297,9.50003065 L11.0469799,4.49996935 C11.0470001,4.49737985 11.0470103,4.49479029 11.0470103,4.49220071 C11.0470103,3.94422339 10.6027869,3.5 10.0548096,3.5 Z M10,13.8736842 C7.63428571,13.8736842 5.45714286,12.1052632 5.45714286,9.57894737 L4,9.57894737 C4,12.4589474 6.33142857,14.8252632 9.14285714,15.2378947 L9.14285714,18 L10.8571429,18 L10.8571429,15.2378947 C13.6685714,14.8336842 16,12.4589474 16,9.57894737 L14.5428571,9.57894737 C14.5428571,12.1052632 12.3657143,13.8736842 10,13.8736842 Z" fill="#5F6368"></path></g> </defs> </svg> </iron-iconset-svg>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_permission_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_permission_view.html index 5441399..39cfada 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_permission_view.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/pwa_permission_view.html
@@ -1,10 +1,11 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="browser_proxy.html"> +<link rel="import" href="icons.html"> <link rel="import" href="permission_item.html"> +<link rel="import" href="pin_to_shelf_item.html"> <link rel="import" href="shared_style.html"> <link rel="import" href="store_client.html"> -<link rel="import" href="pin_to_shelf_item.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> @@ -29,16 +30,16 @@ <div class="header-text">$i18n{permissions}</div> </div> <app-management-permission-item id="location" - class="subpermission-row" icon="cr:location-on" + class="subpermission-row" icon="app-management:location" permission-label="$i18n{location}" permission-type="CONTENT_SETTINGS_TYPE_GEOLOCATION"> </app-management-permission-item> <app-management-permission-item id="camera" class="subpermission-row" - icon="cr:videocam" permission-label="$i18n{camera}" + icon="app-management:camera" permission-label="$i18n{camera}" permission-type="CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA"> </app-management-permission-item> <app-management-permission-item id="microphone" - class="subpermission-row" icon="cr:mic" + class="subpermission-row" icon="app-management:microphone" permission-label="$i18n{microphone}" permission-type="CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC"> </app-management-permission-item>
diff --git a/chrome/browser/sharing/sharing_metrics.cc b/chrome/browser/sharing/sharing_metrics.cc index 5b2ca502..7978055 100644 --- a/chrome/browser/sharing/sharing_metrics.cc +++ b/chrome/browser/sharing/sharing_metrics.cc
@@ -106,7 +106,7 @@ base::UmaHistogramMediumTimes("Sharing.MessageAckTime", time); } -void LogClickToCallDialogShown(SharingClickToCallDialogType type) { +void LogClickToCallDialogShown(SharingDialogType type) { base::UmaHistogramEnumeration("Sharing.ClickToCallDialogShown", type); }
diff --git a/chrome/browser/sharing/sharing_metrics.h b/chrome/browser/sharing/sharing_metrics.h index 415a810..9c37e8f 100644 --- a/chrome/browser/sharing/sharing_metrics.h +++ b/chrome/browser/sharing/sharing_metrics.h
@@ -23,11 +23,11 @@ kMaxValue = kExportPrivateKeyFailed, }; -// The types of dialogs that can be shown for Click to Call. +// The types of dialogs that can be shown for sharing features. // These values are logged to UMA. Entries should not be renumbered and numeric // values should never be reused. Please keep in sync with -// "SharingClickToCallDialogType" in src/tools/metrics/histograms/enums.xml. -enum class SharingClickToCallDialogType { +// "SharingDialogType" in src/tools/metrics/histograms/enums.xml. +enum class SharingDialogType { kDialogWithDevicesMaybeApps = 0, kDialogWithoutDevicesWithApp = 1, kEducationalDialog = 2, @@ -86,7 +86,7 @@ void LogSharingMessageAckTime(base::TimeDelta time); // Logs to UMA the |type| of dialog shown for Click to Call. -void LogClickToCallDialogShown(SharingClickToCallDialogType type); +void LogClickToCallDialogShown(SharingDialogType type); // Logs to UMA result of sending a SharingMessage. This should not be called for // sending ack messages.
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc index 03e4c2c..e44f73d 100644 --- a/chrome/browser/sync/chrome_sync_client.cc +++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" +#include "chrome/browser/password_manager/account_storage/account_password_store_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/prefs/pref_service_syncable_util.h" #include "chrome/browser/profiles/profile.h" @@ -184,14 +185,17 @@ DCHECK(!account_web_data_service_ || web_data_service_thread_ == account_web_data_service_->GetDBTaskRunner()); - password_store_ = PasswordStoreFactory::GetForProfile( + profile_password_store_ = PasswordStoreFactory::GetForProfile( + profile_, ServiceAccessType::IMPLICIT_ACCESS); + account_password_store_ = AccountPasswordStoreFactory::GetForProfile( profile_, ServiceAccessType::IMPLICIT_ACCESS); component_factory_ = std::make_unique<ProfileSyncComponentsFactoryImpl>( this, chrome::GetChannel(), prefs::kSavingBrowserHistoryDisabled, base::CreateSequencedTaskRunner({content::BrowserThread::UI}), web_data_service_thread_, profile_web_data_service_, - account_web_data_service_, password_store_, + account_web_data_service_, profile_password_store_, + account_password_store_, BookmarkSyncServiceFactory::GetForProfile(profile_)); } @@ -494,8 +498,8 @@ ->AsWeakPtr(); #endif // BUILDFLAG(ENABLE_SUPERVISED_USERS) case syncer::PASSWORDS: { - return password_store_.get() - ? password_store_->GetPasswordSyncableService() + return profile_password_store_.get() + ? profile_password_store_->GetPasswordSyncableService() : nullptr; } #if defined(OS_CHROMEOS) @@ -581,9 +585,12 @@ case syncer::GROUP_PASSIVE: return new syncer::PassiveModelWorker(); case syncer::GROUP_PASSWORD: { - if (!password_store_.get()) + // Note: This is only used for the directory implementation of passwords, + // not for USS, but only USS supports the account password store. So we + // can safely ignore the account store here. + if (!profile_password_store_.get()) return nullptr; - return new PasswordModelWorker(password_store_); + return new PasswordModelWorker(profile_password_store_); } default: return nullptr;
diff --git a/chrome/browser/sync/chrome_sync_client.h b/chrome/browser/sync/chrome_sync_client.h index f52eb2c..5282d0f 100644 --- a/chrome/browser/sync/chrome_sync_client.h +++ b/chrome/browser/sync/chrome_sync_client.h
@@ -77,7 +77,8 @@ // respective backend threads. scoped_refptr<autofill::AutofillWebDataService> profile_web_data_service_; scoped_refptr<autofill::AutofillWebDataService> account_web_data_service_; - scoped_refptr<password_manager::PasswordStore> password_store_; + scoped_refptr<password_manager::PasswordStore> profile_password_store_; + scoped_refptr<password_manager::PasswordStore> account_password_store_; // The task runner for the |web_data_service_|, if any. scoped_refptr<base::SequencedTaskRunner> web_data_service_thread_;
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc index 2792fc0f..cfce36a8 100644 --- a/chrome/browser/sync/profile_sync_service_factory.cc +++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/invalidation/deprecated_profile_invalidation_provider_factory.h" #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" +#include "chrome/browser/password_manager/account_storage/account_password_store_factory.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" @@ -52,6 +53,7 @@ #include "components/invalidation/impl/profile_invalidation_provider.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/network_time/network_time_tracker.h" +#include "components/password_manager/core/common/password_manager_features.h" #include "components/sync/driver/profile_sync_service.h" #include "components/sync/driver/sync_driver_switches.h" #include "content/public/browser/browser_context.h" @@ -130,6 +132,7 @@ // destruction order. Note that some of the dependencies are listed here but // actually plumbed in ChromeSyncClient, which this factory constructs. DependsOn(AboutSigninInternalsFactory::GetInstance()); + DependsOn(AccountPasswordStoreFactory::GetInstance()); DependsOn(autofill::PersonalDataManagerFactory::GetInstance()); DependsOn(BookmarkModelFactory::GetInstance()); DependsOn(BookmarkSyncServiceFactory::GetInstance()); @@ -196,6 +199,8 @@ init_params.autofill_enable_account_wallet_storage = base::FeatureList::IsEnabled( autofill::features::kAutofillEnableAccountWalletStorage); + init_params.enable_passwords_account_storage = base::FeatureList::IsEnabled( + password_manager::features::kEnablePasswordsAccountStorage); bool local_sync_backend_enabled = false;
diff --git a/chrome/browser/sync/test/integration/fake_server_invalidation_sender.cc b/chrome/browser/sync/test/integration/fake_server_invalidation_sender.cc new file mode 100644 index 0000000..1bc02e4 --- /dev/null +++ b/chrome/browser/sync/test/integration/fake_server_invalidation_sender.cc
@@ -0,0 +1,70 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/sync/test/integration/fake_server_invalidation_sender.h" + +#include "chrome/browser/profiles/profile.h" +#include "components/invalidation/impl/fcm_network_handler.h" + +namespace fake_server { + +namespace { + +const char kInvalidationsFCMAppId[] = "com.google.chrome.fcm.invalidations"; + +} // namespace + +FakeServerInvalidationSender::FakeServerInvalidationSender( + const std::string& client_id, + bool self_notify, + base::RepeatingCallback<syncer::FCMNetworkHandler*()> + fcm_network_handler_getter) + : client_id_(client_id), + self_notify_(self_notify), + fcm_network_handler_getter_(fcm_network_handler_getter) {} + +FakeServerInvalidationSender::~FakeServerInvalidationSender() {} + +void FakeServerInvalidationSender::OnCommit( + const std::string& committer_id, + syncer::ModelTypeSet committed_model_types) { + if (!self_notify_ && client_id_ == committer_id) { + return; + } + syncer::FCMNetworkHandler* fcm_network_handler = + fcm_network_handler_getter_.Run(); + // If there is no FCM network handler registered for this profile, there is + // nothing to do. This could be the case during test Setup phase because the + // FCM network handlers get assigned in SetupInvalidations() which happens + // after SetupSync(). + if (fcm_network_handler == nullptr) { + DLOG(WARNING) << "Received invalidations for the following data types in " + "invalidation sender " + << this << " will be dropped:" + << ModelTypeSetToString(committed_model_types); + return; + } + // For each of the committed model types, pass a message to the FCM Network + // Handler to simulate a message from the GCMDriver. + for (syncer::ModelType type : committed_model_types) { + std::string notification_type; + bool result = RealModelTypeToNotificationType(type, ¬ification_type); + // We shouldn't ever get commits for non-protocol types. + DCHECK(result); + + gcm::IncomingMessage message; + // Client doesn't parse the payload. + message.data["payload"] = "any_payload"; + // version doesn't matter, it's not used in the client. + message.data["version"] = "1234567890"; + // The public topic name should be stored in the external name field. + message.data["external_name"] = notification_type; + // The private topic name is stored in the sender_id field. + message.sender_id = + "/topics/private/" + notification_type + "-topic_server_user_id"; + fcm_network_handler->OnMessage(kInvalidationsFCMAppId, message); + } +} + +} // namespace fake_server
diff --git a/chrome/browser/sync/test/integration/fake_server_invalidation_sender.h b/chrome/browser/sync/test/integration/fake_server_invalidation_sender.h new file mode 100644 index 0000000..86ba61e --- /dev/null +++ b/chrome/browser/sync/test/integration/fake_server_invalidation_sender.h
@@ -0,0 +1,46 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_FAKE_SERVER_INVALIDATION_SENDER_H_ +#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_FAKE_SERVER_INVALIDATION_SENDER_H_ + +#include "base/macros.h" + +#include "components/sync/base/model_type.h" +#include "components/sync/test/fake_server/fake_server.h" + +namespace syncer { +class FCMNetworkHandler; +} + +namespace fake_server { + +// This class is observing changes to the fake server, and sends invalidations +// to different clients upon commits. Sent invalidation follows the same format +// expected by the FCM invalidations framework. +class FakeServerInvalidationSender : public FakeServer::Observer { + public: + FakeServerInvalidationSender( + const std::string& client_id, + bool self_notify, + base::RepeatingCallback<syncer::FCMNetworkHandler*()> + fcm_network_handler_getter); + ~FakeServerInvalidationSender() override; + + // FakeServer::Observer implementation. + void OnCommit(const std::string& committer_id, + syncer::ModelTypeSet committed_model_types) override; + + private: + const std::string client_id_; + const bool self_notify_; + const base::RepeatingCallback<syncer::FCMNetworkHandler*()> + fcm_network_handler_getter_; + + DISALLOW_COPY_AND_ASSIGN(FakeServerInvalidationSender); +}; + +} // namespace fake_server + +#endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_FAKE_SERVER_INVALIDATION_SENDER_H_
diff --git a/chrome/browser/sync/test/integration/fake_server_invalidation_service.cc b/chrome/browser/sync/test/integration/fake_server_invalidation_service.cc deleted file mode 100644 index cc0b6a8f..0000000 --- a/chrome/browser/sync/test/integration/fake_server_invalidation_service.cc +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/test/integration/fake_server_invalidation_service.h" - -#include "components/invalidation/impl/invalidation_service_util.h" -#include "components/invalidation/public/invalidation.h" -#include "components/invalidation/public/object_id_invalidation_map.h" -#include "components/sync/base/invalidation_helper.h" - -namespace fake_server { - -FakeServerInvalidationService::FakeServerInvalidationService() - : client_id_(invalidation::GenerateInvalidatorClientId()), - self_notify_(true) { - invalidator_registrar_.UpdateInvalidatorState(syncer::INVALIDATIONS_ENABLED); -} - -FakeServerInvalidationService::~FakeServerInvalidationService() { -} - -void FakeServerInvalidationService::RegisterInvalidationHandler( - syncer::InvalidationHandler* handler) { - invalidator_registrar_.RegisterHandler(handler); -} - -bool FakeServerInvalidationService::UpdateRegisteredInvalidationIds( - syncer::InvalidationHandler* handler, - const syncer::ObjectIdSet& ids) { - return invalidator_registrar_.UpdateRegisteredIds(handler, ids); -} - -void FakeServerInvalidationService::UnregisterInvalidationHandler( - syncer::InvalidationHandler* handler) { - invalidator_registrar_.UnregisterHandler(handler); -} - -syncer::InvalidatorState FakeServerInvalidationService::GetInvalidatorState() - const { - return invalidator_registrar_.GetInvalidatorState(); -} - -std::string FakeServerInvalidationService::GetInvalidatorClientId() const { - return client_id_; -} - -invalidation::InvalidationLogger* -FakeServerInvalidationService::GetInvalidationLogger() { - return nullptr; -} - -void FakeServerInvalidationService::RequestDetailedStatus( - base::Callback<void(const base::DictionaryValue&)> caller) const { - base::DictionaryValue value; - caller.Run(value); -} - -void FakeServerInvalidationService::EnableSelfNotifications() { - self_notify_ = true; -} - -void FakeServerInvalidationService::DisableSelfNotifications() { - self_notify_ = false; -} - -void FakeServerInvalidationService::OnCommit( - const std::string& committer_id, - syncer::ModelTypeSet committed_model_types) { - syncer::ObjectIdSet object_ids = syncer::ModelTypeSetToObjectIdSet( - committed_model_types); - syncer::ObjectIdInvalidationMap invalidation_map; - for (auto it = object_ids.begin(); it != object_ids.end(); ++it) { - // TODO(pvalenzuela): Create more refined invalidations instead of - // invalidating all items of a given type. - - if (self_notify_ || client_id_ != committer_id) { - invalidation_map.Insert(syncer::Invalidation::InitUnknownVersion(*it)); - } - } - invalidator_registrar_.DispatchInvalidationsToHandlers(invalidation_map); -} - -} // namespace fake_server
diff --git a/chrome/browser/sync/test/integration/fake_server_invalidation_service.h b/chrome/browser/sync/test/integration/fake_server_invalidation_service.h deleted file mode 100644 index 6306c40e..0000000 --- a/chrome/browser/sync/test/integration/fake_server_invalidation_service.h +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_FAKE_SERVER_INVALIDATION_SERVICE_H_ -#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_FAKE_SERVER_INVALIDATION_SERVICE_H_ - -#include <string> -#include <utility> - -#include "base/macros.h" -#include "components/invalidation/impl/deprecated_invalidator_registrar.h" -#include "components/invalidation/public/invalidation_service.h" -#include "components/sync/base/model_type.h" -#include "components/sync/test/fake_server/fake_server.h" - -namespace invalidation { -class InvalidationLogger; -} - -namespace fake_server { - -// An InvalidationService that is used in conjunction with FakeServer. -class FakeServerInvalidationService : public invalidation::InvalidationService, - public FakeServer::Observer { - public: - FakeServerInvalidationService(); - ~FakeServerInvalidationService() override; - - void RegisterInvalidationHandler( - syncer::InvalidationHandler* handler) override; - bool UpdateRegisteredInvalidationIds(syncer::InvalidationHandler* handler, - const syncer::ObjectIdSet& ids) override; - void UnregisterInvalidationHandler( - syncer::InvalidationHandler* handler) override; - - syncer::InvalidatorState GetInvalidatorState() const override; - std::string GetInvalidatorClientId() const override; - invalidation::InvalidationLogger* GetInvalidationLogger() override; - void RequestDetailedStatus( - base::Callback<void(const base::DictionaryValue&)> caller) const override; - - // Functions to enable or disable sending of self-notifications. In the real - // world, clients do not receive notifications of their own commits. - void EnableSelfNotifications(); - void DisableSelfNotifications(); - - // FakeServer::Observer: - void OnCommit(const std::string& committer_id, - syncer::ModelTypeSet committed_model_types) override; - - private: - std::string client_id_; - bool self_notify_; - - syncer::DeprecatedInvalidatorRegistrar invalidator_registrar_; - - DISALLOW_COPY_AND_ASSIGN(FakeServerInvalidationService); -}; - -} // namespace fake_server - -#endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_FAKE_SERVER_INVALIDATION_SERVICE_H_
diff --git a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc index 183995a..33d1417a 100644 --- a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
@@ -729,8 +729,19 @@ /*LOCAL_DELETION=*/0)); } +// Flaky (mostly) on ASan/TSan. http://crbug.com/998130 +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#define MAYBE_PRE_PersistProgressMarkerOnRestart \ + DISABLED_PRE_PersistProgressMarkerOnRestart +#define MAYBE_PersistProgressMarkerOnRestart \ + DISABLED_PersistProgressMarkerOnRestart +#else +#define MAYBE_PRE_PersistProgressMarkerOnRestart \ + PRE_PersistProgressMarkerOnRestart +#define MAYBE_PersistProgressMarkerOnRestart PersistProgressMarkerOnRestart +#endif IN_PROC_BROWSER_TEST_P(SingleClientBookmarksSyncTest, - PRE_PersistProgressMarkerOnRestart) { + MAYBE_PRE_PersistProgressMarkerOnRestart) { const std::string title = "Seattle Sounders FC"; fake_server::EntityBuilderFactory entity_builder_factory; fake_server::BookmarkEntityBuilder bookmark_builder = @@ -747,7 +758,7 @@ } IN_PROC_BROWSER_TEST_P(SingleClientBookmarksSyncTest, - PersistProgressMarkerOnRestart) { + MAYBE_PersistProgressMarkerOnRestart) { const std::string title = "Seattle Sounders FC"; fake_server::EntityBuilderFactory entity_builder_factory; fake_server::BookmarkEntityBuilder bookmark_builder =
diff --git a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc index 0251d94..da37ac68 100644 --- a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
@@ -162,7 +162,13 @@ EXPECT_TRUE(ExpectUserEvents({specifics1, specifics1, specifics2})); } -IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, RetryParallel) { +// Flaky (mostly) on ASan/TSan. http://crbug.com/998130 +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#define MAYBE_RetryParallel DISABLED_RetryParallel +#else +#define MAYBE_RetryParallel RetryParallel +#endif +IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, MAYBE_RetryParallel) { ASSERT_TRUE(SetupSync()); bool first = true; const UserEventSpecifics specifics1 =
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc index 24c5485..a67ab56c 100644 --- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -948,8 +948,16 @@ // Wallet data present on the client should be cleared in favor of the new data // synced down form the server. +// Flaky (mostly) on ASan/TSan. http://crbug.com/998130 +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#define MAYBE_NewWalletCardRemovesExistingCardAndProfile \ + DISABLED_NewWalletCardRemovesExistingCardAndProfile +#else +#define MAYBE_NewWalletCardRemovesExistingCardAndProfile \ + NewWalletCardRemovesExistingCardAndProfile +#endif IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, - NewWalletCardRemovesExistingCardAndProfile) { + MAYBE_NewWalletCardRemovesExistingCardAndProfile) { ASSERT_TRUE(SetupSync()); autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); @@ -1012,8 +1020,15 @@ // Wallet data present on the client should be cleared in favor of the new data // synced down form the server. +// Flaky (mostly) on ASan/TSan. http://crbug.com/998130 +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#define MAYBE_NewWalletDataRemovesExistingData \ + DISABLED_NewWalletDataRemovesExistingData +#else +#define MAYBE_NewWalletDataRemovesExistingData NewWalletDataRemovesExistingData +#endif IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, - NewWalletDataRemovesExistingData) { + MAYBE_NewWalletDataRemovesExistingData) { ASSERT_TRUE(SetupSync()); autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm); @@ -1119,8 +1134,16 @@ // Tests that a server billing address id set on a card on the client is // overwritten when that same card is synced again. +// Flaky (mostly) on ASan/TSan. http://crbug.com/998130 +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#define MAYBE_SameWalletCard_DiscardsOldServerBillingAddressId \ + DISABLED_SameWalletCard_DiscardsOldServerBillingAddressId +#else +#define MAYBE_SameWalletCard_DiscardsOldServerBillingAddressId \ + SameWalletCard_DiscardsOldServerBillingAddressId +#endif IN_PROC_BROWSER_TEST_F(SingleClientWalletSyncTest, - SameWalletCard_DiscardsOldServerBillingAddressId) { + MAYBE_SameWalletCard_DiscardsOldServerBillingAddressId) { ASSERT_TRUE(SetupSync()); autofill::PersonalDataManager* pdm = GetPersonalDataManager(0); ASSERT_NE(nullptr, pdm);
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index ec14123..b09fbc6 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -19,6 +19,7 @@ #include "build/build_config.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/gcm/gcm_profile_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h" #include "chrome/browser/net/system_network_context_manager.h" @@ -28,7 +29,6 @@ #include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "chrome/browser/sync/test/integration/fake_server_invalidation_service.h" #include "chrome/browser/sync/test/integration/p2p_sync_refresher.h" #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" @@ -46,14 +46,23 @@ #include "chrome/test/base/search_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/bookmarks/test/bookmark_test_helpers.h" +#include "components/gcm_driver/gcm_profile_service.h" +#include "components/invalidation/impl/fake_invalidation_service.h" +#include "components/invalidation/impl/fcm_invalidation_service.h" +#include "components/invalidation/impl/fcm_network_handler.h" +#include "components/invalidation/impl/invalidation_prefs.h" #include "components/invalidation/impl/invalidation_switches.h" +#include "components/invalidation/impl/per_user_topic_registration_manager.h" #include "components/invalidation/impl/profile_identity_provider.h" #include "components/invalidation/impl/profile_invalidation_provider.h" #include "components/invalidation/public/invalidation_service.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/keyed_service.h" #include "components/os_crypt/os_crypt_mocker.h" +#include "components/prefs/scoped_user_pref_update.h" #include "components/search_engines/template_url_service.h" #include "components/sync/base/invalidation_helper.h" +#include "components/sync/base/sync_base_switches.h" #include "components/sync/driver/profile_sync_service.h" #include "components/sync/driver/sync_driver_switches.h" #include "components/sync/driver/sync_user_settings.h" @@ -69,6 +78,7 @@ #include "net/base/port_util.h" #include "net/dns/mock_host_resolver.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "services/data_decoder/public/cpp/safe_json_parser.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "url/gurl.h" @@ -96,6 +106,8 @@ } // namespace switches namespace { +// Sender ID coming from the Firebase console. +const char kInvalidationGCMSenderId[] = "8181035976"; void SetURLLoaderFactoryForTest( Profile* profile, @@ -112,6 +124,58 @@ account_manager->SetUrlLoaderFactoryForTests(url_loader_factory); #endif // defined(OS_CHROMEOS) } +class FakePerUserTopicRegistrationManager + : public syncer::PerUserTopicRegistrationManager { + public: + explicit FakePerUserTopicRegistrationManager(PrefService* local_state) + : syncer::PerUserTopicRegistrationManager( + /*identity_provider=*/nullptr, + /*pref_service=*/local_state, + /*url_loader_factory=*/nullptr, + base::BindRepeating(&data_decoder::SafeJsonParser::Parse, nullptr), + /*project_id*/ kInvalidationGCMSenderId, + /*migrate_prefs=*/false) {} + ~FakePerUserTopicRegistrationManager() override = default; + + void UpdateRegisteredTopics(const syncer::Topics& topics, + const std::string& instance_id_token) override {} + + private: + DISALLOW_COPY_AND_ASSIGN(FakePerUserTopicRegistrationManager); +}; + +std::unique_ptr<syncer::FCMNetworkHandler> CreateFCMNetworkHandler( + Profile* profile, + std::map<const Profile*, syncer::FCMNetworkHandler*>* + profile_to_fcm_network_handler_map, + gcm::GCMDriver* gcm_driver, + instance_id::InstanceIDDriver* instance_id_driver, + const std::string& sender_id, + const std::string& app_id) { + auto handler = std::make_unique<syncer::FCMNetworkHandler>( + gcm_driver, instance_id_driver, sender_id, app_id); + (*profile_to_fcm_network_handler_map)[profile] = handler.get(); + return handler; +} + +std::unique_ptr<syncer::PerUserTopicRegistrationManager> +CreatePerUserTopicRegistrationManager( + invalidation::IdentityProvider* identity_provider, + PrefService* local_state, + network::mojom::URLLoaderFactory* url_loader_factory, + const syncer::ParseJSONCallback& parse_json, + const std::string& project_id, + bool migrate_prefs) { + return std::make_unique<FakePerUserTopicRegistrationManager>(local_state); +} + +syncer::FCMNetworkHandler* GetFCMNetworkHandler( + const Profile* profile, + std::map<const Profile*, syncer::FCMNetworkHandler*>* + profile_to_fcm_network_handler_map) { + auto it = profile_to_fcm_network_handler_map->find(profile); + return it != profile_to_fcm_network_handler_map->end() ? it->second : nullptr; +} // Helper class to ensure a profile is registered before the manager is // notified of creation. @@ -160,23 +224,17 @@ std::string GetDebugMessage() const override { return "Encryption"; } }; -std::unique_ptr<invalidation::InvalidationService> CreateInvalidationService( - const std::string& sender_id) { - return std::make_unique<fake_server::FakeServerInvalidationService>(); -} - -std::unique_ptr<KeyedService> BuildFakeServerProfileInvalidationProvider( - content::BrowserContext* context) { - Profile* profile = static_cast<Profile*>(context); - return std::make_unique<invalidation::ProfileInvalidationProvider>( - std::make_unique<fake_server::FakeServerInvalidationService>(), - std::make_unique<invalidation::ProfileIdentityProvider>( - IdentityManagerFactory::GetForProfile(profile)), - base::BindRepeating(&CreateInvalidationService)); -} - } // namespace +instance_id::InstanceID* SyncTest::FakeInstanceIDDriver::GetInstanceID( + const std::string& app_id) { + return &fake_instance_id_; +} +bool SyncTest::FakeInstanceIDDriver::ExistsInstanceID( + const std::string& app_id) const { + return true; +} + SyncTest::SyncTest(TestType test_type) : test_type_(test_type), server_type_(SERVER_TYPE_UNDECIDED), @@ -510,7 +568,7 @@ profile_delegates_.resize(num_clients_ + 1); // + 1 for the verifier. clients_.resize(num_clients_); sync_refreshers_.resize(num_clients_); - fake_server_invalidation_services_.resize(num_clients_); + fake_server_invalidation_observers_.resize(num_clients_); if (create_gaia_account_at_runtime_) { if (!UsingExternalServers()) { @@ -612,7 +670,8 @@ } void SyncTest::DisableNotificationsForClient(int index) { - fake_server_->RemoveObserver(fake_server_invalidation_services_[index]); + fake_server_->RemoveObserver( + fake_server_invalidation_observers_[index].get()); } void SyncTest::SetEncryptionPassphraseForClient(int index, @@ -643,26 +702,41 @@ break; case IN_PROCESS_FAKE_SERVER: { - KeyedService* test_factory = - invalidation::ProfileInvalidationProviderFactory::GetInstance() - ->SetTestingFactoryAndUse( - GetProfile(index), - base::BindRepeating( - &BuildFakeServerProfileInvalidationProvider)); + const std::string client_id = "Client " + base::NumberToString(index); + // Listen for fake server changes. + fake_server_invalidation_observers_[index] = + std::make_unique<fake_server::FakeServerInvalidationSender>( + client_id, TestUsesSelfNotifications(), + base::BindRepeating(&GetFCMNetworkHandler, GetProfile(index), + &profile_to_fcm_network_handler_map_)); + fake_server_->AddObserver( + fake_server_invalidation_observers_[index].get()); - invalidation::InvalidationService* invalidation_service = - static_cast<invalidation::ProfileInvalidationProvider*>(test_factory) - ->GetInvalidationService(); - auto* fake_invalidation_service = - static_cast<fake_server::FakeServerInvalidationService*>( - invalidation_service); + // Store in prefs the mapping between public and private topics names. In + // real clients, those are stored upon registration with the + // per-user-topic server. The pref name is defined in + // per_user_topic_registration_manager.cc. + DictionaryPrefUpdate update( + GetProfile(index)->GetPrefs(), + "invalidation.per_sender_registered_for_invalidation"); + update->SetDictionary(kInvalidationGCMSenderId, + std::make_unique<base::DictionaryValue>()); + for (syncer::ModelType model_type : + GetSyncService(index)->GetPreferredDataTypes()) { + std::string notification_type; + if (!RealModelTypeToNotificationType(model_type, ¬ification_type)) { + continue; + } + update->FindDictKey(kInvalidationGCMSenderId) + ->SetKey(notification_type, + base::Value("/private/" + notification_type + + "-topic_server_user_id")); + } + DictionaryPrefUpdate update_client_id( + GetProfile(index)->GetPrefs(), + invalidation::prefs::kInvalidationClientIDCache); - fake_server_->AddObserver(fake_invalidation_service); - if (TestUsesSelfNotifications()) - fake_invalidation_service->EnableSelfNotifications(); - else - fake_invalidation_service->DisableSelfNotifications(); - fake_server_invalidation_services_[index] = fake_invalidation_service; + update_client_id->SetString(kInvalidationGCMSenderId, client_id); break; } case SERVER_TYPE_UNDECIDED: @@ -841,10 +915,9 @@ init_browser_count - browsers_.size()); if (fake_server_.get()) { - std::vector<fake_server::FakeServerInvalidationService*>::const_iterator it; - for (it = fake_server_invalidation_services_.begin(); - it != fake_server_invalidation_services_.end(); ++it) { - fake_server_->RemoveObserver(*it); + for (const std::unique_ptr<fake_server::FakeServerInvalidationSender>& + observer : fake_server_invalidation_observers_) { + fake_server_->RemoveObserver(observer.get()); } } @@ -853,6 +926,67 @@ configuration_refresher_.reset(); } +void SyncTest::SetUpInProcessBrowserTestFixture() { + will_create_browser_context_services_subscription_ = + BrowserContextDependencyManager::GetInstance() + ->RegisterWillCreateBrowserContextServicesCallbackForTesting( + base::BindRepeating(&SyncTest::OnWillCreateBrowserContextServices, + base::Unretained(this))); +} + +void SyncTest::OnWillCreateBrowserContextServices( + content::BrowserContext* context) { + invalidation::ProfileInvalidationProviderFactory::GetInstance() + ->SetTestingFactory( + context, + base::BindRepeating(&SyncTest::CreateProfileInvalidationProvider, + &profile_to_fcm_network_handler_map_, + &fake_instance_id_driver_)); +} + +// static +std::unique_ptr<KeyedService> SyncTest::CreateProfileInvalidationProvider( + std::map<const Profile*, syncer::FCMNetworkHandler*>* + profile_to_fcm_network_handler_map, + instance_id::InstanceIDDriver* instance_id_driver, + content::BrowserContext* context) { + Profile* profile = Profile::FromBrowserContext(context); + gcm::GCMProfileService* gcm_profile_service = + gcm::GCMProfileServiceFactory::GetForProfile(profile); + + auto profile_identity_provider = + std::make_unique<invalidation::ProfileIdentityProvider>( + IdentityManagerFactory::GetForProfile(profile)); + + auto fcm_invalidation_service = + std::make_unique<invalidation::FCMInvalidationService>( + profile_identity_provider.get(), + base::BindRepeating(&CreateFCMNetworkHandler, profile, + profile_to_fcm_network_handler_map, + gcm_profile_service->driver(), + instance_id_driver), + base::BindRepeating( + &CreatePerUserTopicRegistrationManager, + profile_identity_provider.get(), profile->GetPrefs(), + base::RetainedRef( + content::BrowserContext::GetDefaultStoragePartition(profile) + ->GetURLLoaderFactoryForBrowserProcess() + .get()), + base::BindRepeating(&data_decoder::SafeJsonParser::Parse, + nullptr)), + instance_id_driver, profile->GetPrefs(), kInvalidationGCMSenderId); + fcm_invalidation_service->Init(); + + return std::make_unique<invalidation::ProfileInvalidationProvider>( + std::move(fcm_invalidation_service), std::move(profile_identity_provider), + /*custom_sender_invalidation_service_factory=*/ + base::BindRepeating( + [](const std::string&) + -> std::unique_ptr<invalidation::InvalidationService> { + return std::make_unique<invalidation::FakeInvalidationService>(); + })); +} + void SyncTest::SetUpOnMainThread() { // Start up a sync test server if one is needed and setup mock gaia responses. // Note: This must be done prior to the call to SetupClients() because we want
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h index a0acecc..79b2ad6 100644 --- a/chrome/browser/sync/test/integration/sync_test.h +++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -16,8 +16,11 @@ #include "chrome/browser/extensions/install_verifier.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/test/integration/configuration_refresher.h" +#include "chrome/browser/sync/test/integration/fake_server_invalidation_sender.h" #include "chrome/common/buildflags.h" #include "chrome/test/base/in_process_browser_test.h" +#include "components/gcm_driver/instance_id/instance_id.h" +#include "components/gcm_driver/instance_id/instance_id_driver.h" #include "components/sync/base/model_type.h" #include "components/sync/base/user_selectable_type.h" #include "components/sync/test/fake_server/fake_server.h" @@ -59,7 +62,6 @@ namespace fake_server { class FakeServer; -class FakeServerInvalidationService; } // namespace fake_server namespace syncer { @@ -92,6 +94,55 @@ // in-process (bypassing HTTP calls). }; + class FakeInstanceID : public instance_id::InstanceID { + public: + FakeInstanceID() + : instance_id::InstanceID("FakeAppId", /*gcm_driver = */ nullptr) {} + ~FakeInstanceID() override = default; + + void GetID(const GetIDCallback& callback) override {} + + void GetCreationTime(const GetCreationTimeCallback& callback) override {} + + void GetToken(const std::string& authorized_entity, + const std::string& scope, + const std::map<std::string, std::string>& options, + std::set<Flags> flags, + GetTokenCallback callback) override {} + + void ValidateToken(const std::string& authorized_entity, + const std::string& scope, + const std::string& token, + const ValidateTokenCallback& callback) override {} + + void DeleteToken(const std::string& authorized_entity, + const std::string& scope, + DeleteTokenCallback callback) override {} + + protected: + void DeleteTokenImpl(const std::string& authorized_entity, + const std::string& scope, + DeleteTokenCallback callback) override {} + void DeleteIDImpl(DeleteIDCallback callback) override {} + + private: + DISALLOW_COPY_AND_ASSIGN(FakeInstanceID); + }; + + class FakeInstanceIDDriver : public instance_id::InstanceIDDriver { + public: + FakeInstanceIDDriver() + : instance_id::InstanceIDDriver(/*gcm_driver=*/nullptr) {} + ~FakeInstanceIDDriver() override = default; + instance_id::InstanceID* GetInstanceID(const std::string& app_id) override; + void RemoveInstanceID(const std::string& app_id) override {} + bool ExistsInstanceID(const std::string& app_id) const override; + + private: + FakeInstanceID fake_instance_id_; + DISALLOW_COPY_AND_ASSIGN(FakeInstanceIDDriver); + }; + // A SyncTest must be associated with a particular test type. explicit SyncTest(TestType test_type); @@ -228,6 +279,9 @@ // BrowserTestBase implementation: void SetUpOnMainThread() override; void TearDownOnMainThread() override; + void SetUpInProcessBrowserTestFixture() override; + + void OnWillCreateBrowserContextServices(content::BrowserContext* context); virtual void BeforeSetupClient(int index); @@ -294,6 +348,12 @@ Profile* profile, Profile::CreateStatus status); + static std::unique_ptr<KeyedService> CreateProfileInvalidationProvider( + std::map<const Profile*, syncer::FCMNetworkHandler*>* + profile_to_fcm_network_handler_map, + instance_id::InstanceIDDriver* instance_id_driver, + content::BrowserContext* context); + // Helper to Profile::CreateProfile that handles path creation, setting up // preexisting pref files, and registering the created profile as a testing // profile. @@ -409,14 +469,25 @@ // notifications of this activity to its peer sync clients. std::vector<std::unique_ptr<P2PSyncRefresher>> sync_refreshers_; - // Collection of pointers to FakeServerInvalidation objects for each - // profile. - std::vector<fake_server::FakeServerInvalidationService*> - fake_server_invalidation_services_; + // Owns the FakeServerInvalidationSender for each profile. + std::vector<std::unique_ptr<fake_server::FakeServerInvalidationSender>> + fake_server_invalidation_observers_; + + // Maps a profile to the corresponding FCMNetworkHandler. Contains one entry + // per profile. It is used to simulate an incoming FCM messages to different + // profiles within the FakeServerInvalidationSender. + std::map<const Profile*, syncer::FCMNetworkHandler*> + profile_to_fcm_network_handler_map_; + + FakeInstanceIDDriver fake_instance_id_driver_; // Triggers a GetUpdates via refresh after a configuration. std::unique_ptr<ConfigurationRefresher> configuration_refresher_; + std::unique_ptr< + base::CallbackList<void(content::BrowserContext*)>::Subscription> + will_create_browser_context_services_subscription_; + // Sync profile against which changes to individual profiles are verified. // We don't need a corresponding verifier sync client because the contents // of the verifier profile are strictly local, and are not meant to be
diff --git a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc index dca21d94..dfa8f65 100644 --- a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
@@ -517,8 +517,16 @@ // syncing results in a conflict where the update wins. This only works with // a server that supports a strong consistency model and is hence capable of // detecting conflicts server-side. +// Flaky (mostly) on ASan/TSan. http://crbug.com/998130 +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) +#define MAYBE_DeleteAndUpdateWithStrongConsistency \ + DISABLED_DeleteAndUpdateWithStrongConsistency +#else +#define MAYBE_DeleteAndUpdateWithStrongConsistency \ + DeleteAndUpdateWithStrongConsistency +#endif IN_PROC_BROWSER_TEST_F(TwoClientAutofillProfileSyncTest, - DeleteAndUpdateWithStrongConsistency) { + MAYBE_DeleteAndUpdateWithStrongConsistency) { ASSERT_TRUE(SetupSync()); base::HistogramTester histograms; GetFakeServer()->EnableStrongConsistencyWithConflictDetectionModel();
diff --git a/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc b/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc index 8b74eab4..86fa328c 100644 --- a/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc +++ b/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc
@@ -12,6 +12,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/password_manager/core/browser/password_form_manager_for_ui.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_manager_onboarding.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" @@ -47,18 +48,34 @@ client_->GetPrefs()->SetInteger( password_manager::prefs::kPasswordManagerOnboardingState, - static_cast<int>(password_manager::OnboardingState::kShown)); + static_cast<int>( + password_manager::metrics_util::OnboardingState::kShown)); +} + +void OnboardingDialogView::DismissWithReasonAndDelete( + password_manager::metrics_util::OnboardingUIDismissalReason reason) { + password_manager::metrics_util::LogOnboardingUIDismissalReason(reason); + delete this; } void OnboardingDialogView::OnboardingAccepted( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) { client_->OnOnboardingSuccessful(std::move(form_to_save_)); - delete this; + DismissWithReasonAndDelete( + password_manager::metrics_util::OnboardingUIDismissalReason::kAccepted); } void OnboardingDialogView::OnboardingRejected( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) { - delete this; + DismissWithReasonAndDelete( + password_manager::metrics_util::OnboardingUIDismissalReason::kRejected); +} + +void OnboardingDialogView::OnboardingAborted( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj) { + DismissWithReasonAndDelete( + password_manager::metrics_util::OnboardingUIDismissalReason::kDismissed); }
diff --git a/chrome/browser/ui/android/passwords/onboarding_dialog_view.h b/chrome/browser/ui/android/passwords/onboarding_dialog_view.h index 109899a..b943a80 100644 --- a/chrome/browser/ui/android/passwords/onboarding_dialog_view.h +++ b/chrome/browser/ui/android/passwords/onboarding_dialog_view.h
@@ -8,6 +8,7 @@ #include <jni.h> #include "base/android/scoped_java_ref.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" class ChromePasswordManagerClient; @@ -31,15 +32,26 @@ // Sets the |kPasswordManagerOnboardingState| pref to |kShown|. void Show(); - // Called from Java via JNI. Prompts user to save their password. + // Called from Java via JNI when the positive button is pressed, + // e.g. "Continue" or "Got it". Prompts the user to save their password. void OnboardingAccepted(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); - // Called from Java via JNI. + // Called from Java via JNI when the negative button is pressed, + // e.g. "Cancel". void OnboardingRejected(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + // Called from Java via JNI when the dialog is dismissed in any other way, + // e.g. pressing the back button or navigating to another tab. + void OnboardingAborted(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); + private: + // Records the reaction to the onboarding and deletes this class. + void DismissWithReasonAndDelete( + password_manager::metrics_util::OnboardingUIDismissalReason reason); + // The corresponding java object. base::android::ScopedJavaGlobalRef<jobject> java_object_;
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc index 165046c3..089b88d9 100644 --- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -126,7 +126,6 @@ ~KeyboardControllerWebContentTest() override {} void SetUp() override { - ui::SetUpInputMethodFactoryForTesting(); InProcessBrowserTest::SetUp(); } @@ -170,6 +169,7 @@ private: std::unique_ptr<ui::DummyTextInputClient> client; + ui::ScopedTestInputMethodFactory scoped_test_input_method_factory_; DISALLOW_COPY_AND_ASSIGN(KeyboardControllerWebContentTest); };
diff --git a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc index 121447d..34317f4 100644 --- a/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_state_unittest.cc
@@ -13,7 +13,7 @@ #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/common/form_data.h" #include "components/password_manager/core/browser/fake_form_fetcher.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" @@ -26,7 +26,7 @@ using autofill::FormFieldData; using autofill::PasswordForm; using base::ASCIIToUTF16; -using password_manager::NewPasswordFormManager; +using password_manager::PasswordFormManager; using password_manager::PasswordStoreChange; using password_manager::PasswordStoreChangeList; using ::testing::_; @@ -102,7 +102,7 @@ passwords_data_.set_client(&mock_client_); - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); } PasswordForm& saved_match() { return saved_match_; } @@ -116,17 +116,17 @@ ManagePasswordsState& passwords_data() { return passwords_data_; } password_manager::PasswordManagerDriver& driver() { return driver_; } - // Returns a NewPasswordFormManager containing |test_stored_forms_| as the + // Returns a PasswordFormManager containing |test_stored_forms_| as the // best matches. // TODO(https://crbug.com/998496): Create a mock object which implements // PasswordFormManagerForUI interface. - std::unique_ptr<NewPasswordFormManager> CreateFormManager(); + std::unique_ptr<PasswordFormManager> CreateFormManager(); - // Returns a NewPasswordFormManager containing local_federated_form() as + // Returns a PasswordFormManager containing local_federated_form() as // a stored federated credential. // TODO(https://crbug.com/998496): Create a mock object which implements // PasswordFormManagerForUI interface. - std::unique_ptr<NewPasswordFormManager> CreateFormManagerWithFederation(); + std::unique_ptr<PasswordFormManager> CreateFormManagerWithFederation(); // Pushes irrelevant updates to |passwords_data_| and checks that they don't // affect the state. @@ -142,7 +142,7 @@ private: // Implements both CreateFormManager and CreateFormManagerWithFederation. - std::unique_ptr<NewPasswordFormManager> CreateFormManagerInternal( + std::unique_ptr<PasswordFormManager> CreateFormManagerInternal( bool include_federated); MockPasswordManagerClient mock_client_; @@ -158,19 +158,19 @@ std::vector<const PasswordForm*> test_stored_forms_; }; -std::unique_ptr<NewPasswordFormManager> +std::unique_ptr<PasswordFormManager> ManagePasswordsStateTest::CreateFormManager() { return CreateFormManagerInternal(false); } -std::unique_ptr<NewPasswordFormManager> +std::unique_ptr<PasswordFormManager> ManagePasswordsStateTest::CreateFormManagerWithFederation() { return CreateFormManagerInternal(true); } -std::unique_ptr<NewPasswordFormManager> +std::unique_ptr<PasswordFormManager> ManagePasswordsStateTest::CreateFormManagerInternal(bool include_federated) { - auto form_manager = std::make_unique<NewPasswordFormManager>( + auto form_manager = std::make_unique<PasswordFormManager>( &mock_client_, driver_.AsWeakPtr(), observed_form(), &fetcher_, base::WrapUnique(new password_manager::StubFormSaver), nullptr /* metrics_recorder */); @@ -316,8 +316,7 @@ TEST_F(ManagePasswordsStateTest, PasswordSubmitted) { test_stored_forms().push_back(&saved_match()); test_stored_forms().push_back(&psl_match()); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnPendingPassword(std::move(test_form_manager)); @@ -332,8 +331,7 @@ TEST_F(ManagePasswordsStateTest, PasswordSaved) { test_stored_forms().push_back(&saved_match()); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnPendingPassword(std::move(test_form_manager)); EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, @@ -349,7 +347,7 @@ } TEST_F(ManagePasswordsStateTest, PasswordSubmittedFederationsPresent) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithFederation()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnPendingPassword(std::move(test_form_manager)); @@ -404,8 +402,7 @@ TEST_F(ManagePasswordsStateTest, AutomaticPasswordSave) { test_stored_forms().push_back(&psl_match()); test_stored_forms().push_back(&saved_match()); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); passwords_data().OnAutomaticPasswordSave(std::move(test_form_manager)); EXPECT_EQ(password_manager::ui::CONFIRMATION_STATE, passwords_data().state()); @@ -423,7 +420,7 @@ TEST_F(ManagePasswordsStateTest, AutomaticPasswordSaveWithFederations) { test_stored_forms().push_back(&saved_match()); - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithFederation()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); @@ -507,8 +504,7 @@ } TEST_F(ManagePasswordsStateTest, OnInactive) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnPendingPassword(std::move(test_form_manager)); @@ -523,8 +519,7 @@ } TEST_F(ManagePasswordsStateTest, PendingPasswordAddBlacklisted) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnPendingPassword(std::move(test_form_manager)); EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_STATE, @@ -557,8 +552,7 @@ } TEST_F(ManagePasswordsStateTest, AutomaticPasswordSaveAddBlacklisted) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnAutomaticPasswordSave(std::move(test_form_manager)); EXPECT_EQ(password_manager::ui::CONFIRMATION_STATE, passwords_data().state()); @@ -578,8 +572,7 @@ } TEST_F(ManagePasswordsStateTest, PasswordUpdateAddBlacklisted) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnUpdatePassword(std::move(test_form_manager)); EXPECT_EQ(password_manager::ui::PENDING_PASSWORD_UPDATE_STATE, @@ -591,8 +584,7 @@ TEST_F(ManagePasswordsStateTest, PasswordUpdateSubmitted) { test_stored_forms().push_back(&saved_match()); test_stored_forms().push_back(&psl_match()); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnUpdatePassword(std::move(test_form_manager)); @@ -612,8 +604,7 @@ android_form.username_value = submitted_form().fields[0].value; android_form.password_value = base::ASCIIToUTF16("old pass"); test_stored_forms().push_back(&android_form); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnUpdatePassword(std::move(test_form_manager)); @@ -629,7 +620,7 @@ TEST_F(ManagePasswordsStateTest, PasswordUpdateSubmittedWithFederations) { test_stored_forms().push_back(&saved_match()); - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithFederation()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); passwords_data().OnUpdatePassword(std::move(test_form_manager));
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.cc b/chrome/browser/ui/passwords/manage_passwords_test.cc index 92303c54f..fe8fce7 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.cc +++ b/chrome/browser/ui/passwords/manage_passwords_test.cc
@@ -20,12 +20,12 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" #include "components/autofill/core/common/password_form.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "content/public/test/test_utils.h" -using password_manager::NewPasswordFormManager; +using password_manager::PasswordFormManager; namespace { constexpr char kTestOrigin[] = "https://www.example.com"; @@ -56,8 +56,8 @@ observed_form_.fields.push_back(field); // Turn off waiting for server predictions in order to avoid dealing with - // posted tasks in NewPasswordFormManager. - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); + // posted tasks in PasswordFormManager. + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); } ManagePasswordsTest::~ManagePasswordsTest() = default; @@ -87,7 +87,7 @@ } void ManagePasswordsTest::SetupPendingPassword() { - auto form_manager = std::make_unique<NewPasswordFormManager>( + auto form_manager = std::make_unique<PasswordFormManager>( &client_, driver_.AsWeakPtr(), observed_form_, &fetcher_, base::WrapUnique(new password_manager::StubFormSaver), nullptr /* metrics_recorder */); @@ -96,7 +96,7 @@ } void ManagePasswordsTest::SetupAutomaticPassword() { - auto form_manager = std::make_unique<NewPasswordFormManager>( + auto form_manager = std::make_unique<PasswordFormManager>( &client_, driver_.AsWeakPtr(), observed_form_, &fetcher_, base::WrapUnique(new password_manager::StubFormSaver), nullptr /* metrics_recorder */);
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc index c974744..13ff2186 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -26,8 +26,8 @@ #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/fake_form_fetcher.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/statistics_table.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" @@ -49,7 +49,7 @@ using autofill::FormFieldData; using autofill::PasswordForm; using base::ASCIIToUTF16; -using password_manager::NewPasswordFormManager; +using password_manager::PasswordFormManager; using ::testing::_; using ::testing::Contains; using ::testing::DoAll; @@ -201,22 +201,21 @@ void ExpectIconStateIs(password_manager::ui::State state); void ExpectIconAndControllerStateIs(password_manager::ui::State state); - std::unique_ptr<NewPasswordFormManager> CreateFormManagerWithBestMatches( + std::unique_ptr<PasswordFormManager> CreateFormManagerWithBestMatches( const FormData& observed_form, const std::vector<const PasswordForm*>& best_matches, scoped_refptr<password_manager::PasswordFormMetricsRecorder> metrics_recorder); - std::unique_ptr<NewPasswordFormManager> - CreateFormManagerWithBlacklistedMatches( + std::unique_ptr<PasswordFormManager> CreateFormManagerWithBlacklistedMatches( const FormData& observed_form, const std::vector<const PasswordForm*>& blacklisted_matches, scoped_refptr<password_manager::PasswordFormMetricsRecorder> metrics_recorder); - std::unique_ptr<NewPasswordFormManager> CreateFormManager(); + std::unique_ptr<PasswordFormManager> CreateFormManager(); - std::unique_ptr<NewPasswordFormManager> CreateFormManagerWithMetricsRecorder( + std::unique_ptr<PasswordFormManager> CreateFormManagerWithMetricsRecorder( scoped_refptr<password_manager::PasswordFormMetricsRecorder> metrics_recorder); @@ -274,7 +273,7 @@ // Turn off waiting for server predictions in order to avoid dealing with // posted tasks. - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); // We need to be on a "webby" URL for most tests. EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); @@ -295,13 +294,13 @@ EXPECT_EQ(state, controller()->GetState()); } -std::unique_ptr<NewPasswordFormManager> +std::unique_ptr<PasswordFormManager> ManagePasswordsUIControllerTest::CreateFormManagerWithBestMatches( const FormData& observed_form, const std::vector<const PasswordForm*>& best_matches, scoped_refptr<password_manager::PasswordFormMetricsRecorder> metrics_recorder) { - auto form_manager = std::make_unique<NewPasswordFormManager>( + auto form_manager = std::make_unique<PasswordFormManager>( &client_, driver_.AsWeakPtr(), observed_form, &fetcher_, std::make_unique<password_manager::StubFormSaver>(), metrics_recorder); fetcher_.SetNonFederated(best_matches); @@ -309,13 +308,13 @@ return form_manager; } -std::unique_ptr<NewPasswordFormManager> +std::unique_ptr<PasswordFormManager> ManagePasswordsUIControllerTest::CreateFormManagerWithBlacklistedMatches( const FormData& observed_form, const std::vector<const PasswordForm*>& blacklisted_matches, scoped_refptr<password_manager::PasswordFormMetricsRecorder> metrics_recorder) { - auto form_manager = std::make_unique<NewPasswordFormManager>( + auto form_manager = std::make_unique<PasswordFormManager>( &client_, driver_.AsWeakPtr(), observed_form, &fetcher_, std::make_unique<password_manager::StubFormSaver>(), metrics_recorder); fetcher_.SetBlacklisted(blacklisted_matches); @@ -323,12 +322,12 @@ return form_manager; } -std::unique_ptr<NewPasswordFormManager> +std::unique_ptr<PasswordFormManager> ManagePasswordsUIControllerTest::CreateFormManager() { return CreateFormManagerWithMetricsRecorder(nullptr); } -std::unique_ptr<NewPasswordFormManager> +std::unique_ptr<PasswordFormManager> ManagePasswordsUIControllerTest::CreateFormManagerWithMetricsRecorder( scoped_refptr<password_manager::PasswordFormMetricsRecorder> metrics_recorder) { @@ -343,8 +342,7 @@ state == password_manager::ui::CONFIRMATION_STATE); // Set the bubble state to |state|. - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); if (state == password_manager::ui::PENDING_PASSWORD_STATE) @@ -390,8 +388,7 @@ } TEST_F(ManagePasswordsUIControllerTest, PasswordSubmitted) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager)); @@ -406,7 +403,7 @@ blacklisted.origin = test_local_form().origin; blacklisted.signon_realm = blacklisted.origin.spec(); blacklisted.blacklisted_by_user = true; - std::unique_ptr<NewPasswordFormManager> test_form_manager = + std::unique_ptr<PasswordFormManager> test_form_manager = CreateFormManagerWithBlacklistedMatches(observed_form(), {&blacklisted}, nullptr); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); @@ -418,8 +415,7 @@ TEST_F(ManagePasswordsUIControllerTest, PasswordSubmittedBubbleSuppressed) { CreateSmartBubbleFieldTrial(); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); std::vector<password_manager::InteractionsStats> stats(1); stats[0].origin_domain = test_local_form().origin.GetOrigin(); stats[0].username_value = test_local_form().username_value; @@ -438,8 +434,7 @@ TEST_F(ManagePasswordsUIControllerTest, PasswordSubmittedBubbleNotSuppressed) { CreateSmartBubbleFieldTrial(); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); std::vector<password_manager::InteractionsStats> stats(1); stats[0].origin_domain = test_local_form().origin.GetOrigin(); stats[0].username_value = ASCIIToUTF16("not my username"); @@ -465,8 +460,7 @@ ManagePasswordsUIController::FromWebContents(web_content.get()); controller->set_client(&client()); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); // The bubble is ready to open but the tab is inactive. Therefore, we don't // call UpdateIconAndBubbleState here. @@ -481,8 +475,7 @@ } TEST_F(ManagePasswordsUIControllerTest, PasswordSaved) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager)); @@ -520,7 +513,7 @@ true /*is_main_frame_secure*/, source_id); // Exercise controller. - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithMetricsRecorder(recorder)); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); @@ -579,8 +572,7 @@ } TEST_F(ManagePasswordsUIControllerTest, PasswordBlacklisted) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager)); @@ -592,7 +584,7 @@ TEST_F(ManagePasswordsUIControllerTest, PasswordBlacklistedWithExistingCredentials) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithBestMatches(observed_form(), {&test_local_form()}, nullptr)); test_form_manager->ProvisionallySave(submitted_form(), &driver()); @@ -605,8 +597,7 @@ } TEST_F(ManagePasswordsUIControllerTest, NormalNavigations) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager)); ExpectIconAndControllerStateIs(password_manager::ui::PENDING_PASSWORD_STATE); @@ -621,8 +612,7 @@ } TEST_F(ManagePasswordsUIControllerTest, NormalNavigationsClosedBubble) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager)); @@ -646,8 +636,7 @@ content::WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("chrome://sign-in")); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager)); @@ -675,8 +664,7 @@ } TEST_F(ManagePasswordsUIControllerTest, AutomaticPasswordSave) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnAutomaticPasswordSave(std::move(test_form_manager)); EXPECT_EQ(password_manager::ui::CONFIRMATION_STATE, controller()->GetState()); @@ -920,8 +908,7 @@ } TEST_F(ManagePasswordsUIControllerTest, UpdatePasswordSubmitted) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnUpdatePasswordSubmitted(std::move(test_form_manager)); ExpectIconAndControllerStateIs( @@ -929,8 +916,7 @@ } TEST_F(ManagePasswordsUIControllerTest, PasswordUpdated) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnUpdatePasswordSubmitted(std::move(test_form_manager)); @@ -995,7 +981,7 @@ auto recorder = base::MakeRefCounted<password_manager::PasswordFormMetricsRecorder>( true /*is_main_frame_secure*/, source_id); - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithMetricsRecorder(recorder)); test_form_manager->ProvisionallySave(submitted_form(), &driver()); @@ -1046,7 +1032,7 @@ for (bool is_update : {false, true}) { SCOPED_TRACE(testing::Message("is_update = ") << is_update); // Create password form manager with stored passwords. - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithBestMatches(observed_form(), {&test_local_form()}, nullptr)); @@ -1077,7 +1063,7 @@ TEST_F(ManagePasswordsUIControllerTest, ManualFallbackForSaving_HideFallback_WithoutPreexistingPasswords) { // Create password form manager without stored passwords. - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithBestMatches(observed_form(), {}, nullptr)); // Simulate user typing a password. @@ -1105,8 +1091,7 @@ << enforce_navigation); ManagePasswordsUIController::set_save_fallback_timeout_in_seconds(0); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); @@ -1143,8 +1128,7 @@ << user_saved_password); ManagePasswordsUIController::set_save_fallback_timeout_in_seconds(0); - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); @@ -1184,8 +1168,7 @@ TEST_F(ManagePasswordsUIControllerTest, ManualFallbackForSavingFollowedByAutomaticBubble) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); @@ -1220,7 +1203,7 @@ for (bool user_closed_bubble : {false, true}) { SCOPED_TRACE(testing::Message("user_closed_bubble = ") << user_closed_bubble); - std::unique_ptr<NewPasswordFormManager> test_form_manager( + std::unique_ptr<PasswordFormManager> test_form_manager( CreateFormManagerWithBestMatches(observed_form(), {&test_local_form()}, nullptr)); test_form_manager->ProvisionallySave(submitted_form(), &driver()); @@ -1244,8 +1227,7 @@ } TEST_F(ManagePasswordsUIControllerTest, AutofillDuringSignInPromo) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager)); @@ -1268,8 +1250,7 @@ } TEST_F(ManagePasswordsUIControllerTest, AuthenticateUserToRevealPasswords) { - std::unique_ptr<NewPasswordFormManager> test_form_manager( - CreateFormManager()); + std::unique_ptr<PasswordFormManager> test_form_manager(CreateFormManager()); test_form_manager->ProvisionallySave(submitted_form(), &driver()); EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); controller()->OnPasswordSubmitted(std::move(test_form_manager));
diff --git a/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.cc b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.cc index ec38747..0e65db1 100644 --- a/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.cc +++ b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.cc
@@ -113,10 +113,8 @@ } std::unique_ptr<views::View> ClickToCallDialogView::CreateFootnoteView() { - if (GetDialogType() != - SharingClickToCallDialogType::kDialogWithoutDevicesWithApp) { + if (GetDialogType() != SharingDialogType::kDialogWithoutDevicesWithApp) return nullptr; - } return CreateHelpText(this); } @@ -127,18 +125,18 @@ controller_->OnHelpTextClicked(); } -SharingClickToCallDialogType ClickToCallDialogView::GetDialogType() const { +SharingDialogType ClickToCallDialogView::GetDialogType() const { if (send_failed_) - return SharingClickToCallDialogType::kErrorDialog; + return SharingDialogType::kErrorDialog; bool has_devices = !controller_->devices().empty(); bool has_apps = !controller_->apps().empty(); if (has_devices) - return SharingClickToCallDialogType::kDialogWithDevicesMaybeApps; + return SharingDialogType::kDialogWithDevicesMaybeApps; - return has_apps ? SharingClickToCallDialogType::kDialogWithoutDevicesWithApp - : SharingClickToCallDialogType::kEducationalDialog; + return has_apps ? SharingDialogType::kDialogWithoutDevicesWithApp + : SharingDialogType::kEducationalDialog; } void ClickToCallDialogView::Init() { @@ -147,22 +145,22 @@ dialog_buttons_.clear(); auto* provider = ChromeLayoutProvider::Get(); - SharingClickToCallDialogType type = GetDialogType(); + SharingDialogType type = GetDialogType(); LogClickToCallDialogShown(type); switch (type) { - case SharingClickToCallDialogType::kErrorDialog: + case SharingDialogType::kErrorDialog: set_margins( provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT)); InitErrorView(); break; - case SharingClickToCallDialogType::kEducationalDialog: + case SharingDialogType::kEducationalDialog: set_margins( provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT)); InitEmptyView(); break; - case SharingClickToCallDialogType::kDialogWithoutDevicesWithApp: - case SharingClickToCallDialogType::kDialogWithDevicesMaybeApps: + case SharingDialogType::kDialogWithoutDevicesWithApp: + case SharingDialogType::kDialogWithDevicesMaybeApps: set_margins( gfx::Insets(provider->GetDistanceMetric( views::DISTANCE_DIALOG_CONTENT_MARGIN_TOP_CONTROL), @@ -275,13 +273,13 @@ base::string16 ClickToCallDialogView::GetWindowTitle() const { switch (GetDialogType()) { - case SharingClickToCallDialogType::kErrorDialog: + case SharingDialogType::kErrorDialog: return controller_->GetErrorDialogTitle(); - case SharingClickToCallDialogType::kEducationalDialog: + case SharingDialogType::kEducationalDialog: return l10n_util::GetStringUTF16( IDS_BROWSER_SHARING_CLICK_TO_CALL_DIALOG_TITLE_NO_DEVICES); - case SharingClickToCallDialogType::kDialogWithoutDevicesWithApp: - case SharingClickToCallDialogType::kDialogWithDevicesMaybeApps: + case SharingDialogType::kDialogWithoutDevicesWithApp: + case SharingDialogType::kDialogWithDevicesMaybeApps: return controller_->GetTitle(); } }
diff --git a/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h index 2d66303..d3997f1 100644 --- a/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h +++ b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h
@@ -21,7 +21,7 @@ class Browser; class HoverButton; -enum class SharingClickToCallDialogType; +enum class SharingDialogType; class ClickToCallDialogView : public SharingDialog, public views::ButtonListener, @@ -66,7 +66,7 @@ FRIEND_TEST_ALL_PREFIXES(ClickToCallDialogViewTest, DevicePressed); FRIEND_TEST_ALL_PREFIXES(ClickToCallDialogViewTest, AppPressed); - SharingClickToCallDialogType GetDialogType() const; + SharingDialogType GetDialogType() const; // views::BubbleDialogDelegateView: void Init() override;
diff --git a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc index 6f308dc..409bc5a 100644 --- a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
@@ -3,10 +3,11 @@ // found in the LICENSE file. #include "chrome/browser/badging/badge_manager.h" -#include "chrome/browser/badging/badge_manager_delegate.h" #include "chrome/browser/badging/badge_manager_factory.h" +#include "chrome/browser/badging/test_badge_manager_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" +#include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "content/public/browser/web_contents.h" using content::RenderFrameHost; @@ -16,40 +17,9 @@ class WebAppBadgingBrowserTest : public WebAppControllerBrowserTest { public: - // Listens to BadgeManager events and forwards them to the test class. - class TestBadgeManagerDelegate : public badging::BadgeManagerDelegate { - public: - using SetBadgeCallback = - base::RepeatingCallback<void(const AppId&, base::Optional<uint64_t>)>; - using ClearBadgeCallback = base::RepeatingCallback<void(const AppId&)>; - - using ChangeFailedCallback = base::RepeatingCallback<void()>; - - TestBadgeManagerDelegate(Profile* profile, - SetBadgeCallback on_set_badge, - ClearBadgeCallback on_clear_badge, - ChangeFailedCallback on_change_failed) - : badging::BadgeManagerDelegate(profile), - on_set_badge_(on_set_badge), - on_clear_badge_(on_clear_badge), - on_change_failed_(on_change_failed) {} - - void OnBadgeSet(const AppId& app_id, - base::Optional<uint64_t> contents) override { - on_set_badge_.Run(app_id, contents); - } - - void OnBadgeCleared(const AppId& app_id) override { - on_clear_badge_.Run(app_id); - } - - void OnBadgeChangeIgnoredForTesting() override { on_change_failed_.Run(); } - - private: - SetBadgeCallback on_set_badge_; - ClearBadgeCallback on_clear_badge_; - ChangeFailedCallback on_change_failed_; - }; + WebAppBadgingBrowserTest() + : WebAppControllerBrowserTest(), + cross_origin_https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} void SetUpCommandLine(base::CommandLine* command_line) override { WebAppControllerBrowserTest::SetUpCommandLine(command_line); @@ -59,25 +29,33 @@ void SetUpOnMainThread() override { WebAppControllerBrowserTest::SetUpOnMainThread(); + ASSERT_TRUE(cross_origin_https_server_.Start()); ASSERT_TRUE(https_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start()); - AppId app_id = InstallPWA(https_server()->GetURL( - "/ssl/page_with_in_scope_and_cross_site_frame.html")); + GURL cross_site_frame_url = + cross_origin_https_server_.GetURL("/ssl/google.html"); + // Note: The url for the cross site frame is embedded in the query string. + GURL app_url = https_server()->GetURL( + "/ssl/page_with_in_scope_and_cross_site_frame.html?url=" + + cross_site_frame_url.spec()); + AppId app_id = InstallPWA(app_url); content::WebContents* web_contents = OpenApplication(app_id); // There should be exactly 3 frames: // 1) The main frame. - // 2) A cross site frame, on https://example.com/ + // 2) A cross site frame, on |cross_site_frame_url|. // 3) A sub frame in the app's scope. auto frames = web_contents->GetAllFrames(); ASSERT_EQ(3u, frames.size()); main_frame_ = web_contents->GetMainFrame(); for (auto* frame : frames) { - if (frame->GetLastCommittedURL() == "https://example.com/") - cross_site_frame_ = frame; - else if (frame != main_frame_) + if (url::IsSameOriginWith(frame->GetLastCommittedURL(), + main_frame_->GetLastCommittedURL())) { in_scope_frame_ = frame; + } else if (frame != main_frame_) { + cross_site_frame_ = frame; + } } ASSERT_TRUE(main_frame_); @@ -86,36 +64,38 @@ awaiter_ = std::make_unique<base::RunLoop>(); - std::unique_ptr<badging::BadgeManagerDelegate> delegate = - std::make_unique<TestBadgeManagerDelegate>( - profile(), - base::BindRepeating(&WebAppBadgingBrowserTest::OnBadgeSet, - base::Unretained(this)), - base::BindRepeating(&WebAppBadgingBrowserTest::OnBadgeCleared, - base::Unretained(this)), - base::BindRepeating(&WebAppBadgingBrowserTest::OnBadgeChangeFailed, - base::Unretained(this))); - badging::BadgeManagerFactory::GetInstance() - ->GetForProfile(profile()) - ->SetDelegate(std::move(delegate)); + badging::BadgeManager* badge_manager = + badging::BadgeManagerFactory::GetInstance()->GetForProfile(profile()); + + // The delegate is owned by the badge manager. We hold a pointer to it for + // the test. + std::unique_ptr<badging::TestBadgeManagerDelegate> owned_delegate = + std::make_unique<badging::TestBadgeManagerDelegate>( + profile(), badge_manager, + &WebAppProviderBase::GetProviderBase(profile())->registrar()); + owned_delegate->SetOnBadgeChanged(base::BindRepeating( + &WebAppBadgingBrowserTest::OnBadgeChanged, base::Unretained(this))); + delegate_ = owned_delegate.get(); + + badge_manager->SetDelegate(std::move(owned_delegate)); } - void OnBadgeSet(const AppId& app_id, base::Optional<uint64_t> badge_content) { - if (badge_content.has_value()) - last_badge_content_ = badge_content; - else - was_flagged_ = true; + void OnBadgeChanged() { + // This is only set up to deal with one badge change at a time, in order to + // make asserting the result of a badge change easier. + int total_changes = delegate_->cleared_app_badges().size() + + delegate_->set_app_badges().size(); + EXPECT_LE(total_changes, 1); - awaiter_->Quit(); - } + // A change is a failure if it doesn't set or clear any badges. + change_failed_ = total_changes == 0; + was_cleared_ = delegate_->cleared_app_badges().size(); - void OnBadgeCleared(const AppId& app_id) { - was_cleared_ = true; - awaiter_->Quit(); - } + if (delegate_->set_app_badges().size() == 1) { + last_badge_content_ = delegate_->set_app_badges()[0].second; + was_flagged_ = last_badge_content_ == base::nullopt; + } - void OnBadgeChangeFailed() { - change_failed_ = true; awaiter_->Quit(); } @@ -127,6 +107,7 @@ change_failed_ = false; last_badge_content_ = base::nullopt; awaiter_ = std::make_unique<base::RunLoop>(); + delegate_->ResetBadges(); ASSERT_TRUE(content::ExecuteScript(on, script)); @@ -148,8 +129,29 @@ private: std::unique_ptr<base::RunLoop> awaiter_; + badging::TestBadgeManagerDelegate* delegate_; + net::EmbeddedTestServer cross_origin_https_server_; }; +// Tests that the badge for the main frame is not affected by changing the badge +// of a cross site subframe. +IN_PROC_BROWSER_TEST_P(WebAppBadgingBrowserTest, + BadgeCannotBeChangedFromCrossSiteFrame) { + // Clearing from cross site frame should be a no-op. + ExecuteScriptAndWaitForBadgeChange("ExperimentalBadge.clear()", + cross_site_frame_); + ASSERT_FALSE(was_cleared_); + ASSERT_FALSE(was_flagged_); + ASSERT_TRUE(change_failed_); + + // Setting from cross site frame should be a no-op. + ExecuteScriptAndWaitForBadgeChange("ExperimentalBadge.set(77)", + cross_site_frame_); + ASSERT_FALSE(was_cleared_); + ASSERT_FALSE(was_flagged_); + ASSERT_TRUE(change_failed_); +} + // Tests that setting the badge to an integer will be propagated across // processes. IN_PROC_BROWSER_TEST_P(WebAppBadgingBrowserTest, BadgeCanBeSetToAnInteger) { @@ -213,24 +215,6 @@ ASSERT_EQ(base::nullopt, last_badge_content_); } -// Tests that the badge cannot be set and cleared from a cross site frame. -IN_PROC_BROWSER_TEST_P(WebAppBadgingBrowserTest, - BadgeCannotBeChangedFromCrossSiteFrame) { - // Clearing from cross site frame should be a no-op. - ExecuteScriptAndWaitForBadgeChange("ExperimentalBadge.clear()", - cross_site_frame_); - ASSERT_FALSE(was_cleared_); - ASSERT_FALSE(was_flagged_); - ASSERT_TRUE(change_failed_); - - // Setting from cross site frame should be a no-op. - ExecuteScriptAndWaitForBadgeChange("ExperimentalBadge.set(77)", - cross_site_frame_); - ASSERT_FALSE(was_cleared_); - ASSERT_FALSE(was_flagged_); - ASSERT_TRUE(change_failed_); -} - INSTANTIATE_TEST_SUITE_P( /* no prefix */, WebAppBadgingBrowserTest,
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index b7724347..07035ae 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -631,6 +631,18 @@ IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_TITLE); builder->Add("securityTokenPinDialogSubtitle", IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_SUBTITLE); + builder->Add("securityTokenPinDialogTryAgain", + IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_TRY_AGAIN); + builder->Add("securityTokenPinDialogAttemptsLeft", + IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT); + builder->Add("securityTokenPinDialogUnknownError", + IDS_REQUEST_PIN_DIALOG_UNKNOWN_ERROR); + builder->Add("securityTokenPinDialogUnknownInvalidPin", + IDS_REQUEST_PIN_DIALOG_INVALID_PIN_ERROR); + builder->Add("securityTokenPinDialogUnknownInvalidPuk", + IDS_REQUEST_PIN_DIALOG_INVALID_PUK_ERROR); + builder->Add("securityTokenPinDialogUnknownMaxAttemptsExceeded", + IDS_REQUEST_PIN_DIALOG_MAX_ATTEMPTS_EXCEEDED_ERROR); } void GaiaScreenHandler::Initialize() {
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index e4ff297..8a7a29b6 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -556,6 +556,10 @@ "dependencies": ["permission:loginScreenUi"], "contexts": ["blessed_extension"] }, + "loginState": { + "dependencies": ["permission:loginState"], + "contexts": ["blessed_extension"] + }, "webcamPrivate": { "dependencies": ["permission:webcamPrivate"], "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index a8b5dcf..eb95198 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json
@@ -479,6 +479,11 @@ "4DBFC1C52D6660DD90791976DF7FEF7B3D360509" // Imprivata (login screen) DEV ] }, + "loginState": { + "channel": "dev", + "extension_types": ["login_screen_extension", "extension"], + "platforms": ["chromeos"] + }, "webcamPrivate": { "channel": "stable", "extension_types": ["extension", "platform_app"],
diff --git a/chrome/common/extensions/api/api_sources.gni b/chrome/common/extensions/api/api_sources.gni index 6652939f..67e412b 100644 --- a/chrome/common/extensions/api/api_sources.gni +++ b/chrome/common/extensions/api/api_sources.gni
@@ -100,6 +100,7 @@ "login.idl", "login_screen_storage.idl", "login_screen_ui.idl", + "login_state.idl", "platform_keys.idl", "platform_keys_internal.idl", "quick_unlock_private.idl",
diff --git a/chrome/common/extensions/api/login_state.idl b/chrome/common/extensions/api/login_state.idl new file mode 100644 index 0000000..c8195e4 --- /dev/null +++ b/chrome/common/extensions/api/login_state.idl
@@ -0,0 +1,51 @@ +// 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. + +// Use the <code>chrome.loginState</code> API to read and monitor the login +// state. +[platforms=("chromeos"), + implemented_in="chrome/browser/chromeos/extensions/login_screen/login_state/login_state_api.h"] +namespace loginState { + enum ProfileType { + // The extension is in the signin profile. + SIGNIN_PROFILE, + + // The extension is in the user profile. + USER_PROFILE + }; + + enum SessionState { + // The session state is unknown. + UNKNOWN, + + // The user is in the out-of-box-experience screen. + IN_OOBE_SCREEN, + + // The user is in the login screen. + IN_LOGIN_SCREEN, + + // The user is in the session. + IN_SESSION, + + // The user is in the lock screen. + IN_LOCK_SCREEN + }; + + callback ProfileTypeCallback = void (ProfileType result); + callback SessionStateCallback = void (SessionState result); + + interface Functions { + // Gets the type of the profile the extension is in. + static void getProfileType(ProfileTypeCallback callback); + + // Gets the current session state. + static void getSessionState(SessionStateCallback callback); + }; + + interface Events { + // Dispatched when the session state changes. <code>sessionState</code> + // is the new session state. + static void onSessionStateChanged(SessionState sessionState); + }; +};
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc index fe26ddd..e43cd3f 100644 --- a/chrome/common/extensions/permissions/permission_set_unittest.cc +++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -772,6 +772,7 @@ skip.insert(APIPermission::kIdle); skip.insert(APIPermission::kImeWindowEnabled); skip.insert(APIPermission::kIdltest); + skip.insert(APIPermission::kLoginState); skip.insert(APIPermission::kOverrideEscFullscreen); skip.insert(APIPermission::kPointerLock); skip.insert(APIPermission::kPower);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 86bcda0..c7fba9f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -798,6 +798,8 @@ "../browser/background_fetch/background_fetch_browsertest.cc", "../browser/background_sync/background_sync_browsertest.cc", "../browser/background_sync/background_sync_metrics_browsertest.cc", + "../browser/badging/test_badge_manager_delegate.cc", + "../browser/badging/test_badge_manager_delegate.h", "../browser/banners/app_banner_manager_browsertest.cc", "../browser/banners/app_banner_manager_browsertest_base.cc", "../browser/banners/app_banner_manager_browsertest_base.h", @@ -2002,6 +2004,8 @@ "../browser/chromeos/extensions/login_screen/login_screen_apitest_base.cc", "../browser/chromeos/extensions/login_screen/login_screen_apitest_base.h", "../browser/chromeos/extensions/login_screen/login_screen_ui/login_screen_ui_apitest.cc", + "../browser/chromeos/extensions/login_screen/login_state/login_state_apitest.cc", + "../browser/chromeos/extensions/login_screen/login_state/session_state_changed_event_dispatcher_apitest.cc", "../browser/chromeos/extensions/login_screen/storage_apitest.cc", "../browser/chromeos/extensions/users_private/users_private_apitest.cc", "../browser/chromeos/extensions/wallpaper_apitest.cc", @@ -3594,7 +3598,10 @@ # !is_android sources += [ # Badging isn't supported on Android. + "../browser/badging/badge_manager_delegate_unittest.cc", "../browser/badging/badge_manager_unittest.cc", + "../browser/badging/test_badge_manager_delegate.cc", + "../browser/badging/test_badge_manager_delegate.h", # Bookmark export/import are handled via the BookmarkColumns # ContentProvider. @@ -5814,8 +5821,8 @@ "../browser/sync/test/integration/extension_settings_helper.h", "../browser/sync/test/integration/extensions_helper.cc", "../browser/sync/test/integration/extensions_helper.h", - "../browser/sync/test/integration/fake_server_invalidation_service.cc", - "../browser/sync/test/integration/fake_server_invalidation_service.h", + "../browser/sync/test/integration/fake_server_invalidation_sender.cc", + "../browser/sync/test/integration/fake_server_invalidation_sender.h", "../browser/sync/test/integration/fake_server_match_status_checker.cc", "../browser/sync/test/integration/fake_server_match_status_checker.h", "../browser/sync/test/integration/feature_toggler.cc",
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/login_state/get_profile_type/manifest.json b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/get_profile_type/manifest.json new file mode 100644 index 0000000..bdd9ebb --- /dev/null +++ b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/get_profile_type/manifest.json
@@ -0,0 +1,12 @@ +{ + "name": "Get Profile Type", + "version": "0.1", + "manifest_version": 2, + "description": "Browser test for chrome.loginState.getProfileType()", + "background": { + "scripts": ["test.js"] + }, + "permissions": [ + "loginState" + ] +}
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/login_state/get_profile_type/test.js b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/get_profile_type/test.js new file mode 100644 index 0000000..bea3f95 --- /dev/null +++ b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/get_profile_type/test.js
@@ -0,0 +1,17 @@ +// 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. + +function testGetProfileType(expected) { + chrome.test.runTests([() => { + chrome.loginState.getProfileType(profileType => { + chrome.test.assertNoLastError(); + chrome.test.assertEq(expected, profileType); + chrome.test.succeed(); + }); + }]); +} + +chrome.test.getConfig(config => { + testGetProfileType(config.customArg); +});
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/login_state/on_session_state_changed/manifest.json b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/on_session_state_changed/manifest.json new file mode 100644 index 0000000..f299e1a9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/on_session_state_changed/manifest.json
@@ -0,0 +1,12 @@ +{ + "name": "On Session State Changed", + "version": "0.1", + "manifest_version": 2, + "description": "Browser test for chrome.loginState.onSessionStateChanged()", + "background": { + "scripts": ["test.js"] + }, + "permissions": [ + "loginState" + ] +}
diff --git a/chrome/test/data/extensions/api_test/login_screen_apis/login_state/on_session_state_changed/test.js b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/on_session_state_changed/test.js new file mode 100644 index 0000000..99a2e4e4 --- /dev/null +++ b/chrome/test/data/extensions/api_test/login_screen_apis/login_state/on_session_state_changed/test.js
@@ -0,0 +1,13 @@ +// 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. + +chrome.test.runTests([ + function testOnSessionStateChanged() { + chrome.loginState.onSessionStateChanged.addListener(sessionState => { + chrome.test.assertNoLastError(); + chrome.test.sendMessage(sessionState); + }); + chrome.test.succeed(); + }, +]);
diff --git a/chrome/test/data/ssl/page_with_in_scope_and_cross_site_frame.html b/chrome/test/data/ssl/page_with_in_scope_and_cross_site_frame.html index 39fa824..c7d7611 100644 --- a/chrome/test/data/ssl/page_with_in_scope_and_cross_site_frame.html +++ b/chrome/test/data/ssl/page_with_in_scope_and_cross_site_frame.html
@@ -3,6 +3,11 @@ </head> <body> <iframe name="in-scope" src="/ssl/google.html" id="in-scope"></iframe> - <iframe name="cross-site" src="https://example.com" id="cross-site"></iframe> + <iframe name="cross-site" id="cross-site"></iframe> + <script type="text/javascript"> + const crossFrame = document.getElementById('cross-site'); + const crossSiteUrl = new URLSearchParams(location.search).get('url'); + crossFrame.src = crossSiteUrl; + </script> </body> </html>
diff --git a/components/arc/ime/DEPS b/components/arc/ime/DEPS index 2b080107..ab2c42a0 100644 --- a/components/arc/ime/DEPS +++ b/components/arc/ime/DEPS
@@ -7,5 +7,4 @@ "+ui/gfx/geometry", # Revisit this dependency when crbug.com/890403 is resovled. "+ui/views", - "+ui/wm", ]
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc index 2ee9d3c..5db6d52 100644 --- a/components/arc/ime/arc_ime_service.cc +++ b/components/arc/ime/arc_ime_service.cc
@@ -26,7 +26,6 @@ #include "ui/gfx/range/range.h" #include "ui/views/widget/widget.h" #include "ui/views/window/non_client_view.h" -#include "ui/wm/core/ime_util_chromeos.h" namespace arc { @@ -497,13 +496,6 @@ return true; } -void ArcImeService::EnsureCaretNotInRect(const gfx::Rect& rect_in_screen) { - if (focused_arc_window_ == nullptr) - return; - aura::Window* top_level_window = focused_arc_window_->GetToplevelWindow(); - wm::EnsureWindowNotInRect(top_level_window, rect_in_screen); -} - ui::TextInputMode ArcImeService::GetTextInputMode() const { return ui::TEXT_INPUT_MODE_DEFAULT; }
diff --git a/components/arc/ime/arc_ime_service.h b/components/arc/ime/arc_ime_service.h index 8b59b60..9b68a96 100644 --- a/components/arc/ime/arc_ime_service.h +++ b/components/arc/ime/arc_ime_service.h
@@ -122,7 +122,6 @@ bool GetEditableSelectionRange(gfx::Range* range) const override; bool GetTextFromRange(const gfx::Range& range, base::string16* text) const override; - void EnsureCaretNotInRect(const gfx::Rect& rect) override; // Overridden from ui::TextInputClient (with default implementation): // TODO(kinaba): Support each of these methods to the extent possible in @@ -142,6 +141,7 @@ bool ChangeTextDirectionAndLayoutAlignment( base::i18n::TextDirection direction) override; void ExtendSelectionAndDelete(size_t before, size_t after) override; + void EnsureCaretNotInRect(const gfx::Rect& rect) override {} bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override; void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override { }
diff --git a/components/autofill/core/browser/data_model/credit_card_unittest.cc b/components/autofill/core/browser/data_model/credit_card_unittest.cc index 3280327..beda49c 100644 --- a/components/autofill/core/browser/data_model/credit_card_unittest.cc +++ b/components/autofill/core/browser/data_model/credit_card_unittest.cc
@@ -55,6 +55,15 @@ "3056 9309 0259 04aa", /* non-digit characters */ }; +// Time moves on. Today is yesterday's tomorrow. Tests don't like time moving +// on, in particular if Credit Card expiration is compared to local time. +// Use this function to generate a year in the future. +base::string16 GetYearInTheFuture() { + base::Time::Exploded now; + base::Time::Now().LocalExplode(&now); + return base::NumberToString16(now.year + 4); +} + } // namespace TEST(CreditCardTest, GetObfuscatedStringForCardDigits) { @@ -694,6 +703,8 @@ } TEST(CreditCardTest, UpdateFromImportedCard_UpdatedWithNameAndExpirationDate) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -704,18 +715,20 @@ b.set_guid(base::GenerateGUID()); b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger")); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); // |a| should be updated with the information from |b|. EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ(test::kEmptyOrigin, a.origin()); EXPECT_EQ(ASCIIToUTF16("J. Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL)); EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH)); - EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); + EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); } TEST(CreditCardTest, UpdateFromImportedCard_UpdatedWithNameAndInvalidExpirationDateMonth) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -729,7 +742,7 @@ b.set_guid(base::GenerateGUID()); b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger")); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("0")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ(test::kEmptyOrigin, a.origin()); @@ -766,6 +779,8 @@ TEST(CreditCardTest, UpdateFromImportedCard_UpdatedWithEmptyNameAndValidExpirationDate) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -778,19 +793,21 @@ b.set_guid(base::GenerateGUID()); b.SetRawInfo(CREDIT_CARD_NAME_FULL, base::string16()); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ(test::kEmptyOrigin, a.origin()); EXPECT_EQ(ASCIIToUTF16("John Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL)); EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH)); - EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); + EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); } TEST( CreditCardTest, UpdateFromImportedCard_VerifiedCardNotUpdatedWithEmptyExpirationDateMonth) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -805,7 +822,7 @@ b.set_origin(test::kEmptyOrigin); b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger")); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("0")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ("Chrome settings", a.origin()); @@ -867,6 +884,8 @@ TEST(CreditCardTest, UpdateFromImportedCard_ExpiredVerifiedCardNotUpdatedWithDifferentName) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -882,7 +901,7 @@ b.set_origin(test::kEmptyOrigin); b.SetRawInfo(CREDIT_CARD_NAME_FULL, ASCIIToUTF16("J. Dillinger")); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ("Chrome settings", a.origin()); @@ -894,6 +913,8 @@ TEST(CreditCardTest, UpdateFromImportedCard_ExpiredVerifiedCardUpdatedWithSameName) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -908,14 +929,14 @@ b.set_guid(base::GenerateGUID()); b.set_origin(test::kEmptyOrigin); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ("Chrome settings", a.origin()); EXPECT_EQ(ASCIIToUTF16("John Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL)); EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH)); - EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); + EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); } TEST(CreditCardTest, @@ -946,6 +967,8 @@ TEST(CreditCardTest, UpdateFromImportedCard_VerifiedCardUpdatedWithVerifiedCard) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -959,18 +982,20 @@ b.set_guid(base::GenerateGUID()); b.set_origin(kSettingsOrigin); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); EXPECT_TRUE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ("Chrome settings", a.origin()); EXPECT_EQ(ASCIIToUTF16("John Dillinger"), a.GetRawInfo(CREDIT_CARD_NAME_FULL)); EXPECT_EQ(ASCIIToUTF16("08"), a.GetRawInfo(CREDIT_CARD_EXP_MONTH)); - EXPECT_EQ(ASCIIToUTF16("2019"), a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); + EXPECT_EQ(kYearInFuture, a.GetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR)); } TEST(CreditCardTest, UpdateFromImportedCard_VerifiedCardNotUpdatedWithDifferentCard) { + const base::string16 kYearInFuture = GetYearInTheFuture(); + CreditCard original_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&original_card, "John Dillinger", "123456789012", "09", "2017", "1"); @@ -985,7 +1010,7 @@ b.set_origin(kSettingsOrigin); b.SetRawInfo(CREDIT_CARD_NUMBER, ASCIIToUTF16("4111111111111111")); b.SetRawInfo(CREDIT_CARD_EXP_MONTH, ASCIIToUTF16("08")); - b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, ASCIIToUTF16("2019")); + b.SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, kYearInFuture); EXPECT_FALSE(a.UpdateFromImportedCard(b, "en-US")); EXPECT_EQ("Chrome settings", a.origin());
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn index 1dbe41d2..9ddc5a1 100644 --- a/components/autofill_assistant/browser/BUILD.gn +++ b/components/autofill_assistant/browser/BUILD.gn
@@ -198,6 +198,7 @@ "actions/wait_for_dom_action_unittest.cc", "batch_element_checker_unittest.cc", "controller_unittest.cc", + "details_unittest.cc", "element_area_unittest.cc", "element_precondition_unittest.cc", "fake_script_executor_delegate.cc", @@ -228,6 +229,7 @@ "//base", "//base/test:test_support", "//components/autofill/core/browser:test_support", + "//components/strings:components_strings_grit", "//content/test:test_support", "//testing/gmock", "//testing/gtest",
diff --git a/components/autofill_assistant/browser/client_settings.cc b/components/autofill_assistant/browser/client_settings.cc index 81d8f29..f375b67 100644 --- a/components/autofill_assistant/browser/client_settings.cc +++ b/components/autofill_assistant/browser/client_settings.cc
@@ -44,6 +44,27 @@ if (proto.has_document_ready_check_count()) { document_ready_check_count = proto.document_ready_check_count(); } + if (proto.has_enable_graceful_shutdown()) { + enable_graceful_shutdown = proto.enable_graceful_shutdown(); + } + if (proto.has_graceful_shutdown_delay_ms()) { + graceful_shutdown_delay = + base::TimeDelta::FromMilliseconds(proto.graceful_shutdown_delay_ms()); + } + if (proto.has_cancel_delay_ms()) { + cancel_delay = base::TimeDelta::FromMilliseconds(proto.cancel_delay_ms()); + } + if (proto.has_tap_count()) { + tap_count = proto.tap_count(); + } + if (proto.has_tap_tracking_duration_ms()) { + tap_tracking_duration = + base::TimeDelta::FromMilliseconds(proto.tap_tracking_duration_ms()); + } + if (proto.has_tap_shutdown_delay_ms()) { + tap_shutdown_delay = + base::TimeDelta::FromMilliseconds(proto.tap_shutdown_delay_ms()); + } } } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/client_settings.h b/components/autofill_assistant/browser/client_settings.h index 0aaae220..f007b58 100644 --- a/components/autofill_assistant/browser/client_settings.h +++ b/components/autofill_assistant/browser/client_settings.h
@@ -61,6 +61,29 @@ // ready. int document_ready_check_count = 50; + // Whether graceful shutdown should be enabled. If false, the UI stays + // up until it's dismissed. + bool enable_graceful_shutdown = true; + + // How long to wait before shutting down during graceful shutdown. If 0 + // shutdown happens immediately. + base::TimeDelta graceful_shutdown_delay = base::TimeDelta::FromSeconds(5); + + // How much time to give users to tap undo when they tap a cancel button. + base::TimeDelta cancel_delay = base::TimeDelta::FromSeconds(5); + + // If the user taps the overlay that many time within |tap_duration| turn the + // UI off and give them |tap_shutdown_delay| to undo. If 0, unexpected taps + // are ignored. + int tap_count = 3; + + // Reset the unexpected tap counter after that time. + base::TimeDelta tap_tracking_duration = base::TimeDelta::FromSeconds(5); + + // How much time to give users to tap undo when after |tap_count| unexpected + // taps where + base::TimeDelta tap_shutdown_delay = base::TimeDelta::FromSeconds(5); + void UpdateFromProto(const ClientSettingsProto& proto); private:
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index f2c080c..d8a61ed 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -471,6 +471,10 @@ *colors = *overlay_colors_; } +const ClientSettings& Controller::GetClientSettings() const { + return settings_; +} + void Controller::ReportNavigationStateChanged() { // Listeners are called in the same order they were added. for (auto* listener : listeners_) { @@ -631,8 +635,12 @@ Metrics::DropOutReason::GET_SCRIPTS_UNPARSABLE); return; } - if (response_proto.has_client_settings()) + if (response_proto.has_client_settings()) { settings_.UpdateFromProto(response_proto.client_settings()); + for (ControllerObserver& observer : observers_) { + observer.OnClientSettingsChanged(settings_); + } + } std::vector<std::unique_ptr<Script>> scripts; for (const auto& script_proto : response_proto.scripts()) {
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h index 8257a24..d02640a 100644 --- a/components/autofill_assistant/browser/controller.h +++ b/components/autofill_assistant/browser/controller.h
@@ -169,6 +169,7 @@ ViewportMode GetViewportMode() override; ConfigureBottomSheetProto::PeekMode GetPeekMode() override; void GetOverlayColors(OverlayColors* colors) const override; + const ClientSettings& GetClientSettings() const override; const FormProto* GetForm() const override; void SetCounterValue(int input_index, int counter_index, int value) override; void SetChoiceSelected(int input_index,
diff --git a/components/autofill_assistant/browser/controller_observer.cc b/components/autofill_assistant/browser/controller_observer.cc index 51c3157..15fd369 100644 --- a/components/autofill_assistant/browser/controller_observer.cc +++ b/components/autofill_assistant/browser/controller_observer.cc
@@ -35,5 +35,7 @@ void ControllerObserver::OnOverlayColorsChanged( const UiDelegate::OverlayColors& colors) {} void ControllerObserver::OnFormChanged(const FormProto* form) {} +void ControllerObserver::OnClientSettingsChanged( + const ClientSettings& settings) {} } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller_observer.h b/components/autofill_assistant/browser/controller_observer.h index 91a1e67..2c576277 100644 --- a/components/autofill_assistant/browser/controller_observer.h +++ b/components/autofill_assistant/browser/controller_observer.h
@@ -101,6 +101,9 @@ // Called when the form has changed. virtual void OnFormChanged(const FormProto* form); + + // Called when client settings have changed. + virtual void OnClientSettingsChanged(const ClientSettings& settings); }; } // namespace autofill_assistant #endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CONTROLLER_OBSERVER_H_
diff --git a/components/autofill_assistant/browser/details.cc b/components/autofill_assistant/browser/details.cc index ac72c77..294d566 100644 --- a/components/autofill_assistant/browser/details.cc +++ b/components/autofill_assistant/browser/details.cc
@@ -28,6 +28,7 @@ ShowDetailsProto updated_proto = proto; // Legacy treatment for old proto fields. Can be removed once the backend // is updated to set the description_line_1/line_2 fields. + // TODO(crbug.com/806868): Is this still needed? if (updated_proto.details().has_description() && !updated_proto.details().has_description_line_2()) { updated_proto.mutable_details()->set_description_line_2( @@ -124,41 +125,41 @@ base::Value Details::GetDebugContext() const { base::Value dict(base::Value::Type::DICTIONARY); - if (!detailsProto().title().empty()) - dict.SetKey("title", base::Value(detailsProto().title())); + if (!details_proto().title().empty()) + dict.SetKey("title", base::Value(details_proto().title())); - if (!detailsProto().image_url().empty()) - dict.SetKey("image_url", base::Value(detailsProto().image_url())); + if (!details_proto().image_url().empty()) + dict.SetKey("image_url", base::Value(details_proto().image_url())); - if (!detailsProto().total_price().empty()) - dict.SetKey("total_price", base::Value(detailsProto().total_price())); + if (!details_proto().total_price().empty()) + dict.SetKey("total_price", base::Value(details_proto().total_price())); - if (!detailsProto().total_price_label().empty()) + if (!details_proto().total_price_label().empty()) dict.SetKey("total_price_label", - base::Value(detailsProto().total_price_label())); + base::Value(details_proto().total_price_label())); - if (!detailsProto().description_line_1().empty()) + if (!details_proto().description_line_1().empty()) dict.SetKey("description_line_1", - base::Value(detailsProto().description_line_1())); + base::Value(details_proto().description_line_1())); - if (!detailsProto().description_line_2().empty()) + if (!details_proto().description_line_2().empty()) dict.SetKey("description_line_2", - base::Value(detailsProto().description_line_2())); + base::Value(details_proto().description_line_2())); - if (!detailsProto().description_line_3().empty()) + if (!details_proto().description_line_3().empty()) dict.SetKey("description_line_3", - base::Value(detailsProto().description_line_3())); + base::Value(details_proto().description_line_3())); - if (detailsProto().has_datetime()) { + if (details_proto().has_datetime()) { dict.SetKey("datetime", base::Value(base::StringPrintf( "%d-%02d-%02dT%02d:%02d:%02d", - static_cast<int>(detailsProto().datetime().date().year()), - detailsProto().datetime().date().month(), - detailsProto().datetime().date().day(), - detailsProto().datetime().time().hour(), - detailsProto().datetime().time().minute(), - detailsProto().datetime().time().second()))); + static_cast<int>(details_proto().datetime().date().year()), + details_proto().datetime().date().month(), + details_proto().datetime().date().day(), + details_proto().datetime().time().hour(), + details_proto().datetime().time().minute(), + details_proto().datetime().time().second()))); } if (!datetime_.empty()) dict.SetKey("datetime_str", base::Value(datetime_));
diff --git a/components/autofill_assistant/browser/details.h b/components/autofill_assistant/browser/details.h index f19a1eb5..ccbdf748 100644 --- a/components/autofill_assistant/browser/details.h +++ b/components/autofill_assistant/browser/details.h
@@ -17,9 +17,9 @@ class Details { public: - const DetailsProto& detailsProto() const { return proto_; } + const DetailsProto& details_proto() const { return proto_; } const DetailsChangesProto& changes() const { return change_flags_; } - const std::string GetDatetime() const { return datetime_; } + const std::string datetime() const { return datetime_; } // Returns a dictionary describing the current execution context, which // is intended to be serialized as JSON string. The execution context is
diff --git a/components/autofill_assistant/browser/details_unittest.cc b/components/autofill_assistant/browser/details_unittest.cc new file mode 100644 index 0000000..8abf364c --- /dev/null +++ b/components/autofill_assistant/browser/details_unittest.cc
@@ -0,0 +1,245 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill_assistant/browser/details.h" + +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/geo/country_names.h" +#include "components/autofill_assistant/browser/details.h" +#include "components/autofill_assistant/browser/service.pb.h" +#include "components/autofill_assistant/browser/trigger_context.h" +#include "components/strings/grit/components_strings.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/base/l10n/l10n_util.h" + +namespace autofill_assistant { +namespace { + +using ::testing::Eq; + +MATCHER_P(EqualsProto, message, "") { + std::string expected_serialized, actual_serialized; + message.SerializeToString(&expected_serialized); + arg.SerializeToString(&actual_serialized); + return expected_serialized == actual_serialized; +} + +class DetailsTest : public testing::Test { + public: + DetailsTest() {} + + void SetUp() override { autofill::CountryNames::SetLocaleString("us-en"); } + + protected: + std::unique_ptr<autofill::CreditCard> MakeCreditCard() { + return std::make_unique<autofill::CreditCard>(); + } + + std::unique_ptr<autofill::AutofillProfile> MakeAutofillProfile() { + // The email contains a UTF-8 smiley face. + auto profile = std::make_unique<autofill::AutofillProfile>(); + autofill::test::SetProfileInfo(profile.get(), "Charles", "Hardin", "Holley", + "\xE2\x98\xBA@gmail.com", "Decca", + "123 Apple St.", "unit 6", "Lubbock", + "Texas", "79401", "US", "23456789012"); + return profile; + } + + ClientMemory client_memory_; +}; + +TEST_F(DetailsTest, DetailsProtoStoredInMemberVariable) { + Details details; + DetailsProto proto; + proto.set_title("title"); + + details.SetDetailsProto(proto); + EXPECT_THAT(proto, EqualsProto(details.details_proto())); +} + +TEST_F(DetailsTest, DetailsChangesProto) { + Details details; + DetailsChangesProto proto; + proto.set_user_approval_required(true); + + details.SetDetailsChangesProto(proto); + EXPECT_THAT(proto, EqualsProto(details.changes())); + + details.ClearChanges(); + EXPECT_THAT(DetailsChangesProto(), EqualsProto(details.changes())); +} + +TEST_F(DetailsTest, UpdateFromParametersEmpty) { + Details details; + // Nothing has to be updated. + auto context = TriggerContext::CreateEmpty(); + EXPECT_FALSE(details.UpdateFromParameters(*context)); +} + +TEST_F(DetailsTest, UpdateFromParametersShowInitialNoUpdate) { + std::map<std::string, std::string> parameters; + parameters["DETAILS_SHOW_INITIAL"] = "false"; + auto context = TriggerContext::Create(parameters, "exps"); + + Details details; + EXPECT_FALSE(details.UpdateFromParameters(*context)); +} + +TEST_F(DetailsTest, UpdateFromParametersUpdateFromDetails) { + std::map<std::string, std::string> parameters; + parameters["DETAILS_SHOW_INITIAL"] = "true"; + parameters["DETAILS_TITLE"] = "title"; + parameters["DETAILS_DESCRIPTION_LINE_1"] = "line1"; + parameters["DETAILS_DESCRIPTION_LINE_2"] = "line2"; + parameters["DETAILS_DESCRIPTION_LINE_3"] = "line3"; + parameters["DETAILS_IMAGE_URL"] = "image"; + parameters["DETAILS_IMAGE_CLICKTHROUGH_URL"] = "clickthrough"; + parameters["DETAILS_TOTAL_PRICE_LABEL"] = "total"; + parameters["DETAILS_TOTAL_PRICE"] = "12"; + + auto context = TriggerContext::Create(parameters, "exps"); + + Details details; + EXPECT_TRUE(details.UpdateFromParameters(*context)); + + DetailsProto expected; + expected.set_animate_placeholders(true); + expected.set_show_image_placeholder(true); + + expected.set_title("title"); + expected.set_description_line_1("line1"); + expected.set_description_line_2("line2"); + expected.set_description_line_3("line3"); + expected.set_image_url("image"); + auto* data = expected.mutable_image_clickthrough_data(); + data->set_allow_clickthrough(true); + data->set_clickthrough_url("clickthrough"); + expected.set_total_price_label("total"); + expected.set_total_price("12"); + + EXPECT_THAT(details.details_proto(), EqualsProto(expected)); +} + +TEST_F(DetailsTest, UpdateFromParametersBackwardsCompatibility) { + std::map<std::string, std::string> parameters; + parameters["MOVIES_MOVIE_NAME"] = "movie_name"; + parameters["MOVIES_THEATER_NAME"] = "movie_theater"; + parameters["MOVIES_SCREENING_DATETIME"] = "datetime"; + + auto context = TriggerContext::Create(parameters, "exps"); + + Details details; + EXPECT_TRUE(details.UpdateFromParameters(*context)); + + DetailsProto expected; + expected.set_animate_placeholders(true); + expected.set_show_image_placeholder(true); + + expected.set_title("movie_name"); + expected.set_description_line_2("movie_theater"); + + EXPECT_THAT(details.datetime(), "datetime"); + EXPECT_THAT(details.details_proto().title(), "movie_name"); + EXPECT_THAT(details.details_proto().description_line_2(), "movie_theater"); + + EXPECT_THAT(details.details_proto(), EqualsProto(expected)); +} + +TEST_F(DetailsTest, UpdateFromProtoNoDetails) { + Details details; + EXPECT_FALSE(Details::UpdateFromProto(ShowDetailsProto(), &details)); +} + +TEST_F(DetailsTest, UpdateFromProto) { + ShowDetailsProto proto; + proto.mutable_details()->set_title("title"); + proto.mutable_change_flags()->set_user_approval_required(true); + + Details details; + EXPECT_TRUE(Details::UpdateFromProto(proto, &details)); + + EXPECT_EQ(details.details_proto().title(), "title"); + EXPECT_TRUE(details.changes().user_approval_required()); +} + +TEST_F(DetailsTest, UpdateFromContactDetailsNoAddressInMemory) { + EXPECT_FALSE(Details::UpdateFromContactDetails(ShowDetailsProto(), + &client_memory_, nullptr)); +} + +TEST_F(DetailsTest, UpdateFromContactDetails) { + ShowDetailsProto proto; + proto.set_contact_details("contact"); + client_memory_.set_selected_address("contact", MakeAutofillProfile()); + + Details details; + EXPECT_TRUE( + Details::UpdateFromContactDetails(proto, &client_memory_, &details)); + + const auto& result = details.details_proto(); + EXPECT_THAT(result.title(), + Eq(l10n_util::GetStringUTF8(IDS_PAYMENTS_CONTACT_DETAILS_LABEL))); + EXPECT_THAT(result.description_line_1(), Eq("Charles Hardin Holley")); + EXPECT_THAT(result.description_line_2(), Eq("\xE2\x98\xBA@gmail.com")); +} + +TEST_F(DetailsTest, UpdateFromShippingAddressNoAddressInMemory) { + EXPECT_FALSE(Details::UpdateFromShippingAddress(ShowDetailsProto(), + &client_memory_, nullptr)); +} + +TEST_F(DetailsTest, UpdateFromShippingAddress) { + ShowDetailsProto proto; + proto.set_shipping_address("shipping"); + client_memory_.set_selected_address("shipping", MakeAutofillProfile()); + + Details details; + EXPECT_TRUE( + Details::UpdateFromShippingAddress(proto, &client_memory_, &details)); + + const auto& result = details.details_proto(); + EXPECT_THAT( + result.title(), + Eq(l10n_util::GetStringUTF8(IDS_PAYMENTS_SHIPPING_ADDRESS_LABEL))); + EXPECT_THAT(result.description_line_1(), Eq("Charles Hardin Holley")); + EXPECT_THAT(result.description_line_2(), + Eq("123 Apple St.\nunit 6 79401 Lubbock US")); +} + +TEST_F(DetailsTest, UpdateFromSelectedCreditCardEmptyMemory) { + ShowDetailsProto proto; + proto.set_credit_card(true); + EXPECT_FALSE(Details::UpdateFromContactDetails(ShowDetailsProto(), + &client_memory_, nullptr)); +} + +TEST_F(DetailsTest, UpdateFromSelectedCreditCardNotRequested) { + ShowDetailsProto proto; + proto.set_credit_card(false); + client_memory_.set_selected_card(MakeCreditCard()); + EXPECT_FALSE(Details::UpdateFromContactDetails(ShowDetailsProto(), + &client_memory_, nullptr)); +} + +TEST_F(DetailsTest, UpdateFromCreditCard) { + ShowDetailsProto proto; + proto.set_credit_card(true); + client_memory_.set_selected_card(MakeCreditCard()); + + Details details; + EXPECT_TRUE( + Details::UpdateFromSelectedCreditCard(proto, &client_memory_, &details)); + + const auto& result = details.details_proto(); + EXPECT_THAT( + result.title(), + Eq(l10n_util::GetStringUTF8(IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL))); + // The credit card string contains 4 non-ascii dots, we just check that it + // does contain something. + EXPECT_FALSE(result.description_line_1().empty()); +} + +} // namespace +} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index 9ef3ee8..d8e7d83 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -107,6 +107,29 @@ // Maximum number of checks to run while waiting for the document to become // ready. optional int32 document_ready_check_count = 9; + + // Whether graceful shutdown should be enabled. If false, the UI stays + // up until it's dismissed. + optional bool enable_graceful_shutdown = 10; + + // How long to wait before shutting down during graceful shutdown. If 0 + // shutdown happens immediately. + optional int32 graceful_shutdown_delay_ms = 11; + + // How much time to give users to tap undo when they tap a cancel button. + optional int32 cancel_delay_ms = 12; + + // If the user taps the overlay that many time within |tap_duration| turn the + // UI off and give them |tap_shutdown_delay| to undo. If 0, unexpected taps + // are ignored. + optional int32 tap_count = 13; + + // Reset the unexpected tap counter after that time. + optional int32 tap_tracking_duration_ms = 14; + + // How much time to give users to tap undo when after |tap_count| unexpected + // taps where + optional int32 tap_shutdown_delay_ms = 15; } message ScriptTimeoutError {
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h index c437d902..1c637dcd 100644 --- a/components/autofill_assistant/browser/ui_delegate.h +++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -19,6 +19,7 @@ namespace autofill_assistant { class ControllerObserver; +struct ClientSettings; // UI delegate called for script executions. class UiDelegate { @@ -156,6 +157,9 @@ // Fills in the overlay colors. virtual void GetOverlayColors(OverlayColors* colors) const = 0; + // Gets the current Client Settings + virtual const ClientSettings& GetClientSettings() const = 0; + // Returns the current form. May be null if there is no form to show. virtual const FormProto* GetForm() const = 0;
diff --git a/components/autofill_assistant/browser/website_login_fetcher_impl.cc b/components/autofill_assistant/browser/website_login_fetcher_impl.cc index 64ba33fe..f9fd911c 100644 --- a/components/autofill_assistant/browser/website_login_fetcher_impl.cc +++ b/components/autofill_assistant/browser/website_login_fetcher_impl.cc
@@ -81,10 +81,9 @@ std::vector<const autofill::PasswordForm*> matches = form_fetcher_->GetNonFederatedMatches(); std::map<base::string16, const autofill::PasswordForm*> best_matches; - std::vector<const autofill::PasswordForm*> not_best_matches; const autofill::PasswordForm* preferred_match = nullptr; password_manager_util::FindBestMatches(matches, &best_matches, - ¬_best_matches, &preferred_match); + &preferred_match); std::vector<Login> logins; for (const auto& match : best_matches) {
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc index e1ccedb..f00987f 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.cc +++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -111,7 +111,10 @@ web_data_service_on_disk, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service_in_memory, - const scoped_refptr<password_manager::PasswordStore>& password_store, + const scoped_refptr<password_manager::PasswordStore>& + profile_password_store, + const scoped_refptr<password_manager::PasswordStore>& + account_password_store, sync_bookmarks::BookmarkSyncService* bookmark_sync_service) : sync_client_(sync_client), channel_(channel), @@ -120,7 +123,8 @@ db_thread_(db_thread), web_data_service_on_disk_(web_data_service_on_disk), web_data_service_in_memory_(web_data_service_in_memory), - password_store_(password_store), + profile_password_store_(profile_password_store), + account_password_store_(account_password_store), bookmark_sync_service_(bookmark_sync_service) { DCHECK(sync_client_); } @@ -279,17 +283,21 @@ // disabled. if (!disabled_types.Has(syncer::PASSWORDS)) { if (base::FeatureList::IsEnabled(switches::kSyncUSSPasswords)) { - if (password_store_) { - // |password_store_| can be null in tests. + if (profile_password_store_) { + // |profile_password_store_| can be null in tests. controllers.push_back( std::make_unique<password_manager::PasswordModelTypeController>( - password_store_->CreateSyncControllerDelegate(), sync_service, - sync_client_->GetPasswordStateChangedCallback())); + profile_password_store_->CreateSyncControllerDelegate(), + account_password_store_ + ? account_password_store_->CreateSyncControllerDelegate() + : nullptr, + sync_service, sync_client_->GetPasswordStateChangedCallback())); } } else { controllers.push_back(std::make_unique<PasswordDataTypeController>( dump_stack, sync_service, sync_client_, - sync_client_->GetPasswordStateChangedCallback(), password_store_)); + sync_client_->GetPasswordStateChangedCallback(), + profile_password_store_)); } }
diff --git a/components/browser_sync/profile_sync_components_factory_impl.h b/components/browser_sync/profile_sync_components_factory_impl.h index 73f9459..f99db61 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.h +++ b/components/browser_sync/profile_sync_components_factory_impl.h
@@ -51,7 +51,10 @@ web_data_service_on_disk, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service_in_memory, - const scoped_refptr<password_manager::PasswordStore>& password_store, + const scoped_refptr<password_manager::PasswordStore>& + profile_password_store, + const scoped_refptr<password_manager::PasswordStore>& + account_password_store, sync_bookmarks::BookmarkSyncService* bookmark_sync_service); ~ProfileSyncComponentsFactoryImpl() override; @@ -119,7 +122,8 @@ web_data_service_on_disk_; const scoped_refptr<autofill::AutofillWebDataService> web_data_service_in_memory_; - const scoped_refptr<password_manager::PasswordStore> password_store_; + const scoped_refptr<password_manager::PasswordStore> profile_password_store_; + const scoped_refptr<password_manager::PasswordStore> account_password_store_; sync_bookmarks::BookmarkSyncService* const bookmark_sync_service_; DISALLOW_COPY_AND_ASSIGN(ProfileSyncComponentsFactoryImpl);
diff --git a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc index 8b2f294..286b3a1 100644 --- a/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc +++ b/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
@@ -40,8 +40,6 @@ #include "media/gpu/format_utils.h" #include "media/gpu/test/video_accelerator_unittest_helpers.h" #include "media/gpu/test/video_frame_helpers.h" -#include "media/gpu/video_frame_mapper.h" -#include "media/gpu/video_frame_mapper_factory.h" #include "media/parsers/jpeg_parser.h" #include "mojo/core/embedder/embedder.h" #include "testing/gtest/include/gtest/gtest.h" @@ -188,11 +186,20 @@ const gfx::Size& coded_size, const gfx::Size& visible_size); - // Creates a zero-initialized DMA-buf backed VideoFrame. + // Creates a zero-initialized DMA-buf backed VideoFrame. Also returns the + // backing GpuMemoryBuffer in |backing_gmb| if it is not null. scoped_refptr<media::VideoFrame> CreateDmaBufVideoFrame( media::VideoPixelFormat format, const gfx::Size& coded_size, - const gfx::Size& visible_size); + const gfx::Size& visible_size, + std::unique_ptr<gfx::GpuMemoryBuffer>* backing_gmb = nullptr); + + // Maps |gmb| into a VideoFrame containing the data pointers. |gmb| should + // outlive the returned Videoframe. + scoped_refptr<media::VideoFrame> MapToVideoFrame( + gfx::GpuMemoryBuffer* gmb, + const media::VideoFrameLayout& layout, + const gfx::Rect& visible_rect); // Gets a list of supported DMA-buf frame formats for // CreateDmaBufVideoFrame(). @@ -290,7 +297,8 @@ MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufVideoFrame( media::VideoPixelFormat format, const gfx::Size& coded_size, - const gfx::Size& visible_size) { + const gfx::Size& visible_size, + std::unique_ptr<gfx::GpuMemoryBuffer>* backing_gmb) { if (!gpu_memory_buffer_manager_) { LOG(ERROR) << "GpuMemoryBufferManager is not created" << format; return nullptr; @@ -351,11 +359,41 @@ LOG(ERROR) << "Failed to create VideoFrameLayout"; return nullptr; } + + if (backing_gmb) + *backing_gmb = std::move(gmb); + return media::VideoFrame::WrapExternalDmabufs( *layout, gfx::Rect(visible_size), visible_size, std::move(dmabuf_fds), base::TimeDelta()); } +scoped_refptr<media::VideoFrame> +MjpegDecodeAcceleratorTestEnvironment::MapToVideoFrame( + gfx::GpuMemoryBuffer* gmb, + const media::VideoFrameLayout& layout, + const gfx::Rect& visible_rect) { + DCHECK(gmb); + if (!gmb->Map()) { + LOG(ERROR) << "Failed to map GpuMemoryBuffer"; + return nullptr; + } + std::array<uint8_t*, 3> data{}; + for (size_t i = 0; i < layout.num_planes(); i++) + data[i] = static_cast<uint8_t*>(gmb->memory(i)); + scoped_refptr<media::VideoFrame> frame = + media::VideoFrame::WrapExternalYuvDataWithLayout( + layout, visible_rect, visible_rect.size(), data[0], data[1], data[2], + base::TimeDelta()); + if (!frame) { + LOG(ERROR) << "Failed to create VideoFrame"; + return nullptr; + } + frame->AddDestructionObserver( + base::BindOnce(&gfx::GpuMemoryBuffer::Unmap, base::Unretained(gmb))); + return frame; +} + std::vector<media::VideoPixelFormat> MjpegDecodeAcceleratorTestEnvironment::GetSupportedDmaBufFormats() { constexpr media::VideoPixelFormat kPreferredFormats[] = { @@ -437,14 +475,12 @@ base::UnsafeSharedMemoryRegion in_shm_; base::WritableSharedMemoryMapping in_shm_mapping_; // Output video frame from the hardware decoder. + std::unique_ptr<gfx::GpuMemoryBuffer> hw_out_gmb_; scoped_refptr<media::VideoFrame> hw_out_dmabuf_frame_; scoped_refptr<media::VideoFrame> hw_out_frame_; // Output video frame from the software decoder. scoped_refptr<media::VideoFrame> sw_out_frame_; - // Video frame mapper used to map |hw_out_dmabuf_frame_| for software access. - std::unique_ptr<media::VideoFrameMapper> frame_mapper_; - // This should be the first member to get destroyed because |decoder_| // potentially uses other members in the JpegClient instance. For example, // as decode tasks finish in a new thread spawned by |decoder_|, @@ -510,9 +546,9 @@ if (use_dmabuf_) { // Map and convert the output frame to I420. - ASSERT_TRUE(frame_mapper_); - scoped_refptr<media::VideoFrame> mapped_frame = - frame_mapper_->Map(hw_out_dmabuf_frame_); + scoped_refptr<media::VideoFrame> mapped_frame = g_env->MapToVideoFrame( + hw_out_gmb_.get(), hw_out_dmabuf_frame_->layout(), + hw_out_dmabuf_frame_->visible_rect()); ASSERT_TRUE(mapped_frame); hw_out_frame_ = media::test::ConvertVideoFrame(mapped_frame.get(), media::PIXEL_FORMAT_I420); @@ -558,11 +594,10 @@ g_env->GetSupportedDmaBufFormats(); ASSERT_FALSE(supported_formats.empty()); hw_out_dmabuf_frame_ = g_env->CreateDmaBufVideoFrame( - supported_formats[0], image_file->coded_size, image_file->visible_size); + supported_formats[0], image_file->coded_size, image_file->visible_size, + &hw_out_gmb_); ASSERT_TRUE(hw_out_dmabuf_frame_); - frame_mapper_ = media::VideoFrameMapperFactory::CreateMapper( - hw_out_dmabuf_frame_->format()); - ASSERT_TRUE(frame_mapper_); + ASSERT_TRUE(hw_out_gmb_); } else { // MJDA only supports I420 format for SHM output buffer. hw_out_frame_ = g_env->CreateShmVideoFrame(media::PIXEL_FORMAT_I420,
diff --git a/components/exo/test/exo_test_base_views.cc b/components/exo/test/exo_test_base_views.cc index 09f25a3..78fa55ed 100644 --- a/components/exo/test/exo_test_base_views.cc +++ b/components/exo/test/exo_test_base_views.cc
@@ -102,7 +102,6 @@ ExoTestBaseViews::~ExoTestBaseViews() {} void ExoTestBaseViews::SetUp() { - ui::SetUpInputMethodFactoryForTesting(); views::ViewsTestBase::SetUp(); // Takes care of its own lifetime. new wm::DefaultActivationClient(root_window());
diff --git a/components/exo/test/exo_test_base_views.h b/components/exo/test/exo_test_base_views.h index 4ffebe3..0635d45 100644 --- a/components/exo/test/exo_test_base_views.h +++ b/components/exo/test/exo_test_base_views.h
@@ -6,6 +6,7 @@ #define COMPONENTS_EXO_TEST_EXO_TEST_BASE_VIEWS_H_ #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/ime/init/input_method_factory.h" #include "ui/views/test/views_test_base.h" namespace exo { @@ -27,6 +28,7 @@ private: std::unique_ptr<WMHelper> wm_helper_; + ui::ScopedTestInputMethodFactory scoped_test_input_method_factory_; }; } // namespace test
diff --git a/components/password_manager/README.md b/components/password_manager/README.md index 3bbe4aae1..24a37729 100644 --- a/components/password_manager/README.md +++ b/components/password_manager/README.md
@@ -97,9 +97,6 @@ to offer password saving or updating existing credentials after a successful form submission. - Note: At the moment [`NewPasswordFormManager`] is the relevant class to look - at. This will soon replace the old [`PasswordFormManager`] implementation. - * `*::PasswordManagerDriver` (1 per frame) The `*::PasswordManagerDriver` is the browser-side communication end-point for @@ -155,7 +152,7 @@ [`mojom::PasswordAutofillAgent`]: https://cs.chromium.org/search?q=file:autofill_agent.mojom+"interface+PasswordAutofillAgent" [`mojom::PasswordGenerationAgent`]: https://cs.chromium.org/search?q=file:autofill_agent.mojom+"interface+PasswordGenerationAgent" [`mojom::PasswordManagerDriver`]: https://cs.chromium.org/search?q=file:autofill_driver.mojom+"interface+PasswordManagerDriver" -[`NewPasswordFormManager`]: https://cs.chromium.org/search?q=file:/new_password_form_manager.h$ +[`PasswordFormManager`]: https://cs.chromium.org/search?q=file:/password_form_manager.h$ [`password_manager::PasswordManagerDriver`]: https://cs.chromium.org/search?q=file:/password_manager_driver.h$ [`password_manager::PasswordManagerDriver`]: https://cs.chromium.org/search?q=file:/password_manager_driver.h$ [`PasswordAutofillAgent`]: https://cs.chromium.org/search?q=file:/password_autofill_agent.h$
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index a06156a..b6ec5e5 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -98,8 +98,6 @@ "login_database_mac.cc", "login_database_win.cc", "manage_passwords_referrer.h", - "new_password_form_manager.cc", - "new_password_form_manager.h", "origin_credential_store.cc", "origin_credential_store.h", "password_autofill_manager.cc", @@ -108,6 +106,8 @@ "password_bubble_experiment.h", "password_form_filling.cc", "password_form_filling.h", + "password_form_manager.cc", + "password_form_manager.h", "password_form_manager_for_ui.h", "password_form_metrics_recorder.cc", "password_form_metrics_recorder.h", @@ -493,11 +493,11 @@ "import/password_csv_reader_unittest.cc", "import/password_importer_unittest.cc", "login_database_unittest.cc", - "new_password_form_manager_unittest.cc", "origin_credential_store_unittest.cc", "password_autofill_manager_unittest.cc", "password_bubble_experiment_unittest.cc", "password_form_filling_unittest.cc", + "password_form_manager_unittest.cc", "password_form_metrics_recorder_unittest.cc", "password_generation_frame_helper_unittest.cc", "password_generation_state_unittest.cc",
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager.cc b/components/password_manager/core/browser/credential_manager_password_form_manager.cc index 8d620b57..aa580710 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager.cc +++ b/components/password_manager/core/browser/credential_manager_password_form_manager.cc
@@ -26,19 +26,19 @@ CredentialManagerPasswordFormManagerDelegate* delegate, std::unique_ptr<FormSaver> form_saver, std::unique_ptr<FormFetcher> form_fetcher) - : NewPasswordFormManager(client, - std::move(saved_form), - std::move(form_fetcher), - (form_saver ? std::move(form_saver) - : std::make_unique<FormSaverImpl>( - client->GetPasswordStore()))), + : PasswordFormManager(client, + std::move(saved_form), + std::move(form_fetcher), + (form_saver ? std::move(form_saver) + : std::make_unique<FormSaverImpl>( + client->GetPasswordStore()))), delegate_(delegate) {} CredentialManagerPasswordFormManager::~CredentialManagerPasswordFormManager() = default; void CredentialManagerPasswordFormManager::OnFetchCompleted() { - NewPasswordFormManager::OnFetchCompleted(); + PasswordFormManager::OnFetchCompleted(); CreatePendingCredentials();
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager.h b/components/password_manager/core/browser/credential_manager_password_form_manager.h index 5f6648d..6a88aa81 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager.h +++ b/components/password_manager/core/browser/credential_manager_password_form_manager.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" namespace autofill { struct PasswordForm; @@ -27,7 +27,7 @@ // A PasswordFormManager built to handle PasswordForm objects synthesized // by the Credential Manager API. -class CredentialManagerPasswordFormManager : public NewPasswordFormManager { +class CredentialManagerPasswordFormManager : public PasswordFormManager { public: // Given a |client| and an |observed_form|, kick off the process of fetching // matching logins from the password store; if |observed_form| doesn't map to
diff --git a/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc b/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc index 83ed65f..83dd964 100644 --- a/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/credential_manager_password_form_manager_unittest.cc
@@ -47,7 +47,7 @@ const base::string16& old_password)); // Convenience downcasting method. - static MockFormSaver& Get(NewPasswordFormManager* form_manager) { + static MockFormSaver& Get(PasswordFormManager* form_manager) { return *static_cast<MockFormSaver*>(form_manager->form_saver()); }
diff --git a/components/password_manager/core/browser/http_auth_manager_impl.cc b/components/password_manager/core/browser/http_auth_manager_impl.cc index 13e66d38..7f57ce5 100644 --- a/components/password_manager/core/browser/http_auth_manager_impl.cc +++ b/components/password_manager/core/browser/http_auth_manager_impl.cc
@@ -9,7 +9,7 @@ #include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/save_password_progress_logger.h" #include "components/password_manager/core/browser/form_saver_impl.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_form_manager_for_ui.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_util.h" @@ -59,7 +59,7 @@ observer_->OnLoginModelDestroying(); observer_ = observer; // Initialize the form manager. - form_manager_ = std::make_unique<NewPasswordFormManager>( + form_manager_ = std::make_unique<PasswordFormManager>( client_, PasswordStore::FormDigest(observed_form), nullptr, /* form_fetcher */ std::make_unique<FormSaverImpl>(client_->GetPasswordStore()));
diff --git a/components/password_manager/core/browser/http_auth_manager_impl.h b/components/password_manager/core/browser/http_auth_manager_impl.h index f6fca7c..bd54cf4 100644 --- a/components/password_manager/core/browser/http_auth_manager_impl.h +++ b/components/password_manager/core/browser/http_auth_manager_impl.h
@@ -18,7 +18,7 @@ namespace password_manager { class PasswordManagerClient; -class NewPasswordFormManager; +class PasswordFormManager; class PasswordFormManagerForUI; // Implementation of the HttpAuthManager as used by the PasswordManagerClient. @@ -55,7 +55,7 @@ // Get a Logger object and write a log message defined by the message id. void LogMessage(const BrowserSavePasswordProgressLogger::StringID) const; - // Passes |form| to NewPasswordFormManager that manages it for using it after + // Passes |form| to PasswordFormManager that manages it for using it after // detecting submission success for saving. void ProvisionallySaveForm(const autofill::PasswordForm& password_form); @@ -69,7 +69,7 @@ HttpAuthObserver* observer_; // Single password form manager to handle the http-auth request form. - std::unique_ptr<NewPasswordFormManager> form_manager_; + std::unique_ptr<PasswordFormManager> form_manager_; // When set to true, the password form has been dismissed and |form_manager_| // will be cleared on next navigation.
diff --git a/components/password_manager/core/browser/http_auth_manager_unittest.cc b/components/password_manager/core/browser/http_auth_manager_unittest.cc index 5465022e..a2d57dd 100644 --- a/components/password_manager/core/browser/http_auth_manager_unittest.cc +++ b/components/password_manager/core/browser/http_auth_manager_unittest.cc
@@ -21,7 +21,7 @@ #include "components/password_manager/core/browser/form_fetcher_impl.h" #include "components/password_manager/core/browser/http_auth_manager_impl.h" #include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_form_manager_for_ui.h" #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/core/browser/password_store.h"
diff --git a/components/password_manager/core/browser/leak_detection_delegate.cc b/components/password_manager/core/browser/leak_detection_delegate.cc index e6c8667..56a9fd8 100644 --- a/components/password_manager/core/browser/leak_detection_delegate.cc +++ b/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -61,15 +61,15 @@ if (client_->GetPasswordSyncState() != SYNCING_NORMAL_ENCRYPTION) { // If the credentials are not synced, the |CredentialLeakType| needed to // show the correct notification is already determined. - OnShowLeakDetectionNotifiction( + OnShowLeakDetectionNotification( CreateLeakType(IsSaved(false), IsReused(false), IsSyncing(false)), std::move(url), std::move(username)); } else { // Otherwise query the helper to asynchronously determine the // |CredentialLeakType|. - helper_ = std::make_unique<LeakDetectionDelegateHelper>( - base::BindOnce(&LeakDetectionDelegate::OnShowLeakDetectionNotifiction, - base::Unretained(this))); + helper_ = std::make_unique<LeakDetectionDelegateHelper>(base::BindOnce( + &LeakDetectionDelegate::OnShowLeakDetectionNotification, + base::Unretained(this))); helper_->GetCredentialLeakType(client_->GetPasswordStore(), std::move(url), std::move(username), std::move(password)); @@ -77,7 +77,7 @@ } } -void LeakDetectionDelegate::OnShowLeakDetectionNotifiction( +void LeakDetectionDelegate::OnShowLeakDetectionNotification( CredentialLeakType leak_type, GURL url, base::string16 username) {
diff --git a/components/password_manager/core/browser/leak_detection_delegate.h b/components/password_manager/core/browser/leak_detection_delegate.h index ebb9c2eb..d05282537 100644 --- a/components/password_manager/core/browser/leak_detection_delegate.h +++ b/components/password_manager/core/browser/leak_detection_delegate.h
@@ -55,9 +55,9 @@ // Initiates the showing of the leak detection notification. If the account is // synced, it is called by |helper_| after the |leak_type| was asynchronously // determined. - void OnShowLeakDetectionNotifiction(CredentialLeakType leak_type, - GURL url, - base::string16 username); + void OnShowLeakDetectionNotification(CredentialLeakType leak_type, + GURL url, + base::string16 username); void OnError(LeakDetectionError error) override;
diff --git a/components/password_manager/core/browser/password_form_filling.cc b/components/password_manager/core/browser/password_form_filling.cc index 63293c3..9652bf00 100644 --- a/components/password_manager/core/browser/password_form_filling.cc +++ b/components/password_manager/core/browser/password_form_filling.cc
@@ -121,7 +121,7 @@ } DCHECK(preferred_match); - // If the parser of the NewPasswordFormManager decides that there is no + // If the parser of the PasswordFormManager decides that there is no // current password field, no filling attempt will be made. In this case the // renderer won't treat this as the "first filling" and won't record metrics // accordingly. The browser should not do that either.
diff --git a/components/password_manager/core/browser/new_password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc similarity index 88% rename from components/password_manager/core/browser/new_password_form_manager.cc rename to components/password_manager/core/browser/password_form_manager.cc index bf8d938..8ff4bdb 100644 --- a/components/password_manager/core/browser/new_password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.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/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include <algorithm> #include <memory> @@ -43,7 +43,7 @@ namespace password_manager { -bool NewPasswordFormManager::wait_for_server_predictions_for_filling_ = true; +bool PasswordFormManager::wait_for_server_predictions_for_filling_ = true; namespace { @@ -127,18 +127,18 @@ } // namespace -NewPasswordFormManager::NewPasswordFormManager( +PasswordFormManager::PasswordFormManager( PasswordManagerClient* client, const base::WeakPtr<PasswordManagerDriver>& driver, const FormData& observed_form, FormFetcher* form_fetcher, std::unique_ptr<FormSaver> form_saver, scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder) - : NewPasswordFormManager(client, - form_fetcher, - std::move(form_saver), - metrics_recorder, - PasswordStore::FormDigest(observed_form)) { + : PasswordFormManager(client, + form_fetcher, + std::move(form_saver), + metrics_recorder, + PasswordStore::FormDigest(observed_form)) { driver_ = driver; observed_form_ = observed_form; metrics_recorder_->RecordFormSignature(CalculateFormSignature(observed_form)); @@ -152,27 +152,27 @@ votes_uploader_.StoreInitialFieldValues(observed_form); } -NewPasswordFormManager::NewPasswordFormManager( +PasswordFormManager::PasswordFormManager( PasswordManagerClient* client, PasswordStore::FormDigest observed_http_auth_digest, FormFetcher* form_fetcher, std::unique_ptr<FormSaver> form_saver) - : NewPasswordFormManager(client, - form_fetcher, - std::move(form_saver), - nullptr /* metrics_recorder */, - observed_http_auth_digest) { + : PasswordFormManager(client, + form_fetcher, + std::move(form_saver), + nullptr /* metrics_recorder */, + observed_http_auth_digest) { observed_not_web_form_digest_ = std::move(observed_http_auth_digest); if (owned_form_fetcher_) owned_form_fetcher_->Fetch(); form_fetcher_->AddConsumer(this); } -NewPasswordFormManager::~NewPasswordFormManager() { +PasswordFormManager::~PasswordFormManager() { form_fetcher_->RemoveConsumer(this); } -bool NewPasswordFormManager::DoesManage( +bool PasswordFormManager::DoesManage( const FormData& form, const PasswordManagerDriver* driver) const { if (driver != driver_.get()) @@ -191,7 +191,7 @@ #endif } -bool NewPasswordFormManager::DoesManageAccordingToRendererId( +bool PasswordFormManager::DoesManageAccordingToRendererId( uint32_t form_renderer_id, const PasswordManagerDriver* driver) const { if (driver != driver_.get()) @@ -205,7 +205,7 @@ #endif } -bool NewPasswordFormManager::IsEqualToSubmittedForm( +bool PasswordFormManager::IsEqualToSubmittedForm( const autofill::FormData& form) const { if (!is_submitted_) return false; @@ -218,49 +218,48 @@ return false; } -const GURL& NewPasswordFormManager::GetOrigin() const { +const GURL& PasswordFormManager::GetOrigin() const { return observed_not_web_form_digest_ ? observed_not_web_form_digest_->origin : observed_form_.url; } const std::map<base::string16, const PasswordForm*>& -NewPasswordFormManager::GetBestMatches() const { +PasswordFormManager::GetBestMatches() const { return best_matches_; } std::vector<const autofill::PasswordForm*> -NewPasswordFormManager::GetFederatedMatches() const { +PasswordFormManager::GetFederatedMatches() const { return form_fetcher_->GetFederatedMatches(); } -const PasswordForm& NewPasswordFormManager::GetPendingCredentials() const { +const PasswordForm& PasswordFormManager::GetPendingCredentials() const { return pending_credentials_; } -metrics_util::CredentialSourceType -NewPasswordFormManager::GetCredentialSource() { +metrics_util::CredentialSourceType PasswordFormManager::GetCredentialSource() { return metrics_util::CredentialSourceType::kPasswordManager; } -PasswordFormMetricsRecorder* NewPasswordFormManager::GetMetricsRecorder() { +PasswordFormMetricsRecorder* PasswordFormManager::GetMetricsRecorder() { return metrics_recorder_.get(); } base::span<const autofill::PasswordForm* const> -NewPasswordFormManager::GetBlacklistedMatches() const { +PasswordFormManager::GetBlacklistedMatches() const { return base::make_span(blacklisted_matches_); } -base::span<const InteractionsStats> -NewPasswordFormManager::GetInteractionsStats() const { +base::span<const InteractionsStats> PasswordFormManager::GetInteractionsStats() + const { return base::make_span(form_fetcher_->GetInteractionsStats()); } -bool NewPasswordFormManager::IsBlacklisted() const { +bool PasswordFormManager::IsBlacklisted() const { return !blacklisted_matches_.empty(); } -void NewPasswordFormManager::Save() { +void PasswordFormManager::Save() { DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState()); DCHECK(!client_->IsIncognito()); @@ -302,7 +301,7 @@ client_->UpdateFormManagers(); } -void NewPasswordFormManager::Update(const PasswordForm& credentials_to_update) { +void PasswordFormManager::Update(const PasswordForm& credentials_to_update) { metrics_util::LogPasswordAcceptedSaveUpdateSubmissionIndicatorEvent( parsed_submitted_form_->submission_event); metrics_recorder_->SetSubmissionIndicatorEvent( @@ -325,8 +324,7 @@ client_->UpdateFormManagers(); } -void NewPasswordFormManager::UpdateUsername( - const base::string16& new_username) { +void PasswordFormManager::UpdateUsername(const base::string16& new_username) { DCHECK(parsed_submitted_form_); parsed_submitted_form_->username_value = new_username; parsed_submitted_form_->username_element.clear(); @@ -352,7 +350,7 @@ CreatePendingCredentials(); } -void NewPasswordFormManager::UpdatePasswordValue( +void PasswordFormManager::UpdatePasswordValue( const base::string16& new_password) { DCHECK(parsed_submitted_form_); parsed_submitted_form_->password_value = new_password; @@ -374,13 +372,13 @@ CreatePendingCredentials(); } -void NewPasswordFormManager::OnNopeUpdateClicked() { +void PasswordFormManager::OnNopeUpdateClicked() { votes_uploader_.UploadPasswordVote(*parsed_submitted_form_, *parsed_submitted_form_, autofill::NOT_NEW_PASSWORD, std::string()); } -void NewPasswordFormManager::OnNeverClicked() { +void PasswordFormManager::OnNeverClicked() { // |UNKNOWN_TYPE| is sent in order to record that a generation popup was // shown and ignored. votes_uploader_.UploadPasswordVote(*parsed_submitted_form_, @@ -389,7 +387,7 @@ PermanentlyBlacklist(); } -void NewPasswordFormManager::OnNoInteraction(bool is_update) { +void PasswordFormManager::OnNoInteraction(bool is_update) { // |UNKNOWN_TYPE| is sent in order to record that a generation popup was // shown and ignored. votes_uploader_.UploadPasswordVote( @@ -398,7 +396,7 @@ std::string()); } -void NewPasswordFormManager::PermanentlyBlacklist() { +void PasswordFormManager::PermanentlyBlacklist() { DCHECK(!client_->IsIncognito()); if (!new_blacklisted_) { @@ -420,31 +418,30 @@ PasswordStore::FormDigest(*new_blacklisted_)); } -void NewPasswordFormManager::OnPasswordsRevealed() { +void PasswordFormManager::OnPasswordsRevealed() { votes_uploader_.set_has_passwords_revealed_vote(true); } -bool NewPasswordFormManager::IsNewLogin() const { +bool PasswordFormManager::IsNewLogin() const { return is_new_login_; } -FormFetcher* NewPasswordFormManager::GetFormFetcher() { +FormFetcher* PasswordFormManager::GetFormFetcher() { return form_fetcher_; } -bool NewPasswordFormManager::IsPendingCredentialsPublicSuffixMatch() const { +bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() const { return pending_credentials_.is_public_suffix_match; } -void NewPasswordFormManager::PresaveGeneratedPassword( - const PasswordForm& form) { +void PasswordFormManager::PresaveGeneratedPassword(const PasswordForm& form) { // TODO(https://crbug.com/831123): Propagate generated password independently // of PasswordForm when PasswordForm goes away from the renderer process. PresaveGeneratedPasswordInternal(form.form_data, form.password_value /*generated_password*/); } -void NewPasswordFormManager::PasswordNoLongerGenerated() { +void PasswordFormManager::PasswordNoLongerGenerated() { if (!HasGeneratedPassword()) return; @@ -456,11 +453,11 @@ PasswordFormMetricsRecorder::GeneratedPasswordStatus::kPasswordDeleted); } -bool NewPasswordFormManager::HasGeneratedPassword() const { +bool PasswordFormManager::HasGeneratedPassword() const { return generation_state_ && generation_state_->HasGeneratedPassword(); } -void NewPasswordFormManager::SetGenerationPopupWasShown( +void PasswordFormManager::SetGenerationPopupWasShown( bool generation_popup_was_shown, bool is_manual_generation) { votes_uploader_.set_generation_popup_was_shown(generation_popup_was_shown); @@ -469,32 +466,31 @@ is_manual_generation); } -void NewPasswordFormManager::SetGenerationElement( +void PasswordFormManager::SetGenerationElement( const base::string16& generation_element) { votes_uploader_.set_generation_element(generation_element); } -bool NewPasswordFormManager::IsPossibleChangePasswordFormWithoutUsername() - const { +bool PasswordFormManager::IsPossibleChangePasswordFormWithoutUsername() const { return parsed_submitted_form_ && parsed_submitted_form_->IsPossibleChangePasswordFormWithoutUsername(); } -bool NewPasswordFormManager::IsPasswordUpdate() const { +bool PasswordFormManager::IsPasswordUpdate() const { return password_overridden_; } std::vector<base::WeakPtr<PasswordManagerDriver>> -NewPasswordFormManager::GetDrivers() const { +PasswordFormManager::GetDrivers() const { return {driver_}; } -const PasswordForm* NewPasswordFormManager::GetSubmittedForm() const { +const PasswordForm* PasswordFormManager::GetSubmittedForm() const { return parsed_submitted_form_.get(); } #if defined(OS_IOS) -void NewPasswordFormManager::PresaveGeneratedPassword( +void PasswordFormManager::PresaveGeneratedPassword( PasswordManagerDriver* driver, const FormData& form, const base::string16& generated_password, @@ -504,7 +500,7 @@ votes_uploader_.set_generation_element(generation_element); } -bool NewPasswordFormManager::UpdateGeneratedPasswordOnUserInput( +bool PasswordFormManager::UpdateGeneratedPasswordOnUserInput( const base::string16& form_identifier, const base::string16& field_identifier, const base::string16& field_value) { @@ -533,7 +529,7 @@ } #endif // defined(OS_IOS) -std::unique_ptr<NewPasswordFormManager> NewPasswordFormManager::Clone() { +std::unique_ptr<PasswordFormManager> PasswordFormManager::Clone() { // Fetcher is cloned to avoid re-fetching data from PasswordStore. std::unique_ptr<FormFetcher> fetcher = form_fetcher_->Clone(); @@ -542,7 +538,7 @@ // renderer process, to which the driver serves as an interface. The full // |observed_form_| needs to be copied, because it is used to create the // blacklisting entry if needed. - auto result = std::make_unique<NewPasswordFormManager>( + auto result = std::make_unique<PasswordFormManager>( client_, base::WeakPtr<PasswordManagerDriver>(), observed_form_, fetcher.get(), form_saver_->Clone(), metrics_recorder_); @@ -579,16 +575,16 @@ return result; } -NewPasswordFormManager::NewPasswordFormManager( +PasswordFormManager::PasswordFormManager( PasswordManagerClient* client, std::unique_ptr<PasswordForm> saved_form, std::unique_ptr<FormFetcher> form_fetcher, std::unique_ptr<FormSaver> form_saver) - : NewPasswordFormManager(client, - form_fetcher.get(), - std::move(form_saver), - nullptr /* metrics_recorder */, - PasswordStore::FormDigest(*saved_form)) { + : PasswordFormManager(client, + form_fetcher.get(), + std::move(form_saver), + nullptr /* metrics_recorder */, + PasswordStore::FormDigest(*saved_form)) { observed_not_web_form_digest_ = PasswordStore::FormDigest(*saved_form); parsed_submitted_form_ = std::move(saved_form); is_submitted_ = true; @@ -598,17 +594,12 @@ form_fetcher_->Fetch(); } -void NewPasswordFormManager::OnFetchCompleted() { +void PasswordFormManager::OnFetchCompleted() { received_stored_credentials_time_ = TimeTicks::Now(); - std::vector<const PasswordForm*> matches; - PasswordForm::Scheme observed_form_scheme = GetScheme(); - for (const auto* match : form_fetcher_->GetNonFederatedMatches()) { - if (match->scheme == observed_form_scheme) - matches.push_back(match); - } + std::vector<const PasswordForm*> matches = GetAllMatches(); password_manager_util::FindBestMatches(matches, &best_matches_, - ¬_best_matches_, &preferred_match_); + &preferred_match_); // Copy out blacklisted matches. new_blacklisted_.reset(); @@ -633,13 +624,13 @@ waiting_for_server_predictions_ = true; base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, - base::BindOnce(&NewPasswordFormManager::Fill, + base::BindOnce(&PasswordFormManager::Fill, weak_ptr_factory_.GetWeakPtr()), kMaxFillingDelayForServerPredictions); } } -bool NewPasswordFormManager::ProvisionallySave( +bool PasswordFormManager::ProvisionallySave( const FormData& submitted_form, const PasswordManagerDriver* driver) { DCHECK(DoesManage(submitted_form, driver)); @@ -664,7 +655,7 @@ return true; } -bool NewPasswordFormManager::ProvisionallySaveHttpAuthForm( +bool PasswordFormManager::ProvisionallySaveHttpAuthForm( const PasswordForm& submitted_form) { if (!IsHttpAuth()) return false; @@ -678,20 +669,20 @@ return true; } -bool NewPasswordFormManager::IsHttpAuth() const { +bool PasswordFormManager::IsHttpAuth() const { return GetScheme() != PasswordForm::Scheme::kHtml; } -bool NewPasswordFormManager::IsCredentialAPISave() const { +bool PasswordFormManager::IsCredentialAPISave() const { return observed_not_web_form_digest_ && !IsHttpAuth(); } -PasswordForm::Scheme NewPasswordFormManager::GetScheme() const { +PasswordForm::Scheme PasswordFormManager::GetScheme() const { return observed_not_web_form_digest_ ? observed_not_web_form_digest_->scheme : PasswordForm::Scheme::kHtml; } -void NewPasswordFormManager::ProcessServerPredictions( +void PasswordFormManager::ProcessServerPredictions( const std::map<FormSignature, FormPredictions>& predictions) { if (parser_.predictions()) { // This method might be called multiple times. No need to process @@ -709,7 +700,7 @@ Fill(); } -void NewPasswordFormManager::Fill() { +void PasswordFormManager::Fill() { if (!driver_) return; @@ -762,7 +753,7 @@ preferred_match_, metrics_recorder_.get()); } -void NewPasswordFormManager::FillForm(const FormData& observed_form) { +void PasswordFormManager::FillForm(const FormData& observed_form) { uint32_t differences_bitmask = FindFormsDifferences(observed_form_, observed_form); metrics_recorder_->RecordFormChangeBitmask(differences_bitmask); @@ -774,7 +765,7 @@ Fill(); } -void NewPasswordFormManager::OnGeneratedPasswordAccepted( +void PasswordFormManager::OnGeneratedPasswordAccepted( FormData form_data, uint32_t generation_element_id, const base::string16& password) { @@ -802,7 +793,7 @@ driver_); } -NewPasswordFormManager::NewPasswordFormManager( +PasswordFormManager::PasswordFormManager( PasswordManagerClient* client, FormFetcher* form_fetcher, std::unique_ptr<FormSaver> form_saver, @@ -827,7 +818,7 @@ } } -void NewPasswordFormManager::RecordMetricOnCompareParsingResult( +void PasswordFormManager::RecordMetricOnCompareParsingResult( const PasswordForm& parsed_form) { bool same = parsed_form.username_element == old_parsing_result_.username_element && @@ -865,7 +856,7 @@ } } -void NewPasswordFormManager::RecordMetricOnReadonly( +void PasswordFormManager::RecordMetricOnReadonly( FormDataParser::ReadonlyPasswordFields readonly_status, bool parsing_successful, FormDataParser::Mode mode) { @@ -884,7 +875,7 @@ } } -void NewPasswordFormManager::ReportTimeBetweenStoreAndServerUMA() { +void PasswordFormManager::ReportTimeBetweenStoreAndServerUMA() { if (!received_stored_credentials_time_.is_null()) { UMA_HISTOGRAM_TIMES("PasswordManager.TimeBetweenStoreAndServer", TimeTicks::Now() - received_stored_credentials_time_); @@ -893,7 +884,7 @@ // TODO(https://crbug.com/831123): move this function to the proper place // corresponding to its place in the header. -void NewPasswordFormManager::CreatePendingCredentials() { +void PasswordFormManager::CreatePendingCredentials() { DCHECK(is_submitted_); // TODO(https://crbug.com/831123): Process correctly the case when saved // credentials are not received from the store yet. @@ -946,8 +937,7 @@ // Generate username correction votes. bool username_correction_found = votes_uploader_.FindCorrectedUsernameElement( - best_matches_, not_best_matches_, - parsed_submitted_form_->username_value, + GetAllMatches(), parsed_submitted_form_->username_value, parsed_submitted_form_->password_value); UMA_HISTOGRAM_BOOLEAN("PasswordManager.UsernameCorrectionFound", username_correction_found); @@ -988,7 +978,7 @@ pending_credentials_.type = PasswordForm::Type::kGenerated; } -void NewPasswordFormManager::CreatePendingCredentialsForNewCredentials( +void PasswordFormManager::CreatePendingCredentialsForNewCredentials( const PasswordForm& submitted_password_form, const base::string16& password_element) { if (IsHttpAuth() || IsCredentialAPISave()) { @@ -1020,7 +1010,7 @@ pending_credentials_.new_password_element.clear(); } -void NewPasswordFormManager::ProcessUpdate() { +void PasswordFormManager::ProcessUpdate() { DCHECK_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState()); DCHECK(preferred_match_ || pending_credentials_.IsFederatedCredential()); // If we're doing an Update, we either autofilled correctly and need to @@ -1057,14 +1047,14 @@ } } -void NewPasswordFormManager::FillHttpAuth() { +void PasswordFormManager::FillHttpAuth() { DCHECK(IsHttpAuth()); if (!preferred_match_) return; client_->AutofillHttpAuth(*preferred_match_, this); } -std::unique_ptr<PasswordForm> NewPasswordFormManager::ParseFormAndMakeLogging( +std::unique_ptr<PasswordForm> PasswordFormManager::ParseFormAndMakeLogging( const FormData& form, FormDataParser::Mode mode) { std::unique_ptr<PasswordForm> password_form = parser_.Parse(form, mode); @@ -1079,7 +1069,7 @@ return password_form; } -void NewPasswordFormManager::PresaveGeneratedPasswordInternal( +void PasswordFormManager::PresaveGeneratedPasswordInternal( const FormData& form, const base::string16& generated_password) { std::unique_ptr<PasswordForm> parsed_form = @@ -1121,7 +1111,7 @@ GetAllMatches()); } -void NewPasswordFormManager::CalculateFillingAssistanceMetric( +void PasswordFormManager::CalculateFillingAssistanceMetric( const FormData& submitted_form) { // TODO(https://crbug.com/918846): implement collecting all necessary data on // iOS. @@ -1144,7 +1134,7 @@ #endif } -std::vector<const PasswordForm*> NewPasswordFormManager::GetAllMatches() const { +std::vector<const PasswordForm*> PasswordFormManager::GetAllMatches() const { std::vector<const autofill::PasswordForm*> result = form_fetcher_->GetNonFederatedMatches(); PasswordForm::Scheme observed_form_scheme = GetScheme(); @@ -1154,7 +1144,7 @@ return result; } -void NewPasswordFormManager::SavePendingToStore(bool update) { +void PasswordFormManager::SavePendingToStore(bool update) { const PasswordForm* saved_form = password_manager_util::GetMatchForUpdating( *parsed_submitted_form_, best_matches_); if ((update || password_overridden_) &&
diff --git a/components/password_manager/core/browser/new_password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h similarity index 90% rename from components/password_manager/core/browser/new_password_form_manager.h rename to components/password_manager/core/browser/password_form_manager.h index b7ff3bf..f7d9f292 100644 --- a/components/password_manager/core/browser/new_password_form_manager.h +++ b/components/password_manager/core/browser/password_form_manager.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_NEW_PASSWORD_FORM_MANAGER_H_ -#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_NEW_PASSWORD_FORM_MANAGER_H_ +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_MANAGER_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_MANAGER_H_ #include <map> #include <memory> @@ -38,8 +38,8 @@ // stored information about it. It is aimed to replace PasswordFormManager and // to be renamed in new Password Manager design. Details // go/new-cpm-design-refactoring. -class NewPasswordFormManager : public PasswordFormManagerInterface, - public FormFetcher::Consumer { +class PasswordFormManager : public PasswordFormManagerInterface, + public FormFetcher::Consumer { public: // TODO(crbug.com/621355): So far, |form_fetcher| can be null. In that case // |this| creates an instance of it itself (meant for production code). Once @@ -47,7 +47,7 @@ // required that |form_fetcher| is not null. |form_saver| is used to // save/update the form. |metrics_recorder| records metrics for |*this|. If // null a new instance will be created. - NewPasswordFormManager( + PasswordFormManager( PasswordManagerClient* client, const base::WeakPtr<PasswordManagerDriver>& driver, const autofill::FormData& observed_form, @@ -56,12 +56,12 @@ scoped_refptr<PasswordFormMetricsRecorder> metrics_recorder); // Constructor for http authentication (aka basic authentication). - NewPasswordFormManager(PasswordManagerClient* client, - PasswordStore::FormDigest observed_http_auth_digest, - FormFetcher* form_fetcher, - std::unique_ptr<FormSaver> form_saver); + PasswordFormManager(PasswordManagerClient* client, + PasswordStore::FormDigest observed_http_auth_digest, + FormFetcher* form_fetcher, + std::unique_ptr<FormSaver> form_saver); - ~NewPasswordFormManager() override; + ~PasswordFormManager() override; // The upper limit on how many times Chrome will try to autofill the same // form. @@ -196,7 +196,7 @@ // the result is not identical to the original. // TODO(crbug.com/739366): Replace with translating one appropriate class into // another one. - std::unique_ptr<NewPasswordFormManager> Clone(); + std::unique_ptr<PasswordFormManager> Clone(); #if defined(UNIT_TEST) static void set_wait_for_server_predictions_for_filling(bool value) { @@ -214,10 +214,10 @@ protected: // Constructor for Credentials API. - NewPasswordFormManager(PasswordManagerClient* client, - std::unique_ptr<autofill::PasswordForm> saved_form, - std::unique_ptr<FormFetcher> form_fetcher, - std::unique_ptr<FormSaver> form_saver); + PasswordFormManager(PasswordManagerClient* client, + std::unique_ptr<autofill::PasswordForm> saved_form, + std::unique_ptr<FormFetcher> form_fetcher, + std::unique_ptr<FormSaver> form_saver); // FormFetcher::Consumer: void OnFetchCompleted() override; @@ -228,7 +228,7 @@ private: // Delegating constructor. - NewPasswordFormManager( + PasswordFormManager( PasswordManagerClient* client, FormFetcher* form_fetcher, std::unique_ptr<FormSaver> form_saver, @@ -287,8 +287,7 @@ void CalculateFillingAssistanceMetric( const autofill::FormData& submitted_form); - // Returns all the credentials for the origin (essentially, |best_matches_| - // and |not_best_matches_|). + // Returns all the credentials for the origin. std::vector<const autofill::PasswordForm*> GetAllMatches() const; // Save/update |pending_credentials_| to the password store. @@ -312,13 +311,6 @@ // by |form_fetcher_|. std::map<base::string16, const autofill::PasswordForm*> best_matches_; - // Set of forms from PasswordStore that correspond to the current site and - // that are not in |best_matches_|. They are owned by |form_fetcher_|. - // It is leftover from the old PasswordFormManager. - // TODO(https://crbug.com/831123): update all places where it is used with - // saved credentials from |form_fetcher_|. - std::vector<const autofill::PasswordForm*> not_best_matches_; - // Set of blacklisted forms from the PasswordStore that best match the current // form. They are owned by |form_fetcher_|. std::vector<const autofill::PasswordForm*> blacklisted_matches_; @@ -401,11 +393,11 @@ // Used to transform FormData into PasswordForms. FormDataParser parser_; - base::WeakPtrFactory<NewPasswordFormManager> weak_ptr_factory_{this}; + base::WeakPtrFactory<PasswordFormManager> weak_ptr_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(NewPasswordFormManager); + DISALLOW_COPY_AND_ASSIGN(PasswordFormManager); }; } // namespace password_manager -#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_NEW_PASSWORD_FORM_MANAGER_H_ +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_MANAGER_H_
diff --git a/components/password_manager/core/browser/new_password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc similarity index 94% rename from components/password_manager/core/browser/new_password_form_manager_unittest.cc rename to components/password_manager/core/browser/password_form_manager_unittest.cc index cba69e7..bd63226 100644 --- a/components/password_manager/core/browser/new_password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_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/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include <string> #include <utility> @@ -222,7 +222,7 @@ } // Convenience downcasting method. - static MockFormSaver& Get(NewPasswordFormManager* form_manager) { + static MockFormSaver& Get(PasswordFormManager* form_manager) { return *static_cast<MockFormSaver*>(form_manager->form_saver()); } @@ -235,9 +235,9 @@ // generation happened. // TODO(https://crbug.com/831123): Test create pending credentials with // Credential API. -class NewPasswordFormManagerTest : public testing::Test { +class PasswordFormManagerTest : public testing::Test { public: - NewPasswordFormManagerTest() : task_runner_(new TestMockTimeTaskRunner) { + PasswordFormManagerTest() : task_runner_(new TestMockTimeTaskRunner) { GURL origin = GURL("https://accounts.google.com/a/ServiceLoginAuth"); GURL action = GURL("https://accounts.google.com/a/ServiceLogin"); GURL psl_origin = GURL("https://myaccounts.google.com/a/ServiceLoginAuth"); @@ -363,21 +363,21 @@ // Define |fetcher_| before |form_manager_|, because the former needs to // outlive the latter. std::unique_ptr<FakeFormFetcher> fetcher_; - std::unique_ptr<NewPasswordFormManager> form_manager_; + std::unique_ptr<PasswordFormManager> form_manager_; - // Creates NewPasswordFormManager and sets it to |form_manager_|. Along the + // Creates PasswordFormManager and sets it to |form_manager_|. Along the // way a new |fetcher_| is created. void CreateFormManager(const FormData& observed_form) { - form_manager_.reset(new NewPasswordFormManager( + form_manager_.reset(new PasswordFormManager( &client_, driver_.AsWeakPtr(), observed_form, fetcher_.get(), std::make_unique<NiceMock<MockFormSaver>>(), nullptr)); } - // Creates NewPasswordFormManager and sets it to |form_manager_| for + // Creates PasswordFormManager and sets it to |form_manager_| for // |base_auth_observed_form|. Along the way a new |fetcher_| is created. void CreateFormManagerForNonWebForm( const PasswordForm& base_auth_observed_form) { - form_manager_.reset(new NewPasswordFormManager( + form_manager_.reset(new PasswordFormManager( &client_, PasswordStore::FormDigest(base_auth_observed_form), fetcher_.get(), std::make_unique<NiceMock<MockFormSaver>>())); } @@ -389,7 +389,7 @@ } }; -TEST_F(NewPasswordFormManagerTest, DoesManage) { +TEST_F(PasswordFormManagerTest, DoesManage) { EXPECT_TRUE(form_manager_->DoesManage(observed_form_, &driver_)); // Forms on other drivers are not considered managed. EXPECT_FALSE(form_manager_->DoesManage(observed_form_, nullptr)); @@ -416,7 +416,7 @@ #endif } -TEST_F(NewPasswordFormManagerTest, DoesManageNoFormTag) { +TEST_F(PasswordFormManagerTest, DoesManageNoFormTag) { observed_form_.is_form_tag = false; CreateFormManager(observed_form_); @@ -428,7 +428,7 @@ EXPECT_FALSE(form_manager_->DoesManage(another_form, nullptr)); } -TEST_F(NewPasswordFormManagerTest, Autofill) { +TEST_F(PasswordFormManagerTest, Autofill) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); CreateFormManager(observed_form_); @@ -448,7 +448,7 @@ EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); } -TEST_F(NewPasswordFormManagerTest, AutofillNotMoreThan5Times) { +TEST_F(PasswordFormManagerTest, AutofillNotMoreThan5Times) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); EXPECT_CALL(driver_, FillPasswordForm(_)); @@ -457,7 +457,7 @@ task_runner_->FastForwardUntilNoTasksRemain(); Mock::VerifyAndClearExpectations(&driver_); - for (size_t i = 0; i < NewPasswordFormManager::kMaxTimesAutofill - 1; ++i) { + for (size_t i = 0; i < PasswordFormManager::kMaxTimesAutofill - 1; ++i) { EXPECT_CALL(driver_, FillPasswordForm(_)); form_manager_->Fill(); Mock::VerifyAndClearExpectations(&driver_); @@ -467,13 +467,13 @@ form_manager_->Fill(); } -// NewPasswordFormManager should always send fill data to renderer, even for +// PasswordFormManager should always send fill data to renderer, even for // sign-up forms (no "current-password" field, i.e., no password field to fill // into). However, for sign-up forms, no particular password field should be // identified for filling. That way, Chrome won't disturb the user by filling // the sign-up form, but will be able to offer a manual fallback for filling if // the form was misclassified. -TEST_F(NewPasswordFormManagerTest, AutofillSignUpForm) { +TEST_F(PasswordFormManagerTest, AutofillSignUpForm) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); // Make |observed_form_| to be sign-up form. observed_form_.fields.back().autocomplete_attribute = "new-password"; @@ -505,7 +505,7 @@ // Check that generation signal is sent the the renderer when new password // fields are marked with autocomplete attribute. -TEST_F(NewPasswordFormManagerTest, GenerationOnNewAndConfirmPasswordFields) { +TEST_F(PasswordFormManagerTest, GenerationOnNewAndConfirmPasswordFields) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); // Make |observed_form_| to be sign-up form. observed_form_.fields.back().autocomplete_attribute = "new-password"; @@ -538,7 +538,7 @@ #endif } -TEST_F(NewPasswordFormManagerTest, AutofillWithBlacklistedMatch) { +TEST_F(PasswordFormManagerTest, AutofillWithBlacklistedMatch) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); PasswordFormFillData fill_data; EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data)); @@ -553,7 +553,7 @@ EXPECT_EQ(saved_match_.password_value, fill_data.password_field.value); } -TEST_F(NewPasswordFormManagerTest, SetSubmitted) { +TEST_F(PasswordFormManagerTest, SetSubmitted) { EXPECT_FALSE(form_manager_->is_submitted()); EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_)); EXPECT_TRUE(form_manager_->is_submitted()); @@ -568,7 +568,7 @@ #endif } -TEST_F(NewPasswordFormManagerTest, SetSubmittedMultipleTimes) { +TEST_F(PasswordFormManagerTest, SetSubmittedMultipleTimes) { EXPECT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_)); EXPECT_TRUE(form_manager_->is_submitted()); @@ -582,9 +582,9 @@ EXPECT_TRUE(form_manager_->GetSubmittedForm()); } -// Tests that when NewPasswordFormManager receives saved matches it waits for +// Tests that when PasswordFormManager receives saved matches it waits for // server predictions and fills on receving them. -TEST_F(NewPasswordFormManagerTest, ServerPredictionsWithinDelay) { +TEST_F(PasswordFormManagerTest, ServerPredictionsWithinDelay) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); // Expects no filling on save matches receiving. @@ -605,9 +605,9 @@ form_manager_->ProcessServerPredictions(predictions); } -// Tests that NewPasswordFormManager fills after some delay even without +// Tests that PasswordFormManager fills after some delay even without // server predictions. -TEST_F(NewPasswordFormManagerTest, ServerPredictionsAfterDelay) { +TEST_F(PasswordFormManagerTest, ServerPredictionsAfterDelay) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); EXPECT_CALL(driver_, FillPasswordForm(_)).Times(1); @@ -630,7 +630,7 @@ // Tests that filling happens immediately if server predictions are received // before saved matches. -TEST_F(NewPasswordFormManagerTest, ServerPredictionsBeforeFetcher) { +TEST_F(PasswordFormManagerTest, ServerPredictionsBeforeFetcher) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); // Expect no filling after receiving saved matches from |fetcher_|, since // |form_manager| is waiting for server-side predictions. @@ -648,7 +648,7 @@ } // Tests creating pending credentials when the password store is empty. -TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsEmptyStore) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsEmptyStore) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); @@ -666,7 +666,7 @@ // Tests creating pending credentials when new credentials are submitted and the // store has another credentials saved. -TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsNewCredentials) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsNewCredentials) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -679,7 +679,7 @@ // Tests that when submitted credentials are equal to already saved one then // pending credentials equal to saved match. -TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsAlreadySaved) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsAlreadySaved) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -704,7 +704,7 @@ // Tests that when submitted credentials are equal to already saved PSL // credentials. -TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsPSLMatchSaved) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsPSLMatchSaved) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); PasswordForm expected = saved_match_; @@ -727,7 +727,7 @@ // Tests creating pending credentials when new credentials are different only in // password with already saved one. -TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsPasswordOverriden) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsPasswordOverriden) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -745,7 +745,7 @@ // Tests that when submitted credentials are equal to already saved one then // pending credentials equal to saved match. -TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsUpdate) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsUpdate) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -764,8 +764,7 @@ // Tests creating pending credentials when a change password form is submitted // and there are multipe saved forms. -TEST_F(NewPasswordFormManagerTest, - CreatePendingCredentialsUpdateMultipleSaved) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsUpdateMultipleSaved) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); PasswordForm another_saved_match = saved_match_; another_saved_match.username_value += ASCIIToUTF16("1"); @@ -783,7 +782,7 @@ } // Tests creating pending credentials when the password field has an empty name. -TEST_F(NewPasswordFormManagerTest, CreatePendingCredentialsEmptyName) { +TEST_F(PasswordFormManagerTest, CreatePendingCredentialsEmptyName) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); @@ -804,7 +803,7 @@ // Tests that there is no crash even when the observed form is a not password // form and the submitted form is password form. -TEST_F(NewPasswordFormManagerTest, NoCrashOnNonPasswordForm) { +TEST_F(PasswordFormManagerTest, NoCrashOnNonPasswordForm) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); FormData form_without_password_fields = observed_form_; // Remove the password field. @@ -820,7 +819,7 @@ form_manager_->ProvisionallySave(submitted_form, &driver_); } -TEST_F(NewPasswordFormManagerTest, IsEqualToSubmittedForm) { +TEST_F(PasswordFormManagerTest, IsEqualToSubmittedForm) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); @@ -846,7 +845,7 @@ // Tests that when credentials with a new username (i.e. not saved yet) is // successfully submitted, then they are saved correctly. -TEST_F(NewPasswordFormManagerTest, SaveNewCredentials) { +TEST_F(PasswordFormManagerTest, SaveNewCredentials) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -895,7 +894,7 @@ // Check that if there is saved PSL matched credentials with the same // username/password as in submitted form, then the saved form is the same // already saved only with origin and signon_realm from the submitted form. -TEST_F(NewPasswordFormManagerTest, SavePSLToAlreadySaved) { +TEST_F(PasswordFormManagerTest, SavePSLToAlreadySaved) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&psl_saved_match_}); @@ -932,7 +931,7 @@ // Tests that when credentials with already saved username but with a new // password are submitted, then the saved password is updated. -TEST_F(NewPasswordFormManagerTest, OverridePassword) { +TEST_F(PasswordFormManagerTest, OverridePassword) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -961,7 +960,7 @@ // Tests that when the user changes password on a change password form then the // saved password is updated. -TEST_F(NewPasswordFormManagerTest, UpdatePasswordOnChangePasswordForm) { +TEST_F(PasswordFormManagerTest, UpdatePasswordOnChangePasswordForm) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); CreateFormManager(observed_form_only_password_fields_); PasswordForm not_best_saved_match = saved_match_; @@ -998,7 +997,7 @@ EXPECT_EQ(new_password, updated_form.password_value); } -TEST_F(NewPasswordFormManagerTest, VotesUploadingOnPasswordUpdate) { +TEST_F(PasswordFormManagerTest, VotesUploadingOnPasswordUpdate) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); for (auto expected_vote : @@ -1039,7 +1038,7 @@ } } -TEST_F(NewPasswordFormManagerTest, UpdateUsernameEmptyStore) { +TEST_F(PasswordFormManagerTest, UpdateUsernameEmptyStore) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); @@ -1057,7 +1056,7 @@ EXPECT_TRUE(form_manager_->IsNewLogin()); } -TEST_F(NewPasswordFormManagerTest, UpdateUsernameToAnotherFieldValue) { +TEST_F(PasswordFormManagerTest, UpdateUsernameToAnotherFieldValue) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); @@ -1091,7 +1090,7 @@ form_manager_->Save(); } -TEST_F(NewPasswordFormManagerTest, UpdateUsernameToAlreadyExisting) { +TEST_F(PasswordFormManagerTest, UpdateUsernameToAlreadyExisting) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -1109,7 +1108,7 @@ EXPECT_TRUE(form_manager_->IsPasswordUpdate()); } -TEST_F(NewPasswordFormManagerTest, UpdatePasswordValueEmptyStore) { +TEST_F(PasswordFormManagerTest, UpdatePasswordValueEmptyStore) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); @@ -1134,7 +1133,7 @@ form_manager_->Save(); } -TEST_F(NewPasswordFormManagerTest, UpdatePasswordValueToAlreadyExisting) { +TEST_F(PasswordFormManagerTest, UpdatePasswordValueToAlreadyExisting) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -1152,7 +1151,7 @@ EXPECT_FALSE(form_manager_->IsPasswordUpdate()); } -TEST_F(NewPasswordFormManagerTest, UpdatePasswordValueMultiplePasswordFields) { +TEST_F(PasswordFormManagerTest, UpdatePasswordValueMultiplePasswordFields) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); FormData form = observed_form_only_password_fields_; @@ -1196,7 +1195,7 @@ CheckPendingCredentials(expected, saved_form); } -TEST_F(NewPasswordFormManagerTest, PermanentlyBlacklist) { +TEST_F(PasswordFormManagerTest, PermanentlyBlacklist) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); @@ -1214,15 +1213,14 @@ ElementsAre(Pointee(actual_blacklisted_form))); } -TEST_F(NewPasswordFormManagerTest, Clone) { +TEST_F(PasswordFormManagerTest, Clone) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); // Provisionally save in order to create pending credentials. ASSERT_TRUE(form_manager_->ProvisionallySave(submitted_form_, &driver_)); - std::unique_ptr<NewPasswordFormManager> cloned_manager = - form_manager_->Clone(); + std::unique_ptr<PasswordFormManager> cloned_manager = form_manager_->Clone(); EXPECT_TRUE(cloned_manager->DoesManage(observed_form_, nullptr)); EXPECT_TRUE(cloned_manager->GetFormFetcher()); @@ -1258,7 +1256,7 @@ } // Test that an attempt to log to ReadonlyWhenFilling UKM is made when filling. -TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenFilling) { +TEST_F(PasswordFormManagerTest, RecordReadonlyWhenFilling) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; EXPECT_CALL(driver_, FillPasswordForm(_)); @@ -1280,7 +1278,7 @@ // Test that an attempt to log to ReadonlyWhenFilling UKM is made when filling, // even when the parsing itself is unsuccessful. -TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenFilling_ParsingFailed) { +TEST_F(PasswordFormManagerTest, RecordReadonlyWhenFilling_ParsingFailed) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); FormData malformed_form = observed_form_; @@ -1308,7 +1306,7 @@ // Test that an attempt to log to ReadonlyWhenSaving UKM is made when creating // pending credentials. -TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenSaving) { +TEST_F(PasswordFormManagerTest, RecordReadonlyWhenSaving) { // The scoped context is needed for the UKM recorder. TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; @@ -1330,7 +1328,7 @@ // Test that an attempt to log to ReadonlyWhenSaving UKM is made when creating // pending credentials, even when their parsing itself is unsuccessful. -TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenSaving_ParsingFailed) { +TEST_F(PasswordFormManagerTest, RecordReadonlyWhenSaving_ParsingFailed) { // The scoped context is needed for the UKM recorder. TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; @@ -1352,7 +1350,7 @@ entries[0], ukm::builders::PasswordForm::kReadonlyWhenSavingName)); } -TEST_F(NewPasswordFormManagerTest, PresaveGeneratedPasswordEmptyStore) { +TEST_F(PasswordFormManagerTest, PresaveGeneratedPasswordEmptyStore) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; fetcher_->NotifyFetchCompleted(); @@ -1410,7 +1408,7 @@ CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics); } -TEST_F(NewPasswordFormManagerTest, PresaveGenerated_ModifiedUsername) { +TEST_F(PasswordFormManagerTest, PresaveGenerated_ModifiedUsername) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; fetcher_->NotifyFetchCompleted(); @@ -1454,7 +1452,7 @@ CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics); } -TEST_F(NewPasswordFormManagerTest, GeneratedPasswordWhichIsNotInFormData) { +TEST_F(PasswordFormManagerTest, GeneratedPasswordWhichIsNotInFormData) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get()); @@ -1491,7 +1489,7 @@ EXPECT_EQ(generated_password, saved_form.password_value); } -TEST_F(NewPasswordFormManagerTest, PresaveGenerationWhenParsingFails) { +TEST_F(PasswordFormManagerTest, PresaveGenerationWhenParsingFails) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get()); @@ -1510,7 +1508,7 @@ EXPECT_EQ(generated_password, saved_form.password_value); } -TEST_F(NewPasswordFormManagerTest, PasswordNoLongerGenerated) { +TEST_F(PasswordFormManagerTest, PasswordNoLongerGenerated) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; fetcher_->NotifyFetchCompleted(); @@ -1544,7 +1542,7 @@ CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics); } -TEST_F(NewPasswordFormManagerTest, PresaveGeneratedPasswordExistingCredential) { +TEST_F(PasswordFormManagerTest, PresaveGeneratedPasswordExistingCredential) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -1572,7 +1570,7 @@ saved_form.password_value); } -TEST_F(NewPasswordFormManagerTest, UserEventsForGeneration) { +TEST_F(PasswordFormManagerTest, UserEventsForGeneration) { using GeneratedPasswordStatus = PasswordFormMetricsRecorder::GeneratedPasswordStatus; @@ -1618,7 +1616,7 @@ } } -TEST_F(NewPasswordFormManagerTest, FillForm) { +TEST_F(PasswordFormManagerTest, FillForm) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); for (bool observed_form_changed : {false, true}) { @@ -1667,7 +1665,7 @@ } } -TEST_F(NewPasswordFormManagerTest, FillFormWaitForServerPredictions) { +TEST_F(PasswordFormManagerTest, FillFormWaitForServerPredictions) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -1700,7 +1698,7 @@ expected_differences_mask, 1); } -TEST_F(NewPasswordFormManagerTest, Update) { +TEST_F(PasswordFormManagerTest, Update) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); PasswordForm not_best_saved_match = saved_match_; @@ -1743,7 +1741,7 @@ #else #define MAYBE_FillingAssistanceMetric FillingAssistanceMetric #endif -TEST_F(NewPasswordFormManagerTest, MAYBE_FillingAssistanceMetric) { +TEST_F(PasswordFormManagerTest, MAYBE_FillingAssistanceMetric) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); SetNonFederatedAndNotifyFetchCompleted({&saved_match_}); @@ -1768,7 +1766,7 @@ PasswordFormMetricsRecorder::FillingAssistance::kManual, 1); } -TEST_F(NewPasswordFormManagerTest, PasswordRevealedVote) { +TEST_F(PasswordFormManagerTest, PasswordRevealedVote) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); for (bool password_revealed : {false, true}) { @@ -1789,7 +1787,7 @@ } } -TEST_F(NewPasswordFormManagerTest, GenerationUploadOnNoInteraction) { +TEST_F(PasswordFormManagerTest, GenerationUploadOnNoInteraction) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); for (bool generation_popup_shown : {false, true}) { @@ -1814,7 +1812,7 @@ } } -TEST_F(NewPasswordFormManagerTest, GenerationUploadOnNeverClicked) { +TEST_F(PasswordFormManagerTest, GenerationUploadOnNeverClicked) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); for (bool generation_popup_shown : {false, true}) { @@ -1839,7 +1837,7 @@ } } -TEST_F(NewPasswordFormManagerTest, SaveHttpAuthNoHttpAuthStored) { +TEST_F(PasswordFormManagerTest, SaveHttpAuthNoHttpAuthStored) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); for (bool html_credentials_saved : {false, true}) { @@ -1879,7 +1877,7 @@ } } -TEST_F(NewPasswordFormManagerTest, HTTPAuthAlreadySaved) { +TEST_F(PasswordFormManagerTest, HTTPAuthAlreadySaved) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); PasswordForm http_auth_form = parsed_observed_form_; http_auth_form.scheme = PasswordForm::Scheme::kBasic; @@ -1900,7 +1898,7 @@ EXPECT_FALSE(form_manager_->IsPasswordUpdate()); } -TEST_F(NewPasswordFormManagerTest, HTTPAuthPasswordOverridden) { +TEST_F(PasswordFormManagerTest, HTTPAuthPasswordOverridden) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); PasswordForm http_auth_form = parsed_observed_form_; http_auth_form.scheme = PasswordForm::Scheme::kBasic; @@ -1939,7 +1937,7 @@ EXPECT_EQ(new_password, updated_form.password_value); } -TEST_F(NewPasswordFormManagerTest, BlacklistHttpAuthCredentials) { +TEST_F(PasswordFormManagerTest, BlacklistHttpAuthCredentials) { PasswordForm http_auth_form = parsed_observed_form_; http_auth_form.signon_realm += "my-auth-realm"; http_auth_form.scheme = PasswordForm::Scheme::kBasic; @@ -1960,7 +1958,7 @@ } #if defined(OS_IOS) -TEST_F(NewPasswordFormManagerTest, iOSPresavedGeneratedPassword) { +TEST_F(PasswordFormManagerTest, iOSPresavedGeneratedPassword) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get()); @@ -1998,7 +1996,7 @@ EXPECT_EQ(changed_password, saved_form.password_value); } -TEST_F(NewPasswordFormManagerTest, UpdateGeneratedPasswordBeforePresaving) { +TEST_F(PasswordFormManagerTest, UpdateGeneratedPasswordBeforePresaving) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); fetcher_->NotifyFetchCompleted(); MockFormSaver& form_saver = MockFormSaver::Get(form_manager_.get());
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 9840da6..ef4adb5 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -25,8 +25,8 @@ #include "components/autofill/core/common/save_password_progress_logger.h" #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" #include "components/password_manager/core/browser/form_saver_impl.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" #include "components/password_manager/core/browser/password_autofill_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_generation_frame_helper.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_driver.h" @@ -150,9 +150,9 @@ } // Finds the matched form manager for |form| in |form_managers|. -NewPasswordFormManager* FindMatchedManager( +PasswordFormManager* FindMatchedManager( const FormData& form, - const std::vector<std::unique_ptr<NewPasswordFormManager>>& form_managers, + const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers, const PasswordManagerDriver* driver) { for (const auto& form_manager : form_managers) { if (form_manager->DoesManage(form, driver)) @@ -162,9 +162,9 @@ } // Finds the matched form manager with id |form_renderer_id| in |form_managers|. -NewPasswordFormManager* FindMatchedManagerByRendererId( +PasswordFormManager* FindMatchedManagerByRendererId( uint32_t form_renderer_id, - const std::vector<std::unique_ptr<NewPasswordFormManager>>& form_managers, + const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers, const PasswordManagerDriver* driver) { for (const auto& form_manager : form_managers) { if (form_manager->DoesManageAccordingToRendererId(form_renderer_id, driver)) @@ -217,8 +217,9 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); registry->RegisterDoublePref(prefs::kLastTimeObsoleteHttpCredentialsRemoved, 0.0); - registry->RegisterIntegerPref(prefs::kPasswordManagerOnboardingState, - static_cast<int>(OnboardingState::kDoNotShow)); + registry->RegisterIntegerPref( + prefs::kPasswordManagerOnboardingState, + static_cast<int>(metrics_util::OnboardingState::kDoNotShow)); #if defined(OS_MACOSX) registry->RegisterIntegerPref(prefs::kKeychainMigrationStatus, @@ -260,7 +261,7 @@ const FormData& form_data, uint32_t generation_element_id, const base::string16& password) { - NewPasswordFormManager* manager = GetMatchedManager(driver, form_data); + PasswordFormManager* manager = GetMatchedManager(driver, form_data); if (manager) { manager->OnGeneratedPasswordAccepted(form_data, generation_element_id, password); @@ -327,7 +328,7 @@ } } - for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) { + for (std::unique_ptr<PasswordFormManager>& manager : form_managers_) { if (form_may_be_submitted && manager->is_submitted()) { owned_submitted_form_manager_ = std::move(manager); break; @@ -436,9 +437,9 @@ return; std::unique_ptr<PasswordFormManagerInterface> manager; - NewPasswordFormManager* matched_manager = - ProvisionallySaveForm(password_form.form_data, driver, true); - manager = matched_manager ? matched_manager->Clone() : nullptr; + PasswordFormManager* matched_manager = + ProvisionallySaveForm(password_form.form_data, driver, true); + manager = matched_manager ? matched_manager->Clone() : nullptr; auto availability = manager ? PasswordManagerMetricsRecorder::FormManagerAvailable::kSuccess @@ -528,7 +529,7 @@ if (!client_->IsFillingEnabled(form.origin)) continue; - NewPasswordFormManager* manager = + PasswordFormManager* manager = FindMatchedManager(form.form_data, form_managers_, driver); if (manager) { @@ -550,10 +551,10 @@ } } -NewPasswordFormManager* PasswordManager::CreateFormManager( +PasswordFormManager* PasswordManager::CreateFormManager( PasswordManagerDriver* driver, const autofill::FormData& form) { - form_managers_.push_back(std::make_unique<NewPasswordFormManager>( + form_managers_.push_back(std::make_unique<PasswordFormManager>( client_, driver ? driver->AsWeakPtr() : base::WeakPtr<PasswordManagerDriver>(), form, nullptr, @@ -562,7 +563,7 @@ return form_managers_.back().get(); } -NewPasswordFormManager* PasswordManager::ProvisionallySaveForm( +PasswordFormManager* PasswordManager::ProvisionallySaveForm( const FormData& submitted_form, PasswordManagerDriver* driver, bool is_manual_fallback) { @@ -583,7 +584,7 @@ return nullptr; // No need to report PasswordManagerMetricsRecorder::EMPTY_PASSWORD, because - // PasswordToSave in NewPasswordFormManager DCHECKs that the password is never + // PasswordToSave in PasswordFormManager DCHECKs that the password is never // empty. const GURL& origin = submitted_form.url; @@ -594,7 +595,7 @@ return nullptr; } - NewPasswordFormManager* matched_manager = + PasswordFormManager* matched_manager = GetMatchedManager(driver, submitted_form); auto availability = @@ -646,7 +647,7 @@ void PasswordManager::LogFirstFillingResult(PasswordManagerDriver* driver, uint32_t form_renderer_id, int32_t result) { - NewPasswordFormManager* matching_manager = + PasswordFormManager* matching_manager = FindMatchedManagerByRendererId(form_renderer_id, form_managers_, driver); if (!matching_manager) return; @@ -664,7 +665,7 @@ const FormData& form, const base::string16& generated_password, const base::string16& generation_element) { - NewPasswordFormManager* form_manager = + PasswordFormManager* form_manager = FindMatchedManager(form, form_managers_, driver); UMA_HISTOGRAM_BOOLEAN("PasswordManager.GeneratedFormHasNoFormManager", !form_manager); @@ -680,7 +681,7 @@ const base::string16& form_identifier, const base::string16& field_identifier, const base::string16& field_value) { - for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) { + for (std::unique_ptr<PasswordFormManager>& manager : form_managers_) { if (manager->UpdateGeneratedPasswordOnUserInput( form_identifier, field_identifier, field_value)) { break; @@ -690,7 +691,7 @@ void PasswordManager::OnPasswordNoLongerGenerated( PasswordManagerDriver* driver) { - for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) + for (std::unique_ptr<PasswordFormManager>& manager : form_managers_) manager->PasswordNoLongerGenerated(); } #endif @@ -849,7 +850,7 @@ MaybeSavePasswordHash(*submitted_manager); // TODO(https://crbug.com/831123): Implement checking whether to save with - // NewPasswordFormManager. + // PasswordFormManager. if (!client_->GetStoreResultFilter()->ShouldSave( *submitted_manager->GetSubmittedForm())) { RecordProvisionalSaveFailure( @@ -996,8 +997,7 @@ if (owned_submitted_form_manager_) return owned_submitted_form_manager_.get(); - for (const std::unique_ptr<NewPasswordFormManager>& manager : - form_managers_) { + for (const std::unique_ptr<PasswordFormManager>& manager : form_managers_) { if (manager->is_submitted()) return manager.get(); } @@ -1013,8 +1013,7 @@ for (auto iter = form_managers_.begin(); iter != form_managers_.end(); ++iter) { if ((*iter)->is_submitted()) { - std::unique_ptr<NewPasswordFormManager> submitted_manager = - std::move(*iter); + std::unique_ptr<PasswordFormManager> submitted_manager = std::move(*iter); form_managers_.erase(iter); return std::move(submitted_manager); } @@ -1035,22 +1034,22 @@ } scoped_refptr<PasswordFormMetricsRecorder> -PasswordManager::GetMetricRecorderFromNewPasswordFormManager( +PasswordManager::GetMetricRecorderFromPasswordFormManager( const FormData& form, const PasswordManagerDriver* driver) { - NewPasswordFormManager* matched_manager = GetMatchedManager(driver, form); + PasswordFormManager* matched_manager = GetMatchedManager(driver, form); return matched_manager ? matched_manager->metrics_recorder() : nullptr; } // TODO(https://crbug.com/831123): Implement creating missing -// NewPasswordFormManager when PasswordFormManager is gone. +// PasswordFormManager when PasswordFormManager is gone. PasswordFormManagerInterface* PasswordManager::GetMatchedManager( const PasswordManagerDriver* driver, const PasswordForm& form) { return GetMatchedManager(driver, form.form_data); } -NewPasswordFormManager* PasswordManager::GetMatchedManager( +PasswordFormManager* PasswordManager::GetMatchedManager( const PasswordManagerDriver* driver, const FormData& form) { for (auto& form_manager : form_managers_) {
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h index 2ad59103..d2dd8b5 100644 --- a/components/password_manager/core/browser/password_manager.h +++ b/components/password_manager/core/browser/password_manager.h
@@ -45,7 +45,7 @@ class PasswordFormManagerInterface; class PasswordFormMetricsRecorder; class PasswordManagerMetricsRecorder; -class NewPasswordFormManager; +class PasswordFormManager; // Per-tab password manager. Handles creation and management of UI elements, // receiving password form data from the renderer and managing the password @@ -157,7 +157,7 @@ PasswordManagerClient* client() { return client_; } #if defined(UNIT_TEST) - const std::vector<std::unique_ptr<NewPasswordFormManager>>& form_managers() + const std::vector<std::unique_ptr<PasswordFormManager>>& form_managers() const { return form_managers_; } @@ -259,16 +259,16 @@ void CreateFormManagers(PasswordManagerDriver* driver, const std::vector<autofill::PasswordForm>& forms); - // Create NewPasswordFormManager for |form|, adds the newly created one to + // Create PasswordFormManager for |form|, adds the newly created one to // |form_managers_| and returns it. - NewPasswordFormManager* CreateFormManager(PasswordManagerDriver* driver, - const autofill::FormData& form); + PasswordFormManager* CreateFormManager(PasswordManagerDriver* driver, + const autofill::FormData& form); - // Passes |form| to NewPasswordFormManager that manages it for using it after + // Passes |form| to PasswordFormManager that manages it for using it after // detecting submission success for saving. |driver| is needed to determine // the match. If the function is called multiple times, only the form from the // last call is provisionally saved. Multiple calls is possible because it is - // called on any user keystroke. If there is no NewPasswordFormManager that + // called on any user keystroke. If there is no PasswordFormManager that // manages |form|, the new one is created. If |is_manual_fallback| is true // and the matched form manager has not recieved yet response from the // password store, then nullptr is returned. Returns manager which manages @@ -277,9 +277,9 @@ // should be skipped on saving. // TODO(https://crbug.com/949519): move |is_gaia_with_skip_save_password_form| // from PasswordForm to FormData, and remove it from arguments. - NewPasswordFormManager* ProvisionallySaveForm(const autofill::FormData& form, - PasswordManagerDriver* driver, - bool is_manual_fallback); + PasswordFormManager* ProvisionallySaveForm(const autofill::FormData& form, + PasswordManagerDriver* driver, + bool is_manual_fallback); // Returns the form manager that corresponds to the submitted form. It might // be nullptr if there is no submitted form. @@ -301,9 +301,8 @@ BrowserSavePasswordProgressLogger* logger); scoped_refptr<PasswordFormMetricsRecorder> - GetMetricRecorderFromNewPasswordFormManager( - const autofill::FormData& form, - const PasswordManagerDriver* driver); + GetMetricRecorderFromPasswordFormManager(const autofill::FormData& form, + const PasswordManagerDriver* driver); // Returns the manager which manages |form|. |driver| is needed to determine // the match. Returns nullptr when no matched manager is found. @@ -313,14 +312,14 @@ // Returns the manager which manages |form|. |driver| is needed to determine // the match. Returns nullptr when no matched manager is found. - NewPasswordFormManager* GetMatchedManager(const PasswordManagerDriver* driver, - const autofill::FormData& form); + PasswordFormManager* GetMatchedManager(const PasswordManagerDriver* driver, + const autofill::FormData& form); // Log a frame (main frame, iframe) of a submitted password form. void ReportSubmittedFormFrameMetric(const PasswordManagerDriver* driver, const autofill::PasswordForm& form); - // NewPasswordFormManager transition schemes: + // PasswordFormManager transition schemes: // 1. HTML submission with navigation afterwads. // form "seen" // | @@ -337,14 +336,14 @@ // ____ Prompt. // --> (is_submitted = true) ---- Automatic save. - // Contains one NewPasswordFormManager per each form on the page. - // When a form is "seen" on a page, a NewPasswordFormManager is created + // Contains one PasswordFormManager per each form on the page. + // When a form is "seen" on a page, a PasswordFormManager is created // and stored in this collection until user navigates away from page. - std::vector<std::unique_ptr<NewPasswordFormManager>> form_managers_; + std::vector<std::unique_ptr<PasswordFormManager>> form_managers_; // Corresponds to the submitted form, after navigion away before submission // success detection is finished. - std::unique_ptr<NewPasswordFormManager> owned_submitted_form_manager_; + std::unique_ptr<PasswordFormManager> owned_submitted_form_manager_; // The embedder-level client. Must outlive this class. PasswordManagerClient* const client_;
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index 326cafe6..4b69530 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -76,6 +76,15 @@ reason); } +void LogOnboardingState(OnboardingState state) { + base::UmaHistogramEnumeration("PasswordManager.Onboarding.State", state); +} + +void LogOnboardingUIDismissalReason(OnboardingUIDismissalReason reason) { + base::UmaHistogramEnumeration("PasswordManager.Onboarding.UIDismissalReason", + reason); +} + void LogUIDisplayDisposition(UIDisplayDisposition disposition) { base::UmaHistogramEnumeration("PasswordBubble.DisplayDisposition", disposition, NUM_DISPLAY_DISPOSITIONS);
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index 3382876e6..b2a51db8 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -80,6 +80,43 @@ kMaxValue = kClickedOk, }; +// Metrics: "PasswordManager.Onboarding.State" +// Enum recording the state of showing the onboarding to the user. This +// will be recorded on startup. Needs to stay in sync with the +// PasswordManagerOnboardingState enum in enums.xml. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class OnboardingState { + // The onboarding wasn't shown to the user. + kDoNotShow = 0, + // The onboarding wasn't shown to the user, + // but it should be shown the next time they are prompted to save a password. + kShouldShow = 1, + // The onboarding was shown to the user. + kShown = 2, + kMaxValue = kShown, +}; + +// Metrics: "PasswordManager.Onboarding.UIDismissalReason" +// Enum recording the dismissal reason of the onboarding dialog which is shown +// when the user is offered to save their password for the first time. +// Needs to stay in sync with the PasswordManagerOnboardingUIDismissalReason +// enum in enums.xml. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class OnboardingUIDismissalReason { + // The accepting button was pressed, e.g. "Continue" or "Got it". + kAccepted = 0, + // The rejecting button was pressed, e.g. "Cancel". + kRejected = 1, + // The dialog was dismissed, e.g. by pressing the back button, or + // opening a new tab. + kDismissed = 2, + kMaxValue = kDismissed, +}; + enum FormDeserializationStatus { LOGIN_DATABASE_SUCCESS, LOGIN_DATABASE_FAILURE, @@ -405,6 +442,12 @@ void LogLeakDialogTypeAndDismissalReason(LeakDialogType type, LeakDialogDismissalReason reason); +// Log the current onboarding |state| of the user. +void LogOnboardingState(OnboardingState state); + +// Log the |reason| a user dismissed the onboarding UI. +void LogOnboardingUIDismissalReason(OnboardingUIDismissalReason reason); + // Log the appropriate display disposition. void LogUIDisplayDisposition(UIDisplayDisposition disposition);
diff --git a/components/password_manager/core/browser/password_manager_onboarding.cc b/components/password_manager/core/browser/password_manager_onboarding.cc index 490b012..17ca35020 100644 --- a/components/password_manager/core/browser/password_manager_onboarding.cc +++ b/components/password_manager/core/browser/password_manager_onboarding.cc
@@ -5,12 +5,15 @@ #include "components/password_manager/core/browser/password_manager_onboarding.h" #include "base/feature_list.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" namespace password_manager { +using OnboardingState = password_manager::metrics_util::OnboardingState; + OnboardingStateUpdate::OnboardingStateUpdate( scoped_refptr<password_manager::PasswordStore> store, PrefService* prefs)
diff --git a/components/password_manager/core/browser/password_manager_onboarding.h b/components/password_manager/core/browser/password_manager_onboarding.h index 58796b5..c81e512 100644 --- a/components/password_manager/core/browser/password_manager_onboarding.h +++ b/components/password_manager/core/browser/password_manager_onboarding.h
@@ -16,15 +16,6 @@ // saved credentials or more. constexpr int kOnboardingCredentialsThreshold = 3; -// Possible values for the |kPasswordManagerOnboardingState| pref. -// |kShouldShow| indicates that the onboarding should be shown -// the next time the user gets prompted to save their password. -enum class OnboardingState { - kDoNotShow, - kShouldShow, - kShown, -}; - // This utility class is responsible for updating the // |kPasswordManagerOnboardingState| pref, for later use in the triggering logic // for the onboarding.
diff --git a/components/password_manager/core/browser/password_manager_onboarding_unittest.cc b/components/password_manager/core/browser/password_manager_onboarding_unittest.cc index ff458a4..21831ebf 100644 --- a/components/password_manager/core/browser/password_manager_onboarding_unittest.cc +++ b/components/password_manager/core/browser/password_manager_onboarding_unittest.cc
@@ -18,6 +18,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/password_manager/core/browser/test_password_store.h" #include "components/password_manager/core/common/password_manager_features.h" @@ -32,6 +33,8 @@ namespace password_manager { +using OnboardingState = metrics_util::OnboardingState; + class PasswordManagerOnboardingTest : public testing::Test { public: PasswordManagerOnboardingTest() = default;
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 269cc44..d77233e 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -29,9 +29,9 @@ #include "components/password_manager/core/browser/leak_detection/leak_detection_check.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h" #include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" #include "components/password_manager/core/browser/password_autofill_manager.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_form_manager_for_ui.h" #include "components/password_manager/core/browser/password_manager_driver.h" #include "components/password_manager/core/browser/password_manager_onboarding.h" @@ -313,7 +313,7 @@ prefs_.reset(new TestingPrefServiceSimple()); prefs_->registry()->RegisterIntegerPref( prefs::kPasswordManagerOnboardingState, - static_cast<int>(OnboardingState::kDoNotShow)); + static_cast<int>(metrics_util::OnboardingState::kDoNotShow)); prefs_->registry()->RegisterBooleanPref( prefs::kPasswordLeakDetectionEnabled, true); ON_CALL(client_, GetPrefs()).WillByDefault(Return(prefs_.get())); @@ -322,7 +322,7 @@ // Disable waiting, since most tests have nothing to do with predictions. // All tests that test working with prediction should explicitly turn // predictions on. - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); } void TearDown() override { @@ -905,8 +905,9 @@ base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature( features::kPasswordManagerOnboardingAndroid); - prefs_->SetInteger(prefs::kPasswordManagerOnboardingState, - static_cast<int>(OnboardingState::kShouldShow)); + prefs_->SetInteger( + prefs::kPasswordManagerOnboardingState, + static_cast<int>(metrics_util::OnboardingState::kShouldShow)); PasswordForm form(MakeSimpleForm()); std::vector<PasswordForm> observed = {form}; @@ -933,8 +934,9 @@ base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature( features::kPasswordManagerOnboardingAndroid); - prefs_->SetInteger(prefs::kPasswordManagerOnboardingState, - static_cast<int>(OnboardingState::kShouldShow)); + prefs_->SetInteger( + prefs::kPasswordManagerOnboardingState, + static_cast<int>(metrics_util::OnboardingState::kShouldShow)); PasswordForm observed_form(MakeSimpleForm()); std::vector<PasswordForm> observed_forms = {observed_form}; @@ -1586,16 +1588,16 @@ // tests below. // If kNewPasswordFormParsing is enabled, then "similar" is governed by -// NewPasswordFormManager::DoesManage, which in turn delegates to the unique +// PasswordFormManager::DoesManage, which in turn delegates to the unique // renderer ID of the forms being the same. Note, however, that such ID is only // unique within one renderer process. If different frames on the page are // rendered by different processes, two unrelated forms can end up with the same // ID. The test checks that nevertheless each of them gets assigned its own -// NewPasswordFormManager and filled as expected. +// PasswordFormManager and filled as expected. TEST_F(PasswordManagerTest, FillPasswordOnManyFrames_SameId) { - // Setting task runner is required since NewPasswordFormManager uses + // Setting task runner is required since PasswordFormManager uses // PostDelayTask for making filling. - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true); + PasswordFormManager::set_wait_for_server_predictions_for_filling(true); TestMockTimeTaskRunner::ScopedContext scoped_context_(task_runner_.get()); // Two unrelated forms... @@ -2087,16 +2089,16 @@ } TEST_F(PasswordManagerTest, UpdateFormManagers) { - // Seeing a form should result in creating PasswordFormManager and - // NewPasswordFormManager and querying PasswordStore. Calling - // UpdateFormManagers should result in querying the store again. - EXPECT_CALL(*store_, GetLogins(_, _)) - .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); + // Seeing a form should result in creating PasswordFormManager and + // PasswordFormManager and querying PasswordStore. Calling + // UpdateFormManagers should result in querying the store again. + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); - manager()->OnPasswordFormsParsed(&driver_, {PasswordForm()}); + manager()->OnPasswordFormsParsed(&driver_, {PasswordForm()}); - EXPECT_CALL(*store_, GetLogins(_, _)); - manager()->UpdateFormManagers(); + EXPECT_CALL(*store_, GetLogins(_, _)); + manager()->UpdateFormManagers(); } TEST_F(PasswordManagerTest, AutofillingOfAffiliatedCredentials) { @@ -2701,7 +2703,7 @@ } TEST_F(PasswordManagerTest, ManualFallbackForSavingNewParser) { - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); std::vector<PasswordForm> observed; PasswordForm form(MakeSimpleForm()); @@ -2779,7 +2781,7 @@ // Check that when autofill predictions are received before a form is found then // server predictions are not ignored and used for filling. TEST_F(PasswordManagerTest, AutofillPredictionBeforeFormParsed) { - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true); + PasswordFormManager::set_wait_for_server_predictions_for_filling(true); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); @@ -2845,7 +2847,7 @@ } } -// Check that when a form is submitted and a NewPasswordFormManager not present, +// Check that when a form is submitted and a PasswordFormManager not present, // this ends up reported in ProvisionallySaveFailure UMA and UKM. TEST_F(PasswordManagerTest, ProvisionallySaveFailure) { EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) @@ -2913,7 +2915,7 @@ const MissingFormManagerTestCase kTestCases[] = { { .description = - "A form is submitted and a NewPasswordFormManager not present.", + "A form is submitted and a PasswordFormManager not present.", .parsed_forms = {}, .save_signal = MissingFormManagerTestCase::Signal::Automatic, // .parsed_forms is empty, so the processed form below was not @@ -2925,7 +2927,7 @@ }, { .description = "Manual saving is requested and a " - "NewPasswordFormManager is created.", + "PasswordFormManager is created.", .parsed_forms = {}, .save_signal = MissingFormManagerTestCase::Signal::Manual, // .parsed_forms is empty, so the processed form below was not @@ -2944,7 +2946,7 @@ }, { .description = - "A form is submitted and a NewPasswordFormManager present.", + "A form is submitted and a PasswordFormManager present.", .parsed_forms = {form}, .save_signal = MissingFormManagerTestCase::Signal::Automatic, .processed_forms = {form}, @@ -3027,8 +3029,8 @@ } // Tests that despite there a form was not seen on a page load, new -// |NewPasswordFormManager| is created in process of saving. -TEST_F(PasswordManagerTest, CreateNewPasswordFormManagerOnSaving) { +// |PasswordFormManager| is created in process of saving. +TEST_F(PasswordManagerTest, CreatePasswordFormManagerOnSaving) { EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); @@ -3086,43 +3088,43 @@ // Check that on non-password form, saving and filling fallbacks are available // but no automatic filling and saving are available. TEST_F(PasswordManagerTest, FillingAndSavingFallbacksOnNonPasswordForm) { - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); - EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) - .WillRepeatedly(Return(true)); + PasswordFormManager::set_wait_for_server_predictions_for_filling(false); + EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) + .WillRepeatedly(Return(true)); - PasswordForm saved_match(MakeSimpleForm()); - PasswordForm credit_card_form(MakeSimpleCreditCardForm()); - credit_card_form.only_for_fallback = true; + PasswordForm saved_match(MakeSimpleForm()); + PasswordForm credit_card_form(MakeSimpleCreditCardForm()); + credit_card_form.only_for_fallback = true; - EXPECT_CALL(*store_, GetLogins(_, _)) - .WillRepeatedly(WithArg<1>(InvokeConsumer(saved_match))); + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeConsumer(saved_match))); - PasswordFormFillData form_data; - EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&form_data)); + PasswordFormFillData form_data; + EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&form_data)); - manager()->OnPasswordFormsParsed(&driver_, {credit_card_form}); - // Check that manual filling fallback available. - EXPECT_EQ(saved_match.username_value, form_data.username_field.value); - EXPECT_EQ(saved_match.password_value, form_data.password_field.value); - // Check that no automatic filling available. - uint32_t renderer_id_not_set = FormFieldData::kNotSetFormControlRendererId; - EXPECT_EQ(renderer_id_not_set, form_data.username_field.unique_renderer_id); - EXPECT_EQ(renderer_id_not_set, form_data.password_field.unique_renderer_id); + manager()->OnPasswordFormsParsed(&driver_, {credit_card_form}); + // Check that manual filling fallback available. + EXPECT_EQ(saved_match.username_value, form_data.username_field.value); + EXPECT_EQ(saved_match.password_value, form_data.password_field.value); + // Check that no automatic filling available. + uint32_t renderer_id_not_set = FormFieldData::kNotSetFormControlRendererId; + EXPECT_EQ(renderer_id_not_set, form_data.username_field.unique_renderer_id); + EXPECT_EQ(renderer_id_not_set, form_data.password_field.unique_renderer_id); - // Check that saving fallback is available. - std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; - EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) - .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, credit_card_form); - ASSERT_TRUE(form_manager_to_save); - EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), - FormMatches(credit_card_form)); + // Check that saving fallback is available. + std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; + EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); + manager()->ShowManualFallbackForSaving(&driver_, credit_card_form); + ASSERT_TRUE(form_manager_to_save); + EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), + FormMatches(credit_card_form)); - // Check that no automatic save prompt is shown. - OnPasswordFormSubmitted(credit_card_form); - EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0); - manager()->DidNavigateMainFrame(true); - manager()->OnPasswordFormsRendered(&driver_, {}, true); + // Check that no automatic save prompt is shown. + OnPasswordFormSubmitted(credit_card_form); + EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0); + manager()->DidNavigateMainFrame(true); + manager()->OnPasswordFormsRendered(&driver_, {}, true); } #if !defined(OS_IOS) @@ -3161,7 +3163,7 @@ // Check that a non-password form with SINGLE_USERNAME prediction is filled. TEST_F(PasswordManagerTest, FillSingleUsername) { - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true); + PasswordFormManager::set_wait_for_server_predictions_for_filling(true); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); PasswordForm saved_match(MakeSavedForm()); @@ -3202,7 +3204,7 @@ // in marking the password field as eligible for password generation. TEST_F(PasswordManagerTest, MarkServerPredictedClearTextPasswordFieldEligibleForGeneration) { - NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true); + PasswordFormManager::set_wait_for_server_predictions_for_filling(true); EXPECT_CALL(client_, IsSavingAndFillingEnabled(_)) .WillRepeatedly(Return(true)); PasswordForm saved_match(MakeSavedForm());
diff --git a/components/password_manager/core/browser/password_manager_util.cc b/components/password_manager/core/browser/password_manager_util.cc index 1637ad7e..8cc2657 100644 --- a/components/password_manager/core/browser/password_manager_util.cc +++ b/components/password_manager/core/browser/password_manager_util.cc
@@ -228,18 +228,15 @@ void FindBestMatches( std::vector<const PasswordForm*> matches, std::map<base::string16, const PasswordForm*>* best_matches, - std::vector<const PasswordForm*>* not_best_matches, const PasswordForm** preferred_match) { DCHECK(std::all_of( matches.begin(), matches.end(), [](const PasswordForm* match) { return !match->blacklisted_by_user; })); DCHECK(best_matches); - DCHECK(not_best_matches); DCHECK(preferred_match); *preferred_match = nullptr; best_matches->clear(); - not_best_matches->clear(); if (matches.empty()) return; @@ -251,8 +248,6 @@ // The first match for |username| in the sorted array is best match. if (best_matches->find(username) == best_matches->end()) best_matches->insert(std::make_pair(username, match)); - else - not_best_matches->push_back(match); } *preferred_match = *matches.begin();
diff --git a/components/password_manager/core/browser/password_manager_util.h b/components/password_manager/core/browser/password_manager_util.h index 6e90fd05..2fc22bf 100644 --- a/components/password_manager/core/browser/password_manager_util.h +++ b/components/password_manager/core/browser/password_manager_util.h
@@ -113,8 +113,8 @@ base::StringPiece GetSignonRealmWithProtocolExcluded( const autofill::PasswordForm& form); -// Given all non-blacklisted |matches|, finds and populates -// |best_matches_|, |preferred_match_| and |non_best_matches_| accordingly. +// Given all non-blacklisted |matches|, finds and populates |best_matches| and +// |preferred_match_| accordingly. // For comparing credentials the following rule is used: non-psl match is better // than psl match, preferred match is better than non-preferred match. In case // of tie, an arbitrary credential from the tied ones is chosen for @@ -122,7 +122,6 @@ void FindBestMatches( std::vector<const autofill::PasswordForm*> matches, std::map<base::string16, const autofill::PasswordForm*>* best_matches, - std::vector<const autofill::PasswordForm*>* not_best_matches, const autofill::PasswordForm** preferred_match); // If the user submits a form, they may have used existing credentials, new
diff --git a/components/password_manager/core/browser/password_manager_util_unittest.cc b/components/password_manager/core/browser/password_manager_util_unittest.cc index f8fb995..c26eadb6 100644 --- a/components/password_manager/core/browser/password_manager_util_unittest.cc +++ b/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -198,17 +198,14 @@ matches.push_back(&match); std::map<base::string16, const PasswordForm*> best_matches; - std::vector<const PasswordForm*> not_best_matches; const PasswordForm* preferred_match = nullptr; - FindBestMatches(matches, &best_matches, ¬_best_matches, - &preferred_match); + FindBestMatches(matches, &best_matches, &preferred_match); if (test_case.expected_preferred_match_index == kNotFound) { // Case of empty |matches|. EXPECT_FALSE(preferred_match); EXPECT_TRUE(best_matches.empty()); - EXPECT_TRUE(not_best_matches.empty()); } else { // Check |preferred_match|. EXPECT_EQ(matches[test_case.expected_preferred_match_index], @@ -228,18 +225,6 @@ std::find(matches.begin(), matches.end(), username_match.second)); EXPECT_EQ(expected_index, actual_index); } - - // Check non-best matches. - ASSERT_EQ(matches.size(), best_matches.size() + not_best_matches.size()); - for (const PasswordForm* form : not_best_matches) { - // A non-best match form must not be in |best_matches|. - EXPECT_NE(best_matches[form->username_value], form); - - base::Erase(matches, form); - } - // Expect that all non-best matches were found in |matches| and only best - // matches left. - EXPECT_EQ(best_matches.size(), matches.size()); } } }
diff --git a/components/password_manager/core/browser/store_metrics_reporter.cc b/components/password_manager/core/browser/store_metrics_reporter.cc index 4464ab3..34eca4d 100644 --- a/components/password_manager/core/browser/store_metrics_reporter.cc +++ b/components/password_manager/core/browser/store_metrics_reporter.cc
@@ -6,6 +6,7 @@ #include "base/metrics/histogram_functions.h" #include "components/password_manager/core/browser/password_manager_client.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/browser/password_sync_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" @@ -33,6 +34,10 @@ "PasswordManager.LeakDetection.Enabled", prefs->GetBoolean( password_manager::prefs::kPasswordLeakDetectionEnabled)); + password_manager::metrics_util::LogOnboardingState( + static_cast<password_manager::metrics_util::OnboardingState>( + prefs->GetInteger( + password_manager::prefs::kPasswordManagerOnboardingState))); } StoreMetricsReporter::~StoreMetricsReporter() = default;
diff --git a/components/password_manager/core/browser/store_metrics_reporter_unittest.cc b/components/password_manager/core/browser/store_metrics_reporter_unittest.cc index 3b9929b..4a151bd4 100644 --- a/components/password_manager/core/browser/store_metrics_reporter_unittest.cc +++ b/components/password_manager/core/browser/store_metrics_reporter_unittest.cc
@@ -8,6 +8,7 @@ #include "base/memory/scoped_refptr.h" #include "base/test/metrics/histogram_tester.h" #include "components/password_manager/core/browser/mock_password_store.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/sync_username_test_base.h" #include "components/password_manager/core/common/password_manager_pref_names.h" @@ -17,6 +18,7 @@ #include "testing/gtest/include/gtest/gtest.h" using ::testing::Bool; +using ::testing::Range; using ::testing::Return; namespace password_manager { @@ -35,7 +37,7 @@ // them. class StoreMetricsReporterTest : public SyncUsernameTestBase, - public ::testing::WithParamInterface<std::tuple<bool, bool>> { + public ::testing::WithParamInterface<std::tuple<bool, bool, int>> { public: StoreMetricsReporterTest() { prefs_.registry()->RegisterBooleanPref(prefs::kCredentialsEnableService, @@ -44,6 +46,10 @@ false); prefs_.registry()->RegisterBooleanPref( password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, false); + prefs_.registry()->RegisterIntegerPref( + password_manager::prefs::kPasswordManagerOnboardingState, + static_cast<int>( + password_manager::metrics_util::OnboardingState::kDoNotShow)); } ~StoreMetricsReporterTest() override = default; @@ -58,11 +64,14 @@ TEST_P(StoreMetricsReporterTest, StoreIndependentMetrics) { const bool password_manager_enabled = std::get<0>(GetParam()); const bool leak_detection_enabled = std::get<1>(GetParam()); + const int onboarding_state = std::get<2>(GetParam()); prefs_.SetBoolean(password_manager::prefs::kCredentialsEnableService, password_manager_enabled); prefs_.SetBoolean(password_manager::prefs::kPasswordLeakDetectionEnabled, leak_detection_enabled); + prefs_.SetInteger(password_manager::prefs::kPasswordManagerOnboardingState, + onboarding_state); base::HistogramTester histogram_tester; EXPECT_CALL(client_, GetPasswordStore()).WillOnce(Return(nullptr)); StoreMetricsReporter reporter(&client_, sync_service(), identity_manager(), @@ -72,6 +81,8 @@ password_manager_enabled, 1); histogram_tester.ExpectUniqueSample("PasswordManager.LeakDetection.Enabled", leak_detection_enabled, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.Onboarding.State", + onboarding_state, 1); } // Test that sync username and syncing state are passed correctly to the @@ -98,9 +109,16 @@ store->ShutdownOnUIThread(); } -INSTANTIATE_TEST_SUITE_P(/*InstantiationName*/, - StoreMetricsReporterTest, - testing::Combine(Bool(), Bool())); +INSTANTIATE_TEST_SUITE_P( + /*InstantiationName*/, + StoreMetricsReporterTest, + testing::Combine( + Bool(), + Bool(), + Range(0, + static_cast<int>( + password_manager::metrics_util::OnboardingState::kMaxValue) + + 1))); } // namespace } // namespace password_manager
diff --git a/components/password_manager/core/browser/sync/password_model_type_controller.cc b/components/password_manager/core/browser/sync/password_model_type_controller.cc index db4dab36..b65603a3 100644 --- a/components/password_manager/core/browser/sync/password_model_type_controller.cc +++ b/components/password_manager/core/browser/sync/password_model_type_controller.cc
@@ -15,9 +15,12 @@ PasswordModelTypeController::PasswordModelTypeController( std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk, + std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory, syncer::SyncService* sync_service, const base::RepeatingClosure& state_changed_callback) - : ModelTypeController(syncer::PASSWORDS, std::move(delegate_on_disk)), + : ModelTypeController(syncer::PASSWORDS, + std::move(delegate_on_disk), + std::move(delegate_in_memory)), sync_service_(sync_service), state_changed_callback_(state_changed_callback) {}
diff --git a/components/password_manager/core/browser/sync/password_model_type_controller.h b/components/password_manager/core/browser/sync/password_model_type_controller.h index 2593dab..3745f88 100644 --- a/components/password_manager/core/browser/sync/password_model_type_controller.h +++ b/components/password_manager/core/browser/sync/password_model_type_controller.h
@@ -25,6 +25,7 @@ public: PasswordModelTypeController( std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk, + std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory, syncer::SyncService* sync_service, const base::RepeatingClosure& state_changed_callback); ~PasswordModelTypeController() override;
diff --git a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc index dc57f9b6..9603ef7 100644 --- a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc +++ b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -19,7 +19,7 @@ #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/fake_form_fetcher.h" #include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" @@ -143,7 +143,7 @@ StubPasswordManagerDriver driver_; PasswordForm pending_; FakeFormFetcher fetcher_; - NewPasswordFormManager form_manager_; + PasswordFormManager form_manager_; SyncCredentialsFilter filter_; };
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index 422479e..dbc89a6 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -527,19 +527,12 @@ } bool VotesUploader::FindCorrectedUsernameElement( - const std::map<base::string16, const PasswordForm*>& best_matches, - const std::vector<const PasswordForm*>& not_best_matches, + const std::vector<const PasswordForm*>& matches, const base::string16& username, const base::string16& password) { if (username.empty()) return false; - for (const auto& key_value : best_matches) { - const PasswordForm* match = key_value.second; - if ((match->password_value == password) && - FindUsernameInOtherPossibleUsernames(*match, username)) - return true; - } - for (const PasswordForm* match : not_best_matches) { + for (const PasswordForm* match : matches) { if ((match->password_value == password) && FindUsernameInOtherPossibleUsernames(*match, username)) return true;
diff --git a/components/password_manager/core/browser/votes_uploader.h b/components/password_manager/core/browser/votes_uploader.h index abe6879..acf0fc13 100644 --- a/components/password_manager/core/browser/votes_uploader.h +++ b/components/password_manager/core/browser/votes_uploader.h
@@ -70,15 +70,12 @@ const autofill::PasswordForm& pending_credentials, const autofill::PasswordForm& form_to_upload); - // Searches for |username| in |all_possible_usernames| of |best_matches| - // and |not_best_matches|. If the username value is found in - // |all_possible_usernames| and the password value of the match is equal to - // |password|, the match is saved to |username_correction_vote_| and the - // method returns true. + // Searches for |username| in |all_possible_usernames| of |matches|. If the + // username value is found in |all_possible_usernames| and the password value + // of the match is equal to |password|, the match is saved to + // |username_correction_vote_| and the method returns true. bool FindCorrectedUsernameElement( - const std::map<base::string16, const autofill::PasswordForm*>& - best_matches, - const std::vector<const autofill::PasswordForm*>& not_best_matches, + const std::vector<const autofill::PasswordForm*>& matches, const base::string16& username, const base::string16& password);
diff --git a/components/search_engines/keyword_web_data_service.cc b/components/search_engines/keyword_web_data_service.cc index c1ab407..8638763 100644 --- a/components/search_engines/keyword_web_data_service.cc +++ b/components/search_engines/keyword_web_data_service.cc
@@ -12,16 +12,51 @@ #include "components/webdata/common/web_data_results.h" #include "components/webdata/common/web_database_service.h" -using base::Bind; +namespace { -WDKeywordsResult::WDKeywordsResult() - : default_search_provider_id(0), - builtin_keyword_version(0) { +WebDatabase::State PerformKeywordOperationsImpl( + const KeywordTable::Operations& operations, + WebDatabase* db) { + return KeywordTable::FromWebDatabase(db)->PerformOperations(operations) + ? WebDatabase::COMMIT_NEEDED + : WebDatabase::COMMIT_NOT_NEEDED; } -WDKeywordsResult::WDKeywordsResult(const WDKeywordsResult& other) = default; +std::unique_ptr<WDTypedResult> GetKeywordsImpl(WebDatabase* db) { + KeywordTable* const keyword_table = KeywordTable::FromWebDatabase(db); + WDKeywordsResult result; + if (!keyword_table->GetKeywords(&result.keywords)) + return nullptr; -WDKeywordsResult::~WDKeywordsResult() {} + result.default_search_provider_id = + keyword_table->GetDefaultSearchProviderID(); + result.builtin_keyword_version = keyword_table->GetBuiltinKeywordVersion(); + return std::make_unique<WDResult<WDKeywordsResult>>(KEYWORDS_RESULT, result); +} + +WebDatabase::State SetDefaultSearchProviderIDImpl(TemplateURLID id, + WebDatabase* db) { + return KeywordTable::FromWebDatabase(db)->SetDefaultSearchProviderID(id) + ? WebDatabase::COMMIT_NEEDED + : WebDatabase::COMMIT_NOT_NEEDED; +} + +WebDatabase::State SetBuiltinKeywordVersionImpl(int version, WebDatabase* db) { + return KeywordTable::FromWebDatabase(db)->SetBuiltinKeywordVersion(version) + ? WebDatabase::COMMIT_NEEDED + : WebDatabase::COMMIT_NOT_NEEDED; +} + +} // namespace + +WDKeywordsResult::WDKeywordsResult() = default; + +WDKeywordsResult::WDKeywordsResult(const WDKeywordsResult&) = default; + +WDKeywordsResult& WDKeywordsResult::operator=(const WDKeywordsResult&) = + default; + +WDKeywordsResult::~WDKeywordsResult() = default; KeywordWebDataService::BatchModeScoper::BatchModeScoper( KeywordWebDataService* service) @@ -40,7 +75,10 @@ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, const ProfileErrorCallback& callback) : WebDataServiceBase(wdbs, callback, ui_task_runner), - batch_mode_level_(0) {} + timer_(FROM_HERE, + base::TimeDelta::FromSeconds(5), + base::BindRepeating(&KeywordWebDataService::CommitQueuedOperations, + base::Unretained(this))) {} void KeywordWebDataService::AddKeyword(const TemplateURLData& data) { if (batch_mode_level_) { @@ -79,25 +117,27 @@ WebDataServiceBase::Handle KeywordWebDataService::GetKeywords( WebDataServiceConsumer* consumer) { + // Force pending changes to be visible immediately so the results of this call + // won't be out of date. + CommitQueuedOperations(); + return wdbs_->ScheduleDBTaskWithResult( - FROM_HERE, Bind(&KeywordWebDataService::GetKeywordsImpl, this), consumer); + FROM_HERE, base::Bind(&GetKeywordsImpl), consumer); } void KeywordWebDataService::SetDefaultSearchProviderID(TemplateURLID id) { - wdbs_->ScheduleDBTask( - FROM_HERE, - Bind(&KeywordWebDataService::SetDefaultSearchProviderIDImpl, this, id)); + wdbs_->ScheduleDBTask(FROM_HERE, + base::Bind(&SetDefaultSearchProviderIDImpl, id)); } void KeywordWebDataService::SetBuiltinKeywordVersion(int version) { - wdbs_->ScheduleDBTask( - FROM_HERE, - Bind(&KeywordWebDataService::SetBuiltinKeywordVersionImpl, - this, version)); + wdbs_->ScheduleDBTask(FROM_HERE, + base::Bind(&SetBuiltinKeywordVersionImpl, version)); } KeywordWebDataService::~KeywordWebDataService() { DCHECK(!batch_mode_level_); + CommitQueuedOperations(); } void KeywordWebDataService::AdjustBatchModeLevel(bool entering_batch_mode) { @@ -106,47 +146,17 @@ } else { DCHECK(batch_mode_level_); --batch_mode_level_; - if (!batch_mode_level_ && !queued_keyword_operations_.empty()) { - wdbs_->ScheduleDBTask( - FROM_HERE, - Bind(&KeywordWebDataService::PerformKeywordOperationsImpl, this, - queued_keyword_operations_)); - queued_keyword_operations_.clear(); - } + if (!batch_mode_level_ && !queued_keyword_operations_.empty() && + !timer_.IsRunning()) + timer_.Reset(); } } -WebDatabase::State KeywordWebDataService::PerformKeywordOperationsImpl( - const KeywordTable::Operations& operations, - WebDatabase* db) { - return KeywordTable::FromWebDatabase(db)->PerformOperations(operations) ? - WebDatabase::COMMIT_NEEDED : WebDatabase::COMMIT_NOT_NEEDED; -} - -std::unique_ptr<WDTypedResult> KeywordWebDataService::GetKeywordsImpl( - WebDatabase* db) { - std::unique_ptr<WDTypedResult> result_ptr; - WDKeywordsResult result; - if (KeywordTable::FromWebDatabase(db)->GetKeywords(&result.keywords)) { - result.default_search_provider_id = - KeywordTable::FromWebDatabase(db)->GetDefaultSearchProviderID(); - result.builtin_keyword_version = - KeywordTable::FromWebDatabase(db)->GetBuiltinKeywordVersion(); - result_ptr.reset(new WDResult<WDKeywordsResult>(KEYWORDS_RESULT, result)); +void KeywordWebDataService::CommitQueuedOperations() { + if (!queued_keyword_operations_.empty()) { + wdbs_->ScheduleDBTask(FROM_HERE, base::Bind(&PerformKeywordOperationsImpl, + queued_keyword_operations_)); + queued_keyword_operations_.clear(); } - return result_ptr; -} - -WebDatabase::State KeywordWebDataService::SetDefaultSearchProviderIDImpl( - TemplateURLID id, - WebDatabase* db) { - return KeywordTable::FromWebDatabase(db)->SetDefaultSearchProviderID(id) ? - WebDatabase::COMMIT_NEEDED : WebDatabase::COMMIT_NOT_NEEDED; -} - -WebDatabase::State KeywordWebDataService::SetBuiltinKeywordVersionImpl( - int version, - WebDatabase* db) { - return KeywordTable::FromWebDatabase(db)->SetBuiltinKeywordVersion(version) ? - WebDatabase::COMMIT_NEEDED : WebDatabase::COMMIT_NOT_NEEDED; + timer_.Stop(); }
diff --git a/components/search_engines/keyword_web_data_service.h b/components/search_engines/keyword_web_data_service.h index f97f0363..2b4a16c 100644 --- a/components/search_engines/keyword_web_data_service.h +++ b/components/search_engines/keyword_web_data_service.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/timer/timer.h" #include "components/search_engines/keyword_table.h" #include "components/search_engines/template_url_id.h" #include "components/webdata/common/web_data_service_base.h" @@ -19,21 +20,21 @@ class SingleThreadTaskRunner; } -class WDTypedResult; class WebDatabaseService; struct TemplateURLData; struct WDKeywordsResult { WDKeywordsResult(); - WDKeywordsResult(const WDKeywordsResult& other); + WDKeywordsResult(const WDKeywordsResult&); + WDKeywordsResult& operator=(const WDKeywordsResult&); ~WDKeywordsResult(); KeywordTable::Keywords keywords; // Identifies the ID of the TemplateURL that is the default search. A value of // 0 indicates there is no default search provider. - int64_t default_search_provider_id; + int64_t default_search_provider_id = 0; // Version of the built-in keywords. A value of 0 indicates a first run. - int builtin_keyword_version; + int builtin_keyword_version = 0; }; class WebDataServiceConsumer; @@ -43,8 +44,8 @@ // Instantiate this to turn on batch mode on the provided |service| // until the scoper is destroyed. When batch mode is on, calls to any of the // three keyword table modification functions below will result in locally - // queueing the operation; on setting this back to false, all the - // modifications will be performed at once. This is a performance + // queueing the operation; on setting this back to false, after a short delay, + // all the modifications will be performed at once. This is a performance // optimization; see comments on KeywordTable::PerformOperations(). // // If multiple scopers are in-scope simultaneously, batch mode will only be @@ -94,21 +95,13 @@ // Called by the BatchModeScoper (see comments there). void AdjustBatchModeLevel(bool entering_batch_mode); - ////////////////////////////////////////////////////////////////////////////// - // - // The following methods are only invoked on the DB sequence. - // - ////////////////////////////////////////////////////////////////////////////// - WebDatabase::State PerformKeywordOperationsImpl( - const KeywordTable::Operations& operations, - WebDatabase* db); - std::unique_ptr<WDTypedResult> GetKeywordsImpl(WebDatabase* db); - WebDatabase::State SetDefaultSearchProviderIDImpl(TemplateURLID id, - WebDatabase* db); - WebDatabase::State SetBuiltinKeywordVersionImpl(int version, WebDatabase* db); + // Schedules a task to commit any |queued_keyword_operations_| immediately. + void CommitQueuedOperations(); - size_t batch_mode_level_; + size_t batch_mode_level_ = 0; KeywordTable::Operations queued_keyword_operations_; + base::RetainingOneShotTimer timer_; // Used to commit updates no more often + // than every five seconds. DISALLOW_COPY_AND_ASSIGN(KeywordWebDataService); };
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc index d7fac12..d1e1710 100644 --- a/components/signin/core/browser/account_reconcilor.cc +++ b/components/signin/core/browser/account_reconcilor.cc
@@ -40,8 +40,13 @@ using signin::AccountReconcilorDelegate; using signin_metrics::AccountReconcilorState; +#if defined(OS_ANDROID) || defined(OS_IOS) +const base::Feature kUseMultiloginEndpoint{"UseMultiloginEndpoint", + base::FEATURE_ENABLED_BY_DEFAULT}; +#else const base::Feature kUseMultiloginEndpoint{"UseMultiloginEndpoint", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif namespace {
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index 1a63c72..85c57f8f 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -76,6 +76,14 @@ return primary_account; } + std::vector<CoreAccountId> GetChromeAccountsForReconcile( + const std::vector<CoreAccountId>& chrome_accounts, + const CoreAccountId& primary_account, + const std::vector<gaia::ListedAccount>& gaia_accounts, + const gaia::MultiloginMode mode) const override { + return chrome_accounts; + } + void OnReconcileFinished(const CoreAccountId& first_account, bool reconcile_is_noop) override { ++num_reconcile_finished_calls_; @@ -309,6 +317,8 @@ SetAccountConsistency(signin::AccountConsistencyMethod::kMirror); if (IsMultiloginEnabled()) scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint); + else + scoped_feature_list_.InitAndDisableFeature(kUseMultiloginEndpoint); } bool IsMultiloginEnabled() { return GetParam(); } @@ -2958,7 +2968,8 @@ // performing a full logout. TEST_P(AccountReconcilorMethodParamTest, StartReconcileWithSessionInfoExpiredDefault) { - SetAccountConsistency(GetParam()); + signin::AccountConsistencyMethod account_consistency = GetParam(); + SetAccountConsistency(account_consistency); AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); const CoreAccountId account_id = account_info.account_id; AccountInfo account_info2 = @@ -2971,18 +2982,46 @@ false /* signed_out */, true /* verified */}}, &test_url_loader_factory_); - EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); - AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); + if (!reconcilor->IsMultiloginEndpointEnabled()) { + EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); + } else { + switch (account_consistency) { + case signin::AccountConsistencyMethod::kMirror: { + signin::MultiloginParameters params( + gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, + {account_id, account_id2}); + EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params)); + break; + } + case signin::AccountConsistencyMethod::kDice: { + signin::MultiloginParameters params( + gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER, + {account_id2, account_id}); + EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params)); + break; + } + case signin::AccountConsistencyMethod::kDisabled: + case signin::AccountConsistencyMethod::kDiceMigration: + NOTREACHED(); + break; + } + } + ASSERT_FALSE(reconcilor->is_reconcile_started_); reconcilor->StartReconcile(); ASSERT_TRUE(reconcilor->is_reconcile_started_); base::RunLoop().RunUntilIdle(); - SimulateAddAccountToCookieCompleted(reconcilor, account_id, - GoogleServiceAuthError::AuthErrorNone()); + if (!reconcilor->IsMultiloginEndpointEnabled()) { + SimulateAddAccountToCookieCompleted( + reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone()); + } else { + SimulateSetAccountsInCookieCompleted( + reconcilor, signin::SetAccountsInCookieResult::kSuccess); + } ASSERT_FALSE(reconcilor->is_reconcile_started_); } @@ -2999,15 +3038,43 @@ MOCK_METHOD1(OnStateChanged, void(AccountReconcilorState state)); }; - SetAccountConsistency(GetParam()); - AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + signin::AccountConsistencyMethod account_consistency = GetParam(); + SetAccountConsistency(account_consistency); + AccountInfo account_info1 = ConnectProfileToAccount("user@gmail.com"); AccountInfo account_info2 = identity_test_env()->MakeAccountAvailable("other@gmail.com"); + const CoreAccountId account_id1 = account_info1.account_id; const CoreAccountId account_id2 = account_info2.account_id; signin::SetListAccountsResponseOneAccount( - account_info.email, account_info.gaia, &test_url_loader_factory_); + account_info1.email, account_info1.gaia, &test_url_loader_factory_); - EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); + AccountReconcilor* reconcilor = GetMockReconcilor(); + ASSERT_TRUE(reconcilor); + + if (!reconcilor->IsMultiloginEndpointEnabled()) { + EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); + } else { + switch (account_consistency) { + case signin::AccountConsistencyMethod::kMirror: { + signin::MultiloginParameters params( + gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, + {account_id1, account_id2}); + EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params)); + break; + } + case signin::AccountConsistencyMethod::kDice: { + signin::MultiloginParameters params( + gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER, + {account_id2, account_id1}); + EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params)); + break; + } + case signin::AccountConsistencyMethod::kDisabled: + case signin::AccountConsistencyMethod::kDiceMigration: + NOTREACHED(); + break; + } + } // The reconcilor should run twice without going to the OK state in between. // OK only happens at the end. @@ -3027,8 +3094,6 @@ OnStateChanged(AccountReconcilorState::ACCOUNT_RECONCILOR_OK)) .Times(1); - AccountReconcilor* reconcilor = GetMockReconcilor(); - ASSERT_TRUE(reconcilor); ScopedObserver<AccountReconcilor, AccountReconcilor::Observer> scoped_observer(&observer); scoped_observer.Add(reconcilor); @@ -3051,9 +3116,14 @@ // reconcile after the current one. identity_test_env()->RemoveRefreshTokenForAccount(account_id2); - // Unblock the first reconcile. - SimulateAddAccountToCookieCompleted(reconcilor, account_id2, - GoogleServiceAuthError::AuthErrorNone()); + if (!reconcilor->IsMultiloginEndpointEnabled()) { + SimulateAddAccountToCookieCompleted( + reconcilor, account_id2, GoogleServiceAuthError::AuthErrorNone()); + } else { + SimulateSetAccountsInCookieCompleted( + reconcilor, signin::SetAccountsInCookieResult::kSuccess); + } + // Wait until the first reconcile finishes, and a second reconcile is done. // The second reconcile will be a no-op. base::RunLoop().RunUntilIdle();
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java index 580e920..b13fa47f 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java
@@ -8,7 +8,9 @@ import org.junit.runner.Description; import org.junit.runners.model.Statement; +import org.chromium.base.ThreadUtils; import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.ProfileDataSource; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -20,6 +22,7 @@ */ public class AccountManagerTestRule implements TestRule { private FakeAccountManagerDelegate mDelegate; + private @FakeAccountManagerDelegate.ProfileDataSourceFlag int mProfileDataSourceFlag; /** * Test method annotation signaling that the account population should be blocked until {@link @@ -29,19 +32,26 @@ @Retention(RetentionPolicy.RUNTIME) public @interface BlockGetAccounts {} + public AccountManagerTestRule() { + this(FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE); + } + + public AccountManagerTestRule( + @FakeAccountManagerDelegate.ProfileDataSourceFlag int profileDataSourceFlag) { + mProfileDataSourceFlag = profileDataSourceFlag; + } + @Override public Statement apply(Statement statement, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { - final int profileDataSourceFlag = - FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE; final int blockGetAccountsFlag = description.getAnnotation(BlockGetAccounts.class) == null ? FakeAccountManagerDelegate.DISABLE_BLOCK_GET_ACCOUNTS : FakeAccountManagerDelegate.ENABLE_BLOCK_GET_ACCOUNTS; - mDelegate = - new FakeAccountManagerDelegate(profileDataSourceFlag, blockGetAccountsFlag); + mDelegate = new FakeAccountManagerDelegate( + mProfileDataSourceFlag, blockGetAccountsFlag); AccountManagerFacade.overrideAccountManagerFacadeForTests(mDelegate); statement.evaluate(); } @@ -56,4 +66,18 @@ mDelegate.unblockGetAccounts(); AccountManagerFacade.get().tryGetGoogleAccounts(); } + + public void addAccount(AccountHolder accountHolder) { + mDelegate.addAccountHolderBlocking(accountHolder); + } + + public void addAccount(AccountHolder accountHolder, ProfileDataSource.ProfileData profileData) { + mDelegate.addAccountHolderBlocking(accountHolder); + ThreadUtils.runOnUiThreadBlocking( + () -> mDelegate.setProfileData(accountHolder.getAccount().name, profileData)); + } + + public void removeAccount(AccountHolder accountHolder) { + mDelegate.removeAccountHolderBlocking(accountHolder); + } }
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java index 029306e..ded8b607 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
@@ -65,7 +65,7 @@ @Retention(RetentionPolicy.SOURCE) public @interface BlockGetAccountsFlag {} - /** Disables block get accounts: {@link #getAccountInfosSync} will return immediately. */ + /** Disables block get accounts: {@link #getAccountsSync()} will return immediately. */ public static final int DISABLE_BLOCK_GET_ACCOUNTS = 0; /** Block get accounts until {@link #unblockGetAccounts()} is called. */ public static final int ENABLE_BLOCK_GET_ACCOUNTS = 1;
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index f673a51..211198498 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -140,6 +140,8 @@ debug_identifier_(init_params.debug_identifier), autofill_enable_account_wallet_storage_( init_params.autofill_enable_account_wallet_storage), + enable_passwords_account_storage_( + init_params.enable_passwords_account_storage), sync_service_url_( GetSyncServiceURL(*base::CommandLine::ForCurrentProcess(), channel_)), crypto_( @@ -1271,6 +1273,13 @@ } } + if (enable_passwords_account_storage_ && + base::FeatureList::IsEnabled(switches::kSyncUSSPasswords)) { + if (!GetUserSettings()->IsUsingSecondaryPassphrase()) { + allowed_types.Put(PASSWORDS); + } + } + types = Intersection(types, allowed_types); configure_context.storage_option = STORAGE_IN_MEMORY; }
diff --git a/components/sync/driver/profile_sync_service.h b/components/sync/driver/profile_sync_service.h index 834d9612..8be1975 100644 --- a/components/sync/driver/profile_sync_service.h +++ b/components/sync/driver/profile_sync_service.h
@@ -98,6 +98,7 @@ version_info::Channel channel = version_info::Channel::UNKNOWN; std::string debug_identifier; bool autofill_enable_account_wallet_storage = false; + bool enable_passwords_account_storage = false; private: DISALLOW_COPY_AND_ASSIGN(InitParams); @@ -386,6 +387,7 @@ const std::string debug_identifier_; const bool autofill_enable_account_wallet_storage_; + const bool enable_passwords_account_storage_; // This specifies where to find the sync server. const GURL sync_service_url_;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 7c8a677..f4fd88b 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1639,6 +1639,8 @@ "scheduler/scoped_do_not_use_ui_default_queue_from_io.h", "scoped_active_url.cc", "scoped_active_url.h", + "screen_enumeration/screen_enumeration_impl.cc", + "screen_enumeration/screen_enumeration_impl.h", "screen_orientation/screen_orientation_provider.cc", "screen_orientation/screen_orientation_provider.h", "screenlock_monitor/screenlock_monitor.cc",
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc index 2a18e79..fc7fc3ed 100644 --- a/content/browser/appcache/appcache_request_handler.cc +++ b/content/browser/appcache/appcache_request_handler.cc
@@ -229,16 +229,16 @@ std::make_unique<AppCacheURLLoaderRequest>(request), static_cast<ResourceType>(request.resource_type), request.should_reset_appcache); - handler->appcache_host_ = std::move(appcache_host); + if (handler) + handler->appcache_host_ = std::move(appcache_host); return handler; } // static bool AppCacheRequestHandler::IsMainResourceType(ResourceType type) { - // When PlzDedicatedWorker is enabled, a dedicated worker script is considered - // to be a main resource. - if (type == ResourceType::kWorker) - return base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker); + // This returns false for kWorker, which is typically considered a main + // resource. In appcache, dedicated workers are treated as subresources of + // their nearest ancestor frame's appcache host unlike shared workers. return IsResourceTypeFrame(type) || type == ResourceType::kSharedWorker; } @@ -571,8 +571,16 @@ return false; } DCHECK(was_called); - if (IsMainResourceType(resource_type_)) + + // Create a subresource loader if needed (it's a main resource or a dedicated + // worker). + // In appcache, dedicated workers are treated as subresources of their nearest + // ancestor frame's appcache host. On the other hand, dedicated workers need + // their own subresource loader. + if (IsMainResourceType(resource_type_) || + resource_type_ == ResourceType::kWorker) { should_create_subresource_loader_ = true; + } return true; }
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index 30d5290..14d5549 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -5,6 +5,7 @@ #include "base/command_line.h" #include "base/test/bind_test_util.h" #include "base/test/scoped_feature_list.h" +#include "components/network_session_configurator/common/network_switches.h" #include "content/browser/frame_host/back_forward_cache.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -22,6 +23,7 @@ #include "content/public/test/url_loader_interceptor.h" #include "content/shell/browser/shell.h" #include "content/test/content_browser_test_utils_internal.h" +#include "net/base/filename_util.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/controllable_http_response.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -37,14 +39,24 @@ // Test about the BackForwardCache. class BackForwardCacheBrowserTest : public ContentBrowserTest { + public: + ~BackForwardCacheBrowserTest() override = default; + protected: void SetUpCommandLine(base::CommandLine* command_line) override { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kUseFakeUIForMediaStream); - feature_list_.InitAndEnableFeature(features::kBackForwardCache); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kIgnoreCertificateErrors); + feature_list_.InitWithFeatures(FeaturesToEnable(), {}); + ContentBrowserTest::SetUpCommandLine(command_line); } + virtual std::vector<base::Feature> FeaturesToEnable() { + return std::vector<base::Feature>({features::kBackForwardCache}); + } + void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1"); ContentBrowserTest::SetUpOnMainThread(); @@ -1600,4 +1612,177 @@ )")); } +// Only HTTP/HTTPS main document can enter the BackForwardCache. +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, CacheHTTPDocumentOnly) { + ASSERT_TRUE(embedded_test_server()->Start()); + + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.AddDefaultHandlers(GetTestDataFilePath()); + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); + ASSERT_TRUE(https_server.Start()); + + GURL http_url(embedded_test_server()->GetURL("a.com", "/title1.html")); + GURL https_url(https_server.GetURL("a.com", "/title1.html")); + GURL file_url = net::FilePathToFileURL(GetTestFilePath("", "title1.html")); + GURL data_url = GURL("data:text/html,"); + GURL blank_url = GURL(url::kAboutBlankURL); + GURL webui_url = GetWebUIURL("gpu"); + + enum { STORED, DELETED }; + struct { + int expectation; + GURL url; + } test_cases[] = { + // Only document with HTTP/HTTPS URLs are allowed to enter the + // BackForwardCache. + {STORED, http_url}, + {STORED, https_url}, + + // Others aren't allowed. + {DELETED, file_url}, + {DELETED, data_url}, + {DELETED, webui_url}, + {DELETED, blank_url}, + }; + + char hostname[] = "a.unique"; + for (auto& test_case : test_cases) { + SCOPED_TRACE(testing::Message() + << std::endl + << "expectation = " << test_case.expectation << std::endl + << "url = " << test_case.url << std::endl); + + // 1) Navigate to. + EXPECT_TRUE(NavigateToURL(shell(), test_case.url)); + RenderFrameHostImpl* rfh = current_frame_host(); + RenderFrameDeletedObserver delete_observer(rfh); + + // 2) Navigate away. + hostname[0]++; + GURL reset_url(embedded_test_server()->GetURL(hostname, "/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), reset_url)); + + if (test_case.expectation == STORED) { + EXPECT_FALSE(delete_observer.deleted()); + EXPECT_TRUE(rfh->is_in_back_forward_cache()); + continue; + } + + // On Android, navigations to about:blank keeps the same RenderFrameHost. + // Obviously, it can't enter the BackForwardCache, because it is still used + // to display the current document. + if (test_case.url == blank_url && + !SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) { + EXPECT_FALSE(delete_observer.deleted()); + EXPECT_FALSE(rfh->is_in_back_forward_cache()); + EXPECT_EQ(rfh, current_frame_host()); + continue; + } + + delete_observer.WaitUntilDeleted(); + } +} + +namespace { + +void RegisterServiceWorker(RenderFrameHostImpl* rfh) { + EXPECT_EQ("success", EvalJs(rfh, R"( + let controller_changed_promise = new Promise(resolve_controller_change => { + navigator.serviceWorker.oncontrollerchange = resolve_controller_change; + }); + + new Promise(async resolve => { + try { + await navigator.serviceWorker.register( + "./service-worker.js", {scope: "./"}) + } catch (e) { + resolve("error: registration has failed"); + } + + await controller_changed_promise; + + if (navigator.serviceWorker.controller) { + resolve("success"); + } else { + resolve("error: not controlled by service worker"); + } + }); + )")); +} + +} // namespace + +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, + DoesNotCachePagesWithServiceWorkers) { + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.AddDefaultHandlers(GetTestDataFilePath()); + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); + ASSERT_TRUE(https_server.Start()); + + // 1) Navigate to A. + EXPECT_TRUE(NavigateToURL( + shell(), https_server.GetURL("a.com", "/back_forward_cache/empty.html"))); + + // Register a service worker. + RegisterServiceWorker(current_frame_host()); + + RenderFrameHostImpl* rfh_a = current_frame_host(); + RenderFrameDeletedObserver deleted(rfh_a); + + // 2) Navigate away. + shell()->LoadURL(https_server.GetURL("b.com", "/title1.html")); + + EXPECT_FALSE(rfh_a->is_in_back_forward_cache()); + // The page is controlled by a service worker, so it shouldn't have been + // cached. + deleted.WaitUntilDeleted(); +} + +class BackForwardCacheBrowserTestWithServiceWorkerEnabled + : public BackForwardCacheBrowserTest { + public: + BackForwardCacheBrowserTestWithServiceWorkerEnabled() {} + ~BackForwardCacheBrowserTestWithServiceWorkerEnabled() override {} + + protected: + std::vector<base::Feature> FeaturesToEnable() override { + std::vector<base::Feature> result = + BackForwardCacheBrowserTest::FeaturesToEnable(); + result.push_back(kBackForwardCacheWithServiceWorker); + return result; + } +}; + +IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTestWithServiceWorkerEnabled, + CachedPagesWithServiceWorkers) { + net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_server.AddDefaultHandlers(GetTestDataFilePath()); + https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); + SetupCrossSiteRedirector(&https_server); + ASSERT_TRUE(https_server.Start()); + + // 1) Navigate to A. + EXPECT_TRUE(NavigateToURL( + shell(), https_server.GetURL("a.com", "/back_forward_cache/empty.html"))); + + // Register a service worker. + RegisterServiceWorker(current_frame_host()); + + RenderFrameHostImpl* rfh_a = current_frame_host(); + RenderFrameDeletedObserver deleted(rfh_a); + + // 2) Navigate away. + EXPECT_TRUE( + NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html"))); + + EXPECT_FALSE(deleted.deleted()); + EXPECT_TRUE(rfh_a->is_in_back_forward_cache()); + + // 3) Go back to A. The navigation should be served from the cache. + web_contents()->GetController().GoBack(); + EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); + EXPECT_FALSE(deleted.deleted()); + EXPECT_EQ(rfh_a, current_frame_host()); +} + } // namespace content
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 226caa0..6b64a0b 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -7,6 +7,7 @@ #include "content/browser/background_fetch/background_fetch_service_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" +#include "content/browser/screen_enumeration/screen_enumeration_impl.h" #include "content/browser/service_worker/service_worker_provider_host.h" #include "content/browser/worker_host/dedicated_worker_host.h" #include "content/browser/worker_host/shared_worker_host.h" @@ -31,6 +32,9 @@ map->Add<blink::mojom::IdleManager>(base::BindRepeating( &RenderFrameHostImpl::GetIdleManager, base::Unretained(host))); + + map->Add<blink::mojom::ScreenEnumeration>( + base::BindRepeating(&ScreenEnumerationImpl::Create)); } void PopulateBinderMapWithContext( @@ -63,6 +67,8 @@ &DedicatedWorkerHost::BindFileSystemManager, base::Unretained(host))); map->Add<blink::mojom::IdleManager>(base::BindRepeating( &DedicatedWorkerHost::CreateIdleManager, base::Unretained(host))); + map->Add<blink::mojom::ScreenEnumeration>( + base::BindRepeating(&ScreenEnumerationImpl::Create)); } void PopulateBinderMapWithContext( @@ -86,6 +92,8 @@ // |SharedWorkerHost::broker_|. map->Add<blink::mojom::AppCacheBackend>(base::BindRepeating( &SharedWorkerHost::CreateAppCacheBackend, base::Unretained(host))); + map->Add<blink::mojom::ScreenEnumeration>( + base::BindRepeating(&ScreenEnumerationImpl::Create)); } void PopulateBinderMapWithContext( @@ -114,6 +122,8 @@ void PopulateServiceWorkerBinders(ServiceWorkerProviderHost* host, service_manager::BinderMap* map) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + map->Add<blink::mojom::ScreenEnumeration>( + base::BindRepeating(&ScreenEnumerationImpl::Create)); } void PopulateBinderMapWithContext(
diff --git a/content/browser/frame_host/back_forward_cache.cc b/content/browser/frame_host/back_forward_cache.cc index 27009242..c226015 100644 --- a/content/browser/frame_host/back_forward_cache.cc +++ b/content/browser/frame_host/back_forward_cache.cc
@@ -29,31 +29,6 @@ return 1 << static_cast<uint32_t>(feature); } -// TODO(lowell): Finalize disallowed feature list, and test for each disallowed -// feature. -constexpr uint64_t kDisallowedFeatures = - ToFeatureBit(WebSchedulerTrackedFeature::kWebRTC) | - ToFeatureBit(WebSchedulerTrackedFeature::kContainsPlugins) | - ToFeatureBit(WebSchedulerTrackedFeature::kDedicatedWorkerOrWorklet) | - ToFeatureBit(WebSchedulerTrackedFeature::kServiceWorkerControlledPage) | - ToFeatureBit(WebSchedulerTrackedFeature::kOutstandingIndexedDBTransaction) | - ToFeatureBit( - WebSchedulerTrackedFeature::kHasScriptableFramesInMultipleTabs) | - ToFeatureBit(WebSchedulerTrackedFeature::kRequestedGeolocationPermission) | - ToFeatureBit( - WebSchedulerTrackedFeature::kRequestedNotificationsPermission) | - ToFeatureBit(WebSchedulerTrackedFeature::kRequestedMIDIPermission) | - ToFeatureBit(WebSchedulerTrackedFeature::kRequestedAudioCapturePermission) | - ToFeatureBit(WebSchedulerTrackedFeature::kRequestedVideoCapturePermission) | - ToFeatureBit(WebSchedulerTrackedFeature::kRequestedSensorsPermission) | - ToFeatureBit( - WebSchedulerTrackedFeature::kRequestedBackgroundWorkPermission) | - ToFeatureBit(WebSchedulerTrackedFeature::kBroadcastChannel) | - ToFeatureBit(WebSchedulerTrackedFeature::kIndexedDBConnection) | - ToFeatureBit(WebSchedulerTrackedFeature::kWebGL) | - ToFeatureBit(WebSchedulerTrackedFeature::kWebVR) | - ToFeatureBit(WebSchedulerTrackedFeature::kWebXR); - void SetPageFrozenImpl( RenderFrameHostImpl* render_frame_host, bool frozen, @@ -85,7 +60,8 @@ // Recursively checks whether this RenderFrameHost and all child frames // can be cached. -bool CanStoreRenderFrameHost(RenderFrameHostImpl* rfh) { +bool CanStoreRenderFrameHost(RenderFrameHostImpl* rfh, + uint64_t disallowed_features) { // For the main frame, we don't check loading at the FrameTreeNode level, // because the FrameTreeNode has already begun loading the page being // navigated to. @@ -106,11 +82,12 @@ // One solution could be to listen for changes to scheduler_tracked_features // and if we see a frame in bfcache starting to use something forbidden, evict // it from the bfcache. - if (kDisallowedFeatures & rfh->scheduler_tracked_features()) + if (disallowed_features & rfh->scheduler_tracked_features()) return false; for (size_t i = 0; i < rfh->child_count(); i++) { - if (!CanStoreRenderFrameHost(rfh->child_at(i)->current_frame_host())) { + if (!CanStoreRenderFrameHost(rfh->child_at(i)->current_frame_host(), + disallowed_features)) { return false; } } @@ -118,8 +95,49 @@ return true; } +uint64_t GetDisallowedFeatures() { + // TODO(lowell): Finalize disallowed feature list, and test for each + // disallowed feature. + constexpr uint64_t kAlwaysDisallowedFeatures = + ToFeatureBit(WebSchedulerTrackedFeature::kWebRTC) | + ToFeatureBit(WebSchedulerTrackedFeature::kContainsPlugins) | + ToFeatureBit(WebSchedulerTrackedFeature::kDedicatedWorkerOrWorklet) | + ToFeatureBit( + WebSchedulerTrackedFeature::kOutstandingIndexedDBTransaction) | + ToFeatureBit( + WebSchedulerTrackedFeature::kHasScriptableFramesInMultipleTabs) | + ToFeatureBit( + WebSchedulerTrackedFeature::kRequestedGeolocationPermission) | + ToFeatureBit( + WebSchedulerTrackedFeature::kRequestedNotificationsPermission) | + ToFeatureBit(WebSchedulerTrackedFeature::kRequestedMIDIPermission) | + ToFeatureBit( + WebSchedulerTrackedFeature::kRequestedAudioCapturePermission) | + ToFeatureBit( + WebSchedulerTrackedFeature::kRequestedVideoCapturePermission) | + ToFeatureBit(WebSchedulerTrackedFeature::kRequestedSensorsPermission) | + ToFeatureBit( + WebSchedulerTrackedFeature::kRequestedBackgroundWorkPermission) | + ToFeatureBit(WebSchedulerTrackedFeature::kBroadcastChannel) | + ToFeatureBit(WebSchedulerTrackedFeature::kIndexedDBConnection) | + ToFeatureBit(WebSchedulerTrackedFeature::kWebGL) | + ToFeatureBit(WebSchedulerTrackedFeature::kWebVR) | + ToFeatureBit(WebSchedulerTrackedFeature::kWebXR); + + uint64_t result = kAlwaysDisallowedFeatures; + + if (!base::FeatureList::IsEnabled(kBackForwardCacheWithServiceWorker)) { + result |= + ToFeatureBit(WebSchedulerTrackedFeature::kServiceWorkerControlledPage); + } + return result; +} + } // namespace +const base::Feature kBackForwardCacheWithServiceWorker = { + "BackForwardCacheWithServiceWorker", base::FEATURE_DISABLED_BY_DEFAULT}; + BackForwardCache::BackForwardCache() = default; BackForwardCache::~BackForwardCache() = default; @@ -144,11 +162,16 @@ return false; // Only store documents that have successful http status code. - // Note that for non-http navigations, |last_http_status_code| is equal to 0. + // Note that for error pages, |last_http_status_code| is equal to 0. if (rfh->last_http_status_code() != net::HTTP_OK) return false; - return CanStoreRenderFrameHost(rfh); + // Do store main document with non HTTP/HTTPS URL scheme. In particular, this + // excludes the new tab page. + if (!rfh->GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) + return false; + + return CanStoreRenderFrameHost(rfh, GetDisallowedFeatures()); } void BackForwardCache::StoreDocument(std::unique_ptr<RenderFrameHostImpl> rfh) {
diff --git a/content/browser/frame_host/back_forward_cache.h b/content/browser/frame_host/back_forward_cache.h index ea572d6..28f0ba6 100644 --- a/content/browser/frame_host/back_forward_cache.h +++ b/content/browser/frame_host/back_forward_cache.h
@@ -8,6 +8,7 @@ #include <list> #include <memory> +#include "base/feature_list.h" #include "base/macros.h" #include "content/common/content_export.h" @@ -85,6 +86,13 @@ DISALLOW_COPY_AND_ASSIGN(BackForwardCache); }; + +// TODO(crbug.com/991082): We need to implement frozen frame enumeration +// before we can properly support pages with ServiceWorker in back-forward +// cache. This flag allows to bypass this restriction for local testing. +// Remove after ServiceWorker support is implemented. +CONTENT_EXPORT extern const base::Feature kBackForwardCacheWithServiceWorker; + } // namespace content #endif // CONTENT_BROWSER_FRAME_HOST_BACK_FORWARD_CACHE_H_
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 0122a4a39..ee76a8b 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -597,7 +597,7 @@ frame_tree_node, std::move(common_params), std::move(navigation_params), std::move(commit_params), browser_initiated, false /* from_begin_navigation */, false /* is_for_commit */, frame_entry, - entry, std::move(navigation_ui_data), nullptr, nullptr, + entry, std::move(navigation_ui_data), nullptr, mojo::NullRemote(), rfh_restored_from_back_forward_cache)); if (frame_entry) { @@ -632,7 +632,7 @@ bool override_user_agent, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache) { // Only normal navigations to a different document or reloads are expected. @@ -758,8 +758,7 @@ false /* from_begin_navigation */, true /* is_for_commit */, entry ? entry->GetFrameEntry(frame_tree_node) : nullptr, entry, nullptr /* navigation_ui_data */, - mojom::NavigationClientAssociatedPtrInfo(), - blink::mojom::NavigationInitiatorPtr(), + mojom::NavigationClientAssociatedPtrInfo(), mojo::NullRemote(), nullptr /* rfh_restored_from_back_forward_cache */)); // Update the state of the NavigationRequest to match the fact that the @@ -783,7 +782,7 @@ NavigationEntryImpl* entry, std::unique_ptr<NavigationUIData> navigation_ui_data, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, RenderFrameHostImpl* rfh_restored_from_back_forward_cache) : frame_tree_node_(frame_tree_node), common_params_(std::move(common_params)),
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 2de927f..b806051 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -30,6 +30,7 @@ #include "content/public/browser/navigation_type.h" #include "content/public/browser/render_process_host_observer.h" #include "content/public/common/previews_state.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/proxy_server.h" #include "services/network/public/cpp/origin_policy.h" @@ -156,7 +157,8 @@ bool override_user_agent, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache); @@ -547,7 +549,8 @@ NavigationEntryImpl* navitation_entry, std::unique_ptr<NavigationUIData> navigation_ui_data, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator, RenderFrameHostImpl* rfh_restored_from_back_forward_cache); // NavigationURLLoaderDelegate implementation.
diff --git a/content/browser/frame_host/navigator.cc b/content/browser/frame_host/navigator.cc index ee699208..b1006648 100644 --- a/content/browser/frame_host/navigator.cc +++ b/content/browser/frame_host/navigator.cc
@@ -33,7 +33,7 @@ mojom::BeginNavigationParamsPtr begin_params, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache) {}
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h index dbf67691..cea80e7 100644 --- a/content/browser/frame_host/navigator.h +++ b/content/browser/frame_host/navigator.h
@@ -13,6 +13,7 @@ #include "content/common/content_export.h" #include "content/common/navigation_params.mojom.h" #include "content/public/browser/navigation_controller.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/web/web_triggering_event_info.h" #include "ui/base/window_open_disposition.h" @@ -150,7 +151,8 @@ mojom::BeginNavigationParamsPtr begin_params, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache);
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index 7c2f729..a781313e 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -619,7 +619,7 @@ mojom::BeginNavigationParamsPtr begin_params, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache) { // TODO(clamy): the url sent by the renderer should be validated with
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h index e8069bdc..b941c0c 100644 --- a/content/browser/frame_host/navigator_impl.h +++ b/content/browser/frame_host/navigator_impl.h
@@ -16,6 +16,7 @@ #include "content/common/navigation_params.h" #include "content/common/navigation_params.mojom.h" #include "content/public/common/previews_state.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "url/gurl.h" class GURL; @@ -97,7 +98,8 @@ mojom::BeginNavigationParamsPtr begin_params, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator, + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache) override; void RestartNavigationAsCrossDocument(
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index c5434f3..ab46d4ee 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -180,7 +180,6 @@ #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/data_pipe.h" -#include "net/base/features.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "services/device/public/cpp/device_features.h" #include "services/device/public/mojom/sensor_provider.mojom.h" @@ -542,14 +541,15 @@ mojom::BeginNavigationParamsPtr begin_navigation_params; scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory; mojom::NavigationClientAssociatedPtrInfo navigation_client; - blink::mojom::NavigationInitiatorPtr navigation_initiator; + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator; PendingNavigation( mojom::CommonNavigationParamsPtr common_params, mojom::BeginNavigationParamsPtr begin_navigation_params, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator); + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator); }; PendingNavigation::PendingNavigation( @@ -557,7 +557,7 @@ mojom::BeginNavigationParamsPtr begin_navigation_params, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator) + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator) : common_params(std::move(common_params)), begin_navigation_params(std::move(begin_navigation_params)), blob_url_loader_factory(std::move(blob_url_loader_factory)), @@ -3890,7 +3890,7 @@ std::unique_ptr<blink::URLLoaderFactoryBundleInfo> RenderFrameHostImpl::CreateCrossOriginPrefetchLoaderFactoryBundle() { DCHECK(base::FeatureList::IsEnabled( - net::features::kSplitCacheByNetworkIsolationKey)); + network::features::kPrefetchMainResourceNetworkIsolationKey)); mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory; bool bypass_redirect_checks = false; // Passing a nullopt NetworkIsolationKey ensures the factory is not @@ -4152,7 +4152,8 @@ mojom::BeginNavigationParamsPtr begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator) { + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator) { if (frame_tree_node_->render_manager()->is_attaching_inner_delegate()) { // Avoid starting any new navigations since this frame is in the process of // attaching an inner delegate. @@ -5492,13 +5493,10 @@ associated_registry_->AddInterface( base::BindRepeating(make_binding, base::Unretained(this))); - // TODO(crbug.com/955171): This shim is necessary due to the Mojo change from - // AssociatedInterfaceRequest to PendingAssociatedReceiver. It can be - // simplified once that is complete. associated_registry_->AddInterface(base::BindRepeating( [](RenderFrameHostImpl* self, - mojo::AssociatedInterfaceRequest<blink::mojom::PortalHost> request) { - Portal::BindPortalHostReceiver(self, std::move(request)); + mojo::PendingAssociatedReceiver<blink::mojom::PortalHost> receiver) { + Portal::BindPortalHostReceiver(self, std::move(receiver)); }, base::Unretained(this)));
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 9e031023..fc2a6ab 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -59,6 +59,7 @@ #include "media/mojo/mojom/interface_factory.mojom.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/network_isolation_key.h" @@ -1056,6 +1057,10 @@ std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CreateCrossOriginPrefetchLoaderFactoryBundle(); + const AppCacheNavigationHandle* GetAppCacheNavigationHandle() const { + return appcache_handle_.get(); + } + protected: friend class RenderFrameHostFactory; @@ -1322,7 +1327,8 @@ mojom::BeginNavigationParamsPtr begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator) override; + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator) override; void SubresourceResponseStarted(const GURL& url, net::CertStatus cert_status) override; void ResourceLoadComplete(
diff --git a/content/browser/initiator_csp_context.cc b/content/browser/initiator_csp_context.cc index 2529f9e..4e3b56a 100644 --- a/content/browser/initiator_csp_context.cc +++ b/content/browser/initiator_csp_context.cc
@@ -9,9 +9,9 @@ InitiatorCSPContext::InitiatorCSPContext( const std::vector<ContentSecurityPolicy>& policies, base::Optional<CSPSource>& self_source, - blink::mojom::NavigationInitiatorPtr navigation_initiator) + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator) : reporting_render_frame_host_impl_(nullptr), - initiator_ptr(std::move(navigation_initiator)) { + initiator(std::move(navigation_initiator)) { for (const auto& policy : policies) AddContentSecurityPolicy(policy); @@ -28,8 +28,8 @@ void InitiatorCSPContext::ReportContentSecurityPolicyViolation( const CSPViolationParams& violation_params) { - if (initiator_ptr.is_bound()) { - initiator_ptr->SendViolationReport(blink::mojom::CSPViolationParams::New( + if (initiator) { + initiator->SendViolationReport(blink::mojom::CSPViolationParams::New( violation_params.directive, violation_params.effective_directive, violation_params.console_message, violation_params.blocked_url.spec(), violation_params.report_endpoints, violation_params.use_reporting_api,
diff --git a/content/browser/initiator_csp_context.h b/content/browser/initiator_csp_context.h index 097e228..59237b7 100644 --- a/content/browser/initiator_csp_context.h +++ b/content/browser/initiator_csp_context.h
@@ -8,6 +8,8 @@ #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/common/content_security_policy/csp_context.h" #include "content/common/navigation_params.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" namespace content { @@ -20,10 +22,10 @@ // `navigate-to` and `form-action` (in the case of form submissions). class InitiatorCSPContext : public CSPContext { public: - InitiatorCSPContext( - const std::vector<ContentSecurityPolicy>& policies, - base::Optional<CSPSource>& self_source, - blink::mojom::NavigationInitiatorPtr navigation_initiator); + InitiatorCSPContext(const std::vector<ContentSecurityPolicy>& policies, + base::Optional<CSPSource>& self_source, + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator); ~InitiatorCSPContext() override; void ReportContentSecurityPolicyViolation( @@ -38,7 +40,7 @@ private: RenderFrameHostImpl* reporting_render_frame_host_impl_; - blink::mojom::NavigationInitiatorPtr initiator_ptr; + mojo::Remote<blink::mojom::NavigationInitiator> initiator; DISALLOW_COPY_AND_ASSIGN(InitiatorCSPContext); };
diff --git a/content/browser/loader/prefetch_browsertest.cc b/content/browser/loader/prefetch_browsertest.cc index d3b8143..739a50b5 100644 --- a/content/browser/loader/prefetch_browsertest.cc +++ b/content/browser/loader/prefetch_browsertest.cc
@@ -46,9 +46,13 @@ if (split_cache_enabled_) { enable_features.push_back( net::features::kSplitCacheByNetworkIsolationKey); + enable_features.push_back( + network::features::kPrefetchMainResourceNetworkIsolationKey); } else { disabled_features.push_back( net::features::kSplitCacheByNetworkIsolationKey); + disabled_features.push_back( + network::features::kPrefetchMainResourceNetworkIsolationKey); } feature_list_.InitWithFeatures(enable_features, disabled_features); @@ -597,6 +601,11 @@ auto preload_request_counter = RequestCounter::CreateAndMonitor( cross_origin_server_.get(), preload_path, &preload_waiter); RegisterRequestHandler(cross_origin_server_.get()); + base::RunLoop preload_waiter_second_request; + auto preload_request_counter_second_request = + RequestCounter::CreateAndMonitor(cross_origin_server_.get(), preload_path, + &preload_waiter_second_request); + ASSERT_TRUE(cross_origin_server_->Start()); const GURL cross_origin_target_url = @@ -619,7 +628,47 @@ EXPECT_EQ(1, preload_request_counter->GetRequestCount()); EXPECT_EQ(1, GetPrefetchURLLoaderCallCount()); - WaitUntilLoaded(cross_origin_server_->GetURL(preload_path)); + GURL cross_origin_preload_url = cross_origin_server_->GetURL(preload_path); + WaitUntilLoaded(cross_origin_preload_url); + + // When SplitCache is enabled and the prefetch resource and its headers are + // fetched with a modified NetworkIsolationKey, the preload header resource + // must not be reusable by any other origin but its parent prefetch's. + // TODO(crbug.com/910708): When SplitCache is enabled by default, get rid of + // the below conditional. + if (split_cache_enabled_) { + // Spin up another server, hosting a page with a preload header identical to + // the one in |target_path|. + const char* reuse_preload_attempt_path = "/reuse.html"; + RegisterResponse( + reuse_preload_attempt_path, + ResponseEntry( + base::StringPrintf("<head><title>Other site</title><script " + "src='%s'></script></head>", + cross_origin_preload_url.spec().c_str()), + "text/html", + {{"link", + base::StringPrintf("<%s>;rel=\"preload\";as=\"script\"", + cross_origin_preload_url.spec().c_str())}, + {"access-control-allow-origin", "*"}})); + std::unique_ptr<net::EmbeddedTestServer> other_cross_origin_server = + std::make_unique<net::EmbeddedTestServer>( + net::EmbeddedTestServer::TYPE_HTTPS); + RegisterRequestHandler(other_cross_origin_server.get()); + + ASSERT_TRUE(other_cross_origin_server->Start()); + + // Navigate to a page on the above-created server. A request for the same + // preload header fetched earlier must not be reusable, and must hit the + // network. + EXPECT_TRUE(NavigateToURL(shell(), other_cross_origin_server->GetURL( + reuse_preload_attempt_path))); + preload_waiter_second_request.Run(); + EXPECT_EQ(2, preload_request_counter_second_request->GetRequestCount()); + + // We won't need this server again. + EXPECT_TRUE(other_cross_origin_server->ShutdownAndWaitUntilComplete()); + } // Shutdown the servers. EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
diff --git a/content/browser/loader/prefetch_url_loader.cc b/content/browser/loader/prefetch_url_loader.cc index c20f51a..269945e 100644 --- a/content/browser/loader/prefetch_url_loader.cc +++ b/content/browser/loader/prefetch_url_loader.cc
@@ -13,8 +13,6 @@ #include "content/browser/web_package/signed_exchange_prefetch_metric_recorder.h" #include "content/browser/web_package/signed_exchange_utils.h" #include "content/public/common/content_features.h" -#include "net/base/features.h" -#include "net/base/load_flags.h" #include "services/network/loader_util.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc index c5d0f46..3cb3acd 100644 --- a/content/browser/loader/prefetch_url_loader_service.cc +++ b/content/browser/loader/prefetch_url_loader_service.cc
@@ -17,7 +17,6 @@ #include "content/public/common/content_client.h" #include "content/public/common/resource_type.h" #include "mojo/public/cpp/bindings/strong_binding.h" -#include "net/base/features.h" #include "net/base/load_flags.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -218,7 +217,7 @@ void PrefetchURLLoaderService::EnsureCrossOriginFactory() { DCHECK(base::FeatureList::IsEnabled( - net::features::kSplitCacheByNetworkIsolationKey)); + network::features::kPrefetchMainResourceNetworkIsolationKey)); auto& current_context = *loader_factory_receivers_.current_context(); // If the factory has already been created, don't re-create it. if (current_context.cross_origin_factory)
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index 801b21e6..ceeb63b4 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -55,6 +55,7 @@ #include "content/test/content_browser_test_utils_internal.h" #include "content/test/did_commit_navigation_interceptor.h" #include "ipc/ipc_security_test_util.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/features.h" #include "net/base/filename_util.h" #include "net/base/load_flags.h" @@ -741,11 +742,11 @@ mojo::MakeRequestAssociatedWithDedicatedPipe(&navigation_client); rfh->frame_host_binding_for_testing().impl()->BeginNavigation( std::move(common_params), std::move(begin_params), mojo::NullRemote(), - navigation_client.PassInterface(), nullptr); + navigation_client.PassInterface(), mojo::NullRemote()); } else { rfh->frame_host_binding_for_testing().impl()->BeginNavigation( std::move(common_params), std::move(begin_params), mojo::NullRemote(), - nullptr, nullptr); + nullptr, mojo::NullRemote()); } EXPECT_EQ(bad_message::RFH_BASE_URL_FOR_DATA_URL_SPECIFIED, process_kill_waiter.Wait());
diff --git a/content/browser/network_context_client_base_impl.cc b/content/browser/network_context_client_base_impl.cc index 8d4c408c..e77169d 100644 --- a/content/browser/network_context_client_base_impl.cc +++ b/content/browser/network_context_client_base_impl.cc
@@ -11,6 +11,7 @@ #include "build/build_config.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/public/browser/network_context_client_base.h" +#include "mojo/public/cpp/bindings/remote.h" #if defined(OS_ANDROID) #include "base/android/content_uri_utils.h" @@ -89,8 +90,11 @@ bool first_auth_attempt, const net::AuthChallengeInfo& auth_info, network::mojom::URLResponseHeadPtr head, - network::mojom::AuthChallengeResponderPtr auth_challenge_responder) { - std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt); + mojo::PendingRemote<network::mojom::AuthChallengeResponder> + auth_challenge_responder) { + mojo::Remote<network::mojom::AuthChallengeResponder> + auth_challenge_responder_remote(std::move(auth_challenge_responder)); + auth_challenge_responder_remote->OnAuthCredentials(base::nullopt); } void NetworkContextClientBase::OnCertificateRequested(
diff --git a/content/browser/renderer_host/plugin_registry_impl.cc b/content/browser/renderer_host/plugin_registry_impl.cc index e50aa09c..a6d6188f 100644 --- a/content/browser/renderer_host/plugin_registry_impl.cc +++ b/content/browser/renderer_host/plugin_registry_impl.cc
@@ -23,8 +23,9 @@ PluginRegistryImpl::~PluginRegistryImpl() {} -void PluginRegistryImpl::Bind(blink::mojom::PluginRegistryRequest request) { - bindings_.AddBinding(this, std::move(request)); +void PluginRegistryImpl::Bind( + mojo::PendingReceiver<blink::mojom::PluginRegistry> receiver) { + receivers_.Add(this, std::move(receiver)); } void PluginRegistryImpl::GetPlugins(bool refresh,
diff --git a/content/browser/renderer_host/plugin_registry_impl.h b/content/browser/renderer_host/plugin_registry_impl.h index 499ab2a..632ae86 100644 --- a/content/browser/renderer_host/plugin_registry_impl.h +++ b/content/browser/renderer_host/plugin_registry_impl.h
@@ -7,7 +7,8 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "third_party/blink/public/mojom/plugins/plugin_registry.mojom.h" namespace content { @@ -19,7 +20,7 @@ explicit PluginRegistryImpl(int render_process_id); ~PluginRegistryImpl() override; - void Bind(blink::mojom::PluginRegistryRequest request); + void Bind(mojo::PendingReceiver<blink::mojom::PluginRegistry> receiver); // blink::mojom::PluginRegistry void GetPlugins(bool refresh, @@ -32,7 +33,7 @@ const std::vector<WebPluginInfo>& all_plugins); int render_process_id_; - mojo::BindingSet<PluginRegistry> bindings_; + mojo::ReceiverSet<PluginRegistry> receivers_; base::TimeTicks last_plugin_refresh_time_; base::WeakPtrFactory<PluginRegistryImpl> weak_factory_{this}; };
diff --git a/content/browser/screen_enumeration/OWNERS b/content/browser/screen_enumeration/OWNERS new file mode 100644 index 0000000..adc726c --- /dev/null +++ b/content/browser/screen_enumeration/OWNERS
@@ -0,0 +1,5 @@ +msw@chromium.org +staphany@chromium.org + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage \ No newline at end of file
diff --git a/content/browser/screen_enumeration/screen_enumeration_impl.cc b/content/browser/screen_enumeration/screen_enumeration_impl.cc new file mode 100644 index 0000000..82840c1 --- /dev/null +++ b/content/browser/screen_enumeration/screen_enumeration_impl.cc
@@ -0,0 +1,53 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/screen_enumeration/screen_enumeration_impl.h" + +#include <memory> + +#include "content/public/browser/render_frame_host.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "url/origin.h" + +namespace content { + +// static +void ScreenEnumerationImpl::Create( + mojo::PendingReceiver<blink::mojom::ScreenEnumeration> receiver) { + mojo::MakeSelfOwnedReceiver(std::make_unique<ScreenEnumerationImpl>(), + std::move(receiver)); +} + +ScreenEnumerationImpl::ScreenEnumerationImpl() = default; +ScreenEnumerationImpl::~ScreenEnumerationImpl() = default; + +void ScreenEnumerationImpl::RequestDisplays(RequestDisplaysCallback callback) { + display::Screen* screen = display::Screen::GetScreen(); + std::vector<display::Display> displays = screen->GetAllDisplays(); + int64_t primary_id = screen->GetPrimaryDisplay().id(); + + std::vector<blink::mojom::DisplayPtr> result; + for (const display::Display& display : displays) { + const gfx::Rect& bounds = display.bounds(); + auto mojo_display = blink::mojom::Display::New(); + // TODO(staphany): Get actual display name instead of hardcoded value. + mojo_display->name = "Generic Display"; + mojo_display->scale_factor = display.device_scale_factor(); + mojo_display->width = bounds.width(); + mojo_display->height = bounds.height(); + mojo_display->left = bounds.x(); + mojo_display->top = bounds.y(); + mojo_display->color_depth = display.color_depth(); + mojo_display->is_primary = (display.id() == primary_id); + mojo_display->is_internal = display.IsInternal(); + result.emplace_back(std::move(mojo_display)); + } + // TODO(staphany): Add a permission prompt, and return empty |result| and + // |false| if the permission check fails. + std::move(callback).Run(std::move(result), true); +} + +} // namespace content \ No newline at end of file
diff --git a/content/browser/screen_enumeration/screen_enumeration_impl.h b/content/browser/screen_enumeration/screen_enumeration_impl.h new file mode 100644 index 0000000..a9816a7c --- /dev/null +++ b/content/browser/screen_enumeration/screen_enumeration_impl.h
@@ -0,0 +1,29 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_SCREEN_ENUMERATION_SCREEN_ENUMERATION_IMPL_H_ +#define CONTENT_BROWSER_SCREEN_ENUMERATION_SCREEN_ENUMERATION_IMPL_H_ + +#include "third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom.h" + +namespace content { + +class ScreenEnumerationImpl : public blink::mojom::ScreenEnumeration { + public: + static void Create( + mojo::PendingReceiver<blink::mojom::ScreenEnumeration> receiver); + + ScreenEnumerationImpl(); + ~ScreenEnumerationImpl() override; + + ScreenEnumerationImpl(const ScreenEnumerationImpl&) = delete; + ScreenEnumerationImpl& operator=(const ScreenEnumerationImpl&) = delete; + + // blink::mojom::ScreenEnumeration: + void RequestDisplays(RequestDisplaysCallback callback) override; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SCREEN_ENUMERATION_SCREEN_ENUMERATION_IMPL_H_ \ No newline at end of file
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index f106046..a0d9dc0c 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -52,6 +52,7 @@ #include "content/test/test_content_browser_client.h" #include "ipc/ipc_security_test_util.h" #include "mojo/core/embedder/embedder.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/strong_associated_binding.h" #include "mojo/public/cpp/test_support/test_utils.h" #include "net/base/network_isolation_key.h" @@ -1221,7 +1222,8 @@ mojom::BeginNavigationParamsPtr* begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken>* blob_url_token, mojom::NavigationClientAssociatedPtrInfo* navigation_client, - blink::mojom::NavigationInitiatorPtr* navigation_initiator) override { + mojo::PendingRemote<blink::mojom::NavigationInitiator>* + navigation_initiator) override { if (is_activated_) { (*common_params)->initiator_origin = initiator_to_inject_; is_activated_ = false; @@ -1364,7 +1366,8 @@ mojom::BeginNavigationParamsPtr* begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken>* blob_url_token, mojom::NavigationClientAssociatedPtrInfo* navigation_client, - blink::mojom::NavigationInitiatorPtr* navigation_initiator) override { + mojo::PendingRemote<blink::mojom::NavigationInitiator>* + navigation_initiator) override { if (is_activated_) { (*common_params)->transition = transition_to_inject_; is_activated_ = false;
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index de2ef7c..57cc541d 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -480,6 +480,19 @@ "NetworkError: The service worker navigation preload request failed with " "a network error."; +void CheckPageIsMarkedSecure( + Shell* shell, + scoped_refptr<net::X509Certificate> expected_certificate) { + NavigationEntry* entry = + shell->web_contents()->GetController().GetVisibleEntry(); + EXPECT_TRUE(entry->GetSSL().initialized); + EXPECT_FALSE(!!(entry->GetSSL().content_status & + SSLStatus::DISPLAYED_INSECURE_CONTENT)); + EXPECT_TRUE(expected_certificate->EqualsExcludingChain( + entry->GetSSL().certificate.get())); + EXPECT_FALSE(net::IsCertStatusError(entry->GetSSL().cert_status)); +} + } // namespace class ServiceWorkerBrowserTest : public ContentBrowserTest { @@ -2834,35 +2847,78 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) { StartServerAndNavigateToSetup(); - const char kPageUrl[] = "/service_worker/fetch_event_blob.html"; - const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js"; + const char kPageUrl[] = "/service_worker/in-scope"; + const char kWorkerUrl[] = "/service_worker/worker_script"; + const char kWorkerScript[] = R"( + self.addEventListener('fetch', e => { + e.respondWith(new Response('<title>Title</title>', { + headers: {'Content-Type': 'text/html'} + })); + }); + // Version: %d)"; + + // Register a handler which serves different script on each request. The + // service worker returns a page titled by "Title" via Blob. + int service_worker_served_count = 0; net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); - https_server.ServeFilesFromSourceDirectory(GetTestDataFilePath()); + https_server.RegisterRequestHandler(base::BindLambdaForTesting( + [&](const net::test_server::HttpRequest& request) + -> std::unique_ptr<net::test_server::HttpResponse> { + if (request.relative_url != kWorkerUrl) + return nullptr; + auto response = std::make_unique<net::test_server::BasicHttpResponse>(); + response->set_code(net::HTTP_OK); + response->set_content_type("text/javascript"); + response->set_content( + base::StringPrintf(kWorkerScript, ++service_worker_served_count)); + return response; + })); ASSERT_TRUE(https_server.Start()); - scoped_refptr<WorkerActivatedObserver> observer = - new WorkerActivatedObserver(wrapper()); - observer->Init(); - blink::mojom::ServiceWorkerRegistrationOptions options( - https_server.GetURL(kPageUrl), blink::mojom::ScriptType::kClassic, - blink::mojom::ServiceWorkerUpdateViaCache::kImports); - public_context()->RegisterServiceWorker( - https_server.GetURL(kWorkerUrl), options, - base::BindOnce(&ExpectResultAndRun, true, base::DoNothing())); - observer->Wait(); + // 1st attempt: install a service worker and open the controlled page. + { + // Register a service worker which controls |kPageUrl|. + auto observer = base::MakeRefCounted<WorkerActivatedObserver>(wrapper()); + observer->Init(); + blink::mojom::ServiceWorkerRegistrationOptions options( + https_server.GetURL(kPageUrl), blink::mojom::ScriptType::kClassic, + blink::mojom::ServiceWorkerUpdateViaCache::kImports); + public_context()->RegisterServiceWorker( + https_server.GetURL(kWorkerUrl), options, + base::BindOnce(&ExpectResultAndRun, true, base::DoNothing())); + observer->Wait(); + EXPECT_EQ(1, service_worker_served_count); - const base::string16 title = base::ASCIIToUTF16("Title"); - TitleWatcher title_watcher(shell()->web_contents(), title); - EXPECT_TRUE(NavigateToURL(shell(), https_server.GetURL(kPageUrl))); - EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); - NavigationEntry* entry = - shell()->web_contents()->GetController().GetVisibleEntry(); - EXPECT_TRUE(entry->GetSSL().initialized); - EXPECT_FALSE(!!(entry->GetSSL().content_status & - SSLStatus::DISPLAYED_INSECURE_CONTENT)); - EXPECT_TRUE(https_server.GetCertificate()->EqualsExcludingChain( - entry->GetSSL().certificate.get())); - EXPECT_FALSE(net::IsCertStatusError(entry->GetSSL().cert_status)); + // Wait until the page is appropriately served by the service worker. + const base::string16 title = base::ASCIIToUTF16("Title"); + TitleWatcher title_watcher(shell()->web_contents(), title); + EXPECT_TRUE(NavigateToURL(shell(), https_server.GetURL(kPageUrl))); + EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); + + // The page should be marked as secure. + CheckPageIsMarkedSecure(shell(), https_server.GetCertificate()); + } + + // Navigate away from the page so that the worker has no controllee. + EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank"))); + + // 2nd attempt: update the service worker and open the controlled page again. + { + // Update the service worker. + auto observer = base::MakeRefCounted<WorkerActivatedObserver>(wrapper()); + observer->Init(); + wrapper()->UpdateRegistration(https_server.GetURL(kPageUrl)); + observer->Wait(); + + // Wait until the page is appropriately served by the service worker. + const base::string16 title = base::ASCIIToUTF16("Title"); + TitleWatcher title_watcher(shell()->web_contents(), title); + EXPECT_TRUE(NavigateToURL(shell(), https_server.GetURL(kPageUrl))); + EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); + + // The page should be marked as secure. + CheckPageIsMarkedSecure(shell(), https_server.GetCertificate()); + } shell()->Close();
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker.cc b/content/browser/service_worker/service_worker_single_script_update_checker.cc index f9ca75b..abde435 100644 --- a/content/browser/service_worker/service_worker_single_script_update_checker.cc +++ b/content/browser/service_worker/service_worker_single_script_update_checker.cc
@@ -123,6 +123,7 @@ script_url.spec(), "main_script_url", main_script_url.spec()); + uint32_t options = network::mojom::kURLLoadOptionNone; network::ResourceRequest resource_request; resource_request.url = script_url; resource_request.site_for_cookies = main_script_url; @@ -162,6 +163,11 @@ static_cast<int>(blink::mojom::RequestContextType::SERVICE_WORKER); resource_request.resource_type = static_cast<int>(ResourceType::kServiceWorker); + + // Request SSLInfo. It will be persisted in service worker storage and + // may be used by ServiceWorkerNavigationLoader for navigations handled + // by this service worker. + options |= network::mojom::kURLLoadOptionSendSSLInfoWithResponse; } else { // The "fetch a classic worker-imported script" doesn't have any statement // about mode and credentials mode. Use the default value, which is @@ -219,8 +225,8 @@ network_loader_ = ServiceWorkerUpdatedScriptLoader:: ThrottlingURLLoaderCoreWrapper::CreateLoaderAndStart( loader_factory->Clone(), browser_context_getter, MSG_ROUTING_NONE, - request_id, network::mojom::kURLLoadOptionNone, resource_request, - std::move(network_client), kUpdateCheckTrafficAnnotation); + request_id, options, resource_request, std::move(network_client), + kUpdateCheckTrafficAnnotation); DCHECK_EQ(network_loader_state_, ServiceWorkerUpdatedScriptLoader::LoaderState::kNotStarted); network_loader_state_ =
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc index 76532aa7..e51d6cc 100644 --- a/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc +++ b/content/browser/service_worker/service_worker_single_script_update_checker_unittest.cc
@@ -1163,5 +1163,51 @@ blink::ServiceWorkerStatusCode::kErrorNetwork); } +// The main script needs to request a SSL info so that the navigation handled +// by the service worker can use the SSL info served for the main script. +TEST_F(ServiceWorkerSingleScriptUpdateCheckerTest, RequestSSLInfo) { + auto loader_factory = std::make_unique<network::TestURLLoaderFactory>(); + base::Optional<CheckResult> check_result; + + // Load the main script. It needs a SSL info. + std::unique_ptr<ServiceWorkerSingleScriptUpdateChecker> checker = + CreateSingleScriptUpdateChecker( + kScriptURL, kScriptURL, GURL(kScope), false /* force_bypass_cache */, + blink::mojom::ServiceWorkerUpdateViaCache::kNone, base::TimeDelta(), + std::make_unique<MockServiceWorkerResponseReader>(), + std::make_unique<MockServiceWorkerResponseReader>(), + std::make_unique<MockServiceWorkerResponseWriter>(), + loader_factory.get(), &check_result); + base::RunLoop().RunUntilIdle(); + + { + ASSERT_EQ(1u, loader_factory->pending_requests()->size()); + const network::TestURLLoaderFactory::PendingRequest* pending_request = + loader_factory->GetPendingRequest(0); + EXPECT_EQ(kScriptURL, pending_request->request.url); + EXPECT_EQ(network::mojom::kURLLoadOptionSendSSLInfoWithResponse, + pending_request->options); + } + + // Load imported script. It doesn't need SSL info. + checker = CreateSingleScriptUpdateChecker( + kImportedScriptURL, kScriptURL, GURL(kScope), + false /* force_bypass_cache */, + blink::mojom::ServiceWorkerUpdateViaCache::kNone, base::TimeDelta(), + std::make_unique<MockServiceWorkerResponseReader>(), + std::make_unique<MockServiceWorkerResponseReader>(), + std::make_unique<MockServiceWorkerResponseWriter>(), loader_factory.get(), + &check_result); + base::RunLoop().RunUntilIdle(); + + { + ASSERT_EQ(2u, loader_factory->pending_requests()->size()); + const network::TestURLLoaderFactory::PendingRequest* pending_request = + loader_factory->GetPendingRequest(1); + EXPECT_EQ(kImportedScriptURL, pending_request->request.url); + EXPECT_EQ(network::mojom::kURLLoadOptionNone, pending_request->options); + } +} + } // namespace } // namespace content
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc index d89ce278..f0c566b8 100644 --- a/content/browser/service_worker/service_worker_storage.cc +++ b/content/browser/service_worker/service_worker_storage.cc
@@ -68,9 +68,6 @@ const base::FilePath::CharType kDiskCacheName[] = FILE_PATH_LITERAL("ScriptCache"); -// Taken from AppCache's in-memory cache size. -const int kMaxServiceWorkerStorageMemDiskCacheSize = 10 * 1024 * 1024; - blink::ServiceWorkerStatusCode DatabaseStatusToStatusCode( ServiceWorkerDatabase::Status status) { switch (status) { @@ -1713,9 +1710,7 @@ base::FilePath path = GetDiskCachePath(); if (path.empty()) { - int rv = disk_cache_->InitWithMemBackend( - kMaxServiceWorkerStorageMemDiskCacheSize, - net::CompletionOnceCallback()); + int rv = disk_cache_->InitWithMemBackend(0, net::CompletionOnceCallback()); DCHECK_EQ(net::OK, rv); return disk_cache_.get(); }
diff --git a/content/browser/service_worker/service_worker_updated_script_loader.cc b/content/browser/service_worker/service_worker_updated_script_loader.cc index 1e72f6f..449d74b1 100644 --- a/content/browser/service_worker/service_worker_updated_script_loader.cc +++ b/content/browser/service_worker/service_worker_updated_script_loader.cc
@@ -342,6 +342,13 @@ auto response = ServiceWorkerUtils::CreateResourceResponseHeadAndMetadata( info, options_, request_start_, base::TimeTicks::Now(), response_info->response_data_size); + // Don't pass SSLInfo to the client when the original request doesn't ask + // to send it. + if (response.head.ssl_info.has_value() && + !(options_ & network::mojom::kURLLoadOptionSendSSLInfoWithResponse)) { + response.head.ssl_info.reset(); + } + client_->OnReceiveResponse(std::move(response.head)); if (!response.metadata.empty()) client_->OnReceiveCachedMetadata(std::move(response.metadata));
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index a4e31cf..c3deabb2 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -68,6 +68,7 @@ #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "mojo/public/cpp/bindings/callback_helpers.h" +#include "mojo/public/cpp/bindings/remote.h" #include "net/base/net_errors.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_util.h" @@ -512,7 +513,8 @@ class LoginHandlerDelegate { public: LoginHandlerDelegate( - network::mojom::AuthChallengeResponderPtr auth_challenge_responder, + mojo::PendingRemote<network::mojom::AuthChallengeResponder> + auth_challenge_responder, WebContents::Getter web_contents_getter, const net::AuthChallengeInfo& auth_info, bool is_request_for_main_frame, @@ -533,7 +535,7 @@ first_auth_attempt_(first_auth_attempt), web_contents_getter_(web_contents_getter) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - auth_challenge_responder_.set_connection_error_handler(base::BindOnce( + auth_challenge_responder_.set_disconnect_handler(base::BindOnce( &LoginHandlerDelegate::OnRequestCancelled, base::Unretained(this))); auto continue_after_inteceptor_io = @@ -606,7 +608,8 @@ delete this; } - network::mojom::AuthChallengeResponderPtr auth_challenge_responder_; + mojo::Remote<network::mojom::AuthChallengeResponder> + auth_challenge_responder_; net::AuthChallengeInfo auth_info_; const content::GlobalRequestID request_id_; const uint32_t routing_id_; @@ -629,14 +632,17 @@ bool first_auth_attempt, const net::AuthChallengeInfo& auth_info, network::mojom::URLResponseHeadPtr head, - network::mojom::AuthChallengeResponderPtr auth_challenge_responder, + mojo::PendingRemote<network::mojom::AuthChallengeResponder> + auth_challenge_responder, base::RepeatingCallback<WebContents*(void)> web_contents_getter) { if (!web_contents_getter) { web_contents_getter = base::BindRepeating(GetWebContents, process_id, routing_id); } if (!web_contents_getter.Run()) { - std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt); + mojo::Remote<network::mojom::AuthChallengeResponder> + auth_challenge_responder_remote(std::move(auth_challenge_responder)); + auth_challenge_responder_remote->OnAuthCredentials(base::nullopt); return; } new LoginHandlerDelegate(std::move(auth_challenge_responder), @@ -667,18 +673,23 @@ bool first_auth_attempt, const net::AuthChallengeInfo& auth_info, network::mojom::URLResponseHeadPtr head, - network::mojom::AuthChallengeResponderPtr auth_challenge_responder, + mojo::PendingRemote<network::mojom::AuthChallengeResponder> + auth_challenge_responder, FrameTreeNodeIdRegistry::IsMainFrameGetter is_main_frame_getter) { if (!is_main_frame_getter) { // FrameTreeNode id may already be removed from FrameTreeNodeIdRegistry // due to thread hopping. - std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt); + mojo::Remote<network::mojom::AuthChallengeResponder> + auth_challenge_responder_remote(std::move(auth_challenge_responder)); + auth_challenge_responder_remote->OnAuthCredentials(base::nullopt); return; } base::Optional<bool> is_main_frame_opt = is_main_frame_getter.Run(); // The frame may already be gone due to thread hopping. if (!is_main_frame_opt) { - std::move(auth_challenge_responder)->OnAuthCredentials(base::nullopt); + mojo::Remote<network::mojom::AuthChallengeResponder> + auth_challenge_responder_remote(std::move(auth_challenge_responder)); + auth_challenge_responder_remote->OnAuthCredentials(base::nullopt); return; } @@ -1593,7 +1604,8 @@ bool first_auth_attempt, const net::AuthChallengeInfo& auth_info, network::mojom::URLResponseHeadPtr head, - network::mojom::AuthChallengeResponderPtr auth_challenge_responder) { + mojo::PendingRemote<network::mojom::AuthChallengeResponder> + auth_challenge_responder) { if (window_id) { if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) { OnAuthRequiredContinuationForWindowId(
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 7898ce2e..f8d097ac 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -37,6 +37,7 @@ #include "content/common/content_export.h" #include "content/public/browser/storage_partition.h" #include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -189,16 +190,17 @@ override; // network::mojom::NetworkContextClient interface. - void OnAuthRequired(const base::Optional<base::UnguessableToken>& window_id, - uint32_t process_id, - uint32_t routing_id, - uint32_t request_id, - const GURL& url, - bool first_auth_attempt, - const net::AuthChallengeInfo& auth_info, - network::mojom::URLResponseHeadPtr head, - network::mojom::AuthChallengeResponderPtr - auth_challenge_responder) override; + void OnAuthRequired( + const base::Optional<base::UnguessableToken>& window_id, + uint32_t process_id, + uint32_t routing_id, + uint32_t request_id, + const GURL& url, + bool first_auth_attempt, + const net::AuthChallengeInfo& auth_info, + network::mojom::URLResponseHeadPtr head, + mojo::PendingRemote<network::mojom::AuthChallengeResponder> + auth_challenge_responder) override; void OnCertificateRequested( const base::Optional<base::UnguessableToken>& window_id, uint32_t process_id,
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index 485dc45..5f9cbeb 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -191,8 +191,14 @@ } } - appcache_handle_ = std::make_unique<AppCacheNavigationHandle>( - storage_partition_impl->GetAppCacheService(), worker_process_id_); + // A dedicated worker depends on its nearest ancestor's appcache host. + AppCacheHost* appcache_host = nullptr; + const AppCacheNavigationHandle* appcache_handle = + nearest_ancestor_render_frame_host->GetAppCacheNavigationHandle(); + if (appcache_handle) { + appcache_host = storage_partition_impl->GetAppCacheService()->GetHost( + appcache_handle->appcache_host_id()); + } service_worker_handle_ = std::make_unique<ServiceWorkerNavigationHandle>( storage_partition_impl->GetServiceWorkerContext()); @@ -202,7 +208,8 @@ request_initiator_origin, network_isolation_key_, credentials_mode, std::move(outside_fetch_client_settings_object), ResourceType::kWorker, storage_partition_impl->GetServiceWorkerContext(), - service_worker_handle_.get(), appcache_handle_->host()->GetWeakPtr(), + service_worker_handle_.get(), + appcache_host ? appcache_host->GetWeakPtr() : nullptr, std::move(blob_url_loader_factory), nullptr, storage_partition_impl, storage_domain, base::BindOnce(&DedicatedWorkerHost::DidStartScriptLoad,
diff --git a/content/browser/worker_host/dedicated_worker_host.h b/content/browser/worker_host/dedicated_worker_host.h index ae4b34cc..316cade 100644 --- a/content/browser/worker_host/dedicated_worker_host.h +++ b/content/browser/worker_host/dedicated_worker_host.h
@@ -26,7 +26,6 @@ namespace content { -class AppCacheNavigationHandle; class ServiceWorkerNavigationHandle; class ServiceWorkerObjectHost; @@ -164,7 +163,6 @@ // starting or running. mojo::Remote<blink::mojom::DedicatedWorkerHostFactoryClient> client_; - std::unique_ptr<AppCacheNavigationHandle> appcache_handle_; std::unique_ptr<ServiceWorkerNavigationHandle> service_worker_handle_; service_manager::BinderRegistry registry_;
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index 16c2bda..79660beb 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -417,7 +417,7 @@ BeginNavigationParams begin_params, pending_remote<blink.mojom.BlobURLToken>? blob_url_token, associated NavigationClient? navigation_client, - blink.mojom.NavigationInitiator? navigation_initiator); + pending_remote<blink.mojom.NavigationInitiator>? navigation_initiator); // Sent when a subresource response has started. // |cert_status| is the bitmask of status info of the SSL certificate. (see
diff --git a/content/public/browser/network_context_client_base.h b/content/public/browser/network_context_client_base.h index 47bd3a7..c5e0badd 100644 --- a/content/public/browser/network_context_client_base.h +++ b/content/public/browser/network_context_client_base.h
@@ -21,16 +21,17 @@ ~NetworkContextClientBase() override; // network::mojom::NetworkContextClient implementation: - void OnAuthRequired(const base::Optional<base::UnguessableToken>& window_id, - uint32_t process_id, - uint32_t routing_id, - uint32_t request_id, - const GURL& url, - bool first_auth_attempt, - const net::AuthChallengeInfo& auth_info, - network::mojom::URLResponseHeadPtr head, - network::mojom::AuthChallengeResponderPtr - auth_challenge_responder) override; + void OnAuthRequired( + const base::Optional<base::UnguessableToken>& window_id, + uint32_t process_id, + uint32_t routing_id, + uint32_t request_id, + const GURL& url, + bool first_auth_attempt, + const net::AuthChallengeInfo& auth_info, + network::mojom::URLResponseHeadPtr head, + mojo::PendingRemote<network::mojom::AuthChallengeResponder> + auth_challenge_responder) override; void OnCertificateRequested( const base::Optional<base::UnguessableToken>& window_id, uint32_t process_id,
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 87c4eda4..7717cb0 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -146,6 +146,7 @@ #include "content/renderer/web_ui_extension_data.h" #include "content/renderer/worker/dedicated_worker_host_factory_client.h" #include "crypto/sha2.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/data_url.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" @@ -7277,9 +7278,8 @@ navigation_client_impl_->MarkWasInitiatedInThisFrame(); } - blink::mojom::NavigationInitiatorPtr initiator_ptr( - blink::mojom::NavigationInitiatorPtrInfo( - std::move(info->navigation_initiator_handle), 0)); + mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator( + std::move(info->navigation_initiator_handle), 0); bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownloadWithoutUserActivation(); @@ -7293,7 +7293,7 @@ load_flags, has_download_sandbox_flag, from_ad, is_history_navigation_in_new_child_frame), std::move(begin_navigation_params), std::move(blob_url_token), - std::move(navigation_client_info), std::move(initiator_ptr)); + std::move(navigation_client_info), std::move(navigation_initiator)); } void RenderFrameImpl::DecodeDataURL(
diff --git a/content/test/data/accessibility/display-locking/activatable-activated.html b/content/test/data/accessibility/display-locking/activatable-activated.html index 5a5d97a9..8682b67 100644 --- a/content/test/data/accessibility/display-locking/activatable-activated.html +++ b/content/test/data/accessibility/display-locking/activatable-activated.html
@@ -2,9 +2,9 @@ @BLINK-ALLOW:offscreen --> <div> - <div id="locked" rendersubtree="invisible-activatable"> + <div id="locked" rendersubtree="invisible activatable"> <div>child</div> - <div id="nested" rendersubtree="invisible-activatable">nested locked element!</div> + <div id="nested" rendersubtree="invisible activatable">nested locked element!</div> <div id="nonActivatable" rendersubtree="invisible">nested non activatable locked element</div> </div> </div>
diff --git a/content/test/data/accessibility/display-locking/activatable.html b/content/test/data/accessibility/display-locking/activatable.html index 5aaba61..dca7e48 100644 --- a/content/test/data/accessibility/display-locking/activatable.html +++ b/content/test/data/accessibility/display-locking/activatable.html
@@ -2,9 +2,9 @@ @BLINK-ALLOW:offscreen --> <div> - <div id="locked" rendersubtree="invisible-activatable"> + <div id="locked" rendersubtree="invisible activatable"> <div>child</div> - <div id="nested" rendersubtree="invisible-activatable">nested locked element!</div> + <div id="nested" rendersubtree="invisible activatable">nested locked element!</div> <div id="nonActivatable" rendersubtree="invisible">nested non activatable locked element</div> </div> </div>
diff --git a/content/test/data/accessibility/display-locking/all.html b/content/test/data/accessibility/display-locking/all.html index 39719e7..fc60826 100644 --- a/content/test/data/accessibility/display-locking/all.html +++ b/content/test/data/accessibility/display-locking/all.html
@@ -2,9 +2,9 @@ @BLINK-ALLOW:offscreen --> <div> - <div id="locked" rendersubtree="invisible-activatable"> + <div id="locked" rendersubtree="invisible activatable"> <div>child</div> - <div id="nested" rendersubtree="invisible-activatable">nested locked element!</div> + <div id="nested" rendersubtree="invisible activatable">nested locked element!</div> <div id="nonActivatable" rendersubtree="invisible">nested non activatable locked element</div> <!-- TODO(rakina): Make display:none, visibility:hidden, aria-hidden nodes
diff --git a/content/test/data/back_forward_cache/empty.html b/content/test/data/back_forward_cache/empty.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/back_forward_cache/empty.html
diff --git a/content/test/data/back_forward_cache/service-worker.js b/content/test/data/back_forward_cache/service-worker.js new file mode 100644 index 0000000..0516c24f --- /dev/null +++ b/content/test/data/back_forward_cache/service-worker.js
@@ -0,0 +1,12 @@ +// 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. + +self.addEventListener('install', function(event) { + event.waitUntil(self.skipWaiting()); +}); + +self.addEventListener('activate', function(event) { + event.waitUntil(self.clients.claim()); +}); +
diff --git a/content/test/frame_host_interceptor.cc b/content/test/frame_host_interceptor.cc index a8d42de..f355e5c 100644 --- a/content/test/frame_host_interceptor.cc +++ b/content/test/frame_host_interceptor.cc
@@ -44,7 +44,8 @@ mojom::BeginNavigationParamsPtr begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token, mojom::NavigationClientAssociatedPtrInfo navigation_client, - blink::mojom::NavigationInitiatorPtr navigation_initiator) override { + mojo::PendingRemote<blink::mojom::NavigationInitiator> + navigation_initiator) override { if (interceptor_->WillDispatchBeginNavigation( rfhi_, &common_params, &begin_params, &blob_url_token, &navigation_client, &navigation_initiator)) { @@ -80,7 +81,8 @@ mojom::BeginNavigationParamsPtr* begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken>* blob_url_token, mojom::NavigationClientAssociatedPtrInfo* navigation_client, - blink::mojom::NavigationInitiatorPtr* navigation_initiator) { + mojo::PendingRemote<blink::mojom::NavigationInitiator>* + navigation_initiator) { return true; }
diff --git a/content/test/frame_host_interceptor.h b/content/test/frame_host_interceptor.h index 28c787ba..3aec1e1 100644 --- a/content/test/frame_host_interceptor.h +++ b/content/test/frame_host_interceptor.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "content/common/frame.mojom.h" #include "content/public/browser/web_contents_observer.h" +#include "mojo/public/cpp/bindings/pending_remote.h" namespace content { @@ -46,7 +47,8 @@ mojom::BeginNavigationParamsPtr* begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken>* blob_url_token, mojom::NavigationClientAssociatedPtrInfo* navigation_client, - blink::mojom::NavigationInitiatorPtr* navigation_initiator); + mojo::PendingRemote<blink::mojom::NavigationInitiator>* + navigation_initiator); private: class FrameAgent;
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py index 6dfec37..ecda631 100644 --- a/content/test/gpu/gpu_tests/gpu_helper.py +++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -8,8 +8,8 @@ # This set must be the union of the driver tags used in WebGL and WebGL2 # expectations files. EXPECTATIONS_DRIVER_TAGS = frozenset([ - 'intel_lt_25.20.100.6444', - 'intel_lt_25.20.100.6577', + 'angle_lt_25.20.100.6444', + 'angle_lt_25.20.100.6577', 'mesa_lt_17.1.6', 'mesa_lt_17.3.9', 'mesa_lt_19.1.2'
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 447ab10e..87c9ed4 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
@@ -6,7 +6,7 @@ # nvidia nvidia-0xf02 nvidia-0xfe9 nvidia-0x1cb3 # qualcomm qualcomm-adreno-(tm)-540 ] # tags: [ debug ] -# tags: [ intel_lt_25.20.100.6444 intel_lt_25.20.100.6577 mesa_lt_17.1.6 mesa_lt_17.3.9 mesa_lt_19.1.2 ] +# tags: [ angle_lt_25.20.100.6444 angle_lt_25.20.100.6577 mesa_lt_17.1.6 mesa_lt_17.3.9 mesa_lt_19.1.2 ] # results: [ Failure RetryOnFailure Skip ] @@ -127,21 +127,19 @@ # This case causes no-over-optimization-on-uniform-array fail. crbug.com/884210 [ opengl win passthrough intel ] conformance/ogles/GL/gl_FragCoord/gl_FragCoord_001_to_003.html [ Skip ] -crbug.com/602688 [ opengl win passthrough intel intel_lt_25.20.100.6577 ] conformance/glsl/constructors/glsl-construct-mat2.html [ Failure ] -crbug.com/602688 [ opengl win passthrough intel intel_lt_25.20.100.6577 ] conformance2/textures/misc/texture-npot.html [ Failure ] -# TODO(crbug.com/994852) : Add back driver version tag intel_lt_25.20.100.6577 to these 3 tests -# once it is working again. -crbug.com/854100 [ opengl win passthrough intel ] conformance/glsl/variables/gl-pointcoord.html [ Failure ] -crbug.com/957631 [ opengl win passthrough intel ] conformance2/rendering/element-index-uint.html [ Failure ] -crbug.com/angleproject/2880 [ opengl win passthrough intel ] deqp/functional/gles3/shaderbuiltinvar.html [ Failure ] +crbug.com/602688 [ opengl win passthrough intel angle_lt_25.20.100.6577 ] conformance/glsl/constructors/glsl-construct-mat2.html [ Failure ] +crbug.com/602688 [ opengl win passthrough intel angle_lt_25.20.100.6577 ] conformance2/textures/misc/texture-npot.html [ Failure ] +crbug.com/854100 [ opengl win passthrough intel angle_lt_25.20.100.6577 ] conformance/glsl/variables/gl-pointcoord.html [ Failure ] +crbug.com/957631 [ opengl win passthrough intel angle_lt_25.20.100.6577 ] conformance2/rendering/element-index-uint.html [ Failure ] +crbug.com/angleproject/2880 [ opengl win passthrough intel angle_lt_25.20.100.6577 ] deqp/functional/gles3/shaderbuiltinvar.html [ Failure ] # This is an OpenGL driver bug on Intel platform and it is fixed in # Intel Driver 25.20.100.6444. # Case no-over-optimization-on-uniform-array-08 always fail if run # case gl-min-uniforms first. # Temporarily skip these two cases now. -crbug.com/953243 [ opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/limits/gl-min-uniforms.html [ Skip ] -crbug.com/953243 [ opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-08.html [ Skip ] +crbug.com/953243 [ opengl win passthrough intel angle_lt_25.20.100.6444 ] conformance/limits/gl-min-uniforms.html [ Skip ] +crbug.com/953243 [ opengl win passthrough intel angle_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-08.html [ Skip ] # This is an OpenGL driver bug on Intel platform and it is fixed in # Intel Driver 25.20.100.6444. @@ -149,8 +147,8 @@ # case biuDepthRange_001_to_002 first. # Temporarily skip these two cases now because this issue blocks # WEBGL_video_texture implementation. -crbug.com/907195 [ opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html [ Skip ] -crbug.com/907195 [ opengl win passthrough intel intel_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-09.html [ Skip ] +crbug.com/907195 [ opengl win passthrough intel angle_lt_25.20.100.6444 ] conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html [ Skip ] +crbug.com/907195 [ opengl win passthrough intel angle_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-09.html [ Skip ] # Windows only. crbug.com/736926 [ win ] conformance2/textures/svg_image/tex-2d-rgb565-rgb-unsigned_short_5_6_5.html [ RetryOnFailure ]
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 40355d8..844b170 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
@@ -8,7 +8,7 @@ # tags: [ d3d11 d3d9 no-angle opengl opengles vulkan ] # tags: [ no-passthrough passthrough ] # tags: [ webgl-version-1 ] -# tags: [ intel_lt_25.20.100.6444 mesa_lt_17.1.6 ] +# tags: [ angle_lt_25.20.100.6444 mesa_lt_17.1.6 ] # results: [ Failure RetryOnFailure Skip ] @@ -134,8 +134,8 @@ # case biuDepthRange_001_to_002 first. # Temporarily skip these two cases now because this issue blocks # WEBGL_video_texture implementation. -crbug.com/907195 [ win intel opengl passthrough intel_lt_25.20.100.6444 ] conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html [ Skip ] -crbug.com/907195 [ win intel opengl passthrough intel_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-09.html [ Skip ] +crbug.com/907195 [ win intel opengl passthrough angle_lt_25.20.100.6444 ] conformance/ogles/GL/biuDepthRange/biuDepthRange_001_to_002.html [ Skip ] +crbug.com/907195 [ win intel opengl passthrough angle_lt_25.20.100.6444 ] conformance/uniforms/no-over-optimization-on-uniform-array-09.html [ Skip ] # TODO(kbr): re-enable suppression for same test below once fixed. crbug.com/angleproject/2103 [ win ] conformance/glsl/bugs/sampler-struct-function-arg.html [ Skip ]
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py index d9e3960a..1b1d3f5 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
@@ -475,6 +475,12 @@ driver_vendor = driver_vendor.lower() driver_version = driver_version.lower() + # Extract the string of vendor from 'angle (vendor)' + matcher = re.compile(r'^angle \(([a-z]+)\)$') + match = matcher.match(driver_vendor) + if match: + driver_vendor = match.group(1) + # Extract the substring before first space/dash/underscore matcher = re.compile(r'^([a-z\d]+)([\s\-_]+[a-z\d]+)+$') match = matcher.match(driver_vendor)
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc index 7f2bc25..008c4ea6 100644 --- a/content/test/navigation_simulator_impl.cc +++ b/content/test/navigation_simulator_impl.cc
@@ -24,6 +24,7 @@ #include "content/test/test_navigation_url_loader.h" #include "content/test/test_render_frame_host.h" #include "content/test/test_web_contents.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/load_flags.h" #include "net/url_request/redirect_info.h" @@ -1137,12 +1138,13 @@ .impl() ->BeginNavigation(std::move(common_params), std::move(begin_params), mojo::NullRemote(), - navigation_client_ptr.PassInterface(), nullptr); + navigation_client_ptr.PassInterface(), + mojo::NullRemote()); } else { render_frame_host_->frame_host_binding_for_testing() .impl() ->BeginNavigation(std::move(common_params), std::move(begin_params), - mojo::NullRemote(), nullptr, nullptr); + mojo::NullRemote(), nullptr, mojo::NullRemote()); } NavigationRequest* request =
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc index c6ed542..630388f 100644 --- a/content/test/test_render_frame.cc +++ b/content/test/test_render_frame.cc
@@ -19,6 +19,7 @@ #include "content/public/test/mock_render_thread.h" #include "content/renderer/input/frame_input_handler_impl.h" #include "content/renderer/loader/web_url_loader_impl.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/data_url.h" #include "services/network/public/cpp/resource_response.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" @@ -158,7 +159,7 @@ mojom::BeginNavigationParamsPtr begin_params, mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token, mojom::NavigationClientAssociatedPtrInfo, - blink::mojom::NavigationInitiatorPtr) override {} + mojo::PendingRemote<blink::mojom::NavigationInitiator>) override {} void SubresourceResponseStarted(const GURL& url, net::CertStatus cert_status) override {}
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 226e2b3..7332a204 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -29,6 +29,7 @@ #include "content/test/test_render_view_host.h" #include "content/test/test_render_widget_host.h" #include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" @@ -364,10 +365,10 @@ GetRemoteAssociatedInterfaces()->GetInterface(&navigation_client_ptr); BeginNavigation(std::move(common_params), std::move(begin_params), mojo::NullRemote(), navigation_client_ptr.PassInterface(), - nullptr); + mojo::NullRemote()); } else { BeginNavigation(std::move(common_params), std::move(begin_params), - mojo::NullRemote(), nullptr, nullptr); + mojo::NullRemote(), nullptr, mojo::NullRemote()); } }
diff --git a/dbus/bus.cc b/dbus/bus.cc index 0f50eb9d..5c51d7f7 100644 --- a/dbus/bus.cc +++ b/dbus/bus.cc
@@ -15,9 +15,9 @@ #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/threading/scoped_blocking_call.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/timer/elapsed_timer.h" #include "dbus/exported_object.h" @@ -171,8 +171,8 @@ dbus_threads_init_default(); // The origin message loop is unnecessary if the client uses synchronous // functions only. - if (base::ThreadTaskRunnerHandle::IsSet()) - origin_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + if (base::SequencedTaskRunnerHandle::IsSet()) + origin_task_runner_ = base::SequencedTaskRunnerHandle::Get(); } Bus::~Bus() { @@ -857,7 +857,11 @@ } void Bus::AssertOnOriginThread() { - CHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId()); + if (origin_task_runner_) { + CHECK(origin_task_runner_->RunsTasksInCurrentSequence()); + } else { + CHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId()); + } } void Bus::AssertOnDBusThread() {
diff --git a/dbus/bus.h b/dbus/bus.h index b082110e..63c9c1b 100644 --- a/dbus/bus.h +++ b/dbus/bus.h
@@ -24,7 +24,6 @@ namespace base { class SequencedTaskRunner; -class SingleThreadTaskRunner; class TaskRunner; } @@ -724,8 +723,8 @@ base::WaitableEvent on_shutdown_; DBusConnection* connection_; - scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; base::PlatformThreadId origin_thread_id_; + scoped_refptr<base::SequencedTaskRunner> origin_task_runner_; std::set<std::string> owned_service_names_; // The following sets are used to check if rules/object_paths/filters
diff --git a/extensions/browser/extension_event_histogram_value.h b/extensions/browser/extension_event_histogram_value.h index 0403f0a..359ebe6 100644 --- a/extensions/browser/extension_event_histogram_value.h +++ b/extensions/browser/extension_event_histogram_value.h
@@ -460,6 +460,7 @@ ACTION_ON_CLICKED = 438, ACCESSIBILITY_PRIVATE_ON_SWITCH_ACCESS_COMMAND = 439, ACCESSIBILITY_PRIVATE_FIND_SCROLLABLE_BOUNDS_FOR_POINT = 440, + LOGIN_STATE_ON_SESSION_STATE_CHANGED = 441, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 411decaf6..77c76fc 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1439,6 +1439,8 @@ AUTOTESTPRIVATE_GETALLINSTALLEDAPPS = 1376, AUTOTESTPRIVATE_SWAPWINDOWSINSPLITVIEW = 1377, AUTOTESTPRIVATE_SETARCAPPWINDOWFOCUS = 1378, + LOGINSTATE_GETPROFILETYPE = 1379, + LOGINSTATE_GETSESSIONSTATE = 1380, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/value_store/lazy_leveldb.cc b/extensions/browser/value_store/lazy_leveldb.cc index 8453860..dfa5daa 100644 --- a/extensions/browser/value_store/lazy_leveldb.cc +++ b/extensions/browser/value_store/lazy_leveldb.cc
@@ -85,7 +85,7 @@ LazyLevelDb::~LazyLevelDb() = default; ValueStore::Status LazyLevelDb::Read(const std::string& key, - std::unique_ptr<base::Value>* value) { + base::Optional<base::Value>* value) { DCHECK(value); std::string value_as_json; @@ -100,13 +100,13 @@ if (!s.ok()) return ToValueStoreError(s); - std::unique_ptr<base::Value> val = - base::JSONReader().ReadToValueDeprecated(value_as_json); - if (!val) + base::Optional<base::Value> read_value = + base::JSONReader().ReadToValue(value_as_json); + if (!read_value) { return ValueStore::Status(ValueStore::CORRUPTION, FixCorruption(&key), kInvalidJson); - - *value = std::move(val); + } + *value = std::move(read_value); return ValueStore::Status(); }
diff --git a/extensions/browser/value_store/lazy_leveldb.h b/extensions/browser/value_store/lazy_leveldb.h index c0098ae3..2810bd1 100644 --- a/extensions/browser/value_store/lazy_leveldb.h +++ b/extensions/browser/value_store/lazy_leveldb.h
@@ -11,6 +11,8 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/metrics/histogram_base.h" +#include "base/optional.h" +#include "base/values.h" #include "extensions/browser/value_store/value_store.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/src/include/leveldb/db.h" @@ -55,7 +57,7 @@ // be returned and value will be unchanged. Caller must ensure the database is // open before calling this method. ValueStore::Status Read(const std::string& key, - std::unique_ptr<base::Value>* value); + base::Optional<base::Value>* value); // Opens the underlying database if not yet open. If the open fails due to // corruption will attempt to repair the database. Failing that, will attempt
diff --git a/extensions/browser/value_store/leveldb_scoped_database.cc b/extensions/browser/value_store/leveldb_scoped_database.cc index 4dcf307..a87cec1f 100644 --- a/extensions/browser/value_store/leveldb_scoped_database.cc +++ b/extensions/browser/value_store/leveldb_scoped_database.cc
@@ -49,7 +49,7 @@ ValueStore::Status LeveldbScopedDatabase::Read( const std::string& scope, const std::string& key, - std::unique_ptr<base::Value>* value) { + base::Optional<base::Value>* value) { ValueStore::Status status = EnsureDbIsOpen(); if (!status.ok()) return status;
diff --git a/extensions/browser/value_store/leveldb_scoped_database.h b/extensions/browser/value_store/leveldb_scoped_database.h index 46f59943..e2b8b099 100644 --- a/extensions/browser/value_store/leveldb_scoped_database.h +++ b/extensions/browser/value_store/leveldb_scoped_database.h
@@ -46,7 +46,7 @@ // Reads a single |value| from the database for the specified |key|. ValueStore::Status Read(const std::string& scope, const std::string& key, - std::unique_ptr<base::Value>* value); + base::Optional<base::Value>* value); // Reads all |values| from the database stored within the specified |scope|. ValueStore::Status Read(const std::string& scope,
diff --git a/extensions/browser/value_store/leveldb_scoped_database_unittest.cc b/extensions/browser/value_store/leveldb_scoped_database_unittest.cc index e7649e8..7ced8f1 100644 --- a/extensions/browser/value_store/leveldb_scoped_database_unittest.cc +++ b/extensions/browser/value_store/leveldb_scoped_database_unittest.cc
@@ -160,11 +160,11 @@ values.SetString("s1_key1", ""); EXPECT_TRUE(db_->Write("scope1", values).ok()); - std::unique_ptr<base::Value> value; + base::Optional<base::Value> value; ASSERT_TRUE(db_->Read("scope1", "s1_key1", &value).ok()); - std::string str; - EXPECT_TRUE(value->GetAsString(&str)); - EXPECT_EQ(str, ""); + ASSERT_TRUE(value.has_value()); + ASSERT_TRUE(value->is_string()); + EXPECT_EQ(value->GetString(), ""); } TEST_F(LeveldbScopedDatabaseUnitTest, TestValueContainingDelimiter) { @@ -172,11 +172,11 @@ values.SetString("s1_key1", "with:delimiter"); EXPECT_TRUE(db_->Write("scope1", values).ok()); - std::unique_ptr<base::Value> value; + base::Optional<base::Value> value; ASSERT_TRUE(db_->Read("scope1", "s1_key1", &value).ok()); - std::string str; - EXPECT_TRUE(value->GetAsString(&str)); - EXPECT_EQ(str, "with:delimiter"); + ASSERT_TRUE(value.has_value()); + ASSERT_TRUE(value->is_string()); + EXPECT_EQ(value->GetString(), "with:delimiter"); } TEST_F(LeveldbScopedDatabaseUnitTest, TestDeleteValues) {
diff --git a/extensions/browser/value_store/leveldb_value_store.cc b/extensions/browser/value_store/leveldb_value_store.cc index 5f46c96..97a1933 100644 --- a/extensions/browser/value_store/leveldb_value_store.cc +++ b/extensions/browser/value_store/leveldb_value_store.cc
@@ -83,12 +83,12 @@ std::unique_ptr<base::DictionaryValue> settings(new base::DictionaryValue()); for (const std::string& key : keys) { - std::unique_ptr<base::Value> setting; + base::Optional<base::Value> setting; status.Merge(Read(key, &setting)); if (!status.ok()) return ReadResult(std::move(status)); if (setting) - settings->SetWithoutPathExpansion(key, std::move(setting)); + settings->SetKey(key, std::move(*setting)); } return ReadResult(std::move(settings), std::move(status)); @@ -178,13 +178,14 @@ std::unique_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList()); for (const std::string& key : keys) { - std::unique_ptr<base::Value> old_value; + base::Optional<base::Value> old_value; status.Merge(Read(key, &old_value)); if (!status.ok()) return WriteResult(std::move(status)); if (old_value) { - changes->push_back(ValueStoreChange(key, std::move(old_value), nullptr)); + changes->push_back( + ValueStoreChange(key, std::move(old_value), base::nullopt)); batch.Delete(key); } } @@ -210,7 +211,7 @@ std::unique_ptr<base::Value> next_value; whole_db.RemoveWithoutPathExpansion(next_key, &next_value); changes->push_back( - ValueStoreChange(next_key, std::move(next_value), nullptr)); + ValueStoreChange(next_key, std::move(*next_value), base::nullopt)); } DeleteDbFile(); @@ -258,13 +259,13 @@ bool write_new_value = true; if (!(options & NO_GENERATE_CHANGES)) { - std::unique_ptr<base::Value> old_value; + base::Optional<base::Value> old_value; Status status = Read(key, &old_value); if (!status.ok()) return status; - if (!old_value || !old_value->Equals(&value)) { + if (!old_value || *old_value != value) { changes->push_back( - ValueStoreChange(key, std::move(old_value), value.CreateDeepCopy())); + ValueStoreChange(key, std::move(old_value), value.Clone())); } else { write_new_value = false; }
diff --git a/extensions/browser/value_store/testing_value_store.cc b/extensions/browser/value_store/testing_value_store.cc index 72a292c8..052293a 100644 --- a/extensions/browser/value_store/testing_value_store.cc +++ b/extensions/browser/value_store/testing_value_store.cc
@@ -95,8 +95,10 @@ if (!storage_.GetWithoutPathExpansion(it.key(), &old_value) || !old_value->Equals(&it.value())) { changes->push_back(ValueStoreChange( - it.key(), old_value ? old_value->CreateDeepCopy() : nullptr, - it.value().CreateDeepCopy())); + it.key(), + old_value ? base::Optional<base::Value>(old_value->Clone()) + : base::nullopt, + it.value().Clone())); storage_.SetWithoutPathExpansion(it.key(), it.value().CreateDeepCopy()); } } @@ -117,7 +119,8 @@ for (auto it = keys.cbegin(); it != keys.cend(); ++it) { std::unique_ptr<base::Value> old_value; if (storage_.RemoveWithoutPathExpansion(*it, &old_value)) { - changes->push_back(ValueStoreChange(*it, std::move(old_value), nullptr)); + changes->push_back( + ValueStoreChange(*it, std::move(*old_value), base::nullopt)); } } return WriteResult(std::move(changes), CreateStatusCopy(status_));
diff --git a/extensions/browser/value_store/value_store_change.cc b/extensions/browser/value_store/value_store_change.cc index dc5abce..ea6acdd 100644 --- a/extensions/browser/value_store/value_store_change.cc +++ b/extensions/browser/value_store/value_store_change.cc
@@ -12,17 +12,16 @@ // static std::string ValueStoreChange::ToJson( const ValueStoreChangeList& changes) { - base::DictionaryValue changes_value; - for (auto it = changes.cbegin(); it != changes.cend(); ++it) { - std::unique_ptr<base::DictionaryValue> change_value = - std::make_unique<base::DictionaryValue>(); - if (it->old_value()) { - change_value->SetKey("oldValue", it->old_value()->Clone()); + base::Value changes_value(base::Value::Type::DICTIONARY); + for (const auto& change : changes) { + base::Value change_value(base::Value::Type::DICTIONARY); + if (change.old_value()) { + change_value.SetKey("oldValue", change.old_value()->Clone()); } - if (it->new_value()) { - change_value->SetKey("newValue", it->new_value()->Clone()); + if (change.new_value()) { + change_value.SetKey("newValue", change.new_value()->Clone()); } - changes_value.SetWithoutPathExpansion(it->key(), std::move(change_value)); + changes_value.SetKey(change.key(), std::move(change_value)); } std::string json; bool success = base::JSONWriter::Write(changes_value, &json); @@ -31,8 +30,8 @@ } ValueStoreChange::ValueStoreChange(const std::string& key, - std::unique_ptr<base::Value> old_value, - std::unique_ptr<base::Value> new_value) + base::Optional<base::Value> old_value, + base::Optional<base::Value> new_value) : inner_(new Inner(key, std::move(old_value), std::move(new_value))) {} ValueStoreChange::ValueStoreChange(const ValueStoreChange& other) = default; @@ -46,17 +45,17 @@ const base::Value* ValueStoreChange::old_value() const { DCHECK(inner_.get()); - return inner_->old_value_.get(); + return inner_->old_value_ ? &*inner_->old_value_ : nullptr; } const base::Value* ValueStoreChange::new_value() const { DCHECK(inner_.get()); - return inner_->new_value_.get(); + return inner_->new_value_ ? &*inner_->new_value_ : nullptr; } ValueStoreChange::Inner::Inner(const std::string& key, - std::unique_ptr<base::Value> old_value, - std::unique_ptr<base::Value> new_value) + base::Optional<base::Value> old_value, + base::Optional<base::Value> new_value) : key_(key), old_value_(std::move(old_value)), new_value_(std::move(new_value)) {}
diff --git a/extensions/browser/value_store/value_store_change.h b/extensions/browser/value_store/value_store_change.h index 8645b57..0719b38 100644 --- a/extensions/browser/value_store/value_store_change.h +++ b/extensions/browser/value_store/value_store_change.h
@@ -5,11 +5,11 @@ #ifndef EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_CHANGE_H_ #define EXTENSIONS_BROWSER_VALUE_STORE_VALUE_STORE_CHANGE_H_ -#include <memory> #include <string> #include <vector> #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/values.h" class ValueStoreChange; @@ -23,8 +23,8 @@ static std::string ToJson(const ValueStoreChangeList& changes); ValueStoreChange(const std::string& key, - std::unique_ptr<base::Value> old_value, - std::unique_ptr<base::Value> new_value); + base::Optional<base::Value> old_value, + base::Optional<base::Value> new_value); ValueStoreChange(const ValueStoreChange& other); @@ -45,12 +45,12 @@ class Inner : public base::RefCountedThreadSafe<Inner> { public: Inner(const std::string& key, - std::unique_ptr<base::Value> old_value, - std::unique_ptr<base::Value> new_value); + base::Optional<base::Value> old_value, + base::Optional<base::Value> new_value); const std::string key_; - const std::unique_ptr<base::Value> old_value_; - const std::unique_ptr<base::Value> new_value_; + const base::Optional<base::Value> old_value_; + const base::Optional<base::Value> new_value_; private: friend class base::RefCountedThreadSafe<Inner>;
diff --git a/extensions/browser/value_store/value_store_change_unittest.cc b/extensions/browser/value_store/value_store_change_unittest.cc index 8b479e2..7c6f82a6 100644 --- a/extensions/browser/value_store/value_store_change_unittest.cc +++ b/extensions/browser/value_store/value_store_change_unittest.cc
@@ -18,8 +18,7 @@ namespace { TEST(ValueStoreChangeTest, NullOldValue) { - ValueStoreChange change("key", nullptr, - std::make_unique<base::Value>("value")); + ValueStoreChange change("key", base::nullopt, base::Value("value")); EXPECT_EQ("key", change.key()); EXPECT_EQ(NULL, change.old_value()); @@ -30,8 +29,7 @@ } TEST(ValueStoreChangeTest, NullNewValue) { - ValueStoreChange change("key", std::make_unique<base::Value>("value"), - nullptr); + ValueStoreChange change("key", base::Value("value"), base::nullopt); EXPECT_EQ("key", change.key()); { @@ -42,8 +40,8 @@ } TEST(ValueStoreChangeTest, NonNullValues) { - ValueStoreChange change("key", std::make_unique<base::Value>("old_value"), - std::make_unique<base::Value>("new_value")); + ValueStoreChange change("key", base::Value("old_value"), + base::Value("new_value")); EXPECT_EQ("key", change.key()); { @@ -67,10 +65,10 @@ .Build(); ValueStoreChangeList change_list; - change_list.push_back(ValueStoreChange("key", value->CreateDeepCopy(), - value->CreateDeepCopy())); - change_list.push_back(ValueStoreChange( - "key.with.dots", value->CreateDeepCopy(), value->CreateDeepCopy())); + change_list.push_back( + ValueStoreChange("key", value->Clone(), value->Clone())); + change_list.push_back( + ValueStoreChange("key.with.dots", value->Clone(), value->Clone())); std::string json = ValueStoreChange::ToJson(change_list); base::Optional<base::Value> from_json = base::JSONReader::Read(json);
diff --git a/extensions/browser/value_store/value_store_unittest.cc b/extensions/browser/value_store/value_store_unittest.cc index b797e438..644392f 100644 --- a/extensions/browser/value_store/value_store_unittest.cc +++ b/extensions/browser/value_store/value_store_unittest.cc
@@ -180,8 +180,7 @@ TEST_P(ValueStoreTest, GetWithSingleValue) { { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, nullptr, val1_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, key1_, *val1_)); } @@ -197,10 +196,8 @@ TEST_P(ValueStoreTest, GetWithMultipleValues) { { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, nullptr, val1_->CreateDeepCopy())); - changes.push_back( - ValueStoreChange(key2_, nullptr, val2_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone())); + changes.push_back(ValueStoreChange(key2_, base::nullopt, val2_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_)); } @@ -224,8 +221,7 @@ storage_->Set(DEFAULTS, *dict1_); { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, val1_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_)); } @@ -240,8 +236,7 @@ storage_->Set(DEFAULTS, *dict123_); { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key3_, val3_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange(key3_, val3_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key3_)); } @@ -256,10 +251,8 @@ { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, val1_->CreateDeepCopy(), nullptr)); - changes.push_back( - ValueStoreChange(key2_, val2_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt)); + changes.push_back(ValueStoreChange(key2_, val2_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_)); } @@ -277,10 +270,8 @@ storage_->Set(DEFAULTS, key1_, *val2_); { ValueStoreChangeList changes; - changes.push_back(ValueStoreChange(key1_, val2_->CreateDeepCopy(), - val1_->CreateDeepCopy())); - changes.push_back( - ValueStoreChange(key2_, nullptr, val2_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key1_, val2_->Clone(), val1_->Clone())); + changes.push_back(ValueStoreChange(key2_, base::nullopt, val2_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_)); } @@ -307,10 +298,8 @@ storage_->Set(DEFAULTS, *dict12_); { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, val1_->CreateDeepCopy(), nullptr)); - changes.push_back( - ValueStoreChange(key2_, val2_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt)); + changes.push_back(ValueStoreChange(key2_, val2_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear()); } @@ -335,7 +324,7 @@ { ValueStoreChangeList changes; changes.push_back( - ValueStoreChange(dot_key, nullptr, dot_value.CreateDeepCopy())); + ValueStoreChange(dot_key, base::nullopt, dot_value.Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, dot_key, dot_value)); } @@ -347,7 +336,7 @@ { ValueStoreChangeList changes; changes.push_back( - ValueStoreChange(dot_key, dot_value.CreateDeepCopy(), nullptr)); + ValueStoreChange(dot_key, dot_value.Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_key)); } EXPECT_PRED_FORMAT2(ChangesEq, @@ -355,7 +344,7 @@ { ValueStoreChangeList changes; changes.push_back( - ValueStoreChange(dot_key, nullptr, dot_value.CreateDeepCopy())); + ValueStoreChange(dot_key, base::nullopt, dot_value.Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, dot_dict)); } @@ -365,7 +354,7 @@ { ValueStoreChangeList changes; changes.push_back( - ValueStoreChange(dot_key, dot_value.CreateDeepCopy(), nullptr)); + ValueStoreChange(dot_key, dot_value.Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(dot_list)); } @@ -382,7 +371,7 @@ { ValueStoreChangeList changes; changes.push_back( - ValueStoreChange("foo", nullptr, inner_dict.CreateDeepCopy())); + ValueStoreChange("foo", base::nullopt, inner_dict.Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, outer_dict)); } @@ -404,48 +393,41 @@ ValueStoreChangeList(), storage_->Set(DEFAULTS, key1_, *val1_)); { ValueStoreChangeList changes; - changes.push_back(ValueStoreChange(key1_, val1_->CreateDeepCopy(), - val2_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key1_, val1_->Clone(), val2_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, key1_, *val2_)); } { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, val2_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange(key1_, val2_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(key1_)); EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Remove(key1_)); } { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, nullptr, val1_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, key1_, *val1_)); } { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, val1_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange(key1_, val1_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear()); EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear()); } { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, nullptr, val1_->CreateDeepCopy())); - changes.push_back( - ValueStoreChange(key2_, nullptr, val2_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key1_, base::nullopt, val1_->Clone())); + changes.push_back(ValueStoreChange(key2_, base::nullopt, val2_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict12_)); EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Set(DEFAULTS, *dict12_)); } { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key3_, nullptr, val3_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key3_, base::nullopt, val3_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, *dict123_)); } { @@ -456,20 +438,16 @@ to_set.Set("qwerty", val3_->CreateDeepCopy()); ValueStoreChangeList changes; - changes.push_back(ValueStoreChange(key1_, val1_->CreateDeepCopy(), - val2_->CreateDeepCopy())); + changes.push_back(ValueStoreChange(key1_, val1_->Clone(), val2_->Clone())); + changes.push_back(ValueStoreChange("asdf", base::nullopt, val1_->Clone())); changes.push_back( - ValueStoreChange("asdf", nullptr, val1_->CreateDeepCopy())); - changes.push_back( - ValueStoreChange("qwerty", nullptr, val3_->CreateDeepCopy())); + ValueStoreChange("qwerty", base::nullopt, val3_->Clone())); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Set(DEFAULTS, to_set)); } { ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange(key1_, val2_->CreateDeepCopy(), nullptr)); - changes.push_back( - ValueStoreChange(key2_, val2_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange(key1_, val2_->Clone(), base::nullopt)); + changes.push_back(ValueStoreChange(key2_, val2_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(list12_)); } { @@ -478,16 +456,14 @@ to_remove.push_back("asdf"); ValueStoreChangeList changes; - changes.push_back( - ValueStoreChange("asdf", val1_->CreateDeepCopy(), nullptr)); + changes.push_back(ValueStoreChange("asdf", val1_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Remove(to_remove)); } { ValueStoreChangeList changes; + changes.push_back(ValueStoreChange(key3_, val3_->Clone(), base::nullopt)); changes.push_back( - ValueStoreChange(key3_, val3_->CreateDeepCopy(), nullptr)); - changes.push_back( - ValueStoreChange("qwerty", val3_->CreateDeepCopy(), nullptr)); + ValueStoreChange("qwerty", val3_->Clone(), base::nullopt)); EXPECT_PRED_FORMAT2(ChangesEq, changes, storage_->Clear()); EXPECT_PRED_FORMAT2(ChangesEq, ValueStoreChangeList(), storage_->Clear()); }
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h index 08be0b1..f3ddb903 100644 --- a/extensions/common/permissions/api_permission.h +++ b/extensions/common/permissions/api_permission.h
@@ -263,6 +263,7 @@ kTransientBackground = 219, kLogin = 220, kLoginScreenStorage = 221, + kLoginState = 222, // Last entry: Add new entries above and ensure to update the // "ExtensionPermission3" enum in tools/metrics/histograms/enums.xml // (by running update_extension_permission.py).
diff --git a/extensions/common/permissions/extensions_api_permissions.cc b/extensions/common/permissions/extensions_api_permissions.cc index fbcb281b..000d8653 100644 --- a/extensions/common/permissions/extensions_api_permissions.cc +++ b/extensions/common/permissions/extensions_api_permissions.cc
@@ -79,6 +79,7 @@ {APIPermission::kLogin, "login"}, {APIPermission::kLoginScreenStorage, "loginScreenStorage"}, {APIPermission::kLoginScreenUi, "loginScreenUi"}, + {APIPermission::kLoginState, "loginState"}, {APIPermission::kMediaPerceptionPrivate, "mediaPerceptionPrivate"}, {APIPermission::kMetricsPrivate, "metricsPrivate", APIPermissionInfo::kFlagCannotBeOptional},
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 5eda2598..ec3f851 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -116,10 +116,6 @@ "When enable, the browser container keeps the content view in the view " "hierarchy, to avoid WKWebView from being unloaded from the process."; -const char kBrowserTaskScheduler[] = "Task Scheduler"; -const char kBrowserTaskSchedulerDescription[] = - "Enables redirection of some task posting APIs to the task scheduler."; - // TODO(crbug.com/893314) : Remove this flag. const char kClosingLastIncognitoTabName[] = "Closing Last Incognito Tab"; const char kClosingLastIncognitoTabDescription[] = @@ -132,10 +128,6 @@ "When enabled collections are presented using the new iOS13 card " "style."; -const char kContextualSearch[] = "Contextual Search"; -const char kContextualSearchDescription[] = - "Whether or not Contextual Search is enabled."; - const char kCopiedContentBehaviorName[] = "Enable differentiating between copied urls, text, and images"; const char kCopiedContentBehaviorDescription[] = @@ -157,31 +149,11 @@ const char kDragAndDropName[] = "Drag and Drop"; const char kDragAndDropDescription[] = "Enable support for drag and drop."; -const char kEnableAutocompleteDataRetentionPolicyName[] = - "Enable automatic cleanup of expired Autocomplete entries."; -const char kEnableAutocompleteDataRetentionPolicyDescription[] = - "If enabled, will clean-up Autocomplete entries whose last use date is " - "older than the current retention policy. These entries will be " - "permanently deleted from the client on startup, and will be unlinked " - "from sync."; - -const char kEnableAutofillCreditCardUploadUpdatePromptExplanationName[] = - "Enable updated prompt explanation when offering credit card upload"; -const char kEnableAutofillCreditCardUploadUpdatePromptExplanationDescription[] = - "If enabled, changes the server save card prompt's explanation to mention " - "the saving of the billing address."; - const char kEnableAutofillSaveCardShowNoThanksName[] = "Show explicit decline option in credit card save prompts"; const char kEnableAutofillSaveCardShowNoThanksDescription[] = "If enabled, adds a [No thanks] button to credit card save prompts."; -const char kEnableAutofillSaveCreditCardUsesStrikeSystemName[] = - "Enable limit on offering to save the same credit card repeatedly"; -const char kEnableAutofillSaveCreditCardUsesStrikeSystemDescription[] = - "If enabled, prevents popping up the credit card offer-to-save prompt if " - "it has repeatedly been ignored, declined, or failed."; - const char kEnableAutofillImportDynamicFormsName[] = "Allow credit card import from dynamic forms after entry"; const char kEnableAutofillImportDynamicFormsDescription[] = @@ -226,11 +198,6 @@ "The different ways in which the web view's viewport is updated for scroll " "events. The default option updates the web view's frame."; -const char kHistoryBatchUpdatesFilterName[] = "History Single Batch Filtering"; -const char kHistoryBatchUpdatesFilterDescription[] = - "When enabled History inserts and deletes history items in the same " - "BatchUpdates block."; - const char kIdentityDiscName[] = "Identity Disc"; const char kIdentityDiscDescription[] = "Enables Identity Disc, profile avatar icon button in toolbar."; @@ -289,17 +256,6 @@ "Instead of ZeroSuggest, show most visited sites and collection shortcuts " "in the omnibox popup."; -const char kOmniboxTabSwitchSuggestionsName[] = - "Enable 'switch to this tab' option"; -const char kOmniboxTabSwitchSuggestionsDescription[] = - "Enable the 'switch to this tab' options in the omnibox suggestions."; - -const char kOmniboxUIElideSuggestionUrlAfterHostName[] = - "Hide the path, query, and ref of omnibox suggestions"; -const char kOmniboxUIElideSuggestionUrlAfterHostDescription[] = - "Elides the path, query, and ref of suggested URLs in the omnibox " - "dropdown."; - const char kOmniboxUIMaxAutocompleteMatchesName[] = "Omnibox UI Max Autocomplete Matches"; const char kOmniboxUIMaxAutocompleteMatchesDescription[] = @@ -323,10 +279,6 @@ "Make thumbnails of NTP articles optional due to European copyright " "directive(EUCD). Also change the layout of article cells"; -const char kPasswordGenerationName[] = "Password generation suggestion"; -const char kPasswordGenerationDescription[] = - "Add 'Suggest Password' in suggestion list for form completion."; - const char kSearchIconToggleName[] = "Change the icon for the search button"; const char kSearchIconToggleDescription[] = "Different icons for the search button."; @@ -406,11 +358,6 @@ const char kUseMultiloginEndpointDescription[] = "Use Gaia OAuth multilogin for identity consistency."; -const char kUseNSURLSessionForGaiaSigninRequestsName[] = - "Use NSURLSession for sign-in requests"; -const char kUseNSURLSessionForGaiaSigninRequestsDescription[] = - "Use NSURLSession to make sign-in requests to Gaia"; - const char kWalletServiceUseSandboxName[] = "Use Google Payments sandbox"; const char kWalletServiceUseSandboxDescription[] = "Uses the sandbox service for Google Payments API calls.";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 2cd8ca1..e7ddf07 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -87,11 +87,6 @@ extern const char kBrowserContainerKeepsContentViewName[]; extern const char kBrowserContainerKeepsContentViewDescription[]; -// Title and description for the flag to control redirection to the task -// scheduler. -extern const char kBrowserTaskScheduler[]; -extern const char kBrowserTaskSchedulerDescription[]; - // Title and description for the flag to enable automatically switching to the // regular tabs after closing the last incognito tab. extern const char kClosingLastIncognitoTabName[]; @@ -102,10 +97,6 @@ extern const char kCollectionsCardPresentationStyleName[]; extern const char kCollectionsCardPresentationStyleDescription[]; -// Title and description for the flag to enable Contextual Search. -extern const char kContextualSearch[]; -extern const char kContextualSearchDescription[]; - // Title and description for the flag to diffentiate between copied // urls, strings, and images. extern const char kCopiedContentBehaviorName[]; @@ -126,28 +117,11 @@ extern const char kDragAndDropName[]; extern const char kDragAndDropDescription[]; -// Title and description for the flag to control the autocomplete retention -// policy. -extern const char kEnableAutocompleteDataRetentionPolicyName[]; -extern const char kEnableAutocompleteDataRetentionPolicyDescription[]; - -// Title and description for the flag to control the updated prompt explanation -// when offering credit card upload. -extern const char kEnableAutofillCreditCardUploadUpdatePromptExplanationName[]; -extern const char - kEnableAutofillCreditCardUploadUpdatePromptExplanationDescription[]; - // Title and description for the flag to control if no thanks button should be // shown when saving a card. extern const char kEnableAutofillSaveCardShowNoThanksName[]; extern const char kEnableAutofillSaveCardShowNoThanksDescription[]; -// Title and description for the flag to control if credit card save should -// utilize the Autofill StrikeDatabase when determining whether save -// should be offered. -extern const char kEnableAutofillSaveCreditCardUsesStrikeSystemName[]; -extern const char kEnableAutofillSaveCreditCardUsesStrikeSystemDescription[]; - // Title and description for the flag to control the credit card import from // dynamic forms. extern const char kEnableAutofillImportDynamicFormsName[]; @@ -186,10 +160,6 @@ extern const char kFullscreenViewportAdjustmentExperimentName[]; extern const char kFullscreenViewportAdjustmentExperimentDescription[]; -// Title and description for the flag to enable History batch filtering. -extern const char kHistoryBatchUpdatesFilterName[]; -extern const char kHistoryBatchUpdatesFilterDescription[]; - // Title and description for the flag to display current user identity on // New Tab Page. extern const char kIdentityDiscName[]; @@ -243,16 +213,6 @@ extern const char kOmniboxPopupShortcutIconsInZeroStateName[]; extern const char kOmniboxPopupShortcutIconsInZeroStateDescription[]; -// Title and description for the flag to enable the "switch to this tab" option -// in the omnibox suggestion. It doesn't add new suggestions. -extern const char kOmniboxTabSwitchSuggestionsName[]; -extern const char kOmniboxTabSwitchSuggestionsDescription[]; - -// Title and description for the flag to enable elision of the URL path, query, -// and ref in omnibox URL suggestions. -extern const char kOmniboxUIElideSuggestionUrlAfterHostName[]; -extern const char kOmniboxUIElideSuggestionUrlAfterHostDescription[]; - // Title and description for the flag to change the max number of autocomplete // matches in the omnibox popup. extern const char kOmniboxUIMaxAutocompleteMatchesName[]; @@ -273,10 +233,6 @@ extern const char kOptionalArticleThumbnailName[]; extern const char kOptionalArticleThumbnailDescription[]; -// Title and description for the flag to enable password generation. -extern const char kPasswordGenerationName[]; -extern const char kPasswordGenerationDescription[]; - // Title and description for the flag to toggle the flag of the search button. extern const char kSearchIconToggleName[]; extern const char kSearchIconToggleDescription[]; @@ -338,10 +294,6 @@ extern const char kToolbarNewTabButtonName[]; extern const char kToolbarNewTabButtonDescription[]; -// Title and description for the flag to control manual translate trigger. -extern const char kTranslateManualTriggerName[]; -extern const char kTranslateManualTriggerDescription[]; - // Title and description for the flag to enable the unified consent. extern const char kUnifiedConsentName[]; extern const char kUnifiedConsentDescription[]; @@ -355,11 +307,6 @@ extern const char kUseMultiloginEndpointName[]; extern const char kUseMultiloginEndpointDescription[]; -// Title and description for the flag to switch from WKWebView to NSURLSession -// to make sign-in requests to Gaia with attached cookies. -extern const char kUseNSURLSessionForGaiaSigninRequestsName[]; -extern const char kUseNSURLSessionForGaiaSigninRequestsDescription[]; - // Title and description for the flag to control if Google Payments API calls // should use the sandbox servers. extern const char kWalletServiceUseSandboxName[];
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder.mm b/ios/chrome/browser/metrics/tab_usage_recorder.mm index 970e41e0..86beff9c 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder.mm
@@ -290,9 +290,13 @@ UMA_HISTOGRAM_ENUMERATION(kRendererTerminationStateHistogram, static_cast<int>(web_state_state), static_cast<int>(TERMINATION_TAB_STATE_COUNT)); - if (!web_state_visible) { - DCHECK(!WebStateAlreadyEvicted(terminated_web_state)); + if (WebStateAlreadyEvicted(terminated_web_state)) { + // A web state may get notified multiple times that it's been evicted. + // To avoid double-counting, don't do any further processing if this + // happens. + return; + } evicted_web_states_[terminated_web_state] = EVICTED_DUE_TO_RENDERER_TERMINATION; }
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_unittest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_unittest.mm index 3cc6190..40a1d63 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_unittest.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_unittest.mm
@@ -344,6 +344,15 @@ histogram_tester_.ExpectUniqueSample( kRendererTerminationRecentlyAliveRenderers, kAliveTabsCountAtRendererTermination + 2, 1); + + // Regression test for crbug.com/935205 + // Terminate the same tab again. Verify that it isn't double-counted. + mock_tab_a->OnRenderProcessGone(); + histogram_tester_.ExpectUniqueSample(kRendererTerminationAliveRenderers, + kAliveTabsCountAtRendererTermination, 1); + histogram_tester_.ExpectUniqueSample( + kRendererTerminationRecentlyAliveRenderers, + kAliveTabsCountAtRendererTermination + 2, 1); } // Verifies that metrics are recorded correctly when a renderer terminated tab
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index 70b8c04d0..0ddb381 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -22,7 +22,7 @@ #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/common/password_form_fill_data.h" #include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/new_password_form_manager.h" +#include "components/password_manager/core/browser/password_form_manager.h" #include "components/password_manager/core/browser/password_store_consumer.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/common/password_manager_pref_names.h" @@ -219,7 +219,7 @@ // Disable wating, since most tests have nothing to do with predictions. All // tests that test working with prediction should explicitly turn // predictions on. - password_manager::NewPasswordFormManager:: + password_manager::PasswordFormManager:: set_wait_for_server_predictions_for_filling(false); passwordController_ = @@ -1505,8 +1505,8 @@ TearDown(); ChromeWebTest::SetUp(); - password_manager::NewPasswordFormManager:: - set_wait_for_server_predictions_for_filling(false); + password_manager::PasswordFormManager:: + set_wait_for_server_predictions_for_filling(false); auto client = std::make_unique<NiceMock<MockPasswordManagerClient>>(store_.get());
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm index 4021b83..de279ba 100644 --- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm +++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -104,11 +104,13 @@ password_store_ = IOSChromePasswordStoreFactory::GetForBrowserState( browser_state_, ServiceAccessType::IMPLICIT_ACCESS); - component_factory_.reset(new browser_sync::ProfileSyncComponentsFactoryImpl( - this, ::GetChannel(), prefs::kSavingBrowserHistoryDisabled, - base::CreateSingleThreadTaskRunner({web::WebThread::UI}), db_thread_, - profile_web_data_service_, account_web_data_service_, password_store_, - ios::BookmarkSyncServiceFactory::GetForBrowserState(browser_state_))); + component_factory_ = + std::make_unique<browser_sync::ProfileSyncComponentsFactoryImpl>( + this, ::GetChannel(), prefs::kSavingBrowserHistoryDisabled, + base::CreateSingleThreadTaskRunner({web::WebThread::UI}), db_thread_, + profile_web_data_service_, account_web_data_service_, password_store_, + /*account_password_store=*/nullptr, + ios::BookmarkSyncServiceFactory::GetForBrowserState(browser_state_)); } IOSChromeSyncClient::~IOSChromeSyncClient() {}
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm index 7b33079..86cbec1 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
@@ -263,7 +263,8 @@ // Returns a location icon for offline pages. - (UIImage*)imageForOfflinePage { - return [UIImage imageNamed:@"location_bar_offline"]; + return [[UIImage imageNamed:@"location_bar_offline"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; } #pragma mark Shareability helpers
diff --git a/ios/web_view/internal/sync/web_view_sync_client.mm b/ios/web_view/internal/sync/web_view_sync_client.mm index 66dfa28..73baee4 100644 --- a/ios/web_view/internal/sync/web_view_sync_client.mm +++ b/ios/web_view/internal/sync/web_view_sync_client.mm
@@ -76,11 +76,14 @@ password_store_ = WebViewPasswordStoreFactory::GetForBrowserState( browser_state_, ServiceAccessType::IMPLICIT_ACCESS); - component_factory_.reset(new browser_sync::ProfileSyncComponentsFactoryImpl( - this, version_info::Channel::STABLE, prefs::kSavingBrowserHistoryDisabled, - base::CreateSingleThreadTaskRunner({web::WebThread::UI}), db_thread_, - profile_web_data_service_, account_web_data_service_, password_store_, - /*bookmark_sync_service=*/nullptr)); + component_factory_ = + std::make_unique<browser_sync::ProfileSyncComponentsFactoryImpl>( + this, version_info::Channel::STABLE, + prefs::kSavingBrowserHistoryDisabled, + base::CreateSingleThreadTaskRunner({web::WebThread::UI}), db_thread_, + profile_web_data_service_, account_web_data_service_, password_store_, + /*account_password_store=*/nullptr, + /*bookmark_sync_service=*/nullptr); } WebViewSyncClient::~WebViewSyncClient() {}
diff --git a/media/gpu/chromeos/BUILD.gn b/media/gpu/chromeos/BUILD.gn index 708fa5b..20ab7282 100644 --- a/media/gpu/chromeos/BUILD.gn +++ b/media/gpu/chromeos/BUILD.gn
@@ -22,7 +22,7 @@ ] if (use_vaapi || use_v4l2_codec) { - deps += [ "//media/gpu/linux:common" ] + deps += [ "//media/gpu/linux" ] } if (use_vaapi) {
diff --git a/media/gpu/chromeos/chromeos_video_decoder_factory.cc b/media/gpu/chromeos/chromeos_video_decoder_factory.cc index 8497e37..e2734a9 100644 --- a/media/gpu/chromeos/chromeos_video_decoder_factory.cc +++ b/media/gpu/chromeos/chromeos_video_decoder_factory.cc
@@ -9,8 +9,12 @@ #include "base/sequenced_task_runner.h" #include "media/base/video_decoder.h" #include "media/gpu/buildflags.h" + +#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC) #include "media/gpu/linux/mailbox_video_frame_converter.h" #include "media/gpu/linux/platform_video_frame_pool.h" +#include "media/gpu/linux/video_decoder_pipeline.h" +#endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC) #if BUILDFLAG(USE_VAAPI) #include "media/gpu/vaapi/vaapi_video_decoder.h" @@ -20,9 +24,6 @@ #include "media/gpu/v4l2/v4l2_slice_video_decoder.h" #endif -#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC) -#include "media/gpu/linux/video_decoder_pipeline.h" -#endif namespace media { @@ -52,29 +53,14 @@ scoped_refptr<base::SequencedTaskRunner> client_task_runner, std::unique_ptr<DmabufVideoFramePool> frame_pool, std::unique_ptr<VideoFrameConverter> frame_converter) { - if (!client_task_runner || !frame_pool || !frame_converter) - return nullptr; - - std::unique_ptr<VideoDecoder> decoder; - - // TODO(dstaessens@): We first try VAAPI as USE_V4L2_CODEC might also be - // set, even though initialization of V4L2SliceVideoDecoder would fail. We - // need to implement a better way to select the correct decoder. -#if BUILDFLAG(USE_VAAPI) - decoder = - VaapiVideoDecoder::Create(client_task_runner, std::move(frame_pool)); -#elif BUILDFLAG(USE_V4L2_CODEC) - decoder = - V4L2SliceVideoDecoder::Create(client_task_runner, std::move(frame_pool)); -#endif - #if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC) - return std::make_unique<VideoDecoderPipeline>(std::move(client_task_runner), - std::move(decoder), - std::move(frame_converter)); -#else + // TODO(akahuang): Remove ChromeosVideoDecoderFactory. + return VideoDecoderPipeline::Create(std::move(client_task_runner), + std::move(frame_pool), + std::move(frame_converter)); +#endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC) + return nullptr; -#endif } } // namespace media
diff --git a/media/gpu/linux/BUILD.gn b/media/gpu/linux/BUILD.gn index eaff735..4cf799e 100644 --- a/media/gpu/linux/BUILD.gn +++ b/media/gpu/linux/BUILD.gn
@@ -7,6 +7,36 @@ assert(use_v4l2_codec || use_vaapi) +# The source that depends on //media/gpu/{vaapi,v4l2}. It is created to avoid +# circular dependency because //media/gpu/linux:common could be depended by +# //media/gpu/{vaapi,v4l2}. +source_set("linux") { + defines = [ "MEDIA_GPU_IMPLEMENTATION" ] + sources = [ + "video_decoder_pipeline.cc", + "video_decoder_pipeline.h", + ] + + public_deps = [ + ":common", + ] + + deps = [ + "//base", + "//media", + "//media/gpu:buildflags", + "//media/gpu:common", + ] + + if (use_vaapi) { + deps += [ "//media/gpu/vaapi" ] + } + + if (use_v4l2_codec) { + deps += [ "//media/gpu/v4l2" ] + } +} + source_set("common") { defines = [ "MEDIA_GPU_IMPLEMENTATION" ] sources = [ @@ -18,8 +48,6 @@ "platform_video_frame_pool.h", "platform_video_frame_utils.cc", "platform_video_frame_utils.h", - "video_decoder_pipeline.cc", - "video_decoder_pipeline.h", ] deps = [
diff --git a/media/gpu/linux/video_decoder_pipeline.cc b/media/gpu/linux/video_decoder_pipeline.cc index fd64a7c..8c5e7dab 100644 --- a/media/gpu/linux/video_decoder_pipeline.cc +++ b/media/gpu/linux/video_decoder_pipeline.cc
@@ -7,71 +7,154 @@ #include "base/bind.h" #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" -#include "media/base/video_decoder_config.h" +#include "base/task/task_traits.h" +#include "media/gpu/buildflags.h" +#include "media/gpu/linux/dmabuf_video_frame_pool.h" #include "media/gpu/macros.h" +#if BUILDFLAG(USE_VAAPI) +#include "media/gpu/vaapi/vaapi_video_decoder.h" +#endif + +#if BUILDFLAG(USE_V4L2_CODEC) +#include "media/gpu/v4l2/v4l2_slice_video_decoder.h" +#endif + namespace media { +// static +base::queue<VideoDecoderPipeline::CreateVDFunc> +VideoDecoderPipeline::GetCreateVDFunctions( + VideoDecoderPipeline::CreateVDFunc cur_create_vd_func) { + static constexpr VideoDecoderPipeline::CreateVDFunc kCreateVDFuncs[] = { +#if BUILDFLAG(USE_V4L2_CODEC) + &V4L2SliceVideoDecoder::Create, +#endif // BUILDFLAG(USE_V4L2_CODEC) + +#if BUILDFLAG(USE_VAAPI) + &VaapiVideoDecoder::Create, +#endif // BUILDFLAG(USE_VAAPI) + }; + + base::queue<VideoDecoderPipeline::CreateVDFunc> ret; + for (const auto& func : kCreateVDFuncs) { + if (func != cur_create_vd_func) + ret.push(func); + } + return ret; +} + +// static +std::unique_ptr<VideoDecoder> VideoDecoderPipeline::Create( + scoped_refptr<base::SequencedTaskRunner> client_task_runner, + std::unique_ptr<DmabufVideoFramePool> frame_pool, + std::unique_ptr<VideoFrameConverter> frame_converter) { + if (!client_task_runner || !frame_pool || !frame_converter) { + VLOGF(1) << "One of arguments is nullptr."; + return nullptr; + } + + if (GetCreateVDFunctions(nullptr).empty()) { + VLOGF(1) << "No available function to create video decoder."; + return nullptr; + } + + return base::WrapUnique<VideoDecoder>(new VideoDecoderPipeline( + std::move(client_task_runner), std::move(frame_pool), + std::move(frame_converter))); +} + VideoDecoderPipeline::VideoDecoderPipeline( scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<VideoDecoder> decoder, + std::unique_ptr<DmabufVideoFramePool> frame_pool, std::unique_ptr<VideoFrameConverter> frame_converter) : client_task_runner_(std::move(client_task_runner)), - decoder_(std::move(decoder)), - frame_converter_(std::move(frame_converter)), - weak_this_factory_(this) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(decoder_); + decoder_task_runner_(base::CreateSingleThreadTaskRunner( + {base::ThreadPool(), base::WithBaseSyncPrimitives(), + base::TaskPriority::USER_VISIBLE}, + base::SingleThreadTaskRunnerThreadMode::DEDICATED)), + frame_pool_(std::move(frame_pool)), + frame_converter_(std::move(frame_converter)) { + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + DETACH_FROM_SEQUENCE(decoder_sequence_checker_); + DCHECK(frame_pool_); DCHECK(frame_converter_); DCHECK(client_task_runner_); DVLOGF(2); + weak_this_ = weak_this_factory_.GetWeakPtr(); + frame_pool_->set_parent_task_runner(decoder_task_runner_); frame_converter_->Initialize( client_task_runner_, - base::BindRepeating(&VideoDecoderPipeline::OnFrameConverted, - weak_this_factory_.GetWeakPtr())); + base::BindRepeating(&VideoDecoderPipeline::OnFrameConverted, weak_this_)); } VideoDecoderPipeline::~VideoDecoderPipeline() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // We have to destroy |frame_pool_| on |decoder_task_runner_|, so the + // destructor is also called on |decoder_task_runner_|. + DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); DVLOGF(3); } void VideoDecoderPipeline::Destroy() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DVLOGF(2); + weak_this_factory_.InvalidateWeakPtrs(); + + decoder_.reset(); + used_create_vd_func_ = nullptr; + frame_converter_.reset(); + + decoder_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&VideoDecoderPipeline::DestroyTask, + base::Unretained(this))); +} + +void VideoDecoderPipeline::DestroyTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_); + DVLOGF(3); + + // |frame_pool_| should be destroyed on |decoder_task_runner_|, which is set + // by frame_pool_->set_parent_task_runner(). + frame_pool_.reset(); delete this; } std::string VideoDecoderPipeline::GetDisplayName() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); - return decoder_->GetDisplayName(); + return "VideoDecoderPipeline"; } bool VideoDecoderPipeline::IsPlatformDecoder() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); - return decoder_->IsPlatformDecoder(); + return true; } int VideoDecoderPipeline::GetMaxDecodeRequests() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); - return decoder_->GetMaxDecodeRequests(); + if (!decoder_) + DVLOGF(1) << "Call before Initialize() success."; + return decoder_ ? decoder_->GetMaxDecodeRequests() : 1; } bool VideoDecoderPipeline::NeedsBitstreamConversion() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); - return decoder_->NeedsBitstreamConversion(); + if (!decoder_) + DVLOGF(1) << "Call before Initialize() success."; + return decoder_ ? decoder_->NeedsBitstreamConversion() : false; } bool VideoDecoderPipeline::CanReadWithoutStalling() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); - return decoder_->CanReadWithoutStalling(); + if (!decoder_) + DVLOGF(1) << "Call before Initialize() success."; + return decoder_ ? decoder_->CanReadWithoutStalling() : false; } void VideoDecoderPipeline::Initialize(const VideoDecoderConfig& config, @@ -80,30 +163,111 @@ InitCB init_cb, const OutputCB& output_cb, const WaitingCB& waiting_cb) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + DCHECK(!init_cb_); VLOGF(2) << "config: " << config.AsHumanReadableString(); client_output_cb_ = std::move(output_cb); + init_cb_ = std::move(init_cb); + base::queue<VideoDecoderPipeline::CreateVDFunc> create_vd_funcs = + GetCreateVDFunctions(used_create_vd_func_); + + if (!decoder_) { + CreateAndInitializeVD(std::move(create_vd_funcs), config, low_delay, + cdm_context, waiting_cb); + } else { + decoder_->Initialize( + config, low_delay, cdm_context, + // If it fails to re-initialize current |decoder_|, it will create + // another decoder instance by trying available VD creation functions + // again. See |OnInitializeDone| for detail. + base::BindOnce(&VideoDecoderPipeline::OnInitializeDone, weak_this_, + std::move(create_vd_funcs), config, low_delay, + cdm_context, waiting_cb), + base::BindRepeating(&VideoDecoderPipeline::OnFrameDecodedThunk, + client_task_runner_, weak_this_), + waiting_cb); + } +} + +void VideoDecoderPipeline::CreateAndInitializeVD( + base::queue<VideoDecoderPipeline::CreateVDFunc> create_vd_funcs, + VideoDecoderConfig config, + bool low_delay, + CdmContext* cdm_context, + WaitingCB waiting_cb) { + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + DCHECK(init_cb_); + DCHECK(!decoder_); + DCHECK(!used_create_vd_func_); + DVLOGF(3); + + if (create_vd_funcs.empty()) { + DVLOGF(2) << "No available video decoder."; + std::move(init_cb_).Run(false); + return; + } + + used_create_vd_func_ = create_vd_funcs.front(); + create_vd_funcs.pop(); + decoder_ = used_create_vd_func_( + client_task_runner_, decoder_task_runner_, + base::BindRepeating(&VideoDecoderPipeline::GetVideoFramePool, + base::Unretained(this))); + if (!decoder_) { + DVLOGF(2) << "Failed to create VideoDecoder."; + used_create_vd_func_ = nullptr; + return CreateAndInitializeVD(std::move(create_vd_funcs), config, low_delay, + cdm_context, std::move(waiting_cb)); + } decoder_->Initialize( - config, low_delay, cdm_context, std::move(init_cb), + config, low_delay, cdm_context, + base::BindOnce(&VideoDecoderPipeline::OnInitializeDone, weak_this_, + std::move(create_vd_funcs), config, low_delay, cdm_context, + waiting_cb), base::BindRepeating(&VideoDecoderPipeline::OnFrameDecodedThunk, - client_task_runner_, weak_this_factory_.GetWeakPtr()), - std::move(waiting_cb)); + client_task_runner_, weak_this_), + waiting_cb); +} + +void VideoDecoderPipeline::OnInitializeDone( + base::queue<VideoDecoderPipeline::CreateVDFunc> create_vd_funcs, + VideoDecoderConfig config, + bool low_delay, + CdmContext* cdm_context, + WaitingCB waiting_cb, + bool success) { + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + DCHECK(init_cb_); + DVLOGF(4) << "Initialization " << (success ? "success." : "failure."); + + if (success) { + DVLOGF(2) << "Initialize VD successfully."; + std::move(init_cb_).Run(true); + return; + } + + DVLOGF(3) << "Reset VD, try the next create function."; + decoder_ = nullptr; + used_create_vd_func_ = nullptr; + CreateAndInitializeVD(std::move(create_vd_funcs), config, low_delay, + cdm_context, std::move(waiting_cb)); } void VideoDecoderPipeline::Reset(base::OnceClosure closure) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + DCHECK(decoder_); DCHECK(!client_reset_cb_); DVLOGF(3); client_reset_cb_ = std::move(closure); - decoder_->Reset(base::BindOnce(&VideoDecoderPipeline::OnResetDone, - weak_this_factory_.GetWeakPtr())); + decoder_->Reset( + base::BindOnce(&VideoDecoderPipeline::OnResetDone, weak_this_)); } void VideoDecoderPipeline::OnResetDone() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DCHECK(client_reset_cb_); DVLOGF(3); @@ -116,20 +280,20 @@ void VideoDecoderPipeline::Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); + DCHECK(decoder_); DVLOGF(4); bool is_flush = buffer->end_of_stream(); decoder_->Decode(std::move(buffer), base::BindOnce(&VideoDecoderPipeline::OnDecodeDone, - weak_this_factory_.GetWeakPtr(), is_flush, - std::move(decode_cb))); + weak_this_, is_flush, std::move(decode_cb))); } void VideoDecoderPipeline::OnDecodeDone(bool is_flush, DecodeCB decode_cb, DecodeStatus status) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DVLOGF(4) << "is_flush: " << is_flush << ", status: " << status; if (has_error_) @@ -185,7 +349,7 @@ } void VideoDecoderPipeline::OnFrameDecoded(scoped_refptr<VideoFrame> frame) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DCHECK(frame_converter_); DVLOGF(4); @@ -193,7 +357,7 @@ } void VideoDecoderPipeline::OnFrameConverted(scoped_refptr<VideoFrame> frame) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DVLOGF(4); if (!frame) @@ -210,7 +374,7 @@ } void VideoDecoderPipeline::OnError(const std::string& msg) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); VLOGF(1) << msg; has_error_ = true; @@ -218,7 +382,7 @@ } void VideoDecoderPipeline::CallFlushCbIfNeeded(DecodeStatus status) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DVLOGF(3) << "status: " << status; if (!client_flush_cb_) @@ -231,4 +395,8 @@ std::move(client_flush_cb_).Run(status); } +DmabufVideoFramePool* VideoDecoderPipeline::GetVideoFramePool() const { + return frame_pool_.get(); +} + } // namespace media
diff --git a/media/gpu/linux/video_decoder_pipeline.h b/media/gpu/linux/video_decoder_pipeline.h index 19d08c9..b5163ae 100644 --- a/media/gpu/linux/video_decoder_pipeline.h +++ b/media/gpu/linux/video_decoder_pipeline.h
@@ -7,10 +7,12 @@ #include <memory> +#include "base/containers/queue.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/sequence_checker.h" #include "media/base/video_decoder.h" +#include "media/base/video_decoder_config.h" #include "media/gpu/media_gpu_export.h" #include "media/gpu/video_frame_converter.h" @@ -20,12 +22,15 @@ namespace media { +class DmabufVideoFramePool; + class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder { public: - VideoDecoderPipeline( + static std::unique_ptr<VideoDecoder> Create( scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<VideoDecoder> decoder, + std::unique_ptr<DmabufVideoFramePool> frame_pool, std::unique_ptr<VideoFrameConverter> frame_converter); + ~VideoDecoderPipeline() override; // VideoDecoder implementation @@ -45,7 +50,35 @@ void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override; private: + // Function signature for creating VideoDecoder. + using CreateVDFunc = std::unique_ptr<VideoDecoder> (*)( + scoped_refptr<base::SequencedTaskRunner>, + scoped_refptr<base::SequencedTaskRunner>, + base::RepeatingCallback<DmabufVideoFramePool*()>); + + // Get a list of the available functions for creating VideoDeocoder. + static base::queue<CreateVDFunc> GetCreateVDFunctions( + CreateVDFunc current_func); + + VideoDecoderPipeline( + scoped_refptr<base::SequencedTaskRunner> client_task_runner, + std::unique_ptr<DmabufVideoFramePool> frame_pool, + std::unique_ptr<VideoFrameConverter> frame_converter); void Destroy() override; + void DestroyTask(); + + void CreateAndInitializeVD(base::queue<CreateVDFunc> create_vd_funcs, + VideoDecoderConfig config, + bool low_delay, + CdmContext* cdm_context, + WaitingCB waiting_cb); + void OnInitializeDone(base::queue<CreateVDFunc> create_vd_funcs, + VideoDecoderConfig config, + bool low_delay, + CdmContext* cdm_context, + WaitingCB waiting_cb, + bool success); + void OnDecodeDone(bool eos_buffer, DecodeCB decode_cb, DecodeStatus status); void OnResetDone(); void OnFrameConverted(scoped_refptr<VideoFrame> frame); @@ -60,13 +93,34 @@ // Call |client_flush_cb_| with |status| if we need. void CallFlushCbIfNeeded(DecodeStatus status); - const scoped_refptr<base::SequencedTaskRunner> client_task_runner_; + // Get the video frame pool without passing the ownership. + DmabufVideoFramePool* GetVideoFramePool() const; - const std::unique_ptr<VideoDecoder> decoder_; - const std::unique_ptr<VideoFrameConverter> frame_converter_; + // The client task runner and its sequence checker. All public methods should + // run on this task runner. + const scoped_refptr<base::SequencedTaskRunner> client_task_runner_; + SEQUENCE_CHECKER(client_sequence_checker_); + + // The decoder task runner and its sequence checker. |decoder_| should post + // time-consuming task and call |frame_pool_|'s methods on this task runner. + const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_; + SEQUENCE_CHECKER(decoder_sequence_checker_); + + // The frame pool passed from the client. Destroyed on |decoder_task_runner_|. + std::unique_ptr<DmabufVideoFramePool> frame_pool_; + // The frame converter passed from the client. Destroyed on + // |client_task_runner_|. + std::unique_ptr<VideoFrameConverter> frame_converter_; + + // The current video decoder implementation. Valid after initialization is + // successfully done. + std::unique_ptr<VideoDecoder> decoder_; + // The create function of |decoder_|. nullptr iff |decoder_| is nullptr. + CreateVDFunc used_create_vd_func_ = nullptr; // Callback from the client. These callback are called on // |client_task_runner_|. + InitCB init_cb_; OutputCB client_output_cb_; DecodeCB client_flush_cb_; base::OnceClosure client_reset_cb_; @@ -74,9 +128,9 @@ // Set to true when any unexpected error occurs. bool has_error_ = false; - SEQUENCE_CHECKER(sequence_checker_); - - base::WeakPtrFactory<VideoDecoderPipeline> weak_this_factory_; + // The weak pointer of this, bound to |client_task_runner_|. + base::WeakPtr<VideoDecoderPipeline> weak_this_; + base::WeakPtrFactory<VideoDecoderPipeline> weak_this_factory_{this}; }; } // namespace media
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn index 8aa4cf9f..5e47411 100644 --- a/media/gpu/v4l2/BUILD.gn +++ b/media/gpu/v4l2/BUILD.gn
@@ -71,6 +71,10 @@ configs += [ "//third_party/libyuv:libyuv_config" ] + public_deps = [ + "//ui/gl", + ] + deps = [ "//base", "//gpu/ipc/common",
diff --git a/media/gpu/v4l2/v4l2_slice_video_decoder.cc b/media/gpu/v4l2/v4l2_slice_video_decoder.cc index 58d69766..ad0e36b 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decoder.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decoder.cc
@@ -128,9 +128,10 @@ // static std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create( scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<DmabufVideoFramePool> frame_pool) { + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, + GetFramePoolCB get_pool_cb) { DCHECK(client_task_runner->RunsTasksInCurrentSequence()); - DCHECK(frame_pool); + DCHECK(get_pool_cb); scoped_refptr<V4L2Device> device = V4L2Device::Create(); if (!device) { @@ -139,7 +140,8 @@ } return base::WrapUnique<VideoDecoder>(new V4L2SliceVideoDecoder( - std::move(client_task_runner), std::move(device), std::move(frame_pool))); + std::move(client_task_runner), std::move(decoder_task_runner), + std::move(device), std::move(get_pool_cb))); } // static @@ -156,22 +158,19 @@ V4L2SliceVideoDecoder::V4L2SliceVideoDecoder( scoped_refptr<base::SequencedTaskRunner> client_task_runner, + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, scoped_refptr<V4L2Device> device, - std::unique_ptr<DmabufVideoFramePool> frame_pool) + GetFramePoolCB get_pool_cb) : device_(std::move(device)), - frame_pool_(std::move(frame_pool)), + get_pool_cb_(std::move(get_pool_cb)), client_task_runner_(std::move(client_task_runner)), - decoder_task_runner_(base::CreateSequencedTaskRunner( - {base::ThreadPool(), base::WithBaseSyncPrimitives(), - base::TaskPriority::USER_VISIBLE})), + decoder_task_runner_(std::move(decoder_task_runner)), device_poll_thread_("V4L2SliceVideoDecoderDevicePollThread"), weak_this_factory_(this) { DETACH_FROM_SEQUENCE(client_sequence_checker_); DETACH_FROM_SEQUENCE(decoder_sequence_checker_); VLOGF(2); weak_this_ = weak_this_factory_.GetWeakPtr(); - - frame_pool_->set_parent_task_runner(decoder_task_runner_); } V4L2SliceVideoDecoder::~V4L2SliceVideoDecoder() { @@ -245,6 +244,7 @@ DCHECK(surfaces_at_device_.empty()); weak_this_factory_.InvalidateWeakPtrs(); + delete this; VLOGF(2) << "Destroyed"; } @@ -318,6 +318,9 @@ SetState(State::kUninitialized); } + // Setup frame pool. + frame_pool_ = get_pool_cb_.Run(); + // Open V4L2 device. VideoCodecProfile profile = config.profile(); uint32_t input_format_fourcc =
diff --git a/media/gpu/v4l2/v4l2_slice_video_decoder.h b/media/gpu/v4l2/v4l2_slice_video_decoder.h index 51542386..8d5d4fd4 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decoder.h +++ b/media/gpu/v4l2/v4l2_slice_video_decoder.h
@@ -38,12 +38,15 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder, public V4L2DecodeSurfaceHandler { public: + using GetFramePoolCB = base::RepeatingCallback<DmabufVideoFramePool*()>; + // Create V4L2SliceVideoDecoder instance. The success of the creation doesn't // ensure V4L2SliceVideoDecoder is available on the device. It will be // determined in Initialize(). static std::unique_ptr<VideoDecoder> Create( scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<DmabufVideoFramePool> frame_pool); + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, + GetFramePoolCB get_pool_cb); static SupportedVideoDecoderConfigs GetSupportedConfigs(); @@ -80,8 +83,9 @@ V4L2SliceVideoDecoder( scoped_refptr<base::SequencedTaskRunner> client_task_runner, + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, scoped_refptr<V4L2Device> device, - std::unique_ptr<DmabufVideoFramePool> frame_pool); + GetFramePoolCB get_pool_cb); ~V4L2SliceVideoDecoder() override; void Destroy() override; @@ -218,7 +222,8 @@ // V4L2 device in use. scoped_refptr<V4L2Device> device_; // VideoFrame manager used to allocate and recycle video frame. - std::unique_ptr<DmabufVideoFramePool> frame_pool_; + GetFramePoolCB get_pool_cb_; + DmabufVideoFramePool* frame_pool_ = nullptr; // Video decoder used to parse stream headers by software. std::unique_ptr<AcceleratedVideoDecoder> avd_;
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc index 77d7d50..475cd678 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.cc +++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -68,9 +68,11 @@ // static std::unique_ptr<VideoDecoder> VaapiVideoDecoder::Create( scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<DmabufVideoFramePool> frame_pool) { + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, + GetFramePoolCB get_pool_cb) { return base::WrapUnique<VideoDecoder>(new VaapiVideoDecoder( - std::move(client_task_runner), std::move(frame_pool))); + std::move(client_task_runner), std::move(decoder_task_runner), + std::move(get_pool_cb))); } // static @@ -81,10 +83,11 @@ VaapiVideoDecoder::VaapiVideoDecoder( scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<DmabufVideoFramePool> frame_pool) - : frame_pool_(std::move(frame_pool)), + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, + GetFramePoolCB get_pool_cb) + : get_pool_cb_(std::move(get_pool_cb)), client_task_runner_(std::move(client_task_runner)), - decoder_thread_("VaapiDecoderThread"), + decoder_task_runner_(std::move(decoder_task_runner)), weak_this_factory_(this) { DETACH_FROM_SEQUENCE(decoder_sequence_checker_); VLOGF(2); @@ -149,17 +152,7 @@ return; } - if (!decoder_thread_.IsRunning() && !decoder_thread_.Start()) { - std::move(init_cb).Run(false); - return; - } - - if (!decoder_thread_task_runner_) { - decoder_thread_task_runner_ = decoder_thread_.task_runner(); - frame_pool_->set_parent_task_runner(decoder_thread_task_runner_); - } - - decoder_thread_task_runner_->PostTask( + decoder_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::InitializeTask, weak_this_, config, std::move(init_cb), std::move(output_cb))); @@ -227,6 +220,9 @@ } needs_bitstream_conversion_ = (config.codec() == kCodecH264); + // Get and initialize the frame pool. + frame_pool_ = get_pool_cb_.Run(); + visible_rect_ = config.visible_rect(); pixel_aspect_ratio_ = config.GetPixelAspectRatio(); profile_ = profile; @@ -243,14 +239,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); VLOGF(2); - if (decoder_thread_task_runner_) { - decoder_thread_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&VaapiVideoDecoder::DestroyTask, weak_this_)); - decoder_thread_.Stop(); - } - - delete this; - VLOGF(2) << "Destroying VAAPI VD done"; + decoder_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&VaapiVideoDecoder::DestroyTask, weak_this_)); } void VaapiVideoDecoder::DestroyTask() { @@ -265,18 +255,17 @@ decoder_ = nullptr; } - // Drop all video frame references. This will cause the frames to be - // destroyed once the decoder's client is done using them. - frame_pool_ = nullptr; - weak_this_factory_.InvalidateWeakPtrs(); + + delete this; + VLOGF(2) << "Destroying VAAPI VD done"; } void VaapiVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); - decoder_thread_task_runner_->PostTask( + decoder_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::QueueDecodeTask, weak_this_, std::move(buffer), std::move(decode_cb))); } @@ -324,7 +313,7 @@ *current_decode_task_->buffer_); } - decoder_thread_task_runner_->PostTask( + decoder_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_)); } @@ -541,7 +530,7 @@ vaapi_wrapper_->CreateContext(pic_size); // Retry the current decode task. - decoder_thread_task_runner_->PostTask( + decoder_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_)); } @@ -570,7 +559,7 @@ if (state_ == State::kWaitingForOutput) { DCHECK(current_decode_task_); SetState(State::kDecoding); - decoder_thread_task_runner_->PostTask( + decoder_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_)); } @@ -610,7 +599,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DVLOGF(2); - decoder_thread_task_runner_->PostTask( + decoder_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetTask, weak_this_, std::move(reset_cb))); } @@ -632,7 +621,7 @@ SetState(State::kResetting); // Wait until any pending decode task has been aborted. - decoder_thread_task_runner_->PostTask( + decoder_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetDoneTask, weak_this_, std::move(reset_cb))); }
diff --git a/media/gpu/vaapi/vaapi_video_decoder.h b/media/gpu/vaapi/vaapi_video_decoder.h index 5ffd13da..472ee24 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.h +++ b/media/gpu/vaapi/vaapi_video_decoder.h
@@ -39,9 +39,12 @@ class VaapiVideoDecoder : public media::VideoDecoder, public DecodeSurfaceHandler<VASurface> { public: + using GetFramePoolCB = base::RepeatingCallback<DmabufVideoFramePool*()>; + static std::unique_ptr<VideoDecoder> Create( scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<DmabufVideoFramePool> frame_pool); + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, + GetFramePoolCB get_pool); static SupportedVideoDecoderConfigs GetSupportedConfigs(); @@ -91,8 +94,10 @@ kError, // decoder encountered an error. }; - VaapiVideoDecoder(scoped_refptr<base::SequencedTaskRunner> client_task_runner, - std::unique_ptr<DmabufVideoFramePool> frame_pool); + VaapiVideoDecoder( + scoped_refptr<base::SequencedTaskRunner> client_task_runner, + scoped_refptr<base::SequencedTaskRunner> decoder_task_runner, + GetFramePoolCB get_pool); ~VaapiVideoDecoder() override; // Destroy the VAAPIVideoDecoder, aborts pending decode requests and blocks @@ -171,7 +176,8 @@ double pixel_aspect_ratio_ = 0.0; // Video frame pool used to allocate and recycle video frames. - std::unique_ptr<DmabufVideoFramePool> frame_pool_; + GetFramePoolCB get_pool_cb_; + DmabufVideoFramePool* frame_pool_ = nullptr; // The mapping between buffer id and the timestamp. std::map<int32_t, base::TimeDelta> buffer_id_to_timestamp_; @@ -191,8 +197,7 @@ scoped_refptr<VaapiWrapper> vaapi_wrapper_; const scoped_refptr<base::SequencedTaskRunner> client_task_runner_; - base::Thread decoder_thread_; - scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_; + const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_; SEQUENCE_CHECKER(client_sequence_checker_); SEQUENCE_CHECKER(decoder_sequence_checker_);
diff --git a/net/dns/dns_client.cc b/net/dns/dns_client.cc index 20a940b..b0d235d5 100644 --- a/net/dns/dns_client.cc +++ b/net/dns/dns_client.cc
@@ -7,7 +7,9 @@ #include <utility> #include "base/bind.h" +#include "base/metrics/field_trial.h" #include "base/rand_util.h" +#include "base/timer/timer.h" #include "base/values.h" #include "net/dns/address_sorter.h" #include "net/dns/dns_session.h" @@ -39,17 +41,33 @@ return c1.value() == *c2; } -class DnsClientImpl : public DnsClient { +constexpr base::TimeDelta kInitialDoHTimeout = + base::TimeDelta::FromMilliseconds(5000); + +class DnsClientImpl : public DnsClient, + public NetworkChangeNotifier::ConnectionTypeObserver { public: DnsClientImpl(NetLog* net_log, ClientSocketFactory* socket_factory, const RandIntCallback& rand_int_callback) - : net_log_(net_log), + : probes_allowed_(false), + url_request_context_for_probes_(nullptr), + net_log_(net_log), socket_factory_(socket_factory), - rand_int_callback_(rand_int_callback) {} + rand_int_callback_(rand_int_callback) { + NetworkChangeNotifier::AddConnectionTypeObserver(this); + delayed_probes_allowed_timer_.Start( + FROM_HERE, kInitialDoHTimeout, + base::Bind(&DnsClientImpl::SetProbesAllowed, base::Unretained(this))); + } + + ~DnsClientImpl() override { + NetworkChangeNotifier::RemoveConnectionTypeObserver(this); + } bool CanUseSecureDnsTransactions() const override { - return HasAvailableDohServer(); + const DnsConfig* config = GetEffectiveConfig(); + return config && config->dns_over_https_servers.size() > 0; } bool CanUseInsecureDnsTransactions() const override { @@ -61,6 +79,13 @@ insecure_enabled_ = enabled; } + bool FallbackFromSecureTransactionPreferred() const override { + if (!CanUseSecureDnsTransactions()) + return true; + + return !(session_.get() && session_->HasAvailableDohServer()); + } + bool FallbackFromInsecureTransactionPreferred() const override { return !CanUseInsecureDnsTransactions() || insecure_fallback_failures_ >= kMaxInsecureFallbackFailures; @@ -100,6 +125,11 @@ return &config->hosts; } + void SetRequestContextForProbes( + URLRequestContext* url_request_context) override { + url_request_context_for_probes_ = url_request_context; + } + DnsTransactionFactory* GetTransactionFactory() override { return session_.get() ? factory_.get() : nullptr; } @@ -122,6 +152,10 @@ return config_overrides_; } + void SetProbeSuccessForTest(unsigned index, bool success) override { + session_->SetProbeSuccess(index, success); + } + private: base::Optional<DnsConfig> BuildEffectiveConfig() const { DnsConfig config; @@ -175,16 +209,37 @@ new DnsSession(std::move(new_effective_config).value(), std::move(socket_pool), rand_int_callback_, net_log_); factory_ = DnsTransactionFactory::CreateFactory(session_.get()); + StartDohProbes(); } } - bool HasAvailableDohServer() const { - // TODO(crbug.com/985589): Once DoH probes are sent, update this such that a - // DoH server is considered successful if it has a successful probe state. - const DnsConfig* config = GetEffectiveConfig(); - return config && config->dns_over_https_servers.size() > 0; + void OnConnectionTypeChanged( + NetworkChangeNotifier::ConnectionType type) override { + if (session_) { + session_->UpdateTimeouts(type); + const char* kTrialName = "AsyncDnsFlushServerStatsOnConnectionTypeChange"; + if (base::FieldTrialList::FindFullName(kTrialName) == "enable") + session_->InitializeServerStats(); + if (type != NetworkChangeNotifier::CONNECTION_NONE) + StartDohProbes(); + } } + void StartDohProbes() { + if (probes_allowed_) { + factory_->StartDohProbes(url_request_context_for_probes_); + } else { + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&DnsTransactionFactory::StartDohProbes, + factory_->weak_factory_.GetWeakPtr(), + url_request_context_for_probes_), + delayed_probes_allowed_timer_.GetCurrentDelay()); + } + } + + void SetProbesAllowed() { probes_allowed_ = true; } + bool insecure_enabled_ = false; int insecure_fallback_failures_ = 0; @@ -195,6 +250,11 @@ std::unique_ptr<DnsTransactionFactory> factory_; std::unique_ptr<AddressSorter> address_sorter_ = AddressSorter::CreateAddressSorter(); + // Probes are not allowed until some amount of time has passed in order to + // prevent interference with startup tasks. + bool probes_allowed_; + base::OneShotTimer delayed_probes_allowed_timer_; + URLRequestContext* url_request_context_for_probes_; NetLog* net_log_;
diff --git a/net/dns/dns_client.h b/net/dns/dns_client.h index 9914ef9e..8e71e852 100644 --- a/net/dns/dns_client.h +++ b/net/dns/dns_client.h
@@ -13,6 +13,7 @@ #include "net/dns/dns_config.h" #include "net/dns/dns_config_overrides.h" #include "net/dns/dns_hosts.h" +#include "net/url_request/url_request_context.h" namespace net { @@ -40,6 +41,10 @@ virtual bool CanUseInsecureDnsTransactions() const = 0; virtual void SetInsecureEnabled(bool enabled) = 0; + // When true, DoH should not be used in AUTOMATIC mode since no DoH servers + // have a successful probe state. + virtual bool FallbackFromSecureTransactionPreferred() const = 0; + // When true, insecure DNS transactions should not be used when reasonable // fallback alternatives, e.g. system resolution can be used instead. virtual bool FallbackFromInsecureTransactionPreferred() const = 0; @@ -58,6 +63,10 @@ virtual const DnsConfig* GetEffectiveConfig() const = 0; virtual const DnsHosts* GetHosts() const = 0; + // Sets the URLRequestContext to use for issuing DoH probes. + virtual void SetRequestContextForProbes( + URLRequestContext* url_request_context) = 0; + // Returns null if the current config is not valid. virtual DnsTransactionFactory* GetTransactionFactory() = 0; @@ -69,6 +78,8 @@ virtual base::Optional<DnsConfig> GetSystemConfigForTesting() const = 0; virtual DnsConfigOverrides GetConfigOverridesForTesting() const = 0; + virtual void SetProbeSuccessForTest(unsigned index, bool success) = 0; + // Creates default client. static std::unique_ptr<DnsClient> CreateClient(NetLog* net_log);
diff --git a/net/dns/dns_client_unittest.cc b/net/dns/dns_client_unittest.cc index 2f969f9..edb83024 100644 --- a/net/dns/dns_client_unittest.cc +++ b/net/dns/dns_client_unittest.cc
@@ -66,6 +66,7 @@ client_->SetInsecureEnabled(true); EXPECT_FALSE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_FALSE(client_->CanUseInsecureDnsTransactions()); EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred()); @@ -79,6 +80,7 @@ client_->SetSystemConfig(DnsConfig()); EXPECT_FALSE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_FALSE(client_->CanUseInsecureDnsTransactions()); EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred()); @@ -92,6 +94,7 @@ client_->SetSystemConfig(BasicValidConfig()); EXPECT_FALSE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_TRUE(client_->CanUseInsecureDnsTransactions()); EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred()); @@ -106,6 +109,7 @@ client_->SetSystemConfig(ValidConfigWithDoh()); EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_FALSE(client_->CanUseInsecureDnsTransactions()); EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred()); @@ -115,6 +119,16 @@ EXPECT_TRUE(client_->GetTransactionFactory()); } +TEST_F(DnsClientTest, CanUseSecureDnsTransactions_ProbeSuccess) { + client_->SetSystemConfig(ValidConfigWithDoh()); + EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); + + client_->SetProbeSuccessForTest(0, true /* success */); + EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_FALSE(client_->FallbackFromSecureTransactionPreferred()); +} + TEST_F(DnsClientTest, DnsOverTlsActive) { client_->SetInsecureEnabled(true); DnsConfig config = ValidConfigWithDoh(); @@ -122,6 +136,7 @@ client_->SetSystemConfig(config); EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_FALSE(client_->CanUseInsecureDnsTransactions()); EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred()); @@ -133,8 +148,10 @@ TEST_F(DnsClientTest, AllAllowed) { client_->SetInsecureEnabled(true); client_->SetSystemConfig(ValidConfigWithDoh()); + client_->SetProbeSuccessForTest(0, true /* success */); EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_FALSE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_TRUE(client_->CanUseInsecureDnsTransactions()); EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred()); @@ -150,6 +167,7 @@ for (int i = 0; i < DnsClient::kMaxInsecureFallbackFailures; ++i) { EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_TRUE(client_->CanUseInsecureDnsTransactions()); EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred()); @@ -157,12 +175,14 @@ } EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_TRUE(client_->CanUseInsecureDnsTransactions()); EXPECT_TRUE(client_->FallbackFromInsecureTransactionPreferred()); client_->ClearInsecureFallbackFailures(); EXPECT_TRUE(client_->CanUseSecureDnsTransactions()); + EXPECT_TRUE(client_->FallbackFromSecureTransactionPreferred()); EXPECT_TRUE(client_->CanUseInsecureDnsTransactions()); EXPECT_FALSE(client_->FallbackFromInsecureTransactionPreferred()); }
diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc index 6164f313..e55427578 100644 --- a/net/dns/dns_session.cc +++ b/net/dns/dns_session.cc
@@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/lazy_instance.h" #include "base/macros.h" -#include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/sample_vector.h" #include "base/rand_util.h" @@ -20,6 +19,7 @@ #include "base/time/time.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/dns/dns_config.h" #include "net/dns/dns_socket_pool.h" #include "net/dns/dns_util.h" #include "net/log/net_log_event_type.h" @@ -45,6 +45,8 @@ const size_t kRTTBucketCount = 350; // Target percentile in the RTT histogram used for retransmission timeout. const unsigned kRTOPercentile = 99; +// Number of samples to seed the histogram with. +const unsigned kNumSeeds = 2; } // namespace @@ -56,7 +58,7 @@ // Seed histogram with 2 samples at |rtt_estimate| timeout. rtt_histogram->Accumulate( static_cast<base::HistogramBase::Sample>(rtt_estimate.InMilliseconds()), - 2); + kNumSeeds); } // Count of consecutive failures after last success. @@ -114,12 +116,9 @@ config_.nameservers.size(), 1, 10, 11); UpdateTimeouts(NetworkChangeNotifier::GetConnectionType()); InitializeServerStats(); - NetworkChangeNotifier::AddConnectionTypeObserver(this); } -DnsSession::~DnsSession() { - NetworkChangeNotifier::RemoveConnectionTypeObserver(this); -} +DnsSession::~DnsSession() = default; void DnsSession::UpdateTimeouts(NetworkChangeNotifier::ConnectionType type) { initial_timeout_ = GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault( @@ -131,20 +130,16 @@ void DnsSession::InitializeServerStats() { server_stats_.clear(); - for (size_t i = 0; - i < config_.nameservers.size() + config_.dns_over_https_servers.size(); - ++i) { + for (size_t i = 0; i < config_.nameservers.size(); ++i) { server_stats_.push_back(std::make_unique<ServerStats>( initial_timeout_, rtt_buckets_.Pointer())); } -} -void DnsSession::OnConnectionTypeChanged( - NetworkChangeNotifier::ConnectionType type) { - UpdateTimeouts(type); - const char* kTrialName = "AsyncDnsFlushServerStatsOnConnectionTypeChange"; - if (base::FieldTrialList::FindFullName(kTrialName) == "enable") { - InitializeServerStats(); + doh_server_stats_.clear(); + for (size_t i = 0; i < config_.dns_over_https_servers.size(); ++i) { + doh_server_stats_.push_back(std::make_pair( + std::make_unique<ServerStats>(initial_timeout_, rtt_buckets_.Pointer()), + false)); } } @@ -167,13 +162,13 @@ unsigned oldest_server_failure_index = 0; do { - base::Time cur_server_failure = server_stats_[index]->last_failure; // If number of failures on this server doesn't exceed number of allowed // attempts, return its index. if (server_stats_[server_index]->last_failure_count < config_.attempts) { return index; } // Track oldest failed server. + base::Time cur_server_failure = server_stats_[index]->last_failure; if (cur_server_failure < oldest_server_failure) { oldest_server_failure = cur_server_failure; oldest_server_failure_index = index; @@ -186,85 +181,164 @@ return oldest_server_failure_index; } -unsigned DnsSession::NextGoodDnsOverHttpsServerIndex(unsigned server_index) { - DCHECK_GE(server_index, config_.nameservers.size()); - DCHECK_LT(server_index, - config_.nameservers.size() + config_.dns_over_https_servers.size()); - unsigned index = server_index; +int DnsSession::NextGoodDohServerIndex( + unsigned doh_server_index, + DnsConfig::SecureDnsMode secure_dns_mode) { + DCHECK_GE(doh_server_index, 0u); + DCHECK_LT(doh_server_index, config_.dns_over_https_servers.size()); + unsigned index = doh_server_index; base::Time oldest_server_failure(base::Time::Now()); - unsigned oldest_server_failure_index = config_.nameservers.size(); + int oldest_available_server_failure_index = -1; do { - base::Time cur_server_failure = server_stats_[index]->last_failure; - // If number of failures on this server doesn't exceed number of allowed - // attempts, return its index. - if (server_stats_[index]->last_failure_count < config_.attempts) { - return index; + // For a server to be considered "available", the server must have a + // successful probe status if we are in AUTOMATIC mode. + if (secure_dns_mode == DnsConfig::SecureDnsMode::SECURE || + doh_server_stats_[index].second) { + // If number of failures on this server doesn't exceed |config_.attempts|, + // return its index. |config_.attempts| will generally be more restrictive + // than |kAutomaticModeFailureLimit|, although this is not guaranteed. + const ServerStats* stats = + GetServerStats(index, true /* is_doh_server */); + if (stats->last_failure_count < config_.attempts) { + return index; + } + // Track oldest failed available server. + base::Time cur_server_failure = stats->last_failure; + if (cur_server_failure < oldest_server_failure) { + oldest_server_failure = cur_server_failure; + oldest_available_server_failure_index = index; + } } - // Track oldest failed server. - if (cur_server_failure < oldest_server_failure) { - oldest_server_failure = cur_server_failure; - oldest_server_failure_index = index; - } - // Index of dns over https servers begins at nameservers.size(). - unsigned doh_index = index - config_.nameservers.size(); - doh_index = ((doh_index + 1) % config_.dns_over_https_servers.size()); - index = doh_index + config_.nameservers.size(); - } while (index != server_index); + index = (index + 1) % config_.dns_over_https_servers.size(); + } while (index != doh_server_index); - // If we are here it means that there are no successful servers, so we have - // to use one that has failed oldest. - return oldest_server_failure_index; + // If we are here it means that there are either no available DoH servers or + // that all available DoH servers have at least |config_.attempts| consecutive + // failures. In the latter case, we'll return the available DoH server that + // failed least recently. In the former case we return -1. + return oldest_available_server_failure_index; } -void DnsSession::RecordServerFailure(unsigned server_index) { - ++(server_stats_[server_index]->last_failure_count); - server_stats_[server_index]->last_failure = base::Time::Now(); +bool DnsSession::HasAvailableDohServer() { + for (const auto& doh_stats_ : doh_server_stats_) { + if (doh_stats_.second) + return true; + } + return false; } -void DnsSession::RecordServerSuccess(unsigned server_index) { - server_stats_[server_index]->last_failure_count = 0; - server_stats_[server_index]->last_failure = base::Time(); - server_stats_[server_index]->last_success = base::Time::Now(); +unsigned DnsSession::NumAvailableDohServers() { + unsigned count = 0; + for (const auto& doh_stats_ : doh_server_stats_) { + if (doh_stats_.second) + count++; + } + return count; } -void DnsSession::RecordRTT(unsigned server_index, base::TimeDelta rtt) { - DCHECK_LT(server_index, server_stats_.size()); +DnsSession::ServerStats* DnsSession::GetServerStats(unsigned server_index, + bool is_doh_server) { + DCHECK_GE(server_index, 0u); + if (!is_doh_server) { + DCHECK_LT(server_index, config_.nameservers.size()); + return server_stats_[server_index].get(); + } else { + DCHECK_LT(server_index, config_.dns_over_https_servers.size()); + return doh_server_stats_[server_index].first.get(); + } +} + +void DnsSession::RecordServerFailure(unsigned server_index, + bool is_doh_server) { + ServerStats* stats = GetServerStats(server_index, is_doh_server); + ++(stats->last_failure_count); + stats->last_failure = base::Time::Now(); + + if (is_doh_server && + stats->last_failure_count >= kAutomaticModeFailureLimit) { + SetProbeSuccess(server_index, false /* success */); + } +} + +void DnsSession::RecordServerSuccess(unsigned server_index, + bool is_doh_server) { + ServerStats* stats = GetServerStats(server_index, is_doh_server); + + // DoH queries can be sent using more than one URLRequestContext. A success + // from one URLRequestContext shouldn't zero out failures that may be + // consistently occurring for another URLRequestContext. + if (!is_doh_server) + stats->last_failure_count = 0; + stats->last_failure = base::Time(); + stats->last_success = base::Time::Now(); +} + +void DnsSession::SetProbeSuccess(unsigned doh_server_index, bool success) { + DCHECK_GE(doh_server_index, 0u); + DCHECK_LT(doh_server_index, config_.dns_over_https_servers.size()); + doh_server_stats_[doh_server_index].second = success; +} + +void DnsSession::RecordRTT(unsigned server_index, + bool is_doh_server, + bool is_probe, + base::TimeDelta rtt) { + ServerStats* stats = GetServerStats(server_index, is_doh_server); + // If the histogram has not yet been populated beyond the initial seed values + // and this was a probe query, replace the seed values with a multiple of + // the probe's RTT. + if (is_probe && stats->rtt_histogram->TotalCount() == kNumSeeds) { + DCHECK(is_doh_server); + doh_server_stats_[server_index].first = std::make_unique<ServerStats>( + rtt * kDohProbeTimeMultiplier, rtt_buckets_.Pointer()); + return; + } // Jacobson/Karels algorithm for TCP. // Using parameters: alpha = 1/8, delta = 1/4, beta = 4 - base::TimeDelta& estimate = server_stats_[server_index]->rtt_estimate; - base::TimeDelta& deviation = server_stats_[server_index]->rtt_deviation; + base::TimeDelta& estimate = stats->rtt_estimate; + base::TimeDelta& deviation = stats->rtt_deviation; base::TimeDelta current_error = rtt - estimate; estimate += current_error / 8; // * alpha base::TimeDelta abs_error = base::TimeDelta::FromInternalValue( std::abs(current_error.ToInternalValue())); deviation += (abs_error - deviation) / 4; // * delta - // RTT values shouldn't be less than 0, but it shouldn't cause a crash if they - // are anyway, so clip to 0. See https://crbug.com/753568. + // RTT values shouldn't be less than 0, but it shouldn't cause a crash if + // they are anyway, so clip to 0. See https://crbug.com/753568. int32_t rtt_ms = rtt.InMilliseconds(); if (rtt_ms < 0) rtt_ms = 0; // Histogram-based method. - server_stats_[server_index]->rtt_histogram->Accumulate( + stats->rtt_histogram->Accumulate( static_cast<base::HistogramBase::Sample>(rtt_ms), 1); } base::TimeDelta DnsSession::NextTimeout(unsigned server_index, int attempt) { + return NextTimeoutHelper( + GetServerStats(server_index, false /* is _doh_server */), + attempt / config_.nameservers.size()); +} + +base::TimeDelta DnsSession::NextDohTimeout(unsigned doh_server_index) { + return NextTimeoutHelper( + GetServerStats(doh_server_index, true /* is _doh_server */), + 0 /* num_backoffs */); +} + +base::TimeDelta DnsSession::NextTimeoutHelper(ServerStats* server_stats, + int num_backoffs) { // Respect initial timeout (from config or field trial) if it exceeds max. if (initial_timeout_ > max_timeout_) return initial_timeout_; - DCHECK_LT(server_index, server_stats_.size()); - static_assert(std::numeric_limits<base::HistogramBase::Count>::is_signed, "histogram base count assumed to be signed"); // Use fixed percentile of observed samples. - const base::SampleVector& samples = - *server_stats_[server_index]->rtt_histogram; + const base::SampleVector& samples = *server_stats->rtt_histogram; base::HistogramBase::Count total = samples.TotalCount(); base::HistogramBase::Count remaining_count = kRTOPercentile * total / 100; @@ -279,9 +353,6 @@ timeout = std::max(timeout, base::TimeDelta::FromMilliseconds(kMinTimeoutMs)); - // The timeout still doubles every full round. - unsigned num_backoffs = attempt / config_.nameservers.size(); - return std::min(timeout * (1 << num_backoffs), max_timeout_); }
diff --git a/net/dns/dns_session.h b/net/dns/dns_session.h index b16cfb1..566f3ba 100644 --- a/net/dns/dns_session.h +++ b/net/dns/dns_session.h
@@ -32,12 +32,22 @@ struct NetLogSource; class StreamSocket; +// Number of failures allowed before a DoH server is designated 'unavailable'. +// In AUTOMATIC mode, non-probe DoH queries should not be sent to DoH servers +// that have reached this limit. +// This limit is different from the failure limit that governs insecure async +// resolver bypass in several ways: the failures need not be consecutive, +// NXDOMAIN responses are never counted as failures, and the outcome of +// fallback queries is not taken into account. +const int kAutomaticModeFailureLimit = 10; + +// Amount to scale a successful DoH probe RTT when setting a new seed timeout. +const double kDohProbeTimeMultiplier = 1.5; + // Session parameters and state shared between DNS transactions. // Ref-counted so that DnsClient::Request can keep working in absence of // DnsClient. A DnsSession must be recreated when DnsConfig changes. -class NET_EXPORT_PRIVATE DnsSession - : public base::RefCounted<DnsSession>, - public NetworkChangeNotifier::ConnectionTypeObserver { +class NET_EXPORT_PRIVATE DnsSession : public base::RefCounted<DnsSession> { public: typedef base::Callback<int()> RandCallback; @@ -68,6 +78,9 @@ const DnsConfig& config() const { return config_; } NetLog* net_log() const { return net_log_; } + void UpdateTimeouts(NetworkChangeNotifier::ConnectionType type); + void InitializeServerStats(); + // Return the next random query ID. uint16_t NextQueryId() const; @@ -76,28 +89,48 @@ // Start with |server_index| and find the index of the next known // good non-dns-over-https server to use on this attempt. Returns - // |server_index| if this server has no recorded failures, or if - // there are no other servers that have not failed or have failed - // longer time ago. + // |server_index| if this server is below the failure limit, or if there are + // no other servers below the failure limit or with an older last failure. unsigned NextGoodServerIndex(unsigned server_index); - // Same as above, but for DNS over HTTPS servers and ignoring - // non-dns-over-https servers - unsigned NextGoodDnsOverHttpsServerIndex(unsigned server_index); + // Similar to |NextGoodServerIndex| except for DoH servers. If no DoH server + // is under the failure limit in AUTOMATIC mode, returns -1. + int NextGoodDohServerIndex(unsigned doh_server_index, + DnsConfig::SecureDnsMode secure_dns_mode); - // Record that server failed to respond (due to SRV_FAIL or timeout). - void RecordServerFailure(unsigned server_index); + // Returns whether there is a DoH server that has a successful probe state. + bool HasAvailableDohServer(); + + // Returns the number of DoH servers with successful probe states. + unsigned NumAvailableDohServers(); + + // Record that server failed to respond (due to SRV_FAIL or timeout). If + // |is_doh_server| and the number of failures has surpassed a threshold, + // sets the DoH probe state to unavailable. + void RecordServerFailure(unsigned server_index, bool is_doh_server); // Record that server responded successfully. - void RecordServerSuccess(unsigned server_index); + void RecordServerSuccess(unsigned server_index, bool is_doh_server); - // Record how long it took to receive a response from the server. - void RecordRTT(unsigned server_index, base::TimeDelta rtt); + // Record the latest DoH probe state. + void SetProbeSuccess(unsigned doh_server_index, bool success); + + // Record how long it took to receive a response from the server. If + // |is_probe| and the underlying |ServerStats::rtt_histogram| has not been + // populated by real query times yet, update the seed value for the histogram + // to a scaled version of |rtt|. + void RecordRTT(unsigned server_index, + bool is_doh_server, + bool is_probe, + base::TimeDelta rtt); // Return the timeout for the next query. |attempt| counts from 0 and is used // for exponential backoff. base::TimeDelta NextTimeout(unsigned server_index, int attempt); + // Return the timeout for the next DoH query. + base::TimeDelta NextDohTimeout(unsigned doh_server_index); + // Allocate a socket, already connected to the server address. // When the SocketLease is destroyed, the socket will be freed. std::unique_ptr<SocketLease> AllocateSocket(unsigned server_index, @@ -110,18 +143,19 @@ private: friend class base::RefCounted<DnsSession>; - ~DnsSession() override; - - void UpdateTimeouts(NetworkChangeNotifier::ConnectionType type); - void InitializeServerStats(); + struct ServerStats; + ~DnsSession(); // Release a socket. void FreeSocket(unsigned server_index, std::unique_ptr<DatagramClientSocket> socket); - // NetworkChangeNotifier::ConnectionTypeObserver: - void OnConnectionTypeChanged( - NetworkChangeNotifier::ConnectionType type) override; + // Returns the ServerStats for the designated server. Returns nullptr if no + // ServerStats found. + ServerStats* GetServerStats(unsigned server_index, bool is_doh_server); + + // Return the timeout for the next query. + base::TimeDelta NextTimeoutHelper(ServerStats* server_stats, int attempt); const DnsConfig config_; std::unique_ptr<DnsSocketPool> socket_pool_; @@ -134,14 +168,12 @@ base::TimeDelta initial_timeout_; base::TimeDelta max_timeout_; - struct ServerStats; - - // Track runtime statistics of each DNS server. This combines both - // dns-over-https servers and non-dns-over-https servers. - // non-dns-over-https servers come first and dns-over-https servers - // started at the index of nameservers.size(). + // Track runtime statistics of each insecure DNS server. std::vector<std::unique_ptr<ServerStats>> server_stats_; + // Track runtime statistics and availability of each DoH server. + std::vector<std::pair<std::unique_ptr<ServerStats>, bool>> doh_server_stats_; + // Buckets shared for all |ServerStats::rtt_histogram|. struct RttBuckets : public base::BucketRanges { RttBuckets();
diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc index 4a6ae56..ebb461f 100644 --- a/net/dns/dns_session_unittest.cc +++ b/net/dns/dns_session_unittest.cc
@@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/rand_util.h" +#include "base/strings/stringprintf.h" #include "net/base/ip_address.h" #include "net/dns/dns_socket_pool.h" #include "net/dns/public/dns_protocol.h" @@ -83,7 +84,7 @@ void OnSocketFreed(unsigned server_index); protected: - void Initialize(unsigned num_servers); + void Initialize(unsigned num_servers, unsigned num_doh_servers); std::unique_ptr<DnsSession::SocketLease> Allocate(unsigned server_index); bool DidAllocate(unsigned server_index); bool DidFree(unsigned server_index); @@ -126,14 +127,23 @@ DnsSessionTest* test_; }; -void DnsSessionTest::Initialize(unsigned num_servers) { +void DnsSessionTest::Initialize(unsigned num_servers, + unsigned num_doh_servers) { CHECK(num_servers < 256u); config_.nameservers.clear(); + config_.dns_over_https_servers.clear(); for (unsigned char i = 0; i < num_servers; ++i) { IPEndPoint dns_endpoint(IPAddress(192, 168, 1, i), dns_protocol::kDefaultPort); config_.nameservers.push_back(dns_endpoint); } + for (unsigned char i = 0; i < num_doh_servers; ++i) { + std::string server_template( + base::StringPrintf("https://mock.http/doh_test_%d{?dns}", i)); + config_.dns_over_https_servers.push_back( + DnsConfig::DnsOverHttpsServerConfig(server_template, + true /* is_post */)); + } test_client_socket_factory_.reset(new TestClientSocketFactory()); @@ -210,7 +220,7 @@ TEST_F(DnsSessionTest, AllocateFree) { std::unique_ptr<DnsSession::SocketLease> lease1, lease2; - Initialize(2); + Initialize(2 /* num_servers */, 0 /* num_doh_servers */); EXPECT_TRUE(NoMoreEvents()); lease1 = Allocate(0); @@ -232,17 +242,21 @@ // Expect default calculated timeout to be within 10ms of one in DnsConfig. TEST_F(DnsSessionTest, HistogramTimeoutNormal) { - Initialize(2); + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); base::TimeDelta delta = session_->NextTimeout(0, 0) - config_.timeout; EXPECT_LE(delta.InMilliseconds(), 10); + delta = session_->NextDohTimeout(0) - config_.timeout; + EXPECT_LE(delta.InMilliseconds(), 10); } // Expect short calculated timeout to be within 10ms of one in DnsConfig. TEST_F(DnsSessionTest, HistogramTimeoutShort) { config_.timeout = base::TimeDelta::FromMilliseconds(15); - Initialize(2); + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); base::TimeDelta delta = session_->NextTimeout(0, 0) - config_.timeout; EXPECT_LE(delta.InMilliseconds(), 10); + delta = session_->NextDohTimeout(0) - config_.timeout; + EXPECT_LE(delta.InMilliseconds(), 10); } // Expect long calculated timeout to be equal to one in DnsConfig. @@ -250,16 +264,78 @@ // the config timeout.) TEST_F(DnsSessionTest, HistogramTimeoutLong) { config_.timeout = base::TimeDelta::FromSeconds(15); - Initialize(2); + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); base::TimeDelta timeout = session_->NextTimeout(0, 0); EXPECT_EQ(timeout.InMilliseconds(), config_.timeout.InMilliseconds()); + timeout = session_->NextDohTimeout(0); + EXPECT_EQ(timeout.InMilliseconds(), config_.timeout.InMilliseconds()); } // Ensures that reported negative RTT values don't cause a crash. Regression // test for https://crbug.com/753568. TEST_F(DnsSessionTest, NegativeRtt) { - Initialize(2); - session_->RecordRTT(0, base::TimeDelta::FromMilliseconds(-1)); + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); + session_->RecordRTT(0, false /* is_doh_server */, false /* is_probe */, + base::TimeDelta::FromMilliseconds(-1)); + session_->RecordRTT(0, true /* is_doh_server */, false /* is_probe */, + base::TimeDelta::FromMilliseconds(-1)); +} + +TEST_F(DnsSessionTest, DohServerAvailability) { + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); + EXPECT_FALSE(session_->HasAvailableDohServer()); + EXPECT_EQ(session_->NumAvailableDohServers(), 0u); + session_->SetProbeSuccess(1, true /* success */); + EXPECT_TRUE(session_->HasAvailableDohServer()); + EXPECT_EQ(session_->NumAvailableDohServers(), 1u); + + // Record a probe failure. + session_->SetProbeSuccess(1, false /* success */); + EXPECT_FALSE(session_->HasAvailableDohServer()); + EXPECT_EQ(session_->NumAvailableDohServers(), 0u); +} + +TEST_F(DnsSessionTest, DohProbeConsecutiveFailures) { + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); + session_->SetProbeSuccess(1, true /* success */); + + for (size_t i = 0; i < kAutomaticModeFailureLimit; i++) { + EXPECT_TRUE(session_->HasAvailableDohServer()); + session_->RecordServerFailure(1, true /* is_doh_server */); + } + EXPECT_FALSE(session_->HasAvailableDohServer()); +} + +TEST_F(DnsSessionTest, DohProbeNonConsecutiveFailures) { + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); + session_->SetProbeSuccess(1, true /* success */); + + for (size_t i = 0; i < kAutomaticModeFailureLimit - 1; i++) { + EXPECT_TRUE(session_->HasAvailableDohServer()); + session_->RecordServerFailure(1, true /* is_doh_server */); + } + EXPECT_TRUE(session_->HasAvailableDohServer()); + + session_->RecordServerSuccess(1, true /* is_doh_server */); + EXPECT_TRUE(session_->HasAvailableDohServer()); + + session_->RecordServerFailure(1, true /* is_doh_server */); + EXPECT_FALSE(session_->HasAvailableDohServer()); +} + +TEST_F(DnsSessionTest, DohProbeRtt) { + Initialize(2 /* num_servers */, 2 /* num_doh_servers */); + base::TimeDelta probe_time = base::TimeDelta::FromMilliseconds(300); + session_->RecordRTT(1, true /* is_doh_server */, true /* is_probe */, + probe_time); + + // Only the DoH server that had the successful probe should have an updated + // histogram. + base::TimeDelta delta = + session_->NextDohTimeout(1) - probe_time * kDohProbeTimeMultiplier; + EXPECT_LE(delta.InMilliseconds(), 10); + delta = session_->NextDohTimeout(0) - config_.timeout; + EXPECT_GE(delta.InMilliseconds(), 10); } } // namespace
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc index 42cd367..a5834e4 100644 --- a/net/dns/dns_test_util.cc +++ b/net/dns/dns_test_util.cc
@@ -188,6 +188,7 @@ const std::string& hostname, uint16_t qtype, bool secure, + DnsConfig::SecureDnsMode secure_dns_mode, URLRequestContext* url_request_context, DnsTransactionFactory::CallbackType callback) : result_(MockDnsClientRule::FAIL), @@ -465,10 +466,11 @@ DnsTransactionFactory::CallbackType callback, const NetLogWithSource&, bool secure, + DnsConfig::SecureDnsMode secure_dns_mode, URLRequestContext* url_request_context) override { std::unique_ptr<MockTransaction> transaction = std::make_unique<MockTransaction>(rules_, hostname, qtype, secure, - url_request_context, + secure_dns_mode, url_request_context, std::move(callback)); if (transaction->delayed()) delayed_transactions_.push_back(transaction->AsWeakPtr()); @@ -477,6 +479,18 @@ void AddEDNSOption(const OptRecordRdata::Opt& opt) override {} + base::TimeDelta GetDelayUntilNextProbeForTest( + unsigned doh_server_index) override { + NOTREACHED(); + return base::TimeDelta(); + } + + void StartDohProbes(URLRequestContext* url_request_context) override {} + + DnsConfig::SecureDnsMode GetSecureDnsModeForTest() override { + return DnsConfig::SecureDnsMode::AUTOMATIC; + } + void CompleteDelayedTransactions() { DelayedTransactionList old_delayed_transactions; old_delayed_transactions.swap(delayed_transactions_); @@ -518,6 +532,10 @@ insecure_enabled_ = enabled; } +bool MockDnsClient::FallbackFromSecureTransactionPreferred() const { + return !CanUseSecureDnsTransactions() || !doh_server_available_; +} + bool MockDnsClient::FallbackFromInsecureTransactionPreferred() const { return !CanUseInsecureDnsTransactions() || fallback_failures_ >= max_fallback_failures_; @@ -552,6 +570,9 @@ return &config->hosts; } +void MockDnsClient::SetRequestContextForProbes( + URLRequestContext* url_request_context) {} + DnsTransactionFactory* MockDnsClient::GetTransactionFactory() { return GetEffectiveConfig() ? factory_.get() : nullptr; } @@ -576,6 +597,8 @@ return overrides_; } +void MockDnsClient::SetProbeSuccessForTest(unsigned index, bool success) {} + void MockDnsClient::CompleteDelayedTransactions() { factory_->CompleteDelayedTransactions(); }
diff --git a/net/dns/dns_test_util.h b/net/dns/dns_test_util.h index 0d2596d..7b5e751 100644 --- a/net/dns/dns_test_util.h +++ b/net/dns/dns_test_util.h
@@ -157,6 +157,26 @@ // +2 for the CNAME records, +1 for TXT record. static const unsigned kT3RecordCount = base::size(kT3IpAddresses) + 3; +//----------------------------------------------------------------------------- +// Query/response set for www.gstatic.com, ID is fixed to 4. +static const char kT4HostName[] = "www.gstatic.com"; +static const uint16_t kT4Qtype = dns_protocol::kTypeA; +static const char kT4DnsName[] = {0x03, 'w', 'w', 'w', 0x07, 'g', + 's', 't', 'a', 't', 'i', 'c', + 0x03, 'c', 'o', 'm', 0x00}; +static const size_t kT4QuerySize = 33; +static const uint8_t kT4ResponseDatagram[] = { + // response contains the following IP addresses: 172.217.6.195. + 0x00, 0x04, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, 0x07, 0x67, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x63, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, + 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x2b, 0x00, 0x04, 0xac, 0xd9, 0x06, 0xc3}; + +static const char* const kT4IpAddresses[] = {"172.217.6.195"}; +static const int kT4TTL = 0x0000012b; +static const unsigned kT4RecordCount = base::size(kT0IpAddresses); + class AddressSorter; class DnsClient; class IPAddress; @@ -249,17 +269,21 @@ bool CanUseSecureDnsTransactions() const override; bool CanUseInsecureDnsTransactions() const override; void SetInsecureEnabled(bool enabled) override; + bool FallbackFromSecureTransactionPreferred() const override; bool FallbackFromInsecureTransactionPreferred() const override; bool SetSystemConfig(base::Optional<DnsConfig> system_config) override; bool SetConfigOverrides(DnsConfigOverrides config_overrides) override; const DnsConfig* GetEffectiveConfig() const override; const DnsHosts* GetHosts() const override; + void SetRequestContextForProbes( + URLRequestContext* url_request_context) override; DnsTransactionFactory* GetTransactionFactory() override; AddressSorter* GetAddressSorter() override; void IncrementInsecureFallbackFailures() override; void ClearInsecureFallbackFailures() override; base::Optional<DnsConfig> GetSystemConfigForTesting() const override; DnsConfigOverrides GetConfigOverridesForTesting() const override; + void SetProbeSuccessForTest(unsigned index, bool success) override; // Completes all DnsTransactions that were delayed by a rule. void CompleteDelayedTransactions(); @@ -272,6 +296,10 @@ ignore_system_config_changes_ = ignore_system_config_changes; } + void set_doh_server_available(bool available) { + doh_server_available_ = available; + } + private: class MockTransactionFactory; @@ -281,6 +309,7 @@ int fallback_failures_ = 0; int max_fallback_failures_ = DnsClient::kMaxInsecureFallbackFailures; bool ignore_system_config_changes_ = false; + bool doh_server_available_ = true; base::Optional<DnsConfig> config_; DnsConfigOverrides overrides_;
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc index 7f55527846..d60632c 100644 --- a/net/dns/dns_transaction.cc +++ b/net/dns/dns_transaction.cc
@@ -32,6 +32,7 @@ #include "base/timer/timer.h" #include "base/values.h" #include "build/build_config.h" +#include "net/base/backoff_entry.h" #include "net/base/completion_once_callback.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" @@ -122,7 +123,7 @@ // matches. Logging is done in the socket and in the outer DnsTransaction. class DnsAttempt { public: - explicit DnsAttempt(unsigned server_index) + explicit DnsAttempt(int server_index) : result_(ERR_FAILED), server_index_(server_index) {} virtual ~DnsAttempt() = default; @@ -141,7 +142,9 @@ virtual const NetLogWithSource& GetSocketNetLog() const = 0; // Returns the index of the destination server within DnsConfig::nameservers. - unsigned server_index() const { return server_index_; } + // If the server index is -1, indicates that no request was sent and that the + // attempt was resolved synchronously with failure. + int server_index() const { return server_index_; } // Returns a Value representing the received response, along with a reference // to the NetLog source source of the UDP socket used. The request must have @@ -171,7 +174,7 @@ // Result of last operation. int result_; - const unsigned server_index_; + const int server_index_; DISALLOW_COPY_AND_ASSIGN(DnsAttempt); }; @@ -321,14 +324,14 @@ class DnsHTTPAttempt : public DnsAttempt, public URLRequest::Delegate { public: - DnsHTTPAttempt(unsigned server_index, + DnsHTTPAttempt(unsigned doh_server_index, std::unique_ptr<DnsQuery> query, const string& server_template, const GURL& gurl_without_parameters, bool use_post, URLRequestContext* url_request_context, RequestPriority request_priority_) - : DnsAttempt(server_index), query_(std::move(query)) { + : DnsAttempt(doh_server_index), query_(std::move(query)) { GURL url; if (use_post) { // Set url for a POST request @@ -543,6 +546,36 @@ DISALLOW_COPY_AND_ASSIGN(DnsHTTPAttempt); }; +void ConstructDnsHTTPAttempt(DnsSession* session, + int doh_server_index, + std::string hostname, + uint16_t qtype, + const OptRecordRdata* opt_rdata, + std::vector<std::unique_ptr<DnsAttempt>>* attempts, + URLRequestContext* url_request_context, + RequestPriority request_priority) { + uint16_t id = session->NextQueryId(); + std::unique_ptr<DnsQuery> query; + if (attempts->empty()) { + query.reset(new DnsQuery(id, hostname, qtype, opt_rdata, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); + } else { + query = attempts->at(0)->GetQuery()->CloneWithNewId(id); + } + + DCHECK_GE(doh_server_index, 0); + DCHECK_LT(doh_server_index, + (int)session->config().dns_over_https_servers.size()); + const DnsConfig::DnsOverHttpsServerConfig& doh_config = + session->config().dns_over_https_servers[doh_server_index]; + GURL gurl_without_parameters( + GetURLFromTemplateWithoutParameters(doh_config.server_template)); + attempts->push_back(std::make_unique<DnsHTTPAttempt>( + doh_server_index, std::move(query), doh_config.server_template, + gurl_without_parameters, doh_config.use_post, url_request_context, + request_priority)); +} + class DnsTCPAttempt : public DnsAttempt { public: DnsTCPAttempt(unsigned server_index, @@ -782,6 +815,139 @@ // ---------------------------------------------------------------------------- +const char kDoHProbeHostname[] = "www.gstatic.com"; + +const net::BackoffEntry::Policy kProbeBackoffPolicy = { + // Apply exponential backoff rules after the first error. + 0, + // Begin with a 1s delay between probes. + 1000, + // Increase the delay between consecutive probes by a factor of 1.5. + 1.5, + // Fuzz the delay between consecutive probes between 90%-100% of the + // calculated time. + 0.1, + // Cap the maximum delay between consecutive probes at 1 hour. + 1000 * 60 * 60, + // Never expire entries. + -1, + // Do not apply an initial delay. + false, +}; + +// DnsOverHttpsProbeRunner implements a prober that continually sends test +// queries (with backoff) to DoH servers to determine availability. +class DnsOverHttpsProbeRunner { + public: + DnsOverHttpsProbeRunner(DnsSession* session) : session_(session) { + DNSDomainFromDot(kDoHProbeHostname, &formatted_probe_hostname_); + + for (size_t i = 0; i < session_->config().dns_over_https_servers.size(); + i++) { + probe_stats_.push_back(nullptr); + } + } + + base::TimeDelta GetDelayUntilNextProbeForTest(unsigned doh_server_index) { + if (doh_server_index >= probe_stats_.size() || + !probe_stats_[doh_server_index]) + return base::TimeDelta(); + + return probe_stats_[doh_server_index]->backoff_entry->GetTimeUntilRelease(); + } + + void StartProbe(int doh_server_index, URLRequestContext* context) { + // Clear the existing probe stats. + probe_stats_[doh_server_index] = std::make_unique<ProbeStats>(); + session_->SetProbeSuccess(doh_server_index, false /* success */); + ContinueProbe(doh_server_index, context, + probe_stats_[doh_server_index]->weak_factory.GetWeakPtr()); + } + + private: + struct ProbeStats { + ProbeStats() + : backoff_entry( + std::make_unique<net::BackoffEntry>(&kProbeBackoffPolicy)) {} + + std::unique_ptr<net::BackoffEntry> backoff_entry; + std::vector<std::unique_ptr<DnsAttempt>> probe_attempts; + base::WeakPtrFactory<ProbeStats> weak_factory{this}; + }; + + void ContinueProbe(int doh_server_index, + URLRequestContext* context, + base::WeakPtr<ProbeStats> probe_stats) { + // If the ProbeStats for which this probe was scheduled has been deleted, + // don't continue to send probes. + if (!probe_stats) + return; + + // Schedule a new probe assuming this one will fail. The newly scheduled + // probe will not run if an earlier probe has already succeeded. Probes may + // take awhile to fail, which is why we schedule the next one here rather + // than on probe completion. + DCHECK(probe_stats); + DCHECK(probe_stats->backoff_entry); + probe_stats->backoff_entry->InformOfRequest(false /* success */); + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&DnsOverHttpsProbeRunner::ContinueProbe, + base::Unretained(this), doh_server_index, context, + probe_stats), + probe_stats->backoff_entry->GetTimeUntilRelease()); + + unsigned attempt_number = probe_stats->probe_attempts.size(); + ConstructDnsHTTPAttempt(session_, doh_server_index, + formatted_probe_hostname_, dns_protocol::kTypeA, + nullptr /* opt_rdata */, + &probe_stats->probe_attempts, context, + RequestPriority::DEFAULT_PRIORITY); + + probe_stats->probe_attempts.back()->Start( + base::BindOnce(&DnsOverHttpsProbeRunner::ProbeComplete, + base::Unretained(this), attempt_number, doh_server_index, + std::move(probe_stats), base::TimeTicks::Now())); + } + + void ProbeComplete(unsigned attempt_number, + int doh_server_index, + base::WeakPtr<ProbeStats> probe_stats, + base::TimeTicks start, + int rv) { + if (rv != OK || !probe_stats) + return; + + // Check that the response parses properly before considering it a success. + DCHECK_LT(attempt_number, probe_stats->probe_attempts.size()); + const DnsAttempt* attempt = + probe_stats->probe_attempts[attempt_number].get(); + const DnsResponse* response = attempt->GetResponse(); + AddressList addresses; + base::TimeDelta ttl; + if (!response || + attempt->GetResponse()->ParseToAddressList(&addresses, &ttl) != + DnsResponse::DNS_PARSE_OK || + addresses.empty()) { + return; + } + + // The DoH probe queries don't go through the standard DnsAttempt path, so + // the ServerStats have not been updated yet. + session_->RecordServerSuccess(doh_server_index, true /* is_doh_server */); + session_->RecordRTT(doh_server_index, true /* is_doh_server */, + true /* is_probe */, base::TimeTicks::Now() - start); + session_->SetProbeSuccess(doh_server_index, true /* success */); + probe_stats_[doh_server_index] = nullptr; + } + + DnsSession* session_; + std::string formatted_probe_hostname_; + std::vector<std::unique_ptr<ProbeStats>> probe_stats_; +}; + +// ---------------------------------------------------------------------------- + // Implements DnsTransaction. Configuration is supplied by DnsSession. // The suffix list is built according to the DnsConfig from the session. // The timeout for each DnsUDPAttempt is given by DnsSession::NextTimeout. @@ -798,19 +964,20 @@ const NetLogWithSource& net_log, const OptRecordRdata* opt_rdata, bool secure, + DnsConfig::SecureDnsMode secure_dns_mode, URLRequestContext* url_request_context) : session_(session), hostname_(hostname), qtype_(qtype), opt_rdata_(opt_rdata), secure_(secure), + secure_dns_mode_(secure_dns_mode), callback_(std::move(callback)), net_log_(net_log), qnames_initial_size_(0), attempts_count_(0), doh_attempts_(0), had_tcp_attempt_(false), - doh_attempt_(false), first_server_index_(0), url_request_context_(url_request_context), request_priority_(DEFAULT_PRIORITY) { @@ -946,7 +1113,7 @@ DnsConfig config = session_->config(); if (secure_) { DCHECK_GT(config.dns_over_https_servers.size(), 0u); - return MakeHTTPAttempt(config.dns_over_https_servers); + return MakeHTTPAttempt(); } DCHECK_GT(config.nameservers.size(), 0u); @@ -957,7 +1124,6 @@ // next nameserver. AttemptResult MakeUDPAttempt() { DCHECK(!secure_); - doh_attempt_ = false; unsigned attempt_number = attempts_.size(); uint16_t id = session_->NextQueryId(); @@ -993,8 +1159,8 @@ attempt->GetSocketNetLog().source()); int rv = attempt->Start(base::Bind( - &DnsTransactionImpl::OnUdpAttemptComplete, base::Unretained(this), - attempt_number, base::TimeTicks::Now())); + &DnsTransactionImpl::OnAttemptComplete, base::Unretained(this), + attempt_number, true /* record_rtt */, base::TimeTicks::Now())); if (rv == ERR_IO_PENDING) { base::TimeDelta timeout = session_->NextTimeout(non_doh_server_index, attempt_number); @@ -1003,43 +1169,32 @@ return AttemptResult(rv, attempt); } - AttemptResult MakeHTTPAttempt( - const std::vector<DnsConfig::DnsOverHttpsServerConfig>& servers) { + AttemptResult MakeHTTPAttempt() { DCHECK(secure_); - doh_attempt_ = true; - unsigned attempt_number = attempts_.size(); - uint16_t id = session_->NextQueryId(); - std::unique_ptr<DnsQuery> query; - if (attempts_.empty()) { - query.reset(new DnsQuery(id, qnames_.front(), qtype_, opt_rdata_, - DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); - } else { - query = attempts_[0]->GetQuery()->CloneWithNewId(id); - } // doh_attempts_ counts the number of attempts made via HTTPS. To // get a server index cap that by the number of DoH servers we - // have configured and then offset it by the number of non-doh - // servers we have configured since they come first in the server - // stats list. - unsigned server_index = session_->NextGoodDnsOverHttpsServerIndex( - (doh_attempts_ % session_->config().dns_over_https_servers.size()) + - session_->config().nameservers.size()); + // have configured and search for the next good server. + int doh_server_index = session_->NextGoodDohServerIndex( + doh_attempts_ % session_->config().dns_over_https_servers.size(), + secure_dns_mode_); + // Do not construct an attempt if there is no DoH server that we should send + // a request to. + if (doh_server_index < 0) + return AttemptResult(ERR_BLOCKED_BY_CLIENT, nullptr); - std::string server_template = - servers[server_index - session_->config().nameservers.size()] - .server_template; - GURL gurl_without_parameters( - GetURLFromTemplateWithoutParameters(server_template)); - attempts_.push_back(std::make_unique<DnsHTTPAttempt>( - server_index, std::move(query), server_template, - gurl_without_parameters, - servers[server_index - session_->config().nameservers.size()].use_post, - url_request_context_, request_priority_)); + unsigned attempt_number = attempts_.size(); + ConstructDnsHTTPAttempt(session_.get(), doh_server_index, qnames_.front(), + qtype_, opt_rdata_, &attempts_, + url_request_context_, request_priority_); ++doh_attempts_; ++attempts_count_; - int rv = attempts_.back()->Start( - base::Bind(&DnsTransactionImpl::OnAttemptComplete, - base::Unretained(this), attempt_number)); + int rv = attempts_.back()->Start(base::BindOnce( + &DnsTransactionImpl::OnAttemptComplete, base::Unretained(this), + attempt_number, true /* record_rtt */, base::TimeTicks::Now())); + if (rv == ERR_IO_PENDING) { + base::TimeDelta timeout = session_->NextDohTimeout(doh_server_index); + timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); + } return AttemptResult(rv, attempts_.back().get()); } @@ -1075,8 +1230,9 @@ NetLogEventType::DNS_TRANSACTION_TCP_ATTEMPT, attempt->GetSocketNetLog().source()); - int rv = attempt->Start(base::Bind(&DnsTransactionImpl::OnAttemptComplete, - base::Unretained(this), attempt_number)); + int rv = attempt->Start(base::BindOnce( + &DnsTransactionImpl::OnAttemptComplete, base::Unretained(this), + attempt_number, false /* record_rtt */, base::TimeTicks::Now())); if (rv == ERR_IO_PENDING) { // Custom timeout for TCP attempt. base::TimeDelta timeout = timer_.GetCurrentDelay() * 2; @@ -1099,23 +1255,18 @@ return MakeAttempt(); } - void OnUdpAttemptComplete(unsigned attempt_number, - base::TimeTicks start, - int rv) { + void OnAttemptComplete(unsigned attempt_number, + bool record_rtt, + base::TimeTicks start, + int rv) { DCHECK_LT(attempt_number, attempts_.size()); const DnsAttempt* attempt = attempts_[attempt_number].get(); - if (attempt->GetResponse()) { - session_->RecordRTT(attempt->server_index(), - base::TimeTicks::Now() - start); + if (record_rtt && attempt->GetResponse()) { + session_->RecordRTT(attempt->server_index(), secure_ /* is_doh_server */, + false /* is_probe */, base::TimeTicks::Now() - start); } - OnAttemptComplete(attempt_number, rv); - } - - void OnAttemptComplete(unsigned attempt_number, int rv) { if (callback_.is_null()) return; - DCHECK_LT(attempt_number, attempts_.size()); - const DnsAttempt* attempt = attempts_[attempt_number].get(); AttemptResult result = ProcessAttemptResult(AttemptResult(rv, attempt)); if (result.rv != ERR_IO_PENDING) DoCallback(result); @@ -1133,8 +1284,12 @@ return false; const DnsConfig& config = session_->config(); - if (secure_) - return attempts_.size() < config.dns_over_https_servers.size(); + if (secure_) { + if (secure_dns_mode_ == DnsConfig::SecureDnsMode::AUTOMATIC) + return attempts_.size() < session_->NumAvailableDohServers(); + else + return attempts_.size() < config.dns_over_https_servers.size(); + } return attempts_.size() < config.attempts * config.nameservers.size(); } @@ -1147,15 +1302,16 @@ switch (result.rv) { case OK: - if (!doh_attempt_) - session_->RecordServerSuccess(result.attempt->server_index()); + session_->RecordServerSuccess(result.attempt->server_index(), + secure_ /* is_doh_server */); net_log_.EndEventWithNetErrorCode( NetLogEventType::DNS_TRANSACTION_QUERY, result.rv); DCHECK(result.attempt); DCHECK(result.attempt->GetResponse()); return result; case ERR_NAME_NOT_RESOLVED: - session_->RecordServerSuccess(result.attempt->server_index()); + session_->RecordServerSuccess(result.attempt->server_index(), + secure_ /* is_doh_server */); net_log_.EndEventWithNetErrorCode( NetLogEventType::DNS_TRANSACTION_QUERY, result.rv); // Try next suffix. Check that qnames_ isn't already empty first, @@ -1173,7 +1329,8 @@ case ERR_CONNECTION_REFUSED: case ERR_DNS_TIMED_OUT: if (result.attempt) - session_->RecordServerFailure(result.attempt->server_index()); + session_->RecordServerFailure(result.attempt->server_index(), + secure_ /* is_doh_server */); if (MoreAttemptsAllowed()) { result = MakeAttempt(); } else { @@ -1183,12 +1340,18 @@ case ERR_DNS_SERVER_REQUIRES_TCP: result = MakeTCPAttempt(result.attempt); break; + case ERR_BLOCKED_BY_CLIENT: + net_log_.EndEventWithNetErrorCode( + NetLogEventType::DNS_TRANSACTION_QUERY, result.rv); + return result; default: // Server failure. DCHECK(result.attempt); if (result.attempt != attempts_.back().get()) { // This attempt already timed out. Ignore it. - session_->RecordServerFailure(result.attempt->server_index()); + DCHECK_GE(result.attempt->server_index(), 0); + session_->RecordServerFailure(result.attempt->server_index(), + secure_ /* is_doh_server */); return AttemptResult(ERR_IO_PENDING, nullptr); } if (!MoreAttemptsAllowed()) { @@ -1228,6 +1391,7 @@ uint16_t qtype_; const OptRecordRdata* opt_rdata_; const bool secure_; + const DnsConfig::SecureDnsMode secure_dns_mode_; // Cleared in DoCallback. DnsTransactionFactory::CallbackType callback_; @@ -1243,7 +1407,6 @@ int attempts_count_; uint16_t doh_attempts_; bool had_tcp_attempt_; - bool doh_attempt_; // Index of the first server to try on each search query. int first_server_index_; @@ -1266,6 +1429,7 @@ public: explicit DnsTransactionFactoryImpl(DnsSession* session) { session_ = session; + probe_runner_ = std::make_unique<DnsOverHttpsProbeRunner>(session_.get()); } std::unique_ptr<DnsTransaction> CreateTransaction( @@ -1274,10 +1438,11 @@ CallbackType callback, const NetLogWithSource& net_log, bool secure, + DnsConfig::SecureDnsMode secure_dns_mode, URLRequestContext* url_request_context) override { return std::make_unique<DnsTransactionImpl>( session_.get(), hostname, qtype, std::move(callback), net_log, - opt_rdata_.get(), secure, url_request_context); + opt_rdata_.get(), secure, secure_dns_mode, url_request_context); } void AddEDNSOption(const OptRecordRdata::Opt& opt) override { @@ -1287,13 +1452,33 @@ opt_rdata_->AddOpt(opt); } + base::TimeDelta GetDelayUntilNextProbeForTest( + unsigned doh_server_index) override { + return probe_runner_->GetDelayUntilNextProbeForTest(doh_server_index); + } + + void StartDohProbes(URLRequestContext* context) override { + for (size_t i = 0; i < session_->config().dns_over_https_servers.size(); + i++) { + probe_runner_->StartProbe(i, context); + } + } + + DnsConfig::SecureDnsMode GetSecureDnsModeForTest() override { + return session_->config().secure_dns_mode; + } + private: scoped_refptr<DnsSession> session_; + std::unique_ptr<DnsOverHttpsProbeRunner> probe_runner_; std::unique_ptr<OptRecordRdata> opt_rdata_; }; } // namespace +DnsTransactionFactory::DnsTransactionFactory() = default; +DnsTransactionFactory::~DnsTransactionFactory() = default; + // static std::unique_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( DnsSession* session) {
diff --git a/net/dns/dns_transaction.h b/net/dns/dns_transaction.h index ec6a3bb..273a543 100644 --- a/net/dns/dns_transaction.h +++ b/net/dns/dns_transaction.h
@@ -11,6 +11,8 @@ #include <string> #include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "net/base/request_priority.h" #include "net/dns/dns_config.h" #include "net/dns/record_rdata.h" @@ -59,7 +61,8 @@ const DnsResponse* response)> CallbackType; - virtual ~DnsTransactionFactory() {} + DnsTransactionFactory(); + virtual ~DnsTransactionFactory(); // Creates DnsTransaction for the given |hostname| and |qtype| (assuming // QCLASS is IN). |hostname| should be in the dotted form. A dot at the end @@ -77,16 +80,30 @@ CallbackType callback, const NetLogWithSource& net_log, bool secure, + DnsConfig::SecureDnsMode secure_dns_mode, URLRequestContext* url_request_context) WARN_UNUSED_RESULT = 0; // The given EDNS0 option will be included in all DNS queries performed by // transactions from this factory. virtual void AddEDNSOption(const OptRecordRdata::Opt& opt) = 0; + // Gets the delay until the next scheduled probe to the specified DoH server. + // Returns base::TimeDelta() if no probe scheduled. + virtual base::TimeDelta GetDelayUntilNextProbeForTest( + unsigned doh_server_index) = 0; + + // Initiate probe sequences to all configured DoH resolvers. + virtual void StartDohProbes(URLRequestContext* context) = 0; + + // Returns the default SecureDnsMode in the config. + virtual DnsConfig::SecureDnsMode GetSecureDnsModeForTest() = 0; + // Creates a DnsTransactionFactory which creates DnsTransactionImpl using the // |session|. static std::unique_ptr<DnsTransactionFactory> CreateFactory( DnsSession* session) WARN_UNUSED_RESULT; + + base::WeakPtrFactory<DnsTransactionFactory> weak_factory_{this}; }; } // namespace net
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc index 93bd17c..e665fe8 100644 --- a/net/dns/dns_transaction_unittest.cc +++ b/net/dns/dns_transaction_unittest.cc
@@ -305,7 +305,7 @@ base::Bind(&TransactionHelper::OnTransactionComplete, base::Unretained(this)), NetLogWithSource::Make(&net_log_, net::NetLogSourceType::NONE), secure_, - &request_context_); + factory->GetSecureDnsModeForTest(), &request_context_); transaction_->SetRequestPriority(DEFAULT_PRIORITY); EXPECT_EQ(hostname_, transaction_->GetHostname()); EXPECT_EQ(qtype_, transaction_->GetType()); @@ -580,6 +580,29 @@ } } + // Configures the DnsConfig DNS-over-HTTPS server(s), which either + // accept GET or POST requests based on use_post. If a + // ResponseModifierCallback is provided it will be called to construct the + // HTTPResponse. + void ConfigureDohServers(bool use_post, unsigned num_doh_servers = 1) { + GURL url(URLRequestMockDohJob::GetMockHttpsUrl("doh_test")); + URLRequestFilter* filter = URLRequestFilter::GetInstance(); + filter->AddHostnameInterceptor(url.scheme(), url.host(), + std::make_unique<DohJobInterceptor>(this)); + CHECK_LE(num_doh_servers, 255u); + for (unsigned i = 0; i < num_doh_servers; ++i) { + std::string server_template(URLRequestMockDohJob::GetMockHttpsUrl( + base::StringPrintf("doh_test_%d", i)) + + "{?dns}"); + config_.dns_over_https_servers.push_back( + DnsConfig::DnsOverHttpsServerConfig(server_template, use_post)); + } + ConfigureFactory(); + for (unsigned i = 0; i < num_doh_servers; ++i) { + session_->SetProbeSuccess(i, true /* success */); + } + } + // Called after fully configuring |config|. void ConfigureFactory() { socket_factory_.reset(new TestSocketFactory()); @@ -718,74 +741,6 @@ } } - void SetUp() override { - // By default set one server, - ConfigureNumServers(1); - // and no retransmissions, - config_.attempts = 1; - // and an arbitrary timeout. - config_.timeout = kTimeout; - ConfigureFactory(); - } - - void TearDown() override { - // Check that all socket data was at least written to. - for (size_t i = 0; i < socket_data_.size(); ++i) { - EXPECT_TRUE(socket_data_[i]->GetProvider()->AllWriteDataConsumed()) << i; - } - } - - protected: - int GetNextId(int min, int max) { - EXPECT_FALSE(transaction_ids_.empty()); - int id = transaction_ids_.front(); - transaction_ids_.pop_front(); - EXPECT_GE(id, min); - EXPECT_LE(id, max); - return id; - } - - DnsConfig config_; - - std::vector<std::unique_ptr<DnsSocketData>> socket_data_; - - base::circular_deque<int> transaction_ids_; - std::unique_ptr<TestSocketFactory> socket_factory_; - scoped_refptr<DnsSession> session_; - std::unique_ptr<DnsTransactionFactory> transaction_factory_; -}; - -class DnsTransactionTest : public DnsTransactionTestBase, - public WithTaskEnvironment { - public: - DnsTransactionTest() = default; - ~DnsTransactionTest() override = default; - - // Generates |nameservers| for DnsConfig. - void ConfigureDohServers(unsigned num_servers, bool use_post) { - CHECK_LE(num_servers, 255u); - for (unsigned i = 0; i < num_servers; ++i) { - std::string server_template(URLRequestMockDohJob::GetMockHttpsUrl( - base::StringPrintf("doh_test_%d", i)) + - "{?dns}"); - config_.dns_over_https_servers.push_back( - DnsConfig::DnsOverHttpsServerConfig(server_template, use_post)); - } - } - - // Configures the DnsConfig with one dns over https server, which either - // accepts GET or POST requests based on use_post. If a - // ResponseModifierCallback is provided it will be called to contruct the - // HTTPResponse. - void ConfigDohServers(bool use_post, int num_doh_servers = 1) { - GURL url(URLRequestMockDohJob::GetMockHttpsUrl("doh_test")); - URLRequestFilter* filter = URLRequestFilter::GetInstance(); - filter->AddHostnameInterceptor(url.scheme(), url.host(), - std::make_unique<DohJobInterceptor>(this)); - ConfigureDohServers(num_doh_servers, use_post); - ConfigureFactory(); - } - URLRequestJob* MaybeInterceptRequest(URLRequest* request, NetworkDelegate* network_delegate) { // If the path indicates a redirect, skip checking the list of @@ -841,7 +796,7 @@ class DohJobInterceptor : public URLRequestInterceptor { public: - explicit DohJobInterceptor(DnsTransactionTest* test) : test_(test) {} + explicit DohJobInterceptor(DnsTransactionTestBase* test) : test_(test) {} ~DohJobInterceptor() override {} // URLRequestInterceptor implementation: @@ -852,16 +807,11 @@ } private: - DnsTransactionTest* test_; + DnsTransactionTestBase* test_; DISALLOW_COPY_AND_ASSIGN(DohJobInterceptor); }; - void TearDown() override { - URLRequestFilter* filter = URLRequestFilter::GetInstance(); - filter->ClearHandlers(); - } - void SetResponseModifierCallback(ResponseModifierCallback response_modifier) { response_modifier_ = response_modifier; } @@ -870,11 +820,57 @@ doh_job_maker_ = doh_job_maker; } - private: + void SetUp() override { + // By default set one server, + ConfigureNumServers(1); + // and no retransmissions, + config_.attempts = 1; + // and an arbitrary timeout. + config_.timeout = kTimeout; + ConfigureFactory(); + } + + void TearDown() override { + // Check that all socket data was at least written to. + for (size_t i = 0; i < socket_data_.size(); ++i) { + EXPECT_TRUE(socket_data_[i]->GetProvider()->AllWriteDataConsumed()) << i; + } + } + + protected: + int GetNextId(int min, int max) { + EXPECT_FALSE(transaction_ids_.empty()); + int id = transaction_ids_.front(); + transaction_ids_.pop_front(); + EXPECT_GE(id, min); + EXPECT_LE(id, max); + return id; + } + + DnsConfig config_; + + std::vector<std::unique_ptr<DnsSocketData>> socket_data_; + + base::circular_deque<int> transaction_ids_; + std::unique_ptr<TestSocketFactory> socket_factory_; + scoped_refptr<DnsSession> session_; + std::unique_ptr<DnsTransactionFactory> transaction_factory_; ResponseModifierCallback response_modifier_; DohJobMakerCallback doh_job_maker_; }; +class DnsTransactionTest : public DnsTransactionTestBase, + public WithTaskEnvironment { + public: + DnsTransactionTest() = default; + ~DnsTransactionTest() override = default; + + void TearDown() override { + URLRequestFilter* filter = URLRequestFilter::GetInstance(); + filter->ClearHandlers(); + } +}; + class DnsTransactionTestWithMockTime : public DnsTransactionTestBase, public WithTaskEnvironment { protected: @@ -1389,7 +1385,7 @@ } TEST_F(DnsTransactionTest, HttpsGetLookup) { - ConfigDohServers(false /* use_post */); + ConfigureDohServers(false /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1400,7 +1396,7 @@ } TEST_F(DnsTransactionTest, HttpsGetFailure) { - ConfigDohServers(false /* use_post */); + ConfigureDohServers(false /* use_post */); AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL, SYNCHRONOUS, Transport::HTTPS, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); @@ -1413,7 +1409,7 @@ } TEST_F(DnsTransactionTest, HttpsGetMalformed) { - ConfigDohServers(false /* use_post */); + ConfigureDohServers(false /* use_post */); AddQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1424,7 +1420,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookup) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1435,7 +1431,7 @@ } TEST_F(DnsTransactionTest, HttpsPostFailure) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL, SYNCHRONOUS, Transport::HTTPS, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); @@ -1448,7 +1444,7 @@ } TEST_F(DnsTransactionTest, HttpsPostMalformed) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(1 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1460,7 +1456,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupAsync) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), ASYNC, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1479,7 +1475,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupFailStart) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1499,7 +1495,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupFailSync) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1520,7 +1516,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupFailAsync) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1532,7 +1528,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookup2Sync) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1546,7 +1542,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookup2Async) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1560,7 +1556,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupAsyncWithAsyncZeroRead) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1574,7 +1570,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupSyncWithAsyncZeroRead) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1588,7 +1584,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenSync) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1602,7 +1598,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenSyncError) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1615,7 +1611,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenAsyncError) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1628,7 +1624,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupSyncThenAsyncError) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1641,7 +1637,7 @@ } TEST_F(DnsTransactionTest, HttpsPostLookupSyncThenSyncError) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); std::unique_ptr<DnsSocketData> data(new DnsSocketData( 0, kT0HostName, kT0Qtype, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128)); @@ -1653,9 +1649,20 @@ EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); } +TEST_F(DnsTransactionTest, HttpsNotAvailable) { + ConfigureDohServers(true /* use_post */); + session_->SetProbeSuccess(0, false /* success */); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + -1); + TransactionHelper helper0(kT0HostName, kT0Qtype, true /* secure */, + ERR_BLOCKED_BY_CLIENT); + EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); +} + TEST_F(DnsTransactionTest, HttpsMarkHttpsBad) { config_.attempts = 1; - ConfigDohServers(true /* use_post */, 3); + ConfigureDohServers(true /* use_post */, 3); AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1685,26 +1692,38 @@ TransactionHelper helper1(kT1HostName, kT1Qtype, true /* secure */, kT1RecordCount); EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); - // Server 0 is our only UDP server, so it will be good. HTTPS - // servers 1 and 2 failed and will be marked bad. Server 3 succeeded + // UDP server 0 is our only UDP server, so it will be good. HTTPS + // servers 0 and 1 failed and will be marked bad. HTTPS server 2 succeeded // so will be good. EXPECT_EQ(session_->NextGoodServerIndex(0), 0u); - EXPECT_EQ(session_->NextGoodDnsOverHttpsServerIndex(1), 3u); - EXPECT_EQ(session_->NextGoodDnsOverHttpsServerIndex(2), 3u); - EXPECT_EQ(session_->NextGoodDnsOverHttpsServerIndex(3), 3u); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 2); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::AUTOMATIC), + 2); + EXPECT_EQ( + session_->NextGoodDohServerIndex(2, DnsConfig::SecureDnsMode::AUTOMATIC), + 2); unsigned kOrder0[] = {1, 2, 3}; CheckServerOrder(kOrder0, base::size(kOrder0)); EXPECT_TRUE(helper1.RunUntilDone(transaction_factory_.get())); - // Server 0 is still our only UDP server, so will be good by definition. - // Server 3 started out as good, so was tried first and failed. Server 1 - // then had the oldest failure so would be the next good server and - // failed so is marked bad. Next attempt was server 2, which succeded so is - // good. + // UDP server 0 is still our only UDP server, so will be good by definition. + // HTTPS server 2 started out as good, so was tried first and failed. HTTPS + // server 0 then had the oldest failure so would be the next good server and + // failed so is marked bad. Next attempt was HTTPS server 1, which succeeded + // so is good. EXPECT_EQ(session_->NextGoodServerIndex(0), 0u); - EXPECT_EQ(session_->NextGoodDnsOverHttpsServerIndex(1), 2u); - EXPECT_EQ(session_->NextGoodDnsOverHttpsServerIndex(2), 2u); - EXPECT_EQ(session_->NextGoodDnsOverHttpsServerIndex(3), 2u); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 1); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::AUTOMATIC), + 1); + EXPECT_EQ( + session_->NextGoodDohServerIndex(2, DnsConfig::SecureDnsMode::AUTOMATIC), + 1); unsigned kOrder1[] = { 1, 2, 3, /* transaction0 */ 3, 1, 2 /* transaction1 */ @@ -1713,7 +1732,7 @@ } TEST_F(DnsTransactionTest, HttpsPostFailThenHTTPFallback) { - ConfigDohServers(true /* use_post */, 2); + ConfigureDohServers(true /* use_post */, 2); AddQueryAndRcode(kT0HostName, kT0Qtype, dns_protocol::kRcodeSERVFAIL, ASYNC, Transport::HTTPS, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); @@ -1730,7 +1749,7 @@ TEST_F(DnsTransactionTest, HttpsPostFailTwice) { config_.attempts = 3; - ConfigDohServers(true /* use_post */, 2); + ConfigureDohServers(true /* use_post */, 2); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1747,6 +1766,147 @@ CheckServerOrder(kOrder0, base::size(kOrder0)); } +TEST_F(DnsTransactionTest, HttpsNotAvailableThenHttpFallback) { + ConfigureDohServers(true /* use_post */, 2); + session_->SetProbeSuccess(0, false /* success */); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 1); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::AUTOMATIC), + 1); + AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, + base::size(kT0ResponseDatagram), SYNCHRONOUS, + Transport::HTTPS, nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + TransactionHelper helper0(kT0HostName, kT0Qtype, true /* secure */, + kT0RecordCount); + EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); + unsigned kOrder0[] = {2}; + CheckServerOrder(kOrder0, base::size(kOrder0)); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 1); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::AUTOMATIC), + 1); +} + +TEST_F(DnsTransactionTest, HttpsFailureThenNotAvailable_Automatic) { + config_.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; + ConfigureDohServers(true /* use_post */, 3); + session_->SetProbeSuccess(1, false /* success */); + session_->SetProbeSuccess(2, false /* success */); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + EXPECT_EQ( + session_->NextGoodDohServerIndex(2, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + TransactionHelper helper0(kT0HostName, kT0Qtype, true /* secure */, + ERR_CONNECTION_REFUSED); + EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); + unsigned kOrder0[] = {1}; + CheckServerOrder(kOrder0, base::size(kOrder0)); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + EXPECT_EQ( + session_->NextGoodDohServerIndex(2, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); +} + +TEST_F(DnsTransactionTest, HttpsFailureThenNotAvailable_Secure) { + config_.secure_dns_mode = DnsConfig::SecureDnsMode::SECURE; + ConfigureDohServers(true /* use_post */, 3); + session_->SetProbeSuccess(1, false /* success */); + session_->SetProbeSuccess(2, false /* success */); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::SECURE), 0); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::SECURE), 1); + EXPECT_EQ( + session_->NextGoodDohServerIndex(2, DnsConfig::SecureDnsMode::SECURE), 2); + AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + TransactionHelper helper0(kT0HostName, kT0Qtype, true /* secure */, + ERR_CONNECTION_REFUSED); + EXPECT_TRUE(helper0.RunUntilDone(transaction_factory_.get())); + unsigned kOrder0[] = {1, 2, 3}; + CheckServerOrder(kOrder0, base::size(kOrder0)); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::SECURE), 0); + EXPECT_EQ( + session_->NextGoodDohServerIndex(1, DnsConfig::SecureDnsMode::SECURE), 0); + EXPECT_EQ( + session_->NextGoodDohServerIndex(2, DnsConfig::SecureDnsMode::SECURE), 0); +} + +TEST_F(DnsTransactionTest, UnavailableAfterMaxHttpsFailures) { + config_.attempts = 1; + ConfigureDohServers(false /* use_post */); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + + for (size_t i = 0; i < kAutomaticModeFailureLimit - 1; i++) { + AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + TransactionHelper failure(kT0HostName, kT0Qtype, true /* secure */, + ERR_CONNECTION_REFUSED); + EXPECT_TRUE(failure.RunUntilDone(transaction_factory_.get())); + EXPECT_EQ(session_->NextGoodDohServerIndex( + 0, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + } + + // A success should not reset the failure counter for DoH. + AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, + base::size(kT0ResponseDatagram), SYNCHRONOUS, + Transport::HTTPS, nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + TransactionHelper success(kT0HostName, kT0Qtype, true /* secure */, + kT0RecordCount); + EXPECT_TRUE(success.RunUntilDone(transaction_factory_.get())); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); + + // One more failure should pass the threshold. + AddQueryAndErrorResponse(0, kT0HostName, kT0Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + TransactionHelper last_failure(kT0HostName, kT0Qtype, true /* secure */, + ERR_CONNECTION_REFUSED); + EXPECT_TRUE(last_failure.RunUntilDone(transaction_factory_.get())); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + -1); +} + void MakeResponseWithCookie(URLRequest* request, HttpResponseInfo* info) { info->headers->AddHeader("Set-Cookie: test-cookie=you-fail"); } @@ -1781,7 +1941,7 @@ }; TEST_F(DnsTransactionTest, HttpsPostTestNoCookies) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1824,7 +1984,7 @@ } TEST_F(DnsTransactionTest, HttpsPostNoContentLength) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1841,7 +2001,7 @@ } TEST_F(DnsTransactionTest, HttpsPostWithBadRequestResponse) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1859,7 +2019,7 @@ } TEST_F(DnsTransactionTest, HttpsPostWithWrongType) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1879,7 +2039,7 @@ } TEST_F(DnsTransactionTest, HttpsGetRedirect) { - ConfigDohServers(false /* use_post */); + ConfigureDohServers(false /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1899,7 +2059,7 @@ } TEST_F(DnsTransactionTest, HttpsPostWithNoType) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1912,7 +2072,7 @@ TEST_F(DnsTransactionTest, CanLookupDohServerName) { config_.search.push_back("http"); - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndErrorResponse(0, kMockHostname, dns_protocol::kTypeA, ERR_NAME_NOT_RESOLVED, SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -1947,7 +2107,7 @@ }; TEST_F(DnsTransactionTest, HttpsPostLookupWithLog) { - ConfigDohServers(true /* use_post */); + ConfigureDohServers(true /* use_post */); AddQueryAndResponse(0, kT0HostName, kT0Qtype, kT0ResponseDatagram, base::size(kT0ResponseDatagram), SYNCHRONOUS, Transport::HTTPS, nullptr /* opt_rdata */, @@ -2189,6 +2349,42 @@ EXPECT_TRUE(helper1.Run(transaction_factory_.get())); } +TEST_F(DnsTransactionTestWithMockTime, ProbeUntilSuccess) { + ConfigureDohServers(true /* use_post */); + TestURLRequestContext request_context; + AddQueryAndErrorResponse(4, kT4HostName, kT4Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + AddQueryAndErrorResponse(4, kT4HostName, kT4Qtype, ERR_CONNECTION_REFUSED, + SYNCHRONOUS, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + AddQueryAndResponse(4, kT4HostName, kT4Qtype, kT4ResponseDatagram, + base::size(kT4ResponseDatagram), ASYNC, Transport::HTTPS, + nullptr /* opt_rdata */, + DnsQuery::PaddingStrategy::BLOCK_LENGTH_128); + transaction_factory_->StartDohProbes(&request_context); + + // The first probe happens without any delay. + RunUntilIdle(); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + -1); + + // Expect the server to still be unavailable after the second probe. + FastForwardBy(transaction_factory_->GetDelayUntilNextProbeForTest(0)); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + -1); + + // Expect the server to be available after the successful third probe. + FastForwardBy(transaction_factory_->GetDelayUntilNextProbeForTest(0)); + EXPECT_EQ( + session_->NextGoodDohServerIndex(0, DnsConfig::SecureDnsMode::AUTOMATIC), + 0); +} + } // namespace } // namespace net
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index 9e87406..920246d 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -1015,6 +1015,7 @@ DnsQueryType query_type, URLRequestContext* request_context, bool secure, + DnsConfig::SecureDnsMode secure_dns_mode, Delegate* delegate, const NetLogWithSource& job_net_log, const base::TickClock* tick_clock) @@ -1023,6 +1024,7 @@ query_type_(query_type), request_context_(request_context), secure_(secure), + secure_dns_mode_(secure_dns_mode), delegate_(delegate), net_log_(job_net_log), num_completed_transactions_(0), @@ -1080,7 +1082,7 @@ base::BindOnce(&DnsTask::OnTransactionComplete, base::Unretained(this), tick_clock_->NowTicks(), dns_query_type), - net_log_, secure_, request_context_); + net_log_, secure_, secure_dns_mode_, request_context_); trans->SetRequestPriority(delegate_->priority()); return trans; } @@ -1440,6 +1442,7 @@ // Whether lookups in this DnsTask should occur using DoH or plaintext. const bool secure_; + const DnsConfig::SecureDnsMode secure_dns_mode_; // The listener to the results of this DnsTask. Delegate* delegate_; @@ -1490,6 +1493,7 @@ HostResolverFlags host_resolver_flags, HostResolverSource requested_source, ResolveHostParameters::CacheUsage cache_usage, + DnsConfig::SecureDnsMode secure_dns_mode, URLRequestContext* request_context, HostCache* host_cache, std::deque<TaskType> tasks, @@ -1503,6 +1507,7 @@ host_resolver_flags_(host_resolver_flags), requested_source_(requested_source), cache_usage_(cache_usage), + secure_dns_mode_(secure_dns_mode), request_context_(request_context), host_cache_(host_cache), tasks_(tasks), @@ -1944,8 +1949,8 @@ // Need to create the task even if we're going to post a failure instead of // running it, as a "started" job needs a task to be properly cleaned up. dns_task_.reset(new DnsTask(resolver_->dns_client_.get(), hostname_, - query_type_, request_context_, secure, this, - net_log_, tick_clock_)); + query_type_, request_context_, secure, + secure_dns_mode_, this, net_log_, tick_clock_)); dns_task_->StartFirstTransaction(); // Schedule a second transaction, if needed. DoH queries can bypass the // dispatcher and start immediately. @@ -2312,6 +2317,7 @@ const HostResolverFlags host_resolver_flags_; const HostResolverSource requested_source_; const ResolveHostParameters::CacheUsage cache_usage_; + const DnsConfig::SecureDnsMode secure_dns_mode_; URLRequestContext* const request_context_; // TODO(crbug.com/969847): Consider allowing requests within a single Job to // have different HostCaches. @@ -2542,6 +2548,12 @@ } } +void HostResolverManager::SetRequestContextForProbes( + URLRequestContext* url_request_context) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + dns_client_->SetRequestContextForProbes(url_request_context); +} + void HostResolverManager::AddHostCacheInvalidator( HostCache::Invalidator* invalidator) { host_cache_invalidators_.AddObserver(invalidator); @@ -2779,9 +2791,9 @@ weak_ptr_factory_.GetWeakPtr(), request->request_host().host(), effective_query_type, effective_host_resolver_flags, request->parameters().source, request->parameters().cache_usage, - request->request_context(), request->host_cache(), std::move(tasks), - request->priority(), proc_task_runner_, request->source_net_log(), - tick_clock_); + effective_secure_dns_mode, request->request_context(), + request->host_cache(), std::move(tasks), request->priority(), + proc_task_runner_, request->source_net_log(), tick_clock_); job = new_job.get(); auto insert_result = jobs_.emplace(std::move(key), std::move(new_job)); DCHECK(insert_result.second); @@ -3064,7 +3076,7 @@ break; case DnsConfig::SecureDnsMode::AUTOMATIC: DCHECK(!allow_cache || out_tasks->front() == TaskType::CACHE_LOOKUP); - if (!dns_client_->CanUseSecureDnsTransactions()) { + if (dns_client_->FallbackFromSecureTransactionPreferred()) { // Don't run a secure DnsTask if there are no available DoH servers. if (dns_tasks_allowed && insecure_tasks_allowed) out_tasks->push_back(TaskType::DNS);
diff --git a/net/dns/host_resolver_manager.h b/net/dns/host_resolver_manager.h index c7b9237..76297549 100644 --- a/net/dns/host_resolver_manager.h +++ b/net/dns/host_resolver_manager.h
@@ -149,6 +149,9 @@ // read from the system for DnsClient resolution. void SetDnsConfigOverrides(DnsConfigOverrides overrides); + // Sets the URLRequestContext to use for issuing DoH probes. + void SetRequestContextForProbes(URLRequestContext* url_request_context); + // Support for invalidating HostCaches on changes to network or DNS // configuration. HostCaches should register/deregister invalidators here // rather than attempting to listen for relevant network change signals
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index 1ef2af2..420b7ed 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -5029,6 +5029,67 @@ EXPECT_TRUE(!!cache_result); } +TEST_F(HostResolverManagerDnsTest, SecureDnsMode_Automatic_Unavailable) { + ChangeDnsConfig(CreateValidDnsConfig()); + DnsConfigOverrides overrides; + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; + resolver_->SetDnsConfigOverrides(overrides); + dns_client_->set_doh_server_available(false); + + // DoH requests should be skipped when there are no available DoH servers + // in automatic mode. The cached result should be in the insecure cache. + ResolveHostResponseHelper response_automatic(resolver_->CreateRequest( + HostPortPair("automatic", 80), NetLogWithSource(), base::nullopt, + request_context_.get(), host_cache_.get())); + ASSERT_THAT(response_automatic.result_error(), IsOk()); + EXPECT_THAT( + response_automatic.request()->GetAddressResults().value().endpoints(), + testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80), + CreateExpected("::1", 80))); + HostCache::Key secure_key = + HostCache::Key("automatic", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + secure_key.secure = true; + const std::pair<const HostCache::Key, HostCache::Entry>* cache_result = + GetCacheHit(secure_key); + EXPECT_FALSE(!!cache_result); + + HostCache::Key insecure_key = + HostCache::Key("automatic", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + cache_result = GetCacheHit(insecure_key); + EXPECT_TRUE(!!cache_result); +} + +TEST_F(HostResolverManagerDnsTest, SecureDnsMode_Automatic_Unavailable_Fail) { + set_allow_fallback_to_proctask(false); + ChangeDnsConfig(CreateValidDnsConfig()); + DnsConfigOverrides overrides; + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; + resolver_->SetDnsConfigOverrides(overrides); + dns_client_->set_doh_server_available(false); + + // Insecure requests that fail should not be cached. + ResolveHostResponseHelper response_secure(resolver_->CreateRequest( + HostPortPair("secure", 80), NetLogWithSource(), base::nullopt, + request_context_.get(), host_cache_.get())); + ASSERT_THAT(response_secure.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); + + HostCache::Key secure_key = + HostCache::Key("secure", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + secure_key.secure = true; + const std::pair<const HostCache::Key, HostCache::Entry>* cache_result = + GetCacheHit(secure_key); + EXPECT_FALSE(!!cache_result); + + HostCache::Key insecure_key = + HostCache::Key("secure", DnsQueryType::UNSPECIFIED, + 0 /* host_resolver_flags */, HostResolverSource::ANY); + cache_result = GetCacheHit(insecure_key); + EXPECT_FALSE(!!cache_result); +} + TEST_F(HostResolverManagerDnsTest, SecureDnsMode_Automatic_Stale) { ChangeDnsConfig(CreateValidDnsConfig()); DnsConfigOverrides overrides;
diff --git a/net/url_request/http_with_dns_over_https_unittest.cc b/net/url_request/http_with_dns_over_https_unittest.cc index 7b6bce9983..0376a00 100644 --- a/net/url_request/http_with_dns_over_https_unittest.cc +++ b/net/url_request/http_with_dns_over_https_unittest.cc
@@ -86,7 +86,7 @@ DnsConfigOverrides overrides; overrides.dns_over_https_servers.emplace( {DnsConfig::DnsOverHttpsServerConfig(url.spec(), true /* use_post */)}); - overrides.secure_dns_mode = DnsConfig::SecureDnsMode::AUTOMATIC; + overrides.secure_dns_mode = DnsConfig::SecureDnsMode::SECURE; overrides.use_local_ipv6 = true; resolver_->GetManagerForTesting()->SetDnsConfigOverrides( std::move(overrides));
diff --git a/net/url_request/url_request_quic_perftest.cc b/net/url_request/url_request_quic_perftest.cc index 2a2d9a2..687dda4 100644 --- a/net/url_request/url_request_quic_perftest.cc +++ b/net/url_request/url_request_quic_perftest.cc
@@ -9,10 +9,10 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted_memory.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" +#include "base/test/task_environment.h" #include "base/time/time.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/memory_dump_manager_test_utils.h" @@ -90,7 +90,10 @@ class URLRequestQuicPerfTest : public ::testing::Test { protected: - URLRequestQuicPerfTest() : message_loop_(new base::MessageLoopForIO()) { + URLRequestQuicPerfTest() + : task_environment_( + std::make_unique<base::test::SingleThreadTaskEnvironment>( + base::test::SingleThreadTaskEnvironment::MainThreadType::IO)) { memory_dump_manager_ = base::trace_event::MemoryDumpManager::CreateInstanceForTesting(); base::trace_event::InitializeMemoryDumpManagerForInProcessTesting( @@ -131,7 +134,7 @@ } // |tcp_server_| shuts down in EmbeddedTestServer destructor. memory_dump_manager_.reset(); - message_loop_.reset(); + task_environment_.reset(); } std::unique_ptr<URLRequest> CreateRequest(const GURL& url, @@ -180,7 +183,7 @@ std::unique_ptr<MappedHostResolver> host_resolver_; std::unique_ptr<EmbeddedTestServer> tcp_server_; std::unique_ptr<QuicSimpleServer> quic_server_; - std::unique_ptr<base::MessageLoop> message_loop_; + std::unique_ptr<base::test::SingleThreadTaskEnvironment> task_environment_; std::unique_ptr<TestURLRequestContext> context_; quic::QuicMemoryCacheBackend memory_cache_backend_; MockCertVerifier cert_verifier_;
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc index cc1a175c..fd1c1cffc 100644 --- a/services/network/cors/preflight_controller.cc +++ b/services/network/cors/preflight_controller.cc
@@ -13,6 +13,7 @@ #include "base/strings/stringprintf.h" #include "net/base/load_flags.h" #include "net/http/http_request_headers.h" +#include "services/network/loader_util.h" #include "services/network/public/cpp/cors/cors.h" #include "services/network/public/cpp/cors/cors_error_status.h" #include "services/network/public/cpp/resource_request.h" @@ -90,7 +91,6 @@ preflight_request->headers.SetHeader( header_names::kAccessControlRequestMethod, request.method); - preflight_request->headers.SetHeader("Sec-Fetch-Mode", "cors"); std::string request_headers = CreateAccessControlRequestHeadersHeader( request.headers, request.is_revalidating); @@ -110,6 +110,13 @@ net::HttpRequestHeaders::kOrigin, (tainted ? url::Origin() : *request.request_initiator).Serialize()); + // Additional headers that the algorithm in the spec does not require, but + // it's better that CORS preflight requests have them. + preflight_request->headers.SetHeader("Sec-Fetch-Mode", "cors"); + // See also https://github.com/whatwg/fetch/issues/922 for kAcceptHeader. + preflight_request->headers.SetHeader(network::kAcceptHeader, + kDefaultAcceptHeader); + return preflight_request; }
diff --git a/services/network/cors/preflight_controller.h b/services/network/cors/preflight_controller.h index 4e70572e..59b4c7b 100644 --- a/services/network/cors/preflight_controller.h +++ b/services/network/cors/preflight_controller.h
@@ -30,8 +30,6 @@ // A class to manage CORS-preflight, making a CORS-preflight request, checking // its result, and owning a CORS-preflight cache. -// TODO(toyoshim): Features explained above not fully implemented yet. -// See also https://crbug.com/803766 to check a design doc. class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final { public: using CompletionCallback =
diff --git a/services/network/network_service.cc b/services/network/network_service.cc index 574d7884..a018504 100644 --- a/services/network/network_service.cc +++ b/services/network/network_service.cc
@@ -447,6 +447,14 @@ return; } + for (auto* network_context : network_contexts_) { + if (!network_context->IsPrimaryNetworkContext()) + continue; + + host_resolver_manager_->SetRequestContextForProbes( + network_context->url_request_context()); + } + net::DnsConfigOverrides overrides; overrides.dns_over_https_servers.emplace(); for (const auto& doh_server : *dns_over_https_servers) {
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index d5a30e8..86d7cee2 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -590,15 +590,16 @@ // |window_id| or else |process_id| and |routing_id| indicates // the frame making the request, see // network::ResourceRequest::fetch_window_id. - OnAuthRequired(mojo_base.mojom.UnguessableToken? window_id, - uint32 process_id, - uint32 routing_id, - uint32 request_id, - url.mojom.Url url, - bool first_auth_attempt, - AuthChallengeInfo auth_info, - URLResponseHead? head, - AuthChallengeResponder auth_challenge_responder); + OnAuthRequired( + mojo_base.mojom.UnguessableToken? window_id, + uint32 process_id, + uint32 routing_id, + uint32 request_id, + url.mojom.Url url, + bool first_auth_attempt, + AuthChallengeInfo auth_info, + URLResponseHead? head, + pending_remote<AuthChallengeResponder> auth_challenge_responder); // Called when an SSL certificate requested message is received for client // authentication.
diff --git a/services/network/test/test_network_context_client.h b/services/network/test/test_network_context_client.h index 1c22c745..cb09ce5 100644 --- a/services/network/test/test_network_context_client.h +++ b/services/network/test/test_network_context_client.h
@@ -7,6 +7,7 @@ #include "build/build_config.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/network_context.mojom.h" namespace network { @@ -26,16 +27,16 @@ ignore_last_upload_file_ = ignore_last_upload_file; } - void OnAuthRequired( - const base::Optional<base::UnguessableToken>& window_id, - uint32_t process_id, - uint32_t routing_id, - uint32_t request_id, - const GURL& url, - bool first_auth_attempt, - const net::AuthChallengeInfo& auth_info, - network::mojom::URLResponseHeadPtr head, - mojom::AuthChallengeResponderPtr auth_challenge_responder) override {} + void OnAuthRequired(const base::Optional<base::UnguessableToken>& window_id, + uint32_t process_id, + uint32_t routing_id, + uint32_t request_id, + const GURL& url, + bool first_auth_attempt, + const net::AuthChallengeInfo& auth_info, + network::mojom::URLResponseHeadPtr head, + mojo::PendingRemote<mojom::AuthChallengeResponder> + auth_challenge_responder) override {} void OnCertificateRequested( const base::Optional<base::UnguessableToken>& window_id, uint32_t process_id,
diff --git a/services/network/test/test_url_loader_factory.cc b/services/network/test/test_url_loader_factory.cc index 31ea672c..ad3cca53 100644 --- a/services/network/test/test_url_loader_factory.cc +++ b/services/network/test/test_url_loader_factory.cc
@@ -128,6 +128,7 @@ PendingRequest pending_request; pending_request.client = std::move(client); pending_request.request = url_request; + pending_request.options = options; pending_requests_.push_back(std::move(pending_request)); }
diff --git a/services/network/test/test_url_loader_factory.h b/services/network/test/test_url_loader_factory.h index f6087f98..f6e33195 100644 --- a/services/network/test/test_url_loader_factory.h +++ b/services/network/test/test_url_loader_factory.h
@@ -34,6 +34,7 @@ mojom::URLLoaderClientPtr client; ResourceRequest request; + uint32_t options; }; // Bitfield that is used with |SimulateResponseForPendingRequest()| to
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 5f3aef1..7801e34f 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -351,7 +351,6 @@ keepalive_(request.keepalive), do_not_prompt_for_login_(request.do_not_prompt_for_login), binding_(this, std::move(url_loader_request)), - auth_challenge_responder_binding_(this), client_cert_responder_binding_(this), url_loader_client_(std::move(url_loader_client)), writable_handle_watcher_(FROM_HERE, @@ -827,12 +826,7 @@ return; } - mojom::AuthChallengeResponderPtr auth_challenge_responder; - auto request = mojo::MakeRequest(&auth_challenge_responder); - DCHECK(!auth_challenge_responder_binding_.is_bound()); - auth_challenge_responder_binding_.Bind(std::move(request)); - auth_challenge_responder_binding_.set_connection_error_handler( - base::BindOnce(&URLLoader::DeleteSelf, base::Unretained(this))); + DCHECK(!auth_challenge_responder_receiver_.is_bound()); ResourceResponseHead head; if (url_request->response_headers()) @@ -841,7 +835,10 @@ network_context_client_->OnAuthRequired( fetch_window_id_, factory_params_->process_id, render_frame_id_, request_id_, url_request_->url(), first_auth_attempt_, auth_info, head, - std::move(auth_challenge_responder)); + auth_challenge_responder_receiver_.BindNewPipeAndPassRemote()); + + auth_challenge_responder_receiver_.set_disconnect_handler( + base::BindOnce(&URLLoader::DeleteSelf, base::Unretained(this))); first_auth_attempt_ = false; } @@ -1261,7 +1258,7 @@ void URLLoader::OnAuthCredentials( const base::Optional<net::AuthCredentials>& credentials) { - auth_challenge_responder_binding_.Close(); + auth_challenge_responder_receiver_.reset(); if (!url_request_) return;
diff --git a/services/network/url_loader.h b/services/network/url_loader.h index 5aa46ca..628c0b35 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h
@@ -18,6 +18,7 @@ #include "base/optional.h" #include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/system/data_pipe.h" #include "mojo/public/cpp/system/simple_watcher.h" @@ -265,8 +266,8 @@ const bool do_not_prompt_for_login_; std::unique_ptr<net::URLRequest> url_request_; mojo::Binding<mojom::URLLoader> binding_; - mojo::Binding<mojom::AuthChallengeResponder> - auth_challenge_responder_binding_; + mojo::Receiver<mojom::AuthChallengeResponder> + auth_challenge_responder_receiver_{this}; mojo::Binding<mojom::ClientCertificateResponder> client_cert_responder_binding_; mojom::URLLoaderClientPtr url_loader_client_;
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index 02008ff..65188d9 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -2589,16 +2589,16 @@ MockNetworkContextClient() = default; ~MockNetworkContextClient() override = default; - void OnAuthRequired( - const base::Optional<base::UnguessableToken>& window_id, - uint32_t process_id, - uint32_t routing_id, - uint32_t request_id, - const GURL& url, - bool first_auth_attempt, - const net::AuthChallengeInfo& auth_info, - network::mojom::URLResponseHeadPtr head, - mojom::AuthChallengeResponderPtr auth_challenge_responder) override { + void OnAuthRequired(const base::Optional<base::UnguessableToken>& window_id, + uint32_t process_id, + uint32_t routing_id, + uint32_t request_id, + const GURL& url, + bool first_auth_attempt, + const net::AuthChallengeInfo& auth_info, + network::mojom::URLResponseHeadPtr head, + mojo::PendingRemote<mojom::AuthChallengeResponder> + auth_challenge_responder) override { if (head) EXPECT_TRUE(head->auth_challenge_info.has_value()); switch (credentials_response_) { @@ -2615,7 +2615,9 @@ credentials_response_ = CredentialsResponse::CORRECT_CREDENTIALS; break; } - std::move(auth_challenge_responder)->OnAuthCredentials(auth_credentials_); + mojo::Remote<mojom::AuthChallengeResponder> auth_challenge_responder_remote( + std::move(auth_challenge_responder)); + auth_challenge_responder_remote->OnAuthCredentials(auth_credentials_); ++on_auth_required_call_counter_; last_seen_response_headers_ = head ? head->headers : nullptr; }
diff --git a/testing/buildbot/filters/bfcache.browser_tests.filter b/testing/buildbot/filters/bfcache.browser_tests.filter index 9d2b883..a8d9f520 100644 --- a/testing/buildbot/filters/bfcache.browser_tests.filter +++ b/testing/buildbot/filters/bfcache.browser_tests.filter
@@ -13,6 +13,7 @@ # Terminating renderer for bad IPC message, reason 205 # RFH_ERROR_PROCESS_NON_ERROR_COMMIT +# https://crbug.com/999850 -CaptivePortalBrowserTest.GoBackToTimeout -DNSErrorPageTest.DNSError_DoSearch -DNSErrorPageTest.DNSError_GoBack2
diff --git a/testing/buildbot/filters/bfcache.content_browsertests.filter b/testing/buildbot/filters/bfcache.content_browsertests.filter index f7f0299a..c8d041f7 100644 --- a/testing/buildbot/filters/bfcache.content_browsertests.filter +++ b/testing/buildbot/filters/bfcache.content_browsertests.filter
@@ -54,6 +54,7 @@ -NavigationHandleImplBrowserTest.StartToCommitMetrics # render_view_impl.cc. Check failed: !frame_widget_. +# https://crbug.com/999846 -NavigationControllerBrowserTest.PageStateAfterForwardInCompetingFrames -NavigationControllerBrowserTest.PageStateWithIframeAfterForwardInCompetingFrames -NavigationControllerHistoryInterventionBrowserTest.NoUserActivationSetSkipOnBackForwardCrossSite @@ -61,6 +62,7 @@ -RenderFrameHostManagerTest.BackForwardNotStale # Javascript dialog is shown from a page in the BackForwardCache. +# https://crbug.com/999847 -NavigationControllerBrowserTest.NoDialogsFromSwappedOutFrames # history.back(); history.back() causes the tab to go back twice instead of @@ -96,6 +98,7 @@ -RenderFrameHostManagerTest.UnloadPushStateOnCrossProcessNavigation -RenderFrameHostManagerTest.WebUIJavascriptDisallowedAfterSwapOut -RenderProcessHostTest.KeepAliveRendererProcess +-SitePerProcessBrowserTest.RenderViewHostIsNotReusedAfterDelayedSwapOutACK -SitePerProcessBrowserTest.SubframePendingAndBackToSameSiteInstance -SitePerProcessBrowserTest.SwapOutACKArrivesPriorToProcessShutdownRequest @@ -106,20 +109,16 @@ # Waiting for unload handler, but they aren't executed. -SitePerProcessBrowserTest.PartialUnloadHandler -SitePerProcessBrowserTest.Unload_ABAB - -# Expect the old RenderView to be removed. It isn't, because it it still used -# by a bfcached document. --SitePerProcessBrowserTest.RenderViewHostIsNotReusedAfterDelayedSwapOutACK +-WebContentsImplBrowserTest.SetTitleOnUnload # Check failed: false. Navigation in an inactive frame +# https://crbug.com/999848 -NavigationControllerBrowserTest.HistoryBackTwiceFromRendererWithUserGesture -SitePerProcessBrowserTest.TwoCrossSitePendingNavigationsAndMainFrameWins -# Unload handler not run => Title not updated. --WebContentsImplBrowserTest.SetTitleOnUnload - # FATAL:casting.h Security DCHECK failed: IsA<Derived>(from). # In content::RenderFrameProxy::OnSetFrameOwnerProperties() +# https://crbug.com/999849 -WebContentsSplitCacheBrowserTestEnabled.SplitCacheDedicatedWorkers/0 -WebContentsSplitCacheBrowserTestEnabled.SplitCacheDedicatedWorkers/1 -WebContentsSplitCacheWithFrameOriginBrowserTest.SplitCache @@ -129,3 +128,10 @@ # https://crbug.com/992891 -WebContentsSplitCacheBrowserTestEnabled.SplitCacheDedicatedWorkerScripts/1 -WebContentsSplitCacheBrowserTestEnabled.SplitCacheDedicatedWorkerScripts/0 + +# Histogram "PrefetchedSignedExchangeCache.Count" is recorded when the document +# in the RenderFrameHost is replaced, or when the RenderFrameHost is deleted. +# With the BackForwardCache, the RenderFrameHost is not deleted, so the +# histogram is not recorded before the end of the test. +-SignedExchangeRequestHandlerBrowserTest.Simple/3 +-SignedExchangeRequestHandlerBrowserTest.VariantMatch/3
diff --git a/testing/buildbot/filters/bfcache.unit_tests.filter b/testing/buildbot/filters/bfcache.unit_tests.filter index 8758d22..fac4ff6 100644 --- a/testing/buildbot/filters/bfcache.unit_tests.filter +++ b/testing/buildbot/filters/bfcache.unit_tests.filter
@@ -2,5 +2,7 @@ # Autofill component issue. The AutofillDriver is associated with the # RenderFrameHost, but is is used before it has been associated. +# +# https://crbug.com/999842 -TabsApiUnitTest.TabsGoForwardAndBack -TabsApiUnitTest.TabsGoForwardAndBackWithoutTabId
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 0643d60..e887247 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -103,6 +103,7 @@ "renderer_preference_watcher.mojom", "renderer_preferences.mojom", "reporting/reporting.mojom", + "screen_enumeration/screen_enumeration.mojom", "script/script_type.mojom", "selection_menu/selection_menu_behavior.mojom", "service_worker/controller_service_worker_mode.mojom",
diff --git a/third_party/blink/public/mojom/badging/badging.mojom b/third_party/blink/public/mojom/badging/badging.mojom index c230f14..3b7e10ae 100644 --- a/third_party/blink/public/mojom/badging/badging.mojom +++ b/third_party/blink/public/mojom/badging/badging.mojom
@@ -4,17 +4,28 @@ module blink.mojom; +import "url/mojom/url.mojom"; + +// A value that a badge can hold. +union BadgeValue { + // Represents the special value |flag|. This indicates that a badge should be + // set but that no data should be displayed in it. + // Note: The value of this field is unused (see https://crbug.com/999900). + uint8 flag; + // Represents a numerical badge. Note: This must not be zero (setting the + // badge to 0 should be translated into a clear). + uint64 number; +}; + // Interface for handling badge messages from frames and subframes. interface BadgeService { - // Sets the badge for the PWA corresponding to this request to be a - // non-zero, positive integer. - SetInteger(uint64 content); + // Asks the browser process to set a badge. + // |scope| specifies which badges to set. Note: This must be on the same + // origin as the caller. + SetBadge(url.mojom.Url scope, BadgeValue value); - // Sets the badge for the PWA corresponding to this request to be a - // flag marker. - SetFlag(); - - // Clears the badge (if it exists) for the PWA corresponding to - // this request. - ClearBadge(); + // Asks the browser to clear a badge. + // |scope| specifies the badges to clear. Note: This must be on the same + // origin as the caller. + ClearBadge(url.mojom.Url scope); };
diff --git a/third_party/blink/public/mojom/screen_enumeration/OWNERS b/third_party/blink/public/mojom/screen_enumeration/OWNERS new file mode 100644 index 0000000..222819b --- /dev/null +++ b/third_party/blink/public/mojom/screen_enumeration/OWNERS
@@ -0,0 +1,7 @@ +file://content/browser/screen_enumeration/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage \ No newline at end of file
diff --git a/third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom b/third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom new file mode 100644 index 0000000..bb987e4 --- /dev/null +++ b/third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom
@@ -0,0 +1,45 @@ +// 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. + +module blink.mojom; + +// A physical or virtual unit of rendering space connected to the device. +// +// Display structures typically correspond 1:1 with internal laptop/phone/tablet +// screens and externally-connected monitors. +// +// Properties are populated from the corresponding display::Display object and +// Web-exposed through the Display object in the Screen Enumeration API. The +// following properties should be equivalent to those in the Screen interface: +// width, height, colorDepth. +struct Display { + // A human-readable name for the display. + string name; + // The number of hardware pixels per CSS pixel. + float scale_factor; + // The full width of the display, in CSS pixels. + int32 width; + // The full height of the display, in CSS pixels. + int32 height; + // The x-coordinate of the display's left edge in the screen's coordinate + // system (top-left corner of the primary display is the origin). + int32 left; + // The y-coordinate of the display's top edge in the screen's coordinate + // system (top-left corner of the primary display is the origin). + int32 top; + // The number of bits allocated to pixel color. + int32 color_depth; + // Whether the display is the primary display. + bool is_primary; + // Whether the display is internal (built-in) or external. + bool is_internal; +}; + +// This interface is implemented by the browser process to pass screen data to +// window and worker processes. +interface ScreenEnumeration { + // If success is false, |displays| is meaningless. Otherwise, |displays| is + // the list of all the device's Displays. + RequestDisplays() => (array<Display> displays, bool success); +};
diff --git a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc index fd77a56..e42e8027 100644 --- a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc +++ b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
@@ -125,7 +125,10 @@ void PendingInvalidations::RescheduleSiblingInvalidationsAsDescendants( Element& element) { - DCHECK(element.parentNode()); + auto* parent = element.parentNode(); + DCHECK(parent); + if (parent->IsDocumentNode()) + return; auto pending_invalidations_iterator = pending_invalidation_map_.find(&element); if (pending_invalidations_iterator == pending_invalidation_map_.end() || @@ -143,12 +146,11 @@ invalidation_lists.descendants.push_back(descendants); } } - ScheduleInvalidationSetsForNode(invalidation_lists, *element.parentNode()); + ScheduleInvalidationSetsForNode(invalidation_lists, *parent); } void PendingInvalidations::ClearInvalidation(ContainerNode& node) { - if (!node.NeedsStyleInvalidation()) - return; + DCHECK(node.NeedsStyleInvalidation()); pending_invalidation_map_.erase(&node); node.ClearNeedsStyleInvalidation(); }
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc index 99bb28db..f953969 100644 --- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
@@ -184,6 +184,8 @@ // TreeScope. @keyframes rules may apply to animations on elements in the // same TreeScope as the stylesheet, or the host element in the parent // TreeScope if the TreeScope is a shadow tree. + if (!tree_scope.GetDocument().documentElement()) + return; ScopedStyleResolver* resolver = tree_scope.GetScopedStyleResolver(); ScopedStyleResolver* parent_resolver =
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index e3fc9e5..e31b232 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -65,6 +65,7 @@ #include "third_party/blink/renderer/core/html/imports/html_imports_controller.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/layout/layout_object.h" +#include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/style/computed_style.h" @@ -721,6 +722,11 @@ GetDocument().ScheduleLayoutTreeUpdateIfNeeded(); } +void StyleEngine::MarkViewportStyleDirty() { + viewport_style_dirty_ = true; + GetDocument().ScheduleLayoutTreeUpdateIfNeeded(); +} + CSSStyleSheet* StyleEngine::CreateSheet(Element& element, const String& text, TextPosition start_position, @@ -805,8 +811,8 @@ if (resolver_) resolver_->InvalidateMatchedPropertiesCache(); - GetDocument().SetNeedsStyleRecalc( - kSubtreeStyleChange, + MarkViewportStyleDirty(); + MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kFonts)); probe::FontsUpdated(document_, nullptr, String(), nullptr); } @@ -1287,9 +1293,8 @@ // Media queries may rely on the initial font size relative lengths which may // have changed. MediaQueryAffectingValueChanged(); - - GetDocument().SetNeedsStyleRecalc( - kSubtreeStyleChange, + MarkViewportStyleDirty(); + MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kSettings)); } @@ -1761,19 +1766,13 @@ return initial_data_; } -void StyleEngine::RecalcStyle(const StyleRecalcChange change) { +void StyleEngine::RecalcStyle() { DCHECK(GetDocument().documentElement()); - DCHECK(GetDocument().ChildNeedsStyleRecalc() || change.RecalcDescendants()); - Element* root_element = &style_recalc_root_.RootElement(); Element* parent = root_element->ParentOrShadowHostElement(); - if (change.RecalcChildren()) { - root_element = GetDocument().documentElement(); - parent = nullptr; - } SelectorFilterRootScope filter_scope(parent); - root_element->RecalcStyle(change); + root_element->RecalcStyle({}); for (ContainerNode* ancestor = root_element->ParentOrShadowHostNode(); ancestor; ancestor = ancestor->ParentOrShadowHostNode()) { @@ -1921,6 +1920,27 @@ root->SetNeedsStyleRecalc(kSubtreeStyleChange, reason); } +void StyleEngine::UpdateViewportStyle() { + if (!viewport_style_dirty_) + return; + + viewport_style_dirty_ = false; + + // TODO(futhark@chromium.org): Cannot access the EnsureStyleResolver() + // before calling StyleForViewport() below because apparently the + // StyleResolver's constructor has side effects. We should fix it. See + // printing/setPrinting.html, printing/width-overflow.html though they only + // fail on mac when accessing the resolver by what appears to be a viewport + // size difference. + scoped_refptr<ComputedStyle> viewport_style = + StyleResolver::StyleForViewport(GetDocument()); + if (ComputedStyle::ComputeDifference( + viewport_style.get(), GetDocument().GetLayoutView()->Style()) != + ComputedStyle::Difference::kEqual) { + GetDocument().GetLayoutView()->SetStyle(std::move(viewport_style)); + } +} + void StyleEngine::Trace(blink::Visitor* visitor) { visitor->Trace(document_); visitor->Trace(injected_user_style_sheets_);
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index cc5d56a7..ba452844 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -336,6 +336,8 @@ void ClearWhitespaceReattachSet() { whitespace_reattach_set_.clear(); } void MarkForWhitespaceReattachment(); void MarkAllElementsForStyleRecalc(const StyleChangeReasonForTracing& reason); + void MarkViewportStyleDirty(); + bool IsViewportStyleDirty() const { return viewport_style_dirty_; } StyleRuleKeyframes* KeyframeStylesForAnimation( const AtomicString& animation_name); @@ -346,7 +348,8 @@ scoped_refptr<StyleInitialData> MaybeCreateAndGetInitialData(); - void RecalcStyle(const StyleRecalcChange change); + void UpdateViewportStyle(); + void RecalcStyle(); void RebuildLayoutTree(); bool InRebuildLayoutTree() const { return in_layout_tree_rebuild_; } @@ -506,6 +509,7 @@ bool uses_rem_units_ = false; bool in_layout_tree_rebuild_ = false; bool in_dom_removal_ = false; + bool viewport_style_dirty_ = false; Member<StyleResolver> resolver_; Member<ViewportStyleResolver> viewport_resolver_;
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 1798209..3722659 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -1716,7 +1716,7 @@ div->SetInlineStyleProperty(CSSPropertyID::kColor, "green"); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - GetStyleEngine().RecalcStyle({}); + GetStyleEngine().RecalcStyle(); // Should fast reject ".not-in-filter div::before {}" for both the div and its // ::before pseudo element. @@ -1928,7 +1928,7 @@ span_outer->SetInlineStyleProperty(CSSPropertyID::kColor, "blue"); EXPECT_TRUE(span_outer->NeedsStyleRecalc()); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - GetStyleEngine().RecalcStyle({}); + GetStyleEngine().RecalcStyle(); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kStyleClean); EXPECT_FALSE(span_outer->NeedsStyleRecalc()); @@ -2086,7 +2086,7 @@ CSSPropertyID::kDisplay, "none"); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - GetDocument().GetStyleEngine().RecalcStyle({}); + GetDocument().GetStyleEngine().RecalcStyle(); EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate()); EXPECT_TRUE(GetDocument().NeedsLayoutTreeRebuild());
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 60a1ab0e..162fdff 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1897,8 +1897,9 @@ content_language_ = language; // Document's style depends on the content language. - SetNeedsStyleRecalc(kSubtreeStyleChange, StyleChangeReasonForTracing::Create( - style_change_reason::kLanguage)); + GetStyleEngine().MarkViewportStyleDirty(); + GetStyleEngine().MarkAllElementsForStyleRecalc( + StyleChangeReasonForTracing::Create(style_change_reason::kLanguage)); } void Document::setXMLVersion(const String& version, @@ -2325,7 +2326,7 @@ return true; if (!use_elements_needing_update_.IsEmpty()) return true; - if (NeedsStyleRecalc()) + if (style_engine_->IsViewportStyleDirty()) return true; if (NeedsStyleInvalidation()) return true; @@ -2790,41 +2791,23 @@ // tree properly. DCHECK(!NeedsLayoutTreeRebuild()); - NthIndexCache nth_index_cache(*this); + // SetNeedsStyleRecalc should only happen on Element and Text nodes. + DCHECK(!NeedsStyleRecalc()); - StyleRecalcChange change; - if (GetStyleChangeType() == kSubtreeStyleChange) { - change = change.ForceRecalcDescendants(); - - // TODO(futhark@chromium.org): Cannot access the EnsureStyleResolver() - // before calling StyleForViewport() below because apparently the - // StyleResolver's constructor has side effects. We should fix it. See - // printing/setPrinting.html, printing/width-overflow.html though they only - // fail on mac when accessing the resolver by what appears to be a viewport - // size difference. - scoped_refptr<ComputedStyle> viewport_style = - StyleResolver::StyleForViewport(*this); - if (ComputedStyle::ComputeDifference(viewport_style.get(), - GetLayoutView()->Style()) != - ComputedStyle::Difference::kEqual) { - GetLayoutView()->SetStyle(std::move(viewport_style)); - } - } - - ClearNeedsStyleRecalc(); + GetStyleEngine().UpdateViewportStyle(); StyleResolver& resolver = EnsureStyleResolver(); - bool should_record_stats; TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink,blink_style", &should_record_stats); GetStyleEngine().SetStatsEnabled(should_record_stats); if (Element* document_element = documentElement()) { - if (change.TraverseChild(*document_element)) { + NthIndexCache nth_index_cache(*this); + if (StyleRecalcChange().TraverseChild(*document_element)) { TRACE_EVENT0("blink,blink_style", "Document::recalcStyle"); SCOPED_BLINK_UMA_HISTOGRAM_TIMER_HIGHRES("Style.RecalcTime"); Element* viewport_defining = ViewportDefiningElement(); - GetStyleEngine().RecalcStyle(change); + GetStyleEngine().RecalcStyle(); if (viewport_defining != ViewportDefiningElement()) ViewportDefiningElementDidChange(); } @@ -6270,9 +6253,10 @@ encoding_data_.Encoding().UsesVisualOrdering(); if (should_use_visual_ordering != visually_ordered_) { visually_ordered_ = should_use_visual_ordering; - SetNeedsStyleRecalc(kSubtreeStyleChange, - StyleChangeReasonForTracing::Create( - style_change_reason::kVisuallyOrdered)); + GetStyleEngine().MarkViewportStyleDirty(); + GetStyleEngine().MarkAllElementsForStyleRecalc( + StyleChangeReasonForTracing::Create( + style_change_reason::kVisuallyOrdered)); } } @@ -6393,8 +6377,8 @@ if (new_value == design_mode_) return; design_mode_ = new_value; - SetNeedsStyleRecalc( - kSubtreeStyleChange, + GetStyleEngine().MarkViewportStyleDirty(); + GetStyleEngine().MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kDesignMode)); } @@ -8518,7 +8502,7 @@ } void Document::Dispose() { - navigation_initiator_bindings_.CloseAllBindings(); + navigation_initiator_receivers_.Clear(); } template class CORE_TEMPLATE_EXPORT Supplement<Document>;
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index e1e8320..142efde6 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -35,7 +35,7 @@ #include <utility> #include "base/memory/scoped_refptr.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h" @@ -1498,9 +1498,9 @@ void SendViolationReport( mojom::blink::CSPViolationParamsPtr violation_params) override; - void BindNavigationInitiatorRequest( - mojom::blink::NavigationInitiatorRequest request) { - navigation_initiator_bindings_.AddBinding(this, std::move(request)); + void BindNavigationInitiatorReceiver( + mojo::PendingReceiver<mojom::blink::NavigationInitiator> receiver) { + navigation_initiator_receivers_.Add(this, std::move(receiver)); } LazyLoadImageObserver& EnsureLazyLoadImageObserver(); @@ -2064,11 +2064,11 @@ // opposed to a PluginView. bool is_for_external_handler_ = false; - // A list of all the navigation_initiator bindings owned by this document. + // A list of all the navigation_initiator receivers owned by this document. // Used to report CSP violations that result from CSP blocking // navigation requests that were initiated by this document. - mojo::BindingSet<mojom::blink::NavigationInitiator> - navigation_initiator_bindings_; + mojo::ReceiverSet<mojom::blink::NavigationInitiator> + navigation_initiator_receivers_; Member<LazyLoadImageObserver> lazy_load_image_observer_;
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 519bc96..35996ad4 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2120,19 +2120,16 @@ if (RuntimeEnabledFeatures::DisplayLockingEnabled() && name == html_names::kRendersubtreeAttr && params.old_value != params.new_value) { - const bool should_be_invisible = - EqualIgnoringASCIICase(params.new_value, "invisible"); - const bool should_be_invisible_activatable = - EqualIgnoringASCIICase(params.new_value, "invisible-activatable"); - if (should_be_invisible || should_be_invisible_activatable) { - // Getting locked. - EnsureDisplayLockContext().SetActivatable( - should_be_invisible_activatable); + SpaceSplitString tokens(params.new_value.LowerASCII()); + const bool should_be_activatable = tokens.Contains("activatable"); + EnsureDisplayLockContext().SetActivatable(should_be_activatable); + const bool should_be_invisible = tokens.Contains("invisible"); + if (should_be_invisible) { if (!GetDisplayLockContext()->IsLocked()) GetDisplayLockContext()->StartAcquire(); } else { // Getting unlocked. - if (EnsureDisplayLockContext().IsLocked()) + if (GetDisplayLockContext()->IsLocked()) GetDisplayLockContext()->StartCommit(); } }
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl index 17550330..700ae6a 100644 --- a/third_party/blink/renderer/core/dom/element.idl +++ b/third_party/blink/renderer/core/dom/element.idl
@@ -146,7 +146,7 @@ // Display locking. Returns a display lock context. [RuntimeEnabled=DisplayLocking, ImplementedAs=getDisplayLockForBindings] readonly attribute DisplayLockContext displayLock; // Declarative display locking. - [RuntimeEnabled=DisplayLocking, CEReactions, CustomElementCallbacks, Reflect, ReflectOnly=("invisible-activatable","invisible", "visible"), ReflectInvalid="visible", ReflectEmpty="visible"] attribute DOMString renderSubtree; + [RuntimeEnabled=DisplayLocking, CEReactions, CustomElementCallbacks, Reflect] attribute DOMString renderSubtree; // Element Timing [RuntimeEnabled=ElementTiming, Affects=Nothing, CEReactions, Reflect=elementtiming] attribute DOMString elementTiming;
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index a598c84..6be559e 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -1302,6 +1302,11 @@ const StyleChangeReasonForTracing& reason) { DCHECK(!GetDocument().GetStyleEngine().InRebuildLayoutTree()); DCHECK(change_type != kNoStyleChange); + // TODO(crbug.com/972752): ShadowRoot can be marked kSubtreeStyleChange from + // RescheduleSiblingInvalidationsAsDescendants() for WholeSubtreeInvalid(). We + // should instead mark the shadow host for subtree recalc when we traverse the + // flat tree (and skip non-slotted host children). + DCHECK(IsElementNode() || IsTextNode() || IsShadowRoot()); if (!InActiveDocument()) return; @@ -3150,6 +3155,12 @@ } void Node::FlatTreeParentChanged() { + // TODO(futhark): Replace with DCHECK(IsSlotable()) when Shadow DOM V0 support + // is removed. + if (!IsElementNode() && !IsTextNode()) { + DCHECK(GetDocument().MayContainV0Shadow()); + return; + } // The node changed the flat tree position by being slotted to a new slot or // slotted for the first time. We need to recalc style since the inheritance // parent may have changed.
diff --git a/third_party/blink/renderer/core/dom/node_test.cc b/third_party/blink/renderer/core/dom/node_test.cc index 06e48e5..a8fb877 100644 --- a/third_party/blink/renderer/core/dom/node_test.cc +++ b/third_party/blink/renderer/core/dom/node_test.cc
@@ -39,7 +39,7 @@ LayoutObject* ReattachLayoutTreeForNode(Node& node) { node.SetForceReattachLayoutTree(); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - GetDocument().GetStyleEngine().RecalcStyle({}); + GetDocument().GetStyleEngine().RecalcStyle(); Node::AttachContext context; context.parent = LayoutTreeBuilderTraversal::ParentLayoutObject(node); GetDocument().GetStyleEngine().in_layout_tree_rebuild_ = true;
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc index 96efaa5..c4265f4 100644 --- a/third_party/blink/renderer/core/execution_context/execution_context.cc +++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -312,9 +312,14 @@ bool ExecutionContext::FeaturePolicyFeatureObserved( mojom::FeaturePolicyFeature feature) { - if (parsed_feature_policies_[static_cast<size_t>(feature)]) + size_t feature_index = static_cast<size_t>(feature); + if (parsed_feature_policies_.size() == 0) { + parsed_feature_policies_.resize( + static_cast<size_t>(mojom::FeaturePolicyFeature::kMaxValue) + 1); + } else if (parsed_feature_policies_[feature_index]) { return true; - parsed_feature_policies_.set(static_cast<size_t>(feature)); + } + parsed_feature_policies_[feature_index] = true; return false; }
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.h b/third_party/blink/renderer/core/execution_context/execution_context.h index e266fc1..d278e75 100644 --- a/third_party/blink/renderer/core/execution_context/execution_context.h +++ b/third_party/blink/renderer/core/execution_context/execution_context.h
@@ -358,8 +358,8 @@ // Tracks which feature policies have already been parsed, so as not to count // them multiple times. - std::bitset<static_cast<size_t>(mojom::FeaturePolicyFeature::kMaxValue) + 1> - parsed_feature_policies_; + // The size of this vector is 0 until FeaturePolicyFeatureObserved is called. + Vector<bool> parsed_feature_policies_; DISALLOW_COPY_AND_ASSIGN(ExecutionContext); };
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc index ded2932..de2265ae 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -505,7 +505,8 @@ const String& href_translate, WebContentSecurityPolicyList initiator_csp, network::mojom::IPAddressSpace initiator_address_space, - mojom::blink::NavigationInitiatorPtr navigation_initiator) { + mojo::PendingRemote<mojom::blink::NavigationInitiator> + navigation_initiator) { if (!web_frame_->Client()) return; @@ -528,7 +529,7 @@ navigation_info->initiator_csp = std::move(initiator_csp); navigation_info->initiator_address_space = initiator_address_space; navigation_info->navigation_initiator_handle = - navigation_initiator.PassInterface().PassHandle(); + navigation_initiator.PassPipe(); // Can be null. LocalFrame* local_parent_frame = GetLocalParentFrame(web_frame_);
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h index 27df32e..e044fde 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -36,6 +36,7 @@ #include "base/memory/scoped_refptr.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h" #include "third_party/blink/public/platform/web_insecure_request_policy.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" @@ -129,7 +130,7 @@ const String& href_translate, WebContentSecurityPolicyList, network::mojom::IPAddressSpace, - mojom::blink::NavigationInitiatorPtr) override; + mojo::PendingRemote<mojom::blink::NavigationInitiator>) override; void DispatchWillSendSubmitEvent(HTMLFormElement*) override; void DidStartLoading() override; void DidStopLoading() override;
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h b/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h index 19d0622..50fb406 100644 --- a/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h +++ b/third_party/blink/renderer/core/feature_policy/feature_policy_parser_delegate.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_PARSER_DELEGATE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FEATURE_POLICY_FEATURE_POLICY_PARSER_DELEGATE_H_ -#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" +#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink-forward.h" #include "third_party/blink/renderer/core/frame/web_feature_forward.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 4f724017..5b08529 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -774,8 +774,8 @@ } document->MediaQueryAffectingValueChanged(); - document->SetNeedsStyleRecalc( - kSubtreeStyleChange, + document->GetStyleEngine().MarkViewportStyleDirty(); + document->GetStyleEngine().MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kZoom)); if (View() && View()->DidFirstLayout()) document->UpdateStyleAndLayout(); @@ -783,8 +783,8 @@ void LocalFrame::DeviceScaleFactorChanged() { GetDocument()->MediaQueryAffectingValueChanged(); - GetDocument()->SetNeedsStyleRecalc( - kSubtreeStyleChange, + GetDocument()->GetStyleEngine().MarkViewportStyleDirty(); + GetDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kZoom)); for (Frame* child = Tree().FirstChild(); child; child = child->Tree().NextSibling()) {
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 3e8708d..4554baa 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -35,6 +35,7 @@ #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h" #include "third_party/blink/public/common/feature_policy/feature_policy.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" @@ -179,7 +180,7 @@ const String& href_translate, WebContentSecurityPolicyList, network::mojom::IPAddressSpace, - mojom::blink::NavigationInitiatorPtr) = 0; + mojo::PendingRemote<mojom::blink::NavigationInitiator>) = 0; virtual void DispatchWillSendSubmitEvent(HTMLFormElement*) = 0; @@ -289,8 +290,8 @@ HTMLFrameOwnerElement*) = 0; // Creates a portal for the |HTMLPortalElement| and binds the other end of the - // |PortalRequest|. Returns a pair of a RemoteFrame and a token that - // identifies the portal. + // |mojo::PendingAssociatedReceiver<mojom::blink::Portal>|. Returns a pair of + // a RemoteFrame and a token that identifies the portal. virtual std::pair<RemoteFrame*, base::UnguessableToken> CreatePortal( HTMLPortalElement*, mojo::PendingAssociatedReceiver<mojom::blink::Portal>,
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 66911ff..2670a2e 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1160,9 +1160,9 @@ media_type_when_not_printing_ = g_null_atom; } - frame_->GetDocument()->SetNeedsStyleRecalc( - kSubtreeStyleChange, StyleChangeReasonForTracing::Create( - style_change_reason::kStyleSheetChange)); + frame_->GetDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc( + StyleChangeReasonForTracing::Create( + style_change_reason::kStyleSheetChange)); } void LocalFrameView::AddBackgroundAttachmentFixedObject(LayoutObject* object) {
diff --git a/third_party/blink/renderer/core/html/html_content_element_test.cc b/third_party/blink/renderer/core/html/html_content_element_test.cc index 765c54c..da7d4a26 100644 --- a/third_party/blink/renderer/core/html/html_content_element_test.cc +++ b/third_party/blink/renderer/core/html/html_content_element_test.cc
@@ -41,7 +41,7 @@ GetDocument().UpdateDistributionForLegacyDistributedNodes(); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - GetDocument().GetStyleEngine().RecalcStyle({}); + GetDocument().GetStyleEngine().RecalcStyle(); EXPECT_TRUE(fallback->GetComputedStyle()); }
diff --git a/third_party/blink/renderer/core/html/html_object_element_test.cc b/third_party/blink/renderer/core/html/html_object_element_test.cc index 39e6603..541fd72f 100644 --- a/third_party/blink/renderer/core/html/html_object_element_test.cc +++ b/third_party/blink/renderer/core/html/html_object_element_test.cc
@@ -41,9 +41,7 @@ object->RenderFallbackContent(nullptr); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - StyleRecalcChange change; - change = change.ForceRecalcDescendants(); - GetDocument().GetStyleEngine().RecalcStyle(change); + GetDocument().GetStyleEngine().RecalcStyle(); EXPECT_TRUE(IsHTMLSlotElement(slot)); EXPECT_TRUE(object->UseFallbackContent()); EXPECT_TRUE(object->GetComputedStyle());
diff --git a/third_party/blink/renderer/core/html/html_slot_element.cc b/third_party/blink/renderer/core/html/html_slot_element.cc index fe00537..b549cd5 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.cc +++ b/third_party/blink/renderer/core/html/html_slot_element.cc
@@ -220,8 +220,10 @@ if (assigned_nodes_.IsEmpty()) { // Use children as fallback - for (auto& child : NodeTraversal::ChildrenOf(*this)) - flat_tree_children_.push_back(child); + for (auto& child : NodeTraversal::ChildrenOf(*this)) { + if (child.IsSlotable()) + flat_tree_children_.push_back(child); + } } else { flat_tree_children_ = assigned_nodes_; for (auto& node : old_flat_tree_children) {
diff --git a/third_party/blink/renderer/core/html/html_slot_element.h b/third_party/blink/renderer/core/html/html_slot_element.h index 54d4515..89dc1d5 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.h +++ b/third_party/blink/renderer/core/html/html_slot_element.h
@@ -195,6 +195,7 @@ } friend class HTMLSlotElementTest; + friend class HTMLSlotElementInDocumentTest; }; inline const HTMLSlotElement* ToHTMLSlotElementIfSupportsAssignmentOrNull(
diff --git a/third_party/blink/renderer/core/html/html_slot_element_test.cc b/third_party/blink/renderer/core/html/html_slot_element_test.cc index bb8898cb..745d1aa 100644 --- a/third_party/blink/renderer/core/html/html_slot_element_test.cc +++ b/third_party/blink/renderer/core/html/html_slot_element_test.cc
@@ -131,18 +131,22 @@ EXPECT_EQ(lcs, LongestCommonSubsequence(seq1, seq2)); } -class HTMLSlotElementReattachTest : public testing::Test { +class HTMLSlotElementInDocumentTest : public testing::Test { protected: void SetUp() final { dummy_page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600)); } Document& GetDocument() { return dummy_page_holder_->GetDocument(); } + const HeapVector<Member<Node>>& GetFlatTreeChildren(HTMLSlotElement& slot) { + slot.RecalcFlatTreeChildren(); + return slot.flat_tree_children_; + } private: std::unique_ptr<DummyPageHolder> dummy_page_holder_; }; -TEST_F(HTMLSlotElementReattachTest, RecalcAssignedNodeStyleForReattach) { +TEST_F(HTMLSlotElementInDocumentTest, RecalcAssignedNodeStyleForReattach) { GetDocument().body()->SetInnerHTMLFromString(R"HTML( <div id='host'><span id='span'></span></div> )HTML"); @@ -163,10 +167,28 @@ shadow_span->setAttribute(html_names::kStyleAttr, "display:block"); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - GetDocument().GetStyleEngine().RecalcStyle({}); + GetDocument().GetStyleEngine().RecalcStyle(); EXPECT_TRUE(shadow_span->GetComputedStyle()); EXPECT_TRUE(span.GetComputedStyle()); } +TEST_F(HTMLSlotElementInDocumentTest, SlotableFallback) { + GetDocument().body()->SetInnerHTMLFromString(R"HTML( + <div id='host'></div> + )HTML"); + + Element& host = *GetDocument().getElementById("host"); + ShadowRoot& shadow_root = + host.AttachShadowRootInternal(ShadowRootType::kOpen); + + shadow_root.SetInnerHTMLFromString( + R"HTML(<slot><span></span><!-- -->text</slot>)HTML"); + + auto* slot = To<HTMLSlotElement>(shadow_root.firstChild()); + + EXPECT_TRUE(slot->AssignedNodes().IsEmpty()); + EXPECT_EQ(2u, GetFlatTreeChildren(*slot).size()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc index f83b3d9..f7b7162 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element.cc +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -241,8 +241,10 @@ // The HTMLPortalElement is bound as a persistent so that it won't get // garbage collected while there is a pending callback. - // We also pass the ownership of the PortalPtr, which guarantees that the - // PortalPtr stays alive until the callback is called. + // We also pass the ownership of the + // mojo::AssociatedRemote<mojom::blink::Portal>, which guarantees that the + // mojo::AssociatedRemote<mojom::blink::Portal> stays alive until the callback + // is called. is_activating_ = true; auto* raw_remote_portal = remote_portal_.get(); raw_remote_portal->Activate(
diff --git a/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc b/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc index 97728d0..b193f6f 100644 --- a/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc +++ b/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc
@@ -42,9 +42,7 @@ progress->SetForceReattachLayoutTree(); GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); - StyleRecalcChange change; - change = change.ForceRecalcDescendants(); - GetDocument().GetStyleEngine().RecalcStyle(change); + GetDocument().GetStyleEngine().RecalcStyle(); EXPECT_TRUE(shadow_element->GetComputedStyle()); scoped_refptr<ComputedStyle> style = shadow_element->StyleForLayoutObject();
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index ee77c67c..a06a054 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -4515,6 +4515,12 @@ if (IsFileUploadControl() || IsTextControl() || IsListBox()) return; + // We don't allow custom layout and multicol on the same object. This is + // similar to not allowing it for flexbox, grids and tables (although those + // don't create LayoutBlockFlow, so we don't need to check for those here). + if (IsLayoutNGCustom()) + return; + LayoutMultiColumnFlowThread* flow_thread = LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(), StyleRef()); AddChild(flow_thread);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 7a65375..84199f8 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -80,6 +80,8 @@ const LayoutBox& box = *params.node.GetLayoutBox(); if (box.IsLayoutNGFlexibleBox()) { CreateAlgorithmAndRun<NGFlexLayoutAlgorithm>(params, callback); + } else if (box.IsLayoutNGCustom()) { + CreateAlgorithmAndRun<NGCustomLayoutAlgorithm>(params, callback); } else if (box.IsLayoutNGFieldset()) { CreateAlgorithmAndRun<NGFieldsetLayoutAlgorithm>(params, callback); // If there's a legacy layout box, we can only do block fragmentation if @@ -91,8 +93,6 @@ CreateAlgorithmAndRun<NGColumnLayoutAlgorithm>(params, callback); else CreateAlgorithmAndRun<NGPageLayoutAlgorithm>(params, callback); - } else if (box.IsLayoutNGCustom()) { - CreateAlgorithmAndRun<NGCustomLayoutAlgorithm>(params, callback); } else { CreateAlgorithmAndRun<NGBlockLayoutAlgorithm>(params, callback); }
diff --git a/third_party/blink/renderer/core/loader/DEPS b/third_party/blink/renderer/core/loader/DEPS index 065eac94..0d1f45e 100644 --- a/third_party/blink/renderer/core/loader/DEPS +++ b/third_party/blink/renderer/core/loader/DEPS
@@ -1,7 +1,4 @@ specific_include_rules = { - "preload_helper.cc" : [ - "+net/base/features.h" - ], "alternate_signed_exchange_resource_info.cc" : [ "+net/http/http_request_headers.h" ],
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc index db66846..17515b3 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.cc +++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -112,7 +112,7 @@ const String&, WebContentSecurityPolicyList, network::mojom::IPAddressSpace, - mojom::blink::NavigationInitiatorPtr) {} + mojo::PendingRemote<mojom::blink::NavigationInitiator>) {} void EmptyLocalFrameClient::DispatchWillSendSubmitEvent(HTMLFormElement*) {}
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index c1cf05e..ceb7ed3 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -33,6 +33,7 @@ #include "base/macros.h" #include "cc/paint/paint_canvas.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/mojom/frame/document_interface_broker.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" @@ -284,24 +285,25 @@ void DispatchDidFinishLoad() override {} void DispatchDidChangeThemeColor() override {} - void BeginNavigation(const ResourceRequest&, - network::mojom::RequestContextFrameType, - Document* origin_document, - DocumentLoader*, - WebNavigationType, - NavigationPolicy, - bool, - WebFrameLoadType, - bool, - WebTriggeringEventInfo, - HTMLFormElement*, - ContentSecurityPolicyDisposition, - mojo::PendingRemote<mojom::blink::BlobURLToken>, - base::TimeTicks, - const String&, - WebContentSecurityPolicyList, - network::mojom::IPAddressSpace, - mojom::blink::NavigationInitiatorPtr) override; + void BeginNavigation( + const ResourceRequest&, + network::mojom::RequestContextFrameType, + Document* origin_document, + DocumentLoader*, + WebNavigationType, + NavigationPolicy, + bool, + WebFrameLoadType, + bool, + WebTriggeringEventInfo, + HTMLFormElement*, + ContentSecurityPolicyDisposition, + mojo::PendingRemote<mojom::blink::BlobURLToken>, + base::TimeTicks, + const String&, + WebContentSecurityPolicyList, + network::mojom::IPAddressSpace, + mojo::PendingRemote<mojom::blink::NavigationInitiator>) override; void DispatchWillSendSubmitEvent(HTMLFormElement*) override;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 45a63e0..d22d0fd 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -41,6 +41,7 @@ #include "base/auto_reset.h" #include "base/unguessable_token.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h" @@ -670,14 +671,14 @@ ? network::mojom::RequestContextFrameType::kTopLevel : network::mojom::RequestContextFrameType::kNested); - mojom::blink::NavigationInitiatorPtr navigation_initiator; + mojo::PendingRemote<mojom::blink::NavigationInitiator> navigation_initiator; WebContentSecurityPolicyList initiator_csp; if (origin_document && origin_document->GetContentSecurityPolicy() ->ExperimentalFeaturesEnabled()) { initiator_csp = origin_document->GetContentSecurityPolicy() ->ExposeForNavigationalChecks(); - auto mojo_request = mojo::MakeRequest(&navigation_initiator); - origin_document->BindNavigationInitiatorRequest(std::move(mojo_request)); + origin_document->BindNavigationInitiatorReceiver( + navigation_initiator.InitWithNewPipeAndPassReceiver()); } if (origin_document && origin_document->GetContentSecurityPolicy()) {
diff --git a/third_party/blink/renderer/core/loader/preload_helper.cc b/third_party/blink/renderer/core/loader/preload_helper.cc index cf0c8812..be34009 100644 --- a/third_party/blink/renderer/core/loader/preload_helper.cc +++ b/third_party/blink/renderer/core/loader/preload_helper.cc
@@ -4,7 +4,7 @@ #include "third_party/blink/renderer/core/loader/preload_helper.h" -#include "net/base/features.h" +#include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_prescient_networking.h" @@ -491,7 +491,7 @@ // remove this feature check, also remove the exceptions in // net/base/features.h DEPS as well as audit_non_blink_usage.py. if (base::FeatureList::IsEnabled( - net::features::kSplitCacheByNetworkIsolationKey) && + network::features::kPrefetchMainResourceNetworkIsolationKey) && EqualIgnoringASCIICase(params.as, "document")) { resource_request.SetPrefetchMaybeForTopLevelNavigation(true); }
diff --git a/third_party/blink/renderer/core/page/plugin_data_test.cc b/third_party/blink/renderer/core/page/plugin_data_test.cc index bda80c92..e522955 100644 --- a/third_party/blink/renderer/core/page/plugin_data_test.cc +++ b/third_party/blink/renderer/core/page/plugin_data_test.cc
@@ -4,7 +4,8 @@ #include "third_party/blink/renderer/core/page/plugin_data.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-blink.h" @@ -40,19 +41,20 @@ SchemeRegistry::RegisterURLSchemeAsLocal("nonstandard-862282"); MockPluginRegistry mock_plugin_registry; - mojo::Binding<mojom::blink::PluginRegistry> registry_binding( + mojo::Receiver<mojom::blink::PluginRegistry> registry_receiver( &mock_plugin_registry); TestingPlatformSupport::ScopedOverrideMojoInterface override_plugin_registry( WTF::BindRepeating( - [](mojo::Binding<mojom::blink::PluginRegistry>* registry_binding, + [](mojo::Receiver<mojom::blink::PluginRegistry>* registry_receiver, const char* interface, mojo::ScopedMessagePipeHandle pipe) { if (!strcmp(interface, mojom::blink::PluginRegistry::Name_)) { - registry_binding->Bind( - mojom::blink::PluginRegistryRequest(std::move(pipe))); + registry_receiver->Bind( + mojo::PendingReceiver<mojom::blink::PluginRegistry>( + std::move(pipe))); return; } }, - WTF::Unretained(®istry_binding))); + WTF::Unretained(®istry_receiver))); EXPECT_CALL( mock_plugin_registry,
diff --git a/third_party/blink/renderer/core/testing/scoped_fake_plugin_registry.cc b/third_party/blink/renderer/core/testing/scoped_fake_plugin_registry.cc index 8a4f2767..cb044554 100644 --- a/third_party/blink/renderer/core/testing/scoped_fake_plugin_registry.cc +++ b/third_party/blink/renderer/core/testing/scoped_fake_plugin_registry.cc
@@ -5,7 +5,8 @@ #include "third_party/blink/renderer/core/testing/scoped_fake_plugin_registry.h" #include "base/files/file_path.h" -#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver_set.h" #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h" #include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" @@ -21,8 +22,9 @@ public: static void Bind(mojo::ScopedMessagePipeHandle handle) { DEFINE_STATIC_LOCAL(FakePluginRegistryImpl, impl, ()); - impl.bindings_.AddBinding( - &impl, mojom::blink::PluginRegistryRequest(std::move(handle))); + impl.receivers_.Add( + &impl, + mojo::PendingReceiver<mojom::blink::PluginRegistry>(std::move(handle))); } // PluginRegistry @@ -47,7 +49,7 @@ } private: - mojo::BindingSet<PluginRegistry> bindings_; + mojo::ReceiverSet<PluginRegistry> receivers_; }; } // namespace
diff --git a/third_party/blink/renderer/devtools/front_end/inspector_main/nodeIcon.css b/third_party/blink/renderer/devtools/front_end/inspector_main/nodeIcon.css index 326247d..65e8c924d 100644 --- a/third_party/blink/renderer/devtools/front_end/inspector_main/nodeIcon.css +++ b/third_party/blink/renderer/devtools/front_end/inspector_main/nodeIcon.css
@@ -12,6 +12,7 @@ background-repeat: no-repeat; background-position: center; opacity: 0.8; + cursor: auto; } .node-icon:hover {
diff --git a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js index d64cfe43d..fec6f917 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js +++ b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
@@ -266,6 +266,33 @@ } /** + * @return {!Element} + */ + _createLearnMoreLink() { + let url = + 'https://developers.google.com/web/tools/chrome-devtools/javascript/background-services?utm_source=devtools'; + + switch (this._serviceName) { + case Protocol.BackgroundService.ServiceName.BackgroundFetch: + url += '#fetch'; + break; + case Protocol.BackgroundService.ServiceName.BackgroundSync: + url += '#sync'; + break; + case Protocol.BackgroundService.ServiceName.PushMessaging: + url += '#push'; + break; + case Protocol.BackgroundService.ServiceName.Notifications: + url += '#notifications'; + break; + default: + break; + } + + return UI.XLink.create(url, ls`Learn more`); + } + + /** * @param {?Resources.BackgroundServiceView.EventDataNode} dataNode */ _showPreview(dataNode) { @@ -307,6 +334,8 @@ inlineButton.classList.add('background-service-record-inline-button'); centered.createChild('p').appendChild( UI.formatLocalized('Click the record button %s or hit %s to start recording.', [inlineButton, recordKey])); + + centered.appendChild(this._createLearnMoreLink()); } this._preview.show(this._previewPanel.contentElement);
diff --git a/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css b/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css index 0fd3c0c..6a52e00 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css +++ b/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css
@@ -21,12 +21,12 @@ .background-service-preview > div { max-width: 450px; margin: 10px; + text-align: center; } .background-service-preview > div > p { flex: none; white-space: pre-line; - text-align: center; } .background-service-shortcut {
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js index 28f4bab8..8298410 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js +++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
@@ -700,6 +700,36 @@ /** * @param {!SDK.TracingModel.Event} event + * @return {!Element} + */ + static buildDetailsNodeForPerformanceEvent(event) { + /** @type {string} */ + let link = + 'https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#user-centric_performance_metrics'; + let name = 'page performance metrics'; + const recordType = TimelineModel.TimelineModel.RecordType; + switch (event.name) { + case recordType.MarkLCPCandidate: + link = 'https://web.dev/largest-contentful-paint'; + name = 'largest contentful paint'; + break; + case recordType.MarkFCP: + link = 'https://web.dev/first-contentful-paint'; + name = 'first contentful paint'; + break; + case recordType.MarkFMP: + link = 'https://web.dev/first-meaningful-paint/'; + name = 'first meaningful paint'; + break; + default: + break; + } + + return UI.html`<div>${UI.XLink.create(link, ls`Learn more`)} about ${name}.</div>`; + } + + /** + * @param {!SDK.TracingModel.Event} event * @param {!TimelineModel.TimelineModel} model * @param {!Components.Linkifier} linkifier * @param {!ProductRegistry.BadgePool} badgePool @@ -954,11 +984,8 @@ case recordTypes.MarkDOMContent: contentHelper.appendTextRow( ls`Timestamp`, Number.preciseMillisToString(event.startTime - model.minimumRecordTime(), 1)); - const learnMoreLink = UI.XLink.create( - 'https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#user-centric_performance_metrics', - ls`Learn more`); - const linkDiv = UI.html`<div>${learnMoreLink} about page performance metrics.</div>`; - contentHelper.appendElementRow(ls`Details`, linkDiv); + contentHelper.appendElementRow( + ls`Details`, Timeline.TimelineUIUtils.buildDetailsNodeForPerformanceEvent(event)); break; default: {
diff --git a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js index b85d7a7..1916764f 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js +++ b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
@@ -1605,12 +1605,13 @@ /** * Return whether this request was cached. This works around BUG(chromium:998397), - * which reports pushed resources as disk cached. Pushed resources that were not - * disk cached, however, have a non-zero `_transferSize`. + * which reports pushed resources, and resources serverd by a service worker as + * disk cached. Pushed resources that were not disk cached, however, have a non-zero + * `_transferSize`. * @return {boolean} */ cached() { - return !!this._memoryCached || (!!this._maybeDiskCached && !this._transferSize); + return !!this._memoryCached || (!!this._maybeDiskCached && !this._transferSize && !this.fromServiceWorker); } /**
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index 56d7000..2d1c050 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -148,6 +148,7 @@ "//third_party/blink/renderer/modules/quota", "//third_party/blink/renderer/modules/remoteplayback", "//third_party/blink/renderer/modules/scheduler", + "//third_party/blink/renderer/modules/screen_enumeration", "//third_party/blink/renderer/modules/screen_orientation", "//third_party/blink/renderer/modules/sensor", "//third_party/blink/renderer/modules/service_worker",
diff --git a/third_party/blink/renderer/modules/badging/badge.cc b/third_party/blink/renderer/modules/badging/badge.cc index 90d80f22..8471c03 100644 --- a/third_party/blink/renderer/modules/badging/badge.cc +++ b/third_party/blink/renderer/modules/badging/badge.cc
@@ -7,6 +7,7 @@ #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/modules/badging/badge_options.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" @@ -28,42 +29,62 @@ // static void Badge::set(ScriptState* script_state, ExceptionState& exception_state) { - BadgeFromState(script_state)->SetFlag(); + Badge::set(script_state, BadgeOptions::Create(), exception_state); +} + +// static +void Badge::set(ScriptState* script_state, + const BadgeOptions* options, + ExceptionState& exception_state) { + BadgeFromState(script_state) + ->SetBadge(options->scope(), mojom::blink::BadgeValue::NewFlag(0)); } // static void Badge::set(ScriptState* script_state, uint64_t content, ExceptionState& exception_state) { - if (content == 0) - BadgeFromState(script_state)->Clear(); - else - BadgeFromState(script_state)->SetInteger(content); + Badge::set(script_state, content, BadgeOptions::Create(), exception_state); } // static -void Badge::clear(ScriptState* script_state) { - BadgeFromState(script_state)->Clear(); +void Badge::set(ScriptState* script_state, + uint64_t content, + const BadgeOptions* options, + ExceptionState& exception_state) { + if (content == 0) { + Badge::clear(script_state, options); + } else { + BadgeFromState(script_state) + ->SetBadge(options->scope(), + mojom::blink::BadgeValue::NewNumber(content)); + } } -void Badge::SetInteger(uint64_t content) { - badge_service_->SetInteger(content); +// static +void Badge::clear(ScriptState* script_state, const BadgeOptions* options) { + BadgeFromState(script_state)->ClearBadge(options->scope()); } -void Badge::SetFlag() { - badge_service_->SetFlag(); +void Badge::SetBadge(WTF::String scope, mojom::blink::BadgeValuePtr value) { + // Resolve |scope| against the URL of the current document/worker. + KURL scope_url = KURL(execution_context_->Url(), scope); + badge_service_->SetBadge(scope_url, std::move(value)); } -void Badge::Clear() { - badge_service_->ClearBadge(); +void Badge::ClearBadge(WTF::String scope) { + // Resolve |scope| against the URL of the current document/worker. + badge_service_->ClearBadge(KURL(execution_context_->Url(), scope)); } void Badge::Trace(blink::Visitor* visitor) { Supplement<ExecutionContext>::Trace(visitor); ScriptWrappable::Trace(visitor); + + visitor->Trace(execution_context_); } -Badge::Badge(ExecutionContext* context) { +Badge::Badge(ExecutionContext* context) : execution_context_(context) { context->GetInterfaceProvider()->GetInterface( badge_service_.BindNewPipeAndPassReceiver()); DCHECK(badge_service_);
diff --git a/third_party/blink/renderer/modules/badging/badge.h b/third_party/blink/renderer/modules/badging/badge.h index 7921fc3..0265885 100644 --- a/third_party/blink/renderer/modules/badging/badge.h +++ b/third_party/blink/renderer/modules/badging/badge.h
@@ -9,9 +9,11 @@ #include "third_party/blink/public/mojom/badging/badging.mojom-blink.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/supplementable.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { +class BadgeOptions; class ExceptionState; class ExecutionContext; class ScriptState; @@ -30,13 +32,17 @@ ~Badge() override; // Badge IDL interface. + static void set(ScriptState*, const BadgeOptions*, ExceptionState&); + static void set(ScriptState*, + uint64_t content, + const BadgeOptions*, + ExceptionState&); static void set(ScriptState*, ExceptionState&); static void set(ScriptState*, uint64_t content, ExceptionState&); - static void clear(ScriptState*); + static void clear(ScriptState*, const BadgeOptions*); - void SetInteger(uint64_t content); - void SetFlag(); - void Clear(); + void SetBadge(WTF::String scope, mojom::blink::BadgeValuePtr value); + void ClearBadge(WTF::String scope); void Trace(blink::Visitor*) override; @@ -44,6 +50,7 @@ static Badge* BadgeFromState(ScriptState* script_state); mojo::Remote<blink::mojom::blink::BadgeService> badge_service_; + Member<ExecutionContext> execution_context_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/badging/badge_options.idl b/third_party/blink/renderer/modules/badging/badge_options.idl new file mode 100644 index 0000000..279519c --- /dev/null +++ b/third_party/blink/renderer/modules/badging/badge_options.idl
@@ -0,0 +1,12 @@ +// 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. + +// The options used to decide how to apply a badge. +// See the explainer https://github.com/WICG/badging/blob/master/explainer.md +dictionary BadgeOptions { + // The scope of the badge. This is resolved against the URL of the current + // page. + // https://github.com/WICG/badging/blob/master/explainer.md#badge-scope + DOMString scope = "/"; +}; \ No newline at end of file
diff --git a/third_party/blink/renderer/modules/badging/experimental_badge.idl b/third_party/blink/renderer/modules/badging/experimental_badge.idl index e9a38529..3e84590f 100644 --- a/third_party/blink/renderer/modules/badging/experimental_badge.idl +++ b/third_party/blink/renderer/modules/badging/experimental_badge.idl
@@ -12,6 +12,6 @@ ImplementedAs=Badge ] interface ExperimentalBadge { [CallWith=ScriptState, RaisesException, MeasureAs=BadgeSet] - static void set(optional [EnforceRange] unsigned long long contents); - [CallWith=ScriptState, MeasureAs=BadgeClear] static void clear(); + static void set(optional [EnforceRange] unsigned long long contents, optional BadgeOptions options); + [CallWith=ScriptState, MeasureAs=BadgeClear] static void clear(optional BadgeOptions options); };
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index 2981726..45212cc 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -299,6 +299,7 @@ "scheduler/scheduler.idl", "scheduler/task.idl", "scheduler/task_queue.idl", + "screen_enumeration/screen_manager.idl", "screen_orientation/screen_orientation.idl", "sensor/absolute_orientation_sensor.idl", "sensor/accelerometer.idl", @@ -572,6 +573,7 @@ "background_sync/background_sync_options.idl", "background_sync/sync_event_init.idl", "background_sync/periodic_sync_event_init.idl", + "badging/badge_options.idl", "bluetooth/bluetooth_advertising_event_init.idl", "bluetooth/bluetooth_le_scan_filter_init.idl", "bluetooth/bluetooth_le_scan_options.idl", @@ -775,6 +777,7 @@ "quota/storage_usage_details.idl", "scheduler/scheduler_post_task_options.idl", "scheduler/task_queue_post_task_options.idl", + "screen_enumeration/display.idl", "sensor/sensor_error_event_init.idl", "sensor/sensor_options.idl", "sensor/spatial_sensor_options.idl", @@ -990,6 +993,8 @@ "quota/worker_navigator_storage_quota.idl", "remoteplayback/html_media_element_remote_playback.idl", "scheduler/window_scheduler.idl", + "screen_enumeration/navigator_screen_manager.idl", + "screen_enumeration/worker_navigator_screen_manager.idl", "screen_orientation/screen_screen_orientation.idl", "service_worker/navigator_service_worker.idl", "sms/navigator_sms.idl",
diff --git a/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn b/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn new file mode 100644 index 0000000..e903b9b --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/BUILD.gn
@@ -0,0 +1,18 @@ +# 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("//third_party/blink/renderer/modules/modules.gni") + +blink_modules_sources("screen_enumeration") { + sources = [ + "navigator_screen_manager.cc", + "navigator_screen_manager.h", + "screen_manager.cc", + "screen_manager.h", + ] + + deps = [ + "//third_party/blink/renderer/platform", + ] +}
diff --git a/third_party/blink/renderer/modules/screen_enumeration/OWNERS b/third_party/blink/renderer/modules/screen_enumeration/OWNERS new file mode 100644 index 0000000..f5a53536 --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/OWNERS
@@ -0,0 +1,4 @@ +file://content/browser/screen_enumeration/OWNERS + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage \ No newline at end of file
diff --git a/third_party/blink/renderer/modules/screen_enumeration/display.idl b/third_party/blink/renderer/modules/screen_enumeration/display.idl new file mode 100644 index 0000000..ffbe631 --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/display.idl
@@ -0,0 +1,20 @@ +// 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. + +// https://github.com/spark008/screen-enumeration/blob/master/EXPLAINER.md + +// TODO(staphany): Add working-area versions of width, height, left, and top +// (e.g. like availWidth in the Screen interface). +// TODO(staphany): Add orientation. +dictionary Display { + required DOMString name; + required float scaleFactor; + required long width; + required long height; + required long left; + required long top; + required long colorDepth; + required boolean isPrimary; + required boolean isInternal; +}; \ No newline at end of file
diff --git a/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc b/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc new file mode 100644 index 0000000..41dccb3 --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.cc
@@ -0,0 +1,98 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.h" + +#include "services/service_manager/public/cpp/interface_provider.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.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/core/frame/navigator.h" +#include "third_party/blink/renderer/core/workers/worker_navigator.h" +#include "third_party/blink/renderer/modules/screen_enumeration/screen_manager.h" +#include "third_party/blink/renderer/platform/supplementable.h" + +namespace blink { + +namespace { + +template <typename T> +class NavigatorScreenManagerImpl final + : public GarbageCollectedFinalized<NavigatorScreenManagerImpl<T>>, + public Supplement<T> { + USING_GARBAGE_COLLECTED_MIXIN(NavigatorScreenManagerImpl<T>); + + public: + static const char kSupplementName[]; + + static NavigatorScreenManagerImpl<T>& From(T& supplementable) { + NavigatorScreenManagerImpl<T>* supplement = + Supplement<T>::template From<NavigatorScreenManagerImpl<T>>( + supplementable); + if (!supplement) { + supplement = + MakeGarbageCollected<NavigatorScreenManagerImpl<T>>(supplementable); + Supplement<T>::ProvideTo(supplementable, supplement); + } + return *supplement; + } + + explicit NavigatorScreenManagerImpl(T& supplementable) + : Supplement<T>(supplementable) {} + + NavigatorScreenManagerImpl(const NavigatorScreenManagerImpl&) = delete; + NavigatorScreenManagerImpl& operator=(const NavigatorScreenManagerImpl&) = + delete; + + ScreenManager* GetScreen(ExecutionContext* execution_context) { + if (!screen_manager_) { + auto* browser_interface_broker_proxy = + execution_context->GetBrowserInterfaceBrokerProxy(); + if (!browser_interface_broker_proxy) + return nullptr; + mojo::Remote<mojom::blink::ScreenEnumeration> backend; + browser_interface_broker_proxy->GetInterface( + backend.BindNewPipeAndPassReceiver()); + screen_manager_ = MakeGarbageCollected<ScreenManager>(std::move(backend)); + } + return screen_manager_; + } + + void Trace(blink::Visitor* visitor) override { + visitor->Trace(screen_manager_); + Supplement<T>::Trace(visitor); + } + + private: + Member<ScreenManager> screen_manager_; +}; + +// static +template <typename T> +const char NavigatorScreenManagerImpl<T>::kSupplementName[] = + "NavigatorScreenManager"; + +} // namespace + +// static +ScreenManager* NavigatorScreenManager::screen(Navigator& navigator) { + LocalFrame* local_frame = navigator.GetFrame(); + if (!local_frame) { + return nullptr; + } + + ExecutionContext* execution_context = + local_frame->DomWindow()->GetExecutionContext(); + return NavigatorScreenManagerImpl<Navigator>::From(navigator).GetScreen( + execution_context); +} + +// static +ScreenManager* NavigatorScreenManager::screen(ScriptState* script_state, + WorkerNavigator& navigator) { + return NavigatorScreenManagerImpl<WorkerNavigator>::From(navigator).GetScreen( + ExecutionContext::From(script_state)); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.h b/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.h new file mode 100644 index 0000000..fbcd82f --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.h
@@ -0,0 +1,30 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_NAVIGATOR_SCREEN_MANAGER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_NAVIGATOR_SCREEN_MANAGER_H_ + +#include "third_party/blink/renderer/modules/modules_export.h" + +namespace blink { + +class Navigator; +class ScreenManager; +class ScriptState; +class WorkerNavigator; + +// Exposes the ScreenManager interface on both the Navigator and +// WorkerNavigator interfaces. +class MODULES_EXPORT NavigatorScreenManager { + public: + // The ScreenManager exposed in the Navigator execution context. + static ScreenManager* screen(Navigator&); + + // The ScreenManager exposed in the WorkerNavigator execution context. + static ScreenManager* screen(ScriptState*, WorkerNavigator&); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_NAVIGATOR_SCREEN_MANAGER_H_
diff --git a/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.idl b/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.idl new file mode 100644 index 0000000..d9062139 --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/navigator_screen_manager.idl
@@ -0,0 +1,12 @@ +// 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. + +// https://github.com/spark008/screen-enumeration/blob/master/EXPLAINER.md +[ + ImplementedAs=NavigatorScreenManager, + SecureContext, + RuntimeEnabled=ScreenEnumeration +] partial interface Navigator { + [SameObject] readonly attribute ScreenManager screen; +};
diff --git a/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc b/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc new file mode 100644 index 0000000..bb8085f --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/screen_manager.cc
@@ -0,0 +1,71 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/screen_enumeration/screen_manager.h" + +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/modules/screen_enumeration/display.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h" +#include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +namespace { + +void DidReceiveDisplays(ScriptPromiseResolver* resolver, + WTF::Vector<mojom::blink::DisplayPtr> backend_displays, + bool success) { + ScriptState* script_state = resolver->GetScriptState(); + if (!script_state->ContextIsValid()) + return; + + HeapVector<Member<Display>> displays; + displays.ReserveInitialCapacity(backend_displays.size()); + for (const auto& backend_display : backend_displays) { + auto* display = MakeGarbageCollected<Display>(); + display->setName(backend_display->name); + display->setScaleFactor(backend_display->scale_factor); + display->setWidth(backend_display->width); + display->setHeight(backend_display->height); + display->setLeft(backend_display->left); + display->setTop(backend_display->top); + display->setColorDepth(backend_display->color_depth); + display->setIsPrimary(backend_display->is_primary); + display->setIsInternal(backend_display->is_internal); + displays.emplace_back(display); + } + resolver->Resolve(std::move(displays)); +} + +} // namespace + +ScreenManager::ScreenManager( + mojo::Remote<mojom::blink::ScreenEnumeration> backend) + : backend_(std::move(backend)) { + backend_.set_disconnect_handler(WTF::Bind( + &ScreenManager::OnBackendDisconnected, WrapWeakPersistent(this))); +} + +ScriptPromise ScreenManager::requestDisplays(ScriptState* script_state, + ExceptionState& exception_state) { + if (!backend_) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "ScreenManager backend went away"); + return ScriptPromise(); + } + + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); + backend_->RequestDisplays( + WTF::Bind(&DidReceiveDisplays, WrapPersistent(resolver))); + + return resolver->Promise(); +} + +void ScreenManager::OnBackendDisconnected() { + backend_.reset(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/screen_enumeration/screen_manager.h b/third_party/blink/renderer/modules/screen_enumeration/screen_manager.h new file mode 100644 index 0000000..e9712e8 --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/screen_manager.h
@@ -0,0 +1,41 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_SCREEN_MANAGER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_SCREEN_MANAGER_H_ + +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" + +namespace blink { + +class ScriptState; + +// An interface for querying the state of the device's screen space. +// +// The interface is available in both window and service worker execution +// contexts. +class ScreenManager final : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + // Creates a ScreenManager and binds it to the browser-side implementation. + explicit ScreenManager(mojo::Remote<mojom::blink::ScreenEnumeration> backend); + + // Resolves to the list of |Display| objects in the device's screen space. + ScriptPromise requestDisplays(ScriptState*, ExceptionState&); + + // Called if the backend is disconnected, e.g. during renderer shutdown. + void OnBackendDisconnected(); + + private: + // Connection to the ScreenEnumeration implementation in the browser process. + mojo::Remote<mojom::blink::ScreenEnumeration> backend_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SCREEN_ENUMERATION_SCREEN_MANAGER_H_
diff --git a/third_party/blink/renderer/modules/screen_enumeration/screen_manager.idl b/third_party/blink/renderer/modules/screen_enumeration/screen_manager.idl new file mode 100644 index 0000000..2851ea1 --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/screen_manager.idl
@@ -0,0 +1,12 @@ +// 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. + +// https://github.com/spark008/screen-enumeration/blob/master/EXPLAINER.md +[ + SecureContext, + Exposed=(Window,Worker), + RuntimeEnabled=ScreenEnumeration +] interface ScreenManager { + [CallWith=ScriptState, RaisesException] Promise<sequence<Display>> requestDisplays(); +};
diff --git a/third_party/blink/renderer/modules/screen_enumeration/worker_navigator_screen_manager.idl b/third_party/blink/renderer/modules/screen_enumeration/worker_navigator_screen_manager.idl new file mode 100644 index 0000000..04e2cf45 --- /dev/null +++ b/third_party/blink/renderer/modules/screen_enumeration/worker_navigator_screen_manager.idl
@@ -0,0 +1,12 @@ +// 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. + +// https://github.com/spark008/screen-enumeration/blob/master/EXPLAINER.md +[ + ImplementedAs=NavigatorScreenManager, + SecureContext, + RuntimeEnabled=ScreenEnumeration +] partial interface WorkerNavigator { + [CallWith=ScriptState, SameObject] readonly attribute ScreenManager screen; +};
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker.idl b/third_party/blink/renderer/modules/service_worker/service_worker.idl index ab4fbd7..3b1a85c 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker.idl +++ b/third_party/blink/renderer/modules/service_worker/service_worker.idl
@@ -40,7 +40,11 @@ [ ActiveScriptWrappable, - SecureContext + SecureContext, + // TODO(https://crbug.com/999023): Expose this to Worker (not only to + // ServiceWorker) after Service Worker APIs are supported on dedicated + // workers and shared workers. + Exposed=(Window,ServiceWorker) ] interface ServiceWorker : EventTarget { [CallWith=ScriptState, RaisesException] void postMessage(any message, sequence<object> transfer);
diff --git a/third_party/blink/renderer/platform/exported/DEPS b/third_party/blink/renderer/platform/exported/DEPS index 2a82ffa8..fde7f65 100644 --- a/third_party/blink/renderer/platform/exported/DEPS +++ b/third_party/blink/renderer/platform/exported/DEPS
@@ -1,8 +1,8 @@ include_rules = [ - "+net/base/features.h", "+net/base/load_flags.h", "+net/cookies/canonical_cookie.h", "+net/cookies/cookie_constants.h", + "+services/network/public/cpp/features.h", ] specific_include_rules = {
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc index 41c70d72..cb48f88f 100644 --- a/third_party/blink/renderer/platform/exported/web_url_request.cc +++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -33,8 +33,8 @@ #include <memory> #include "base/time/time.h" -#include "net/base/features.h" #include "net/base/load_flags.h" +#include "services/network/public/cpp/features.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/platform/web_http_body.h" #include "third_party/blink/public/platform/web_http_header_visitor.h" @@ -468,11 +468,8 @@ if (resource_request_->PrefetchMaybeForTopLeveNavigation()) { DCHECK_EQ(resource_request_->GetRequestContext(), blink::mojom::RequestContextType::PREFETCH); - // TODO(domfarolino): When SplitCache is enabled by default and we stop - // referencing the feature, also remove the net/base/features.h DEPS - // exception. DCHECK(base::FeatureList::IsEnabled( - net::features::kSplitCacheByNetworkIsolationKey)); + network::features::kPrefetchMainResourceNetworkIsolationKey)); if (!resource_request_->RequestorOrigin()->IsSameSchemeHostPort( SecurityOrigin::Create(resource_request_->Url()).get())) { load_flags |= net::LOAD_RESTRICTED_PREFETCH;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index a2cbd165..5fbc621d 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1420,6 +1420,12 @@ name: "SameSiteByDefaultCookies", status: "experimental", }, + // Exposes the displays connected to the device and provides the display + // properties needed for window placement features. + { + name: "ScreenEnumeration", + status: "experimental", + }, // WebSpeech API with both speech recognition and synthesis functionality // is not fully enabled on all platforms. {
diff --git a/third_party/blink/renderer/platform/wtf/vector_test.cc b/third_party/blink/renderer/platform/wtf/vector_test.cc index 3cccdc5e..aa8a138c 100644 --- a/third_party/blink/renderer/platform/wtf/vector_test.cc +++ b/third_party/blink/renderer/platform/wtf/vector_test.cc
@@ -120,6 +120,21 @@ EXPECT_EQ(int_vector.end(), end); } +TEST(VectorTest, Resize) { + Vector<int> int_vector; + int_vector.resize(2); + EXPECT_EQ(2u, int_vector.size()); + EXPECT_EQ(0, int_vector[0]); + EXPECT_EQ(0, int_vector[1]); + + Vector<bool> bool_vector; + bool_vector.resize(3); + EXPECT_EQ(3u, bool_vector.size()); + EXPECT_EQ(false, bool_vector[0]); + EXPECT_EQ(false, bool_vector[1]); + EXPECT_EQ(false, bool_vector[2]); +} + TEST(VectorTest, Iterator) { Vector<int> int_vector; int_vector.push_back(10);
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 86bf13b9..0f9e351 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -496,13 +496,6 @@ ], }, { - 'paths': ['third_party/blink/renderer/core/loader/preload_helper.cc'], - 'allowed': [ - # Used by PrefetchIfNeeded to check the SplitCache feature. - 'net::features::kSplitCacheByNetworkIsolationKey', - ], - }, - { 'paths': ['third_party/blink/renderer/core/loader/alternate_signed_exchange_resource_info.cc'], 'allowed': [ # Used by SignedExchangeRequestMatcher in //third_party/blink/common.
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG index a0d4e7b3..2a642408 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
@@ -44,6 +44,8 @@ ### external/wpt/css/css-multicol/ crbug.com/591099 external/wpt/css/css-multicol/multicol-span-all-list-item-002.html [ Failure ] +crbug.com/998423 external/wpt/css/css-multicol/with-custom-layout-on-same-element-crash.https.html [ Skip ] +crbug.com/998423 external/wpt/css/css-multicol/with-custom-layout-on-same-element.https.html [ Skip ] ### external/wpt/css/css-position/ crbug.com/591099 external/wpt/css/css-position/position-absolute-crash-chrome-006.html [ Crash ]
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations index 49aaa6fe..5aa1c1f 100644 --- a/third_party/blink/web_tests/MSANExpectations +++ b/third_party/blink/web_tests/MSANExpectations
@@ -348,6 +348,12 @@ crbug.com/856601 [ Linux ] virtual/cascade/external/wpt/css/css-typed-om/idlharness.html [ Pass Timeout ] crbug.com/856601 [ Linux ] virtual/scalefactor200/external/wpt/css/filter-effects/idlharness.any.html [ Pass Timeout ] crbug.com/856601 [ Linux ] virtual/scalefactor200/external/wpt/css/filter-effects/idlharness.any.worker.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] virtual/omt-worker-fetch/external/wpt/fetch/api/idlharness.any.serviceworker.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] virtual/omt-worker-fetch/external/wpt/fetch/api/idlharness.any.sharedworker.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] virtual/blink-cors/external/wpt/fetch/api/idlharness.any.worker.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] external/wpt/BackgroundSync/idlharness.https.any.worker.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] external/wpt/fetch/api/idlharness.any.serviceworker.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] external/wpt/BackgroundSync/idlharness.https.any.html [ Pass Timeout ] # Note to sheriffs: Timeouts about "idlharness" or "interfaces" are usually crbug.com/856601.
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 6d3ad355..e4a1ea8 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -4386,12 +4386,6 @@ crbug.com/626703 external/wpt/requestidlecallback/callback-timeout.html [ Timeout ] crbug.com/626703 external/wpt/requestidlecallback/callback-xhr-sync.html [ Timeout ] crbug.com/626703 external/wpt/screen-orientation/onchange-event-subframe.html [ Timeout ] -crbug.com/648295 external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] -crbug.com/648295 virtual/blink-cors/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] -crbug.com/648295 virtual/omt-service-worker-startup/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] -crbug.com/648295 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] -crbug.com/648295 virtual/cache-storage-parallel/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] -crbug.com/648295 virtual/cache-storage-sequence/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] crbug.com/626703 external/wpt/svg/linking/reftests/href-filter-element.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html [ Failure ] @@ -5099,15 +5093,6 @@ crbug.com/889798 virtual/omt-service-worker-startup/external/wpt/service-workers/service-worker/import-scripts-redirect.https.html [ Skip ] crbug.com/889798 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/import-scripts-redirect.https.html [ Skip ] -# Service worker updates will succeed when ServiceWorkerImportedScriptUpdateCheck is enabled. -crbug.com/648295 external/wpt/service-workers/service-worker/update.https.html [ Failure ] -crbug.com/648295 virtual/blink-cors/external/wpt/service-workers/service-worker/update.https.html [ Failure ] -crbug.com/648295 virtual/cache-storage-sequence/external/wpt/service-workers/service-worker/update.https.html [ Failure ] -crbug.com/648295 virtual/cache-storage-parallel/external/wpt/service-workers/service-worker/update.https.html [ Failure ] -crbug.com/648295 virtual/not-omt-sw-fetch/external/wpt/service-workers/service-worker/update.https.html [ Failure ] -crbug.com/648295 virtual/omt-service-worker-startup/external/wpt/service-workers/service-worker/update.https.html [ Failure ] -crbug.com/648295 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/update.https.html [ Failure ] - # Sheriff failures 2017-07-03 crbug.com/708994 http/tests/security/cross-frame-mouse-source-capabilities.html [ Timeout Pass ] crbug.com/708994 virtual/blink-cors/http/tests/security/cross-frame-mouse-source-capabilities.html [ Timeout Pass ] @@ -6540,15 +6525,3 @@ crbug.com/999473 external/wpt/streams/writable-streams/properties.any.serviceworker.html [ Pass Failure ] crbug.com/999473 external/wpt/streams/writable-streams/properties.any.html [ Pass Failure ] crbug.com/999473 external/wpt/streams/writable-streams/properties.any.worker.html [ Pass Failure ] - -# Sheriff 2019-08-30 -crbug.com/999535 virtual/omt-worker-fetch/external/wpt/fetch/api/idlharness.any.serviceworker.html [ Pass Failure ] -crbug.com/999535 virtual/omt-worker-fetch/external/wpt/fetch/api/idlharness.any.sharedworker.html [ Pass Failure ] -crbug.com/999535 virtual/blink-cors/external/wpt/fetch/api/idlharness.any.worker.html [ Pass Failure ] -crbug.com/999535 external/wpt/BackgroundSync/idlharness.https.any.worker.html [ Pass Failure ] -crbug.com/999535 external/wpt/fetch/api/idlharness.any.serviceworker.html [ Pass Failure ] -crbug.com/999535 external/wpt/BackgroundSync/idlharness.https.any.html [ Pass Failure ] -crbug.com/999535 external/wpt/css/cssom/idlharness.html [ Pass Failure ] -crbug.com/999535 external/wpt/css/css-typed-om/idlharness.html [ Pass Failure ] -crbug.com/999535 external/wpt/css/filter-effects/idlharness.any.worker.html [ Pass Failure ] -crbug.com/999535 external/wpt/mediasession/idlharness.window.html [ Pass Failure ] \ No newline at end of file
diff --git a/third_party/blink/web_tests/badging/badge-error.html b/third_party/blink/web_tests/badging/badge-error.html index 3203dc6a..86aef73 100644 --- a/third_party/blink/web_tests/badging/badge-error.html +++ b/third_party/blink/web_tests/badging/badge-error.html
@@ -11,9 +11,9 @@ <body> <script> -badge_test(() => { ExperimentalBadge.set(-1); }, 'setInteger', 'TypeError'); +badge_test(() => { ExperimentalBadge.set(-1); }, undefined, 'TypeError'); -badge_test(() => { ExperimentalBadge.set("Foo"); }, 'setInteger', 'TypeError'); +badge_test(() => { ExperimentalBadge.set("Foo"); }, undefined, 'TypeError'); </script> </body>
diff --git a/third_party/blink/web_tests/badging/badge-success.html b/third_party/blink/web_tests/badging/badge-success.html index 48337cc3..9d3088b 100644 --- a/third_party/blink/web_tests/badging/badge-success.html +++ b/third_party/blink/web_tests/badging/badge-success.html
@@ -11,16 +11,16 @@ <body> <script> -badge_test(() => { ExperimentalBadge.set(); }, 'setFlag'); +badge_test(() => { ExperimentalBadge.set(); }, 'flag'); -badge_test(() => { ExperimentalBadge.set(undefined); }, 'setFlag'); +badge_test(() => { ExperimentalBadge.set(undefined); }, 'flag'); -badge_test(() => { ExperimentalBadge.set(1); }, 'setInteger'); +badge_test(() => { ExperimentalBadge.set(1); }, 'number'); // Setting the Badge to 0 should be equivalent to clearing the badge. -badge_test(() => { ExperimentalBadge.set(0); }, 'clearBadge'); +badge_test(() => { ExperimentalBadge.set(0); }, 'clear'); -badge_test(() => { ExperimentalBadge.clear(); }, 'clearBadge'); +badge_test(() => { ExperimentalBadge.clear(); }, 'clear'); </script> </body>
diff --git a/third_party/blink/web_tests/badging/idl.html b/third_party/blink/web_tests/badging/idl.html index e9f9772..19ab1e2 100644 --- a/third_party/blink/web_tests/badging/idl.html +++ b/third_party/blink/web_tests/badging/idl.html
@@ -7,8 +7,8 @@ <script type="text/plain" id="tested"> interface ExperimentalBadge { [CallWith=ScriptState, RaisesException] - static void set(optional [EnforceRange] unsigned long long contents); - [CallWith=ScriptState] static void clear(); + static void set(optional [EnforceRange] unsigned long long contents, optional BadgeOptions options); + [CallWith=ScriptState] static void clear(optional BadgeOptions options); }; </script> <script>
diff --git a/third_party/blink/web_tests/badging/resources/mock-badge-service.js b/third_party/blink/web_tests/badging/resources/mock-badge-service.js index b9a9fc8..52b4765 100644 --- a/third_party/blink/web_tests/badging/resources/mock-badge-service.js +++ b/third_party/blink/web_tests/badging/resources/mock-badge-service.js
@@ -10,35 +10,36 @@ this.interceptor_.start(); } - init_(expectCalled) { - this.expectCalled_ = expectCalled; + init_(expectedAction) { + this.expectedAction = expectedAction; return new Promise((resolve, reject) => { this.reject_ = reject; this.resolve_ = resolve; }); } - setInteger(contents) { + setBadge(scope, value) { + // Accessing number when the union is a flag will throw, so read the + // value in a try catch. + let number; try { - assert_equals(this.expectCalled_, 'setInteger'); + number = value.number; + } catch (error) { + number = undefined; + } + + try { + const action = number === undefined ? 'flag' : 'number'; + assert_equals(this.expectedAction, action); this.resolve_(); } catch (error) { - this.reject_(error); + this.reject_(); } } - setFlag() { + clearBadge(scope) { try { - assert_equals(this.expectCalled_, 'setFlag'); - this.resolve_(); - } catch (error) { - this.reject(error); - } - } - - clearBadge() { - try { - assert_equals(this.expectCalled_, 'clearBadge'); + assert_equals(this.expectedAction, 'clear'); this.resolve_(); } catch (error) { this.reject_(error); @@ -63,9 +64,9 @@ }); } -function badge_test(func, expectCalled, expectError) { +function badge_test(func, expectedAction, expectError) { promise_test(() => { - let mockPromise = mockBadgeService.init_(expectCalled); + let mockPromise = mockBadgeService.init_(expectedAction); return Promise.race([callAndObserveErrors(func, expectError), mockPromise]); }); }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/keyframes-remove-documentElement-crash.html b/third_party/blink/web_tests/external/wpt/css/css-animations/keyframes-remove-documentElement-crash.html new file mode 100644 index 0000000..aba7f9c6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-animations/keyframes-remove-documentElement-crash.html
@@ -0,0 +1,22 @@ +<!doctype html> +<title>CSS Animations Test: Chrome crash when removing documentElement and @keyframes stylesheet</title> +<link rel="help" href="https://crbug.com/999522"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + @keyframes anim { + from { color: pink } + to { color: purple } + } + div { + animation: notfound 1s; + } +</style> +<div></div> +<script> + test(() => { + document.body.offsetTop; + document.querySelector("style").remove(); + document.documentElement.remove(); + }, "Removing documentElement and @keyframes sheet should not crash."); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/with-custom-layout-on-same-element-crash.https.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/with-custom-layout-on-same-element-crash.https.html new file mode 100644 index 0000000..7e1c8042 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/with-custom-layout-on-same-element-crash.https.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=997403"> +<div id="elm" style="display:layout(parent); columns:2; width:10em; height:60px; column-fill:auto; line-height:20px;"> + x + <span> + <div style="display:inline-block;"></div> + </span> + <div style="height:1px;"></div> + <br> +</div> +<script> +</script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + document.body.offsetTop; + elm.style.display = "none"; + document.body.offsetTop; + test(()=> {}, "No crash"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/with-custom-layout-on-same-element.https.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/with-custom-layout-on-same-element.https.html new file mode 100644 index 0000000..5388b08 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/with-custom-layout-on-same-element.https.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=997403"> +<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#cc"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<meta name="assert" content="column-count and column-width should only apply to block containers, and not tables, flexboxes, grid, custom layout containers, etc."> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="display:layout(parent); column-count:2; width:100px; height:100px; background:red;"> + <div style="height:100px; background:green;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/resources/preflight.py b/third_party/blink/web_tests/external/wpt/fetch/api/resources/preflight.py index 1843c74c..d224960 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/resources/preflight.py +++ b/third_party/blink/web_tests/external/wpt/fetch/api/resources/preflight.py
@@ -26,6 +26,11 @@ response.set_error(400, "No Access-Control-Request-Method header") return "ERROR: No access-control-request-method in preflight!" + # https://github.com/whatwg/fetch/issues/922 + if request.headers.get("Accept", "") != "*/*": + response.set_error(400, "Request does not have 'Accept: */*' header") + return "ERROR: Invalid access in preflight!" + if "control_request_headers" in request.GET: stashed_data['control_request_headers'] = request.headers.get("Access-Control-Request-Headers", None)
diff --git a/third_party/blink/web_tests/external/wpt/screen_enumeration/requestDisplays.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/screen_enumeration/requestDisplays.tentative.https.any.js new file mode 100644 index 0000000..e2a5bc42 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/screen_enumeration/requestDisplays.tentative.https.any.js
@@ -0,0 +1,21 @@ +// META: global=window,dedicatedworker,sharedworker,serviceworker +'use strict'; + +promise_test(async testCase => { + assert_class_string(navigator.screen, 'ScreenManager'); + assert_equals(typeof navigator.screen.requestDisplays, 'function'); +}, 'navigator.screen.requestDisplays is present'); + +promise_test(async testCase => { + const displays = await navigator.screen.requestDisplays(); + assert_greater_than(displays.length, 0); + assert_equals(typeof displays[0].name, 'string'); + assert_equals(typeof displays[0].scaleFactor, 'number'); + assert_equals(typeof displays[0].width, 'number'); + assert_equals(typeof displays[0].height, 'number'); + assert_equals(typeof displays[0].left, 'number'); + assert_equals(typeof displays[0].top, 'number'); + assert_equals(typeof displays[0].colorDepth, 'number'); + assert_equals(typeof displays[0].isPrimary, 'boolean'); + assert_equals(typeof displays[0].isInternal, 'boolean'); +}, 'navigator.screen.requestDisplays returns at least 1 Display'); \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 453c6d0..1701d6a8 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1232,6 +1232,10 @@ method formData method json method text +interface ScreenManager + attribute @@toStringTag + method constructor + method requestDisplays interface SecurityPolicyViolationEvent : Event attribute @@toStringTag getter blockedURI @@ -1247,6 +1251,16 @@ getter statusCode getter violatedDirective method constructor +interface ServiceWorker : EventTarget + attribute @@toStringTag + getter onerror + getter onstatechange + getter scriptURL + getter state + method constructor + method postMessage + setter onerror + setter onstatechange interface ServiceWorkerGlobalScope : WorkerGlobalScope attribute @@toStringTag method constructor @@ -3678,6 +3692,7 @@ getter permissions getter platform getter product + getter screen getter serial getter storage getter usb
diff --git a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https-expected.txt b/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https-expected.txt deleted file mode 100644 index 583e534..0000000 --- a/third_party/blink/web_tests/virtual/omt-worker-fetch/external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This is a testharness.js-based test. -FAIL Dedicated worker of the cached script assert_equals: expected "Done: cached" but got "Error: Importing a non-cached script must fail." -FAIL Dedicated worker of the fallbacked script assert_equals: expected "Done: fallbacked" but got "Error: Importing a non-cached script must fail." -FAIL Dedicated worker of the not-in-cache script promise_test: Unhandled rejection with value: "The worker not in the AppCache must not be executed." -PASS Shared worker of the cached script -PASS Shared worker of the fallbacked script -PASS Shared worker of the not-in-cache script -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index d53faa0..9dcae25 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1089,6 +1089,16 @@ getter statusCode getter violatedDirective method constructor +interface ServiceWorker : EventTarget + attribute @@toStringTag + getter onerror + getter onstatechange + getter scriptURL + getter state + method constructor + method postMessage + setter onerror + setter onstatechange interface ServiceWorkerGlobalScope : WorkerGlobalScope attribute @@toStringTag method constructor
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 1c65ce7..08a01700 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1175,6 +1175,10 @@ [Worker] attribute @@toStringTag [Worker] getter content [Worker] method constructor +[Worker] interface ScreenManager +[Worker] attribute @@toStringTag +[Worker] method constructor +[Worker] method requestDisplays [Worker] interface SecurityPolicyViolationEvent : Event [Worker] attribute @@toStringTag [Worker] getter blockedURI @@ -3742,6 +3746,7 @@ [Worker] getter permissions [Worker] getter platform [Worker] getter product +[Worker] getter screen [Worker] getter serial [Worker] getter storage [Worker] getter usb
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 83da79c..2694c60c 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5114,6 +5114,7 @@ getter product getter productSub getter scheduling + getter screen getter serial getter serviceWorker getter sms @@ -7457,6 +7458,10 @@ getter pixelDepth getter width method constructor +interface ScreenManager + attribute @@toStringTag + method constructor + method requestDisplays interface ScreenOrientation : EventTarget attribute @@toStringTag getter angle
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index d71921c..f955701 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1153,6 +1153,10 @@ [Worker] method formData [Worker] method json [Worker] method text +[Worker] interface ScreenManager +[Worker] attribute @@toStringTag +[Worker] method constructor +[Worker] method requestDisplays [Worker] interface SecurityPolicyViolationEvent : Event [Worker] attribute @@toStringTag [Worker] getter blockedURI @@ -3591,6 +3595,7 @@ [Worker] getter permissions [Worker] getter platform [Worker] getter product +[Worker] getter screen [Worker] getter serial [Worker] getter storage [Worker] getter usb
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-focus.html b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-focus.html index 3aa1658..3209160 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-focus.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-focus.html
@@ -6,7 +6,7 @@ </head> <body> -<div id="locked" rendersubtree="invisible-activatable"> +<div id="locked" rendersubtree="invisible activatable"> foo <div id="child" tabindex="0"> bar
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-press.html b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-press.html index 136d330..c634314c 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-press.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-press.html
@@ -6,7 +6,7 @@ </head> <body> -<div id="locked" rendersubtree="invisible-activatable"> +<div id="locked" rendersubtree="invisible activatable"> foo <div id="child" tabindex="0"> bar
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-scroll.html b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-scroll.html index 5b0b4d0..0e47ee88 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-scroll.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/activation/accessibility-activatable-scroll.html
@@ -6,7 +6,7 @@ </head> <body> -<div id="locked" rendersubtree="invisible-activatable"> +<div id="locked" rendersubtree="invisible activatable"> foo <div id="child" tabindex="0"> bar
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/attribute/values.html b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/attribute/values.html index 65854201..a22bd69e 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/attribute/values.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/attribute/values.html
@@ -7,79 +7,29 @@ <script> test(() => { const element = document.createElement("div"); - element.setAttribute("rendersubtree", "visible"); - assert_equals(element.getAttribute("rendersubtree"), "visible"); - assert_equals(element.renderSubtree, "visible"); element.setAttribute("rendersubtree", "invisible"); assert_equals(element.getAttribute("rendersubtree"), "invisible"); assert_equals(element.renderSubtree, "invisible"); - element.setAttribute("rendersubtree", "invisible-activatable"); - assert_equals(element.getAttribute("rendersubtree"), "invisible-activatable"); - assert_equals(element.renderSubtree, "invisible-activatable"); -}, "Valid values on the attribute are saved and reflected as is"); + element.setAttribute("rendersubtree", "invisible activatable"); + assert_equals(element.getAttribute("rendersubtree"), "invisible activatable"); + assert_equals(element.renderSubtree, "invisible activatable"); -test(() => { - const element = document.createElement("div"); - element.setAttribute("rendersubtree", "not-visible"); - assert_equals(element.renderSubtree, "visible"); - - element.setAttribute("rendersubtree", ""); - assert_equals(element.renderSubtree, "visible"); - - element.setAttribute("rendersubtree", "invisibleactivatable"); - assert_equals(element.renderSubtree, "visible"); -}, "Invalid values on the attribute are reflected as visible on the renderSubtree property"); - -test(() => { - const element = document.createElement("div"); element.setAttribute("rendersubtree", "not-visible"); assert_equals(element.getAttribute("rendersubtree"), "not-visible"); + assert_equals(element.renderSubtree, "not-visible"); element.setAttribute("rendersubtree", ""); assert_equals(element.getAttribute("rendersubtree"), ""); + assert_equals(element.renderSubtree, ""); - element.setAttribute("rendersubtree", "invisibleactivatable"); - assert_equals(element.getAttribute("rendersubtree"), "invisibleactivatable"); -}, "Invalid values on the attribute are saved as-is in the rendersubtree attribute"); + element.setAttribute("rendersubtree", "foo bar"); + assert_equals(element.getAttribute("rendersubtree"), "foo bar"); + assert_equals(element.renderSubtree, "foo bar"); -test(() => { - const element = document.createElement("div"); - element.renderSubtree = "visible"; + element.setAttribute("rendersubtree", "visible"); assert_equals(element.getAttribute("rendersubtree"), "visible"); assert_equals(element.renderSubtree, "visible"); - - element.renderSubtree = "invisible"; - assert_equals(element.getAttribute("rendersubtree"), "invisible"); - assert_equals(element.renderSubtree, "invisible"); - - element.renderSubtree = "invisible-activatable"; - assert_equals(element.getAttribute("rendersubtree"), "invisible-activatable"); - assert_equals(element.renderSubtree, "invisible-activatable"); -}, "Valid values on the property are saved and reflected as is"); - -test(() => { - const element = document.createElement("div"); - element.renderSubtree = "not-visible"; - assert_equals(element.renderSubtree, "visible"); - - element.renderSubtree = ""; - assert_equals(element.renderSubtree, "visible"); - - element.renderSubtree = "invisibleactivatable"; - assert_equals(element.renderSubtree, "visible"); -}, "Invalid values on the property are reflected as visible on the renderSubtree property"); - -test(() => { - const element = document.createElement("div"); - element.renderSubtree = "not-visible"; - assert_equals(element.getAttribute("rendersubtree"), "not-visible"); - - element.renderSubtree = ""; - assert_equals(element.getAttribute("rendersubtree"), ""); - - element.renderSubtree = "invisibleactivatable"; - assert_equals(element.getAttribute("rendersubtree"), "invisibleactivatable"); -}, "Invalid values on the property are saved as-is in the rendersubtree attribute"); +}, "Values on the attribute are saved and reflected as is"); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/resources/utils.js b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/resources/utils.js index 00e1144..d223c1a 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/resources/utils.js +++ b/third_party/blink/web_tests/wpt_internal/display-lock/rendersubtree/resources/utils.js
@@ -4,7 +4,7 @@ } function setInvisibleActivatable(element) { - return setRenderSubtree(element, "invisible-activatable"); + return setRenderSubtree(element, "invisible activatable"); } function setVisible(element) {
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 70f0caa..cf423d6 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: cd92fba233d3cc28909c3791710a747c818de244 +Revision: 3a6c6012ba2b9ed662872ccaf7d276d56240943b License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index 46c3424..acb4a39 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -33,7 +33,7 @@ '8048ece6c16c91acfe0d36d1d3cc0890ab6e945c', 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - '5889767521eed1483b5858b12c54893f21d72fd0', + '6ad086b2b6ed3b3169226ee9f311eb2332f332c2', 'crashpad/third_party/libfuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' + 'fda403cf93ecb8792cb1d061564d89a6553ca020',
diff --git a/third_party/crashpad/crashpad/build/BUILDCONFIG.gn b/third_party/crashpad/crashpad/build/BUILDCONFIG.gn index bc53108..95dc277 100644 --- a/third_party/crashpad/crashpad/build/BUILDCONFIG.gn +++ b/third_party/crashpad/crashpad/build/BUILDCONFIG.gn
@@ -55,7 +55,6 @@ _default_configs = [ "//third_party/mini_chromium/mini_chromium/build:default", "//third_party/mini_chromium/mini_chromium/build:Wexit_time_destructors", - "//third_party/mini_chromium/mini_chromium/build:Wimplicit_fallthrough", ] if (crashpad_use_libfuzzer) {
diff --git a/third_party/crashpad/crashpad/client/crashpad_client.h b/third_party/crashpad/crashpad/client/crashpad_client.h index 36c9d1f8..56d738b 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client.h +++ b/third_party/crashpad/crashpad/client/crashpad_client.h
@@ -588,16 +588,6 @@ static void UseSystemDefaultHandler(); #endif -#if defined(OS_CHROMEOS) - //! \brief Sets a timestamp on the signal handler to be passed on to - //! crashpad_handler and then eventually Chrome OS's crash_reporter. - //! - //! \note This method is used by clients that use `StartHandler()` to start - //! a handler and not by clients that use any other handler starting - //! methods. - static void SetCrashLoopBefore(uint64_t crash_loop_before_time); -#endif - private: #if defined(OS_MACOSX) base::mac::ScopedMachSendRight exception_port_;
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc index eb210a2..2e2ec30 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
@@ -301,20 +301,11 @@ ExceptionHandlerProtocol::ClientInformation info = {}; info.exception_information_address = FromPointerCast<VMAddress>(&GetExceptionInfo()); -#if defined(OS_CHROMEOS) - info.crash_loop_before_time = crash_loop_before_time_; -#endif ExceptionHandlerClient client(sock_to_handler_.get(), true); client.RequestCrashDump(info); } -#if defined(OS_CHROMEOS) - void SetCrashLoopBefore(uint64_t crash_loop_before_time) { - crash_loop_before_time_ = crash_loop_before_time; - } -#endif - private: RequestCrashDumpHandler() = default; @@ -323,14 +314,6 @@ ScopedFileHandle sock_to_handler_; pid_t handler_pid_ = -1; -#if defined(OS_CHROMEOS) - // An optional UNIX timestamp passed to us from Chrome. - // This will pass to crashpad_handler and then to Chrome OS crash_reporter. - // This should really be a time_t, but it's basically an opaque value (we - // don't anything with it except pass it along). - uint64_t crash_loop_before_time_ = 0; -#endif - DISALLOW_COPY_AND_ASSIGN(RequestCrashDumpHandler); }; @@ -543,12 +526,4 @@ SignalHandler::Get()->SetFirstChanceHandler(handler); } -#if defined(OS_CHROMEOS) -// static -void CrashpadClient::SetCrashLoopBefore(uint64_t crash_loop_before_time) { - auto request_crash_dump_handler = RequestCrashDumpHandler::Get(); - request_crash_dump_handler->SetCrashLoopBefore(crash_loop_before_time); -} -#endif - } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/compat/BUILD.gn b/third_party/crashpad/crashpad/compat/BUILD.gn index 62ee528..7a33d7ca 100644 --- a/third_party/crashpad/crashpad/compat/BUILD.gn +++ b/third_party/crashpad/crashpad/compat/BUILD.gn
@@ -79,8 +79,6 @@ if (crashpad_is_linux || crashpad_is_android) { sources += [ "linux/signal.h", - "linux/sys/mman.cc", - "linux/sys/mman.h", "linux/sys/ptrace.h", "linux/sys/user.h", ]
diff --git a/third_party/crashpad/crashpad/compat/linux/sys/mman.cc b/third_party/crashpad/crashpad/compat/linux/sys/mman.cc deleted file mode 100644 index 12aaa2c7..0000000 --- a/third_party/crashpad/crashpad/compat/linux/sys/mman.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2019 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <sys/mman.h> - -#include <dlfcn.h> -#include <sys/syscall.h> -#include <unistd.h> - -#if defined(__GLIBC__) - -extern "C" { - -int memfd_create(const char* name, unsigned int flags) { - using MemfdCreateType = int (*)(const char*, int); - static const MemfdCreateType next_memfd_create = - reinterpret_cast<MemfdCreateType>(dlsym(RTLD_NEXT, "memfd_create")); - return next_memfd_create ? next_memfd_create(name, flags) - : syscall(SYS_memfd_create, name, flags); -} - -} // extern "C" - -#endif // __GLIBC__
diff --git a/third_party/crashpad/crashpad/compat/linux/sys/mman.h b/third_party/crashpad/crashpad/compat/linux/sys/mman.h deleted file mode 100644 index 61c55d7..0000000 --- a/third_party/crashpad/crashpad/compat/linux/sys/mman.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2019 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_COMPAT_LINUX_SYS_MMAN_H_ -#define CRASHPAD_COMPAT_LINUX_SYS_MMAN_H_ - -#include_next <sys/mman.h> - -#include <features.h> - -// There's no memfd_create() wrapper before glibc 2.27. -// This can't select for glibc < 2.27 because linux-chromeos-rel bots build this -// code using a sysroot which has glibc 2.27, but then run it on Ubuntu 16.04, -// which doesn't. -#if defined(__GLIBC__) - -#ifdef __cplusplus -extern "C" { -#endif - -int memfd_create(const char* name, unsigned int flags); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // __GLIBC__ - -#endif // CRASHPAD_COMPAT_LINUX_SYS_MMAN_H_
diff --git a/third_party/crashpad/crashpad/handler/BUILD.gn b/third_party/crashpad/crashpad/handler/BUILD.gn index 550f686a..b841b0c 100644 --- a/third_party/crashpad/crashpad/handler/BUILD.gn +++ b/third_party/crashpad/crashpad/handler/BUILD.gn
@@ -42,8 +42,6 @@ if (crashpad_is_linux || crashpad_is_android) { set_sources_assignment_filter([]) sources += [ - "linux/capture_snapshot.cc", - "linux/capture_snapshot.h", "linux/crash_report_exception_handler.cc", "linux/crash_report_exception_handler.h", "linux/exception_handler_server.cc", @@ -51,13 +49,6 @@ ] } - if (crashpad_is_linux) { - sources += [ - "linux/cros_crash_report_exception_handler.cc", - "linux/cros_crash_report_exception_handler.h", - ] - } - if (crashpad_is_win) { sources += [ "win/crash_report_exception_handler.cc",
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc index 7b69e84..05a2e7b 100644 --- a/third_party/crashpad/crashpad/handler/handler_main.cc +++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -56,10 +56,6 @@ #include "util/string/split_string.h" #include "util/synchronization/semaphore.h" -#if defined(OS_CHROMEOS) -#include "handler/linux/cros_crash_report_exception_handler.h" -#endif - #if defined(OS_LINUX) || defined(OS_ANDROID) #include <unistd.h> @@ -161,9 +157,6 @@ #endif // OS_LINUX || OS_ANDROID " --url=URL send crash reports to this Breakpad server URL,\n" " only if uploads are enabled for the database\n" -#if defined(OS_CHROMEOS) -" --use-cros-crash-reporter\n" -#endif // OS_CHROMEOS " --help display this help and exit\n" " --version output version information and exit\n", me.value().c_str()); @@ -195,9 +188,6 @@ bool periodic_tasks; bool rate_limit; bool upload_gzip; -#if defined(OS_CHROMEOS) - bool use_cros_crash_reporter; -#endif // OS_CHROMEOS }; // Splits |key_value| on '=' and inserts the resulting key and value into |map|. @@ -519,12 +509,6 @@ int HandlerMain(int argc, char* argv[], const UserStreamDataSources* user_stream_sources) { -#if defined(OS_CHROMEOS) - if (freopen("/var/log/chrome/chrome", "a", stderr) == nullptr) { - PLOG(ERROR) << "Failed to redirect stderr to /var/log/chrome/chrome"; - } -#endif - InstallCrashHandler(); CallMetricsRecordNormalExit metrics_record_normal_exit; @@ -569,9 +553,6 @@ kOptionTraceParentWithException, #endif kOptionURL, -#if defined(OS_CHROMEOS) - kOptionUseCrosCrashReporter, -#endif // OS_CHROMEOS // Standard options. kOptionHelp = -2, @@ -637,12 +618,6 @@ kOptionTraceParentWithException}, #endif // OS_LINUX || OS_ANDROID {"url", required_argument, nullptr, kOptionURL}, -#if defined(OS_CHROEMOS) - {"use-cros-crash-reporter", - no_argument, - nullptr, - kOptionUseCrosCrashReporter}, -#endif // OS_CHROMEOS {"help", no_argument, nullptr, kOptionHelp}, {"version", no_argument, nullptr, kOptionVersion}, {nullptr, 0, nullptr, 0}, @@ -784,12 +759,6 @@ options.url = optarg; break; } -#if defined(OS_CHROMEOS) - case kOptionUseCrosCrashReporter: { - options.use_cros_crash_reporter = true; - break; - } -#endif // OS_CHROMEOS case kOptionHelp: { Usage(me); MetricsRecordExit(Metrics::LifetimeMilestone::kExitedEarly); @@ -915,27 +884,7 @@ upload_thread.Get()->Start(); } -#if defined(OS_LINUX) || defined(OS_ANDROID) - std::unique_ptr<ExceptionHandlerServer::Delegate> exception_handler; -#else - std::unique_ptr<CrashReportExceptionHandler> exception_handler; -#endif - -#if defined(OS_CHROMEOS) - if (options.use_cros_crash_reporter) { - exception_handler = std::make_unique<CrosCrashReportExceptionHandler>( - database.get(), - &options.annotations, - user_stream_sources); - } else { - exception_handler = std::make_unique<CrashReportExceptionHandler>( - database.get(), - static_cast<CrashReportUploadThread*>(upload_thread.Get()), - &options.annotations, - user_stream_sources); - } -#else - exception_handler = std::make_unique<CrashReportExceptionHandler>( + CrashReportExceptionHandler exception_handler( database.get(), static_cast<CrashReportUploadThread*>(upload_thread.Get()), &options.annotations, @@ -944,17 +893,15 @@ nullptr, #endif user_stream_sources); -#endif // OS_CHROMEOS -#if defined(OS_LINUX) || defined(OS_ANDROID) + #if defined(OS_LINUX) || defined(OS_ANDROID) if (options.exception_information_address) { ExceptionHandlerProtocol::ClientInformation info; info.exception_information_address = options.exception_information_address; info.sanitization_information_address = options.sanitization_information_address; - return exception_handler->HandleException(getppid(), geteuid(), info) - ? EXIT_SUCCESS - : ExitFailure(); + return exception_handler.HandleException(getppid(), info) ? EXIT_SUCCESS + : ExitFailure(); } #endif // OS_LINUX || OS_ANDROID @@ -1058,7 +1005,7 @@ #if defined(OS_WIN) if (options.initial_client_data.IsValid()) { exception_handler_server.InitializeWithInheritedDataForInitialClient( - options.initial_client_data, exception_handler.get()); + options.initial_client_data, &exception_handler); } #elif defined(OS_LINUX) || defined(OS_ANDROID) if (options.initial_client_fd == kInvalidFileHandle || @@ -1069,7 +1016,7 @@ } #endif // OS_WIN - exception_handler_server.Run(exception_handler.get()); + exception_handler_server.Run(&exception_handler); return EXIT_SUCCESS; }
diff --git a/third_party/crashpad/crashpad/handler/linux/capture_snapshot.cc b/third_party/crashpad/crashpad/handler/linux/capture_snapshot.cc deleted file mode 100644 index 005402956..0000000 --- a/third_party/crashpad/crashpad/handler/linux/capture_snapshot.cc +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright 2019 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "handler/linux/capture_snapshot.h" - -#include <utility> - -#include "snapshot/crashpad_info_client_options.h" -#include "snapshot/sanitized/sanitization_information.h" -#include "util/misc/metrics.h" -#include "util/misc/tri_state.h" - -namespace crashpad { - -bool CaptureSnapshot( - PtraceConnection* connection, - const ExceptionHandlerProtocol::ClientInformation& info, - const std::map<std::string, std::string>& process_annotations, - uid_t client_uid, - VMAddress requesting_thread_stack_address, - pid_t* requesting_thread_id, - std::unique_ptr<ProcessSnapshotLinux>* snapshot, - std::unique_ptr<ProcessSnapshotSanitized>* sanitized_snapshot) { - std::unique_ptr<ProcessSnapshotLinux> process_snapshot( - new ProcessSnapshotLinux()); - if (!process_snapshot->Initialize(connection)) { - Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed); - return false; - } - - pid_t local_requesting_thread_id = -1; - if (requesting_thread_stack_address) { - local_requesting_thread_id = process_snapshot->FindThreadWithStackAddress( - requesting_thread_stack_address); - } - - if (requesting_thread_id) { - *requesting_thread_id = local_requesting_thread_id; - } - - if (!process_snapshot->InitializeException(info.exception_information_address, - local_requesting_thread_id)) { - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kExceptionInitializationFailed); - return false; - } - - Metrics::ExceptionCode(process_snapshot->Exception()->Exception()); - - CrashpadInfoClientOptions client_options; - process_snapshot->GetCrashpadOptions(&client_options); - if (client_options.crashpad_handler_behavior == TriState::kDisabled) { - return false; - } - - for (auto& p : process_annotations) { - process_snapshot->AddAnnotation(p.first, p.second); - } - - if (info.sanitization_information_address) { - SanitizationInformation sanitization_info; - ProcessMemoryRange range; - if (!range.Initialize(connection->Memory(), connection->Is64Bit()) || - !range.Read(info.sanitization_information_address, - sizeof(sanitization_info), - &sanitization_info)) { - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kSanitizationInitializationFailed); - return false; - } - - auto annotations_whitelist = std::make_unique<std::vector<std::string>>(); - auto memory_range_whitelist = - std::make_unique<std::vector<std::pair<VMAddress, VMAddress>>>(); - if (!ReadAnnotationsWhitelist( - range, - sanitization_info.annotations_whitelist_address, - annotations_whitelist.get()) || - !ReadMemoryRangeWhitelist( - range, - sanitization_info.memory_range_whitelist_address, - memory_range_whitelist.get())) { - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kSanitizationInitializationFailed); - return false; - } - - std::unique_ptr<ProcessSnapshotSanitized> sanitized( - new ProcessSnapshotSanitized()); - if (!sanitized->Initialize(process_snapshot.get(), - sanitization_info.annotations_whitelist_address - ? std::move(annotations_whitelist) - : nullptr, - std::move(memory_range_whitelist), - sanitization_info.target_module_address, - sanitization_info.sanitize_stacks)) { - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kSkippedDueToSanitization); - return false; - } - *sanitized_snapshot = std::move(sanitized); - } - - *snapshot = std::move(process_snapshot); - return true; -} - -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/handler/linux/capture_snapshot.h b/third_party/crashpad/crashpad/handler/linux/capture_snapshot.h deleted file mode 100644 index 78886dc5..0000000 --- a/third_party/crashpad/crashpad/handler/linux/capture_snapshot.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2019 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_HANDLER_LINUX_CAPTURE_SNAPSHOT_H_ -#define CRASHPAD_HANDLER_LINUX_CAPTURE_SNAPSHOT_H_ - -#include <sys/types.h> - -#include <map> -#include <memory> -#include <string> - -#include "snapshot/linux/process_snapshot_linux.h" -#include "snapshot/sanitized/process_snapshot_sanitized.h" -#include "util/linux/exception_handler_protocol.h" -#include "util/linux/ptrace_connection.h" -#include "util/misc/address_types.h" - -namespace crashpad { - -//! \brief Captures a snapshot of a client over \a connection. -//! -//! \param[in] connection A PtraceConnection to the client to snapshot. -//! \param[in] info Information about the client configuring the snapshot. -//! \param[in] process_annotations A map of annotations to insert as -//! process-level annotations into the snapshot. -//! \param[in] client_uid The client's user ID. -//! \param[in] requesting_thread_stack_address An address on the stack of the -//! thread requesting the snapshot. If \a info includes an exception -//! address, the exception will be assigned to the thread whose stack -//! address range contains this address. If 0, \a requesting_thread_id will -//! be -1. -//! \param[out] requesting_thread_id The thread ID of the thread corresponding -//! to \a requesting_thread_stack_address. Set to -1 if the thread ID could -//! not be determined. Optional. -//! \param[out] process_snapshot A snapshot of the client process, valid if this -//! function returns `true`. -//! \param[out] sanitized_snapshot A sanitized snapshot of the client process, -//! valid if this function returns `true` and sanitization was requested in -//! \a info. -//! \return `true` if \a process_snapshot was successfully created. A message -//! will be logged on failure, but not if the snapshot was skipped because -//! handling was disabled by CrashpadInfoClientOptions. -bool CaptureSnapshot( - PtraceConnection* connection, - const ExceptionHandlerProtocol::ClientInformation& info, - const std::map<std::string, std::string>& process_annotations, - uid_t client_uid, - VMAddress requesting_thread_stack_address, - pid_t* requesting_thread_id, - std::unique_ptr<ProcessSnapshotLinux>* process_snapshot, - std::unique_ptr<ProcessSnapshotSanitized>* sanitized_snapshot); - -} // namespace crashpad - -#endif // CRASHPAD_HANDLER_LINUX_CAPTURE_SNAPSHOT_H_
diff --git a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc index 9b4f201..875afec 100644 --- a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc +++ b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc
@@ -14,19 +14,19 @@ #include "handler/linux/crash_report_exception_handler.h" -#include <memory> -#include <utility> +#include <vector> #include "base/logging.h" #include "client/settings.h" -#include "handler/linux/capture_snapshot.h" #include "minidump/minidump_file_writer.h" +#include "snapshot/crashpad_info_client_options.h" #include "snapshot/linux/process_snapshot_linux.h" #include "snapshot/sanitized/process_snapshot_sanitized.h" +#include "snapshot/sanitized/sanitization_information.h" #include "util/linux/direct_ptrace_connection.h" #include "util/linux/ptrace_client.h" -#include "util/misc/implicit_cast.h" #include "util/misc/metrics.h" +#include "util/misc/tri_state.h" #include "util/misc/uuid.h" namespace crashpad { @@ -45,7 +45,6 @@ bool CrashReportExceptionHandler::HandleException( pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, VMAddress requesting_thread_stack_address, pid_t* requesting_thread_id, @@ -61,7 +60,6 @@ return HandleExceptionWithConnection(&connection, info, - client_uid, requesting_thread_stack_address, requesting_thread_id, local_report_id); @@ -69,7 +67,6 @@ bool CrashReportExceptionHandler::HandleExceptionWithBroker( pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, int broker_sock, UUID* local_report_id) { @@ -83,83 +80,142 @@ } return HandleExceptionWithConnection( - &client, info, client_uid, 0, nullptr, local_report_id); + &client, info, 0, nullptr, local_report_id); } bool CrashReportExceptionHandler::HandleExceptionWithConnection( PtraceConnection* connection, const ExceptionHandlerProtocol::ClientInformation& info, - uid_t client_uid, VMAddress requesting_thread_stack_address, pid_t* requesting_thread_id, UUID* local_report_id) { - std::unique_ptr<ProcessSnapshotLinux> process_snapshot; - std::unique_ptr<ProcessSnapshotSanitized> sanitized_snapshot; - if (!CaptureSnapshot(connection, - info, - *process_annotations_, - client_uid, - requesting_thread_stack_address, - requesting_thread_id, - &process_snapshot, - &sanitized_snapshot)) { + ProcessSnapshotLinux process_snapshot; + if (!process_snapshot.Initialize(connection)) { + Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed); return false; } - UUID client_id; - Settings* const settings = database_->GetSettings(); - if (settings) { - // If GetSettings() or GetClientID() fails, something else will log a - // message and client_id will be left at its default value, all zeroes, - // which is appropriate. - settings->GetClientID(&client_id); + pid_t local_requesting_thread_id = -1; + if (requesting_thread_stack_address) { + local_requesting_thread_id = process_snapshot.FindThreadWithStackAddress( + requesting_thread_stack_address); } - process_snapshot->SetClientID(client_id); - std::unique_ptr<CrashReportDatabase::NewReport> new_report; - CrashReportDatabase::OperationStatus database_status = - database_->PrepareNewCrashReport(&new_report); - if (database_status != CrashReportDatabase::kNoError) { - LOG(ERROR) << "PrepareNewCrashReport failed"; + if (requesting_thread_id) { + *requesting_thread_id = local_requesting_thread_id; + } + + if (!process_snapshot.InitializeException(info.exception_information_address, + local_requesting_thread_id)) { Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kPrepareNewCrashReportFailed); + Metrics::CaptureResult::kExceptionInitializationFailed); return false; } - process_snapshot->SetReportID(new_report->ReportID()); + Metrics::ExceptionCode(process_snapshot.Exception()->Exception()); - ProcessSnapshot* snapshot = - sanitized_snapshot - ? implicit_cast<ProcessSnapshot*>(sanitized_snapshot.get()) - : implicit_cast<ProcessSnapshot*>(process_snapshot.get()); + CrashpadInfoClientOptions client_options; + process_snapshot.GetCrashpadOptions(&client_options); + if (client_options.crashpad_handler_behavior != TriState::kDisabled) { + UUID client_id; + Settings* const settings = database_->GetSettings(); + if (settings) { + // If GetSettings() or GetClientID() fails, something else will log a + // message and client_id will be left at its default value, all zeroes, + // which is appropriate. + settings->GetClientID(&client_id); + } - MinidumpFileWriter minidump; - minidump.InitializeFromSnapshot(snapshot); - AddUserExtensionStreams(user_stream_data_sources_, snapshot, &minidump); + process_snapshot.SetClientID(client_id); + for (auto& p : *process_annotations_) { + process_snapshot.AddAnnotation(p.first, p.second); + } - if (!minidump.WriteEverything(new_report->Writer())) { - LOG(ERROR) << "WriteEverything failed"; - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kMinidumpWriteFailed); - return false; - } + std::unique_ptr<CrashReportDatabase::NewReport> new_report; + CrashReportDatabase::OperationStatus database_status = + database_->PrepareNewCrashReport(&new_report); + if (database_status != CrashReportDatabase::kNoError) { + LOG(ERROR) << "PrepareNewCrashReport failed"; + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kPrepareNewCrashReportFailed); + return false; + } - UUID uuid; - database_status = - database_->FinishedWritingCrashReport(std::move(new_report), &uuid); - if (database_status != CrashReportDatabase::kNoError) { - LOG(ERROR) << "FinishedWritingCrashReport failed"; - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kFinishedWritingCrashReportFailed); - return false; - } + process_snapshot.SetReportID(new_report->ReportID()); - if (upload_thread_) { - upload_thread_->ReportPending(uuid); - } + ProcessSnapshot* snapshot = nullptr; + ProcessSnapshotSanitized sanitized; + std::vector<std::string> annotations_whitelist; + std::vector<std::pair<VMAddress, VMAddress>> memory_range_whitelist; + if (info.sanitization_information_address) { + SanitizationInformation sanitization_info; + ProcessMemoryRange range; + if (!range.Initialize(connection->Memory(), connection->Is64Bit()) || + !range.Read(info.sanitization_information_address, + sizeof(sanitization_info), + &sanitization_info)) { + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kSanitizationInitializationFailed); + return false; + } - if (local_report_id != nullptr) { - *local_report_id = uuid; + if (!ReadAnnotationsWhitelist( + range, + sanitization_info.annotations_whitelist_address, + &annotations_whitelist) || + !ReadMemoryRangeWhitelist( + range, + sanitization_info.memory_range_whitelist_address, + &memory_range_whitelist)) { + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kSanitizationInitializationFailed); + return false; + } + + if (!sanitized.Initialize(&process_snapshot, + sanitization_info.annotations_whitelist_address + ? &annotations_whitelist + : nullptr, + &memory_range_whitelist, + sanitization_info.target_module_address, + sanitization_info.sanitize_stacks)) { + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kSkippedDueToSanitization); + return true; + } + + snapshot = &sanitized; + } else { + snapshot = &process_snapshot; + } + + MinidumpFileWriter minidump; + minidump.InitializeFromSnapshot(snapshot); + AddUserExtensionStreams(user_stream_data_sources_, snapshot, &minidump); + + if (!minidump.WriteEverything(new_report->Writer())) { + LOG(ERROR) << "WriteEverything failed"; + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kMinidumpWriteFailed); + return false; + } + + UUID uuid; + database_status = + database_->FinishedWritingCrashReport(std::move(new_report), &uuid); + if (database_status != CrashReportDatabase::kNoError) { + LOG(ERROR) << "FinishedWritingCrashReport failed"; + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kFinishedWritingCrashReportFailed); + return false; + } + if (local_report_id != nullptr) { + *local_report_id = uuid; + } + + if (upload_thread_) { + upload_thread_->ReportPending(uuid); + } } Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess);
diff --git a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h index 522a77d..dba8b63 100644 --- a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h +++ b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h
@@ -60,12 +60,11 @@ const std::map<std::string, std::string>* process_annotations, const UserStreamDataSources* user_stream_data_sources); - ~CrashReportExceptionHandler() override; + ~CrashReportExceptionHandler(); // ExceptionHandlerServer::Delegate: bool HandleException(pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, VMAddress requesting_thread_stack_address = 0, pid_t* requesting_thread_id = nullptr, @@ -73,7 +72,6 @@ bool HandleExceptionWithBroker( pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, int broker_sock, UUID* local_report_id = nullptr) override; @@ -82,7 +80,6 @@ bool HandleExceptionWithConnection( PtraceConnection* connection, const ExceptionHandlerProtocol::ClientInformation& info, - uid_t client_uid, VMAddress requesting_thread_stack_address, pid_t* requesting_thread_id, UUID* local_report_id = nullptr);
diff --git a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc deleted file mode 100644 index a24b17f6..0000000 --- a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc +++ /dev/null
@@ -1,278 +0,0 @@ -// Copyright 2019 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "handler/linux/cros_crash_report_exception_handler.h" - -#include <vector> - -#include "base/logging.h" -#include "client/settings.h" -#include "handler/linux/capture_snapshot.h" -#include "handler/minidump_to_upload_parameters.h" -#include "minidump/minidump_file_writer.h" -#include "snapshot/linux/process_snapshot_linux.h" -#include "snapshot/minidump/process_snapshot_minidump.h" -#include "snapshot/sanitized/process_snapshot_sanitized.h" -#include "util/file/file_writer.h" -#include "util/linux/direct_ptrace_connection.h" -#include "util/linux/ptrace_client.h" -#include "util/misc/metrics.h" -#include "util/misc/uuid.h" -#include "util/posix/double_fork_and_exec.h" - -namespace crashpad { - -namespace { - -// Returns the process name for a pid. -const std::string GetProcessNameFromPid(pid_t pid) { - // Symlink to process binary is at /proc/###/exe. - std::string link_path = "/proc/" + std::to_string(pid) + "/exe"; - - constexpr int kMaxSize = 4096; - std::unique_ptr<char[]> buf(new char[kMaxSize]); - ssize_t size = readlink(link_path.c_str(), buf.get(), kMaxSize); - std::string result; - if (size < 0) { - PLOG(ERROR) << "Failed to readlink " << link_path; - } else { - result.assign(buf.get(), size); - size_t last_slash_pos = result.rfind('/'); - if (last_slash_pos != std::string::npos) { - result = result.substr(last_slash_pos + 1); - } - } - return result; -} - -bool WriteAnnotationsAndMinidump( - const std::map<std::string, std::string>& parameters, - MinidumpFileWriter& minidump, - FileWriter& file_writer) { - for (const auto& kv : parameters) { - if (kv.first.find(':') != std::string::npos) { - LOG(ERROR) << "Annotation key cannot have ':' in it " << kv.first; - return false; - } - if (!file_writer.Write(kv.first.c_str(), strlen(kv.first.c_str()))) { - return false; - } - if (!file_writer.Write(":", 1)) { - return false; - } - size_t value_size = strlen(kv.second.c_str()); - std::string value_size_str = std::to_string(value_size); - if (!file_writer.Write(value_size_str.c_str(), value_size_str.size())) { - return false; - } - if (!file_writer.Write(":", 1)) { - return false; - } - if (!file_writer.Write(kv.second.c_str(), strlen(kv.second.c_str()))) { - return false; - } - } - - static constexpr char kMinidumpName[] = - "upload_file_minidump\"; filename=\"dump\":"; - if (!file_writer.Write(kMinidumpName, sizeof(kMinidumpName) - 1)) { - return false; - } - crashpad::FileOffset dump_size_start_offset = file_writer.Seek(0, SEEK_CUR); - if (dump_size_start_offset < 0) { - LOG(ERROR) << "Failed to get minidump size start offset"; - return false; - } - static constexpr char kMinidumpLengthFilling[] = "00000000000000000000:"; - if (!file_writer.Write(kMinidumpLengthFilling, - sizeof(kMinidumpLengthFilling) - 1)) { - return false; - } - crashpad::FileOffset dump_start_offset = file_writer.Seek(0, SEEK_CUR); - if (dump_start_offset < 0) { - LOG(ERROR) << "Failed to get minidump start offset"; - return false; - } - if (!minidump.WriteEverything(&file_writer)) { - return false; - } - crashpad::FileOffset dump_end_offset = file_writer.Seek(0, SEEK_CUR); - if (dump_end_offset < 0) { - LOG(ERROR) << "Failed to get minidump end offset"; - return false; - } - - size_t dump_data_size = dump_end_offset - dump_start_offset; - std::string dump_data_size_str = std::to_string(dump_data_size); - file_writer.Seek(dump_size_start_offset + strlen(kMinidumpLengthFilling) - 1 - - dump_data_size_str.size(), - SEEK_SET); - if (!file_writer.Write(dump_data_size_str.c_str(), - dump_data_size_str.size())) { - return false; - } - return true; -} - -} // namespace - -CrosCrashReportExceptionHandler::CrosCrashReportExceptionHandler( - CrashReportDatabase* database, - const std::map<std::string, std::string>* process_annotations, - const UserStreamDataSources* user_stream_data_sources) - : database_(database), - process_annotations_(process_annotations), - user_stream_data_sources_(user_stream_data_sources) {} - -CrosCrashReportExceptionHandler::~CrosCrashReportExceptionHandler() = default; - -bool CrosCrashReportExceptionHandler::HandleException( - pid_t client_process_id, - uid_t client_uid, - const ExceptionHandlerProtocol::ClientInformation& info, - VMAddress requesting_thread_stack_address, - pid_t* requesting_thread_id, - UUID* local_report_id) { - Metrics::ExceptionEncountered(); - - DirectPtraceConnection connection; - if (!connection.Initialize(client_process_id)) { - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kDirectPtraceFailed); - return false; - } - - return HandleExceptionWithConnection(&connection, - info, - client_uid, - requesting_thread_stack_address, - requesting_thread_id, - local_report_id); -} - -bool CrosCrashReportExceptionHandler::HandleExceptionWithBroker( - pid_t client_process_id, - uid_t client_uid, - const ExceptionHandlerProtocol::ClientInformation& info, - int broker_sock, - UUID* local_report_id) { - Metrics::ExceptionEncountered(); - - PtraceClient client; - if (!client.Initialize(broker_sock, client_process_id)) { - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kBrokeredPtraceFailed); - return false; - } - - return HandleExceptionWithConnection( - &client, info, client_uid, 0, nullptr, local_report_id); -} - -bool CrosCrashReportExceptionHandler::HandleExceptionWithConnection( - PtraceConnection* connection, - const ExceptionHandlerProtocol::ClientInformation& info, - uid_t client_uid, - VMAddress requesting_thread_stack_address, - pid_t* requesting_thread_id, - UUID* local_report_id) { - std::unique_ptr<ProcessSnapshotLinux> process_snapshot; - std::unique_ptr<ProcessSnapshotSanitized> sanitized_snapshot; - if (!CaptureSnapshot(connection, - info, - *process_annotations_, - client_uid, - requesting_thread_stack_address, - requesting_thread_id, - &process_snapshot, - &sanitized_snapshot)) { - return false; - } - - UUID client_id; - Settings* const settings = database_->GetSettings(); - if (settings) { - // If GetSettings() or GetClientID() fails, something else will log a - // message and client_id will be left at its default value, all zeroes, - // which is appropriate. - settings->GetClientID(&client_id); - } - process_snapshot->SetClientID(client_id); - - UUID uuid; - uuid.InitializeWithNew(); - process_snapshot->SetReportID(uuid); - - ProcessSnapshot* snapshot = - sanitized_snapshot - ? implicit_cast<ProcessSnapshot*>(sanitized_snapshot.get()) - : implicit_cast<ProcessSnapshot*>(process_snapshot.get()); - - MinidumpFileWriter minidump; - minidump.InitializeFromSnapshot(snapshot); - AddUserExtensionStreams(user_stream_data_sources_, snapshot, &minidump); - - FileWriter file_writer; - if (!file_writer.OpenMemfd(base::FilePath("/tmp/minidump"))) { - Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kOpenMemfdFailed); - return false; - } - - std::map<std::string, std::string> parameters = - BreakpadHTTPFormParametersFromMinidump(snapshot); - // Used to differentiate between breakpad and crashpad while the switch is - // ramping up. - parameters.emplace("crash_library", "crashpad"); - - if (!WriteAnnotationsAndMinidump(parameters, minidump, file_writer)) { - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kMinidumpWriteFailed); - return false; - } - - // CrOS uses crash_reporter instead of Crashpad to report crashes. - // crash_reporter needs to know the pid and uid of the crashing process. - std::vector<std::string> argv({"/sbin/crash_reporter"}); - - argv.push_back("--chrome_memfd=" + std::to_string(file_writer.fd())); - argv.push_back("--pid=" + std::to_string(*requesting_thread_id)); - argv.push_back("--uid=" + std::to_string(client_uid)); - std::string process_name = GetProcessNameFromPid(*requesting_thread_id); - argv.push_back("--exe=" + (process_name.empty() ? "chrome" : process_name)); - - if (info.crash_loop_before_time != 0) { - argv.push_back("--crash_loop_before=" + - std::to_string(info.crash_loop_before_time)); - } - - if (!DoubleForkAndExec(argv, - nullptr /* envp */, - file_writer.fd() /* preserve_fd */, - false /* use_path */, - nullptr /* child_function */)) { - LOG(ERROR) << "DoubleForkAndExec failed"; - Metrics::ExceptionCaptureResult( - Metrics::CaptureResult::kFinishedWritingCrashReportFailed); - return false; - } - - if (local_report_id != nullptr) { - *local_report_id = uuid; - } - - Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess); - return true; -} - -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.h deleted file mode 100644 index f6ca445b..0000000 --- a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.h +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2019 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_HANDLER_LINUX_CROS_CRASH_REPORT_EXCEPTION_HANDLER_H_ -#define CRASHPAD_HANDLER_LINUX_CROS_CRASH_REPORT_EXCEPTION_HANDLER_H_ - -#include <map> -#include <string> - -#include "base/macros.h" -#include "client/crash_report_database.h" -#include "handler/linux/exception_handler_server.h" -#include "handler/user_stream_data_source.h" -#include "util/linux/exception_handler_protocol.h" -#include "util/linux/ptrace_connection.h" -#include "util/misc/address_types.h" -#include "util/misc/uuid.h" - -namespace crashpad { - -//! \brief An exception handler that writes crash reports to the ChromeOS -//! crash_reporter. -class CrosCrashReportExceptionHandler - : public ExceptionHandlerServer::Delegate { - public: - //! \brief Creates a new object that will pass reports to - //! `/sbin/crash_reporter`. - //! - //! \param[in] database The database that supplies settings for this client. - //! This object does not write its reports to this database. - //! \param[in] process_annotations A map of annotations to insert as - //! process-level annotations into each crash report that is written. Do - //! not confuse this with module-level annotations, which are under the - //! control of the crashing process, and are used to implement Chrome’s - //! “crash keys.” Process-level annotations are those that are beyond the - //! control of the crashing process, which must reliably be set even if - //! the process crashes before it’s able to establish its own annotations. - //! To interoperate with Breakpad servers, the recommended practice is to - //! specify values for the `"prod"` and `"ver"` keys as process - //! annotations. - //! \param[in] user_stream_data_sources Data sources to be used to extend - //! crash reports. For each crash report that is written, the data sources - //! are called in turn. These data sources may contribute additional - //! minidump streams. `nullptr` if not required. - CrosCrashReportExceptionHandler( - CrashReportDatabase* database, - const std::map<std::string, std::string>* process_annotations, - const UserStreamDataSources* user_stream_data_sources); - - ~CrosCrashReportExceptionHandler() override; - - // ExceptionHandlerServer::Delegate: - - bool HandleException(pid_t client_process_id, - uid_t client_uid, - const ExceptionHandlerProtocol::ClientInformation& info, - VMAddress requesting_thread_stack_address = 0, - pid_t* requesting_thread_id = nullptr, - UUID* local_report_id = nullptr) override; - - bool HandleExceptionWithBroker( - pid_t client_process_id, - uid_t client_uid, - const ExceptionHandlerProtocol::ClientInformation& info, - int broker_sock, - UUID* local_report_id = nullptr) override; - - private: - bool HandleExceptionWithConnection( - PtraceConnection* connection, - const ExceptionHandlerProtocol::ClientInformation& info, - uid_t client_uid, - VMAddress requesting_thread_stack_address, - pid_t* requesting_thread_id, - UUID* local_report_id = nullptr); - - CrashReportDatabase* database_; // weak - const std::map<std::string, std::string>* process_annotations_; // weak - const UserStreamDataSources* user_stream_data_sources_; // weak - - DISALLOW_COPY_AND_ASSIGN(CrosCrashReportExceptionHandler); -}; - -} // namespace crashpad - -#endif // CRASHPAD_HANDLER_LINUX_CROS_CRASH_REPORT_EXCEPTION_HANDLER_H_
diff --git a/third_party/crashpad/crashpad/handler/linux/exception_handler_server.cc b/third_party/crashpad/crashpad/handler/linux/exception_handler_server.cc index 7bb14f92..ef03696a 100644 --- a/third_party/crashpad/crashpad/handler/linux/exception_handler_server.cc +++ b/third_party/crashpad/crashpad/handler/linux/exception_handler_server.cc
@@ -448,7 +448,6 @@ bool multiple_clients) { pid_t client_process_id = creds.pid; pid_t requesting_thread_id = -1; - uid_t client_uid = creds.uid; switch ( strategy_decider_->ChooseStrategy(client_sock, multiple_clients, creds)) { @@ -470,7 +469,6 @@ case PtraceStrategyDecider::Strategy::kDirectPtrace: { delegate_->HandleException(client_process_id, - client_uid, client_info, requesting_thread_stack_address, &requesting_thread_id); @@ -484,7 +482,7 @@ case PtraceStrategyDecider::Strategy::kUseBroker: DCHECK(!multiple_clients); delegate_->HandleExceptionWithBroker( - client_process_id, client_uid, client_info, client_sock); + client_process_id, client_info, client_sock); break; }
diff --git a/third_party/crashpad/crashpad/handler/linux/exception_handler_server.h b/third_party/crashpad/crashpad/handler/linux/exception_handler_server.h index ac430a4c..b6251e1 100644 --- a/third_party/crashpad/crashpad/handler/linux/exception_handler_server.h +++ b/third_party/crashpad/crashpad/handler/linux/exception_handler_server.h
@@ -76,7 +76,6 @@ //! \brief Called on receipt of a crash dump request from a client. //! //! \param[in] client_process_id The process ID of the crashing client. - //! \param[in] client_uid The user ID of the crashing client. //! \param[in] info Information on the client. //! \param[in] requesting_thread_stack_address Any address within the stack //! range for the the thread that sent the crash dump request. Optional. @@ -89,7 +88,6 @@ //! \return `true` on success. `false` on failure with a message logged. virtual bool HandleException( pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, VMAddress requesting_thread_stack_address = 0, pid_t* requesting_thread_id = nullptr, @@ -99,7 +97,6 @@ //! crash that should be mediated by a PtraceBroker. //! //! \param[in] client_process_id The process ID of the crashing client. - //! \param[in] client_uid The uid of the crashing client. //! \param[in] info Information on the client. //! \param[in] broker_sock A socket connected to the PtraceBroker. //! \param[out] local_report_id The unique identifier for the report created @@ -107,12 +104,12 @@ //! \return `true` on success. `false` on failure with a message logged. virtual bool HandleExceptionWithBroker( pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, int broker_sock, UUID* local_report_id = nullptr) = 0; - virtual ~Delegate() {} + protected: + ~Delegate() {} }; ExceptionHandlerServer();
diff --git a/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc b/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc index 45f19965..ea10db35 100644 --- a/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc +++ b/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc
@@ -108,7 +108,6 @@ } bool HandleException(pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, VMAddress requesting_thread_stack_address, pid_t* requesting_thread_id = nullptr, @@ -142,7 +141,6 @@ bool HandleExceptionWithBroker( pid_t client_process_id, - uid_t client_uid, const ExceptionHandlerProtocol::ClientInformation& info, int broker_sock, UUID* local_report_id = nullptr) override {
diff --git a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h index b5a59e4..0b44de6 100644 --- a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h +++ b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h
@@ -30,8 +30,7 @@ //! \brief An exception handler that writes crash reports for exception messages //! to a CrashReportDatabase. -class CrashReportExceptionHandler final - : public UniversalMachExcServer::Interface { +class CrashReportExceptionHandler : public UniversalMachExcServer::Interface { public: //! \brief Creates a new object that will store crash reports in \a database. //!
diff --git a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h index 566f0472d..c2781de3 100644 --- a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h +++ b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h
@@ -31,8 +31,7 @@ //! \brief An exception handler that writes crash reports for exception messages //! to a CrashReportDatabase. -class CrashReportExceptionHandler final - : public ExceptionHandlerServer::Delegate { +class CrashReportExceptionHandler : public ExceptionHandlerServer::Delegate { public: //! \brief Creates a new object that will store crash reports in \a database. //!
diff --git a/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc index f29a6fa..7226545 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_file_writer.cc
@@ -232,7 +232,7 @@ // it as a valid minidump file. header_.Signature = MINIDUMP_SIGNATURE; - if (file_writer->Seek(start_offset, SEEK_SET) < 0) { + if (file_writer->Seek(start_offset, SEEK_SET) != 0) { return false; }
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc index c76a1f57..ecad29a 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc
@@ -105,6 +105,8 @@ process_memory_.reset(new ProcessMemoryFuchsia()); process_memory_->Initialize(*process_); + memory_map_.Initialize(*process_); + INITIALIZATION_STATE_SET_VALID(initialized_); return true; } @@ -131,16 +133,6 @@ return threads_; } -const MemoryMapFuchsia* ProcessReaderFuchsia::MemoryMap() { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - - if (!initialized_memory_map_) { - InitializeMemoryMap(); - } - - return memory_map_.get(); -} - void ProcessReaderFuchsia::InitializeModules() { DCHECK(!initialized_modules_); DCHECK(modules_.empty()); @@ -263,15 +255,13 @@ std::unique_ptr<ProcessMemoryRange> process_memory_range( new ProcessMemoryRange()); // TODO(scottmg): Could this be limited range? - if (process_memory_range->Initialize(process_memory_.get(), true)) { - process_memory_ranges_.push_back(std::move(process_memory_range)); + process_memory_range->Initialize(process_memory_.get(), true); + process_memory_ranges_.push_back(std::move(process_memory_range)); - if (reader->Initialize(*process_memory_ranges_.back(), base)) { - module.reader = reader.get(); - module_readers_.push_back(std::move(reader)); - modules_.push_back(module); - } - } + reader->Initialize(*process_memory_ranges_.back(), base); + module.reader = reader.get(); + module_readers_.push_back(std::move(reader)); + modules_.push_back(module); map = next; } @@ -321,13 +311,7 @@ } else { thread.general_registers = general_regs; - const MemoryMapFuchsia* memory_map = MemoryMap(); - if (memory_map) { - // Attempt to retrive stack regions if a memory map was retrieved. In - // particular, this may be null when operating on the current process - // where the memory map will not be able to be retrieved. - GetStackRegions(general_regs, *memory_map, &thread.stack_regions); - } + GetStackRegions(general_regs, memory_map_, &thread.stack_regions); } zx_thread_state_vector_regs_t vector_regs; @@ -345,15 +329,4 @@ } } -void ProcessReaderFuchsia::InitializeMemoryMap() { - DCHECK(!initialized_memory_map_); - - initialized_memory_map_ = true; - - memory_map_.reset(new MemoryMapFuchsia); - if (!memory_map_->Initialize(*process_)) { - memory_map_.reset(); - } -} - } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h index 91c6331c7..1392004e 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h
@@ -112,7 +112,7 @@ const ProcessMemory* Memory() const { return process_memory_.get(); } //! \brief Return a memory map for the target process. - const MemoryMapFuchsia* MemoryMap(); + const MemoryMapFuchsia* MemoryMap() const { return &memory_map_; } private: //! Performs lazy initialization of the \a modules_ vector on behalf of @@ -123,20 +123,15 @@ //! Threads(). void InitializeThreads(); - //! Performs lazy initialization of the \a memory_map_ on behalf of - //! MemoryMap(). - void InitializeMemoryMap(); - std::vector<Module> modules_; std::vector<Thread> threads_; std::vector<std::unique_ptr<ElfImageReader>> module_readers_; std::vector<std::unique_ptr<ProcessMemoryRange>> process_memory_ranges_; std::unique_ptr<ProcessMemoryFuchsia> process_memory_; - std::unique_ptr<MemoryMapFuchsia> memory_map_; + MemoryMapFuchsia memory_map_; zx::unowned_process process_; bool initialized_modules_ = false; bool initialized_threads_ = false; - bool initialized_memory_map_ = false; InitializationStateDcheck initialized_; DISALLOW_COPY_AND_ASSIGN(ProcessReaderFuchsia);
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc index 294c9f9..1ff758d1 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc
@@ -41,13 +41,10 @@ InitializeThreads(); InitializeModules(); - const MemoryMapFuchsia* memory_map = process_reader_.MemoryMap(); - if (memory_map) { - for (const auto& entry : memory_map->Entries()) { - if (entry.type == ZX_INFO_MAPS_TYPE_MAPPING) { - memory_map_.push_back( - std::make_unique<internal::MemoryMapRegionSnapshotFuchsia>(entry)); - } + for (const auto& entry : process_reader_.MemoryMap()->Entries()) { + if (entry.type == ZX_INFO_MAPS_TYPE_MAPPING) { + memory_map_.push_back( + std::make_unique<internal::MemoryMapRegionSnapshotFuchsia>(entry)); } }
diff --git a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.cc b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.cc index 722abac..ae689e5 100644 --- a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.cc +++ b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.cc
@@ -84,14 +84,13 @@ bool ProcessSnapshotSanitized::Initialize( const ProcessSnapshot* snapshot, - std::unique_ptr<const std::vector<std::string>> annotations_whitelist, - std::unique_ptr<const std::vector<std::pair<VMAddress, VMAddress>>> - memory_range_whitelist, + const std::vector<std::string>* annotations_whitelist, + const std::vector<std::pair<VMAddress, VMAddress>>* memory_range_whitelist, VMAddress target_module_address, bool sanitize_stacks) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); snapshot_ = snapshot; - annotations_whitelist_ = std::move(annotations_whitelist); + annotations_whitelist_ = annotations_whitelist; sanitize_stacks_ = sanitize_stacks; if (target_module_address) { @@ -142,7 +141,7 @@ if (annotations_whitelist_) { for (const auto module : snapshot_->Modules()) { modules_.emplace_back(std::make_unique<internal::ModuleSnapshotSanitized>( - module, annotations_whitelist_.get())); + module, annotations_whitelist_)); } } @@ -159,7 +158,7 @@ } } - process_memory_.Initialize(snapshot_->Memory(), memory_range_whitelist.get()); + process_memory_.Initialize(snapshot_->Memory(), memory_range_whitelist); INITIALIZATION_STATE_SET_VALID(initialized_); return true;
diff --git a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.h b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.h index 4e7e6d6..9ed2350 100644 --- a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.h +++ b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized.h
@@ -61,13 +61,12 @@ //! internal::StackSnapshotSanitized. //! \return `false` if \a snapshot does not meet sanitization requirements and //! should be filtered entirely. Otherwise `true`. - bool Initialize( - const ProcessSnapshot* snapshot, - std::unique_ptr<const std::vector<std::string>> annotations_whitelist, - std::unique_ptr<const std::vector<std::pair<VMAddress, VMAddress>>> - memory_range_whitelist, - VMAddress target_module_address, - bool sanitize_stacks); + bool Initialize(const ProcessSnapshot* snapshot, + const std::vector<std::string>* annotations_whitelist, + const std::vector<std::pair<VMAddress, VMAddress>>* + memory_range_whitelist, + VMAddress target_module_address, + bool sanitize_stacks); // ProcessSnapshot: @@ -100,7 +99,7 @@ RangeSet address_ranges_; const ProcessSnapshot* snapshot_; ProcessMemorySanitized process_memory_; - std::unique_ptr<const std::vector<std::string>> annotations_whitelist_; + const std::vector<std::string>* annotations_whitelist_; bool sanitize_stacks_; InitializationStateDcheck initialized_;
diff --git a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc index 5c5ff1a..9bad86c 100644 --- a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc +++ b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc
@@ -271,18 +271,17 @@ addrs.string_address, /* sanitized= */ false); - auto annotations_whitelist = std::make_unique<std::vector<std::string>>(); - annotations_whitelist->push_back(kWhitelistedAnnotationName); + std::vector<std::string> annotations_whitelist; + annotations_whitelist.push_back(kWhitelistedAnnotationName); - auto memory_ranges_whitelist = - std::make_unique<std::vector<std::pair<VMAddress, VMAddress>>>(); - memory_ranges_whitelist->push_back( + std::vector<std::pair<VMAddress, VMAddress>> memory_ranges_whitelist; + memory_ranges_whitelist.push_back( std::make_pair(addrs.string_address, addrs.string_address + 1)); ProcessSnapshotSanitized sanitized; ASSERT_TRUE(sanitized.Initialize(&snapshot, - std::move(annotations_whitelist), - std::move(memory_ranges_whitelist), + &annotations_whitelist, + &memory_ranges_whitelist, addrs.module_address, true));
diff --git a/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn b/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn index 9c25b58..b7f69e6 100644 --- a/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn +++ b/third_party/crashpad/crashpad/third_party/fuchsia/BUILD.gn
@@ -17,8 +17,8 @@ if (crashpad_is_in_fuchsia) { group("fuchsia") { public_deps = [ - "//zircon/system/fidl/fuchsia-mem", - "//zircon/system/fidl/fuchsia-sysinfo:fuchsia-sysinfo_c", + "//zircon/public/fidl/fuchsia.mem", + "//zircon/public/fidl/fuchsia.sysinfo:fuchsia.sysinfo_c", "//zircon/public/lib/fdio", "//zircon/public/lib/zx", ]
diff --git a/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn index 3267b981..f84b8baf 100644 --- a/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn +++ b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn
@@ -104,10 +104,6 @@ ] } - configs -= [ - "//third_party/mini_chromium/mini_chromium/build:Wimplicit_fallthrough", - ] - if (current_cpu == "x86" || current_cpu == "x64") { sources += [ "zlib/crc_folding.c",
diff --git a/third_party/crashpad/crashpad/util/file/file_io.h b/third_party/crashpad/crashpad/util/file/file_io.h index 3c956cc..797db682 100644 --- a/third_party/crashpad/crashpad/util/file/file_io.h +++ b/third_party/crashpad/crashpad/util/file/file_io.h
@@ -398,19 +398,6 @@ FileWriteMode mode, FilePermissions permissions); -#if defined(OS_LINUX) -//! \brief Wraps memfd_create(), logging an error if the operation fails. -//! Unlike other file open operations, this doesn't set `O_CLOEXEC`. -//! -//! \return The newly opened FileHandle, or an invalid FileHandle on failure. -//! -//! \sa ScopedFileHandle -//! \sa LoggingOpenFileForRead -//! \sa LoggingOpenFileForWrite -//! \sa LoggingOpenFileForReadAndWrite -FileHandle LoggingOpenMemFileForWrite(const base::FilePath& path); -#endif // OS_LINUX - //! \brief Wraps OpenFileForReadAndWrite(), logging an error if the operation //! fails. //!
diff --git a/third_party/crashpad/crashpad/util/file/file_io_posix.cc b/third_party/crashpad/crashpad/util/file/file_io_posix.cc index b72a48eb..f311616 100644 --- a/third_party/crashpad/crashpad/util/file/file_io_posix.cc +++ b/third_party/crashpad/crashpad/util/file/file_io_posix.cc
@@ -16,7 +16,6 @@ #include <fcntl.h> #include <sys/file.h> -#include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> @@ -99,12 +98,6 @@ permissions == FilePermissions::kWorldReadable ? 0644 : 0600)); } -#if defined(OS_LINUX) -FileHandle OpenMemFileForOutput(const base::FilePath& path) { - return HANDLE_EINTR(memfd_create(path.value().c_str(), 0)); -} -#endif - } // namespace namespace internal { @@ -156,14 +149,6 @@ return fd; } -#if defined(OS_LINUX) -FileHandle LoggingOpenMemFileForWrite(const base::FilePath& path) { - FileHandle fd = OpenMemFileForOutput(path); - PLOG_IF(ERROR, fd < 0) << "memfd_create " << path.value(); - return fd; -} -#endif - FileHandle LoggingOpenFileForReadAndWrite(const base::FilePath& path, FileWriteMode mode, FilePermissions permissions) {
diff --git a/third_party/crashpad/crashpad/util/file/file_writer.cc b/third_party/crashpad/crashpad/util/file/file_writer.cc index de28575d..13ac6cf 100644 --- a/third_party/crashpad/crashpad/util/file/file_writer.cc +++ b/third_party/crashpad/crashpad/util/file/file_writer.cc
@@ -171,23 +171,6 @@ return true; } -#if defined(OS_LINUX) -bool FileWriter::OpenMemfd(const base::FilePath& path) { - CHECK(!file_.is_valid()); - file_.reset(LoggingOpenMemFileForWrite(path)); - if (!file_.is_valid()) { - return false; - } - - weak_file_handle_file_writer_.set_file_handle(file_.get()); - return true; -} - -int FileWriter::fd() { - return file_.get(); -} -#endif - void FileWriter::Close() { CHECK(file_.is_valid());
diff --git a/third_party/crashpad/crashpad/util/file/file_writer.h b/third_party/crashpad/crashpad/util/file/file_writer.h index 663adff..ed261ec 100644 --- a/third_party/crashpad/crashpad/util/file/file_writer.h +++ b/third_party/crashpad/crashpad/util/file/file_writer.h
@@ -131,22 +131,6 @@ FileWriteMode write_mode, FilePermissions permissions); -#if defined(OS_LINUX) - //! \brief Wraps LoggingOpenMemFileForWrite(). - //! - //! \return `true` if the operation succeeded, `false` if it failed, with an - //! error message logged. - //! - //! \note After a successful call, this method or Open() cannot be called - // again until after Close(). - bool OpenMemfd(const base::FilePath& path); - - //! \brief Returns the underlying file descriptor. - //! - //! \note This is used when this writes to a Memfd. - int fd(); -#endif - //! \brief Wraps CheckedCloseHandle(). //! //! \note It is only valid to call this method on an object that has had a
diff --git a/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h b/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h index 90688c7..7f4da26 100644 --- a/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h +++ b/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h
@@ -50,13 +50,6 @@ //! \brief The address in the client's address space of a //! SanitizationInformation struct, or 0 if there is no such struct. VMAddress sanitization_information_address; - -#if defined(OS_LINUX) - //! \brief Indicates that the client is likely in a crash loop if a crash - //! occurs before this timestamp. This value is only used by ChromeOS's - //! `/sbin/crash_reporter`. - uint64_t crash_loop_before_time; -#endif }; //! \brief The signal used to indicate a crash dump is complete.
diff --git a/third_party/crashpad/crashpad/util/misc/metrics.h b/third_party/crashpad/crashpad/util/misc/metrics.h index d976381..8046497 100644 --- a/third_party/crashpad/crashpad/util/misc/metrics.h +++ b/third_party/crashpad/crashpad/util/misc/metrics.h
@@ -139,9 +139,6 @@ //! \brief Sanitization caused this crash dump to be skipped. kSkippedDueToSanitization = 11, - //! \brief Failure to open a memfd caused this crash dump to be skipped. - kOpenMemfdFailed = 12, - //! \brief The number of values in this enumeration; not a valid value. kMaxValue };
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 6b0e8bc..419d73e5 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-10-1-40-gcbee985a2 -Revision: cbee985a2bc14750ff850192f9ee8c1efe2bd7c7 +Version: VER-2-10-1-41-g543a3b939 +Revision: 543a3b939df50e02e52b948f4c9c8ba63bf38059 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/third_party/sqlite/OWNERS b/third_party/sqlite/OWNERS index 279a3cf4..674b2621 100644 --- a/third_party/sqlite/OWNERS +++ b/third_party/sqlite/OWNERS
@@ -1,8 +1,9 @@ # Primary: -pwnall@chromium.org +huangdarwin@chromium.org # Secondary: cmumford@google.com +pwnall@chromium.org # TEAM: storage-dev@chromium.org # COMPONENT: Internals>Storage
diff --git a/tools/android/elf_compression/README.md b/tools/android/elf_compression/README.md index e4aadff..9f3a4d6 100644 --- a/tools/android/elf_compression/README.md +++ b/tools/android/elf_compression/README.md
@@ -18,7 +18,6 @@ ### Library constructor TODO(https://crbug.com/998082): describe this. - ## Usage Firstly, the library needs to be build with the tool's constructor. TODO(https://crbug.com/998082): describe this. @@ -34,3 +33,10 @@ It is important to note that after running the script some of the common ELF tooling utilities, for example objcopy, may stop working because of the unusual (but legal) changes made to the library. + +## Testing +To run tests: + + test/compression_script_test.py + +The test simply verifies that the sample library is not broken after applying the script.
diff --git a/tools/android/elf_compression/test/compression_script_test.py b/tools/android/elf_compression/test/compression_script_test.py new file mode 100755 index 0000000..9f0d0f6 --- /dev/null +++ b/tools/android/elf_compression/test/compression_script_test.py
@@ -0,0 +1,125 @@ +#!/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. +"""Basic test for the compress_section script. + +Runs the script on a sample library and verifies that it still works. +""" + +import os +import subprocess +import tempfile +import unittest + +LIBRARY_CC_NAME = 'libtest.cc' +OPENER_CC_NAME = 'library_opener.cc' + +SCRIPT_PATH = '../compress_section.py' + +# src/third_party/llvm-build/Release+Asserts/bin/clang++ +LLVM_CLANG_PATH = os.path.abspath( + os.path.join( + os.path.dirname(__file__), os.path.pardir, os.path.pardir, + os.path.pardir, os.path.pardir, 'third_party', 'llvm-build', + 'Release+Asserts', 'bin', 'clang++')) + +# The array that we are trying to cut out of the file have those bytes at +# its start and end. This is done to simplify the test code to not perform +# full parse of the library to resolve the symbol. +MAGIC_BEGIN = bytes([151, 155, 125, 68]) +MAGIC_END = bytes([236, 55, 136, 224]) + + +class CompressionScriptTest(unittest.TestCase): + # Error output of the script could be large enough to be trimmed by the + # default setting, so disabling trimming on assertEqual. + maxDiff = None + + def setUp(self): + super(CompressionScriptTest, self).setUp() + self.tmpdir_object = tempfile.TemporaryDirectory() + self.tmpdir = self.tmpdir_object.name + + script_dir = os.path.dirname(os.path.abspath(__file__)) + self.library_cc_path = os.path.join(script_dir, LIBRARY_CC_NAME) + self.opener_cc_path = os.path.join(script_dir, OPENER_CC_NAME) + self.script_path = os.path.join(script_dir, SCRIPT_PATH) + + def tearDown(self): + self.tmpdir_object.cleanup() + super(CompressionScriptTest, self).tearDown() + + def _FindArrayRange(self, library_path): + with open(library_path, 'rb') as f: + data = f.read() + l = data.find(MAGIC_BEGIN) + r = data.find(MAGIC_END) + len(MAGIC_END) - 1 + return l, r + + def _BuildLibrary(self): + library_path = os.path.join(self.tmpdir, 'libtest.so') + library_build_result = subprocess.run([ + LLVM_CLANG_PATH, '-shared', '-fPIC', '-O2', self.library_cc_path, '-o', + library_path + ]) + self.assertEqual(library_build_result.returncode, 0) + return library_path + + def _BuildOpener(self): + opener_path = os.path.join(self.tmpdir, 'library_opener') + opener_build_result = subprocess.run([ + LLVM_CLANG_PATH, '-O2', self.opener_cc_path, '-o', opener_path, '-ldl' + ]) + self.assertEqual(opener_build_result.returncode, 0) + return opener_path + + def _RunScript(self, library_path): + # Finding array borders. + l, r = self._FindArrayRange(library_path) + self.assertNotEqual(l, -1) + self.assertLessEqual(l, r) + + output_path = os.path.join(self.tmpdir, 'patchedlibtest.so') + script_arguments = [ + self.script_path, + '-i', + library_path, + '-o', + output_path, + '-l', + str(l), + '-r', + str(r), + ] + script_run_result = subprocess.run( + script_arguments, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding='utf-8') + self.assertEqual(script_run_result.stderr, '') + self.assertEqual(script_run_result.returncode, 0) + return output_path + + def _RunOpener(self, opener_path, patched_library_path): + opener_run_result = subprocess.run([opener_path, patched_library_path], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding='utf-8') + + self.assertEqual(opener_run_result.stderr, '') + self.assertEqual(opener_run_result.returncode, 0) + return opener_run_result.stdout + + def testLibraryPatching(self): + """Runs the script on a test library and validates that it still works.""" + library_path = self._BuildLibrary() + opener_path = self._BuildOpener() + + patched_library_path = self._RunScript(library_path) + opener_output = self._RunOpener(opener_path, patched_library_path) + self.assertEqual(opener_output, '55\n') + + +if __name__ == '__main__': + unittest.main()
diff --git a/tools/android/elf_compression/test/library_opener.cc b/tools/android/elf_compression/test/library_opener.cc new file mode 100644 index 0000000..bfc78f84 --- /dev/null +++ b/tools/android/elf_compression/test/library_opener.cc
@@ -0,0 +1,36 @@ +// 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. + +// This binary opens the provided library and calls get_sum method from it. +// +// It is used solely for testing purposes to validate that the library is +// still working after applying the compression_script on it. + +#include <dlfcn.h> +#include <iostream> + +using TestFunction = int (*)(); + +int main(int argc, char** argv) { + if (argc < 2) { + std::cerr << "Library name not provided" << std::endl; + return 1; + } + char* name = argv[1]; + void* handle = dlopen(name, RTLD_NOW); + if (handle == nullptr) { + std::cerr << dlerror() << std::endl; + return 1; + } + + TestFunction get_sum = + reinterpret_cast<TestFunction>(dlsym(handle, "GetSum")); + if (get_sum == nullptr) { + std::cerr << "GetSum method not found" << std::endl; + return 1; + } + + std::cout << get_sum() << std::endl; + return 0; +}
diff --git a/tools/android/elf_compression/test/libtest.cc b/tools/android/elf_compression/test/libtest.cc new file mode 100644 index 0000000..fd6f429 --- /dev/null +++ b/tools/android/elf_compression/test/libtest.cc
@@ -0,0 +1,32 @@ +// 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. + +// Test library for compression_script. +// +// The array will be put in the .data section which will be used as an argument +// for the script. We expect library to not crash and return the 55 as a +// result. + +#include <numeric> +#include <vector> + +// The first and last 4 values are randomly chosen bytes to be used by test as +// "magic" values indicating the beginning and the end of the array. This array +// needs to be an exported symbol to avoid compiler optimization which is why it +// is not declared as "const". +unsigned char array[18] = {151, 155, 125, 68, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 236, 55, 136, 224}; + +extern "C" { +int GetSum(); +} + +int GetSum() { + // We are using some c++ features here to better simulate a c++ library and + // cause more code reach to catch potential memory errors. + std::vector<int> sum_array(&array[4], &array[4] + 10); + int sum = std::accumulate(sum_array.begin(), sum_array.end(), 0); + // sum should be equal to 55. + return sum; +}
diff --git a/tools/clang/stack_maps/CMakeLists.txt b/tools/clang/stack_maps/CMakeLists.txt new file mode 100644 index 0000000..ded8d1cf --- /dev/null +++ b/tools/clang/stack_maps/CMakeLists.txt
@@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.1) + +find_package(LLVM REQUIRED CONFIG) + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +add_definitions(${LLVM_DEFINITIONS}) +include_directories(${LLVM_INCLUDE_DIRS}) +link_directories(${LLVM_LIBRARY_DIRS}) + +add_subdirectory(RegisterGcFunctions) +add_subdirectory(IdentifySafepoints)
diff --git a/tools/clang/stack_maps/IdentifySafepoints/CMakeLists.txt b/tools/clang/stack_maps/IdentifySafepoints/CMakeLists.txt new file mode 100644 index 0000000..8b825b8 --- /dev/null +++ b/tools/clang/stack_maps/IdentifySafepoints/CMakeLists.txt
@@ -0,0 +1,2 @@ +add_library(LLVMIdentifySafepointsPass MODULE IdentifySafepoints.cpp) +target_compile_options(LLVMIdentifySafepointsPass PUBLIC -fno-rtti)
diff --git a/tools/clang/stack_maps/IdentifySafepoints/IdentifySafepoints.cpp b/tools/clang/stack_maps/IdentifySafepoints/IdentifySafepoints.cpp new file mode 100644 index 0000000..da670fa --- /dev/null +++ b/tools/clang/stack_maps/IdentifySafepoints/IdentifySafepoints.cpp
@@ -0,0 +1,64 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +using namespace llvm; + +static int kGCAddressSpace = 1; + +bool IsManaged(AllocaInst* AI) { + auto* T = AI->getType(); + + // If it looks like a Handle, it probably is a Handle. This brittle way of + // checking for managed on-stack values returns true if a single element + // struct has a GC address-spaced pointer field. + if (T->getElementType()->isStructTy()) { + auto* ST = dyn_cast<StructType>(&*T->getElementType()); + if (ST->getNumElements() == 1 && ST->getElementType(0)->isPointerTy()) { + if (ST->getElementType(0)->getPointerAddressSpace() == kGCAddressSpace) + return true; + } + } + return false; +} + +namespace { +struct IdentifySafepoints : public FunctionPass { + static char ID; + IdentifySafepoints() : FunctionPass(ID) {} + + bool runOnFunction(Function& F) override { + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { + if (auto* AI = dyn_cast_or_null<AllocaInst>(&*I)) { + if (IsManaged(AI)) { + F.addFnAttr("statepoint"); + return false; + } + } + } + return false; + } +}; + +char IdentifySafepoints::ID; +} // namespace + +static RegisterPass<IdentifySafepoints> X("-identify-safepoints", + "Identify Safepoints", + false /* Only looks at CFG */, + true /* Analysis Pass */); + +static RegisterStandardPasses Y(PassManagerBuilder::EP_EarlyAsPossible, + [](const PassManagerBuilder& Builder, + legacy::PassManagerBase& PM) { + PM.add(new IdentifySafepoints()); + });
diff --git a/tools/clang/stack_maps/README b/tools/clang/stack_maps/README index c7219f88..fe723b1f 100644 --- a/tools/clang/stack_maps/README +++ b/tools/clang/stack_maps/README
@@ -2,3 +2,23 @@ using clang/llvm infrastructure. Design doc: https://bit.ly/chromium-stack-maps + +Building and Running Tests: + +1. Build the gc libary + +`mkdir gc/build/ && cd gc/build` + +`cmake ../ && make` + +2. Build the LLVM passes: + +`mkdir ../../build/ && cd ../../build/` + +`cmake ../ && make all` + +3. Run the tests (from stack_maps/tests/) + +`./test.py <path_to_chromium_llvm_bin_dir> ../gc/build/libGC.a \ +../build/IdentifySafepoints/libLLVMIdentifySafepointsPass.so \ +../build/RegisterGcFunctionsPass.so`
diff --git a/tools/clang/stack_maps/RegisterGcFunctions/CMakeLists.txt b/tools/clang/stack_maps/RegisterGcFunctions/CMakeLists.txt new file mode 100644 index 0000000..2de2b5a --- /dev/null +++ b/tools/clang/stack_maps/RegisterGcFunctions/CMakeLists.txt
@@ -0,0 +1,2 @@ +add_library(LLVMRegisterGcFunctionsPass MODULE RegisterGcFunctions.cpp) +target_compile_options(LLVMRegisterGcFunctionsPass PUBLIC -fno-rtti)
diff --git a/tools/clang/stack_maps/RegisterGcFunctions/RegisterGcFunctions.cpp b/tools/clang/stack_maps/RegisterGcFunctions/RegisterGcFunctions.cpp new file mode 100644 index 0000000..5746dc53 --- /dev/null +++ b/tools/clang/stack_maps/RegisterGcFunctions/RegisterGcFunctions.cpp
@@ -0,0 +1,72 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/Analysis/CallGraph.h" + +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +using namespace llvm; + +static unsigned kGCAddressSpace = 1; + +void MaybeStatepointFunction(Function* F) { + if (F->hasFnAttribute("statepoint")) { + if (F->hasFnAttribute("no-statepoint")) + return; + + F->setGC("statepoint-example"); + } +} + +namespace { +struct RegisterGcFunctions : public ModulePass { + static char ID; + RegisterGcFunctions() : ModulePass(ID) {} + + bool runOnModule(Module& M) override { + auto GA = M.getNamedGlobal("llvm.global.annotations"); + if (GA) { + auto a = cast<ConstantArray>(GA->getOperand(0)); + for (int i = 0; i < a->getNumOperands(); i++) { + auto e = cast<ConstantStruct>(a->getOperand(i)); + + if (auto F = dyn_cast<Function>(e->getOperand(0)->getOperand(0))) { + auto Anno = cast<ConstantDataArray>( + cast<GlobalVariable>(e->getOperand(1)->getOperand(0)) + ->getOperand(0)) + ->getAsCString(); + F->addFnAttr(Anno); + } + } + } + + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + MaybeStatepointFunction(&*F); + } + + return false; + } +}; + +char RegisterGcFunctions::ID; +} // end of anonymous namespace + +static RegisterPass<RegisterGcFunctions> X("register-gc-fns", + "Register GC Functions", + false /* Only looks at CFG */, + true /* Analysis Pass */); + +static RegisterStandardPasses Y(PassManagerBuilder::EP_ModuleOptimizerEarly, + [](const PassManagerBuilder& Builder, + legacy::PassManagerBase& PM) { + PM.add(new RegisterGcFunctions()); + });
diff --git a/tools/clang/stack_maps/gc/GC_Shim_x86_64.S b/tools/clang/stack_maps/gc/GC_Shim_x86_64.S index 1fde626..fe7f750 100644 --- a/tools/clang/stack_maps/gc/GC_Shim_x86_64.S +++ b/tools/clang/stack_maps/gc/GC_Shim_x86_64.S
@@ -1,17 +1,34 @@ +// 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. .text -.globl GetFramePtr -// Places the frame pointer value in the return register -GetFramePtr: - mov (%rbp), %rax +// This function is assumed to be called only from within InitGC. The value +// pointed to by InitGCs frame pointer is loaded as the stack sentinal value. +.globl InitTopOfStack +InitTopOfStack: + mov (%rbp), %rdi + mov %rdi, (TopOfStack) ret .extern StackWalkAndMoveObjects -.globl BeginGC +.globl GC -// We place the frame pointer in the first arg slot register. We jump to -// StackWalkAndMoveObjects instead of calling it so that RET returns to -// BeginGC's caller caller. -BeginGC: +// We place the frame pointer in the first arg slot register and call +// StackWalkAndMoveObjects. The function epilogue needs to be hand-written +// afterwards so as to not corrupt the stack. +GC: + pushq %rbp + movq %rsp, %rbp + subq $8, %rsp mov %rbp, %rdi - jmp StackWalkAndMoveObjects + call StackWalkAndMoveObjects + addq $8, %rsp + popq %rbp + ret + +.bss +.globl TopOfStack +TopOfStack: + .quad 0 + .size TopOfStack, 8
diff --git a/tools/clang/stack_maps/gc/gc_api.cc b/tools/clang/stack_maps/gc/gc_api.cc index 9023846..8fd8ce9 100644 --- a/tools/clang/stack_maps/gc/gc_api.cc +++ b/tools/clang/stack_maps/gc/gc_api.cc
@@ -3,10 +3,9 @@ // found in the LICENSE file. #include "gc_api.h" -#include <ostream> SafepointTable spt = GenSafepointTable(); -Heap* heap = new Heap(); +Heap* heap = nullptr; HeapAddress Heap::AllocRaw(long value) { assert(heap_ptr < kHeapSize && "Allocation failed: Heap full"); @@ -33,27 +32,26 @@ return reinterpret_cast<HeapAddress>(new_ptr); } -std::ostream& operator<<(std::ostream& os, const FrameRoots& fr) { - os << "Register Roots: NYI" << std::endl << "\t"; - if (!fr.stack_roots_.size()) { - os << "Stack Roots: []" << std::endl; - return os; +void FrameRoots::Print() const { + printf("\tRegister Roots: NYI\n"); + if (!stack_roots_.size()) { + printf("\tStack Roots: []\n"); + return; } - os << "Stack Roots: ["; - for (auto SR : fr.stack_roots_) { - os << "RBP - " << SR << ", "; + printf("\tStack Roots: ["); + for (auto SR : stack_roots_) { + printf("RBP - %d, ", SR); } - os << "\b\b]" << std::endl; - return os; + printf("\b\b]\n"); } -std::ostream& operator<<(std::ostream& os, const SafepointTable& st) { - os << "Safepoint Table:" << std::endl; - for (auto const& pair : st.roots_) { - os << "\t" << pair.first << ":\n\t" << pair.second << std::endl; +void SafepointTable::Print() const { + printf("Safepoint Table\n"); + for (auto const& pair : roots_) { + printf("Frame %p\n", reinterpret_cast<void*>(pair.first)); + pair.second.Print(); } - return os; } extern "C" void StackWalkAndMoveObjects(FramePtr fp) { @@ -62,6 +60,11 @@ // RBP value in the current frame auto ra = reinterpret_cast<ReturnAddress>(*(fp + 1)); + // Step up into the caller's frame or bail if we're at the top of stack + fp = reinterpret_cast<FramePtr>(*fp); + if (reinterpret_cast<uintptr_t>(fp) == TopOfStack) + break; + printf("==== Frame %p ====\n", reinterpret_cast<void*>(ra)); auto it = spt.roots()->find(ra); @@ -91,19 +94,24 @@ reinterpret_cast<void*>(*stack_address)); } } - - // Step up into the caller's frame or bail if we're at the top of stack - fp = reinterpret_cast<FramePtr>(*fp); - if (reinterpret_cast<uintptr_t>(fp) < spt.stack_begin()) - break; } - heap->MoveObjects(); } Handle<HeapObject> AllocateHeapObject(long data) { HeapAddress ptr = heap->AllocRaw(data); - /* long* ptr = new long; */ - /* *ptr = data; */ return Handle<HeapObject>::New(reinterpret_cast<HeapObject*>(ptr)); } + +void InitGC() { + InitTopOfStack(); + heap = new Heap(); +} + +void TeardownGC() { + delete heap; +} + +void PrintSafepointTable() { + spt.Print(); +}
diff --git a/tools/clang/stack_maps/gc/gc_api.h b/tools/clang/stack_maps/gc/gc_api.h index 2e08020c..64d7fcd 100644 --- a/tools/clang/stack_maps/gc/gc_api.h +++ b/tools/clang/stack_maps/gc/gc_api.h
@@ -7,7 +7,6 @@ #include <assert.h> #include <map> -#include <ostream> #include <vector> #include "objects.h" @@ -96,15 +95,13 @@ bool empty() { return reg_roots_.empty() && stack_roots_.empty(); } - friend std::ostream& operator<<(std::ostream& os, const FrameRoots& fr); + void Print() const; private: std::vector<DWARF> reg_roots_; std::vector<RBPOffset> stack_roots_; }; -std::ostream& operator<<(std::ostream& os, const FrameRoots& fr); - // A SafepointTable provides a runtime mapping of function return addresses to // on-stack and in-register gc root locations. Return addresses are used as a // function call site is the only place where safepoints can exist. This map is @@ -112,32 +109,35 @@ // looking for the rootset. class SafepointTable { public: - SafepointTable(std::map<ReturnAddress, FrameRoots> roots, - uintptr_t stack_begin) - : roots_(std::move(roots)), stack_begin_(stack_begin) {} + SafepointTable(std::map<ReturnAddress, FrameRoots> roots) + : roots_(std::move(roots)) {} const std::map<ReturnAddress, FrameRoots>* roots() { return &roots_; } - uintptr_t stack_begin() { return stack_begin_; } - friend std::ostream& operator<<(std::ostream& os, const SafepointTable& st); + void Print() const; private: - std::map<ReturnAddress, FrameRoots> roots_; - uintptr_t stack_begin_; + const std::map<ReturnAddress, FrameRoots> roots_; }; -std::ostream& operator<<(std::ostream& os, const SafepointTable& st); - SafepointTable GenSafepointTable(); extern SafepointTable spt; extern Heap* heap; +// During stack scanning, the GC must know when it has reached the top of the +// stack so that it can hand execution back over to the mutator. This global +// variable serves that purpose - it is initialised in main to be equal to +// main's RBP value, and checked against each time the gc steps up into the next +// stack frame. For non-main threads this could be pthread top. +extern "C" void InitTopOfStack(); +extern uintptr_t TopOfStack; + void PrintSafepointTable(); // Walks the execution stack looking for live gc roots. This function should -// never be called directly. Instead, the void |BeginGC| function should be -// called. |BeginGC| is an assembly shim which jumps to this function after +// never be called directly. Instead, the void |GC| function should be +// called. |GC| is an assembly shim which jumps to this function after // placing the value of RBP in RDI (First arg slot mandated by Sys V ABI). // // Stack walking starts from the address in `fp` (assumed to be RBP's
diff --git a/tools/clang/stack_maps/gc/stack_map_parser.cc b/tools/clang/stack_maps/gc/stack_map_parser.cc index eac2522..d51d850 100644 --- a/tools/clang/stack_maps/gc/stack_map_parser.cc +++ b/tools/clang/stack_maps/gc/stack_map_parser.cc
@@ -89,7 +89,7 @@ fn++; } - return SafepointTable(roots, GetFramePtr()); + return SafepointTable(roots); } } // namespace stackmap
diff --git a/tools/clang/stack_maps/gc/stack_map_parser.h b/tools/clang/stack_maps/gc/stack_map_parser.h index fa5121a..a90bb91b 100644 --- a/tools/clang/stack_maps/gc/stack_map_parser.h +++ b/tools/clang/stack_maps/gc/stack_map_parser.h
@@ -12,9 +12,6 @@ // parser. extern const char __LLVM_StackMaps; -// This is done with a non-portable asm shim which places RBP in RAX -extern "C" uintptr_t GetFramePtr(); - namespace stackmap { // These structs group together fields in the stackmap section to be used by the
diff --git a/tools/clang/stack_maps/objects.h b/tools/clang/stack_maps/objects.h index 79119a05..ea3633c5 100644 --- a/tools/clang/stack_maps/objects.h +++ b/tools/clang/stack_maps/objects.h
@@ -8,17 +8,22 @@ #include <stdint.h> #define GC_AS __attribute__((address_space(1))) + +// This should be used only when finer control is needed to prevent statepoint +// insertion. It must not be used on functions which will have a pointer on the +// stack across a GC. It should be used very carefully as it overrides the +// default statepointing mechanism. #define NO_STATEPOINT \ __attribute__((noinline)) __attribute__((annotate("no-statepoint"))) -using Address = uintptr_t; +using Address = void GC_AS*; // A HeapObject is just a heap allocated long integer. This is all that is // necessary to show precise stack scanning in practise and greatly simplifies // the implementation. class HeapObject { public: - HeapObject(long data) : data(data) {} + NO_STATEPOINT HeapObject(long data) : data(data) {} long data; }; @@ -33,11 +38,14 @@ return Handle<T>(gcptr); } - inline T* operator->() { return (T*)address; } + T operator*() const { + long data = *(long GC_AS*)address; + return HeapObject(data); + } private: - Address GC_AS* address; - Handle<T>(Address GC_AS* address) : address(address) {} + Address address; + Handle<T>(Address address) : address(address) {} }; #endif // TOOLS_CLANG_STACK_MAPS_OBJECTS_H_
diff --git a/tools/clang/stack_maps/tests.h b/tools/clang/stack_maps/tests.h new file mode 100644 index 0000000..0baaa421 --- /dev/null +++ b/tools/clang/stack_maps/tests.h
@@ -0,0 +1,19 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef TOOLS_CLANG_STACK_MAPS_TESTS_H_ +#define TOOLS_CLANG_STACK_MAPS_TESTS_H_ + +// Initialises the GC by setting up the heap and marking top of stack so the +// gc knows where to stop during walking. +extern void InitGC(); + +// Calls the collector, which will move the underlying heap objects and update +// pointer values on the stack. +extern "C" void GC(); + +// Frees all heap memory +extern void TeardownGC(); + +#endif // TOOLS_CLANG_STACK_MAPS_TESTS_H_
diff --git a/tools/clang/stack_maps/tests/relocate_across_fns.cpp b/tools/clang/stack_maps/tests/relocate_across_fns.cpp new file mode 100644 index 0000000..7bf49f62 --- /dev/null +++ b/tools/clang/stack_maps/tests/relocate_across_fns.cpp
@@ -0,0 +1,47 @@ +// Copyright 2013 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. + +// This tests whether objects in Handles which are passed in function arguments +// can be re-accessed after a moving collection. +// +// A GC call ensures that every Handle'd object is relocated. Attempting to +// deref the value after this call should yield the same object that was +// initially allocated. + +#include <assert.h> +#include "objects.h" +#include "tests.h" + +extern Handle<HeapObject> AllocateHeapObject(long data); + +long expected = 1234; + +__attribute__((noinline)) Handle<HeapObject> bar(Handle<HeapObject> x) { + GC(); + assert((*x).data == expected && "GC Objects differ across a collection"); + return x; +} + +__attribute__((noinline)) Handle<HeapObject> foo(Handle<HeapObject> x) { + assert((*x).data == expected && "GC Objects differ across a collection"); + return bar(x); +} + +__attribute__((noinline)) Handle<HeapObject> baz(Handle<HeapObject> x) { + assert((*x).data == expected && "GC Objects differ across a collection"); + return foo(x); +} + +__attribute__((noinline)) void test_relocation() { + auto handle = AllocateHeapObject(expected); + baz(handle); + assert((*handle).data == expected && "GC Objects differ across a collection"); +} + +int main() { + InitGC(); + test_relocation(); + TeardownGC(); + return 0; +}
diff --git a/tools/clang/stack_maps/tests/relocate_single_fn.cpp b/tools/clang/stack_maps/tests/relocate_single_fn.cpp new file mode 100644 index 0000000..8880e3d --- /dev/null +++ b/tools/clang/stack_maps/tests/relocate_single_fn.cpp
@@ -0,0 +1,39 @@ +// 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. + +// This file tests whether on-stack roots inside a single function are updated +// across a collection. +// +// A GC call ensures that every Handle'd object is relocated. Attempting to +// deref the value after this call should yield the same object that was +// initially allocated. + +#include <assert.h> +#include "objects.h" +#include "tests.h" + +extern Handle<HeapObject> AllocateHeapObject(long data); + +// We noinline for demonstration purposes only - we want to be able to know the +// call graph deterministically to ensure things behave as expected. Inlining +// small functions like this could make debugging more difficult. +__attribute__((noinline)) void test_relocation() { + auto expected = 1234; + auto handle = AllocateHeapObject(expected); + + // Relocates all objects in the heap from fromspace to tospace and walks the + // stack, updating roots to point to the relocated object. + GC(); + + assert((*handle).data == expected && "GC Objects differ across a collection"); +} + +int main() { + InitGC(); + + test_relocation(); + + TeardownGC(); + return 0; +}
diff --git a/tools/clang/stack_maps/tests/test.py b/tools/clang/stack_maps/tests/test.py new file mode 100755 index 0000000..90b8d8b7 --- /dev/null +++ b/tools/clang/stack_maps/tests/test.py
@@ -0,0 +1,206 @@ +#!/usr/bin/env python +# 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. + +from __future__ import print_function + +import glob +import argparse +import os +import subprocess +import sys +import shutil + +script_dir = os.path.dirname(os.path.realpath(__file__)) +tool_dir = os.path.abspath(os.path.join(script_dir, '../../pylib')) +sys.path.insert(0, tool_dir) + +from clang import plugin_testing + +class StackMapTest(plugin_testing.ClangPluginTest): + """Test harness for stack map artefact.""" + + def __init__(self, test_base, llvm_bin_path, libgc_path, ident_sp_pass_path, + reg_gc_pass_path,): + self._test_base = test_base + self._llvm_bin_path = llvm_bin_path + self._libgc_path = libgc_path + self._ident_sp_pass_path = ident_sp_pass_path + self._reg_gc_pass_path = reg_gc_pass_path + + self._clang_path = os.path.join(llvm_bin_path, 'clang++') + self._opt_path = os.path.join(llvm_bin_path, 'opt') + self._llc_path = os.path.join(llvm_bin_path, 'llc') + self._out_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), 'out') + + def build_commands(self, test_name): + ll_filename = os.path.join(self._out_dir, "%s.ll" % test_name) + ll_with_gc_filename = os.path.join( + self._out_dir, "%s_optimised.ll" % test_name) + asm_filename = os.path.join(self._out_dir, "%s.s" % test_name) + obj_filename = os.path.join(self._out_dir, "%s.o" % test_name) + bin_name = os.path.join(self._out_dir, "%s.out" % test_name) + + # Run the clang++ frontend with -O2 but stop after emitting the IR. There + # is a bug in clang which prevents us from running GC related IR phases + # directly from the frontend and requires us to split it into multiple + # build phases. + clang_cmd = [ + self._clang_path, + '-std=c++14', + '-fno-omit-frame-pointer', + '-I../', + '-Xclang', + '-load', + '-Xclang', + self._ident_sp_pass_path, + '-O2', + '-S', + '-emit-llvm', + '-o', ll_filename, + '%s.cpp' % test_name + ] + + # Run two passes on the IR. The first selects which functions will be + # safepointed, the second inserts statepoint relocation sequences and ends + # up in stack maps being generated during the lowering phase. + opt_cmd = [ + self._opt_path, + '-load=%s' % self._reg_gc_pass_path, + '-register-gc-fns', + '-rewrite-statepoints-for-gc', + '-S', + '-o', ll_with_gc_filename, + ll_filename + ] + + # Note: We must ensure each stage of lowering disables omit frame pointer + # optimisation + llc_cmd = [ + self._llc_path, + ll_with_gc_filename, + '--frame-pointer=all', + '-o', + asm_filename + ] + + # The next two stages are required because ToT LLVM emits stackmaps which + # are local only to their object file. In a somewhat hacky fix, we + # globalise this symbol so that it can be used by the independent GC + # runtime library. + make_native = [ + self._clang_path, + '-c', + '-o', + obj_filename, + asm_filename, + ] + + obj_copy = [ + 'objcopy', + '--globalize-symbol=__LLVM_StackMaps', + obj_filename + ] + + # Link the GC runtime and create target executable + link_cmd = [ + self._clang_path, + obj_filename, + '-fno-omit-frame-pointer', + self._libgc_path, + '-o', + bin_name + ] + + run_cmd = ['%s' % bin_name] + return [ + clang_cmd, + opt_cmd, + llc_cmd, + make_native, + obj_copy, + link_cmd, + run_cmd + ] + + def Run(self): + """Runs the tests. + + The working directory is temporarily changed to self._test_base while + running the tests. + + Returns: the number of failing tests. + """ + print('Using llvm tools in %s...' % self._llvm_bin_path) + + os.chdir(self._test_base) + + passing = [] + failing = [] + tests = glob.glob('*.cpp') + + # Delete out directory if it already exists + if (os.path.exists(self._out_dir)): + shutil.rmtree(self._out_dir) + + os.mkdir(self._out_dir) + for test in tests: + sys.stdout.write('Testing %s...' % test) + test_name, _ = os.path.splitext(test) + + cmds = self.build_commands(test_name) + failure_message = self.RunOneTest(test_name, cmds) + + if failure_message: + print('\n\tfailed: %s' % failure_message) + failing.append(test_name) + else: + print('\tpassed!') + passing.append(test_name) + + print('Ran %d tests: %d succeeded, %d failed' % ( + len(passing) + len(failing), len(passing), len(failing))) + for test in failing: + print(' %s' % test) + return len(failing) + + def RunOneTest(self, test_name, cmds): + for cmd in cmds: + try: + failure_message = "" + subprocess.check_output(cmd, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + failure_message = e.output + break + except Exception as e: + return 'could not execute %s (%s)' % (cmd, e) + + return self.ProcessOneResult(test_name, failure_message) + + def ProcessOneResult(self, test_name, failure_message): + if failure_message: + return failure_message.replace('\r\n', '\n') + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + 'llvm_bin_path', help='The path to the llvm tools bin dir.') + parser.add_argument('libgc_path', help='The path to the runtime gc library.') + parser.add_argument('identify_safepoints_path', + help='The path to the identify safepoints IR pass.') + parser.add_argument('reg_gc_fns_path', + help='The path to the register GC functions IR pass.') + args = parser.parse_args() + + return StackMapTest( + os.path.dirname(os.path.realpath(__file__)), + args.llvm_bin_path, + args.libgc_path, + args.identify_safepoints_path, + args.reg_gc_fns_path, + ).Run() + +if __name__ == '__main__': + sys.exit(main())
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index aeda7b4..acaff45 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -19012,6 +19012,7 @@ <int value="439" label="ACCESSIBILITY_PRIVATE_ON_SWITCH_ACCESS_COMMAND"/> <int value="440" label="ACCESSIBILITY_PRIVATE_FIND_SCROLLABLE_BOUNDS_FOR_POINT"/> + <int value="441" label="LOGIN_STATE_ON_SESSION_STATE_CHANGED"/> </enum> <enum name="ExtensionFileWriteResult"> @@ -20454,6 +20455,8 @@ <int value="1376" label="AUTOTESTPRIVATE_GETALLINSTALLEDAPPS"/> <int value="1377" label="AUTOTESTPRIVATE_SWAPWINDOWSINSPLITVIEW"/> <int value="1378" label="AUTOTESTPRIVATE_SETARCAPPWINDOWFOCUS"/> + <int value="1379" label="LOGINSTATE_GETPROFILETYPE"/> + <int value="1380" label="LOGINSTATE_GETSESSIONSTATE"/> </enum> <enum name="ExtensionIconState"> @@ -20996,6 +20999,7 @@ <int value="219" label="kTransientBackground"/> <int value="220" label="kLogin"/> <int value="221" label="kLoginScreenStorage"/> + <int value="222" label="kLoginState"/> </enum> <enum name="ExtensionServiceVerifyAllSuccess"> @@ -46751,6 +46755,18 @@ <int value="1" label="1+ from Android"/> </enum> +<enum name="PasswordManagerOnboardingState"> + <int value="0" label="Not shown"/> + <int value="1" label="Should be shown"/> + <int value="2" label="Shown"/> +</enum> + +<enum name="PasswordManagerOnboardingUIDismissalReason"> + <int value="0" label="Accepted"/> + <int value="1" label="Rejected"/> + <int value="2" label="Dismissed"/> +</enum> + <enum name="PasswordManagerOsPasswordStatus"> <int value="0" label="Unknown"/> <int value="1" label="Unsupported platform"/> @@ -54398,13 +54414,6 @@ </int> </enum> -<enum name="SharingClickToCallDialogType"> - <int value="0" label="Dialog with devices and maybe apps"/> - <int value="1" label="Dialog without devices but with an app"/> - <int value="2" label="Educational dialog without devices or apps"/> - <int value="3" label="Error dialog"/> -</enum> - <enum name="SharingDeviceRegistrationResult"> <int value="0" label="Operation is successful"/> <int value="1" label="Failed with Sync not ready"/> @@ -54414,6 +54423,13 @@ <int value="5" label="Device has not been registered"/> </enum> +<enum name="SharingDialogType"> + <int value="0" label="Dialog with devices and maybe apps"/> + <int value="1" label="Dialog without devices but with an app"/> + <int value="2" label="Educational dialog without devices or apps"/> + <int value="3" label="Error dialog"/> +</enum> + <enum name="SharingMessageType"> <int value="0" label="Unknown"/> <int value="1" label="Ping"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 2da64be..32d2f18 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -98891,6 +98891,27 @@ </summary> </histogram> +<histogram name="PasswordManager.Onboarding.State" + enum="PasswordManagerOnboardingState" expires_after="2020-01-31"> + <owner>achulkov@google.com</owner> + <owner>ioanap@chromium.org</owner> + <summary> + The current state of showing the password manager onboarding to the user. + Recorded on startup. + </summary> +</histogram> + +<histogram name="PasswordManager.Onboarding.UIDismissalReason" + enum="PasswordManagerOnboardingUIDismissalReason" + expires_after="2020-01-31"> + <owner>achulkov@google.com</owner> + <owner>ioanap@chromium.org</owner> + <summary> + Reason of dismissal of the password manager onboarding dialog. Recorded when + the user is propmpted to save their password and the dialog is shown. + </summary> +</histogram> + <histogram name="PasswordManager.OsPasswordStatus" enum="PasswordManagerOsPasswordStatus" expires_after="M83"> <owner>battre@chromium.org</owner> @@ -128617,6 +128638,17 @@ </summary> </histogram> +<histogram name="Sharing.ClickToCallDialerPresent" enum="BooleanPresent" + expires_after="2020-02-02"> + <owner>mvanouwerkerk@chromium.org</owner> + <owner>knollr@chromium.org</owner> + <summary> + Logged when we try to fire a dial intent in click to call. Distinguishes + between if the user has an app that can handle dial intent or not. Android + only. + </summary> +</histogram> + <histogram name="Sharing.ClickToCallDialIntent" enum="BooleanEmpty" expires_after="2020-02-02"> <owner>mvanouwerkerk@chromium.org</owner> @@ -128628,8 +128660,8 @@ </summary> </histogram> -<histogram name="Sharing.ClickToCallDialogShown" - enum="SharingClickToCallDialogType" expires_after="2020-02-02"> +<histogram name="Sharing.ClickToCallDialogShown" enum="SharingDialogType" + expires_after="2020-02-02"> <owner>mvanouwerkerk@chromium.org</owner> <owner>knollr@chromium.org</owner> <summary>
diff --git a/ui/base/ime/init/input_method_factory.cc b/ui/base/ime/init/input_method_factory.cc index b938a160..b9c988b 100644 --- a/ui/base/ime/init/input_method_factory.cc +++ b/ui/base/ime/init/input_method_factory.cc
@@ -72,20 +72,27 @@ #endif } -void SetUpInputMethodFactoryForTesting() { - if (g_input_method_set_for_testing) - return; - - CHECK(!g_create_input_method_called) - << "ui::SetUpInputMethodFactoryForTesting was called after use of " - << "ui::CreateInputMethod. You must call " - << "ui::SetUpInputMethodFactoryForTesting earlier."; - - g_input_method_set_for_testing = true; -} - void SetUpInputMethodForTesting(InputMethod* input_method) { g_input_method_for_testing = input_method; } +ScopedTestInputMethodFactory::ScopedTestInputMethodFactory() { + CHECK(!g_input_method_set_for_testing) + << "ScopedTestInputMethodFactory was created after calling " + "ui::SetUpInputMethodFactoryForTesting or inside another " + "ScopedTestInputMethodFactory lifetime."; + + DLOG_IF(WARNING, g_create_input_method_called) + << "ui::CreateInputMethod was already called. That can happen when other " + "tests in the same process uses normal ui::InputMethod instance."; + + g_input_method_set_for_testing = true; + g_create_input_method_called = false; +} + +ScopedTestInputMethodFactory::~ScopedTestInputMethodFactory() { + g_input_method_set_for_testing = false; + g_create_input_method_called = false; +} + } // namespace ui
diff --git a/ui/base/ime/init/input_method_factory.h b/ui/base/ime/init/input_method_factory.h index ef2ac395..d2d933a 100644 --- a/ui/base/ime/init/input_method_factory.h +++ b/ui/base/ime/init/input_method_factory.h
@@ -26,10 +26,18 @@ gfx::AcceleratedWidget widget); // Makes CreateInputMethod return a MockInputMethod. -COMPONENT_EXPORT(UI_BASE_IME_INIT) void SetUpInputMethodFactoryForTesting(); COMPONENT_EXPORT(UI_BASE_IME_INIT) void SetUpInputMethodForTesting(InputMethod* input_method); +class COMPONENT_EXPORT(UI_BASE_IME_INIT) ScopedTestInputMethodFactory { + public: + ScopedTestInputMethodFactory(); + ~ScopedTestInputMethodFactory(); + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedTestInputMethodFactory); +}; + } // namespace ui; #endif // UI_BASE_IME_INIT_INPUT_METHOD_FACTORY_H_
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn b/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn index 1f089970..2f393a1 100644 --- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn +++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn
@@ -13,6 +13,7 @@ js_library("cr_searchable_drop_down") { deps = [ "//third_party/polymer/v1_0/components-chromium/iron-dropdown:iron-dropdown-extracted", + "//third_party/polymer/v1_0/components-chromium/iron-icon:iron-icon-extracted", "//third_party/polymer/v1_0/components-chromium/paper-progress:paper-progress-extracted", "//ui/webui/resources/cr_elements/cr_input:cr_input", ]
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html index e0bdd63..bc5c7e2 100644 --- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html +++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
@@ -2,8 +2,10 @@ <link rel="import" href="../cr_input/cr_input.html"> <link rel="import" href="../cr_scrollable_behavior.html"> +<link rel="import" href="../icons.html"> <link rel="import" href="../shared_vars_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html"> <dom-module id="cr-searchable-drop-down"> @@ -41,6 +43,25 @@ width: 100%; } + #dropdown-icon { + --iron-icon-height: 20px; + --iron-icon-width: 20px; + margin-top: -10px; + padding-inline-end: 6px; + position: absolute; + right: 0; + top: 50%; + } + + :host-context([dir='rtl']) #dropdown-icon { + left: 0; + right: unset; + } + + cr-input:focus-within #dropdown-icon { + --iron-icon-fill-color: var(--google-blue-600); + } + #input-box { height: 100%; left: 0; @@ -95,6 +116,7 @@ invalid="[[shouldShowErrorMessage_(errorMessage, errorMessageAllowed)]]"> <div id="input-overlay" slot="suffix"> <div id="input-box"> + <iron-icon id="dropdown-icon" icon="cr:arrow-drop-down"></iron-icon> <paper-progress id="loading" indeterminate hidden="[[!showLoading]]"> </paper-progress> </div>