diff --git a/DEPS b/DEPS index a85dd4c..2bef2e1 100644 --- a/DEPS +++ b/DEPS
@@ -175,11 +175,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': '853789cdfe3c518492959458804add4a8d2e664c', + 'skia_revision': '964aa91580b6aa3f14fe0b61578e5807ae9c92ce', # 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': '189353b3360a48f637f7bb228db10268fdc991c9', + 'v8_revision': '65b70d61b93c092a2cf5c0bcf264c1d594fdc6fb', # 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. @@ -187,11 +187,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'c3655c3a7d55049bb9c881dc89df66f69125afb8', + 'angle_revision': 'f8b28678163603f8fab1c45e19507c7500299021', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '176f3a3dbbc90d7b2dd9822db709505b4ad41b67', + 'swiftshader_revision': 'abc7a30a06c7c135d76032f1346c5d2d1b73f427', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -246,7 +246,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'd5ae9bf042df46c5eddab0d34d643f4dd7897d28', + 'devtools_frontend_revision': '683c198380dbee96fad08e689d30cb9911a4712c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -298,7 +298,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. - 'shaderc_revision': '06b6db68ff7e20d4f097a132dd56a1c6482e8c25', + 'shaderc_revision': '6e9087162a1cd9b67d66ebd3cda0054765f27ee9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -863,7 +863,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '6566156b03a02a3269ef099feccf40b762aa7668', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '181bb9733f8392b5dbea5fe37545f29251268ea6', 'condition': 'checkout_linux', }, @@ -944,7 +944,7 @@ Var('chromium_git') + '/codecs/libgav1.git' + '@' + '8e8c13b9e821f4590761487c4e0b96f432eaf051', 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '56364b6b602696c021349794a8d39744a1052afc', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '8985fc91089f3117d338f0ebd683596a197b2d92', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1239,7 +1239,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '29f04c8cdb9bb12711a1706b061ec81d82311c5f', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '8ff2fc8fcdb168a9ba4ac17d053d3e8dd7864912', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1440,7 +1440,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'ec18cc3262922e7dcdbe70243c6f40606f979144', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '83762b21dbd2efbcbed81fefbd0218a99c03c18a', + Var('webrtc_git') + '/src.git' + '@' + '5e1ea251895c08fbc48cb595b02f9257cedeac75', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1515,7 +1515,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e36af5c1ab9bb1c194e46c956d4e3154eb5caa1b', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f8a16ac6d46764c95d9197be1aab0374b97ae8d9', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 835b045..693253b 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -2397,8 +2397,7 @@ 'tikuta+cc@chromium.org', 'ukai+cc@chromium.org', 'yyanagisawa+cc@chromium.org'], - 'cr_elements': ['michaelpg+watch-elements@chromium.org', - 'stevenjb+watch-md-settings@chromium.org'], + 'cr_elements': ['michaelpg+watch-elements@chromium.org'], 'cros_benchmarks': ['cros-perf-detectives@google.com', 'cywang@chromium.org', 'vovoy@chromium.org'],
diff --git a/android_webview/browser/BUILD.gn b/android_webview/browser/BUILD.gn index f69ebd1e..df05873 100644 --- a/android_webview/browser/BUILD.gn +++ b/android_webview/browser/BUILD.gn
@@ -253,7 +253,6 @@ "//third_party/crashpad/crashpad/client", "//ui/android", "//ui/gl", - "//ui/native_theme", "//ui/resources", "//ui/touch_selection", ]
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS index 0175c4b1..bd5acad41 100644 --- a/android_webview/browser/DEPS +++ b/android_webview/browser/DEPS
@@ -84,7 +84,6 @@ "+ui/display", "+ui/gfx", "+ui/gl", - "+ui/native_theme", "+ui/touch_selection/touch_handle.h", # Temporary until we bundle our own favicon. See
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc index 56dbf31..b579762 100644 --- a/android_webview/browser/aw_settings.cc +++ b/android_webview/browser/aw_settings.cc
@@ -26,7 +26,6 @@ #include "content/public/common/web_preferences.h" #include "net/http/http_util.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" -#include "ui/native_theme/native_theme.h" using base::android::ConvertJavaStringToUTF16; using base::android::ConvertUTF8ToJavaString; @@ -526,19 +525,19 @@ break; } } - ui::NativeTheme::PreferredColorScheme preferred_color_scheme = - is_dark_mode ? ui::NativeTheme::PreferredColorScheme::kDark - : ui::NativeTheme::PreferredColorScheme::kNoPreference; + web_prefs->preferred_color_scheme = + is_dark_mode ? blink::PreferredColorScheme::kDark + : blink::PreferredColorScheme::kNoPreference; if (is_dark_mode) { switch (Java_AwSettings_getForceDarkBehaviorLocked(env, obj)) { case ForceDarkBehavior::FORCE_DARK_ONLY: { - preferred_color_scheme = - ui::NativeTheme::PreferredColorScheme::kNoPreference; + web_prefs->preferred_color_scheme = + blink::PreferredColorScheme::kNoPreference; web_prefs->force_dark_mode_enabled = true; break; } case ForceDarkBehavior::MEDIA_QUERY_ONLY: { - preferred_color_scheme = ui::NativeTheme::PreferredColorScheme::kDark; + web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; web_prefs->force_dark_mode_enabled = false; break; } @@ -549,19 +548,16 @@ // dark so that dark themed content will be preferred over force // darkening. case ForceDarkBehavior::PREFER_MEDIA_QUERY_OVER_FORCE_DARK: { - preferred_color_scheme = ui::NativeTheme::PreferredColorScheme::kDark; + web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; web_prefs->force_dark_mode_enabled = true; break; } } } else { - preferred_color_scheme = - ui::NativeTheme::PreferredColorScheme::kNoPreference; + web_prefs->preferred_color_scheme = + blink::PreferredColorScheme::kNoPreference; web_prefs->force_dark_mode_enabled = false; } - // Notify NativeTheme of changes to dark mode. - ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( - preferred_color_scheme); } bool AwSettings::GetAllowFileAccess() {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/DarkModeTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/DarkModeTest.java new file mode 100644 index 0000000..6fe3f81 --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/DarkModeTest.java
@@ -0,0 +1,148 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview.test; + +import android.support.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.android_webview.AwContents; +import org.chromium.android_webview.AwSettings; +import org.chromium.android_webview.settings.ForceDarkBehavior; +import org.chromium.android_webview.settings.ForceDarkMode; + +/** + * Tests dark-mode related data are correctly passed to blink. + */ +@RunWith(AwJUnit4ClassRunner.class) +public class DarkModeTest { + @Rule + public AwActivityTestRule mRule = new AwActivityTestRule(); + + private TestAwContentsClient mContentsClient = new TestAwContentsClient(); + private AwContents mContents; + private AwSettings mSettings; + + @Before + public void setUp() { + mContents = createAwContentsJsEnabled(); + mSettings = mContents.getSettings(); + } + + @Test + @SmallTest + public void testDarkModeOff() throws Throwable { + mRule.loadUrlSync(mContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + + // Disable dark mode and check that prefers-color-scheme is not set to dark. + mSettings.setForceDarkMode(ForceDarkMode.FORCE_DARK_OFF); + assertNotDarkScheme(mContents); + } + + @Test + @SmallTest + public void testUAOnlyDarkening() throws Throwable { + // If WebView uses UA only darkening strategy prefer-color-scheme should always been set to + // NoPreference to avoid double darkening regardless whether web-page supports dark theme. + mSettings.setForceDarkMode(ForceDarkMode.FORCE_DARK_ON); + mSettings.setForceDarkBehavior(ForceDarkBehavior.FORCE_DARK_ONLY); + + // Load web-page which does not support dark theme and + // check prefers-color-scheme is not set to dark + mRule.loadUrlSync(mContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + assertNotDarkScheme(mContents); + + // Load web page which supports dark theme and + // check prefers-color-scheme is still not set to dark + final String supportsDarkScheme = + "<html><head><meta name=\"color-scheme\" content=\"dark light\"></head>" + + "<body></body></html>"; + mRule.loadHtmlSync( + mContents, mContentsClient.getOnPageFinishedHelper(), supportsDarkScheme); + assertNotDarkScheme(mContents); + } + + @Test + @SmallTest + public void testWebThemeOnlyDarkening() throws Throwable { + // If WebView uses web theme only darkening strategy + // prefer-color-scheme should been set to dark. + mRule.loadUrlSync(mContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + mSettings.setForceDarkMode(ForceDarkMode.FORCE_DARK_ON); + mSettings.setForceDarkBehavior(ForceDarkBehavior.MEDIA_QUERY_ONLY); + + assertDarkScheme(mContents); + } + + @Test + @SmallTest + public void testPreferWebThemeDarkening() throws Throwable { + // If WebView prefers web theme darkening over UA darkening prefer-color-scheme is set + // according to whether web page supports dark-theme + mRule.loadUrlSync(mContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + mSettings.setForceDarkMode(ForceDarkMode.FORCE_DARK_ON); + mSettings.setForceDarkBehavior(ForceDarkBehavior.PREFER_MEDIA_QUERY_OVER_FORCE_DARK); + + // If web page does not support dark theme prefer-color-scheme should be set to NoPreference + assertNotDarkScheme(mContents); + + final String supportsDarkScheme = + "<html><head><meta name=\"color-scheme\" content=\"dark light\"></head>" + + "<body></body></html>"; + mRule.loadHtmlSync( + mContents, mContentsClient.getOnPageFinishedHelper(), supportsDarkScheme); + + // If web page supports dark theme, prefer-color-scheme is set to dark. + assertDarkScheme(mContents); + } + + @Test + @SmallTest + public void testDarkThemePerWebView() throws Throwable { + // WebView allows to set dark mode preferences per WebView, check that their settings + // do not interfere with each other. + + mRule.loadUrlSync(mContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + mSettings.setForceDarkMode(ForceDarkMode.FORCE_DARK_ON); + mSettings.setForceDarkBehavior(ForceDarkBehavior.MEDIA_QUERY_ONLY); + + AwContents otherContents = createAwContentsJsEnabled(); + AwSettings otherSettings = otherContents.getSettings(); + mRule.loadUrlSync(otherContents, mContentsClient.getOnPageFinishedHelper(), "about:blank"); + otherSettings.setForceDarkMode(ForceDarkMode.FORCE_DARK_ON); + otherSettings.setForceDarkBehavior(ForceDarkBehavior.FORCE_DARK_ONLY); + + assertDarkScheme(mContents); + assertNotDarkScheme(otherContents); + } + + private boolean prefersDarkTheme(AwContents contents) throws Exception { + final String colorSchemeSelector = + "window.matchMedia('(prefers-color-scheme: dark)').matches"; + String result = mRule.executeJavaScriptAndWaitForResult( + contents, mContentsClient, colorSchemeSelector); + + return "true".equals(result); + } + + private void assertNotDarkScheme(AwContents contents) throws Exception { + Assert.assertFalse(prefersDarkTheme(contents)); + } + + private void assertDarkScheme(AwContents contents) throws Exception { + Assert.assertTrue(prefersDarkTheme(contents)); + } + + private AwContents createAwContentsJsEnabled() { + AwTestContainerView view = mRule.createAwTestContainerViewOnMainSync(mContentsClient); + AwContents contents = view.getAwContents(); + AwActivityTestRule.enableJavaScriptOnUiThread(contents); + return contents; + } +}
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index cb04470..fedb876b 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -253,6 +253,7 @@ "../javatests/src/org/chromium/android_webview/test/ContentViewMiscTest.java", "../javatests/src/org/chromium/android_webview/test/CookieManagerStartupTest.java", "../javatests/src/org/chromium/android_webview/test/CookieManagerTest.java", + "../javatests/src/org/chromium/android_webview/test/DarkModeTest.java", "../javatests/src/org/chromium/android_webview/test/DisableHardwareAccelerationForTest.java", "../javatests/src/org/chromium/android_webview/test/FullScreenVideoTestAwContentsClient.java", "../javatests/src/org/chromium/android_webview/test/GeolocationTest.java",
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index 6bd26b9..56066cd 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -75,6 +75,7 @@ // Distance from the top of the user view to the user icon. constexpr int kDistanceFromTopOfBigUserViewToUserIconDp = 24; +constexpr SkColor kChallengeResponseSmartCardIconColor = gfx::kGoogleGrey200; constexpr SkColor kChallengeResponseArrowBackgroundColor = SkColorSetARGB(0x2B, 0xFF, 0xFF, 0xFF); constexpr SkColor kChallengeResponseErrorColor = gfx::kGoogleRed300; @@ -596,7 +597,7 @@ case State::kAuthenticating: return gfx::CreateVectorIcon(kLockScreenSmartCardIcon, kChallengeResponseIconSizeDp, - SK_ColorWHITE); + kChallengeResponseSmartCardIconColor); case State::kFailure: return gfx::CreateVectorIcon(kLockScreenSmartCardFailureIcon, kChallengeResponseIconSizeDp,
diff --git a/ash/public/cpp/shelf_test_api.h b/ash/public/cpp/shelf_test_api.h index 1e96a4f..3a51126 100644 --- a/ash/public/cpp/shelf_test_api.h +++ b/ash/public/cpp/shelf_test_api.h
@@ -32,6 +32,10 @@ views::View* GetHomeButton(); + // Whether the shelf has a login shelf gesture handler set up, which would + // imply that swipe from shelf gesture detection is active. + bool HasLoginShelfGestureHandler() const; + // Returns ui information of scrollable shelf for the given state. If |state| // specifies the scroll distance, the target offset, which is the offset value // after scrolling by the distance, is also calculated. It is useful if you
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc index 422f6b18..a88e0d7 100644 --- a/ash/shelf/shelf.cc +++ b/ash/shelf/shelf.cc
@@ -20,6 +20,7 @@ #include "ash/shelf/shelf_controller.h" #include "ash/shelf/shelf_focus_cycler.h" #include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_layout_manager_observer.h" #include "ash/shelf/shelf_navigation_widget.h" #include "ash/shelf/shelf_observer.h" #include "ash/shelf/shelf_tooltip_manager.h" @@ -104,6 +105,65 @@ HotseatState target_state_; }; +// An animation metrics reporter for the shelf navigation widget. +class ASH_EXPORT NavigationWidgetAnimationMetricsReporter + : public ui::AnimationMetricsReporter, + public ShelfLayoutManagerObserver { + public: + explicit NavigationWidgetAnimationMetricsReporter(Shelf* shelf) + : shelf_(shelf) { + shelf_->shelf_layout_manager()->AddObserver(this); + } + + ~NavigationWidgetAnimationMetricsReporter() override { + shelf_->shelf_layout_manager()->RemoveObserver(this); + } + + NavigationWidgetAnimationMetricsReporter( + const NavigationWidgetAnimationMetricsReporter&) = delete; + NavigationWidgetAnimationMetricsReporter& operator=( + const NavigationWidgetAnimationMetricsReporter&) = delete; + + // ui::AnimationMetricsReporter: + void Report(int value) override { + switch (target_state_) { + case HotseatState::kShownClamshell: + case HotseatState::kShownHomeLauncher: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.Widget.AnimationSmoothness." + "TransitionToShownHotseat", + value); + break; + case HotseatState::kExtended: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.Widget.AnimationSmoothness." + "TransitionToExtendedHotseat", + value); + break; + case HotseatState::kHidden: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.Widget.AnimationSmoothness." + "TransitionToHiddenHotseat", + value); + break; + default: + NOTREACHED(); + break; + } + } + + // ShelfLayoutManagerObserver: + void OnHotseatStateChanged(HotseatState old_state, + HotseatState new_state) override { + target_state_ = new_state; + } + + private: + Shelf* shelf_; + // The state to which the animation is transitioning. + HotseatState target_state_ = HotseatState::kShownHomeLauncher; +}; + // Shelf::AutoHideEventHandler ----------------------------------------------- // Forwards mouse and gesture events to ShelfLayoutManager for auto-hide. @@ -257,6 +317,8 @@ navigation_widget_ = std::make_unique<ShelfNavigationWidget>( this, hotseat_widget()->GetShelfView()); navigation_widget_->Initialize(container); + navigation_widget_metrics_reporter_ = + std::make_unique<NavigationWidgetAnimationMetricsReporter>(this); Shell::Get()->focus_cycler()->AddWidget(navigation_widget_.get()); } @@ -540,10 +602,16 @@ return hotseat_transition_metrics_reporter_.get(); } +ui::AnimationMetricsReporter* +Shelf::GetNavigationWidgetAnimationMetricsReporter() { + return navigation_widget_metrics_reporter_.get(); +} + void Shelf::WillDeleteShelfLayoutManager() { // Clear event handlers that might forward events to the destroyed instance. auto_hide_event_handler_.reset(); auto_dim_event_handler_.reset(); + navigation_widget_metrics_reporter_.reset(); DCHECK(shelf_layout_manager_); shelf_layout_manager_->RemoveObserver(this);
diff --git a/ash/shelf/shelf.h b/ash/shelf/shelf.h index a1b3bb1..cd34087 100644 --- a/ash/shelf/shelf.h +++ b/ash/shelf/shelf.h
@@ -34,6 +34,7 @@ enum class AnimationChangeType; class HotseatWidget; class HotseatWidgetAnimationMetricsReporter; +class NavigationWidgetAnimationMetricsReporter; class ShelfFocusCycler; class ShelfLayoutManager; class ShelfLayoutManagerTest; @@ -231,6 +232,7 @@ ShelfTooltipManager* tooltip() { return tooltip_.get(); } ui::AnimationMetricsReporter* GetHotseatTransitionMetricsReporter(); + ui::AnimationMetricsReporter* GetNavigationWidgetAnimationMetricsReporter(); protected: // ShelfLayoutManagerObserver: @@ -292,6 +294,11 @@ std::unique_ptr<HotseatWidgetAnimationMetricsReporter> hotseat_transition_metrics_reporter_; + // Animation metrics reporter for navigation widget animations. Owned by the + // Shelf to ensure it outlives the Navigation Widget. + std::unique_ptr<NavigationWidgetAnimationMetricsReporter> + navigation_widget_metrics_reporter_; + // True while the animation to enter or exit tablet mode is running. Sometimes // this value is true when the shelf movements are not actually animating // (animation value = 0.0). This is because this is set to true when we
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 3f3c860..3bab8c70 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -115,22 +115,27 @@ void SetupAnimator(ui::ScopedLayerAnimationSettings* animation_setter, base::TimeDelta animation_duration, - gfx::Tween::Type type) { + gfx::Tween::Type type, + ui::AnimationMetricsReporter* animation_metrics_reporter) { animation_setter->SetTransitionDuration(animation_duration); if (!animation_duration.is_zero()) { animation_setter->SetTweenType(type); animation_setter->SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + if (animation_metrics_reporter) + animation_setter->SetAnimationMetricsReporter(animation_metrics_reporter); } } void AnimateOpacity(views::Widget* widget, float target_opacity, base::TimeDelta animation_duration, - gfx::Tween::Type type) { + gfx::Tween::Type type, + ui::AnimationMetricsReporter* animation_metrics_reporter) { ui::ScopedLayerAnimationSettings animation_setter( GetLayer(widget)->GetAnimator()); - SetupAnimator(&animation_setter, animation_duration, type); + SetupAnimator(&animation_setter, animation_duration, type, + animation_metrics_reporter); GetLayer(widget)->SetOpacity(target_opacity); } @@ -1446,14 +1451,17 @@ ShelfConfig::Get()->DimAnimationTween(); AnimateOpacity(shelf_->navigation_widget(), target_opacity_, - dim_animation_duration, dim_animation_tween); + dim_animation_duration, dim_animation_tween, + shelf_->GetNavigationWidgetAnimationMetricsReporter()); AnimateOpacity(shelf_->hotseat_widget(), shelf_->hotseat_widget()->CalculateOpacity(), - dim_animation_duration, dim_animation_tween); + dim_animation_duration, dim_animation_tween, + /*animation_metrics_reporter=*/nullptr); AnimateOpacity(shelf_->status_area_widget(), target_opacity_, - dim_animation_duration, dim_animation_tween); + dim_animation_duration, dim_animation_tween, + /*animation_metrics_reporter=*/nullptr); shelf_widget_->SetLoginShelfButtonOpacity(target_opacity_); }
diff --git a/ash/shelf/shelf_navigation_widget.cc b/ash/shelf/shelf_navigation_widget.cc index d9cc2c2..75031c25 100644 --- a/ash/shelf/shelf_navigation_widget.cc +++ b/ash/shelf/shelf_navigation_widget.cc
@@ -11,14 +11,17 @@ #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_focus_cycler.h" #include "ash/shelf/shelf_layout_manager.h" +#include "ash/shelf/shelf_layout_manager_observer.h" #include "ash/shelf/shelf_view.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/status_area_widget.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "base/metrics/histogram_macros.h" #include "chromeos/constants/chromeos_switches.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/compositor/animation_metrics_reporter.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/views/animation/bounds_animator.h" @@ -91,6 +94,115 @@ }; } // namespace +// An animation metrics reporter for the shelf navigation buttons. +class ASH_EXPORT NavigationButtonAnimationMetricsReporter + : public ui::AnimationMetricsReporter, + public ShelfLayoutManagerObserver { + public: + // The different kinds of navigation buttons. + enum class NavigationButtonType { + // The Navigation Widget's back button. + kBackButton, + // The Navigation Widget's home button. + kHomeButton + }; + NavigationButtonAnimationMetricsReporter( + Shelf* shelf, + NavigationButtonType navigation_button_type) + : shelf_(shelf), navigation_button_type_(navigation_button_type) { + shelf_->shelf_layout_manager()->AddObserver(this); + } + + ~NavigationButtonAnimationMetricsReporter() override { + shelf_->shelf_layout_manager()->RemoveObserver(this); + } + + NavigationButtonAnimationMetricsReporter( + const NavigationButtonAnimationMetricsReporter&) = delete; + NavigationButtonAnimationMetricsReporter& operator=( + const NavigationButtonAnimationMetricsReporter&) = delete; + + // ui::AnimationMetricsReporter: + void Report(int value) override { + switch (target_state_) { + case HotseatState::kShownClamshell: + case HotseatState::kShownHomeLauncher: + switch (navigation_button_type_) { + case NavigationButtonType::kBackButton: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.BackButton.AnimationSmoothness." + "TransitionToShownHotseat", + value); + break; + case NavigationButtonType::kHomeButton: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.HomeButton.AnimationSmoothness." + "TransitionToShownHotseat", + value); + break; + default: + NOTREACHED(); + break; + } + break; + case HotseatState::kExtended: + switch (navigation_button_type_) { + case NavigationButtonType::kBackButton: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.BackButton.AnimationSmoothness." + "TransitionToExtendedHotseat", + value); + break; + case NavigationButtonType::kHomeButton: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.HomeButton.AnimationSmoothness." + "TransitionToExtendedHotseat", + value); + break; + default: + NOTREACHED(); + break; + } + break; + case HotseatState::kHidden: + switch (navigation_button_type_) { + case NavigationButtonType::kBackButton: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.BackButton.AnimationSmoothness." + "TransitionToHiddenHotseat", + value); + break; + case NavigationButtonType::kHomeButton: + UMA_HISTOGRAM_PERCENTAGE( + "Ash.NavigationWidget.HomeButton.AnimationSmoothness." + "TransitionToHiddenHotseat", + value); + break; + default: + NOTREACHED(); + break; + } + break; + default: + NOTREACHED(); + break; + } + } + + // ShelfLayoutManagerObserver: + void OnHotseatStateChanged(HotseatState old_state, + HotseatState new_state) override { + target_state_ = new_state; + } + + private: + // Owned by RootWindowController + Shelf* shelf_; + // The state to which the animation is transitioning. + HotseatState target_state_ = HotseatState::kShownHomeLauncher; + // The type of navigation button that is animated. + NavigationButtonType navigation_button_type_; +}; class ShelfNavigationWidget::Delegate : public views::AccessiblePaneView, public views::WidgetDelegate { @@ -283,13 +395,27 @@ ShelfView* shelf_view) : shelf_(shelf), delegate_(new ShelfNavigationWidget::Delegate(shelf, shelf_view)), - bounds_animator_(std::make_unique<views::BoundsAnimator>(delegate_)) { + bounds_animator_(std::make_unique<views::BoundsAnimator>(delegate_)), + back_button_metrics_reporter_( + std::make_unique<NavigationButtonAnimationMetricsReporter>( + shelf, + NavigationButtonAnimationMetricsReporter::NavigationButtonType:: + kBackButton)), + home_button_metrics_reporter_( + std::make_unique<NavigationButtonAnimationMetricsReporter>( + shelf, + NavigationButtonAnimationMetricsReporter::NavigationButtonType:: + kHomeButton)) { DCHECK(shelf_); ShelfConfig::Get()->AddObserver(this); } ShelfNavigationWidget::~ShelfNavigationWidget() { ShelfConfig::Get()->RemoveObserver(this); + + // Cancel animations now so the BoundsAnimator doesn't outlive the metrics + // reporter associated to it. + bounds_animator_->Cancel(); } void ShelfNavigationWidget::Initialize(aura::Window* container) { @@ -447,31 +573,40 @@ const auto animation_duration = animate ? ShelfConfig::Get()->shelf_animation_duration() : base::TimeDelta::FromMilliseconds(0); - bounds_animator_->SetAnimationDuration(animation_duration); - ui::ScopedLayerAnimationSettings nav_animation_setter( GetNativeView()->layer()->GetAnimator()); nav_animation_setter.SetTransitionDuration(animation_duration); nav_animation_setter.SetTweenType(gfx::Tween::EASE_OUT); nav_animation_setter.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + if (animate) { + nav_animation_setter.SetAnimationMetricsReporter( + shelf_->GetNavigationWidgetAnimationMetricsReporter()); + } GetLayer()->SetOpacity(layout_manager->GetOpacity()); SetBounds(target_bounds_); views::View* const back_button = delegate_->back_button(); - UpdateButtonVisibility(back_button, back_button_shown, animate); + UpdateButtonVisibility(back_button, back_button_shown, animate, + back_button_metrics_reporter_.get()); views::View* const home_button = delegate_->home_button(); - UpdateButtonVisibility(home_button, home_button_shown, animate); + UpdateButtonVisibility(home_button, home_button_shown, animate, + home_button_metrics_reporter_.get()); gfx::Rect home_button_bounds = back_button_shown ? GetSecondButtonBounds() : GetFirstButtonBounds(shelf_->IsHorizontalAlignment()); - if (animate) + + if (animate) { + bounds_animator_->SetAnimationDuration(animation_duration); + bounds_animator_->set_animation_metrics_reporter( + home_button_metrics_reporter_.get()); bounds_animator_->AnimateViewTo(home_button, home_button_bounds); - else + } else { home_button->SetBoundsRect(home_button_bounds); + } back_button->SetBoundsRect( GetFirstButtonBounds(shelf_->IsHorizontalAlignment())); @@ -494,9 +629,13 @@ } } -void ShelfNavigationWidget::UpdateButtonVisibility(views::View* button, - bool visible, - bool animate) { +void ShelfNavigationWidget::UpdateButtonVisibility( + views::View* button, + bool visible, + bool animate, + ui::AnimationMetricsReporter* reporter) { + if (button->GetVisible() == visible) + return; // Update visibility immediately only if making the button visible. When // hiding the button, the visibility will be updated when the animations // complete (by AnimationObserverToHideView). @@ -511,6 +650,9 @@ animate ? kButtonOpacityAnimationDuration : base::TimeDelta()); opacity_settings.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); + if (animate) { + opacity_settings.SetAnimationMetricsReporter(reporter); + } if (!visible) opacity_settings.AddObserver(new AnimationObserverToHideView(button));
diff --git a/ash/shelf/shelf_navigation_widget.h b/ash/shelf/shelf_navigation_widget.h index 767e191..c0da3283 100644 --- a/ash/shelf/shelf_navigation_widget.h +++ b/ash/shelf/shelf_navigation_widget.h
@@ -20,9 +20,14 @@ class BoundsAnimator; } +namespace ui { +class AnimationMetricsReporter; +} + namespace ash { class BackButton; class HomeButton; +class NavigationButtonAnimationMetricsReporter; class Shelf; class ShelfView; @@ -90,13 +95,27 @@ private: class Delegate; - void UpdateButtonVisibility(views::View* button, bool visible, bool animate); + void UpdateButtonVisibility( + views::View* button, + bool visible, + bool animate, + ui::AnimationMetricsReporter* animation_metrics_reporter); Shelf* shelf_ = nullptr; Delegate* delegate_ = nullptr; gfx::Rect target_bounds_; std::unique_ptr<views::BoundsAnimator> bounds_animator_; + // Animation metrics reporter for back button animations. Owned by the + // Widget to ensure it outlives the BackButton view. + std::unique_ptr<NavigationButtonAnimationMetricsReporter> + back_button_metrics_reporter_; + + // Animation metrics reporter for home button animations. Owned by the + // Widget to ensure it outlives the HomeButton view. + std::unique_ptr<NavigationButtonAnimationMetricsReporter> + home_button_metrics_reporter_; + DISALLOW_COPY_AND_ASSIGN(ShelfNavigationWidget); };
diff --git a/ash/shelf/shelf_test_api.cc b/ash/shelf/shelf_test_api.cc index 4d314e00..79e59c35 100644 --- a/ash/shelf/shelf_test_api.cc +++ b/ash/shelf/shelf_test_api.cc
@@ -51,6 +51,10 @@ return GetShelfWidget()->navigation_widget()->GetHomeButton(); } +bool ShelfTestApi::HasLoginShelfGestureHandler() const { + return GetShelfWidget()->login_shelf_gesture_controller_for_testing(); +} + ScrollableShelfInfo ShelfTestApi::GetScrollableShelfInfoForState( const ScrollableShelfState& state) { const auto* scrollable_shelf_view = GetScrollableShelfView();
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 02fd7af..a65c9151 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -313,7 +313,9 @@ : model_(model), shelf_(shelf), view_model_(std::make_unique<views::ViewModel>()), - bounds_animator_(std::make_unique<views::BoundsAnimator>(this)), + bounds_animator_( + std::make_unique<views::BoundsAnimator>(this, + /*use_transforms=*/true)), focus_search_(std::make_unique<ShelfFocusSearch>(this)), drag_and_drop_host_(drag_and_drop_host), shelf_button_delegate_(shelf_button_delegate) {
diff --git a/base/BUILD.gn b/base/BUILD.gn index 43b74d0..65f0b56 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1139,7 +1139,6 @@ "mac/scoped_nsautorelease_pool.h", "mac/scoped_nsautorelease_pool.mm", "mac/scoped_nsobject.h", - "mac/scoped_nsobject.mm", "mac/scoped_objc_class_swizzler.h", "mac/scoped_objc_class_swizzler.mm", "mac/scoped_sending_event.h", @@ -1993,7 +1992,6 @@ "mac/scoped_nsautorelease_pool.h", "mac/scoped_nsautorelease_pool.mm", "mac/scoped_nsobject.h", - "mac/scoped_nsobject.mm", "mac/scoped_objc_class_swizzler.h", "mac/scoped_objc_class_swizzler.mm", "mac/scoped_typeref.h", @@ -2435,10 +2433,7 @@ if (is_ios || is_mac) { source_set("base_unittests_arc") { testonly = true - sources = [ - "mac/bind_objc_block_unittest_arc.mm", - "mac/scoped_nsobject_unittest_arc.mm", - ] + sources = [ "mac/bind_objc_block_unittest_arc.mm" ] configs += [ "//build/config/compiler:enable_arc" ] deps = [ ":base",
diff --git a/base/android/java/src/org/chromium/base/task/PostTask.java b/base/android/java/src/org/chromium/base/task/PostTask.java index c5b3754..fcaa95d3 100644 --- a/base/android/java/src/org/chromium/base/task/PostTask.java +++ b/base/android/java/src/org/chromium/base/task/PostTask.java
@@ -87,9 +87,9 @@ getTaskExecutorForTraits(taskTraits).postDelayedTask(taskTraits, task, delay); } else { TaskTraits postedTraits = taskTraits.withExplicitDestination(); - PostTaskJni.get().postDelayedTask(postedTraits.mPrioritySetExplicitly, - postedTraits.mPriority, postedTraits.mMayBlock, postedTraits.mUseThreadPool, - postedTraits.mExtensionId, postedTraits.mExtensionData, task, delay); + PostTaskJni.get().postDelayedTask(postedTraits.mPriority, postedTraits.mMayBlock, + postedTraits.mUseThreadPool, postedTraits.mExtensionId, + postedTraits.mExtensionData, task, delay); } } } @@ -261,8 +261,7 @@ @NativeMethods interface Natives { - void postDelayedTask(boolean prioritySetExplicitly, int priority, boolean mayBlock, - boolean useThreadPool, byte extensionId, byte[] extensionData, Runnable task, - long delay); + void postDelayedTask(int priority, boolean mayBlock, boolean useThreadPool, + byte extensionId, byte[] extensionData, Runnable task, long delay); } }
diff --git a/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java b/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java index d1a750a..7ede72d 100644 --- a/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java +++ b/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java
@@ -163,9 +163,8 @@ protected void initNativeTaskRunnerInternal() { if (mNativeTaskRunnerAndroid == 0) { mNativeTaskRunnerAndroid = TaskRunnerImplJni.get().init(mTaskRunnerType, - mTaskTraits.mPrioritySetExplicitly, mTaskTraits.mPriority, - mTaskTraits.mMayBlock, mTaskTraits.mUseThreadPool, mTaskTraits.mExtensionId, - mTaskTraits.mExtensionData); + mTaskTraits.mPriority, mTaskTraits.mMayBlock, mTaskTraits.mUseThreadPool, + mTaskTraits.mExtensionId, mTaskTraits.mExtensionData); } } @@ -191,8 +190,8 @@ @NativeMethods interface Natives { // NB due to Proguard obfuscation it's easiest to pass the traits via arguments. - long init(@TaskRunnerType int taskRunnerType, boolean prioritySetExplicitly, int priority, - boolean mayBlock, boolean useThreadPool, byte extensionId, byte[] extensionData); + long init(@TaskRunnerType int taskRunnerType, int priority, boolean mayBlock, + boolean useThreadPool, byte extensionId, byte[] extensionData); void destroy(long nativeTaskRunnerAndroid); void postDelayedTask(long nativeTaskRunnerAndroid, Runnable task, long delay);
diff --git a/base/android/java/src/org/chromium/base/task/TaskTraits.java b/base/android/java/src/org/chromium/base/task/TaskTraits.java index a4546bda..f967aa9 100644 --- a/base/android/java/src/org/chromium/base/task/TaskTraits.java +++ b/base/android/java/src/org/chromium/base/task/TaskTraits.java
@@ -79,7 +79,6 @@ // For convenience of the JNI code, we use primitive types only. // Note shutdown behavior is not supported on android. - boolean mPrioritySetExplicitly; int mPriority; boolean mMayBlock; boolean mUseThreadPool; @@ -89,11 +88,11 @@ // Derive custom traits from existing trait constants. private TaskTraits() { - mPriority = TaskPriority.USER_VISIBLE; + // Assume USER_BLOCKING by default. + mPriority = TaskPriority.USER_BLOCKING; } private TaskTraits(TaskTraits other) { - mPrioritySetExplicitly = other.mPrioritySetExplicitly; mPriority = other.mPriority; mMayBlock = other.mMayBlock; mUseThreadPool = other.mUseThreadPool; @@ -103,7 +102,6 @@ public TaskTraits taskPriority(int taskPriority) { TaskTraits taskTraits = new TaskTraits(this); - taskTraits.mPrioritySetExplicitly = true; taskTraits.mPriority = taskPriority; return taskTraits; } @@ -181,10 +179,8 @@ return true; } else if (object instanceof TaskTraits) { TaskTraits other = (TaskTraits) object; - return mPrioritySetExplicitly == other.mPrioritySetExplicitly - && mPriority == other.mPriority && mMayBlock == other.mMayBlock - && mUseThreadPool == other.mUseThreadPool - && mExtensionId == other.mExtensionId + return mPriority == other.mPriority && mMayBlock == other.mMayBlock + && mUseThreadPool == other.mUseThreadPool && mExtensionId == other.mExtensionId && Arrays.equals(mExtensionData, other.mExtensionData) && mIsChoreographerFrame == other.mIsChoreographerFrame; } else { @@ -195,7 +191,6 @@ @Override public int hashCode() { int hash = 31; - hash = 37 * hash + (mPrioritySetExplicitly ? 0 : 1); hash = 37 * hash + mPriority; hash = 37 * hash + (mMayBlock ? 0 : 1); hash = 37 * hash + (mUseThreadPool ? 0 : 1);
diff --git a/base/android/task_scheduler/post_task_android.cc b/base/android/task_scheduler/post_task_android.cc index 78f1cf7..5473cac0 100644 --- a/base/android/task_scheduler/post_task_android.cc +++ b/base/android/task_scheduler/post_task_android.cc
@@ -45,14 +45,12 @@ // static TaskTraits PostTaskAndroid::CreateTaskTraits( JNIEnv* env, - jboolean priority_set_explicitly, jint priority, jboolean may_block, jboolean use_thread_pool, jbyte extension_id, const base::android::JavaParamRef<jbyteArray>& extension_data) { - return TaskTraits(priority_set_explicitly, - static_cast<TaskPriority>(priority), may_block, + return TaskTraits(static_cast<TaskPriority>(priority), may_block, use_thread_pool, TaskTraitsExtensionStorage( extension_id, GetExtensionData(env, extension_data))); @@ -60,7 +58,6 @@ void JNI_PostTask_PostDelayedTask( JNIEnv* env, - jboolean priority_set_explicitly, jint priority, jboolean may_block, jboolean use_thread_pool, @@ -72,8 +69,8 @@ // BindOnce because JNIEnv is thread specific. PostDelayedTask(FROM_HERE, PostTaskAndroid::CreateTaskTraits( - env, priority_set_explicitly, priority, may_block, - use_thread_pool, extension_id, extension_data), + env, priority, may_block, use_thread_pool, extension_id, + extension_data), BindOnce(&PostTaskAndroid::RunJavaTask, base::android::ScopedJavaGlobalRef<jobject>(task)), TimeDelta::FromMilliseconds(delay));
diff --git a/base/android/task_scheduler/post_task_android.h b/base/android/task_scheduler/post_task_android.h index c15c822..f097196 100644 --- a/base/android/task_scheduler/post_task_android.h +++ b/base/android/task_scheduler/post_task_android.h
@@ -24,7 +24,6 @@ static TaskTraits CreateTaskTraits( JNIEnv* env, - jboolean priority_set_explicitly, jint priority, jboolean may_block, jboolean use_thread_pool,
diff --git a/base/android/task_scheduler/task_runner_android.cc b/base/android/task_scheduler/task_runner_android.cc index d1a5e4e1..ca18d20b 100644 --- a/base/android/task_scheduler/task_runner_android.cc +++ b/base/android/task_scheduler/task_runner_android.cc
@@ -16,15 +16,13 @@ jlong JNI_TaskRunnerImpl_Init( JNIEnv* env, jint task_runner_type, - jboolean priority_set_explicitly, jint priority, jboolean may_block, jboolean thread_pool, jbyte extension_id, const base::android::JavaParamRef<jbyteArray>& extension_data) { TaskTraits task_traits = PostTaskAndroid::CreateTaskTraits( - env, priority_set_explicitly, priority, may_block, thread_pool, - extension_id, extension_data); + env, priority, may_block, thread_pool, extension_id, extension_data); scoped_refptr<TaskRunner> task_runner; switch (static_cast<TaskRunnerType>(task_runner_type)) { case TaskRunnerType::BASE:
diff --git a/base/mac/scoped_block.h b/base/mac/scoped_block.h index 10ab4b4e..4011f9ab 100644 --- a/base/mac/scoped_block.h +++ b/base/mac/scoped_block.h
@@ -10,9 +10,7 @@ #include "base/mac/scoped_typeref.h" #if defined(__has_feature) && __has_feature(objc_arc) -#define BASE_MAC_BRIDGE_CAST(TYPE, VALUE) (__bridge TYPE)(VALUE) -#else -#define BASE_MAC_BRIDGE_CAST(TYPE, VALUE) VALUE +#error "Cannot include base/mac/scoped_block.h in file built with ARC." #endif namespace base { @@ -23,13 +21,8 @@ template <typename B> struct ScopedBlockTraits { static B InvalidValue() { return nullptr; } - static B Retain(B block) { - return BASE_MAC_BRIDGE_CAST( - B, Block_copy(BASE_MAC_BRIDGE_CAST(const void*, block))); - } - static void Release(B block) { - Block_release(BASE_MAC_BRIDGE_CAST(const void*, block)); - } + static B Retain(B block) { return Block_copy(block); } + static void Release(B block) { Block_release(block); } }; } // namespace internal @@ -37,36 +30,9 @@ // ScopedBlock<> is patterned after ScopedCFTypeRef<>, but uses Block_copy() and // Block_release() instead of CFRetain() and CFRelease(). template <typename B> -class ScopedBlock : public ScopedTypeRef<B, internal::ScopedBlockTraits<B>> { - public: - using Traits = internal::ScopedBlockTraits<B>; - -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit ScopedBlock( - B block = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : ScopedTypeRef<B, Traits>(block, policy) {} -#else - explicit ScopedBlock(B block = Traits::InvalidValue()) - : ScopedTypeRef<B, Traits>(block, base::scoped_policy::RETAIN) {} -#endif - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(B block = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - ScopedTypeRef<B, Traits>::reset(block, policy); - } -#else - void reset(B block = Traits::InvalidValue()) { - ScopedTypeRef<B, Traits>::reset(block, base::scoped_policy::RETAIN); - } -#endif -}; +using ScopedBlock = ScopedTypeRef<B, internal::ScopedBlockTraits<B>>; } // namespace mac } // namespace base -#undef BASE_MAC_BRIDGE_CAST - #endif // BASE_MAC_SCOPED_BLOCK_H_
diff --git a/base/mac/scoped_nsobject.h b/base/mac/scoped_nsobject.h index b7d1195..ddcfa896 100644 --- a/base/mac/scoped_nsobject.h +++ b/base/mac/scoped_nsobject.h
@@ -16,10 +16,12 @@ #include "base/compiler_specific.h" #include "base/mac/scoped_typeref.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -@class NSAutoreleasePool; +#if defined(__has_feature) && __has_feature(objc_arc) +#error "Cannot include base/mac/scoped_nsobject.h in file built with ARC." #endif +@class NSAutoreleasePool; + namespace base { // scoped_nsobject<> is patterned after std::unique_ptr<>, but maintains @@ -40,39 +42,14 @@ // NSAutoreleasePool; for Objective-C(++) code use @autoreleasepool instead. We // check for bad uses of scoped_nsobject and NSAutoreleasePool at compile time // with a template specialization (see below). -// -// If Automatic Reference Counting (aka ARC) is enabled then the ownership -// policy is not controllable by the user as ARC make it really difficult to -// transfer ownership (the reference passed to scoped_nsobject constructor is -// sunk by ARC and __attribute((ns_consumed)) appears to not work correctly -// with Objective-C++ see https://llvm.org/bugs/show_bug.cgi?id=27887). Due to -// that, the policy is always to |RETAIN| when using ARC. namespace internal { -BASE_EXPORT id ScopedNSProtocolTraitsRetain(__unsafe_unretained id obj) - __attribute((ns_returns_not_retained)); -BASE_EXPORT id ScopedNSProtocolTraitsAutoRelease(__unsafe_unretained id obj) - __attribute((ns_returns_not_retained)); -BASE_EXPORT void ScopedNSProtocolTraitsRelease(__unsafe_unretained id obj); - -// Traits for ScopedTypeRef<>. As this class may be compiled from file with -// Automatic Reference Counting enable or not all methods have annotation to -// enforce the same code generation in both case (in particular, the Retain -// method uses ns_returns_not_retained to prevent ARC to insert a -release -// call on the returned value and thus defeating the -retain). template <typename NST> struct ScopedNSProtocolTraits { - static NST InvalidValue() __attribute((ns_returns_not_retained)) { - return nil; - } - static NST Retain(__unsafe_unretained NST nst) - __attribute((ns_returns_not_retained)) { - return ScopedNSProtocolTraitsRetain(nst); - } - static void Release(__unsafe_unretained NST nst) { - ScopedNSProtocolTraitsRelease(nst); - } + static NST InvalidValue() { return nil; } + static NST Retain(NST nst) { return [nst retain]; } + static void Release(NST nst) { [nst release]; } }; } // namespace internal @@ -81,49 +58,11 @@ class scoped_nsprotocol : public ScopedTypeRef<NST, internal::ScopedNSProtocolTraits<NST>> { public: - using Traits = internal::ScopedNSProtocolTraits<NST>; - -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit constexpr scoped_nsprotocol( - NST object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : ScopedTypeRef<NST, Traits>(object, policy) {} -#else - explicit constexpr scoped_nsprotocol(NST object = Traits::InvalidValue()) - : ScopedTypeRef<NST, Traits>(object, base::scoped_policy::RETAIN) {} -#endif - - scoped_nsprotocol(const scoped_nsprotocol<NST>& that) - : ScopedTypeRef<NST, Traits>(that) {} - - template <typename NSR> - explicit scoped_nsprotocol(const scoped_nsprotocol<NSR>& that_as_subclass) - : ScopedTypeRef<NST, Traits>(that_as_subclass) {} - - scoped_nsprotocol(scoped_nsprotocol<NST>&& that) - : ScopedTypeRef<NST, Traits>(std::move(that)) {} - - scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) { - ScopedTypeRef<NST, Traits>::operator=(that); - return *this; - } - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(NST object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - ScopedTypeRef<NST, Traits>::reset(object, policy); - } -#else - void reset(NST object = Traits::InvalidValue()) { - ScopedTypeRef<NST, Traits>::reset(object, base::scoped_policy::RETAIN); - } -#endif + using ScopedTypeRef<NST, + internal::ScopedNSProtocolTraits<NST>>::ScopedTypeRef; // Shift reference to the autorelease pool to be released later. - NST autorelease() __attribute((ns_returns_not_retained)) { - return internal::ScopedNSProtocolTraitsAutoRelease(this->release()); - } + NST autorelease() { return [this->release() autorelease]; } }; // Free functions @@ -145,93 +84,17 @@ template <typename NST> class scoped_nsobject : public scoped_nsprotocol<NST*> { public: - using Traits = typename scoped_nsprotocol<NST*>::Traits; + using scoped_nsprotocol<NST*>::scoped_nsprotocol; -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit constexpr scoped_nsobject( - NST* object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : scoped_nsprotocol<NST*>(object, policy) {} -#else - explicit constexpr scoped_nsobject(NST* object = Traits::InvalidValue()) - : scoped_nsprotocol<NST*>(object) {} -#endif - - scoped_nsobject(const scoped_nsobject<NST>& that) - : scoped_nsprotocol<NST*>(that) {} - - template <typename NSR> - explicit scoped_nsobject(const scoped_nsobject<NSR>& that_as_subclass) - : scoped_nsprotocol<NST*>(that_as_subclass) {} - - scoped_nsobject(scoped_nsobject<NST>&& that) - : scoped_nsprotocol<NST*>(std::move(that)) {} - - scoped_nsobject& operator=(const scoped_nsobject<NST>& that) { - scoped_nsprotocol<NST*>::operator=(that); - return *this; - } - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(NST* object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - scoped_nsprotocol<NST*>::reset(object, policy); - } -#else - void reset(NST* object = Traits::InvalidValue()) { - scoped_nsprotocol<NST*>::reset(object); - } -#endif - -#if !defined(__has_feature) || !__has_feature(objc_arc) static_assert(std::is_same<NST, NSAutoreleasePool>::value == false, "Use @autoreleasepool instead"); -#endif }; // Specialization to make scoped_nsobject<id> work. template<> class scoped_nsobject<id> : public scoped_nsprotocol<id> { public: - using Traits = typename scoped_nsprotocol<id>::Traits; - -#if !defined(__has_feature) || !__has_feature(objc_arc) - explicit constexpr scoped_nsobject( - id object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) - : scoped_nsprotocol<id>(object, policy) {} -#else - explicit constexpr scoped_nsobject(id object = Traits::InvalidValue()) - : scoped_nsprotocol<id>(object) {} -#endif - - scoped_nsobject(const scoped_nsobject<id>& that) - : scoped_nsprotocol<id>(that) {} - - template <typename NSR> - explicit scoped_nsobject(const scoped_nsobject<NSR>& that_as_subclass) - : scoped_nsprotocol<id>(that_as_subclass) {} - - scoped_nsobject(scoped_nsobject<id>&& that) - : scoped_nsprotocol<id>(std::move(that)) {} - - scoped_nsobject& operator=(const scoped_nsobject<id>& that) { - scoped_nsprotocol<id>::operator=(that); - return *this; - } - -#if !defined(__has_feature) || !__has_feature(objc_arc) - void reset(id object = Traits::InvalidValue(), - base::scoped_policy::OwnershipPolicy policy = - base::scoped_policy::ASSUME) { - scoped_nsprotocol<id>::reset(object, policy); - } -#else - void reset(id object = Traits::InvalidValue()) { - scoped_nsprotocol<id>::reset(object); - } -#endif + using scoped_nsprotocol<id>::scoped_nsprotocol; }; } // namespace base
diff --git a/base/mac/scoped_nsobject.mm b/base/mac/scoped_nsobject.mm deleted file mode 100644 index 65b4031..0000000 --- a/base/mac/scoped_nsobject.mm +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "base/mac/scoped_nsobject.h" - -namespace base { -namespace internal { - -id ScopedNSProtocolTraitsRetain(id obj) { - return [obj retain]; -} - -id ScopedNSProtocolTraitsAutoRelease(id obj) { - return [obj autorelease]; -} - -void ScopedNSProtocolTraitsRelease(id obj) { - return [obj release]; -} - -} // namespace internal -} // namespace base
diff --git a/base/mac/scoped_nsobject_unittest_arc.mm b/base/mac/scoped_nsobject_unittest_arc.mm deleted file mode 100644 index 5cbf3f83..0000000 --- a/base/mac/scoped_nsobject_unittest_arc.mm +++ /dev/null
@@ -1,131 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <vector> - -#import <CoreFoundation/CoreFoundation.h> - -#include "base/logging.h" -#import "base/mac/scoped_nsobject.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -template <typename NST> -CFIndex GetRetainCount(const base::scoped_nsobject<NST>& nst) { - @autoreleasepool { - return CFGetRetainCount((__bridge CFTypeRef)nst.get()) - 1; - } -} - -#if __has_feature(objc_arc_weak) -TEST(ScopedNSObjectTestARC, DefaultPolicyIsRetain) { - __weak id o; - @autoreleasepool { - base::scoped_nsprotocol<id> p([[NSObject alloc] init]); - o = p.get(); - DCHECK_EQ(o, p.get()); - } - DCHECK_EQ(o, nil); -} -#endif - -TEST(ScopedNSObjectTestARC, ScopedNSObject) { - base::scoped_nsobject<NSObject> p1([[NSObject alloc] init]); - @autoreleasepool { - EXPECT_TRUE(p1.get()); - EXPECT_TRUE(p1.get()); - } - EXPECT_EQ(1, GetRetainCount(p1)); - EXPECT_EQ(1, GetRetainCount(p1)); - base::scoped_nsobject<NSObject> p2(p1); - @autoreleasepool { - EXPECT_EQ(p1.get(), p2.get()); - } - EXPECT_EQ(2, GetRetainCount(p1)); - p2.reset(); - EXPECT_EQ(nil, p2.get()); - EXPECT_EQ(1, GetRetainCount(p1)); - { - base::scoped_nsobject<NSObject> p3 = p1; - @autoreleasepool { - EXPECT_EQ(p1.get(), p3.get()); - } - EXPECT_EQ(2, GetRetainCount(p1)); - @autoreleasepool { - p3 = p1; - EXPECT_EQ(p1.get(), p3.get()); - } - EXPECT_EQ(2, GetRetainCount(p1)); - } - EXPECT_EQ(1, GetRetainCount(p1)); - base::scoped_nsobject<NSObject> p4; - @autoreleasepool { - p4 = base::scoped_nsobject<NSObject>(p1.get()); - } - EXPECT_EQ(2, GetRetainCount(p1)); - @autoreleasepool { - EXPECT_TRUE(p1 == p1.get()); - EXPECT_TRUE(p1 == p1); - EXPECT_FALSE(p1 != p1); - EXPECT_FALSE(p1 != p1.get()); - } - base::scoped_nsobject<NSObject> p5([[NSObject alloc] init]); - @autoreleasepool { - EXPECT_TRUE(p1 != p5); - EXPECT_TRUE(p1 != p5.get()); - EXPECT_FALSE(p1 == p5); - EXPECT_FALSE(p1 == p5.get()); - } - - base::scoped_nsobject<NSObject> p6 = p1; - EXPECT_EQ(3, GetRetainCount(p6)); - @autoreleasepool { - p6.autorelease(); - EXPECT_EQ(nil, p6.get()); - } - EXPECT_EQ(2, GetRetainCount(p1)); -} - -TEST(ScopedNSObjectTestARC, ScopedNSObjectInContainer) { - base::scoped_nsobject<id> p([[NSObject alloc] init]); - @autoreleasepool { - EXPECT_TRUE(p.get()); - } - EXPECT_EQ(1, GetRetainCount(p)); - @autoreleasepool { - std::vector<base::scoped_nsobject<id>> objects; - objects.push_back(p); - EXPECT_EQ(2, GetRetainCount(p)); - @autoreleasepool { - EXPECT_EQ(p.get(), objects[0].get()); - } - objects.push_back(base::scoped_nsobject<id>([[NSObject alloc] init])); - @autoreleasepool { - EXPECT_TRUE(objects[1].get()); - } - EXPECT_EQ(1, GetRetainCount(objects[1])); - } - EXPECT_EQ(1, GetRetainCount(p)); -} - -TEST(ScopedNSObjectTestARC, ScopedNSObjectFreeFunctions) { - base::scoped_nsobject<id> p1([[NSObject alloc] init]); - id o1 = p1.get(); - EXPECT_TRUE(o1 == p1); - EXPECT_FALSE(o1 != p1); - base::scoped_nsobject<id> p2([[NSObject alloc] init]); - EXPECT_TRUE(o1 != p2); - EXPECT_FALSE(o1 == p2); - id o2 = p2.get(); - swap(p1, p2); - EXPECT_EQ(o2, p1.get()); - EXPECT_EQ(o1, p2.get()); -} - -} // namespace
diff --git a/base/mac/scoped_typeref.h b/base/mac/scoped_typeref.h index dd9841d734..3bec05f 100644 --- a/base/mac/scoped_typeref.h +++ b/base/mac/scoped_typeref.h
@@ -54,7 +54,7 @@ typedef T element_type; explicit constexpr ScopedTypeRef( - __unsafe_unretained T object = Traits::InvalidValue(), + T object = Traits::InvalidValue(), base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) : object_(object) { if (object_ && policy == base::scoped_policy::RETAIN) @@ -97,7 +97,7 @@ return &object_; } - void reset(__unsafe_unretained T object = Traits::InvalidValue(), + void reset(T object = Traits::InvalidValue(), base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) { if (object && policy == base::scoped_policy::RETAIN) @@ -107,16 +107,16 @@ object_ = object; } - bool operator==(__unsafe_unretained T that) const { return object_ == that; } + bool operator==(T that) const { return object_ == that; } - bool operator!=(__unsafe_unretained T that) const { return object_ != that; } + bool operator!=(T that) const { return object_ != that; } - operator T() const __attribute((ns_returns_not_retained)) { return object_; } + operator T() const { return object_; } - T get() const __attribute((ns_returns_not_retained)) { return object_; } + T get() const { return object_; } void swap(ScopedTypeRef& that) { - __unsafe_unretained T temp = that.object_; + T temp = that.object_; that.object_ = object_; object_ = temp; } @@ -124,14 +124,14 @@ // ScopedTypeRef<>::release() is like std::unique_ptr<>::release. It is NOT // a wrapper for Release(). To force a ScopedTypeRef<> object to call // Release(), use ScopedTypeRef<>::reset(). - T release() __attribute((ns_returns_not_retained)) WARN_UNUSED_RESULT { - __unsafe_unretained T temp = object_; + T release() WARN_UNUSED_RESULT { + T temp = object_; object_ = Traits::InvalidValue(); return temp; } private: - __unsafe_unretained T object_; + T object_; }; } // namespace base
diff --git a/base/memory/shared_memory_mapping.cc b/base/memory/shared_memory_mapping.cc index 8426fa8..0c9c0f8a1 100644 --- a/base/memory/shared_memory_mapping.cc +++ b/base/memory/shared_memory_mapping.cc
@@ -34,21 +34,18 @@ SharedMemoryMapping::SharedMemoryMapping() = default; SharedMemoryMapping::SharedMemoryMapping(SharedMemoryMapping&& mapping) noexcept - : memory_(mapping.memory_), + : memory_(std::exchange(mapping.memory_, nullptr)), size_(mapping.size_), mapped_size_(mapping.mapped_size_), - guid_(mapping.guid_) { - mapping.memory_ = nullptr; -} + guid_(mapping.guid_) {} SharedMemoryMapping& SharedMemoryMapping::operator=( SharedMemoryMapping&& mapping) noexcept { Unmap(); - memory_ = mapping.memory_; + memory_ = std::exchange(mapping.memory_, nullptr); size_ = mapping.size_; mapped_size_ = mapping.mapped_size_; guid_ = mapping.guid_; - mapping.memory_ = nullptr; return *this; }
diff --git a/base/task/post_job.cc b/base/task/post_job.cc index d1f3f23d..8de9115 100644 --- a/base/task/post_job.cc +++ b/base/task/post_job.cc
@@ -134,7 +134,7 @@ DCHECK_GE(internal::GetTaskPriorityForCurrentThread(), task_source_->priority_racy()) << "Join may not be called on Job with higher priority than the current " - "one."; + "thread."; UpdatePriority(internal::GetTaskPriorityForCurrentThread()); bool must_run = task_source_->WillJoin(); while (must_run) @@ -173,10 +173,8 @@ DCHECK_EQ(traits.extension_id(), TaskTraitsExtensionStorage::kInvalidExtensionId); - TaskTraits adjusted_traits = traits; - adjusted_traits.InheritPriority(internal::GetTaskPriorityForCurrentThread()); auto task_source = base::MakeRefCounted<internal::JobTaskSource>( - from_here, adjusted_traits, std::move(worker_task), + from_here, traits, std::move(worker_task), std::move(max_concurrency_callback), static_cast<internal::ThreadPoolImpl*>(ThreadPoolInstance::Get())); const bool queued =
diff --git a/base/task/post_task.cc b/base/task/post_task.cc index 439604a..c1d6d93 100644 --- a/base/task/post_task.cc +++ b/base/task/post_task.cc
@@ -32,14 +32,6 @@ const TaskTraits traits_; }; -// Returns TaskTraits based on |traits|. If TaskPriority hasn't been set -// explicitly in |traits|, the returned TaskTraits will inherit the current -// TaskPriority. -TaskTraits GetTaskTraitsWithExplicitPriority(TaskTraits traits) { - traits.InheritPriority(internal::GetTaskPriorityForCurrentThread()); - return traits; -} - TaskExecutor* GetTaskExecutorForTraits(const TaskTraits& traits) { const bool has_extension = traits.extension_id() != TaskTraitsExtensionStorage::kInvalidExtensionId; @@ -93,9 +85,8 @@ const TaskTraits& traits, OnceClosure task, TimeDelta delay) { - const TaskTraits adjusted_traits = GetTaskTraitsWithExplicitPriority(traits); - return GetTaskExecutorForTraits(adjusted_traits) - ->PostDelayedTask(from_here, adjusted_traits, std::move(task), delay); + return GetTaskExecutorForTraits(traits)->PostDelayedTask( + from_here, traits, std::move(task), delay); } bool PostTaskAndReply(const Location& from_here, @@ -128,9 +119,8 @@ TaskTraitsExtensionStorage::kInvalidExtensionId) << "Extension traits cannot be used with " "CreateUpdateableSequencedTaskRunner()."; - const TaskTraits adjusted_traits = GetTaskTraitsWithExplicitPriority(traits); return static_cast<internal::ThreadPoolImpl*>(ThreadPoolInstance::Get()) - ->CreateUpdateableSequencedTaskRunner(adjusted_traits); + ->CreateUpdateableSequencedTaskRunner(traits); } scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunner(
diff --git a/base/task/post_task_unittest.cc b/base/task/post_task_unittest.cc index fe141eb1..cbbbe66 100644 --- a/base/task/post_task_unittest.cc +++ b/base/task/post_task_unittest.cc
@@ -6,7 +6,6 @@ #include "base/bind_helpers.h" #include "base/run_loop.h" -#include "base/task/scoped_set_task_priority_for_current_thread.h" #include "base/task/task_executor.h" #include "base/task/test_task_traits_extension.h" #include "base/test/bind_test_util.h" @@ -231,21 +230,6 @@ RegisterTaskExecutor(TestTaskTraitsExtension::kExtensionId, &executor_)); } -TEST_F(PostTaskTestWithExecutor, PriorityInherited) { - internal::ScopedSetTaskPriorityForCurrentThread scoped_priority( - TaskPriority::BEST_EFFORT); - TaskTraits traits = {TestExtensionBoolTrait()}; - TaskTraits traits_with_inherited_priority = traits; - traits_with_inherited_priority.InheritPriority(TaskPriority::BEST_EFFORT); - EXPECT_FALSE(traits_with_inherited_priority.priority_set_explicitly()); - EXPECT_CALL(executor_, - PostDelayedTaskMock(_, traits_with_inherited_priority, _, _)) - .Times(1); - EXPECT_TRUE(PostTask(FROM_HERE, traits, DoNothing())); - EXPECT_TRUE(executor_.runner()->HasPendingTask()); - executor_.runner()->ClearPendingTasks(); -} - namespace { class FlagOnDelete {
diff --git a/base/task/scoped_set_task_priority_for_current_thread.h b/base/task/scoped_set_task_priority_for_current_thread.h index 713775f..b94d27f 100644 --- a/base/task/scoped_set_task_priority_for_current_thread.h +++ b/base/task/scoped_set_task_priority_for_current_thread.h
@@ -26,7 +26,7 @@ }; // Returns the priority of the task running on the current thread, -// or TaskPriority::USER_VISIBLE if none. +// or TaskPriority::USER_BLOCKING by default if none. BASE_EXPORT TaskPriority GetTaskPriorityForCurrentThread(); } // namespace internal
diff --git a/base/task/task_features.cc b/base/task/task_features.cc index cda0808..6e6a1d1 100644 --- a/base/task/task_features.cc +++ b/base/task/task_features.cc
@@ -25,7 +25,4 @@ const Feature kUseFiveMinutesThreadReclaimTime = { "UseFiveMinutesThreadReclaimTime", base::FEATURE_DISABLED_BY_DEFAULT}; -const Feature kNoPriorityInheritanceFromThreadPool{ - "NoPriorityInheritanceFromThreadPool", base::FEATURE_ENABLED_BY_DEFAULT}; - } // namespace base
diff --git a/base/task/task_features.h b/base/task/task_features.h index 39d5680..6763cab 100644 --- a/base/task/task_features.h +++ b/base/task/task_features.h
@@ -40,12 +40,6 @@ // minutes, instead of 30 seconds. extern const BASE_EXPORT Feature kUseFiveMinutesThreadReclaimTime; -// Under this feature, the current default of inheriting priority when posting -// from the ThreadPool is disabled. -// Details @ -// https://docs.google.com/document/d/13PIBPuSPJbrgHAgyRbY22EWAfH2narnxpa_CgBmZbSY -extern const BASE_EXPORT Feature kNoPriorityInheritanceFromThreadPool; - } // namespace base #endif // BASE_TASK_TASK_FEATURES_H_
diff --git a/base/task/task_traits.cc b/base/task/task_traits.cc index 472d437..4ebb87a7 100644 --- a/base/task/task_traits.cc +++ b/base/task/task_traits.cc
@@ -12,17 +12,6 @@ namespace base { -// The state of |FeatureList::IsEnabled(kNoPriorityInheritanceFromThreadPool)| -// as controlled by intenal::SetNoPriorityInheritanceFromThreadPool(). -bool g_no_priority_inheritance_from_thread_pool = false; - -void TaskTraits::InheritPriority(TaskPriority priority) { - if (priority_set_explicitly() || g_no_priority_inheritance_from_thread_pool) - return; - - priority_ = static_cast<uint8_t>(priority); -} - const char* TaskPriorityToString(TaskPriority task_priority) { switch (task_priority) { case TaskPriority::BEST_EFFORT: @@ -61,10 +50,4 @@ return os; } -namespace internal { -void SetNoPriorityInheritanceFromThreadPool() { - g_no_priority_inheritance_from_thread_pool = true; -} -} // namespace internal - } // namespace base
diff --git a/base/task/task_traits.h b/base/task/task_traits.h index 5755418..04f6343 100644 --- a/base/task/task_traits.h +++ b/base/task/task_traits.h
@@ -66,6 +66,12 @@ // Example: // - Loading and rendering a web page after the user clicks a link. // - Sorting suggestions after the user types a character in the omnibox. + // + // This is the default TaskPriority in order for tasks to run in order by + // default and avoid unintended consequences. The only way to get a task to + // run at a higher priority than USER_BLOCKING is to coordinate with a + // higher-level scheduler (contact scheduler-dev@chromium.org for such use + // cases). USER_BLOCKING, // This will always be equal to the highest priority available. @@ -198,18 +204,22 @@ ValidTrait(ThreadPool); }; - // Invoking this constructor without arguments produces TaskTraits that are - // appropriate for tasks that + // Invoking this constructor without arguments produces default TaskTraits + // that are appropriate for tasks that // (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()), - // (2) prefer inheriting the current priority to specifying their own, and + // (2) pertain to user-blocking activity, + // (explicitly or implicitly by having an ordering dependency with a + // component that does) // (3) can either block shutdown or be skipped on shutdown - // (ThreadPoolInstance implementation is free to choose a fitting - // default). + // (the task recipient is free to choose a fitting default). // - // To get TaskTraits for tasks that require stricter guarantees and/or know - // the specific TaskPriority appropriate for them, provide arguments of type - // TaskPriority, TaskShutdownBehavior, ThreadPolicy, MayBlock and/or - // WithBaseSyncPrimitives in any order to the constructor. + // To get TaskTraits for tasks that have more precise traits: provide any + // combination of ValidTrait's as arguments to this constructor. + // + // Note: When posting to well-known threads (e.g. UI/IO), default traits are + // almost always what you want unless you know for sure the task being posted + // has no explicit/implicit ordering dependency with anything else running at + // default (USER_BLOCKING) priority. // // E.g. // constexpr base::TaskTraits default_traits = {}; @@ -230,12 +240,8 @@ trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>{}, args...)), priority_( - static_cast<uint8_t>( - trait_helpers::GetEnum<TaskPriority, - TaskPriority::USER_BLOCKING>(args...)) | - (trait_helpers::HasTrait<TaskPriority, ArgTypes...>() - ? kIsExplicitFlag - : 0)), + trait_helpers::GetEnum<TaskPriority, TaskPriority::USER_BLOCKING>( + args...)), shutdown_behavior_( static_cast<uint8_t>( trait_helpers::GetEnum<TaskShutdownBehavior, @@ -273,22 +279,10 @@ } // Sets the priority of tasks with these traits to |priority|. - void UpdatePriority(TaskPriority priority) { - priority_ = static_cast<uint8_t>(priority) | kIsExplicitFlag; - } - - // Sets the priority to |priority| if it wasn't explicitly set before. - void InheritPriority(TaskPriority priority); - - // Returns true if the priority was set explicitly. - constexpr bool priority_set_explicitly() const { - return priority_ & kIsExplicitFlag; - } + void UpdatePriority(TaskPriority priority) { priority_ = priority; } // Returns the priority of tasks with these traits. - constexpr TaskPriority priority() const { - return static_cast<TaskPriority>(priority_ & ~kIsExplicitFlag); - } + constexpr TaskPriority priority() const { return priority_; } // Returns true if the shutdown behavior was set explicitly. constexpr bool shutdown_behavior_set_explicitly() const { @@ -336,14 +330,12 @@ friend PostTaskAndroid; // For use by PostTaskAndroid. - TaskTraits(bool priority_set_explicitly, - TaskPriority priority, + TaskTraits(TaskPriority priority, bool may_block, bool use_thread_pool, TaskTraitsExtensionStorage extension) : extension_(extension), - priority_(static_cast<uint8_t>(priority) | - (priority_set_explicitly ? kIsExplicitFlag : 0)), + priority_(priority), shutdown_behavior_( static_cast<uint8_t>(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)), thread_policy_(static_cast<uint8_t>(ThreadPolicy::PREFER_BACKGROUND)), @@ -368,7 +360,7 @@ // Ordered for packing. TaskTraitsExtensionStorage extension_; - uint8_t priority_; + TaskPriority priority_; uint8_t shutdown_behavior_; uint8_t thread_policy_; bool may_block_; @@ -390,13 +382,6 @@ std::ostream& os, const TaskShutdownBehavior& shutdown_behavior); -namespace internal { -// Enables the kNoPriorityInheritanceFromThreadPool experimental feature. Must -// be done statically when the ThreadPoolImpl is initialized because it's racy -// to check the state later. -void SetNoPriorityInheritanceFromThreadPool(); -} // namespace internal - } // namespace base #endif // BASE_TASK_TASK_TRAITS_H_
diff --git a/base/task/task_traits_unittest.cc b/base/task/task_traits_unittest.cc index b695831..7a1ee8d2 100644 --- a/base/task/task_traits_unittest.cc +++ b/base/task/task_traits_unittest.cc
@@ -10,7 +10,6 @@ TEST(TaskTraitsTest, Default) { constexpr TaskTraits traits = {}; - EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_FALSE(traits.shutdown_behavior_set_explicitly()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); @@ -22,7 +21,6 @@ TEST(TaskTraitsTest, TaskPriority) { constexpr TaskTraits traits = {TaskPriority::BEST_EFFORT}; - EXPECT_TRUE(traits.priority_set_explicitly()); EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority()); EXPECT_FALSE(traits.shutdown_behavior_set_explicitly()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); @@ -35,7 +33,6 @@ TEST(TaskTraitsTest, TaskShutdownBehavior) { constexpr TaskTraits traits = {ThreadPool(), TaskShutdownBehavior::BLOCK_SHUTDOWN}; - EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_TRUE(traits.shutdown_behavior_set_explicitly()); EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior()); @@ -47,7 +44,6 @@ TEST(TaskTraitsTest, ThreadPolicy) { constexpr TaskTraits traits = {ThreadPolicy::MUST_USE_FOREGROUND}; - EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_FALSE(traits.shutdown_behavior_set_explicitly()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); @@ -59,7 +55,6 @@ TEST(TaskTraitsTest, MayBlock) { constexpr TaskTraits traits = {MayBlock()}; - EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_FALSE(traits.shutdown_behavior_set_explicitly()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); @@ -71,7 +66,6 @@ TEST(TaskTraitsTest, WithBaseSyncPrimitives) { constexpr TaskTraits traits = {WithBaseSyncPrimitives()}; - EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_FALSE(traits.shutdown_behavior_set_explicitly()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); @@ -84,34 +78,14 @@ TEST(TaskTraitsTest, UpdatePriority) { { TaskTraits traits = {}; - EXPECT_FALSE(traits.priority_set_explicitly()); traits.UpdatePriority(TaskPriority::BEST_EFFORT); EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority()); - EXPECT_TRUE(traits.priority_set_explicitly()); } { TaskTraits traits = {TaskPriority::USER_VISIBLE}; - EXPECT_TRUE(traits.priority_set_explicitly()); traits.UpdatePriority(TaskPriority::BEST_EFFORT); EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority()); - EXPECT_TRUE(traits.priority_set_explicitly()); - } -} - -TEST(TaskTraitsTest, InheritPriority) { - { - TaskTraits traits = {}; - traits.InheritPriority(TaskPriority::BEST_EFFORT); - EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority()); - EXPECT_FALSE(traits.priority_set_explicitly()); - } - - { - TaskTraits traits = {TaskPriority::USER_VISIBLE}; - traits.InheritPriority(TaskPriority::BEST_EFFORT); - EXPECT_EQ(TaskPriority::USER_VISIBLE, traits.priority()); - EXPECT_TRUE(traits.priority_set_explicitly()); } } @@ -119,7 +93,6 @@ constexpr TaskTraits traits = { TaskPriority::BEST_EFFORT, TaskShutdownBehavior::BLOCK_SHUTDOWN, ThreadPolicy::MUST_USE_FOREGROUND, MayBlock(), WithBaseSyncPrimitives()}; - EXPECT_TRUE(traits.priority_set_explicitly()); EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority()); EXPECT_TRUE(traits.shutdown_behavior_set_explicitly()); EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior()); @@ -137,8 +110,6 @@ EXPECT_EQ(traits, traits_copy); - EXPECT_EQ(traits.priority_set_explicitly(), - traits_copy.priority_set_explicitly()); EXPECT_EQ(traits.priority(), traits_copy.priority()); EXPECT_EQ(traits.shutdown_behavior_set_explicitly(), traits_copy.shutdown_behavior_set_explicitly());
diff --git a/base/task/thread_pool.cc b/base/task/thread_pool.cc index 23f6dfd..f5635d0e 100644 --- a/base/task/thread_pool.cc +++ b/base/task/thread_pool.cc
@@ -30,14 +30,6 @@ const TaskTraits traits_; }; -// Returns TaskTraits based on |traits|. If TaskPriority hasn't been set -// explicitly in |traits|, the returned TaskTraits will inherit the current -// TaskPriority. -TaskTraits GetTaskTraitsWithExplicitPriority(TaskTraits traits) { - traits.InheritPriority(internal::GetTaskPriorityForCurrentThread()); - return traits; -} - internal::ThreadPoolImpl* GetThreadPoolImpl() { auto* instance = ThreadPoolInstance::Get(); DCHECK(instance) @@ -84,8 +76,7 @@ const TaskTraits& traits, OnceClosure task, TimeDelta delay) { - const TaskTraits adjusted_traits = GetTaskTraitsWithExplicitPriority(traits); - return GetThreadPoolImpl()->PostDelayedTask(from_here, adjusted_traits, + return GetThreadPoolImpl()->PostDelayedTask(from_here, traits, std::move(task), delay); } @@ -113,9 +104,7 @@ // static scoped_refptr<UpdateableSequencedTaskRunner> ThreadPool::CreateUpdateableSequencedTaskRunner(const TaskTraits& traits) { - const TaskTraits adjusted_traits = GetTaskTraitsWithExplicitPriority(traits); - return GetThreadPoolImpl()->CreateUpdateableSequencedTaskRunner( - adjusted_traits); + return GetThreadPoolImpl()->CreateUpdateableSequencedTaskRunner(traits); } // static
diff --git a/base/task/thread_pool/thread_pool_impl.cc b/base/task/thread_pool/thread_pool_impl.cc index 1a4ea6bc..f24cbe0 100644 --- a/base/task/thread_pool/thread_pool_impl.cc +++ b/base/task/thread_pool/thread_pool_impl.cc
@@ -118,9 +118,6 @@ internal::InitializeThreadPrioritiesFeature(); - if (FeatureList::IsEnabled(kNoPriorityInheritanceFromThreadPool)) - internal::SetNoPriorityInheritanceFromThreadPool(); - // The max number of concurrent BEST_EFFORT tasks is |kMaxBestEffortTasks|, // unless the max number of foreground threads is lower. const int max_best_effort_tasks =
diff --git a/base/util/memory_pressure/system_memory_pressure_evaluator_chromeos.cc b/base/util/memory_pressure/system_memory_pressure_evaluator_chromeos.cc index aeb3506..2cc13d2 100644 --- a/base/util/memory_pressure/system_memory_pressure_evaluator_chromeos.cc +++ b/base/util/memory_pressure/system_memory_pressure_evaluator_chromeos.cc
@@ -28,7 +28,7 @@ namespace chromeos { const base::Feature kCrOSUserSpaceLowMemoryNotification{ - "kCrOSUserSpaceLowMemoryNotification", base::FEATURE_DISABLED_BY_DEFAULT}; + "CrOSUserSpaceLowMemoryNotification", base::FEATURE_DISABLED_BY_DEFAULT}; namespace { // Pointer to the SystemMemoryPressureEvaluator used by TabManagerDelegate for
diff --git a/build/check_gn_headers_whitelist.txt b/build/check_gn_headers_whitelist.txt index d65e232..fe4406b 100644 --- a/build/check_gn_headers_whitelist.txt +++ b/build/check_gn_headers_whitelist.txt
@@ -30,6 +30,7 @@ chrome/browser/chromeos/certificate_provider/sign_requests.h chrome/browser/chromeos/certificate_provider/thread_safe_certificate_map.h chrome/browser/chromeos/login/signin/oauth2_login_manager.h +chrome/browser/chromeos/login/signin/oauth2_login_verifier.h chrome/browser/chromeos/login/signin/oauth2_token_fetcher.h chrome/browser/chromeos/profiles/profile_helper.h chrome/browser/chromeos/settings/cros_settings.h
diff --git a/build/config/ios/ios_test_runner_config.gni b/build/config/ios/ios_test_runner_config.gni new file mode 100644 index 0000000..f28533b --- /dev/null +++ b/build/config/ios/ios_test_runner_config.gni
@@ -0,0 +1,10 @@ +# Copyright 2020 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. + +declare_args() { + # Controls what version of xcode to use for iOS testers. Note that this + # version should be in alignment with the swarming named caches used by tests, + # defined under src/testing/buildbot/ to avoid performance issues. + test_runner_xcode_build_version = "11c29" +}
diff --git a/build/config/ios/ios_test_runner_wrapper.gni b/build/config/ios/ios_test_runner_wrapper.gni new file mode 100644 index 0000000..572818a --- /dev/null +++ b/build/config/ios/ios_test_runner_wrapper.gni
@@ -0,0 +1,124 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ios/ios_sdk.gni") +import("//build/config/ios/ios_test_runner_config.gni") +import("//build/util/generate_wrapper.gni") + +# Invokes generate_wrapper to create an executable script wrapping iOS' +# run.py with baked in arguments. Only takes effect when test entry in +# gn_isolate_map.pyl is updated to type="generated_script" with script +# set to the wrapper output path. +# +# Arguments: +# +# data +# (optional, default [ "//ios/build/bots/scripts/" ]) list of files or +# directories required to run target +# +# data_deps +# (optional) list of target non-linked labels +# +# deps +# (optional) list of files or directories required to run target +# +# executable_args +# (optional) a list of string arguments to pass to run.py +# +# retries +# (optional, default 3) number of retry attempts +# +# shards +# (optional, default 1) number of shards to execute tests in parallel. not +# the same as swamring shards. +# +# wrapper_output_name +# (optional, default "run_${target_name}") name of the wrapper script +# +template("ios_test_runner_wrapper") { + generate_wrapper(target_name) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "executable_args", + "retries", + "shards", + "wrapper_output_name", + ]) + testonly = true + + # iOS main test runner + executable = "//ios/build/bots/scripts/run.py" + + # arguments passed to run.py + if (!defined(executable_args)) { + executable_args = [] + } + + _rebased_mac_toolchain = rebase_path("//mac_toolchain", root_build_dir) + _rebased_xcode_path = rebase_path("//Xcode.app", root_build_dir) + + # --out-dir argument is specified in gn_isolate_map.pyl because + # ${ISOLATED_OUTDIR} doesn't get resolved through this wrapper. + executable_args += [ + "--xcode-path", + "@WrappedPath(${_rebased_xcode_path})", + "--mac-toolchain-cmd", + "@WrappedPath(${_rebased_mac_toolchain})", + ] + + executable_args += [ + "--xcode-build-version", + test_runner_xcode_build_version, + ] + + # Default retries to 3 + if (!defined(retries)) { + retries = 3 + } + executable_args += [ + "--retries", + "${retries}", + ] + + # Default shards to 1 + if (!defined(shards)) { + shards = 1 + } + executable_args += [ + "--shards", + "${shards}", + ] + + # test runner relies on iossim if use_ios_simulator (defined in ios_sdk.gni) + if (use_ios_simulator) { + _rebased_root_build_dir = rebase_path("${root_build_dir}", root_build_dir) + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ "//testing/iossim" ] + + executable_args += [ + "--iossim", + "@WrappedPath(${_rebased_root_build_dir}/iossim)", + ] + } + + # wrapper script output name and path + if (!defined(wrapper_output_name)) { + _wrapper_output_name = "run_${target_name}" + } else { + _wrapper_output_name = wrapper_output_name + } + wrapper_script = "${root_build_dir}/bin/${_wrapper_output_name}" + + # ios/build/bot/scripts/*.py needs to be present for test runner + if (!defined(data)) { + data = [] + } + data += [ "//ios/build/bots/scripts/" ] + } +}
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni index a1d62f8d..6661a41 100644 --- a/build/config/ios/rules.gni +++ b/build/config/ios/rules.gni
@@ -1781,7 +1781,12 @@ output_name = _xctest_output product_type = _ios_xcode_xctest_bundle_id host_target = _host_target - xcode_test_application_name = _host_output + + # TODO(crbug.com/1056328) The change in output name results in a mismatch + # between this value and the ios_app_bundle target name. To mitigate, this + # has been modified to _host_target. It can be reverted to _host_output + # once the output_name is reverted. + xcode_test_application_name = _host_target deps = [ _xctest_module_target ] } @@ -1971,10 +1976,14 @@ "xcode_test_application_name must be defined for $target_name") _xcuitest_target = target_name + if (defined(invoker.output_name)) { + _xcuitest_target = invoker.output_name + } + _xcuitest_runner_target = _xcuitest_target + "_runner" _xcuitest_module_target = _xcuitest_target + "_module" - group(_xcuitest_target) { + group(target_name) { testonly = true deps = [ ":$_xcuitest_runner_target" ]
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 1d11899..2b00bbc 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200303.2.1 \ No newline at end of file +0.20200303.3.1 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 1d11899..2b00bbc 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200303.2.1 \ No newline at end of file +0.20200303.3.1 \ No newline at end of file
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h index 46c3b656..f3c4640 100644 --- a/cc/input/input_handler.h +++ b/cc/input/input_handler.h
@@ -183,14 +183,20 @@ // accumulated within this ScrollBegin() scope is reported in the return // value's |accumulated_overscroll| field. Should only be called if // ScrollBegin() returned SCROLL_STARTED. + // + // Is a no-op if no scroller was latched to in ScrollBegin and returns an + // empty-initialized InputHandlerScrollResult. + // // |delayed_by| is the delay from the event that caused the scroll. This is // taken into account when determining the duration of the animation if one // is created. virtual InputHandlerScrollResult ScrollUpdate(ScrollState* scroll_state, base::TimeDelta delayed_by) = 0; - // Stop scrolling the selected layer. Should only be called if ScrollBegin() - // returned SCROLL_STARTED. Snap to a snap position if |should_snap| is true. + // Stop scrolling the selected layer. Must be called only if ScrollBegin() + // returned SCROLL_STARTED. No-op if ScrollBegin wasn't called or didn't + // result in a successful scroll latch. Snap to a snap position if + // |should_snap| is true. virtual void ScrollEnd(bool should_snap) = 0; virtual InputHandlerPointerResult MouseMoveAt(
diff --git a/cc/metrics/compositor_timing_history.cc b/cc/metrics/compositor_timing_history.cc index 91e8fc8..05c36c2 100644 --- a/cc/metrics/compositor_timing_history.cc +++ b/cc/metrics/compositor_timing_history.cc
@@ -54,9 +54,6 @@ base::TimeDelta duration) = 0; virtual void AddDrawIntervalWithCustomPropertyAnimations( base::TimeDelta duration) = 0; - - // Synchronization measurements - virtual void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) = 0; }; namespace { @@ -384,11 +381,6 @@ UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Renderer.SwapToAckLatency", duration); } - - void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override { - UMA_HISTOGRAM_CUSTOM_TIMES_VSYNC_ALIGNED( - "Scheduling.Renderer.MainAndImplFrameTimeDelta", delta); - } }; class BrowserUMAReporter : public CompositorTimingHistory::UMAReporter { @@ -462,8 +454,6 @@ UMA_HISTOGRAM_CUSTOM_TIMES_DURATION("Scheduling.Browser.SwapToAckLatency", duration); } - - void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override {} }; class NullUMAReporter : public CompositorTimingHistory::UMAReporter { @@ -492,7 +482,6 @@ void AddActivateDuration(base::TimeDelta duration) override {} void AddDrawDuration(base::TimeDelta duration) override {} void AddSubmitToAckLatency(base::TimeDelta duration) override {} - void AddMainAndImplFrameTimeDelta(base::TimeDelta delta) override {} }; } // namespace @@ -685,13 +674,11 @@ void CompositorTimingHistory::WillBeginMainFrame( const viz::BeginFrameArgs& args) { DCHECK_EQ(base::TimeTicks(), begin_main_frame_sent_time_); - DCHECK_EQ(base::TimeTicks(), begin_main_frame_frame_time_); compositor_frame_reporting_controller_->WillBeginMainFrame(args.frame_id); begin_main_frame_on_critical_path_ = args.on_critical_path; begin_main_frame_sent_time_ = Now(); - begin_main_frame_frame_time_ = args.frame_time; did_send_begin_main_frame_ = true; SetBeginMainFrameNeededContinuously(true); @@ -709,7 +696,6 @@ compositor_frame_reporting_controller_->BeginMainFrameAborted(id); base::TimeTicks begin_main_frame_end_time = Now(); DidBeginMainFrame(begin_main_frame_end_time); - begin_main_frame_frame_time_ = base::TimeTicks(); } void CompositorTimingHistory::NotifyReadyToCommit( @@ -728,7 +714,6 @@ } void CompositorTimingHistory::DidCommit() { - DCHECK_EQ(base::TimeTicks(), pending_tree_main_frame_time_); DCHECK_EQ(pending_tree_creation_time_, base::TimeTicks()); DCHECK_NE(commit_start_time_, base::TimeTicks()); @@ -741,8 +726,6 @@ pending_tree_is_impl_side_ = false; pending_tree_creation_time_ = begin_main_frame_end_time; - pending_tree_main_frame_time_ = begin_main_frame_frame_time_; - begin_main_frame_frame_time_ = base::TimeTicks(); } void CompositorTimingHistory::DidBeginMainFrame( @@ -883,13 +866,7 @@ if (enabled_) activate_duration_history_.InsertSample(activate_duration); - // The synchronous compositor doesn't necessarily draw every new active tree. - if (!using_synchronous_renderer_compositor_) - DCHECK_EQ(base::TimeTicks(), active_tree_main_frame_time_); - active_tree_main_frame_time_ = pending_tree_main_frame_time_; - activate_start_time_ = base::TimeTicks(); - pending_tree_main_frame_time_ = base::TimeTicks(); } void CompositorTimingHistory::WillDraw() { @@ -897,12 +874,7 @@ draw_start_time_ = Now(); } -void CompositorTimingHistory::DrawAborted() { - active_tree_main_frame_time_ = base::TimeTicks(); -} - void CompositorTimingHistory::DidDraw(bool used_new_active_tree, - base::TimeTicks impl_frame_time, size_t composited_animations_count, size_t main_thread_animations_count, bool current_frame_had_raf, @@ -942,17 +914,6 @@ draw_end_time_prev_ = draw_end_time; if (used_new_active_tree) { - DCHECK_NE(base::TimeTicks(), active_tree_main_frame_time_); - base::TimeDelta main_and_impl_delta = - impl_frame_time - active_tree_main_frame_time_; - DCHECK_GE(main_and_impl_delta, base::TimeDelta()); - TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), - "CompositorTimingHistory::DidDraw", - "active_tree_main_frame_time", active_tree_main_frame_time_, - "impl_frame_time", impl_frame_time); - uma_reporter_->AddMainAndImplFrameTimeDelta(main_and_impl_delta); - active_tree_main_frame_time_ = base::TimeTicks(); - bool current_main_frame_had_visual_update = main_thread_animations_count > 0 || current_frame_had_raf; bool previous_main_frame_had_visual_update =
diff --git a/cc/metrics/compositor_timing_history.h b/cc/metrics/compositor_timing_history.h index 613f007..55c5525b 100644 --- a/cc/metrics/compositor_timing_history.h +++ b/cc/metrics/compositor_timing_history.h
@@ -88,10 +88,8 @@ void ReadyToActivate(); void WillActivate(); void DidActivate(); - void DrawAborted(); void WillDraw(); void DidDraw(bool used_new_active_tree, - base::TimeTicks impl_frame_time, size_t composited_animations_count, size_t main_thread_animations_count, bool current_frame_had_raf, @@ -157,16 +155,13 @@ RollingTimeDeltaHistory draw_duration_history_; bool begin_main_frame_on_critical_path_; - base::TimeTicks begin_main_frame_frame_time_; base::TimeTicks begin_main_frame_sent_time_; base::TimeTicks begin_main_frame_start_time_; base::TimeTicks commit_start_time_; - base::TimeTicks pending_tree_main_frame_time_; base::TimeTicks pending_tree_creation_time_; base::TimeTicks pending_tree_ready_to_activate_time_; base::TimeTicks prepare_tiles_start_time_; base::TimeTicks activate_start_time_; - base::TimeTicks active_tree_main_frame_time_; base::TimeTicks draw_start_time_; base::TimeTicks submit_start_time_;
diff --git a/cc/metrics/compositor_timing_history_unittest.cc b/cc/metrics/compositor_timing_history_unittest.cc index 7734463c..b5b7133 100644 --- a/cc/metrics/compositor_timing_history_unittest.cc +++ b/cc/metrics/compositor_timing_history_unittest.cc
@@ -68,7 +68,7 @@ timing_history_.DidActivate(); timing_history_.WillDraw(); AdvanceNowBy(base::TimeDelta::FromMicroseconds(advance_ms)); - timing_history_.DidDraw(true, Now(), composited_animations_count, + timing_history_.DidDraw(true, composited_animations_count, main_thread_animations_count, current_frame_had_raf, next_frame_has_pending_raf, false); } @@ -85,7 +85,7 @@ timing_history_.DidActivate(); timing_history_.WillDraw(); AdvanceNowBy(base::TimeDelta::FromMicroseconds(advance_ms)); - timing_history_.DidDraw(false, Now(), composited_animations_count, + timing_history_.DidDraw(false, composited_animations_count, main_thread_animations_count, false, false, has_custom_property_animation); } @@ -148,7 +148,7 @@ AdvanceNowBy(one_second); timing_history_.WillDraw(); AdvanceNowBy(draw_duration); - timing_history_.DidDraw(true, Now(), 0, 0, false, false, false); + timing_history_.DidDraw(true, 0, 0, false, false, false); EXPECT_EQ(begin_main_frame_queue_duration, timing_history_.BeginMainFrameQueueDurationCriticalEstimate()); @@ -200,7 +200,7 @@ AdvanceNowBy(one_second); timing_history_.WillDraw(); AdvanceNowBy(draw_duration); - timing_history_.DidDraw(false, Now(), 0, 0, false, false, false); + timing_history_.DidDraw(false, 0, 0, false, false, false); EXPECT_EQ(base::TimeDelta(), timing_history_.BeginMainFrameQueueDurationCriticalEstimate());
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 326d7d92..5dd2d88 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -632,10 +632,8 @@ bool has_damage = client_->WillBeginImplFrame(begin_impl_frame_tracker_.Current()); - if (!has_damage) { + if (!has_damage) state_machine_.AbortDraw(); - compositor_timing_history_->DrawAborted(); - } } ProcessScheduledActions(); @@ -747,7 +745,6 @@ state_machine_.DidDraw(result); compositor_timing_history_->DidDraw( drawing_with_new_active_tree, - begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time, client_->CompositedAnimationsCount(), client_->MainThreadAnimationsCount(), client_->CurrentFrameHadRAF(), client_->NextFrameHasPendingRAF(), @@ -766,7 +763,6 @@ state_machine_.DidDraw(result); compositor_timing_history_->DidDraw( drawing_with_new_active_tree, - begin_impl_frame_tracker_.DangerousMethodCurrentOrLast().frame_time, client_->CompositedAnimationsCount(), client_->MainThreadAnimationsCount(), client_->CurrentFrameHadRAF(), client_->NextFrameHasPendingRAF(), @@ -856,7 +852,6 @@ // No action is actually performed, but this allows the state machine to // drain the pipeline without actually drawing. state_machine_.AbortDraw(); - compositor_timing_history_->DrawAborted(); break; } case SchedulerStateMachine::Action::BEGIN_LAYER_TREE_FRAME_SINK_CREATION:
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index c270e01..35a18b6 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2161,7 +2161,7 @@ if (GetDrawMode() == DRAW_MODE_RESOURCELESS_SOFTWARE) { metadata.is_resourceless_software_draw_with_scroll_or_animation = - IsActivelyScrolling() || mutator_host_->NeedsTickAnimations(); + IsActivelyPrecisionScrolling() || mutator_host_->NeedsTickAnimations(); } const base::flat_set<viz::SurfaceRange>& referenced_surfaces = @@ -2974,7 +2974,7 @@ return active_tree()->CurrentlyScrollingNode(); } -bool LayerTreeHostImpl::IsActivelyScrolling() const { +bool LayerTreeHostImpl::IsActivelyPrecisionScrolling() const { if (!CurrentlyScrollingNode()) return false; // On Android WebView root flings are controlled by the application, @@ -2982,7 +2982,14 @@ // are actually animating. So assume there are none. if (settings_.ignore_root_layer_flings && IsCurrentlyScrollingViewport()) return false; - return true; + + if (!last_scroll_update_state_) + return false; + + bool did_scroll_content = + did_scroll_x_for_scroll_gesture_ || did_scroll_y_for_scroll_gesture_; + return !ShouldAnimateScroll(last_scroll_update_state_.value()) && + did_scroll_content; } void LayerTreeHostImpl::CreatePendingTree() { @@ -4615,7 +4622,7 @@ if (!CurrentlyScrollingNode()) return InputHandlerScrollResult(); - last_scroll_state_ = *scroll_state; + last_scroll_update_state_ = *scroll_state; bool is_delta_percent_units = scroll_state->delta_granularity() == ui::ScrollGranularity::kScrollByPercentage; @@ -4774,13 +4781,13 @@ SnapContainerData& data = scroll_node->snap_container_data.value(); gfx::ScrollOffset current_position = GetVisualScrollOffset(*scroll_node); - DCHECK(last_scroll_state_); + DCHECK(last_scroll_update_state_); bool imprecise_wheel_scrolling = latched_scroll_type_ == InputHandler::WHEEL && - last_scroll_state_->delta_granularity() != + last_scroll_update_state_->delta_granularity() != ui::ScrollGranularity::kScrollByPrecisePixel; - gfx::ScrollOffset last_scroll_delta(last_scroll_state_->delta_x(), - last_scroll_state_->delta_y()); + gfx::ScrollOffset last_scroll_delta(last_scroll_update_state_->delta_x(), + last_scroll_update_state_->delta_y()); std::unique_ptr<SnapSelectionStrategy> strategy; @@ -4905,10 +4912,13 @@ did_scroll_y_for_scroll_gesture_ = false; scroll_animating_snap_target_ids_ = TargetSnapAreaElementIds(); latched_scroll_type_.reset(); - last_scroll_state_.reset(); + last_scroll_update_state_.reset(); } void LayerTreeHostImpl::ScrollEnd(bool should_snap) { + if (!CurrentlyScrollingNode()) + return; + // Note that if we deferred the scroll end then we should not snap. We will // snap once we deliver the deferred scroll end. if (mutator_host_->IsImplOnlyScrollAnimating()) {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index b9afa750..bfe9817 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -603,7 +603,18 @@ void QueueSwapPromiseForMainThreadScrollUpdate( std::unique_ptr<SwapPromise> swap_promise); - bool IsActivelyScrolling() const; + // Returns true if there is an active scroll in progress. "Active" here + // means that it's been latched (i.e. we have a CurrentlyScrollingNode()) but + // also that some ScrollUpdates have been received and their delta consumed + // for scrolling. These can differ significantly e.g. the page allows the + // touchstart but preventDefaults all the touchmoves. In that case, we latch + // and have a CurrentlyScrollingNode() but will never receive a ScrollUpdate. + // + // "Precision" means it's a non-animated scroll like a touchscreen or + // high-precision touchpad. The latter distinction is important for things + // like scheduling decisions which might schedule a wheel and a touch + // scrolling differently due to user perception. + bool IsActivelyPrecisionScrolling() const; virtual void SetVisible(bool visible); bool visible() const { return visible_; } @@ -1123,9 +1134,9 @@ // time a CompositorFrame is generated. gfx::Vector2dF scroll_accumulated_this_frame_; - // Tracks the last scroll state received. At the moment, this is used to infer - // the most recent scroll type and direction for scroll snapping purposes. - base::Optional<ScrollState> last_scroll_state_; + // Tracks the last scroll update state received. Used to infer the most + // recent scroll type and direction. + base::Optional<ScrollState> last_scroll_update_state_; std::vector<std::unique_ptr<SwapPromise>> swap_promises_for_main_thread_scroll_update_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 3498a93..325d04d 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1089,6 +1089,49 @@ status.main_thread_scrolling_reasons); } +// Tests that receiving ScrollUpdate and ScrollEnd calls that don't have a +// matching ScrollBegin are just dropped and are a no-op. This can happen due +// to pre-commit input deferral which causes some input events to be dropped +// before the first commit in a renderer has occurred. See the flag +// kAllowPreCommitInput and how it's used. +TEST_F(LayerTreeHostImplTest, ScrollUpdateAndEndNoOpWithoutBegin) { + SetupViewportLayersOuterScrolls(gfx::Size(100, 100), gfx::Size(1000, 1000)); + + // Simulate receiving a gesture mid-stream so that the Begin wasn't ever + // processed. This shouldn't cause any state change but we should crash or + // DCHECK. + { + EXPECT_FALSE(host_impl_->CurrentlyScrollingNode()); + host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10), + InputHandler::TOUCHSCREEN) + .get()); + host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10), + InputHandler::TOUCHSCREEN) + .get()); + EXPECT_FALSE(host_impl_->CurrentlyScrollingNode()); + host_impl_->ScrollEnd(); + } + + // Ensure a new gesture is now able to correctly scroll. + { + InputHandler::ScrollStatus status = + host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10), + InputHandler::TOUCHSCREEN) + .get(), + InputHandler::TOUCHSCREEN); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_TRUE(host_impl_->CurrentlyScrollingNode()); + + host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10), + InputHandler::TOUCHSCREEN) + .get()); + EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 10), + CurrentScrollOffset(OuterViewportScrollLayer())); + + host_impl_->ScrollEnd(); + } +} + // Test that specifying a scroller to ScrollBegin (i.e. avoid hit testing) // returns the correct status if the scroller cannot be scrolled on the // compositor thread. @@ -1149,25 +1192,92 @@ EXPECT_TRUE(did_request_commit_); } -TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) { - SetupViewportLayersInnerScrolls(gfx::Size(50, 50), gfx::Size(100, 100)); +// Ensure correct semantics for the IsActivelyPrecisionScrolling method. This +// method is used to determine scheduler policy so it wants to report true only +// when real scrolling is occurring (i.e. the compositor is consuming scroll +// delta, the page isn't handling the events itself). We also only consider +// this signal for non-animated scrolls. This is partially historical but also +// makes some sense since touchscreen/high-precision touchpad scrolling has a +// physical metaphor (movement sticks to finger) so smoothness should be +// prioritized. +TEST_F(LayerTreeHostImplTest, ActivelyTouchScrollingOnlyAfterScrollMovement) { + SetupViewportLayersOuterScrolls(gfx::Size(50, 50), gfx::Size(100, 100)); DrawFrame(); - InputHandler::ScrollStatus status = host_impl_->ScrollBegin( - BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL) - .get(), - InputHandler::WHEEL); - EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, - status.main_thread_scrolling_reasons); + // Ensure a touch scroll reports true but only after some delta has been + // consumed. + { + InputHandler::ScrollStatus status = + host_impl_->ScrollBegin(BeginState(gfx::Point(), gfx::Vector2dF(0, 10), + InputHandler::TOUCHSCREEN) + .get(), + InputHandler::TOUCHSCREEN); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, + status.main_thread_scrolling_reasons); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); - EXPECT_TRUE(host_impl_->IsActivelyScrolling()); - host_impl_->ScrollUpdate( - UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL) - .get()); - EXPECT_TRUE(host_impl_->IsActivelyScrolling()); - host_impl_->ScrollEnd(); - EXPECT_FALSE(host_impl_->IsActivelyScrolling()); + // There is no extent upwards so the scroll won't consume any delta. + host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, -10), + InputHandler::TOUCHSCREEN) + .get()); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + + // This should scroll so ensure the bit flips to true. + host_impl_->ScrollUpdate(UpdateState(gfx::Point(), gfx::Vector2d(0, 10), + InputHandler::TOUCHSCREEN) + .get()); + EXPECT_TRUE(host_impl_->IsActivelyPrecisionScrolling()); + host_impl_->ScrollEnd(); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + } + + ASSERT_EQ(10, CurrentScrollOffset(OuterViewportScrollLayer()).y()); + + // Ensure an animated wheel scroll doesn't cause the bit to flip even when + // scrolling occurs. + { + InputHandler::ScrollStatus status = host_impl_->ScrollBegin( + BeginState(gfx::Point(), gfx::Vector2dF(0, 10), InputHandler::WHEEL) + .get(), + InputHandler::WHEEL); + EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + + host_impl_->ScrollUpdate( + AnimatedUpdateState(gfx::Point(), gfx::Vector2dF(0, 10)).get()); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + + base::TimeTicks cur_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(100); + viz::BeginFrameArgs begin_frame_args = + viz::CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1); + +#define ANIMATE(time_ms) \ + cur_time += base::TimeDelta::FromMilliseconds(time_ms); \ + begin_frame_args.frame_time = (cur_time); \ + begin_frame_args.frame_id.sequence_number++; \ + host_impl_->WillBeginImplFrame(begin_frame_args); \ + host_impl_->Animate(); \ + host_impl_->UpdateAnimationState(true); \ + host_impl_->DidFinishImplFrame(begin_frame_args); + + // The animation is setup in the first frame so tick at least twice to + // actually animate it. + ANIMATE(0); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + ANIMATE(200); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + ANIMATE(1000); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + +#undef ANIMATE + + ASSERT_EQ(20, CurrentScrollOffset(OuterViewportScrollLayer()).y()); + + host_impl_->ScrollEnd(); + EXPECT_FALSE(host_impl_->IsActivelyPrecisionScrolling()); + } } TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) { @@ -1251,7 +1361,6 @@ UpdateState(gfx::Point(), gfx::Vector2d(0, 10), InputHandler::WHEEL) .get()); EXPECT_TRUE(host_impl_->active_tree()->CurrentlyScrollingNode()); - EXPECT_TRUE(host_impl_->IsActivelyScrolling()); // Create the pending tree containing only the root layer. CreatePendingTree(); @@ -1264,7 +1373,6 @@ // The scroll should stop. EXPECT_FALSE(host_impl_->active_tree()->CurrentlyScrollingNode()); - EXPECT_FALSE(host_impl_->IsActivelyScrolling()); } TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 819e7e44..7327156c 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -2378,10 +2378,6 @@ host_impl_->UpdateImageDecodingHints(std::move(decoding_mode_map)); } -bool LayerTreeImpl::IsActivelyScrolling() const { - return host_impl_->IsActivelyScrolling(); -} - int LayerTreeImpl::GetMSAASampleCountForRaster( const scoped_refptr<DisplayItemList>& display_list) { return host_impl_->GetMSAASampleCountForRaster(display_list);
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index f7ee651..40cd78c 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -153,7 +153,6 @@ void UpdateImageDecodingHints( base::flat_map<PaintImage::Id, PaintImage::DecodingMode> decoding_mode_map); - bool IsActivelyScrolling() const; int GetMSAASampleCountForRaster( const scoped_refptr<DisplayItemList>& display_list);
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc index fa484a8a..ba19dae 100644 --- a/cc/trees/proxy_impl.cc +++ b/cc/trees/proxy_impl.cc
@@ -407,7 +407,7 @@ const bool user_interaction_in_progress = host_impl_->pinch_gesture_active() || host_impl_->page_scale_animation_active() || - host_impl_->IsActivelyScrolling(); + host_impl_->IsActivelyPrecisionScrolling(); if (host_impl_->ukm_manager()) { host_impl_->ukm_manager()->SetUserInteractionInProgress(
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index d724f040..4b74fda 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -77,6 +77,7 @@ "junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java", "junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java", "junit/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiverTest.java", + "junit/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsAnnotationUnitTest.java", "junit/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsUnitTest.java", "junit/src/org/chromium/chrome/browser/fullscreen/BrowserStateBrowserControlsVisibilityDelegateTest.java", "junit/src/org/chromium/chrome/browser/gcore/GoogleApiClientHelperTest.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java index 03d0d0de..ae4444a 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -44,8 +44,9 @@ private final Context mContext; private final PropertyModel mModel; private final ThemeColorProvider mThemeColorProvider; - private final PropertyModelChangeProcessor mModelChangeProcessor; + private final TabGroupUiToolbarView mToolbarView; private final ViewGroup mTabListContainerView; + private PropertyModelChangeProcessor mModelChangeProcessor; private TabGridDialogCoordinator mTabGridDialogCoordinator; private TabListCoordinator mTabStripCoordinator; private TabGroupUiMediator mMediator; @@ -59,13 +60,10 @@ mContext = parentView.getContext(); mThemeColorProvider = themeColorProvider; mModel = new PropertyModel(TabGroupUiProperties.ALL_KEYS); - TabGroupUiToolbarView toolbarView = - (TabGroupUiToolbarView) LayoutInflater.from(mContext).inflate( - R.layout.bottom_tab_strip_toolbar, parentView, false); - mTabListContainerView = toolbarView.getViewContainer(); - parentView.addView(toolbarView); - mModelChangeProcessor = PropertyModelChangeProcessor.create( - mModel, toolbarView, TabGroupUiViewBinder::bind); + mToolbarView = (TabGroupUiToolbarView) LayoutInflater.from(mContext).inflate( + R.layout.bottom_tab_strip_toolbar, parentView, false); + mTabListContainerView = mToolbarView.getViewContainer(); + parentView.addView(mToolbarView); } /** @@ -89,6 +87,11 @@ tabModelSelector, null, null, false, null, null, TabProperties.UiType.STRIP, null, mTabListContainerView, null, true, COMPONENT_NAME); + mModelChangeProcessor = PropertyModelChangeProcessor.create(mModel, + new TabGroupUiViewBinder.ViewHolder( + mToolbarView, mTabStripCoordinator.getContainerView()), + TabGroupUiViewBinder::bind); + // TODO(crbug.com/972217): find a way to enable interactions between grid tab switcher // and the dialog here. mTabGridDialogCoordinator = new TabGridDialogCoordinator(mContext, tabModelSelector,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java index dd9eb618..557d8ae 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.tasks.tab_management; +import android.os.Handler; import android.view.View; import androidx.annotation.Nullable; @@ -137,6 +138,10 @@ @Override public void didAddTab(Tab tab, int type, @TabCreationState int creationState) { + if (type == TabLaunchType.FROM_CHROME_UI && mIsTabGroupUiVisible) { + mModel.set(TabGroupUiProperties.INITIAL_SCROLL_INDEX, + getRelatedTabsForId(tab.getId()).size() - 1); + } if (type == TabLaunchType.FROM_CHROME_UI || type == TabLaunchType.FROM_RESTORE || type == TabLaunchType.FROM_STARTUP) { return; @@ -283,6 +288,15 @@ && BottomToolbarConfiguration.isBottomToolbarEnabled(); assert (mVisibilityController == null) == isDuetTabStripIntegrationEnabled; if (isDuetTabStripIntegrationEnabled) return; + if (mIsTabGroupUiVisible) { + // Post to make sure that the recyclerView already knows how many visible items it has. + // This is to make sure that we can scroll to a state where the selected tab is in the + // middle of the strip. + Handler handler = new Handler(); + handler.post(() + -> mModel.set(TabGroupUiProperties.INITIAL_SCROLL_INDEX, + listOfTabs.indexOf(mTabModelSelector.getCurrentTab()))); + } mVisibilityController.setBottomControlsVisible(mIsTabGroupUiVisible); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java index 09431441..c22a7b5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiProperties.java
@@ -28,8 +28,14 @@ new PropertyModel.WritableObjectPropertyKey<>(); public static final PropertyModel.WritableIntPropertyKey LEFT_BUTTON_DRAWABLE_ID = new PropertyModel.WritableIntPropertyKey(); + /** + * Integer, but not {@link PropertyModel.WritableIntPropertyKey} so that we can force update on + * the same value. + */ + public static final PropertyModel.WritableObjectPropertyKey INITIAL_SCROLL_INDEX = + new PropertyModel.WritableObjectPropertyKey(true); - public static final PropertyKey[] ALL_KEYS = - new PropertyKey[] {LEFT_BUTTON_ON_CLICK_LISTENER, RIGHT_BUTTON_ON_CLICK_LISTENER, - IS_MAIN_CONTENT_VISIBLE, PRIMARY_COLOR, TINT, LEFT_BUTTON_DRAWABLE_ID}; + public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {LEFT_BUTTON_ON_CLICK_LISTENER, + RIGHT_BUTTON_ON_CLICK_LISTENER, IS_MAIN_CONTENT_VISIBLE, PRIMARY_COLOR, TINT, + LEFT_BUTTON_DRAWABLE_ID, INITIAL_SCROLL_INDEX}; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java index 89ad8a8..4045754 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinder.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.tasks.tab_management; +import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.INITIAL_SCROLL_INDEX; import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.IS_MAIN_CONTENT_VISIBLE; import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.LEFT_BUTTON_DRAWABLE_ID; import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.LEFT_BUTTON_ON_CLICK_LISTENER; @@ -11,6 +12,10 @@ import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.RIGHT_BUTTON_ON_CLICK_LISTENER; import static org.chromium.chrome.browser.tasks.tab_management.TabGroupUiProperties.TINT; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -19,26 +24,47 @@ */ class TabGroupUiViewBinder { /** + * ViewHolder class to get access to all {@link View}s inside the TabGroupUi. + */ + public static class ViewHolder { + public final TabGroupUiToolbarView toolbarView; + public final RecyclerView contentView; + + ViewHolder(TabGroupUiToolbarView toolbarView, RecyclerView contentView) { + this.toolbarView = toolbarView; + this.contentView = contentView; + } + } + /** * Binds the given model to the given view, updating the payload in propertyKey. * - * @param model The model to use. - * @param view The view to use. - * @param propertyKey The key for the property to update for. + * @param model The model to use. + * @param viewHolder The {@link ViewHolder} to use. + * @param propertyKey The key for the property to update for. */ - public static void bind( - PropertyModel model, TabGroupUiToolbarView view, PropertyKey propertyKey) { + public static void bind(PropertyModel model, ViewHolder viewHolder, PropertyKey propertyKey) { if (LEFT_BUTTON_ON_CLICK_LISTENER == propertyKey) { - view.setLeftButtonOnClickListener(model.get(LEFT_BUTTON_ON_CLICK_LISTENER)); + viewHolder.toolbarView.setLeftButtonOnClickListener( + model.get(LEFT_BUTTON_ON_CLICK_LISTENER)); } else if (RIGHT_BUTTON_ON_CLICK_LISTENER == propertyKey) { - view.setRightButtonOnClickListener(model.get(RIGHT_BUTTON_ON_CLICK_LISTENER)); + viewHolder.toolbarView.setRightButtonOnClickListener( + model.get(RIGHT_BUTTON_ON_CLICK_LISTENER)); } else if (IS_MAIN_CONTENT_VISIBLE == propertyKey) { - view.setMainContentVisibility(model.get(IS_MAIN_CONTENT_VISIBLE)); + viewHolder.toolbarView.setMainContentVisibility(model.get(IS_MAIN_CONTENT_VISIBLE)); } else if (PRIMARY_COLOR == propertyKey) { - view.setPrimaryColor(model.get(PRIMARY_COLOR)); + viewHolder.toolbarView.setPrimaryColor(model.get(PRIMARY_COLOR)); } else if (TINT == propertyKey) { - view.setTint(model.get(TINT)); + viewHolder.toolbarView.setTint(model.get(TINT)); } else if (LEFT_BUTTON_DRAWABLE_ID == propertyKey) { - view.setLeftButtonDrawableId(model.get(LEFT_BUTTON_DRAWABLE_ID)); + viewHolder.toolbarView.setLeftButtonDrawableId(model.get(LEFT_BUTTON_DRAWABLE_ID)); + } else if (INITIAL_SCROLL_INDEX == propertyKey) { + int index = (Integer) model.get(INITIAL_SCROLL_INDEX); + LinearLayoutManager manager = + (LinearLayoutManager) viewHolder.contentView.getLayoutManager(); + int showingItemsCount = + manager.findLastVisibleItemPosition() - manager.findFirstVisibleItemPosition(); + // Try to scroll to a state where the selected tab is in the middle of the strip. + manager.scrollToPositionWithOffset(index - showingItemsCount / 2, 0); } } }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java new file mode 100644 index 0000000..e96ce94 --- /dev/null +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java
@@ -0,0 +1,152 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.tab_management; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withParent; + +import static org.hamcrest.Matchers.allOf; +import static org.junit.Assert.assertTrue; + +import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.clickFirstCardFromTabSwitcher; +import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.clickNthTabInDialog; +import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.createTabs; +import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.enterTabSwitcher; +import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.mergeAllNormalTabsToAGroup; +import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.verifyTabSwitcherCardCount; + +import android.support.test.filters.MediumTest; +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.compositor.layouts.Layout; +import org.chromium.chrome.browser.flags.CachedFeatureFlags; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.features.start_surface.StartSurfaceLayout; +import org.chromium.chrome.tab_ui.R; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.util.ChromeRenderTestRule; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.ui.test.util.UiRestriction; + +import java.io.IOException; + +/** End-to-end tests for TabGroupUi component. */ +@RunWith(ChromeJUnit4ClassRunner.class) +// clang-format off +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) +public class TabGroupUiTest { + // clang-format on + + @Rule + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + @Rule + public TestRule mProcessor = new Features.InstrumentationProcessor(); + + @Rule + public ChromeRenderTestRule mRenderTestRule = new ChromeRenderTestRule(); + + @Before + public void setUp() { + CachedFeatureFlags.setForTesting(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, true); + CachedFeatureFlags.setForTesting(ChromeFeatureList.TAB_GROUPS_ANDROID, true); + mActivityTestRule.startMainActivityFromLauncher(); + Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout(); + assertTrue(layout instanceof StartSurfaceLayout); + CriteriaHelper.pollUiThread(mActivityTestRule.getActivity() + .getTabModelSelector() + .getTabModelFilterProvider() + .getCurrentTabModelFilter()::isTabModelRestored); + } + + @After + public void tearDown() { + CachedFeatureFlags.setForTesting(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, null); + CachedFeatureFlags.setForTesting(ChromeFeatureList.TAB_GROUPS_ANDROID, null); + } + + @Test + @MediumTest + @Feature({"RenderTest"}) + public void testRenderStrip_Select5thTabIn10Tabs() throws InterruptedException, IOException { + final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + createTabs(cta, false, 10); + enterTabSwitcher(cta); + verifyTabSwitcherCardCount(cta, 10); + mergeAllNormalTabsToAGroup(cta); + verifyTabSwitcherCardCount(cta, 1); + + // Select the 5th tab in group. + clickFirstCardFromTabSwitcher(cta); + clickNthTabInDialog(cta, 4); + + ViewGroup bottomToolbar = cta.findViewById(R.id.bottom_controls); + RecyclerView stripRecyclerView = + (RecyclerView) bottomToolbar.findViewById(R.id.tab_list_view); + mRenderTestRule.render(stripRecyclerView, "5th_tab_selected"); + } + + @Test + @MediumTest + @Feature({"RenderTest"}) + public void testRenderStrip_Select10thTabIn10Tabs() throws InterruptedException, IOException { + final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + createTabs(cta, false, 10); + enterTabSwitcher(cta); + verifyTabSwitcherCardCount(cta, 10); + mergeAllNormalTabsToAGroup(cta); + verifyTabSwitcherCardCount(cta, 1); + + // Select the 10th tab in group. + clickFirstCardFromTabSwitcher(cta); + clickNthTabInDialog(cta, 9); + + ViewGroup bottomToolbar = cta.findViewById(R.id.bottom_controls); + RecyclerView stripRecyclerView = + (RecyclerView) bottomToolbar.findViewById(R.id.tab_list_view); + mRenderTestRule.render(stripRecyclerView, "10th_tab_selected"); + } + + @Test + @MediumTest + @Feature({"RenderTest"}) + public void testRenderStrip_AddTab() throws InterruptedException, IOException { + final ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + createTabs(cta, false, 10); + enterTabSwitcher(cta); + verifyTabSwitcherCardCount(cta, 10); + mergeAllNormalTabsToAGroup(cta); + verifyTabSwitcherCardCount(cta, 1); + + // Select the first tab in group and add one new tab to group. + clickFirstCardFromTabSwitcher(cta); + clickNthTabInDialog(cta, 0); + ViewGroup bottomToolbar = cta.findViewById(R.id.bottom_controls); + RecyclerView stripRecyclerView = + (RecyclerView) bottomToolbar.findViewById(R.id.tab_list_view); + stripRecyclerView.setItemAnimator(null); + onView(allOf(withId(R.id.toolbar_right_button), withParent(withId(R.id.main_content)))) + .perform(click()); + mRenderTestRule.render(stripRecyclerView, "11th_tab_selected"); + } +}
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java index 3dd7e31..24abba5 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java
@@ -16,6 +16,8 @@ import android.os.Build; import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -61,9 +63,16 @@ mRightButton = toolbarView.findViewById(R.id.toolbar_right_button); mContainerView = toolbarView.findViewById(R.id.toolbar_container_view); mMainContent = toolbarView.findViewById(R.id.main_content); + RecyclerView recyclerView = + (TabListRecyclerView) LayoutInflater.from(getActivity()) + .inflate(R.layout.tab_list_recycler_view_layout, parentView, false); + recyclerView.setLayoutManager( + new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false)); mModel = new PropertyModel(TabGroupUiProperties.ALL_KEYS); - mMCP = PropertyModelChangeProcessor.create(mModel, toolbarView, TabGroupUiViewBinder::bind); + mMCP = PropertyModelChangeProcessor.create(mModel, + new TabGroupUiViewBinder.ViewHolder(toolbarView, recyclerView), + TabGroupUiViewBinder::bind); } @Override
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java index f9ee363..041cdcfc 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -405,6 +405,26 @@ } @Test + public void tabSelection_ScrollToSelectedIndex() { + initAndAssertProperties(mTab1); + assertThat(mModel.get(TabGroupUiProperties.INITIAL_SCROLL_INDEX), equalTo(null)); + + // Mock that {tab2, tab3} are in the same tab group. + List<Tab> tabGroup = mTabGroupModelFilter.getRelatedTabList(TAB2_ID); + assertThat(tabGroup.size(), equalTo(2)); + + // Mock selecting tab 3, and the last selected tab is tab 1 which is a single tab. + doReturn(mTab3).when(mTabModelSelector).getCurrentTab(); + mTabModelObserverArgumentCaptor.getValue().didSelectTab( + mTab3, TabSelectionType.FROM_USER, TAB1_ID); + + // Strip should be showing since we are selecting a group, and it should scroll to the index + // of currently selected tab. + verifyResetStrip(true, tabGroup); + assertThat(mModel.get(TabGroupUiProperties.INITIAL_SCROLL_INDEX), equalTo(1)); + } + + @Test public void tabClosure_NotLastTabInGroup() { initAndAssertProperties(mTab2); @@ -501,6 +521,24 @@ } @Test + public void tabAddition_TabGroup_ScrollToTheLast() { + initAndAssertProperties(mTab2); + assertThat(mModel.get(TabGroupUiProperties.INITIAL_SCROLL_INDEX), equalTo(0)); + + TabImpl newTab = prepareTab(TAB4_ID, TAB4_ID); + mTabGroup2.add(newTab); + doReturn(mTabGroup2).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID); + + mTabModelObserverArgumentCaptor.getValue().didAddTab( + newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND); + + // Strip should be not be reset through adding tab from UI. + verifyNeverReset(); + assertThat(mTabGroupModelFilter.getRelatedTabList(TAB4_ID).size(), equalTo(3)); + assertThat(mModel.get(TabGroupUiProperties.INITIAL_SCROLL_INDEX), equalTo(2)); + } + + @Test public void restoreCompleted_TabModelNoTab() { // Simulate no tab in current TabModel. initAndAssertProperties(null);
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni index cda20f8..dd29ddf 100644 --- a/chrome/android/features/tab_ui/tab_management_java_sources.gni +++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -40,6 +40,7 @@ "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupPopupUiViewBinderTest.java", + "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java", "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index ca42c3c..8e54ae60 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -229,7 +229,7 @@ private boolean mPartnerBrowserRefreshNeeded; - protected IntentHandler mIntentHandler; + protected final IntentHandler mIntentHandler; /** Set if {@link #postDeferredStartupIfNeeded()} is called before native has loaded. */ private boolean mDeferredStartupQueued; @@ -312,6 +312,10 @@ /** Controls tab reparenting for night mode. */ NightModeReparentingController mNightModeReparentingController; + protected ChromeActivity() { + mIntentHandler = new IntentHandler(this, createIntentHandlerDelegate()); + } + @Override protected ActivityWindowAndroid createWindowAndroid() { return new ChromeWindow(this); @@ -633,8 +637,8 @@ */ protected StartupTabPreloader getStartupTabPreloader() { if (mStartupTabPreloader == null) { - mStartupTabPreloader = new StartupTabPreloader( - this::getIntent, getLifecycleDispatcher(), getWindowAndroid(), this); + mStartupTabPreloader = new StartupTabPreloader(this::getIntent, + getLifecycleDispatcher(), getWindowAndroid(), this, mIntentHandler); } return mStartupTabPreloader; } @@ -731,7 +735,6 @@ IntentHandler.setTestIntentsEnabled( CommandLine.getInstance().hasSwitch(ContentSwitches.ENABLE_TEST_INTENTS)); - mIntentHandler = new IntentHandler(createIntentHandlerDelegate(), getPackageName()); } @Override @@ -962,7 +965,7 @@ } super.onNewIntentWithNative(intent); - if (IntentHandler.shouldIgnoreIntent(intent)) return; + if (mIntentHandler.shouldIgnoreIntent(intent)) return; // We send this intent so that we can enter WebVr presentation mode if needed. This // call doesn't consume the intent because it also has the url that we need to load.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 17fbe02..62ebd2d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1082,7 +1082,7 @@ this.getLifecycleDispatcher()); mIntentWithEffect = false; if (getSavedInstanceState() == null && intent != null) { - if (!IntentHandler.shouldIgnoreIntent(intent)) { + if (!mIntentHandler.shouldIgnoreIntent(intent)) { mIntentWithEffect = mIntentHandler.onNewIntent(intent); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java index ca81c107..2076ef60 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandler.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser; +import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -12,6 +13,8 @@ import org.chromium.base.ContextUtils; +import java.lang.ref.WeakReference; + /** * Intent handler that is specific for the situation when the screen is unlocked from pin, pattern, * or password. @@ -21,15 +24,17 @@ public class DelayedScreenLockIntentHandler extends BroadcastReceiver { private static final int VALID_DEFERRED_PERIOD_MS = 10000; - private final Handler mTaskHandler; - private final Runnable mUnregisterTask; - + private final Handler mTaskHandler = new Handler(); + private final Runnable mUnregisterTask = () -> updateDeferredIntent(null); + // Must be an Activity context for deferred intents without FLAG_NEW_TASK on Android P+. + // http://crbug.com/1034440 + private final WeakReference<Activity> mActivity; private Intent mDeferredIntent; - private boolean mReceiverRegistered; + private boolean mEnabled; - public DelayedScreenLockIntentHandler() { - mTaskHandler = new Handler(); - mUnregisterTask = () -> updateDeferredIntent(null); + public DelayedScreenLockIntentHandler(Activity activity) { + // Use a WeakReference so that Activity is not retained by call to postDelayed. + mActivity = new WeakReference<>(activity); } @Override @@ -37,7 +42,10 @@ assert Intent.ACTION_USER_PRESENT.equals(intent.getAction()); if (Intent.ACTION_USER_PRESENT.equals(intent.getAction()) && mDeferredIntent != null) { - context.startActivity(mDeferredIntent); + Activity activity = mActivity.get(); + if (activity != null) { + activity.startActivity(mDeferredIntent); + } // Prevent the broadcast receiver from firing intent unexpectedly. updateDeferredIntent(null); } @@ -47,30 +55,12 @@ * Update the deferred intent with the target intent, also reset the deferred intent's lifecycle * @param intent Target intent */ - public void updateDeferredIntent(final Intent intent) { + public void updateDeferredIntent(Intent intent) { mTaskHandler.removeCallbacks(mUnregisterTask); - - if (intent == null) { - unregisterReceiver(); - mDeferredIntent = null; - return; - } - - mDeferredIntent = intent; - registerReceiver(); mTaskHandler.postDelayed(mUnregisterTask, VALID_DEFERRED_PERIOD_MS); - } + mDeferredIntent = intent; - /** - * Register to receive ACTION_USER_PRESENT when the screen is unlocked. - * The ACTION_USER_PRESENT is sent by platform to indicates when user is present. - */ - private void registerReceiver() { - if (mReceiverRegistered) return; - - ContextUtils.getApplicationContext() - .registerReceiver(this, new IntentFilter(Intent.ACTION_USER_PRESENT)); - mReceiverRegistered = true; + setEnabled(intent != null); } /** @@ -78,11 +68,17 @@ * - When the deferred intent expires * - When updateDeferredIntent(null) called * - When the deferred intent has been fired + * Register to receive ACTION_USER_PRESENT when the screen is unlocked. + * The ACTION_USER_PRESENT is sent by platform to indicates when user is present. */ - private void unregisterReceiver() { - if (!mReceiverRegistered) return; - - ContextUtils.getApplicationContext().unregisterReceiver(this); - mReceiverRegistered = false; + private void setEnabled(boolean value) { + if (value == mEnabled) return; + mEnabled = value; + Context applicationContext = ContextUtils.getApplicationContext(); + if (value) { + applicationContext.registerReceiver(this, new IntentFilter(Intent.ACTION_USER_PRESENT)); + } else { + applicationContext.unregisterReceiver(this); + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java index f4fc976..e76b2d1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -274,7 +274,7 @@ private static boolean sTestIntentsEnabled; private final IntentHandlerDelegate mDelegate; - private final String mPackageName; + private final Activity mActivity; /** * Receiver for screen unlock broadcast. @@ -329,9 +329,9 @@ sTestIntentsEnabled = enabled; } - public IntentHandler(IntentHandlerDelegate delegate, String packageName) { + public IntentHandler(Activity activity, IntentHandlerDelegate delegate) { mDelegate = delegate; - mPackageName = packageName; + mActivity = activity; } /** @@ -420,9 +420,9 @@ } } - private static void updateDeferredIntent(Intent intent) { + private void updateDeferredIntent(Intent intent) { if (sDelayedScreenIntentHandler == null && intent != null) { - sDelayedScreenIntentHandler = new DelayedScreenLockIntentHandler(); + sDelayedScreenIntentHandler = new DelayedScreenLockIntentHandler(mActivity); } if (sDelayedScreenIntentHandler != null) { @@ -850,7 +850,7 @@ * @param intent Intent to check. * @return true if the intent should be ignored. */ - public static boolean shouldIgnoreIntent(Intent intent) { + public boolean shouldIgnoreIntent(Intent intent) { // Although not documented to, many/most methods that retrieve values from an Intent may // throw. Because we can't control what packages might send to us, we should catch any // Throwable and then fail closed (safe). This is ugly, but resolves top crashers in the @@ -1060,8 +1060,9 @@ // Intents from chrome open in the same tab by default, all others only clobber // tabs created by the same app. - return mPackageName.equals(appId) ? TabOpenType.CLOBBER_CURRENT_TAB - : TabOpenType.REUSE_APP_ID_MATCHING_TAB_ELSE_NEW_TAB; + return mActivity.getPackageName().equals(appId) + ? TabOpenType.CLOBBER_CURRENT_TAB + : TabOpenType.REUSE_APP_ID_MATCHING_TAB_ELSE_NEW_TAB; } private static boolean isInvalidScheme(String scheme) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java index 1326f2f..ed24838e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -161,7 +161,7 @@ mIntent.getBooleanExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false); // Check if a web search Intent is being handled. - IntentHandler intentHandler = new IntentHandler(this, mActivity.getPackageName()); + IntentHandler intentHandler = new IntentHandler(mActivity, this); String url = IntentHandler.getUrlFromIntent(mIntent); if (url == null && tabId == Tab.INVALID_TAB_ID && !incognito && intentHandler.handleWebSearchIntent(mIntent)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index da90935..0eb28b1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -358,7 +358,7 @@ ChromeActivityCommonsModule commonsModule) { // mIntentHandler comes from the base class. IntentIgnoringCriterion intentIgnoringCriterion = - (intent) -> IntentHandler.shouldIgnoreIntent(intent); + (intent) -> mIntentHandler.shouldIgnoreIntent(intent); CustomTabActivityModule customTabsModule = new CustomTabActivityModule(mIntentDataProvider, mNightModeStateController, intentIgnoringCriterion, getStartupTabPreloader());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java index b6c2bf74..838b72e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -65,6 +65,8 @@ put(ChromeFeatureList.TAB_GROUPS_ANDROID, false); put(ChromeFeatureList.DUET_TABSTRIP_INTEGRATION_ANDROID, false); put(ChromeFeatureList.SHARE_BUTTON_IN_TOP_TOOLBAR, false); + put(ChromeFeatureList.TEST_DEFAULT_DISABLED, false); + put(ChromeFeatureList.TEST_DEFAULT_ENABLED, true); } }; @@ -182,6 +184,24 @@ } /** + * Sets the feature flags to use in JUnit and instrumentation tests. + */ + @VisibleForTesting + public static void setFeaturesForTesting(Map<String, Boolean> features) { + assert features != null; + + for (Map.Entry<String, Boolean> entry : features.entrySet()) { + String key = entry.getKey(); + + if (!sDefaults.containsKey(key)) { + continue; + } + + setForTesting(key, entry.getValue()); + } + } + + /** * Caches flags that must take effect on startup but are set via native code. */ public static void cacheNativeFlags(List<String> featuresToCache) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java b/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java index 09c725b..97c9311 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/StartupTabPreloader.java
@@ -45,17 +45,19 @@ private final ActivityLifecycleDispatcher mActivityLifecycleDispatcher; private final WindowAndroid mWindowAndroid; private final TabCreatorManager mTabCreatorManager; + private final IntentHandler mIntentHandler; private LoadUrlParams mLoadUrlParams; private Tab mTab; private StartupTabObserver mObserver; public StartupTabPreloader(Supplier<Intent> intentSupplier, ActivityLifecycleDispatcher activityLifecycleDispatcher, WindowAndroid windowAndroid, - TabCreatorManager tabCreatorManager) { + TabCreatorManager tabCreatorManager, IntentHandler intentHandler) { mIntentSupplier = intentSupplier; mActivityLifecycleDispatcher = activityLifecycleDispatcher; mWindowAndroid = windowAndroid; mTabCreatorManager = tabCreatorManager; + mIntentHandler = intentHandler; mActivityLifecycleDispatcher.register(this); ProfileManager.addObserver(this); @@ -151,7 +153,7 @@ if (mTab != null) return false; Intent intent = mIntentSupplier.get(); - if (IntentHandler.shouldIgnoreIntent(intent)) return false; + if (mIntentHandler.shouldIgnoreIntent(intent)) return false; if (getUrlFromIntent(intent) == null) return false; // We don't support incognito tabs because only chrome can send new incognito tab
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java index 20fe98c..27ebd78 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryParams.java
@@ -86,4 +86,9 @@ default PaymentRequestUpdateEventCallback getPaymentRequestUpdateEventCallback() { return null; } + + /** @return The currency of the total amount. Should not be null. */ + default String getTotalAmountCurrency() { + return null; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index 32b3811..98ac88b0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -2561,6 +2561,12 @@ return this; } + // PaymentAppFactoryParams implementation. + @Override + public String getTotalAmountCurrency() { + return mRawTotal.amount.currency; + } + // PaymentAppFactoryDelegate implementation. @Override public PaymentAppFactoryParams getParams() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java index 8d91a00..d6ca9fe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java
@@ -162,10 +162,16 @@ } } - fireCanMakePaymentEvent(webContents, registrationId, scope, - mDelegate.getParams().getId(), mDelegate.getParams().getTopLevelOrigin(), - mDelegate.getParams().getPaymentRequestOrigin(), supportedRequestedMethodData, - supportedRequestedModifiers, /*callback=*/this, app); + ServiceWorkerPaymentAppBridgeJni.get().fireCanMakePaymentEvent(webContents, + registrationId, scope, mDelegate.getParams().getId(), + mDelegate.getParams().getTopLevelOrigin(), + mDelegate.getParams().getPaymentRequestOrigin(), + supportedRequestedMethodData.toArray(new PaymentMethodData[0]), + supportedRequestedModifiers.toArray(new PaymentDetailsModifier[0]), + ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_PAYMENTS_MINIMAL_UI) + ? mDelegate.getParams().getTotalAmountCurrency() + : null, + /*callback=*/this, app); } /** Called when an installable payment handler is found. */ @@ -285,34 +291,6 @@ } /** - * Returns whether the app can make a payment. - * - * @param webContents The web contents that invoked PaymentRequest. - * @param registrationId The service worker registration ID of the Payment App. - * @param swScope The service worker scope. - * @param paymentRequestId The payment request identifier. - * @param origin The origin of this merchant. - * @param iframeOrigin The origin of the iframe that invoked PaymentRequest. Same as origin - * if PaymentRequest was not invoked from inside an iframe. - * @param methodData The PaymentMethodData objects that are relevant for this payment - * app. - * @param modifiers Payment method specific modifiers to the payment items and the total. - * @param callback Called after the payment app is finished running. - * @param app The payment handler where the event is being fired. - */ - private static void fireCanMakePaymentEvent(WebContents webContents, long registrationId, - String swScope, String paymentRequestId, String origin, String iframeOrigin, - Set<PaymentMethodData> methodData, Set<PaymentDetailsModifier> modifiers, - PaymentHandlerFinder callback, ServiceWorkerPaymentApp app) { - ThreadUtils.assertOnUiThread(); - - ServiceWorkerPaymentAppBridgeJni.get().fireCanMakePaymentEvent(webContents, registrationId, - swScope, paymentRequestId, origin, iframeOrigin, - methodData.toArray(new PaymentMethodData[0]), - modifiers.toArray(new PaymentDetailsModifier[0]), callback, app); - } - - /** * Make canMakePayment() return true always for testing purpose. * * @param canMakePayment Indicates whether a SW payment app can make payment. @@ -692,7 +670,7 @@ void fireCanMakePaymentEvent(WebContents webContents, long registrationId, String serviceWorkerScope, String paymentRequestId, String topOrigin, String paymentRequestOrigin, PaymentMethodData[] methodData, - PaymentDetailsModifier[] modifiers, PaymentHandlerFinder callback, + PaymentDetailsModifier[] modifiers, String currency, PaymentHandlerFinder callback, ServiceWorkerPaymentApp app); void onClosingPaymentAppWindow(WebContents webContents, int reason); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java index e5788bb5..596bb778 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
@@ -182,8 +182,12 @@ new SpanInfo("<learnmore>", "</learnmore>", new ClickableSpan() { @Override public void onClick(View view) { - HelpAndFeedback.getInstance().show( - getActivity(), helpContext, Profile.getLastUsedProfile(), null); + // TODO(https://crbug.com/1048632): It works correctly now, but unsafe + // if sync runs in incognito mode ever. Use the current profile (i.e., + // regular profile or incognito profile) instead of always using regular + // profile. + HelpAndFeedback.getInstance().show(getActivity(), helpContext, + Profile.getLastUsedRegularProfile(), null); } })); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java index a271e2b..3a48354 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -3230,12 +3230,11 @@ @Test @SmallTest - @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) @Feature({"ContextualSearch"}) // clang-format off @Features.EnableFeatures("ContextualSearchLongpressResolve") - @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.M, - message = "Flaky < M, https://crbug.com/1048827") + @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.P, + message = "Flaky < P, https://crbug.com/1048827") public void testLongpressExtendinSelectionExactResolve() throws TimeoutException { // clang-format on // First test regular long-press. It should not require an exact resolve.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/init/StartupTabPreloaderUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/init/StartupTabPreloaderUnitTest.java index 5c83408..fc9932b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/init/StartupTabPreloaderUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/init/StartupTabPreloaderUnitTest.java
@@ -159,12 +159,15 @@ private StartupTabPreloader createStartupTabPreloader( Intent intent, TabCreatorManager tabCreatorManager) { - return new StartupTabPreloader(new Supplier<Intent>() { - @Override - public Intent get() { - return intent; - } - }, new ActivityLifecycleDispatcherImpl(), null, tabCreatorManager); + return new StartupTabPreloader( + new Supplier<Intent>() { + @Override + public Intent get() { + return intent; + } + }, + new ActivityLifecycleDispatcherImpl(), null, tabCreatorManager, + new IntentHandler(null, null)); } private static class ChromeTabCreatorManager implements TabCreatorManager {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java index 210ee20..dd72c01 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/DelayedScreenLockIntentHandlerTest.java
@@ -9,6 +9,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -29,15 +30,18 @@ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class DelayedScreenLockIntentHandlerTest { - @Mock private Context mContextMock; + @Mock + private Context mApplicationContextMock; + @Mock + private Activity mActivityMock; private DelayedScreenLockIntentHandler mIntentHandler; @Before public void setUp() { MockitoAnnotations.initMocks(this); - mIntentHandler = new DelayedScreenLockIntentHandler(); - ContextUtils.initApplicationContextForTests(mContextMock); + mIntentHandler = new DelayedScreenLockIntentHandler(mActivityMock); + ContextUtils.initApplicationContextForTests(mApplicationContextMock); } @Test @@ -46,11 +50,12 @@ final Intent intent = new Intent(Intent.ACTION_USER_PRESENT); mIntentHandler.updateDeferredIntent(deferredIntent); - mIntentHandler.onReceive(mContextMock, intent); + mIntentHandler.onReceive(null, intent); - verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); - verify(mContextMock).startActivity(deferredIntent); - verify(mContextMock).unregisterReceiver(mIntentHandler); + verify(mApplicationContextMock) + .registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); + verify(mActivityMock).startActivity(deferredIntent); + verify(mApplicationContextMock).unregisterReceiver(mIntentHandler); } @Test @@ -59,12 +64,13 @@ final Intent intent = new Intent(Intent.ACTION_USER_PRESENT); mIntentHandler.updateDeferredIntent(deferredIntent); - mIntentHandler.onReceive(mContextMock, intent); - mIntentHandler.onReceive(mContextMock, intent); + mIntentHandler.onReceive(null, intent); + mIntentHandler.onReceive(null, intent); - verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); - verify(mContextMock).startActivity(deferredIntent); - verify(mContextMock).unregisterReceiver(mIntentHandler); + verify(mApplicationContextMock) + .registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); + verify(mActivityMock).startActivity(deferredIntent); + verify(mApplicationContextMock).unregisterReceiver(mIntentHandler); } @Test @@ -75,24 +81,26 @@ mIntentHandler.updateDeferredIntent(deferredIntent1); mIntentHandler.updateDeferredIntent(deferredIntent2); - mIntentHandler.onReceive(mContextMock, intent); + mIntentHandler.onReceive(null, intent); - verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); - verify(mContextMock).startActivity(deferredIntent2); - verify(mContextMock).unregisterReceiver(mIntentHandler); + verify(mApplicationContextMock) + .registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); + verify(mActivityMock).startActivity(deferredIntent2); + verify(mApplicationContextMock).unregisterReceiver(mIntentHandler); } @Test public void testNonExpectedIntentAction() { mIntentHandler.updateDeferredIntent(new Intent()); try { - mIntentHandler.onReceive(mContextMock, new Intent()); + mIntentHandler.onReceive(null, new Intent()); } catch (AssertionError assertError) { // Ignore AssertErrors } - verify(mContextMock).registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); - verify(mContextMock, never()).startActivity(any(Intent.class)); - verify(mContextMock, never()).unregisterReceiver(mIntentHandler); + verify(mApplicationContextMock) + .registerReceiver(eq(mIntentHandler), any(IntentFilter.class)); + verify(mActivityMock, never()).startActivity(any(Intent.class)); + verify(mApplicationContextMock, never()).unregisterReceiver(mIntentHandler); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsAnnotationUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsAnnotationUnitTest.java new file mode 100644 index 0000000..1e3868a --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsAnnotationUnitTest.java
@@ -0,0 +1,47 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.flags; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.test.util.browser.Features; + +/** + * Unit tests to verify @Features.EnableFeatures() and @Features.DisableFeatures() work for + * {@link CachedFeatureFlags}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Features.EnableFeatures(ChromeFeatureList.TEST_DEFAULT_DISABLED) +@Config(manifest = Config.NONE) +public class CachedFeatureFlagsAnnotationUnitTest { + @Rule + public TestRule mProcessor = new Features.JUnitProcessor(); + + @Test + public void testDefaultFeatureValue() { + Assert.assertTrue(CachedFeatureFlags.isEnabled(ChromeFeatureList.TEST_DEFAULT_ENABLED)); + } + + @Test + public void testFeatureAnnotationOnTestSuiteClass() { + Assert.assertTrue(CachedFeatureFlags.isEnabled(ChromeFeatureList.TEST_DEFAULT_DISABLED)); + } + + @Test + // clang-format off + @Features.DisableFeatures({ChromeFeatureList.TEST_DEFAULT_DISABLED, + ChromeFeatureList.TEST_DEFAULT_ENABLED}) + public void testFeatureAnnotationOnMethod() { + // clang-format on + Assert.assertFalse(CachedFeatureFlags.isEnabled(ChromeFeatureList.TEST_DEFAULT_DISABLED)); + Assert.assertFalse(CachedFeatureFlags.isEnabled(ChromeFeatureList.TEST_DEFAULT_ENABLED)); + } +}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index fd5cff4..c36d9bd 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1184,8 +1184,6 @@ "performance_monitor/system_monitor.h", "permissions/adaptive_quiet_notification_permission_ui_enabler.cc", "permissions/adaptive_quiet_notification_permission_ui_enabler.h", - "permissions/chooser_context_base.cc", - "permissions/chooser_context_base.h", "permissions/chrome_permissions_client.cc", "permissions/chrome_permissions_client.h", "permissions/contextual_notification_permission_ui_selector.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 7ab7071..2220cd1 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4662,11 +4662,6 @@ flag_descriptions::kAndroidSetupSearchEngineName, flag_descriptions::kAndroidSetupSearchEngineDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kAndroidSetupSearchEngine)}, - {"enable-clipboard-provider-text-suggestions", - flag_descriptions::kEnableClipboardProviderTextSuggestionsName, - flag_descriptions::kEnableClipboardProviderTextSuggestionsDescription, - kOsAndroid, - FEATURE_VALUE_TYPE(omnibox::kEnableClipboardProviderTextSuggestions)}, {"omnibox-remove-suggestions-from-clipboard", flag_descriptions::kOmniboxRemoveSuggestionsFromClipboardName, flag_descriptions::kOmniboxRemoveSuggestionsFromClipboardDescription,
diff --git a/chrome/browser/bluetooth/bluetooth_chooser_context.cc b/chrome/browser/bluetooth/bluetooth_chooser_context.cc index 45dce28b..04a5b08 100644 --- a/chrome/browser/bluetooth/bluetooth_chooser_context.cc +++ b/chrome/browser/bluetooth/bluetooth_chooser_context.cc
@@ -9,6 +9,7 @@ #include <vector> #include "base/values.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "components/content_settings/core/common/content_settings_types.h" #include "device/bluetooth/bluetooth_adapter.h" @@ -90,9 +91,10 @@ } // namespace BluetoothChooserContext::BluetoothChooserContext(Profile* profile) - : ChooserContextBase(profile, - ContentSettingsType::BLUETOOTH_GUARD, - ContentSettingsType::BLUETOOTH_CHOOSER_DATA) {} + : ChooserContextBase( + ContentSettingsType::BLUETOOTH_GUARD, + ContentSettingsType::BLUETOOTH_CHOOSER_DATA, + HostContentSettingsMapFactory::GetForProfile(profile)) {} BluetoothChooserContext::~BluetoothChooserContext() = default; @@ -289,6 +291,13 @@ return *object.FindStringKey(kDeviceNameKey); } +// static +WebBluetoothDeviceId BluetoothChooserContext::GetObjectDeviceId( + const base::Value& object) { + std::string device_id_str = *object.FindStringKey(kWebBluetoothDeviceIdKey); + return WebBluetoothDeviceId(device_id_str); +} + bool BluetoothChooserContext::IsValidObject(const base::Value& object) { return object.FindStringKey(kDeviceAddressKey) && object.FindStringKey(kDeviceNameKey) &&
diff --git a/chrome/browser/bluetooth/bluetooth_chooser_context.h b/chrome/browser/bluetooth/bluetooth_chooser_context.h index 9ca5793..b29083bf 100644 --- a/chrome/browser/bluetooth/bluetooth_chooser_context.h +++ b/chrome/browser/bluetooth/bluetooth_chooser_context.h
@@ -10,13 +10,15 @@ #include <utility> #include "base/containers/flat_set.h" -#include "chrome/browser/permissions/chooser_context_base.h" +#include "components/permissions/chooser_context_base.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/public/cpp/bluetooth_uuid.h" #include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h" #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-forward.h" +class Profile; + namespace base { class Value; } // namespace base @@ -77,6 +79,8 @@ // Returns the human readable string representing the given object. static std::string GetObjectName(const base::Value& object); + static blink::WebBluetoothDeviceId GetObjectDeviceId( + const base::Value& object); protected: // ChooserContextBase implementation;
diff --git a/chrome/browser/bluetooth/bluetooth_chooser_context_unittest.cc b/chrome/browser/bluetooth/bluetooth_chooser_context_unittest.cc index 4d704593..0aa10b09 100644 --- a/chrome/browser/bluetooth/bluetooth_chooser_context_unittest.cc +++ b/chrome/browser/bluetooth/bluetooth_chooser_context_unittest.cc
@@ -10,10 +10,10 @@ #include "chrome/browser/bluetooth/bluetooth_chooser_context.h" #include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/permissions/chooser_context_base_mock_permission_observer.h" #include "chrome/test/base/testing_profile.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/permissions/chooser_context_base.h" #include "content/public/test/browser_task_environment.h" #include "device/bluetooth/public/cpp/bluetooth_uuid.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h"
diff --git a/chrome/browser/browsing_data/browsing_data_file_system_helper.cc b/chrome/browser/browsing_data/browsing_data_file_system_helper.cc index a20c7a41..bafcb8f 100644 --- a/chrome/browser/browsing_data/browsing_data_file_system_helper.cc +++ b/chrome/browser/browsing_data/browsing_data_file_system_helper.cc
@@ -79,17 +79,16 @@ storage::FileSystemQuotaUtil* quota_util = filesystem_context_->GetQuotaUtil(type); DCHECK(quota_util); - std::set<GURL> origins; + std::set<url::Origin> origins; quota_util->GetOriginsForTypeOnFileTaskRunner(type, &origins); - for (const GURL& current : origins) { - if (!BrowsingDataHelper::HasWebScheme(current)) + for (const auto& current : origins) { + if (!BrowsingDataHelper::HasWebScheme(current.GetURL())) continue; // Non-websafe state is not considered browsing data. int64_t usage = quota_util->GetOriginUsageOnFileTaskRunner( - filesystem_context_.get(), url::Origin::Create(current), type); + filesystem_context_.get(), current, type); auto inserted = file_system_info_map - .insert(std::make_pair( - current, FileSystemInfo(url::Origin::Create(current)))) + .insert(std::make_pair(current.GetURL(), FileSystemInfo(current))) .first; inserted->second.usage_map[type] = usage; }
diff --git a/chrome/browser/browsing_data/browsing_data_media_license_helper.cc b/chrome/browser/browsing_data/browsing_data_media_license_helper.cc index 1f9d7d6..fea36f54 100644 --- a/chrome/browser/browsing_data/browsing_data_media_license_helper.cc +++ b/chrome/browser/browsing_data/browsing_data_media_license_helper.cc
@@ -99,19 +99,19 @@ filesystem_context_->GetFileSystemBackend(kType)); // Determine the set of origins used. - std::set<GURL> origins; + std::set<url::Origin> origins; std::list<MediaLicenseInfo> result; backend->GetOriginsForTypeOnFileTaskRunner(kType, &origins); - for (const GURL& origin : origins) { - if (!BrowsingDataHelper::HasWebScheme(origin)) + for (const auto& origin : origins) { + if (!BrowsingDataHelper::HasWebScheme(origin.GetURL())) continue; // Non-websafe state is not considered browsing data. int64_t size; base::Time last_modified_time; - backend->GetOriginDetailsOnFileTaskRunner(filesystem_context_.get(), - url::Origin::Create(origin), + backend->GetOriginDetailsOnFileTaskRunner(filesystem_context_.get(), origin, &size, &last_modified_time); - result.push_back(MediaLicenseInfo(origin, size, last_modified_time)); + result.push_back( + MediaLicenseInfo(origin.GetURL(), size, last_modified_time)); } base::PostTask(FROM_HERE, {BrowserThread::UI},
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index cc5fdbc..85eb3a2 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3107,7 +3107,6 @@ base::GetFieldTrialParamByFeatureAsBool(features::kDataSaverHoldback, "holdback_web", false); - auto* native_theme = GetWebTheme(); auto* contents = content::WebContents::FromRenderViewHost(rvh); if (contents) { #if defined(OS_ANDROID) @@ -3122,11 +3121,9 @@ web_prefs->picture_in_picture_enabled = delegate->IsPictureInPictureEnabled(); - // Notify NativeTheme of changes to night mode. - native_theme->set_preferred_color_scheme( - delegate->IsNightModeEnabled() - ? ui::NativeTheme::PreferredColorScheme::kDark - : ui::NativeTheme::PreferredColorScheme::kLight); + web_prefs->preferred_color_scheme = + delegate->IsNightModeEnabled() ? blink::PreferredColorScheme::kDark + : blink::PreferredColorScheme::kLight; } #endif // defined(OS_ANDROID) @@ -3260,6 +3257,7 @@ } } + auto* native_theme = GetWebTheme(); #if !defined(OS_ANDROID) if (IsAutoplayAllowedByPolicy(contents, prefs)) { // If autoplay is allowed by policy then force the no user gesture required @@ -3277,10 +3275,39 @@ ? content::AutoplayPolicy::kDocumentUserActivationRequired : content::AutoplayPolicy::kNoUserGestureRequired; } + + switch (native_theme->GetPreferredColorScheme()) { + case ui::NativeTheme::PreferredColorScheme::kDark: + web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; + break; + case ui::NativeTheme::PreferredColorScheme::kLight: + web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; + break; + case ui::NativeTheme::PreferredColorScheme::kNoPreference: + web_prefs->preferred_color_scheme = + blink::PreferredColorScheme::kNoPreference; + } #endif // !defined(OS_ANDROID) web_prefs->translate_service_available = TranslateService::IsAvailable(prefs); + // Force a light preferred color scheme on certain URLs if kWebUIDarkMode is + // disabled; some of the UI is not yet correctly themed. Note: the WebUI CSS + // explicitly uses light (instead of not dark), which is why we don't reset + // back to no-preference. https://crbug.com/965811 + if (!base::FeatureList::IsEnabled(features::kWebUIDarkMode)) { + const GURL url = rvh->GetSiteInstance()->GetSiteURL(); + bool force_light = url.SchemeIs(content::kChromeUIScheme); +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (!force_light) { + force_light = url.SchemeIs(extensions::kExtensionScheme) && + url.host_piece() == extension_misc::kPdfExtensionId; + } +#endif + if (force_light) + web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; + } + // Apply native CaptionStyle parameters. base::Optional<ui::CaptionStyle> style; @@ -4923,7 +4950,7 @@ url->host() == chrome::kChromeUISettingsHost; } -ui::NativeTheme* ChromeContentBrowserClient::GetWebTheme() const { +const ui::NativeTheme* ChromeContentBrowserClient::GetWebTheme() const { return ui::NativeTheme::GetInstanceForWeb(); }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 146cd63..ae3e827 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -661,7 +661,7 @@ static bool HandleWebUI(GURL* url, content::BrowserContext* browser_context); static bool HandleWebUIReverse(GURL* url, content::BrowserContext* browser_context); - virtual ui::NativeTheme* GetWebTheme() const; // For testing. + virtual const ui::NativeTheme* GetWebTheme() const; // For testing. // Used by subclasses (e.g. implemented by downstream embedders) to add // their own extra part objects.
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc index ec88e4a..0ae7635 100644 --- a/chrome/browser/chrome_content_browser_client_browsertest.cc +++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -885,6 +885,111 @@ opened_tab->GetMainFrame()->GetProcess()->GetID())); } +class PrefersColorSchemeTest : public testing::WithParamInterface<bool>, + public InProcessBrowserTest { + protected: + PrefersColorSchemeTest() : theme_client_(&test_theme_) { + feature_list_.InitWithFeatureState(features::kWebUIDarkMode, GetParam()); + } + + ~PrefersColorSchemeTest() override { + CHECK_EQ(&theme_client_, SetBrowserClientForTesting(original_client_)); + } + + const char* ExpectedColorScheme() const { + return GetParam() ? "dark" : "light"; + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + InProcessBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures, + "MediaQueryPrefersColorScheme"); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + original_client_ = SetBrowserClientForTesting(&theme_client_); + } + + protected: + ui::TestNativeTheme test_theme_; + + private: + content::ContentBrowserClient* original_client_ = nullptr; + + class ChromeContentBrowserClientWithWebTheme + : public ChromeContentBrowserClient { + public: + explicit ChromeContentBrowserClientWithWebTheme( + const ui::NativeTheme* theme) + : theme_(theme) {} + + protected: + const ui::NativeTheme* GetWebTheme() const override { return theme_; } + + private: + const ui::NativeTheme* const theme_; + }; + + base::test::ScopedFeatureList feature_list_; + ChromeContentBrowserClientWithWebTheme theme_client_; +}; + +IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, PrefersColorScheme) { + test_theme_.SetDarkMode(GetParam()); + browser() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetRenderViewHost() + ->OnWebkitPreferencesChanged(); + ui_test_utils::NavigateToURL( + browser(), + ui_test_utils::GetTestUrl( + base::FilePath(base::FilePath::kCurrentDirectory), + base::FilePath(FILE_PATH_LITERAL("prefers-color-scheme.html")))); + base::string16 tab_title; + ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title)); + EXPECT_EQ(base::ASCIIToUTF16(ExpectedColorScheme()), tab_title); +} + +IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, FeatureOverridesChromeSchemes) { + test_theme_.SetDarkMode(true); + + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); + + bool matches; + ASSERT_TRUE(ExecuteScriptAndExtractBool( + browser()->tab_strip_model()->GetActiveWebContents(), + base::StringPrintf("window.domAutomationController.send(window." + "matchMedia('(prefers-color-scheme: %s)').matches)", + ExpectedColorScheme()), + &matches)); + EXPECT_TRUE(matches); +} + +#if BUILDFLAG(ENABLE_EXTENSIONS) +IN_PROC_BROWSER_TEST_P(PrefersColorSchemeTest, FeatureOverridesPdfUI) { + test_theme_.SetDarkMode(true); + + std::string pdf_extension_url(extensions::kExtensionScheme); + pdf_extension_url.append(url::kStandardSchemeSeparator); + pdf_extension_url.append(extension_misc::kPdfExtensionId); + GURL pdf_index = GURL(pdf_extension_url).Resolve("/index.html"); + ui_test_utils::NavigateToURL(browser(), pdf_index); + + bool matches; + ASSERT_TRUE(ExecuteScriptAndExtractBool( + browser()->tab_strip_model()->GetActiveWebContents(), + base::StringPrintf("window.domAutomationController.send(window." + "matchMedia('(prefers-color-scheme: %s)').matches)", + ExpectedColorScheme()), + &matches)); + EXPECT_TRUE(matches); +} +#endif + +INSTANTIATE_TEST_SUITE_P(All, PrefersColorSchemeTest, testing::Bool()); + class ProtocolHandlerTest : public InProcessBrowserTest { public: ProtocolHandlerTest() = default;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 5e2b7aeb0..b4748883 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1531,6 +1531,8 @@ "login/security_token_pin_dialog_host_ash_impl.h", "login/session/chrome_session_manager.cc", "login/session/chrome_session_manager.h", + "login/session/user_session_initializer.cc", + "login/session/user_session_initializer.h", "login/session/user_session_manager.cc", "login/session/user_session_manager.h", "login/signin/auth_error_observer.cc", @@ -1545,6 +1547,8 @@ "login/signin/oauth2_login_manager.h", "login/signin/oauth2_login_manager_factory.cc", "login/signin/oauth2_login_manager_factory.h", + "login/signin/oauth2_login_verifier.cc", + "login/signin/oauth2_login_verifier.h", "login/signin/oauth2_token_fetcher.cc", "login/signin/oauth2_token_fetcher.h", "login/signin/oauth2_token_initializer.cc",
diff --git a/chrome/browser/chromeos/account_manager/account_manager_util.h b/chrome/browser/chromeos/account_manager/account_manager_util.h index f26380ac..97cb028a 100644 --- a/chrome/browser/chromeos/account_manager/account_manager_util.h +++ b/chrome/browser/chromeos/account_manager/account_manager_util.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_UTIL_H_ #define CHROME_BROWSER_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_UTIL_H_ -#include "base/callback_forward.h" +#include "base/bind.h" #include "base/files/file_path.h" class Profile;
diff --git a/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.cc b/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.cc index 2edb72f2..95321c4 100644 --- a/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.cc +++ b/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.cc
@@ -56,6 +56,17 @@ permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 forwardable = true)"; +// Backoff policy used to control managed accounts addition retries. +const net::BackoffEntry::Policy kBackoffPolicyForManagedAccounts = { + 0, // Number of initial errors to ignore without backoff. + 1 * 1000, // Initial delay for backoff in ms: 1 second. + 2, // Factor to multiply for exponential backoff. + 0, // Fuzzing percentage. + 10 * 60 * 1000, // Maximum time to delay requests in ms: 10 minutes. + -1, // Don't discard entry even if unused. + false // Don't use initial delay unless the last was an error. +}; + // If |principal_name| is "UsEr@realm.com", sets |principal_name| to // "user@REALM.COM". Returns false if the given name has no @ or one of the // parts is empty. @@ -93,6 +104,13 @@ return error == kerberos::ERROR_NONE; } +bool ShouldRetry(kerberos::ErrorType error) { + // The error types that should trigger a managed accounts addition retry. + return error == kerberos::ERROR_NETWORK_PROBLEM || + error == kerberos::ERROR_CONTACTING_KDC_FAILED || + error == kerberos::ERROR_IN_PROGRESS; +} + } // namespace // Encapsulates the steps to add a Kerberos account. Overview of the flow: @@ -278,7 +296,8 @@ primary_profile_(primary_profile), kerberos_files_handler_(std::make_unique<KerberosFilesHandler>( base::BindRepeating(&KerberosCredentialsManager::GetKerberosFiles, - base::Unretained(this)))) { + base::Unretained(this)))), + backoff_entry_for_managed_accounts_(&kBackoffPolicyForManagedAccounts) { DCHECK(primary_profile_); const user_manager::User* primary_user = chromeos::ProfileHelper::Get()->GetUserByProfile(primary_profile); @@ -326,7 +345,7 @@ pref_change_registrar_->Add( prefs::kKerberosAccounts, base::BindRepeating(&KerberosCredentialsManager::UpdateAccountsFromPref, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), false /* is_retry */)); // Update accounts if policy is already available or start observing. policy_service_ = @@ -335,7 +354,7 @@ policy_service_->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME); VLOG(1) << "Policy service initialized at startup: " << policy_initialized; if (policy_initialized) - UpdateAccountsFromPref(); + UpdateAccountsFromPref(false /* is_retry */); else policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this); @@ -398,7 +417,7 @@ if (policy_service_->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME)) { VLOG(1) << "Policy service initialized"; policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); - UpdateAccountsFromPref(); + UpdateAccountsFromPref(false /* is_retry */); } } @@ -472,6 +491,18 @@ void KerberosCredentialsManager::OnAddManagedAccountRunnerDone( kerberos::ErrorType error) { + if (!managed_accounts_retry_timer_.IsRunning() && ShouldRetry(error)) { + backoff_entry_for_managed_accounts_.InformOfRequest(false); + + if (backoff_entry_for_managed_accounts_.failure_count() < + kMaxFailureCountForManagedAccounts) { + managed_accounts_retry_timer_.Start( + FROM_HERE, backoff_entry_for_managed_accounts_.GetTimeUntilRelease(), + base::BindOnce(&KerberosCredentialsManager::UpdateAccountsFromPref, + weak_factory_.GetWeakPtr(), true /* is_retry */)); + } + } + if (add_managed_account_callback_for_testing_) { add_managed_account_callback_for_testing_.Run(error); } @@ -746,7 +777,7 @@ if (IsKerberosEnabled()) { // Kerberos got enabled, re-populate managed accounts. VLOG(1) << "Kerberos got enabled, populating managed accounts"; - UpdateAccountsFromPref(); + UpdateAccountsFromPref(false /* is_retry */); return; } @@ -781,7 +812,14 @@ EmptyResultCallback())); } -void KerberosCredentialsManager::UpdateAccountsFromPref() { +void KerberosCredentialsManager::UpdateAccountsFromPref(bool is_retry) { + if (is_retry) { + VLOG(1) << "Retrying to update KerberosAccounts from Prefs"; + } else { + // Refreshing backoff entry, since this call was triggered by prefs change. + backoff_entry_for_managed_accounts_.Reset(); + } + if (!IsKerberosEnabled()) { VLOG(1) << "Kerberos disabled"; NotifyRequiresLoginPassword(false);
diff --git a/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h b/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h index 08fa3d2..34a3fb9 100644 --- a/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h +++ b/chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h
@@ -14,11 +14,13 @@ #include "base/observer_list.h" #include "base/observer_list_types.h" #include "base/optional.h" +#include "base/timer/timer.h" #include "chrome/browser/chromeos/authpolicy/kerberos_files_handler.h" #include "chromeos/dbus/kerberos/kerberos_service.pb.h" #include "components/keyed_service/core/keyed_service.h" #include "components/policy/core/common/policy_namespace.h" #include "components/policy/core/common/policy_service.h" +#include "net/base/backoff_entry.h" class PrefRegistrySimple; class PrefService; @@ -56,6 +58,9 @@ DISALLOW_COPY_AND_ASSIGN(Observer); }; + // Maximum number of managed accounts addition retries per prefs change. + static constexpr int kMaxFailureCountForManagedAccounts = 10; + KerberosCredentialsManager(PrefService* local_state, Profile* primary_profile); ~KerberosCredentialsManager() override; @@ -236,7 +241,7 @@ void UpdateEnabledFromPref(); void UpdateRememberPasswordEnabledFromPref(); void UpdateAddAccountsAllowedFromPref(); - void UpdateAccountsFromPref(); + void UpdateAccountsFromPref(bool is_retry); // Does the main work for UpdateAccountsFromPref(). To clean up stale managed // accounts, an up-to-date accounts list is needed. UpdateAccountsFromPref() @@ -277,6 +282,12 @@ // List of objects that observe this instance. base::ObserverList<Observer, true /* check_empty */> observers_; + // Backoff entry used to control managed accounts addition retries. + net::BackoffEntry backoff_entry_for_managed_accounts_; + + // Timer for keeping track of managed accounts addition retries. + base::OneShotTimer managed_accounts_retry_timer_; + // Callback optionally used for testing. base::RepeatingCallback<void(kerberos::ErrorType)> add_managed_account_callback_for_testing_;
diff --git a/chrome/browser/chromeos/kerberos/kerberos_credentials_manager_test.cc b/chrome/browser/chromeos/kerberos/kerberos_credentials_manager_test.cc index eec263e..6fe28ec4 100644 --- a/chrome/browser/chromeos/kerberos/kerberos_credentials_manager_test.cc +++ b/chrome/browser/chromeos/kerberos/kerberos_credentials_manager_test.cc
@@ -15,6 +15,7 @@ #include "base/run_loop.h" #include "base/stl_util.h" #include "base/test/bind_test_util.h" +#include "base/test/task_environment.h" #include "chrome/browser/chromeos/authpolicy/kerberos_files_handler.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/chromeos/login/users/mock_user_manager.h" @@ -73,6 +74,10 @@ const int kTwoAccounts = 2; const int kThreeAccounts = 3; +const int kOneFailure = 1; +const int kThreeFailures = 3; +const int kLotsOfFailures = 1000000; + // Account keys for the kerberos.accounts pref. constexpr char kKeyPrincipal[] = "principal"; constexpr char kKeyPassword[] = "password"; @@ -89,6 +94,11 @@ permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 forwardable = true)"; +// A long time delta, used to fast forward the task environment until all +// pending operations are completed. This value should be equal to the maximum +// time to delay requests on |kBackoffPolicyForManagedAccounts|. +const base::TimeDelta kLongTimeDelay = base::TimeDelta::FromMinutes(10); + // Fake observer used to test notifications sent by KerberosCredentialsManager // on accounts changes. class FakeKerberosCredentialsManagerObserver @@ -192,23 +202,23 @@ return KerberosClient::Get()->GetTestInterface(); } - void SetupResultCallback(int account_count) { + void SetupResultCallback(int operation_count) { // If this is the first account addition, sets |result_run_loop_|. - if (accounts_addition_count_ == 0) { + if (remaining_operation_count_ == 0) { EXPECT_TRUE(result_errors_.empty()); EXPECT_FALSE(result_run_loop_); result_run_loop_ = std::make_unique<base::RunLoop>(); } - accounts_addition_count_ += account_count; + remaining_operation_count_ += operation_count; } // Gets a callback that adds the passed-in error to |result_errors_|. - // |account_count| is the number of times the callback should be called + // |operation_count| is the number of times the callback should be called // before stopping |result_run_loop_|. base::RepeatingCallback<void(kerberos::ErrorType)> GetRepeatingCallback( - int account_count) { - SetupResultCallback(account_count); + int operation_count) { + SetupResultCallback(operation_count); return base::BindRepeating(&KerberosCredentialsManagerTest::OnResult, weak_ptr_factory_.GetWeakPtr()); } @@ -221,34 +231,45 @@ } void OnResult(kerberos::ErrorType error) { - DCHECK_LT(0, accounts_addition_count_); - accounts_addition_count_--; + // Fails if the test tries to execute more operations than expected. + ASSERT_LT(0, remaining_operation_count_); + remaining_operation_count_--; result_errors_.insert(error); // Stops |result_run_loop_| if all additions are finished. - if (accounts_addition_count_ == 0) { + if (remaining_operation_count_ == 0) { result_run_loop_->Quit(); } } - void WaitAndVerifyResult(std::multiset<kerberos::ErrorType> expected_errors_, + void WaitAndVerifyResult(std::multiset<kerberos::ErrorType> expected_errors, int expected_notifications_count, int expected_accounts_count) { - EXPECT_LT(0, accounts_addition_count_); + EXPECT_LT(0, remaining_operation_count_); ASSERT_TRUE(result_run_loop_); result_run_loop_->Run(); - EXPECT_EQ(expected_errors_, result_errors_); + EXPECT_EQ(expected_errors, result_errors_); EXPECT_EQ(expected_notifications_count, observer_.notifications_count()); EXPECT_EQ(expected_accounts_count, observer_.accounts_count_at_last_notification()); - EXPECT_EQ(0, accounts_addition_count_); + EXPECT_EQ(0, remaining_operation_count_); result_run_loop_.reset(); result_errors_.clear(); observer_.Reset(); } + std::multiset<kerberos::ErrorType> GetRepeatedError(kerberos::ErrorType error, + int repetitions) { + std::multiset<kerberos::ErrorType> result; + for (int i = 0; i < repetitions; i++) { + result.insert(error); + } + + return result; + } + // Calls |mgr_->AddAccountAndAuthenticate()| with |principal_name|, // |is_managed| and some default parameters, waits for the result and checks // expectations. @@ -338,7 +359,8 @@ EXPECT_TRUE(user_context.GetPasswordKey()->GetSecret().empty()); } - content::BrowserTaskEnvironment task_environment_; + content::BrowserTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; user_manager::ScopedUserManager scoped_user_manager_; ScopedTestingLocalState local_state_; std::unique_ptr<TestingProfile> profile_; @@ -346,7 +368,7 @@ std::unique_ptr<KerberosCredentialsManager> mgr_; FakeKerberosCredentialsManagerObserver observer_; - int accounts_addition_count_ = 0; + int remaining_operation_count_ = 0; std::unique_ptr<base::RunLoop> result_run_loop_; std::multiset<kerberos::ErrorType> result_errors_; @@ -587,8 +609,7 @@ kConfig, kAllowExisting, GetResultCallback()); WaitAndVerifyResult( - {kerberos::ERROR_BAD_PASSWORD, kerberos::ERROR_BAD_PASSWORD, - kerberos::ERROR_BAD_PASSWORD}, + GetRepeatedError(kerberos::ERROR_BAD_PASSWORD, kThreeAccounts), kOneNotification, kThreeAccounts); EXPECT_TRUE(mgr_->GetActiveAccount().empty()); } @@ -608,9 +629,8 @@ kDontRememberPassword, kConfig, kAllowExisting, GetResultCallback()); - WaitAndVerifyResult( - {kerberos::ERROR_NONE, kerberos::ERROR_NONE, kerberos::ERROR_NONE}, - kOneNotification, kThreeAccounts); + WaitAndVerifyResult(GetRepeatedError(kerberos::ERROR_NONE, kThreeAccounts), + kOneNotification, kThreeAccounts); EXPECT_EQ(kNormalizedPrincipal, mgr_->GetActiveAccount()); } @@ -780,7 +800,7 @@ // Two notifications are expected: one from AddAccountRunner and another from // RemoveAllManagedAccountsExcept. - WaitAndVerifyResult({kerberos::ERROR_NONE, kerberos::ERROR_NONE}, + WaitAndVerifyResult(GetRepeatedError(kerberos::ERROR_NONE, kTwoAccounts), kTwoNotifications, kTwoAccounts); EXPECT_TRUE(mgr_->IsKerberosEnabled()); @@ -813,7 +833,7 @@ kRememberPassword, kConfig, kAllowExisting, GetResultCallback()); - WaitAndVerifyResult({kerberos::ERROR_NONE, kerberos::ERROR_NONE}, + WaitAndVerifyResult(GetRepeatedError(kerberos::ERROR_NONE, kTwoAccounts), kOneNotification, kTwoAccounts); SetPref(prefs::kKerberosRememberPasswordEnabled, base::Value(false)); @@ -966,7 +986,7 @@ // Two notifications are expected: one from AddAccountRunner and another from // RemoveAllManagedAccountsExcept(). - WaitAndVerifyResult({kerberos::ERROR_NONE, kerberos::ERROR_NONE}, + WaitAndVerifyResult(GetRepeatedError(kerberos::ERROR_NONE, kTwoAccounts), kTwoNotifications, kTwoAccounts); VerifyVotedForSavingLoginPassword(kDontSaveLoginPassword); @@ -1005,7 +1025,7 @@ // Two notifications are expected: one from AddAccountRunner and another from // RemoveAllManagedAccountsExcept(). - WaitAndVerifyResult({kerberos::ERROR_NONE, kerberos::ERROR_NONE}, + WaitAndVerifyResult(GetRepeatedError(kerberos::ERROR_NONE, kTwoAccounts), kTwoNotifications, kTwoAccounts); VerifyVotedForSavingLoginPassword(kSaveLoginPassword); @@ -1046,7 +1066,7 @@ // Two notifications are expected: one from AddAccountRunner and another from // RemoveAllManagedAccountsExcept(). - WaitAndVerifyResult({kerberos::ERROR_NONE, kerberos::ERROR_NONE}, + WaitAndVerifyResult(GetRepeatedError(kerberos::ERROR_NONE, kTwoAccounts), kTwoNotifications, kTwoAccounts); VerifyVotedForSavingLoginPassword(kSaveLoginPassword); @@ -1089,7 +1109,7 @@ // Two notifications are expected: one from AddAccountRunner and another from // RemoveAllManagedAccountsExcept(). - WaitAndVerifyResult({kerberos::ERROR_NONE, kerberos::ERROR_NONE}, + WaitAndVerifyResult(GetRepeatedError(kerberos::ERROR_NONE, kTwoAccounts), kTwoNotifications, kTwoAccounts); VerifyVotedForSavingLoginPassword(kDontSaveLoginPassword); @@ -1101,6 +1121,178 @@ EXPECT_EQ(kNormalizedPrincipal, mgr_->GetActiveAccount()); } +// UpdateAccountsFromPref retries to add account if addition fails for network +// related errors. +TEST_F(KerberosCredentialsManagerTest, UpdateAccountsFromPrefRetry) { + // Starting with Kerberos enabled. + SetPref(prefs::kKerberosEnabled, base::Value(true)); + + client_test_interface()->SetSimulatedNumberOfNetworkFailures(kOneFailure * + kOneAccount); + + mgr_->SetAddManagedAccountCallbackForTesting( + GetRepeatingCallback((kOneFailure + 1) * kOneAccount)); + + base::Value managed_account_1(base::Value::Type::DICTIONARY); + + managed_account_1.SetStringKey(kKeyPrincipal, kPrincipal); + managed_account_1.SetStringKey(kKeyPassword, kPassword); + + base::Value managed_accounts(base::Value::Type::LIST); + managed_accounts.Append(std::move(managed_account_1)); + + SetPref(prefs::kKerberosAccounts, std::move(managed_accounts)); + + // Two notifications are expected for each attempt: one from AddAccountRunner + // and another from RemoveAllManagedAccountsExcept(). + WaitAndVerifyResult({kerberos::ERROR_NETWORK_PROBLEM, kerberos::ERROR_NONE}, + (kOneFailure + 1) * kTwoNotifications, kOneAccount); + + // Fast forwarding the task environment to force all pending tasks to be + // executed. Makes sure no retry is scheduled after a successful attempt. + task_environment_.FastForwardBy(kLongTimeDelay); + + Accounts accounts = ListAccounts(); + ASSERT_EQ(1u, accounts.size()); + EXPECT_EQ(kNormalizedPrincipal, accounts[0].principal_name()); + EXPECT_EQ(kNormalizedPrincipal, mgr_->GetActiveAccount()); +} + +// UpdateAccountsFromPref retries multiple times to add account if addition +// fails multiple times for network related errors. +TEST_F(KerberosCredentialsManagerTest, UpdateAccountsFromPrefMultipleRetries) { + // Starting with Kerberos enabled. + SetPref(prefs::kKerberosEnabled, base::Value(true)); + + client_test_interface()->SetSimulatedNumberOfNetworkFailures(kThreeFailures * + kOneAccount); + + mgr_->SetAddManagedAccountCallbackForTesting( + GetRepeatingCallback((kThreeFailures + 1) * kOneAccount)); + + base::Value managed_account_1(base::Value::Type::DICTIONARY); + + managed_account_1.SetStringKey(kKeyPrincipal, kPrincipal); + managed_account_1.SetStringKey(kKeyPassword, kPassword); + + base::Value managed_accounts(base::Value::Type::LIST); + managed_accounts.Append(std::move(managed_account_1)); + + SetPref(prefs::kKerberosAccounts, std::move(managed_accounts)); + + // Two notifications are expected for each attempt: one from AddAccountRunner + // and another from RemoveAllManagedAccountsExcept(). + WaitAndVerifyResult( + {kerberos::ERROR_NETWORK_PROBLEM, kerberos::ERROR_NETWORK_PROBLEM, + kerberos::ERROR_NETWORK_PROBLEM, kerberos::ERROR_NONE}, + (kThreeFailures + 1) * kTwoNotifications, kOneAccount); + + // Fast forwarding the task environment to force all pending tasks to be + // executed. This will make sure no retry is scheduled after a successful + // attempt. + task_environment_.FastForwardBy(kLongTimeDelay); + + Accounts accounts = ListAccounts(); + ASSERT_EQ(1u, accounts.size()); + EXPECT_EQ(kNormalizedPrincipal, accounts[0].principal_name()); + EXPECT_EQ(kNormalizedPrincipal, mgr_->GetActiveAccount()); +} + +// UpdateAccountsFromPref retries to add multiple accounts if addition fails for +// network related errors. +TEST_F(KerberosCredentialsManagerTest, + UpdateAccountsFromPrefRetryMultipleAccounts) { + // Starting with Kerberos enabled. + SetPref(prefs::kKerberosEnabled, base::Value(true)); + + client_test_interface()->SetSimulatedNumberOfNetworkFailures(kOneFailure * + kTwoAccounts); + + mgr_->SetAddManagedAccountCallbackForTesting( + GetRepeatingCallback((kOneFailure + 1) * kTwoAccounts)); + + base::Value managed_account_1(base::Value::Type::DICTIONARY); + base::Value managed_account_2(base::Value::Type::DICTIONARY); + + managed_account_1.SetStringKey(kKeyPrincipal, kPrincipal); + managed_account_1.SetStringKey(kKeyPassword, kPassword); + managed_account_2.SetStringKey(kKeyPrincipal, kOtherPrincipal); + managed_account_2.SetStringKey(kKeyPassword, kPassword); + + base::Value managed_accounts(base::Value::Type::LIST); + managed_accounts.Append(std::move(managed_account_1)); + managed_accounts.Append(std::move(managed_account_2)); + + SetPref(prefs::kKerberosAccounts, std::move(managed_accounts)); + + // Two notifications are expected for each attempt: one from AddAccountRunner + // and another from RemoveAllManagedAccountsExcept(). + WaitAndVerifyResult( + {kerberos::ERROR_NETWORK_PROBLEM, kerberos::ERROR_NETWORK_PROBLEM, + kerberos::ERROR_NONE, kerberos::ERROR_NONE}, + (kOneFailure + 1) * kTwoNotifications, kTwoAccounts); + + // Fast forwarding the task environment to force all pending tasks to be + // executed. This will make sure no retry is scheduled after a successful + // attempt. + task_environment_.FastForwardBy(kLongTimeDelay); + + Accounts accounts = ListAccounts(); + ASSERT_EQ(2u, accounts.size()); + EXPECT_EQ(kNormalizedPrincipal, accounts[0].principal_name()); + EXPECT_EQ(kNormalizedOtherPrincipal, accounts[1].principal_name()); + EXPECT_EQ(kNormalizedPrincipal, mgr_->GetActiveAccount()); +} + +// UpdateAccountsFromPref stops retrying after a certain number of network +// related errors. +TEST_F(KerberosCredentialsManagerTest, UpdateAccountsFromPrefStopsRetrying) { + // Starting with Kerberos enabled. + SetPref(prefs::kKerberosEnabled, base::Value(true)); + + client_test_interface()->SetSimulatedNumberOfNetworkFailures(kLotsOfFailures); + + mgr_->SetAddManagedAccountCallbackForTesting(GetRepeatingCallback( + KerberosCredentialsManager::kMaxFailureCountForManagedAccounts * + kTwoAccounts)); + + base::Value managed_account_1(base::Value::Type::DICTIONARY); + base::Value managed_account_2(base::Value::Type::DICTIONARY); + + managed_account_1.SetStringKey(kKeyPrincipal, kPrincipal); + managed_account_1.SetStringKey(kKeyPassword, kPassword); + managed_account_2.SetStringKey(kKeyPrincipal, kOtherPrincipal); + managed_account_2.SetStringKey(kKeyPassword, kPassword); + + base::Value managed_accounts(base::Value::Type::LIST); + managed_accounts.Append(std::move(managed_account_1)); + managed_accounts.Append(std::move(managed_account_2)); + + SetPref(prefs::kKerberosAccounts, std::move(managed_accounts)); + + // Two notifications are expected for each attempt: one from AddAccountRunner + // and another from RemoveAllManagedAccountsExcept(). + WaitAndVerifyResult( + GetRepeatedError( + kerberos::ERROR_NETWORK_PROBLEM, + KerberosCredentialsManager::kMaxFailureCountForManagedAccounts * + kTwoAccounts), + KerberosCredentialsManager::kMaxFailureCountForManagedAccounts * + kTwoNotifications, + kTwoAccounts); + + // Fast forwarding the task environment to force all pending tasks to be + // executed. This will make sure no retry is scheduled after a certain number + // of network related errors. + task_environment_.FastForwardBy(kLongTimeDelay); + + Accounts accounts = ListAccounts(); + ASSERT_EQ(2u, accounts.size()); + EXPECT_EQ(kNormalizedPrincipal, accounts[0].principal_name()); + EXPECT_EQ(kNormalizedOtherPrincipal, accounts[1].principal_name()); + EXPECT_EQ(kNormalizedPrincipal, mgr_->GetActiveAccount()); +} + // TODO(https://crbug.com/952251): Add more tests // - ClearAccounts // + Normalization like in AddAccountAndAuthenticate
diff --git a/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h index c55a5358..60024ec 100644 --- a/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h +++ b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h
@@ -32,6 +32,11 @@ // ash::ShelfCondif::Observer: void OnShelfConfigUpdated() override; + void set_exit_callback_for_testing( + const base::RepeatingClosure& exit_callback) { + exit_callback_ = exit_callback; + } + protected: // BaseScreen: void ShowImpl() override;
diff --git a/chrome/browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc new file mode 100644 index 0000000..2fe4902 --- /dev/null +++ b/chrome/browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc
@@ -0,0 +1,219 @@ +// Copyright 2020 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/login/screens/marketing_opt_in_screen.h" + +#include <string> +#include <vector> + +#include "ash/public/cpp/ash_features.h" +#include "ash/public/cpp/ash_pref_names.h" +#include "ash/public/cpp/shelf_test_api.h" +#include "ash/public/cpp/test/shell_test_api.h" +#include "base/bind.h" +#include "base/run_loop.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" +#include "chrome/browser/chromeos/login/screen_manager.h" +#include "chrome/browser/chromeos/login/test/js_checker.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" +#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" +#include "chrome/browser/chromeos/login/ui/login_display_host.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/web_contents.h" +#include "ui/aura/window.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/events/test/event_generator.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/vector2d.h" + +namespace chromeos { + +class MarketingOptInScreenTest : public OobeBaseTest { + public: + MarketingOptInScreenTest() { + feature_list_.InitAndEnableFeature( + ash::features::kHideShelfControlsInTabletMode); + } + ~MarketingOptInScreenTest() override = default; + + // OobeBaseTest: + void SetUpOnMainThread() override { + ash::ShellTestApi().SetTabletModeEnabledForTest(true); + + MarketingOptInScreen* marketing_screen = static_cast<MarketingOptInScreen*>( + WizardController::default_controller()->screen_manager()->GetScreen( + MarketingOptInScreenView::kScreenId)); + marketing_screen->set_exit_callback_for_testing(base::BindRepeating( + &MarketingOptInScreenTest::HandleScreenExit, base::Unretained(this))); + + OobeBaseTest::SetUpOnMainThread(); + } + + // Shows the gesture navigation screen. + void ShowMarketingOptInScreen() { + WizardController::default_controller()->AdvanceToScreen( + MarketingOptInScreenView::kScreenId); + } + + void WaitForScreenExit() { + if (screen_exited_) + return; + + base::RunLoop run_loop; + screen_exit_callback_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + void SimulateFlingFromShelf() { + aura::Window* oobe_window = LoginDisplayHost::default_host() + ->GetOobeWebContents() + ->GetTopLevelNativeWindow(); + display::Screen* const screen = display::Screen::GetScreen(); + const display::Display display = + screen->GetDisplayNearestWindow(oobe_window); + + // Start at the center of the expected shelf bounds. + const int shelf_size = ash::ShelfConfig::Get()->shelf_size(); + const gfx::Point start = + gfx::Point(display.bounds().x() + display.bounds().width() / 2, + display.bounds().bottom() - shelf_size / 2); + // Swipe upwards. + const gfx::Point end = start + gfx::Vector2d(0, -shelf_size); + const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(10); + const int kNumScrollSteps = 4; + ui::test::EventGenerator event_generator(oobe_window->GetRootWindow()); + event_generator.GestureScrollSequence(start, end, kTimeDelta, + kNumScrollSteps); + } + + private: + void HandleScreenExit() { + ASSERT_FALSE(screen_exited_); + screen_exited_ = true; + if (screen_exit_callback_) + std::move(screen_exit_callback_).Run(); + } + + bool screen_exited_ = false; + base::RepeatingClosure screen_exit_callback_; + base::test::ScopedFeatureList feature_list_; +}; + +// Tests that marketing opt in toggles are hidden by default (as the command +// line switch to show marketing opt in is not set). +IN_PROC_BROWSER_TEST_F(MarketingOptInScreenTest, MarketingTogglesHidden) { + ShowMarketingOptInScreen(); + OobeScreenWaiter(MarketingOptInScreenView::kScreenId).Wait(); + test::OobeJS().ExpectHiddenPath( + {"marketing-opt-in", "marketing-opt-in-subtitle"}); + test::OobeJS().ExpectHiddenPath( + {"marketing-opt-in", "marketing-opt-in-toggles"}); + + ash::ShellTestApi().SetTabletModeEnabledForTest(false); + test::OobeJS().ExpectHiddenPath( + {"marketing-opt-in", "marketing-opt-in-subtitle"}); + test::OobeJS().ExpectHiddenPath( + {"marketing-opt-in", "marketing-opt-in-toggles"}); + + ash::ShellTestApi().SetTabletModeEnabledForTest(true); + test::OobeJS().ExpectHiddenPath( + {"marketing-opt-in", "marketing-opt-in-subtitle"}); + test::OobeJS().ExpectHiddenPath( + {"marketing-opt-in", "marketing-opt-in-toggles"}); +} + +// Tests that fling from shelf exits the screen in tablet mode. +IN_PROC_BROWSER_TEST_F(MarketingOptInScreenTest, FlingFromShelfInTabletMode) { + ShowMarketingOptInScreen(); + OobeScreenWaiter(MarketingOptInScreenView::kScreenId).Wait(); + + ASSERT_TRUE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); + SimulateFlingFromShelf(); + + WaitForScreenExit(); + EXPECT_FALSE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); +} + +// Tests that fling from shelf is not enabled in tablet mode if shelf +// navigation buttons are forced by the accessibility setting to show the +// buttons. +IN_PROC_BROWSER_TEST_F(MarketingOptInScreenTest, + ShelfButtonsEnabledInTabletMode) { + ShowMarketingOptInScreen(); + OobeScreenWaiter(MarketingOptInScreenView::kScreenId).Wait(); + + ASSERT_TRUE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); + + // If the setting to always show shelf navigation buttons is enabled, the + // shelf gesture detection should be disabled on the screen, and the user + // should be able to use "next" button to exit the screen. + ProfileManager::GetActiveUserProfile()->GetPrefs()->SetBoolean( + ash::prefs::kAccessibilityTabletModeShelfNavigationButtonsEnabled, true); + EXPECT_FALSE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); + + test::OobeJS() + .CreateVisibilityWaiter( + true, {"marketing-opt-in", "marketing-opt-in-next-button"}) + ->Wait(); + test::OobeJS().TapOnPath( + {"marketing-opt-in", "marketing-opt-in-next-button"}); + + WaitForScreenExit(); + EXPECT_FALSE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); +} + +// Tests that login shelf does not have fling handler in clamshell, and that +// the user can exit the screen using a button in the OOBE screen to exit the +// screen. +IN_PROC_BROWSER_TEST_F(MarketingOptInScreenTest, + ExitScreenUsingButtonInClamshell) { + ShowMarketingOptInScreen(); + OobeScreenWaiter(MarketingOptInScreenView::kScreenId).Wait(); + ash::ShellTestApi().SetTabletModeEnabledForTest(false); + + // When not in tablet mode, the shelf gesture detection should be disabled, + // and the user should be able to exit the screen using "next" button in the + // screen. + EXPECT_FALSE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); + test::OobeJS() + .CreateVisibilityWaiter( + true, {"marketing-opt-in", "marketing-opt-in-next-button"}) + ->Wait(); + test::OobeJS().TapOnPath( + {"marketing-opt-in", "marketing-opt-in-next-button"}); + + WaitForScreenExit(); + EXPECT_FALSE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); +} + +// Tests that enabling tablet mode while on the screen will enable login shelf +// gestures as well. +IN_PROC_BROWSER_TEST_F(MarketingOptInScreenTest, + FlingFromGestureEnabledOnTabletModeEnter) { + ShowMarketingOptInScreen(); + OobeScreenWaiter(MarketingOptInScreenView::kScreenId).Wait(); + ash::ShellTestApi().SetTabletModeEnabledForTest(false); + + EXPECT_FALSE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); + test::OobeJS() + .CreateVisibilityWaiter( + true, {"marketing-opt-in", "marketing-opt-in-next-button"}) + ->Wait(); + + // Enter tablet mode and verify shelf gesture detection gets re-enabled. + ash::ShellTestApi().SetTabletModeEnabledForTest(true); + ASSERT_TRUE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); + + SimulateFlingFromShelf(); + WaitForScreenExit(); + EXPECT_FALSE(ash::ShelfTestApi().HasLoginShelfGestureHandler()); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc index 430b63d..2925e8f 100644 --- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc +++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/chromeos/login/login_wizard.h" #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.h" #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h" +#include "chrome/browser/chromeos/login/session/user_session_initializer.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/wizard_controller.h" @@ -145,19 +146,8 @@ return; } - user_session_mgr->InitRlz(user_profile); - user_session_mgr->InitializeCerts(user_profile); - user_session_mgr->InitializeCRLSetFetcher(user); - user_session_mgr->InitializeCertificateTransparencyComponents(user); - ProfileHelper::Get()->ProfileStartup(user_profile); - user_session_mgr->InitializePrimaryProfileServices(user_profile, user); - - if (user->GetType() == user_manager::USER_TYPE_CHILD) { - user_session_mgr->InitializeChildUserServices(user_profile); - } - user_session_mgr->NotifyUserProfileLoaded(user_profile, user); // This call will set session state to SESSION_STATE_ACTIVE (same one). @@ -196,8 +186,14 @@ } // namespace ChromeSessionManager::ChromeSessionManager() - : oobe_configuration_(std::make_unique<OobeConfiguration>()) {} -ChromeSessionManager::~ChromeSessionManager() {} + : oobe_configuration_(std::make_unique<OobeConfiguration>()), + user_session_initializer_(std::make_unique<UserSessionInitializer>()) { + AddObserver(user_session_initializer_.get()); +} + +ChromeSessionManager::~ChromeSessionManager() { + RemoveObserver(user_session_initializer_.get()); +} void ChromeSessionManager::Initialize( const base::CommandLine& parsed_command_line,
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.h b/chrome/browser/chromeos/login/session/chrome_session_manager.h index bb3fe5fb..386fd1a 100644 --- a/chrome/browser/chromeos/login/session/chrome_session_manager.h +++ b/chrome/browser/chromeos/login/session/chrome_session_manager.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "chrome/browser/chromeos/login/oobe_configuration.h" +#include "chrome/browser/chromeos/login/session/user_session_initializer.h" #include "components/session_manager/core/session_manager.h" namespace base { @@ -43,6 +44,7 @@ private: std::unique_ptr<chromeos::OobeConfiguration> oobe_configuration_; + std::unique_ptr<UserSessionInitializer> user_session_initializer_; DISALLOW_COPY_AND_ASSIGN(ChromeSessionManager); };
diff --git a/chrome/browser/chromeos/login/session/user_session_initializer.cc b/chrome/browser/chromeos/login/session/user_session_initializer.cc new file mode 100644 index 0000000..7f0d74d --- /dev/null +++ b/chrome/browser/chromeos/login/session/user_session_initializer.cc
@@ -0,0 +1,245 @@ +// Copyright 2020 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/login/session/user_session_initializer.h" + +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "base/system/sys_info.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part_chromeos.h" +#include "chrome/browser/chromeos/arc/session/arc_service_launcher.h" +#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h" +#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h" +#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_manager.h" +#include "chrome/browser/chromeos/lock_screen_apps/state_controller.h" +#include "chrome/browser/chromeos/login/startup_utils.h" +#include "chrome/browser/chromeos/policy/app_install_event_log_manager_wrapper.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/component_updater/crl_set_component_installer.h" +#include "chrome/browser/component_updater/sth_set_component_remover.h" +#include "chrome/browser/google/google_brand_chromeos.h" +#include "chrome/browser/net/nss_context.h" +#include "chrome/common/pref_names.h" +#include "chromeos/network/network_cert_loader.h" +#include "chromeos/tpm/install_attributes.h" +#include "components/prefs/pref_service.h" + +#if BUILDFLAG(ENABLE_RLZ) +#include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h" +#include "components/rlz/rlz_tracker.h" +#endif + +namespace chromeos { + +namespace { +UserSessionInitializer* g_instance = nullptr; + +#if BUILDFLAG(ENABLE_RLZ) +// Flag file that disables RLZ tracking, when present. +const base::FilePath::CharType kRLZDisabledFlagName[] = + FILE_PATH_LITERAL(".rlz_disabled"); + +base::FilePath GetRlzDisabledFlagPath() { + base::FilePath homedir; + base::PathService::Get(base::DIR_HOME, &homedir); + return homedir.Append(kRLZDisabledFlagName); +} + +UserSessionInitializer::RlzInitParams CollectRlzParams() { + UserSessionInitializer::RlzInitParams params; + params.disabled = base::PathExists(GetRlzDisabledFlagPath()); + params.time_since_oobe_completion = + chromeos::StartupUtils::GetTimeSinceOobeFlagFileCreation(); + return params; +} +#endif + +// Callback to GetNSSCertDatabaseForProfile. It passes the user-specific NSS +// database to NetworkCertLoader. It must be called for primary user only. +void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase* database) { + if (!NetworkCertLoader::IsInitialized()) + return; + + NetworkCertLoader::Get()->SetUserNSSDB(database); +} + +} // namespace + +UserSessionInitializer::UserSessionInitializer() { + DCHECK(!g_instance); + g_instance = this; +} + +UserSessionInitializer::~UserSessionInitializer() { + DCHECK(g_instance); + g_instance = nullptr; +} + +// static +UserSessionInitializer* UserSessionInitializer::Get() { + return g_instance; +} + +void UserSessionInitializer::OnUserProfileLoaded(const AccountId& account_id) { + Profile* profile = ProfileHelper::Get()->GetProfileByAccountId(account_id); + user_manager::User* user = ProfileHelper::Get()->GetUserByProfile(profile); + + if (user_manager::UserManager::Get()->GetPrimaryUser() == user) { + InitRlz(profile); + InitializeCerts(profile); + InitializeCRLSetFetcher(user); + InitializeCertificateTransparencyComponents(user); + InitializePrimaryProfileServices(profile, user); + } + + if (user->GetType() == user_manager::USER_TYPE_CHILD) + InitializeChildUserServices(profile); +} + +void UserSessionInitializer::InitializeChildUserServices(Profile* profile) { + ChildStatusReportingServiceFactory::GetForBrowserContext(profile); + ChildUserServiceFactory::GetForBrowserContext(profile); + ScreenTimeControllerFactory::GetForBrowserContext(profile); +} + +void UserSessionInitializer::InitRlz(Profile* profile) { +#if BUILDFLAG(ENABLE_RLZ) + // Initialize the brand code in the local prefs if it does not exist yet or + // if it is empty. The latter is to correct a problem in older builds where + // an empty brand code would be persisted if the first login after OOBE was + // a guest session. + if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand) || + g_browser_process->local_state() + ->Get(prefs::kRLZBrand) + ->GetString() + .empty()) { + // Read brand code asynchronously from an OEM data and repost ourselves. + google_brand::chromeos::InitBrand(base::Bind( + &UserSessionInitializer::InitRlz, weak_factory_.GetWeakPtr(), profile)); + return; + } + base::PostTaskAndReplyWithResult( + FROM_HERE, + {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::BindOnce(&CollectRlzParams), + base::BindOnce(&UserSessionInitializer::InitRlzImpl, + weak_factory_.GetWeakPtr(), profile)); +#endif +} + +void UserSessionInitializer::InitializeCerts(Profile* profile) { + // Now that the user profile has been initialized + // |GetNSSCertDatabaseForProfile| is safe to be used. + if (NetworkCertLoader::IsInitialized() && + base::SysInfo::IsRunningOnChromeOS()) { + GetNSSCertDatabaseForProfile(profile, + base::Bind(&OnGetNSSCertDatabaseForUser)); + } +} + +void UserSessionInitializer::InitializeCRLSetFetcher( + const user_manager::User* user) { + const std::string username_hash = user->username_hash(); + if (!username_hash.empty()) { + base::FilePath path = + ProfileHelper::GetProfilePathByUserIdHash(username_hash); + component_updater::ComponentUpdateService* cus = + g_browser_process->component_updater(); + if (cus) + component_updater::RegisterCRLSetComponent(cus, path); + } +} + +void UserSessionInitializer::InitializeCertificateTransparencyComponents( + const user_manager::User* user) { + const std::string username_hash = user->username_hash(); + if (!username_hash.empty()) { + base::FilePath path = + ProfileHelper::GetProfilePathByUserIdHash(username_hash); + component_updater::DeleteLegacySTHSet(path); + } +} + +void UserSessionInitializer::InitializePrimaryProfileServices( + Profile* profile, + const user_manager::User* user) { + lock_screen_apps::StateController::Get()->SetPrimaryProfile(profile); + + if (user->GetType() == user_manager::USER_TYPE_REGULAR) { + // App install logs are uploaded via the user's communication channel with + // the management server. This channel exists for regular users only. + // The |AppInstallEventLogManagerWrapper| manages its own lifetime and + // self-destructs on logout. + policy::AppInstallEventLogManagerWrapper::CreateForProfile(profile); + } + arc::ArcServiceLauncher::Get()->OnPrimaryUserProfilePrepared(profile); + + crostini::CrostiniManager* crostini_manager = + crostini::CrostiniManager::GetForProfile(profile); + if (crostini_manager) + crostini_manager->MaybeUpgradeCrostini(); + + g_browser_process->platform_part()->InitializePrimaryProfileServices(profile); +} + +void UserSessionInitializer::InitRlzImpl(Profile* profile, + const RlzInitParams& params) { +#if BUILDFLAG(ENABLE_RLZ) + // If RLZ is disabled then clear the brand for the session. + // + // RLZ is disabled if disabled explicitly OR if the device's enrollment + // state is not yet known. The device's enrollment state is definitively + // known once the device is locked. Note that for enrolled devices, the + // enrollment login locks the device. + // + // There the following cases to consider when a session starts: + // + // 1) This is a regular session. + // 1a) The device is LOCKED. Thus, the enrollment state is KNOWN. + // 1b) The device is NOT LOCKED. This should only happen on the first + // regular login (due to lock race condition with this code) if the + // device is NOT enrolled; thus, the enrollment state is also KNOWN. + // + // 2) This is a guest session. + // 2a) The device is LOCKED. Thus, the enrollment state is KNOWN. + // 2b) The device is NOT locked. This should happen if ONLY Guest mode + // sessions have ever been used on this device. This is the only + // situation where the enrollment state is NOT KNOWN at this point. + + PrefService* local_state = g_browser_process->local_state(); + if (params.disabled || (profile->IsGuestSession() && + !InstallAttributes::Get()->IsDeviceLocked())) { + // Empty brand code means an organic install (no RLZ pings are sent). + google_brand::chromeos::ClearBrandForCurrentSession(); + } + if (params.disabled != local_state->GetBoolean(prefs::kRLZDisabled)) { + // When switching to RLZ enabled/disabled state, clear all recorded events. + rlz::RLZTracker::ClearRlzState(); + local_state->SetBoolean(prefs::kRLZDisabled, params.disabled); + } + // Init the RLZ library. + int ping_delay = profile->GetPrefs()->GetInteger(prefs::kRlzPingDelaySeconds); + // Negative ping delay means to send ping immediately after a first search is + // recorded. + bool send_ping_immediately = ping_delay < 0; + base::TimeDelta delay = base::TimeDelta::FromSeconds(abs(ping_delay)) - + params.time_since_oobe_completion; + rlz::RLZTracker::SetRlzDelegate( + base::WrapUnique(new ChromeRLZTrackerDelegate)); + rlz::RLZTracker::InitRlzDelayed( + user_manager::UserManager::Get()->IsCurrentUserNew(), + send_ping_immediately, delay, + ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(profile), + ChromeRLZTrackerDelegate::IsGoogleHomepage(profile), + ChromeRLZTrackerDelegate::IsGoogleInStartpages(profile)); +#endif +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/session/user_session_initializer.h b/chrome/browser/chromeos/login/session/user_session_initializer.h new file mode 100644 index 0000000..cbe2ed0 --- /dev/null +++ b/chrome/browser/chromeos/login/session/user_session_initializer.h
@@ -0,0 +1,74 @@ +// Copyright 2020 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_LOGIN_SESSION_USER_SESSION_INITIALIZER_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_USER_SESSION_INITIALIZER_H_ + +#include "components/session_manager/core/session_manager_observer.h" +#include "components/user_manager/user.h" + +class Profile; + +namespace user_manager { +class User; +} + +namespace chromeos { + +class UserSessionInitializer : public session_manager::SessionManagerObserver { + public: + // Parameters to use when initializing the RLZ library. These fields need + // to be retrieved from a blocking task and this structure is used to pass + // the data. + struct RlzInitParams { + // Set to true if RLZ is disabled. + bool disabled; + + // The elapsed time since the device went through the OOBE. This can + // be a very long time. + base::TimeDelta time_since_oobe_completion; + }; + + UserSessionInitializer(); + UserSessionInitializer(const UserSessionInitializer&) = delete; + UserSessionInitializer& operator=(const UserSessionInitializer&) = delete; + ~UserSessionInitializer() override; + + // Returns UserSessionInitializer instance. + static UserSessionInitializer* Get(); + + // session_manager::SessionManagerObserver: + void OnUserProfileLoaded(const AccountId& account_id) override; + + // Initialize child user profile services that depend on the policy. + void InitializeChildUserServices(Profile* profile); + + private: + // Initialize RLZ. + void InitRlz(Profile* profile); + + // Get the NSS cert database for the user represented with |profile| + // and start certificate loader with it. + void InitializeCerts(Profile* profile); + + // Starts loading CRL set. + void InitializeCRLSetFetcher(const user_manager::User* user); + + // Initializes Certificate Transparency-related components. + void InitializeCertificateTransparencyComponents( + const user_manager::User* user); + + // Initialize all services that need the primary profile. + void InitializePrimaryProfileServices(Profile* profile, + const user_manager::User* user); + + // Initializes RLZ. If |disabled| is true, RLZ pings are disabled. + void InitRlzImpl(Profile* profile, const RlzInitParams& params); + + base::WeakPtrFactory<UserSessionInitializer> weak_factory_{this}; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SESSION_USER_SESSION_INITIALIZER_H_
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 5b80bf9e..1e68513 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -20,7 +20,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/feature_list.h" -#include "base/files/file_util.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -31,7 +30,6 @@ #include "base/strings/string16.h" #include "base/system/sys_info.h" #include "base/task/post_task.h" -#include "base/task/thread_pool.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/about_flags.h" #include "chrome/browser/app_mode/app_mode_utils.h" @@ -42,17 +40,11 @@ #include "chrome/browser/chromeos/account_manager/account_manager_util.h" #include "chrome/browser/chromeos/arc/arc_migration_guide_notification.h" #include "chrome/browser/chromeos/arc/arc_util.h" -#include "chrome/browser/chromeos/arc/session/arc_service_launcher.h" #include "chrome/browser/chromeos/base/locale_util.h" #include "chrome/browser/chromeos/boot_times_recorder.h" #include "chrome/browser/chromeos/child_accounts/child_policy_observer.h" -#include "chrome/browser/chromeos/child_accounts/child_status_reporting_service_factory.h" -#include "chrome/browser/chromeos/child_accounts/child_user_service_factory.h" -#include "chrome/browser/chromeos/child_accounts/screen_time_controller_factory.h" -#include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/first_run/first_run.h" #include "chrome/browser/chromeos/first_run/goodies_displayer.h" -#include "chrome/browser/chromeos/lock_screen_apps/state_controller.h" #include "chrome/browser/chromeos/logging.h" #include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h" #include "chrome/browser/chromeos/login/chrome_restart_request.h" @@ -69,6 +61,7 @@ #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h" #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen.h" #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h" +#include "chrome/browser/chromeos/login/session/user_session_initializer.h" #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h" #include "chrome/browser/chromeos/login/signin/token_handle_fetcher.h" #include "chrome/browser/chromeos/login/startup_utils.h" @@ -78,7 +71,6 @@ #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/supervised_user_manager.h" #include "chrome/browser/chromeos/login/wizard_controller.h" -#include "chrome/browser/chromeos/policy/app_install_event_log_manager_wrapper.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -87,13 +79,9 @@ #include "chrome/browser/chromeos/tether/tether_service.h" #include "chrome/browser/chromeos/tpm_firmware_update_notification.h" #include "chrome/browser/chromeos/u2f_notification.h" -#include "chrome/browser/component_updater/crl_set_component_installer.h" -#include "chrome/browser/component_updater/sth_set_component_remover.h" #include "chrome/browser/first_run/first_run.h" -#include "chrome/browser/google/google_brand_chromeos.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/lifetime/browser_shutdown.h" -#include "chrome/browser/net/nss_context.h" #include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/prefs/session_startup_pref.h" @@ -131,11 +119,9 @@ #include "chromeos/login/auth/challenge_response/known_user_pref_utils.h" #include "chromeos/login/auth/stub_authenticator_builder.h" #include "chromeos/login/session/session_termination_manager.h" -#include "chromeos/network/network_cert_loader.h" #include "chromeos/network/portal_detector/network_portal_detector.h" #include "chromeos/network/portal_detector/network_portal_detector_strategy.h" #include "chromeos/settings/cros_settings_names.h" -#include "chromeos/tpm/install_attributes.h" #include "components/account_id/account_id.h" #include "components/component_updater/component_updater_service.h" #include "components/flags_ui/pref_service_flags_storage.h" @@ -174,11 +160,6 @@ #include "ui/message_center/public/cpp/notifier_id.h" #include "url/gurl.h" -#if BUILDFLAG(ENABLE_RLZ) -#include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h" -#include "components/rlz/rlz_tracker.h" -#endif - using signin::ConsentLevel; namespace chromeos { @@ -298,27 +279,6 @@ prefs->SetBoolean(prefs::kLanguageShouldMergeInputMethods, true); } -#if BUILDFLAG(ENABLE_RLZ) -// Flag file that disables RLZ tracking, when present. -const base::FilePath::CharType kRLZDisabledFlagName[] = - FILE_PATH_LITERAL(".rlz_disabled"); - -base::FilePath GetRlzDisabledFlagPath() { - base::FilePath homedir; - base::PathService::Get(base::DIR_HOME, &homedir); - return homedir.Append(kRLZDisabledFlagName); -} -#endif - -// Callback to GetNSSCertDatabaseForProfile. It passes the user-specific NSS -// database to NetworkCertLoader. It must be called for primary user only. -void OnGetNSSCertDatabaseForUser(net::NSSCertDatabase* database) { - if (!NetworkCertLoader::IsInitialized()) - return; - - NetworkCertLoader::Get()->SetUserNSSDB(database); -} - // Returns new CommandLine with per-user flags. base::CommandLine CreatePerSessionCommandLine(Profile* profile) { base::CommandLine user_flags(base::CommandLine::NO_PROGRAM); @@ -402,16 +362,6 @@ ::switches::kTestType); } -#if BUILDFLAG(ENABLE_RLZ) -UserSessionManager::RlzInitParams CollectRlzParams() { - UserSessionManager::RlzInitParams params; - params.disabled = base::PathExists(GetRlzDisabledFlagPath()); - params.time_since_oobe_completion = - chromeos::StartupUtils::GetTimeSinceOobeFlagFileCreation(); - return params; -} -#endif - bool IsOnlineSignin(const UserContext& user_context) { return user_context.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITH_SAML || user_context.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML; @@ -695,31 +645,6 @@ return user_sessions_restore_in_progress_; } -void UserSessionManager::InitRlz(Profile* profile) { -#if BUILDFLAG(ENABLE_RLZ) - // Initialize the brand code in the local prefs if it does not exist yet or - // if it is empty. The latter is to correct a problem in older builds where - // an empty brand code would be persisted if the first login after OOBE was - // a guest session. - if (!g_browser_process->local_state()->HasPrefPath(prefs::kRLZBrand) || - g_browser_process->local_state() - ->Get(prefs::kRLZBrand) - ->GetString() - .empty()) { - // Read brand code asynchronously from an OEM data and repost ourselves. - google_brand::chromeos::InitBrand( - base::Bind(&UserSessionManager::InitRlz, AsWeakPtr(), profile)); - return; - } - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - base::BindOnce(&CollectRlzParams), - base::BindOnce(&UserSessionManager::InitRlzImpl, AsWeakPtr(), profile)); -#endif -} - void UserSessionManager::InitNonKioskExtensionFeaturesSessionType( const user_manager::User* user) { // Kiosk session should be set as part of kiosk user session initialization @@ -963,16 +888,19 @@ IdentityManagerFactory::GetForProfile(user_profile); switch (state) { case OAuth2LoginManager::SESSION_RESTORE_DONE: - if (identity_manager) { - // Now SESSION_RESTORE_DONE state means that primary account has a valid - // token. - DCHECK( - !identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( - identity_manager - ->GetPrimaryAccountInfo(ConsentLevel::kNotRequired) - .account_id)); - } - user_status = user_manager::User::OAUTH2_TOKEN_STATUS_VALID; + // Session restore done does not always mean valid token because the + // merge session operation could be skipped when the first account in + // Gaia cookies matches the primary account in TokenService. However + // the token could still be invalid in some edge cases. See + // http://crbug.com/760610 + user_status = + (identity_manager && + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + identity_manager + ->GetPrimaryAccountInfo(ConsentLevel::kNotRequired) + .account_id)) + ? user_manager::User::OAUTH2_TOKEN_STATUS_INVALID + : user_manager::User::OAUTH2_TOKEN_STATUS_VALID; break; case OAuth2LoginManager::SESSION_RESTORE_FAILED: user_status = user_manager::User::OAUTH2_TOKEN_STATUS_INVALID; @@ -1688,11 +1616,6 @@ // Initialize various services only for primary user. if (user_manager->GetPrimaryUser() == user) { - InitRlz(profile); - InitializeCerts(profile); - InitializeCRLSetFetcher(user); - InitializeCertificateTransparencyComponents(user); - InitializePrimaryProfileServices(profile, user); StartTetherServiceIfPossible(profile); // PrefService is ready, check whether we need to force a VPN connection. @@ -1738,7 +1661,6 @@ kWaitForChildPolicyTimeout); return; } - InitializeChildUserServices(profile); } InitializeBrowser(profile); @@ -1900,120 +1822,6 @@ user_context_.GetAccessToken()); } -void UserSessionManager::InitRlzImpl(Profile* profile, - const RlzInitParams& params) { -#if BUILDFLAG(ENABLE_RLZ) - // If RLZ is disabled then clear the brand for the session. - // - // RLZ is disabled if disabled explicitly OR if the device's enrollment - // state is not yet known. The device's enrollment state is definitively - // known once the device is locked. Note that for enrolled devices, the - // enrollment login locks the device. - // - // There the following cases to consider when a session starts: - // - // 1) This is a regular session. - // 1a) The device is LOCKED. Thus, the enrollment state is KNOWN. - // 1b) The device is NOT LOCKED. This should only happen on the first - // regular login (due to lock race condition with this code) if the - // device is NOT enrolled; thus, the enrollment state is also KNOWN. - // - // 2) This is a guest session. - // 2a) The device is LOCKED. Thus, the enrollment state is KNOWN. - // 2b) The device is NOT locked. This should happen if ONLY Guest mode - // sessions have ever been used on this device. This is the only - // situation where the enrollment state is NOT KNOWN at this point. - - PrefService* local_state = g_browser_process->local_state(); - if (params.disabled || (profile->IsGuestSession() && - !InstallAttributes::Get()->IsDeviceLocked())) { - // Empty brand code means an organic install (no RLZ pings are sent). - google_brand::chromeos::ClearBrandForCurrentSession(); - } - if (params.disabled != local_state->GetBoolean(prefs::kRLZDisabled)) { - // When switching to RLZ enabled/disabled state, clear all recorded events. - rlz::RLZTracker::ClearRlzState(); - local_state->SetBoolean(prefs::kRLZDisabled, params.disabled); - } - // Init the RLZ library. - int ping_delay = profile->GetPrefs()->GetInteger(prefs::kRlzPingDelaySeconds); - // Negative ping delay means to send ping immediately after a first search is - // recorded. - bool send_ping_immediately = ping_delay < 0; - base::TimeDelta delay = base::TimeDelta::FromSeconds(abs(ping_delay)) - - params.time_since_oobe_completion; - rlz::RLZTracker::SetRlzDelegate( - base::WrapUnique(new ChromeRLZTrackerDelegate)); - rlz::RLZTracker::InitRlzDelayed( - user_manager::UserManager::Get()->IsCurrentUserNew(), - send_ping_immediately, delay, - ChromeRLZTrackerDelegate::IsGoogleDefaultSearch(profile), - ChromeRLZTrackerDelegate::IsGoogleHomepage(profile), - ChromeRLZTrackerDelegate::IsGoogleInStartpages(profile)); -#endif -} - -void UserSessionManager::InitializeCerts(Profile* profile) { - // Now that the user profile has been initialized - // |GetNSSCertDatabaseForProfile| is safe to be used. - if (NetworkCertLoader::IsInitialized() && - base::SysInfo::IsRunningOnChromeOS()) { - GetNSSCertDatabaseForProfile(profile, - base::Bind(&OnGetNSSCertDatabaseForUser)); - } -} - -void UserSessionManager::InitializeCRLSetFetcher( - const user_manager::User* user) { - const std::string username_hash = user->username_hash(); - if (!username_hash.empty()) { - base::FilePath path = - ProfileHelper::GetProfilePathByUserIdHash(username_hash); - component_updater::ComponentUpdateService* cus = - g_browser_process->component_updater(); - if (cus) - component_updater::RegisterCRLSetComponent(cus, path); - } -} - -void UserSessionManager::InitializeCertificateTransparencyComponents( - const user_manager::User* user) { - const std::string username_hash = user->username_hash(); - if (!username_hash.empty()) { - base::FilePath path = - ProfileHelper::GetProfilePathByUserIdHash(username_hash); - component_updater::DeleteLegacySTHSet(path); - } -} - -void UserSessionManager::InitializeChildUserServices(Profile* profile) { - ChildStatusReportingServiceFactory::GetForBrowserContext(profile); - ChildUserServiceFactory::GetForBrowserContext(profile); - ScreenTimeControllerFactory::GetForBrowserContext(profile); -} - -void UserSessionManager::InitializePrimaryProfileServices( - Profile* profile, - const user_manager::User* user) { - lock_screen_apps::StateController::Get()->SetPrimaryProfile(profile); - - if (user->GetType() == user_manager::USER_TYPE_REGULAR) { - // App install logs are uploaded via the user's communication channel with - // the management server. This channel exists for regular users only. - // The |AppInstallEventLogManagerWrapper| manages its own lifetime and - // self-destructs on logout. - policy::AppInstallEventLogManagerWrapper::CreateForProfile(profile); - } - arc::ArcServiceLauncher::Get()->OnPrimaryUserProfilePrepared(profile); - - crostini::CrostiniManager* crostini_manager = - crostini::CrostiniManager::GetForProfile(profile); - if (crostini_manager) - crostini_manager->MaybeUpgradeCrostini(); - - g_browser_process->platform_part()->InitializePrimaryProfileServices(profile); -} - void UserSessionManager::NotifyUserProfileLoaded( Profile* profile, const user_manager::User* user) { @@ -2228,7 +2036,8 @@ child_policy_observer_.reset(); - InitializeChildUserServices(profile); + UserSessionInitializer::Get()->InitializeChildUserServices(profile); + InitializeBrowser(profile); }
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h index ea3b713..a7751c7 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.h +++ b/chrome/browser/chromeos/login/session/user_session_manager.h
@@ -132,18 +132,6 @@ kPolicyAndFlagsAndKioskControl }; - // Parameters to use when initializing the RLZ library. These fields need - // to be retrieved from a blocking task and this structure is used to pass - // the data. - struct RlzInitParams { - // Set to true if RLZ is disabled. - bool disabled; - - // The elapsed time since the device went through the OOBE. This can - // be a very long time. - base::TimeDelta time_since_oobe_completion; - }; - // To keep track of which systems need the login password to be stored in the // kernel keyring. enum class PasswordConsumingService { @@ -219,27 +207,6 @@ // user sessions restoration is in progress. bool UserSessionsRestoreInProgress() const; - // Initialize RLZ. - void InitRlz(Profile* profile); - - // Get the NSS cert database for the user represented with |profile| - // and start certificate loader with it. - void InitializeCerts(Profile* profile); - - // Starts loading CRL set. - void InitializeCRLSetFetcher(const user_manager::User* user); - - // Initializes Certificate Transparency-related components. - void InitializeCertificateTransparencyComponents( - const user_manager::User* user); - - // Initialize child user profile services that depend on the policy. - void InitializeChildUserServices(Profile* profile); - - // Initialize all services that need the primary profile. - void InitializePrimaryProfileServices(Profile* profile, - const user_manager::User* user); - // Send the notification before creating the browser so additional objects // that need the profile (e.g. the launcher) can be created first. void NotifyUserProfileLoaded(Profile* profile, @@ -481,9 +448,6 @@ // Restores GAIA auth cookies for the created user profile from OAuth2 token. void RestoreAuthSessionImpl(Profile* profile, bool restore_from_auth_cookies); - // Initializes RLZ. If |disabled| is true, RLZ pings are disabled. - void InitRlzImpl(Profile* profile, const RlzInitParams& params); - // If |user| is not a kiosk app, sets session type as seen by extensions // feature system according to |user|'s type. // The value should eventually be set for kiosk users, too - that's done as
diff --git a/chrome/browser/chromeos/login/signin/merge_session_navigation_throttle.cc b/chrome/browser/chromeos/login/signin/merge_session_navigation_throttle.cc index 57ff3cb..7e8ce168 100644 --- a/chrome/browser/chromeos/login/signin/merge_session_navigation_throttle.cc +++ b/chrome/browser/chromeos/login/signin/merge_session_navigation_throttle.cc
@@ -7,7 +7,6 @@ #include "base/time/time.h" #include "chrome/browser/chromeos/login/signin/merge_session_throttling_utils.h" #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h" -#include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc index 2cd43e5..0643dc6 100644 --- a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc +++ b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc
@@ -14,7 +14,6 @@ #include "base/time/time.h" #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h" #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h" -#include "chrome/browser/profiles/profile.h" #include "chrome/common/url_constants.h" #include "components/google/core/common/google_util.h" #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc index 3fd1836..1d992f7e 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -701,6 +701,57 @@ ->is_under_advanced_protection); } +// Sets up a new user with stored refresh token. +IN_PROC_BROWSER_TEST_F(OAuth2Test, PRE_SetInvalidTokenStatus) { + StartNewUserSession(/*wait_for_merge=*/true, + /*is_under_advanced_protection=*/false); +} + +// Tests that an auth error marks invalid auth token status despite +// OAuth2LoginManager thinks merge session is done successfully +IN_PROC_BROWSER_TEST_F(OAuth2Test, SetInvalidTokenStatus) { + RequestDeferrer list_accounts_request_deferer; + AddRequestDeferer("/ListAccounts", &list_accounts_request_deferer); + + SetupGaiaServerForUnexpiredAccount(); + SimulateNetworkOnline(); + + // Signs in as the existing user created in pre test. + ExistingUserController* const controller = + ExistingUserController::current_controller(); + UserContext user_context( + user_manager::USER_TYPE_REGULAR, + AccountId::FromUserEmailGaiaId(kTestEmail, kTestGaiaId)); + user_context.SetKey(Key(kTestAccountPassword)); + controller->Login(user_context, SigninSpecifics()); + + // Wait until /ListAccounts request happens so that an auth error can be + // generated after user profile is available but before merge session + // finishes. + list_accounts_request_deferer.WaitForRequestToStart(); + + // Make sure that merge session is not finished. + OAuth2LoginManager* const login_manager = + OAuth2LoginManagerFactory::GetInstance()->GetForProfile(GetProfile()); + ASSERT_NE(OAuth2LoginManager::SESSION_RESTORE_DONE, login_manager->state()); + + // Generate an auth error. + signin::SetInvalidRefreshTokenForAccount( + IdentityManagerFactory::GetInstance()->GetForProfile(GetProfile()), + PickAccountId(GetProfile(), kTestGaiaId, kTestEmail)); + + // Let go /ListAccounts request. + list_accounts_request_deferer.UnblockRequest(); + + // Wait for the session merge to finish with success. + WaitForMergeSessionCompletion(OAuth2LoginManager::SESSION_RESTORE_DONE); + + // User oauth2 token status should be marked as invalid because of auth error + // and regardless of the merge session outcome. + EXPECT_EQ(GetOAuthStatusFromLocalState(kTestEmail), + user_manager::User::OAUTH2_TOKEN_STATUS_INVALID); +} + constexpr char kGooglePageContent[] = "<html><title>Hello!</title><script>alert('hello');</script>" "<body>Hello Google!</body></html>"; @@ -709,7 +760,6 @@ constexpr char kHelloPagePath[] = "/hello_google"; constexpr char kRandomPagePath[] = "/non_google_page"; constexpr char kMergeSessionPath[] = "/MergeSession"; -constexpr char kMultiLoginPath[] = "/oauth/multilogin"; // FakeGoogle serves content of http://www.google.com/hello_google page for // merge session tests. @@ -742,8 +792,7 @@ http_response->set_code(net::HTTP_OK); http_response->set_content_type("text/html"); http_response->set_content(kRandomPageContent); - } else if ((hang_merge_session_ && request_path == kMergeSessionPath) || - (hang_merge_session_ && request_path == kMultiLoginPath)) { + } else if (hang_merge_session_ && request_path == kMergeSessionPath) { merge_session_event_.Signal(); base::PostTask(FROM_HERE, {content::BrowserThread::UI}, base::BindOnce(&FakeGoogle::QuitMergeRunnerOnUIThread, @@ -827,7 +876,6 @@ void RegisterAdditionalRequestHandlers() override { OAuth2Test::RegisterAdditionalRequestHandlers(); AddRequestDeferer("/MergeSession", &merge_session_deferer_); - AddRequestDeferer("/oauth/multilogin", &merge_session_deferer_); embedded_test_server()->RegisterRequestHandler(base::BindRepeating( &FakeGoogle::HandleRequest, base::Unretained(&fake_google_)));
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc index a3034d4..038a994 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
@@ -9,13 +9,9 @@ #include "base/command_line.h" #include "base/metrics/histogram_macros.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/account_manager/account_manager_migrator.h" -#include "chrome/browser/chromeos/account_manager/account_migration_runner.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/account_id_from_account_info.h" -#include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/chrome_device_id_helper.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chromeos/constants/chromeos_switches.h" @@ -71,12 +67,6 @@ << "Exchanging cookies for OAuth 2.0 tokens is no longer supported"; SetSessionRestoreState(OAuth2LoginManager::SESSION_RESTORE_PREPARING); - account_reconcilor_observer_.Add(GetAccountReconcilor()); - - // AccountReconcilor may be disabled while migrations are running. - if (GetAccountReconcilor()->IsReconcileEnabled()) { - OnStateChanged(GetAccountReconcilor()->GetState()); - } // Save passed OAuth2 refresh token. if (restore_strategy_ == RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN) { @@ -91,10 +81,12 @@ } void OAuth2LoginManager::RestoreSessionFromSavedTokens() { - SetSessionRestoreState(OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS); signin::IdentityManager* identity_manager = GetIdentityManager(); - if (!identity_manager->HasAccountWithRefreshToken( + if (identity_manager->HasAccountWithRefreshToken( GetUnconsentedPrimaryAccountId())) { + VLOG(1) << "OAuth2 refresh token is already loaded."; + VerifySessionCookies(); + } else { VLOG(1) << "Waiting for OAuth2 refresh token being loaded from database."; // Flag user with unknown token status in case there are no saved tokens @@ -110,6 +102,10 @@ } } +void OAuth2LoginManager::Stop() { + login_verifier_.reset(); +} + bool OAuth2LoginManager::SessionRestoreIsRunning() const { return state_ == SESSION_RESTORE_PREPARING || state_ == SESSION_RESTORE_IN_PROGRESS; @@ -137,29 +133,17 @@ } // Only restore session cookies for the primary account in the profile. if (GetUnconsentedPrimaryAccountId() == account_info.account_id) { + // The refresh token has changed, so stop any ongoing actions that were + // based on the old refresh token. + Stop(); + // Token is loaded. Undo the flagging before token loading. DCHECK(!account_info.gaia.empty()); user_manager::UserManager::Get()->SaveUserOAuthStatus( AccountIdFromAccountInfo(account_info), user_manager::User::OAUTH2_TOKEN_STATUS_VALID); - } -} -void OAuth2LoginManager::OnStateChanged( - signin_metrics::AccountReconcilorState state) { - if (state == signin_metrics::AccountReconcilorState::ACCOUNT_RECONCILOR_OK) { - RecordSessionRestoreOutcome(SESSION_RESTORE_SUCCESS, SESSION_RESTORE_DONE); - GetAccountReconcilor()->RemoveObserver(this); - } else if (state == - signin_metrics::AccountReconcilorState::ACCOUNT_RECONCILOR_ERROR) { - if (GetAccountReconcilor()->GetReconcileError().IsTransientError()) { - RecordSessionRestoreOutcome(SESSION_RESTORE_MERGE_SESSION_FAILED, - SESSION_RESTORE_CONNECTION_FAILED); - } else { - RecordSessionRestoreOutcome(SESSION_RESTORE_MERGE_SESSION_FAILED, - SESSION_RESTORE_FAILED); - } - GetAccountReconcilor()->RemoveObserver(this); + VerifySessionCookies(); } } @@ -167,10 +151,6 @@ return IdentityManagerFactory::GetForProfile(user_profile_); } -AccountReconcilor* OAuth2LoginManager::GetAccountReconcilor() { - return AccountReconcilorFactory::GetForProfile(user_profile_); -} - CoreAccountId OAuth2LoginManager::GetUnconsentedPrimaryAccountId() { // Use the primary ID whether or not the user has consented to browser sync. const CoreAccountId primary_account_id = @@ -200,9 +180,103 @@ OnRefreshTokenUpdatedForAccount(primary_account_info); } +void OAuth2LoginManager::VerifySessionCookies() { + DCHECK(!login_verifier_.get()); + login_verifier_ = std::make_unique<OAuth2LoginVerifier>( + this, GetIdentityManager(), GetUnconsentedPrimaryAccountId(), + oauthlogin_access_token_); + + if (restore_strategy_ == RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN) { + login_verifier_->VerifyUserCookies(); + return; + } + + RestoreSessionCookies(); +} + +void OAuth2LoginManager::RestoreSessionCookies() { + SetSessionRestoreState(SESSION_RESTORE_IN_PROGRESS); + login_verifier_->VerifyProfileTokens(); +} + void OAuth2LoginManager::Shutdown() { GetIdentityManager()->RemoveObserver(this); - account_reconcilor_observer_.RemoveAll(); + login_verifier_.reset(); +} + +void OAuth2LoginManager::OnSessionMergeSuccess() { + VLOG(1) << "OAuth2 refresh and/or GAIA token verification succeeded."; + RecordSessionRestoreOutcome(SESSION_RESTORE_SUCCESS, SESSION_RESTORE_DONE); +} + +void OAuth2LoginManager::OnSessionMergeFailure(bool connection_error) { + LOG(ERROR) << "OAuth2 refresh and GAIA token verification failed!" + << " connection_error: " << connection_error; + RecordSessionRestoreOutcome(SESSION_RESTORE_MERGE_SESSION_FAILED, + connection_error + ? SESSION_RESTORE_CONNECTION_FAILED + : SESSION_RESTORE_FAILED); +} + +void OAuth2LoginManager::OnListAccountsSuccess( + const std::vector<gaia::ListedAccount>& accounts) { + MergeVerificationOutcome outcome = POST_MERGE_SUCCESS; + // Let's analyze which accounts we see logged in here: + CoreAccountId user_account_id = GetUnconsentedPrimaryAccountId(); + if (!accounts.empty()) { + bool found = false; + bool first = true; + for (std::vector<gaia::ListedAccount>::const_iterator iter = + accounts.begin(); + iter != accounts.end(); ++iter) { + if (iter->id == user_account_id) { + found = iter->valid; + break; + } + + first = false; + } + + if (!found) + outcome = POST_MERGE_MISSING_PRIMARY_ACCOUNT; + else if (!first) + outcome = POST_MERGE_PRIMARY_NOT_FIRST_ACCOUNT; + + } else { + outcome = POST_MERGE_NO_ACCOUNTS; + } + + bool is_pre_merge = (state_ == SESSION_RESTORE_PREPARING); + RecordCookiesCheckOutcome(is_pre_merge, outcome); + // If the primary account is missing during the initial cookie freshness + // check, try to restore GAIA session cookies form the OAuth2 tokens. + if (is_pre_merge) { + if (outcome != POST_MERGE_SUCCESS && + outcome != POST_MERGE_PRIMARY_NOT_FIRST_ACCOUNT) { + RestoreSessionCookies(); + } else { + // We are done with this account, it's GAIA cookies are legit. + RecordSessionRestoreOutcome(SESSION_RESTORE_NOT_NEEDED, + SESSION_RESTORE_DONE); + } + } +} + +void OAuth2LoginManager::OnListAccountsFailure(bool connection_error) { + bool is_pre_merge = (state_ == SESSION_RESTORE_PREPARING); + RecordCookiesCheckOutcome(is_pre_merge, connection_error + ? POST_MERGE_CONNECTION_FAILED + : POST_MERGE_VERIFICATION_FAILED); + if (is_pre_merge) { + if (!connection_error) { + // If we failed to get account list, our cookies might be stale so we + // need to attempt to restore them. + RestoreSessionCookies(); + } else { + RecordSessionRestoreOutcome(SESSION_RESTORE_LISTACCOUNTS_FAILED, + SESSION_RESTORE_CONNECTION_FAILED); + } + } } void OAuth2LoginManager::RecordSessionRestoreOutcome( @@ -213,6 +287,19 @@ SetSessionRestoreState(state); } +// static +void OAuth2LoginManager::RecordCookiesCheckOutcome( + bool is_pre_merge, + MergeVerificationOutcome outcome) { + if (is_pre_merge) { + UMA_HISTOGRAM_ENUMERATION("OAuth2Login.PreMergeVerification", outcome, + POST_MERGE_COUNT); + } else { + UMA_HISTOGRAM_ENUMERATION("OAuth2Login.PostMergeVerification", outcome, + POST_MERGE_COUNT); + } +} + void OAuth2LoginManager::SetSessionRestoreState( OAuth2LoginManager::SessionRestoreState state) { if (state_ == state)
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.h b/chrome/browser/chromeos/login/signin/oauth2_login_manager.h index 37c4833..52947fd 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.h +++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.h
@@ -13,8 +13,8 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "base/time/time.h" +#include "chrome/browser/chromeos/login/signin/oauth2_login_verifier.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/signin/core/browser/account_reconcilor.h" #include "components/signin/public/identity_manager/identity_manager.h" class GoogleServiceAuthError; @@ -25,8 +25,8 @@ // This class is responsible for restoring authenticated web sessions out of // OAuth2 refresh tokens or pre-authenticated cookie jar. class OAuth2LoginManager : public KeyedService, - public signin::IdentityManager::Observer, - public AccountReconcilor::Observer { + public OAuth2LoginVerifier::Delegate, + public signin::IdentityManager::Observer { public: // Session restore states. enum SessionRestoreState { @@ -143,13 +143,17 @@ // KeyedService implementation. void Shutdown() override; + // OAuth2LoginVerifier::Delegate overrides. + void OnSessionMergeSuccess() override; + void OnSessionMergeFailure(bool connection_error) override; + void OnListAccountsSuccess( + const std::vector<gaia::ListedAccount>& accounts) override; + void OnListAccountsFailure(bool connection_error) override; + // signin::IdentityManager::Observer implementation: void OnRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info) override; - // AccountReconcilor::Observer implementation: - void OnStateChanged(signin_metrics::AccountReconcilorState state) override; - // Signals delegate that authentication is completed, kicks off token fetching // process. void CompleteAuthentication(); @@ -157,10 +161,7 @@ // Retrieves IdentityManager for |user_profile_|. signin::IdentityManager* GetIdentityManager(); - // Retrieves AccountReconcilor for |user_profile_|. - AccountReconcilor* GetAccountReconcilor(); - - // Retrieves the primary account for |user_profile_|. + // Retrieves the primary account ID for |user_profile_|. CoreAccountId GetUnconsentedPrimaryAccountId(); // Records |refresh_token_| to token service. The associated account id is @@ -169,6 +170,10 @@ // retrieve the associated account info. void StoreOAuth2Token(); + // Checks if primary account sessions cookies are stale and restores them + // if needed. + void VerifySessionCookies(); + // Issue GAIA cookie recovery (MergeSession) from |refresh_token_|. void RestoreSessionCookies(); @@ -198,6 +203,8 @@ // Whether there is pending TokenService::LoadCredentials call. bool pending_token_service_load_ = false; + std::unique_ptr<OAuth2LoginVerifier> login_verifier_; + // OAuth2 refresh token. std::string refresh_token_; @@ -213,9 +220,6 @@ // can change the line below to base::ObserverList<Observer, true>. base::ObserverList<Observer, false>::Unchecked observer_list_; - ScopedObserver<AccountReconcilor, AccountReconcilor::Observer> - account_reconcilor_observer_{this}; - DISALLOW_COPY_AND_ASSIGN(OAuth2LoginManager); };
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.cc b/chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.cc index 073e9182..a188264a 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.cc
@@ -6,7 +6,6 @@ #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" @@ -17,7 +16,6 @@ "OAuth2LoginManager", BrowserContextDependencyManager::GetInstance()) { DependsOn(IdentityManagerFactory::GetInstance()); - DependsOn(AccountReconcilorFactory::GetInstance()); } OAuth2LoginManagerFactory::~OAuth2LoginManagerFactory() {}
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.cc new file mode 100644 index 0000000..eea35da --- /dev/null +++ b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.cc
@@ -0,0 +1,100 @@ +// 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/chromeos/login/signin/oauth2_login_verifier.h" + +#include <vector> + +#include "base/logging.h" +#include "components/signin/public/identity_manager/accounts_cookie_mutator.h" +#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" +#include "content/public/browser/browser_thread.h" +#include "google_apis/gaia/gaia_auth_util.h" + +using content::BrowserThread; + +namespace chromeos { + +OAuth2LoginVerifier::OAuth2LoginVerifier( + OAuth2LoginVerifier::Delegate* delegate, + signin::IdentityManager* identity_manager, + const CoreAccountId& primary_account_id, + const std::string& oauthlogin_access_token) + : delegate_(delegate), + identity_manager_(identity_manager), + primary_account_id_(primary_account_id), + access_token_(oauthlogin_access_token) { + DCHECK(delegate); + identity_manager_->AddObserver(this); +} + +OAuth2LoginVerifier::~OAuth2LoginVerifier() { + identity_manager_->RemoveObserver(this); +} + +void OAuth2LoginVerifier::VerifyUserCookies() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + std::vector<gaia::ListedAccount> accounts; + std::vector<gaia::ListedAccount> signed_out_accounts; + signin::AccountsInCookieJarInfo accounts_in_cookie_jar_info = + identity_manager_->GetAccountsInCookieJar(); + if (accounts_in_cookie_jar_info.accounts_are_fresh) { + OnAccountsInCookieUpdated( + accounts_in_cookie_jar_info, + GoogleServiceAuthError(GoogleServiceAuthError::NONE)); + } +} + +void OAuth2LoginVerifier::VerifyProfileTokens() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + signin::AccountsCookieMutator::AddAccountToCookieCompletedCallback + completion_callback = + base::BindOnce(&OAuth2LoginVerifier::OnAddAccountToCookieCompleted, + weak_ptr_factory_.GetWeakPtr()); + if (access_token_.empty()) { + identity_manager_->GetAccountsCookieMutator()->AddAccountToCookie( + primary_account_id_, gaia::GaiaSource::kOAuth2LoginVerifier, + std::move(completion_callback)); + } else { + identity_manager_->GetAccountsCookieMutator()->AddAccountToCookieWithToken( + primary_account_id_, access_token_, + gaia::GaiaSource::kOAuth2LoginVerifier, std::move(completion_callback)); + } +} + +void OAuth2LoginVerifier::OnAddAccountToCookieCompleted( + const CoreAccountId& account_id, + const GoogleServiceAuthError& error) { + if (account_id != primary_account_id_) + return; + + if (error.state() == GoogleServiceAuthError::State::NONE) { + VLOG(1) << "MergeSession successful."; + delegate_->OnSessionMergeSuccess(); + return; + } + + LOG(WARNING) << "Failed MergeSession request," + << " error: " << error.state(); + delegate_->OnSessionMergeFailure(error.IsTransientError()); +} + +void OAuth2LoginVerifier::OnAccountsInCookieUpdated( + const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info, + const GoogleServiceAuthError& error) { + if (error.state() == GoogleServiceAuthError::State::NONE) { + VLOG(1) << "ListAccounts successful."; + delegate_->OnListAccountsSuccess( + accounts_in_cookie_jar_info.signed_in_accounts); + return; + } + + LOG(WARNING) << "Failed to get list of session accounts, " + << " error: " << error.state(); + delegate_->OnListAccountsFailure(error.IsTransientError()); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_verifier.h b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.h new file mode 100644 index 0000000..c009f6a0 --- /dev/null +++ b/chrome/browser/chromeos/login/signin/oauth2_login_verifier.h
@@ -0,0 +1,76 @@ +// 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_CHROMEOS_LOGIN_SIGNIN_OAUTH2_LOGIN_VERIFIER_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_LOGIN_VERIFIER_H_ + +#include <string> +#include <utility> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/profiles/profile.h" +#include "components/signin/public/identity_manager/identity_manager.h" + +namespace chromeos { + +// Given GCMS and primary account id, this class verifies GAIA credentials +// (SAPISID) and rebuild current session's cookie jar for the primary account. +class OAuth2LoginVerifier : public signin::IdentityManager::Observer { + public: + class Delegate { + public: + virtual ~Delegate() {} + // Invoked when cookie session is successfully merged. + virtual void OnSessionMergeSuccess() = 0; + + // Invoked when cookie session can not be merged. + virtual void OnSessionMergeFailure(bool connection_error) = 0; + + // Invoked when account list is retrieved during post-merge session + // verification. + virtual void OnListAccountsSuccess( + const std::vector<gaia::ListedAccount>& accounts) = 0; + + // Invoked when post-merge session verification fails. + virtual void OnListAccountsFailure(bool connection_error) = 0; + }; + + OAuth2LoginVerifier(OAuth2LoginVerifier::Delegate* delegate, + signin::IdentityManager* identity_manager, + const CoreAccountId& primary_account_id, + const std::string& oauthlogin_access_token); + ~OAuth2LoginVerifier() override; + + // Initiates verification of GAIA cookies in the cookie jar. + void VerifyUserCookies(); + + // Attempts to restore session from OAuth2 refresh token minting all necessary + // tokens along the way (OAuth2 access token, SID/LSID, GAIA service token). + void VerifyProfileTokens(); + + private: + // IdentityManager::Observer + void OnAccountsInCookieUpdated( + const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info, + const GoogleServiceAuthError& error) override; + + void OnAddAccountToCookieCompleted(const CoreAccountId& account_id, + const GoogleServiceAuthError& error); + + OAuth2LoginVerifier::Delegate* delegate_; + signin::IdentityManager* identity_manager_; + const CoreAccountId primary_account_id_; + const std::string access_token_; + + base::WeakPtrFactory<OAuth2LoginVerifier> weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(OAuth2LoginVerifier); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_LOGIN_VERIFIER_H_
diff --git a/chrome/browser/enterprise_reporting/browser_report_generator.cc b/chrome/browser/enterprise_reporting/browser_report_generator.cc index 3cda14f..063221f1 100644 --- a/chrome/browser/enterprise_reporting/browser_report_generator.cc +++ b/chrome/browser/enterprise_reporting/browser_report_generator.cc
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" @@ -45,18 +46,16 @@ BrowserReportGenerator::~BrowserReportGenerator() = default; void BrowserReportGenerator::Generate(ReportCallback callback) { - DCHECK(!callback_); - callback_ = std::move(callback); - auto report = std::make_unique<em::BrowserReport>(); GenerateBasicInfos(report.get()); GenerateProfileInfos(report.get()); // std::move is required here because the function completes the report // asynchronously. - GeneratePluginsIfNeeded(std::move(report)); + GeneratePluginsIfNeeded(std::move(callback), std::move(report)); } +// static void BrowserReportGenerator::GenerateBasicInfos(em::BrowserReport* report) { #if !defined(OS_CHROMEOS) report->set_browser_version(version_info::GetVersionNumber()); @@ -66,6 +65,7 @@ report->set_executable_path(GetExecutablePath()); } +// static void BrowserReportGenerator::GenerateProfileInfos(em::BrowserReport* report) { for (auto* entry : g_browser_process->profile_manager() ->GetProfileAttributesStorage() @@ -86,18 +86,20 @@ } void BrowserReportGenerator::GeneratePluginsIfNeeded( + ReportCallback callback, std::unique_ptr<em::BrowserReport> report) { #if defined(OS_CHROMEOS) || !BUILDFLAG(ENABLE_PLUGINS) - std::move(callback_).Run(std::move(report)); + std::move(callback).Run(std::move(report)); #else - content::PluginService::GetInstance()->GetPlugins( - base::BindOnce(&BrowserReportGenerator::OnPluginsReady, - weak_ptr_factory_.GetWeakPtr(), std::move(report))); + content::PluginService::GetInstance()->GetPlugins(base::BindOnce( + &BrowserReportGenerator::OnPluginsReady, weak_ptr_factory_.GetWeakPtr(), + std::move(callback), std::move(report))); #endif } #if BUILDFLAG(ENABLE_PLUGINS) void BrowserReportGenerator::OnPluginsReady( + ReportCallback callback, std::unique_ptr<em::BrowserReport> report, const std::vector<content::WebPluginInfo>& plugins) { for (content::WebPluginInfo plugin : plugins) { @@ -108,7 +110,7 @@ plugin_info->set_description(base::UTF16ToUTF8(plugin.desc)); } - std::move(callback_).Run(std::move(report)); + std::move(callback).Run(std::move(report)); } #endif // BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/enterprise_reporting/browser_report_generator.h b/chrome/browser/enterprise_reporting/browser_report_generator.h index c1c08fd..abe7c33 100644 --- a/chrome/browser/enterprise_reporting/browser_report_generator.h +++ b/chrome/browser/enterprise_reporting/browser_report_generator.h
@@ -21,9 +21,7 @@ namespace enterprise_reporting { -/** - * A report generator that collects Browser related information. - */ +// A report generator that collects Browser related information. class BrowserReportGenerator { public: using ReportCallback = @@ -32,31 +30,34 @@ BrowserReportGenerator(); ~BrowserReportGenerator(); - // Generate a BrowserReport with following fields. + // Generates a BrowserReport with the following fields: // - browser_version, channel, executable_path // - user profiles: id, name, is_full_report (always be false). // - plugins: name, version, filename, description. void Generate(ReportCallback callback); private: - // Generate browser_version, channel, executable_path info in the given + // Generates browser_version, channel, executable_path info in the given // report instance. - void GenerateBasicInfos(em::BrowserReport* report); + static void GenerateBasicInfos(em::BrowserReport* report); - // Generate user profiles info in the given report instance. - void GenerateProfileInfos(em::BrowserReport* report); + // Generates user profiles info in the given report instance. + static void GenerateProfileInfos(em::BrowserReport* report); - // Generate plugin info in the given report instance, if needed. It requires - // the ownership of report instance to pass into ReportCallback method. - void GeneratePluginsIfNeeded(std::unique_ptr<em::BrowserReport> report); + // Generates plugin info in the given report instance, if needed. Passes + // |report| to |callback| either asynchronously when the plugin info is + // available, or synchronously otherwise. + void GeneratePluginsIfNeeded(ReportCallback callback, + std::unique_ptr<em::BrowserReport> report); #if BUILDFLAG(ENABLE_PLUGINS) - void OnPluginsReady(std::unique_ptr<em::BrowserReport> report, + // Populates |report| with the plugin info in |plugins|, then passes the + // report to |callback|. + void OnPluginsReady(ReportCallback callback, + std::unique_ptr<em::BrowserReport> report, const std::vector<content::WebPluginInfo>& plugins); #endif - ReportCallback callback_; - base::WeakPtrFactory<BrowserReportGenerator> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(BrowserReportGenerator);
diff --git a/chrome/browser/enterprise_reporting/report_generator.cc b/chrome/browser/enterprise_reporting/report_generator.cc index b396877..ab19826 100644 --- a/chrome/browser/enterprise_reporting/report_generator.cc +++ b/chrome/browser/enterprise_reporting/report_generator.cc
@@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/files/file_path.h" +#include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" @@ -33,28 +33,31 @@ ReportGenerator::~ReportGenerator() = default; -void ReportGenerator::Generate(ReportCallback callback) { - DCHECK(!callback_); - callback_ = std::move(callback); - CreateBasicRequest(); +void ReportGenerator::Generate(bool with_profiles, ReportCallback callback) { + CreateBasicRequest(std::make_unique<ReportRequest>(), with_profiles, + std::move(callback)); } void ReportGenerator::SetMaximumReportSizeForTesting(size_t size) { report_request_queue_generator_.SetMaximumReportSizeForTesting(size); } -void ReportGenerator::CreateBasicRequest() { +void ReportGenerator::CreateBasicRequest( + std::unique_ptr<ReportRequest> basic_request, + bool with_profiles, + ReportCallback callback) { #if defined(OS_CHROMEOS) - SetAndroidAppInfos(); + SetAndroidAppInfos(basic_request.get()); #else - basic_request_.set_computer_name(this->GetMachineName()); - basic_request_.set_os_user_name(GetOSUserName()); - basic_request_.set_serial_number(GetSerialNumber()); - basic_request_.set_allocated_os_report(GetOSReport().release()); + basic_request->set_computer_name(this->GetMachineName()); + basic_request->set_os_user_name(GetOSUserName()); + basic_request->set_serial_number(GetSerialNumber()); + basic_request->set_allocated_os_report(GetOSReport().release()); #endif browser_report_generator_.Generate(base::BindOnce( - &ReportGenerator::OnBrowserReportReady, weak_ptr_factory_.GetWeakPtr())); + &ReportGenerator::OnBrowserReportReady, weak_ptr_factory_.GetWeakPtr(), + with_profiles, std::move(callback), std::move(basic_request))); } std::unique_ptr<em::OSReport> ReportGenerator::GetOSReport() { @@ -84,8 +87,9 @@ #if defined(OS_CHROMEOS) -void ReportGenerator::SetAndroidAppInfos() { - basic_request_.clear_android_app_infos(); +void ReportGenerator::SetAndroidAppInfos(ReportRequest* basic_request) { + DCHECK(basic_request); + basic_request->clear_android_app_infos(); // Android application is only supported for primary profile. Profile* primary_profile = @@ -106,7 +110,7 @@ AndroidAppInfoGenerator generator; for (std::string app_id : prefs->GetAppIds()) { - em::AndroidAppInfo* app_info = basic_request_.add_android_app_infos(); + em::AndroidAppInfo* app_info = basic_request->add_android_app_infos(); generator.Generate(prefs, app_id)->Swap(app_info); } } @@ -114,11 +118,24 @@ #endif void ReportGenerator::OnBrowserReportReady( + bool with_profiles, + ReportCallback callback, + std::unique_ptr<ReportRequest> basic_request, std::unique_ptr<em::BrowserReport> browser_report) { - basic_request_.set_allocated_browser_report(browser_report.release()); - ReportRequests requests = - report_request_queue_generator_.Generate(basic_request_); - std::move(callback_).Run(std::move(requests)); + basic_request->set_allocated_browser_report(browser_report.release()); + + if (with_profiles) { + // Generate a queue of requests containing detailed profile information. + std::move(callback).Run( + report_request_queue_generator_.Generate(*basic_request)); + return; + } + + // Return a queue containing only the basic request and browser report without + // detailed profile information. + ReportRequests requests; + requests.push(std::move(basic_request)); + std::move(callback).Run(std::move(requests)); } } // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise_reporting/report_generator.h b/chrome/browser/enterprise_reporting/report_generator.h index a224705..2b62a6c 100644 --- a/chrome/browser/enterprise_reporting/report_generator.h +++ b/chrome/browser/enterprise_reporting/report_generator.h
@@ -30,13 +30,19 @@ ReportGenerator(); virtual ~ReportGenerator(); - virtual void Generate(ReportCallback callback); + // Asynchronously generates a queue of report requests, providing them to + // |callback| when ready. If |with_profiles| is true, full details are + // included for all loaded profiles; otherwise, only profile name and path + // are included. + virtual void Generate(bool with_profiles, ReportCallback callback); void SetMaximumReportSizeForTesting(size_t size); protected: // Creates a basic request that will be used by all Profiles. - void CreateBasicRequest(); + void CreateBasicRequest(std::unique_ptr<ReportRequest> basic_request, + bool with_profiles, + ReportCallback callback); // Returns an OS report contains basic OS information includes OS name, OS // architecture and OS version. @@ -55,17 +61,17 @@ #if defined(OS_CHROMEOS) // Collect the Android application information installed on primary profile, // and set it to |basic_request_|. - virtual void SetAndroidAppInfos(); + virtual void SetAndroidAppInfos(ReportRequest* basic_request); #endif private: - void OnBrowserReportReady(std::unique_ptr<em::BrowserReport> browser_report); + void OnBrowserReportReady(bool with_profiles, + ReportCallback callback, + std::unique_ptr<ReportRequest> basic_request, + std::unique_ptr<em::BrowserReport> browser_report); ReportRequestQueueGenerator report_request_queue_generator_; BrowserReportGenerator browser_report_generator_; - ReportCallback callback_; - // Basic information that is shared among requests. - ReportRequest basic_request_; base::WeakPtrFactory<ReportGenerator> weak_ptr_factory_{this};
diff --git a/chrome/browser/enterprise_reporting/report_generator_unittest.cc b/chrome/browser/enterprise_reporting/report_generator_unittest.cc index b9e6202..7c54c0d9f 100644 --- a/chrome/browser/enterprise_reporting/report_generator_unittest.cc +++ b/chrome/browser/enterprise_reporting/report_generator_unittest.cc
@@ -15,6 +15,7 @@ #include "build/build_config.h" #include "chrome/browser/enterprise_reporting/report_request_definition.h" #include "chrome/browser/profiles/profile_attributes_storage.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/account_id/account_id.h" @@ -194,20 +195,24 @@ plugin_service->RefreshPlugins(); } - std::vector<std::unique_ptr<ReportRequest>> GenerateRequests() { + std::vector<std::unique_ptr<ReportRequest>> GenerateRequests( + bool with_profiles) { histogram_tester_ = std::make_unique<base::HistogramTester>(); base::RunLoop run_loop; std::vector<std::unique_ptr<ReportRequest>> rets; - generator_.Generate(base::BindLambdaForTesting( - [&run_loop, &rets](ReportGenerator::ReportRequests requests) { - while (!requests.empty()) { - rets.push_back(std::move(requests.front())); - requests.pop(); - } - run_loop.Quit(); - })); + generator_.Generate( + with_profiles, + base::BindLambdaForTesting( + [&run_loop, &rets](ReportGenerator::ReportRequests requests) { + while (!requests.empty()) { + rets.push_back(std::move(requests.front())); + requests.pop(); + } + run_loop.Quit(); + })); run_loop.Run(); - VerifyMetrics(rets); + if (with_profiles) + VerifyMetrics(rets); // Only generated for reports with profiles. return rets; } @@ -228,10 +233,7 @@ std::string actual_profile_name = actual_profile_info.name(); // Verify that the profile id is set as profile path. - EXPECT_EQ(profile_manager_.profiles_dir() - .AppendASCII(actual_profile_name) - .AsUTF8Unsafe(), - actual_profile_info.id()); + EXPECT_EQ(GetProfilePath(actual_profile_name), actual_profile_info.id()); EXPECT_TRUE(actual_profile_info.has_is_full_report()); @@ -258,6 +260,23 @@ base::HistogramTester* histogram_tester() { return histogram_tester_.get(); } private: + // Returns a Profile's path, preferring the path of the active profile for + // user |profile_name| and falling back to a generated path based on it. + std::string GetProfilePath(const std::string& profile_name) { + // Find active Profile and return its path. + for (auto* profile : + profile_manager_.profile_manager()->GetLoadedProfiles()) { + if (profile->GetProfileUserName() == profile_name) + return profile->GetPath().AsUTF8Unsafe(); + } + + // No active profile, profile path must be generated by us, return path + // with same generator. + return profile_manager_.profiles_dir() + .AppendASCII(profile_name) + .AsUTF8Unsafe(); + } + ReportGenerator generator_; content::BrowserTaskEnvironment task_environment_; @@ -271,7 +290,57 @@ auto profile_names = CreateProfiles(/*number*/ 2, kIdle); CreatePlugin(); - auto requests = GenerateRequests(); + auto requests = GenerateRequests(/*with_profiles=*/true); + EXPECT_EQ(1u, requests.size()); + + auto* basic_request = requests[0].get(); + + // In the ChromeOsUserReportRequest for Chrome OS, these fields are not + // existing. Therefore, they are skipped according to current environment. +#if !defined(OS_CHROMEOS) + EXPECT_NE(std::string(), basic_request->computer_name()); + EXPECT_NE(std::string(), basic_request->os_user_name()); + VerifySerialNumber(basic_request->serial_number()); + + EXPECT_TRUE(basic_request->has_os_report()); + auto& os_report = basic_request->os_report(); + EXPECT_NE(std::string(), os_report.name()); + EXPECT_NE(std::string(), os_report.arch()); + EXPECT_NE(std::string(), os_report.version()); +#endif + + EXPECT_TRUE(basic_request->has_browser_report()); + auto& browser_report = basic_request->browser_report(); +#if defined(OS_CHROMEOS) + EXPECT_FALSE(browser_report.has_browser_version()); + EXPECT_FALSE(browser_report.has_channel()); +#else + EXPECT_NE(std::string(), browser_report.browser_version()); + EXPECT_TRUE(browser_report.has_channel()); +#endif + EXPECT_NE(std::string(), browser_report.executable_path()); + +#if defined(OS_CHROMEOS) + EXPECT_EQ(0, browser_report.plugins_size()); +#else + // There might be other plugins like PDF plugin, however, our fake plugin + // should be the first one in the report. + EXPECT_LE(1, browser_report.plugins_size()); + EXPECT_EQ(kPluginName, browser_report.plugins(0).name()); + EXPECT_EQ(kPluginVersion, browser_report.plugins(0).version()); + EXPECT_EQ(kPluginDescription, browser_report.plugins(0).description()); + EXPECT_EQ(kPluginFileName, browser_report.plugins(0).filename()); +#endif + + VerifyProfileReport(/*active_profile_names*/ std::set<std::string>(), + profile_names, browser_report); +} + +TEST_F(ReportGeneratorTest, GenerateWithoutProfiles) { + auto profile_names = CreateProfiles(/*number*/ 2, kActive); + CreatePlugin(); + + auto requests = GenerateRequests(/*with_profiles=*/false); EXPECT_EQ(1u, requests.size()); auto* basic_request = requests[0].get(); @@ -334,7 +403,7 @@ // Verify the Arc application information in the report is same as the test // data. - auto requests = GenerateRequests(); + auto requests = GenerateRequests(/*with_profiles=*/true); EXPECT_EQ(1u, requests.size()); ReportRequest* request = requests.front().get(); @@ -346,7 +415,7 @@ // Generate the Arc application information again and make sure the report // remains the same. - requests = GenerateRequests(); + requests = GenerateRequests(/*with_profiles=*/true); EXPECT_EQ(1u, requests.size()); request = requests.front().get(); @@ -375,7 +444,7 @@ // No Arc application information is reported after the Arc Play Store // support for given profile is disabled. primary_profile.GetPrefs()->SetBoolean(arc::prefs::kArcEnabled, false); - auto requests = GenerateRequests(); + auto requests = GenerateRequests(/*with_profiles=*/true); EXPECT_EQ(1u, requests.size()); ReportRequest* request = requests.front().get();
diff --git a/chrome/browser/enterprise_reporting/report_scheduler.cc b/chrome/browser/enterprise_reporting/report_scheduler.cc index 954209b5..58013678 100644 --- a/chrome/browser/enterprise_reporting/report_scheduler.cc +++ b/chrome/browser/enterprise_reporting/report_scheduler.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/policy/browser_dm_token_storage.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/upgrade_detector/build_state.h" #include "chrome/common/pref_names.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/device_management_service.h" @@ -40,6 +41,16 @@ prefs::kCloudReportingEnabled); } +// Returns true if this build should generate basic reports when an update is +// detected. +constexpr bool ShouldReportUpdates() { +#if defined(OS_CHROMEOS) + return false; +#else + return true; +#endif +} + } // namespace ReportScheduler::ReportScheduler( @@ -59,6 +70,8 @@ stale_profiles_->size(), kMaximumTrackedProfiles); } + if (ShouldReportUpdates()) + g_browser_process->GetBuildState()->RemoveObserver(this); } bool ReportScheduler::IsNextReportScheduledForTesting() const { @@ -74,6 +87,14 @@ OnReportEnabledPrefChanged(); } +void ReportScheduler::OnUpdate(const BuildState* build_state) { + DCHECK(ShouldReportUpdates()); + // A new version has been detected on the machine and a restart is now needed + // for it to take effect. Send a basic report (without profile info) + // immediately. + GenerateAndUploadReport(kTriggerUpdate); +} + void ReportScheduler::RegisterPrefObserver() { pref_change_registrar_.Init(g_browser_process->local_state()); pref_change_registrar_.Add( @@ -86,7 +107,7 @@ void ReportScheduler::OnReportEnabledPrefChanged() { if (!IsReportingEnabled()) { - StopRequestTimer(); + Stop(); return; } @@ -95,16 +116,26 @@ // initialized, and will keep valid during whole life-cycle. #if !defined(OS_CHROMEOS) if (!SetupBrowserPolicyClientRegistration()) { - StopRequestTimer(); + Stop(); return; } #endif - Start(); + // Start the periodic report timer. + Start(g_browser_process->local_state()->GetTime(kLastUploadTimestamp)); + + if (ShouldReportUpdates()) { + // Watch for browser updates if not already doing so. + auto* build_state = g_browser_process->GetBuildState(); + if (!build_state->HasObserver(this)) + build_state->AddObserver(this); + } } -void ReportScheduler::StopRequestTimer() { +void ReportScheduler::Stop() { request_timer_.Stop(); + if (ShouldReportUpdates()) + g_browser_process->GetBuildState()->RemoveObserver(this); } bool ReportScheduler::SetupBrowserPolicyClientRegistration() { @@ -127,36 +158,58 @@ return true; } -void ReportScheduler::Start() { - // The |next_upload_time| is based on the |lastUploadTimestamp| in the - // |local_state|, after that, it's 24 hours for each succeeded upload. - base::Time next_upload_time = - g_browser_process->local_state()->GetTime(kLastUploadTimestamp) + - kDefaultUploadInterval; +void ReportScheduler::Start(base::Time last_upload_time) { + // The next report is triggered 24h after the previous was uploaded. + const base::Time next_upload_time = last_upload_time + kDefaultUploadInterval; if (VLOG_IS_ON(1)) { base::TimeDelta first_request_delay = next_upload_time - base::Time::Now(); VLOG(1) << "Schedule the first report in about " << first_request_delay.InHours() << " hour(s) and " << first_request_delay.InMinutes() % 60 << " minute(s)."; } - request_timer_.Start( - FROM_HERE, next_upload_time, - base::BindRepeating(&ReportScheduler::GenerateAndUploadReport, - base::Unretained(this))); + request_timer_.Start(FROM_HERE, next_upload_time, + base::BindOnce(&ReportScheduler::GenerateAndUploadReport, + base::Unretained(this), kTriggerTimer)); } -void ReportScheduler::GenerateAndUploadReport() { - VLOG(1) << "Generating enterprise report."; - report_generator_->Generate(base::BindOnce( - &ReportScheduler::OnReportGenerated, base::Unretained(this))); +void ReportScheduler::GenerateAndUploadReport(ReportTrigger trigger) { + if (active_trigger_ != kTriggerNone) { + // A report is already being generated. Remember this trigger to be handled + // once the current report completes. + pending_triggers_ |= trigger; + return; + } + + active_trigger_ = trigger; + bool with_profiles = true; + switch (trigger) { + case kTriggerNone: + NOTREACHED(); + FALLTHROUGH; + case kTriggerTimer: + VLOG(1) << "Generating enterprise report."; + break; + case kTriggerUpdate: + VLOG(1) << "Generating basic enterprise report upon update."; + with_profiles = false; + break; + } + + report_generator_->Generate( + with_profiles, base::BindOnce(&ReportScheduler::OnReportGenerated, + base::Unretained(this))); } void ReportScheduler::OnReportGenerated( ReportGenerator::ReportRequests requests) { + DCHECK_NE(active_trigger_, kTriggerNone); if (requests.empty()) { SYSLOG(ERROR) << "No cloud report can be generated. Likely the report is too large."; - // We can't generate any report, stop the reporting. + // Do not restart the periodic report timer, as it's likely that subsequent + // attempts to generate full reports would also fail. + active_trigger_ = kTriggerNone; + RunPendingTriggers(); return; } VLOG(1) << "Uploading enterprise report."; @@ -170,6 +223,7 @@ } void ReportScheduler::OnReportUploaded(ReportUploader::ReportStatus status) { + DCHECK_NE(active_trigger_, kTriggerNone); VLOG(1) << "The enterprise report upload result " << status << "."; switch (status) { case ReportUploader::kSuccess: @@ -182,21 +236,32 @@ case ReportUploader::kTransientError: // Stop retrying and schedule the next report to avoid stale report. // Failure count is not reset so retry delay remains. - { - base::Time now = base::Time::Now(); + if (active_trigger_ == kTriggerTimer) { + const base::Time now = base::Time::Now(); g_browser_process->local_state()->SetTime(kLastUploadTimestamp, now); - if (IsReportingEnabled()) { - request_timer_.Start( - FROM_HERE, now + kDefaultUploadInterval, - base::BindRepeating(&ReportScheduler::GenerateAndUploadReport, - base::Unretained(this))); - } + if (IsReportingEnabled()) + Start(now); } break; case ReportUploader::kPersistentError: // No future upload until Chrome relaunch or pref change event. break; } + + active_trigger_ = kTriggerNone; + RunPendingTriggers(); +} + +void ReportScheduler::RunPendingTriggers() { + DCHECK_EQ(active_trigger_, kTriggerNone); + if (!pending_triggers_) + return; + + // Timer-triggered reports are a superset of those triggered by an update, so + // favor them and consider that they serve both purposes. + uint32_t pending_triggers = std::exchange(pending_triggers_, 0); + GenerateAndUploadReport( + (pending_triggers & kTriggerTimer) != 0 ? kTriggerTimer : kTriggerUpdate); } void ReportScheduler::TrackStaleProfiles() {
diff --git a/chrome/browser/enterprise_reporting/report_scheduler.h b/chrome/browser/enterprise_reporting/report_scheduler.h index 60fcf15..b6a5819 100644 --- a/chrome/browser/enterprise_reporting/report_scheduler.h +++ b/chrome/browser/enterprise_reporting/report_scheduler.h
@@ -5,18 +5,19 @@ #ifndef CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_SCHEDULER_H_ #define CHROME_BROWSER_ENTERPRISE_REPORTING_REPORT_SCHEDULER_H_ +#include <stdint.h> #include <memory> #include <queue> #include <string> #include "base/containers/flat_set.h" #include "base/macros.h" -#include "build/build_config.h" #include "chrome/browser/enterprise_reporting/notification/extension_request_observer_factory.h" #include "chrome/browser/enterprise_reporting/report_generator.h" #include "chrome/browser/enterprise_reporting/report_uploader.h" #include "chrome/browser/profiles/profile_manager_observer.h" #include "chrome/browser/ui/views/relaunch_notification/wall_clock_timer.h" +#include "chrome/browser/upgrade_detector/build_state_observer.h" #include "components/prefs/pref_change_registrar.h" namespace policy { @@ -25,9 +26,12 @@ namespace enterprise_reporting { -// Schedules the next report and handles retry in case of error. It also cancels -// all pending uploads if the report policy is turned off. -class ReportScheduler : public ProfileManagerObserver { +// Schedules report generation and upload every 24 hours and upon browser update +// for desktop Chrome while cloud reporting is enabled via administrative +// policy. If either of these triggers fires while a report is being generated, +// processing is deferred until the existing processing completes. +class ReportScheduler : public ProfileManagerObserver, + public BuildStateObserver { public: ReportScheduler(policy::CloudPolicyClient* client, std::unique_ptr<ReportGenerator> report_generator); @@ -43,7 +47,18 @@ void OnDMTokenUpdated(); + // BuildStateObserver: + void OnUpdate(const BuildState* build_state) override; + private: + // The trigger leading to report generation. Values are bitmasks in the + // |pending_triggers_| bitfield. + enum ReportTrigger : uint32_t { + kTriggerNone = 0, // No trigger. + kTriggerTimer = 1U << 0, // The periodic timer expired. + kTriggerUpdate = 1U << 1, // An update was detected. + }; + // Observes CloudReportingEnabled policy. void RegisterPrefObserver(); @@ -51,25 +66,31 @@ // policy value check during startup. void OnReportEnabledPrefChanged(); - // Stop |request_timer_| if it is existing. - void StopRequestTimer(); + // Stops the periodic timer and the update observer. + void Stop(); // Register |cloud_policy_client_| with dm token and client id for desktop // browser only. (Chrome OS doesn't need this step here.) bool SetupBrowserPolicyClientRegistration(); - // Schedules the first update request. - void Start(); + // Starts the periodic timer based on the last time a report was uploaded. + void Start(base::Time last_upload_time); - // Generates a report and uploads it. - void GenerateAndUploadReport(); + // Starts report generation in response to |trigger|. + void GenerateAndUploadReport(ReportTrigger trigger); - // Callback once report is generated. + // Continues processing a report (contained in the |requests| collection) by + // sending it to the uploader. void OnReportGenerated(ReportGenerator::ReportRequests requests); - // Callback once report upload request is finished. + // Finishes processing following report upload. |status| indicates the result + // of the attempted upload. void OnReportUploaded(ReportUploader::ReportStatus status); + // Initiates report generation for any triggers that arrived during generation + // of another report. + void RunPendingTriggers(); + // Tracks profiles that miss at least one report. void TrackStaleProfiles(); @@ -92,6 +113,14 @@ ExtensionRequestObserverFactory extension_request_observer_factory_; + // The trigger responsible for initiating active report generation. + ReportTrigger active_trigger_ = kTriggerNone; + + // The set of triggers that have fired while processing a report (a bitfield + // of ReportTrigger values). They will be handled following completion of the + // in-process report. + uint32_t pending_triggers_ = 0; + DISALLOW_COPY_AND_ASSIGN(ReportScheduler); };
diff --git a/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc b/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc index 20b4776..5088c13fd 100644 --- a/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc +++ b/chrome/browser/enterprise_reporting/report_scheduler_unittest.cc
@@ -10,22 +10,27 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/enterprise_reporting/prefs.h" #include "chrome/browser/policy/fake_browser_dm_token_storage.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/upgrade_detector/build_state.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" +#include "components/version_info/version_info.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::base::test::RunOnceCallback; using ::testing::_; +using ::testing::ByMove; using ::testing::Invoke; +using ::testing::Return; using ::testing::WithArgs; namespace em = enterprise_management; @@ -50,20 +55,18 @@ class MockReportGenerator : public ReportGenerator { public: - void Generate(ReportCallback callback) override { OnGenerate(callback); } - MOCK_METHOD1(OnGenerate, void(ReportCallback& callback)); + void Generate(bool with_profiles, ReportCallback callback) override { + OnGenerate(with_profiles, callback); + } + MOCK_METHOD2(OnGenerate, void(bool with_profiles, ReportCallback& callback)); + MOCK_METHOD0(GenerateBasic, ReportRequests()); }; class MockReportUploader : public ReportUploader { public: MockReportUploader() : ReportUploader(nullptr, 0) {} ~MockReportUploader() override = default; - void SetRequestAndUpload(ReportRequests requests, - ReportCallback callback) override { - OnSetRequestAndUpload(requests, callback); - } - MOCK_METHOD2(OnSetRequestAndUpload, - void(ReportRequests& requests, ReportCallback& callback)); + MOCK_METHOD2(SetRequestAndUpload, void(ReportRequests, ReportCallback)); private: DISALLOW_COPY_AND_ASSIGN(MockReportUploader); @@ -196,9 +199,9 @@ TEST_F(ReportSchedulerTest, UploadReportSucceeded) { EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); CreateScheduler(); @@ -217,9 +220,9 @@ TEST_F(ReportSchedulerTest, UploadReportTransientError) { EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kTransientError)); CreateScheduler(); @@ -238,9 +241,9 @@ TEST_F(ReportSchedulerTest, UploadReportPersistentError) { EXPECT_CALL_SetupRegistrationWithSetDMToken(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kPersistentError)); CreateScheduler(); @@ -264,9 +267,9 @@ TEST_F(ReportSchedulerTest, NoReportGenerate) { EXPECT_CALL_SetupRegistrationWithSetDMToken(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(0))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)).Times(0); + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(0))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)).Times(0); CreateScheduler(); EXPECT_TRUE(scheduler_->IsNextReportScheduledForTesting()); @@ -292,9 +295,9 @@ SetLastUploadInHour(gap); EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); CreateScheduler(); @@ -313,9 +316,9 @@ TEST_F(ReportSchedulerTest, TimerDelayWithoutLastUploadTimestamp) { EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); CreateScheduler(); @@ -350,9 +353,9 @@ TEST_F(ReportSchedulerTest, ReportingIsDisabledWhileNewReportIsPosted) { EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); CreateScheduler(); @@ -394,9 +397,9 @@ TEST_F(ReportSchedulerTest, StaleProfileMetricsForProfileAdded) { EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); CreateScheduler(); @@ -410,9 +413,9 @@ TEST_F(ReportSchedulerTest, StaleProfileMetricsForProfileRemoved) { EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillOnce(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); // Create a profile a head of time to prevent default profile creation during @@ -432,9 +435,9 @@ TEST_F(ReportSchedulerTest, StaleProfileMetricsResetAfterNewUpload) { EXPECT_CALL_SetupRegistration(); - EXPECT_CALL(*generator_, OnGenerate(_)) - .WillRepeatedly(WithArgs<0>(ScheduleGeneratorCallback(1))); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillRepeatedly(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); CreateScheduler(); @@ -444,7 +447,7 @@ auto new_uploader = std::make_unique<MockReportUploader>(); uploader_ = new_uploader.get(); scheduler_->SetReportUploaderForTesting(std::move(new_uploader)); - EXPECT_CALL(*uploader_, OnSetRequestAndUpload(_, _)) + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); profile_manager_.CreateTestingProfile("profile1"); @@ -455,4 +458,80 @@ histogram_tester_.ExpectUniqueSample(kStaleProfileCountMetricsName, 0, 1); } +#if !defined(OS_CHROMEOS) + +// Tests that a basic report is generated and uploaded when a browser update is +// detected. +TEST_F(ReportSchedulerTest, OnUpdate) { + // Pretend that a periodic report was generated recently so that one isn't + // kicked off during startup. + SetLastUploadInHour(base::TimeDelta::FromHours(1)); + EXPECT_CALL_SetupRegistration(); + EXPECT_CALL(*generator_, OnGenerate(false, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) + .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); + + CreateScheduler(); + g_browser_process->GetBuildState()->SetUpdate( + BuildState::UpdateType::kNormalUpdate, + base::Version("1" + version_info::GetVersionNumber()), base::nullopt); + task_environment_.RunUntilIdle(); + + // The timestamp should not have been updated, since a periodic report was not + // generated/uploaded. + ExpectLastUploadTimestampUpdated(false); +} + +// Tests that a full report is generated and uploaded following a basic report +// if the timer fires while the basic report is being uploaded. +TEST_F(ReportSchedulerTest, DeferredTimer) { + EXPECT_CALL_SetupRegistration(); + CreateScheduler(); + + // An update arrives, triggering report generation and upload (sans profiles). + EXPECT_CALL(*generator_, OnGenerate(false, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + + // Hang on to the uploader's ReportCallback. + ReportUploader::ReportCallback saved_callback; + EXPECT_CALL(*uploader_, SetRequestAndUpload(_, _)) + .WillOnce([&saved_callback](ReportUploader::ReportRequests requests, + ReportUploader::ReportCallback callback) { + saved_callback = std::move(callback); + }); + + g_browser_process->GetBuildState()->SetUpdate( + BuildState::UpdateType::kNormalUpdate, + base::Version("1" + version_info::GetVersionNumber()), base::nullopt); + task_environment_.RunUntilIdle(); + ::testing::Mock::VerifyAndClearExpectations(generator_); + ::testing::Mock::VerifyAndClearExpectations(uploader_); + + // Now the timer fires before the upload completes. No new report should be + // generated yet. + task_environment_.RunUntilIdle(); + ::testing::Mock::VerifyAndClearExpectations(generator_); + + // Once the previous upload completes, a new report should be generated + // forthwith. + EXPECT_CALL(*generator_, OnGenerate(true, _)) + .WillOnce(WithArgs<1>(ScheduleGeneratorCallback(1))); + auto new_uploader = std::make_unique<MockReportUploader>(); + EXPECT_CALL(*new_uploader, SetRequestAndUpload(_, _)) + .WillOnce(RunOnceCallback<1>(ReportUploader::kSuccess)); + std::move(saved_callback).Run(ReportUploader::kSuccess); + ExpectLastUploadTimestampUpdated(false); + ::testing::Mock::VerifyAndClearExpectations(generator_); + + this->uploader_ = new_uploader.get(); + this->scheduler_->SetReportUploaderForTesting(std::move(new_uploader)); + + task_environment_.RunUntilIdle(); + ::testing::Mock::VerifyAndClearExpectations(uploader_); + ExpectLastUploadTimestampUpdated(true); +} + +#endif // !defined(OS_CHROMEOS) + } // namespace enterprise_reporting
diff --git a/chrome/browser/extensions/background_header_browsertest.cc b/chrome/browser/extensions/background_header_browsertest.cc index 2c87bc5..bd333ac 100644 --- a/chrome/browser/extensions/background_header_browsertest.cc +++ b/chrome/browser/extensions/background_header_browsertest.cc
@@ -27,12 +27,7 @@ class BackgroundHeaderTest : public ExtensionBrowserTest { public: BackgroundHeaderTest() - : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) { - feature_list_.InitWithFeatures( - {network::features::kFetchMetadata, - network::features::kFetchMetadataDestination}, - {}); - } + : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} BackgroundHeaderTest(const BackgroundHeaderTest& other) = delete; BackgroundHeaderTest& operator=(const BackgroundHeaderTest& other) = delete;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index c810cfe..25df656c 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1079,11 +1079,6 @@ "expiry_milestone": 79 }, { - "name": "enable-clipboard-provider-text-suggestions", - "owners": [ "gangwu", "chrome-omnibox-team@google.com"], - "expiry_milestone": 84 - }, - { "name": "enable-close-tab-suggestions", "owners": [ "memex-team@google.com" ], "expiry_milestone": 82 @@ -1374,7 +1369,7 @@ { "name": "enable-heavy-ad-intervention", "owners": [ "johnidel", "jkarlin" ], - "expiry_milestone": 82 + "expiry_milestone": 85 }, { "name": "enable-heuristic-stylus-palm-rejection", @@ -2258,7 +2253,7 @@ { "name": "forced-colors", "owners": [ "weblayout@microsoft.com" ], - "expiry_milestone": 82 + "expiry_milestone": 85 }, { "name": "form-controls-refresh", @@ -2352,7 +2347,7 @@ { "name": "heavy-ad-privacy-mitigations-opt-out", "owners": [ "johnidel", "jkarlin" ], - "expiry_milestone": 82 + "expiry_milestone": 85 }, { "name": "help-app",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 4cb4aa8b..954ae61d 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -69,11 +69,6 @@ "Allows synchronous XHR requests during page dismissal when the page is " "being navigated away or closed by the user."; -const char kEnableClipboardProviderTextSuggestionsName[] = - "Omnibox clipboard text search suggestions"; -const char kEnableClipboardProviderTextSuggestionsDescription[] = - "Enables search suggestions in omnibox"; - const char kEnableFtpName[] = "Enable support for FTP URLs"; const char kEnableFtpDescription[] = "When enabled, the browser will handle navigations to ftp:// URLs by "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index e0279bd8..2d778875 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -74,9 +74,6 @@ extern const char kAllowSyncXHRInPageDismissalName[]; extern const char kAllowSyncXHRInPageDismissalDescription[]; -extern const char kEnableClipboardProviderTextSuggestionsName[]; -extern const char kEnableClipboardProviderTextSuggestionsDescription[]; - extern const char kEnableFtpName[]; extern const char kEnableFtpDescription[];
diff --git a/chrome/browser/hid/hid_chooser_context.cc b/chrome/browser/hid/hid_chooser_context.cc index dbf8db1c..5b43a54e0 100644 --- a/chrome/browser/hid/hid_chooser_context.cc +++ b/chrome/browser/hid/hid_chooser_context.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/values.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "components/content_settings/core/common/content_settings_types.h" #include "content/public/browser/device_service.h" @@ -31,9 +32,9 @@ } // namespace HidChooserContext::HidChooserContext(Profile* profile) - : ChooserContextBase(profile, - ContentSettingsType::HID_GUARD, - ContentSettingsType::HID_CHOOSER_DATA), + : ChooserContextBase(ContentSettingsType::HID_GUARD, + ContentSettingsType::HID_CHOOSER_DATA, + HostContentSettingsMapFactory::GetForProfile(profile)), is_incognito_(profile->IsOffTheRecord()) {} HidChooserContext::~HidChooserContext() = default;
diff --git a/chrome/browser/hid/hid_chooser_context.h b/chrome/browser/hid/hid_chooser_context.h index bf6ecbc4..90bb8c1 100644 --- a/chrome/browser/hid/hid_chooser_context.h +++ b/chrome/browser/hid/hid_chooser_context.h
@@ -14,12 +14,14 @@ #include "base/memory/weak_ptr.h" #include "base/unguessable_token.h" -#include "chrome/browser/permissions/chooser_context_base.h" +#include "components/permissions/chooser_context_base.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/device/public/mojom/hid.mojom.h" #include "url/origin.h" +class Profile; + namespace base { class Value; }
diff --git a/chrome/browser/payments/android/service_worker_payment_app_bridge.cc b/chrome/browser/payments/android/service_worker_payment_app_bridge.cc index ddfa89f..3f5cc9b1 100644 --- a/chrome/browser/payments/android/service_worker_payment_app_bridge.cc +++ b/chrome/browser/payments/android/service_worker_payment_app_bridge.cc
@@ -467,6 +467,7 @@ const JavaParamRef<jstring>& jpayment_request_origin, const JavaParamRef<jobjectArray>& jmethod_data, const JavaParamRef<jobjectArray>& jmodifiers, + const JavaParamRef<jstring>& jcurrency, const JavaParamRef<jobject>& jcallback, const JavaParamRef<jobject>& japp) { content::WebContents* web_contents = @@ -479,6 +480,8 @@ GURL(ConvertJavaStringToUTF8(env, jpayment_request_origin)); event_data->method_data = ConvertPaymentMethodDataFromJavaToNative(env, jmethod_data); + if (!jcurrency.is_null()) + event_data->currency = ConvertJavaStringToUTF8(env, jcurrency); for (auto jmodifier : jmodifiers.ReadElements<jobject>()) { PaymentDetailsModifierPtr modifier = PaymentDetailsModifier::New();
diff --git a/chrome/browser/permissions/chooser_context_base_mock_permission_observer.h b/chrome/browser/permissions/chooser_context_base_mock_permission_observer.h index 3dca0d5d..877ba676d 100644 --- a/chrome/browser/permissions/chooser_context_base_mock_permission_observer.h +++ b/chrome/browser/permissions/chooser_context_base_mock_permission_observer.h
@@ -5,8 +5,8 @@ #ifndef CHROME_BROWSER_PERMISSIONS_CHOOSER_CONTEXT_BASE_MOCK_PERMISSION_OBSERVER_H_ #define CHROME_BROWSER_PERMISSIONS_CHOOSER_CONTEXT_BASE_MOCK_PERMISSION_OBSERVER_H_ -#include "chrome/browser/permissions/chooser_context_base.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/permissions/chooser_context_base.h" #include "testing/gmock/include/gmock/gmock.h" #include "url/gurl.h"
diff --git a/chrome/browser/permissions/chooser_context_base_unittest.cc b/chrome/browser/permissions/chooser_context_base_unittest.cc index 1c7d91b..3a9b10f 100644 --- a/chrome/browser/permissions/chooser_context_base_unittest.cc +++ b/chrome/browser/permissions/chooser_context_base_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 "chrome/browser/permissions/chooser_context_base.h" +#include "components/permissions/chooser_context_base.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/permissions/chooser_context_base_mock_permission_observer.h" @@ -22,9 +22,10 @@ public: // This class uses the USB content settings type for testing purposes only. explicit TestChooserContext(Profile* profile) - : ChooserContextBase(profile, - ContentSettingsType::USB_GUARD, - ContentSettingsType::USB_CHOOSER_DATA) {} + : ChooserContextBase( + ContentSettingsType::USB_GUARD, + ContentSettingsType::USB_CHOOSER_DATA, + HostContentSettingsMapFactory::GetForProfile(profile)) {} ~TestChooserContext() override {} bool IsValidObject(const base::Value& object) override {
diff --git a/chrome/browser/prerender/prerender_tab_helper.cc b/chrome/browser/prerender/prerender_tab_helper.cc index 7301289..a61b3a2 100644 --- a/chrome/browser/prerender/prerender_tab_helper.cc +++ b/chrome/browser/prerender/prerender_tab_helper.cc
@@ -20,10 +20,9 @@ namespace prerender { PrerenderTabHelper::PrerenderTabHelper(content::WebContents* web_contents) - : content::WebContentsObserver(web_contents), origin_(ORIGIN_NONE) {} + : content::WebContentsObserver(web_contents) {} -PrerenderTabHelper::~PrerenderTabHelper() { -} +PrerenderTabHelper::~PrerenderTabHelper() = default; void PrerenderTabHelper::DidFinishNavigation( content::NavigationHandle* navigation_handle) { @@ -33,40 +32,12 @@ return; } - url_ = navigation_handle->GetURL(); PrerenderManager* prerender_manager = MaybeGetPrerenderManager(); if (!prerender_manager) return; - if (prerender_manager->IsWebContentsPrerendering(web_contents(), NULL)) + if (prerender_manager->IsWebContentsPrerendering(web_contents(), nullptr)) return; - prerender_manager->RecordNavigation(url_); -} - -void PrerenderTabHelper::DidStartNavigation( - content::NavigationHandle* navigation_handle) { - // Determine the origin. - PrerenderManager* prerender_manager = MaybeGetPrerenderManager(); - if (prerender_manager) - prerender_manager->IsWebContentsPrerendering(web_contents(), &origin_); - - if (navigation_handle->IsSameDocument()) - return; - - if (!navigation_handle->IsInMainFrame()) - return; - - MainFrameUrlDidChange(navigation_handle->GetURL()); -} - -void PrerenderTabHelper::DidRedirectNavigation( - content::NavigationHandle* navigation_handle) { - if (!navigation_handle->IsInMainFrame()) - return; - MainFrameUrlDidChange(navigation_handle->GetURL()); -} - -void PrerenderTabHelper::MainFrameUrlDidChange(const GURL& url) { - url_ = url; + prerender_manager->RecordNavigation(navigation_handle->GetURL()); } PrerenderManager* PrerenderTabHelper::MaybeGetPrerenderManager() const { @@ -90,7 +61,7 @@ PrerenderManager* prerender_manager = MaybeGetPrerenderManager(); if (!prerender_manager) return false; - return prerender_manager->IsWebContentsPrerendering(web_contents(), NULL); + return prerender_manager->IsWebContentsPrerendering(web_contents(), nullptr); } void PrerenderTabHelper::PrerenderSwappedIn() {
diff --git a/chrome/browser/prerender/prerender_tab_helper.h b/chrome/browser/prerender/prerender_tab_helper.h index f7127c3..622cb91 100644 --- a/chrome/browser/prerender/prerender_tab_helper.h +++ b/chrome/browser/prerender/prerender_tab_helper.h
@@ -29,24 +29,14 @@ ~PrerenderTabHelper() override; // content::WebContentsObserver implementation. - void DidStartNavigation( - content::NavigationHandle* navigation_handle) override; - void DidRedirectNavigation( - content::NavigationHandle* navigation_handle) override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; - // Called when the URL of the main frame changed, either when the load - // commits, or a redirect happens. - void MainFrameUrlDidChange(const GURL& url); - // Called when this prerendered WebContents has just been swapped in. void PrerenderSwappedIn(); base::TimeTicks swap_ticks() const { return swap_ticks_; } - Origin origin() const { return origin_; } - private: explicit PrerenderTabHelper(content::WebContents* web_contents); friend class content::WebContentsUserData<PrerenderTabHelper>; @@ -62,18 +52,9 @@ // Returns whether the WebContents being observed is currently prerendering. bool IsPrerendering(); - // The origin of the relevant prerender or ORIGIN_NONE if there is no - // prerender associated with the WebContents. - Origin origin_; - // Record the most recent swap time. base::TimeTicks swap_ticks_; - // Current URL being loaded. - GURL url_; - - base::WeakPtrFactory<PrerenderTabHelper> weak_factory_{this}; - WEB_CONTENTS_USER_DATA_KEY_DECL(); DISALLOW_COPY_AND_ASSIGN(PrerenderTabHelper);
diff --git a/chrome/browser/resources/chromeos/login/marketing_opt_in.html b/chrome/browser/resources/chromeos/login/marketing_opt_in.html index 483d7c7..be6037a16 100644 --- a/chrome/browser/resources/chromeos/login/marketing_opt_in.html +++ b/chrome/browser/resources/chromeos/login/marketing_opt_in.html
@@ -15,10 +15,12 @@ <hd-iron-icon slot="oobe-icon" icon1x="oobe-32:checkmark" icon2x="oobe-32:checkmark"> </hd-iron-icon> - <div slot="subtitle"> + <div slot="subtitle" id="marketing-opt-in-subtitle" + hidden="[[!marketingOptInEnabled_]]"> [[i18nRecursive(locale, 'marketingOptInScreenSubtitle', 'productName')]] </div> - <div slot="footer" class="layout vertical"> + <div slot="footer" class="layout vertical" id="marketing-opt-in-toggles" + hidden="[[!marketingOptInEnabled_]]"> <div class="marketing-option layout horizontal center"> <hd-iron-icon icon1x="oobe-32:checkmark" icon2x="oobe-64:checkmark"> </hd-iron-icon>
diff --git a/chrome/browser/resources/chromeos/login/marketing_opt_in.js b/chrome/browser/resources/chromeos/login/marketing_opt_in.js index b37242c..07ecf3d 100644 --- a/chrome/browser/resources/chromeos/login/marketing_opt_in.js +++ b/chrome/browser/resources/chromeos/login/marketing_opt_in.js
@@ -15,6 +15,20 @@ type: Boolean, value: true, }, + + /** + * Whether the marketing opt in toggles should be shown, which will be the + * case only if marketing opt in feature is enabled. + * When this is false, the screen will only contain UI related to the + * tablet mode gestural navigation settings. + */ + marketingOptInEnabled_: { + type: Boolean, + readOnly: true, + value() { + return loadTimeData.getBoolean('enableMarketingOptIn'); + }, + }, }, behaviors: [OobeI18nBehavior, OobeDialogHostBehavior, LoginScreenBehavior],
diff --git a/chrome/browser/resources/chromeos/login/security_token_pin.css b/chrome/browser/resources/chromeos/login/security_token_pin.css index 0f00bf9..0c4ca7ba 100644 --- a/chrome/browser/resources/chromeos/login/security_token_pin.css +++ b/chrome/browser/resources/chromeos/login/security_token_pin.css
@@ -11,8 +11,8 @@ --pin-keyboard-pin-input-style: { width: 192px; }; + --pin-keyboard-input-letter-spacing: 14px; --pin-keyboard-number-color: var(--google-grey-900); - --cr-input-letter-spacing: 14px; --cr-icon-button-margin-start: 5px; }
diff --git a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js index 1288667..60dafcb 100644 --- a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js +++ b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.js
@@ -63,8 +63,8 @@ this.model.incognito); this.browserProxy_.setCategoryPermissionForPattern( - this.origin_, this.origin_, this.model.category, this.model.setting, - this.model.incognito); + this.origin_, settings.SITE_EXCEPTION_WILDCARD, this.model.category, + this.model.setting, this.model.incognito); } this.$.dialog.close();
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js index e58ebd7..c46687c 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -192,7 +192,7 @@ route: 'SITE_SETTINGS_PAYMENT_HANDLER', id: Id.PAYMENT_HANDLER, label: 'siteSettingsPaymentHandler', - icon: 'settings:bluetooth-scanning', + icon: 'settings:payment-handler', enabledLabel: 'siteSettingsPaymentHandlerAllow', disabledLabel: 'siteSettingsPaymentHandlerBlock', shouldShow: () =>
diff --git a/chrome/browser/resources/tab_strip/tab.js b/chrome/browser/resources/tab_strip/tab.js index 467fcd1..7e23975d 100644 --- a/chrome/browser/resources/tab_strip/tab.js +++ b/chrome/browser/resources/tab_strip/tab.js
@@ -236,8 +236,6 @@ /** @private */ onSwipe_() { - // Prevent slideOut animation from playing. - this.remove(); this.tabsApi_.closeTab(this.tab_.id, CloseTabAction.SWIPED_TO_CLOSE); }
diff --git a/chrome/browser/resources/tab_strip/tab_swiper.js b/chrome/browser/resources/tab_strip/tab_swiper.js index d02f130..7c6588a7 100644 --- a/chrome/browser/resources/tab_strip/tab_swiper.js +++ b/chrome/browser/resources/tab_strip/tab_swiper.js
@@ -161,10 +161,6 @@ } const yDiff = this.currentPointerDownEvent_.clientY - event.clientY; - const animationTime = yDiff; - this.animation_.currentTime = - Math.max(0, Math.min(SWIPE_FINISH_THRESHOLD_PX, animationTime)); - if (!this.animationInitiated_ && Math.abs(yDiff) > TRANSLATE_ANIMATION_THRESHOLD_PX) { this.animationInitiated_ = true; @@ -181,22 +177,17 @@ return; } - const pixelsSwiped = this.animation_.currentTime; + const yDiff = this.currentPointerDownEvent_.clientY - event.clientY; + const pixelsSwiped = + Math.max(0, Math.min(SWIPE_FINISH_THRESHOLD_PX, yDiff)); const swipedEnoughToClose = pixelsSwiped > SWIPE_START_THRESHOLD_PX; const wasHighVelocity = pixelsSwiped / (event.timeStamp - this.currentPointerDownEvent_.timeStamp) > SWIPE_VELOCITY_THRESHOLD; - if (pixelsSwiped === SWIPE_FINISH_THRESHOLD_PX) { - // The user has swiped the max amount of pixels to swipe and the animation - // has already completed all its keyframes, so just fire the onfinish - // events on the animation. - this.animation_.finish(); - } else if (swipedEnoughToClose || wasHighVelocity) { - this.animation_.play(); - } else { - this.animation_.cancel(); - this.animation_.currentTime = 0; + if (pixelsSwiped === SWIPE_FINISH_THRESHOLD_PX || swipedEnoughToClose || + wasHighVelocity) { + this.element_.dispatchEvent(new CustomEvent('swipe')); } this.clearPointerEvents_();
diff --git a/chrome/browser/serial/serial_chooser_context.cc b/chrome/browser/serial/serial_chooser_context.cc index 1ca4b4f..60521e0d 100644 --- a/chrome/browser/serial/serial_chooser_context.cc +++ b/chrome/browser/serial/serial_chooser_context.cc
@@ -8,6 +8,7 @@ #include "base/base64.h" #include "base/values.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/device_service.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -51,9 +52,9 @@ } // namespace SerialChooserContext::SerialChooserContext(Profile* profile) - : ChooserContextBase(profile, - ContentSettingsType::SERIAL_GUARD, - ContentSettingsType::SERIAL_CHOOSER_DATA), + : ChooserContextBase(ContentSettingsType::SERIAL_GUARD, + ContentSettingsType::SERIAL_CHOOSER_DATA, + HostContentSettingsMapFactory::GetForProfile(profile)), is_incognito_(profile->IsOffTheRecord()) {} SerialChooserContext::~SerialChooserContext() = default;
diff --git a/chrome/browser/serial/serial_chooser_context.h b/chrome/browser/serial/serial_chooser_context.h index d416eb9..7402b74d 100644 --- a/chrome/browser/serial/serial_chooser_context.h +++ b/chrome/browser/serial/serial_chooser_context.h
@@ -14,7 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/unguessable_token.h" -#include "chrome/browser/permissions/chooser_context_base.h" +#include "components/permissions/chooser_context_base.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/device/public/mojom/serial.mojom-forward.h" @@ -22,6 +22,8 @@ #include "url/gurl.h" #include "url/origin.h" +class Profile; + namespace base { class Value; }
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index e95674f..ee2ac02e 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -2045,12 +2045,7 @@ class MultiOriginSessionRestoreTest : public SessionRestoreTest { public: MultiOriginSessionRestoreTest() - : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) { - feature_list_.InitWithFeatures( - {network::features::kFetchMetadata, - network::features::kFetchMetadataDestination}, - {}); - } + : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} void SetUpOnMainThread() override { SessionRestoreTest::SetUpOnMainThread();
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc index f1b858de..3921787 100644 --- a/chrome/browser/signin/account_reconcilor_factory.cc +++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -44,15 +44,36 @@ namespace { #if defined(OS_CHROMEOS) -class ChromeOSChildAccountReconcilorDelegate +class ChromeOSLimitedAccessAccountReconcilorDelegate : public signin::MirrorAccountReconcilorDelegate { public: - explicit ChromeOSChildAccountReconcilorDelegate( + enum class ReconcilorBehavior { + kChild, + kEnterprise, + }; + + ChromeOSLimitedAccessAccountReconcilorDelegate( + ReconcilorBehavior reconcilor_behavior, signin::IdentityManager* identity_manager) - : signin::MirrorAccountReconcilorDelegate(identity_manager) {} + : signin::MirrorAccountReconcilorDelegate(identity_manager), + reconcilor_behavior_(reconcilor_behavior) {} + + ChromeOSLimitedAccessAccountReconcilorDelegate( + const ChromeOSLimitedAccessAccountReconcilorDelegate&) = delete; + ChromeOSLimitedAccessAccountReconcilorDelegate& operator=( + const ChromeOSLimitedAccessAccountReconcilorDelegate&) = delete; base::TimeDelta GetReconcileTimeout() const override { - return base::TimeDelta::FromSeconds(10); + switch (reconcilor_behavior_) { + case ReconcilorBehavior::kChild: + return base::TimeDelta::FromSeconds(10); + case ReconcilorBehavior::kEnterprise: + // 60 seconds is enough to cover about 99% of all reconcile cases. + return base::TimeDelta::FromSeconds(60); + default: + NOTREACHED(); + return MirrorAccountReconcilorDelegate::GetReconcileTimeout(); + } } void OnReconcileError(const GoogleServiceAuthError& error) override { @@ -74,14 +95,16 @@ user_manager::UserManager::Get()->SaveForceOnlineSignin( primary_user->GetAccountId(), true /* force_online_signin */); + if (reconcilor_behavior_ == ReconcilorBehavior::kChild) { + UMA_HISTOGRAM_BOOLEAN( + "ChildAccountReconcilor.ForcedUserExitOnReconcileError", true); + } // Force a logout. - UMA_HISTOGRAM_BOOLEAN( - "ChildAccountReconcilor.ForcedUserExitOnReconcileError", true); chrome::AttemptUserExit(); } private: - DISALLOW_COPY_AND_ASSIGN(ChromeOSChildAccountReconcilorDelegate); + const ReconcilorBehavior reconcilor_behavior_; }; // An |AccountReconcilorDelegate| for Chrome OS that is exactly the same as @@ -176,7 +199,9 @@ // Only for child accounts on Chrome OS, use the specialized Mirror // delegate. if (profile->IsChild()) { - return std::make_unique<ChromeOSChildAccountReconcilorDelegate>( + return std::make_unique<ChromeOSLimitedAccessAccountReconcilorDelegate>( + ChromeOSLimitedAccessAccountReconcilorDelegate::ReconcilorBehavior:: + kChild, IdentityManagerFactory::GetForProfile(profile)); } @@ -190,6 +215,14 @@ signin::ActiveDirectoryAccountReconcilorDelegate>(); } + if (profile->GetPrefs()->GetBoolean( + prefs::kForceLogoutUnauthenticatedUserEnabled)) { + return std::make_unique<ChromeOSLimitedAccessAccountReconcilorDelegate>( + ChromeOSLimitedAccessAccountReconcilorDelegate::ReconcilorBehavior:: + kEnterprise, + IdentityManagerFactory::GetForProfile(profile)); + } + // TODO(sinhak): Use |MirrorAccountReconcilorDelegate|) when all Chrome OS // users have been migrated to Account Manager. return std::make_unique<ChromeOSAccountReconcilorDelegate>(
diff --git a/chrome/browser/sync/test/integration/cookie_helper.cc b/chrome/browser/sync/test/integration/cookie_helper.cc new file mode 100644 index 0000000..5db66ff --- /dev/null +++ b/chrome/browser/sync/test/integration/cookie_helper.cc
@@ -0,0 +1,65 @@ +// Copyright 2020 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/cookie_helper.h" + +#include "base/run_loop.h" +#include "base/test/bind_test_util.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" +#include "net/cookies/canonical_cookie.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" + +namespace cookie_helper { + +namespace { + +// Name of the GAIA cookie that is being observed to detect when available +// accounts have changed in the content-area. +const char kSigninCookieName[] = "SAPISID"; + +} // namespace + +void AddSigninCookie(Profile* profile) { + DCHECK(profile); + net::CanonicalCookie cookie( + kSigninCookieName, std::string(), ".google.com", "/", base::Time(), + base::Time(), base::Time(), /*secure=*/true, false, + net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_DEFAULT); + + network::mojom::CookieManager* cookie_manager = + content::BrowserContext::GetDefaultStoragePartition(profile) + ->GetCookieManagerForBrowserProcess(); + DCHECK(cookie_manager); + + base::RunLoop run_loop; + cookie_manager->SetCanonicalCookie( + cookie, "https", net::CookieOptions(), + base::BindLambdaForTesting( + [&run_loop](net::CanonicalCookie::CookieInclusionStatus) { + run_loop.Quit(); + })); + run_loop.Run(); +} + +void DeleteSigninCookies(Profile* profile) { + DCHECK(profile); + network::mojom::CookieManager* cookie_manager = + content::BrowserContext::GetDefaultStoragePartition(profile) + ->GetCookieManagerForBrowserProcess(); + DCHECK(cookie_manager); + + base::RunLoop run_loop; + network::mojom::CookieDeletionFilterPtr filter = + network::mojom::CookieDeletionFilter::New(); + filter->cookie_name = kSigninCookieName; + + cookie_manager->DeleteCookies( + std::move(filter), + base::BindLambdaForTesting([&run_loop](uint32_t) { run_loop.Quit(); })); + run_loop.Run(); +} + +} // namespace cookie_helper
diff --git a/chrome/browser/sync/test/integration/cookie_helper.h b/chrome/browser/sync/test/integration/cookie_helper.h new file mode 100644 index 0000000..a439dbe0 --- /dev/null +++ b/chrome/browser/sync/test/integration/cookie_helper.h
@@ -0,0 +1,24 @@ +// Copyright 2020 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_COOKIE_HELPER_H_ +#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_COOKIE_HELPER_H_ + +class Profile; + +namespace cookie_helper { + +// Adds new signin cookie (aka SAPISID cookie) directly to the profile's +// CookieManager. |profile| must not be nullptr and network must be already +// initialized. +void AddSigninCookie(Profile* profile); + +// Removes all signin cookie (aka SAPISID cookie) directly from the profile's +// CookieManager. |profile| must not be nullptr and network must be already +// initialized. +void DeleteSigninCookies(Profile* profile); + +} // namespace cookie_helper + +#endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_COOKIE_HELPER_H_
diff --git a/chrome/browser/sync/test/integration/encryption_helper.cc b/chrome/browser/sync/test/integration/encryption_helper.cc index 25b667e..a8336d1a 100644 --- a/chrome/browser/sync/test/integration/encryption_helper.cc +++ b/chrome/browser/sync/test/integration/encryption_helper.cc
@@ -6,10 +6,12 @@ #include <vector> #include "base/base64.h" +#include "base/bind.h" #include "chrome/browser/sync/test/integration/encryption_helper.h" #include "components/sync/base/passphrase_enums.h" #include "components/sync/base/sync_base_switches.h" #include "components/sync/driver/profile_sync_service.h" +#include "components/sync/driver/sync_client.h" #include "components/sync/engine/sync_engine_switches.h" #include "testing/gtest/include/gtest/gtest.h" @@ -212,6 +214,31 @@ desired_state_; } +TrustedVaultKeysChangedStateChecker::TrustedVaultKeysChangedStateChecker( + syncer::ProfileSyncService* service) + : keys_changed_(false) { + // base::Unretained() is safe here, because callback won't be called once + // |subscription_| is destroyed. + subscription_ = service->GetSyncClientForTest() + ->GetTrustedVaultClient() + ->AddKeysChangedObserver(base::BindRepeating( + &TrustedVaultKeysChangedStateChecker::OnKeysChanged, + base::Unretained(this))); +} + +TrustedVaultKeysChangedStateChecker::~TrustedVaultKeysChangedStateChecker() = + default; + +bool TrustedVaultKeysChangedStateChecker::IsExitConditionSatisfied( + std::ostream* os) { + *os << "Waiting for trusted vault keys change"; + return keys_changed_; +} + +void TrustedVaultKeysChangedStateChecker::OnKeysChanged() { + keys_changed_ = true; +} + ScopedScryptFeatureToggler::ScopedScryptFeatureToggler( bool force_disabled, bool use_for_new_passphrases) {
diff --git a/chrome/browser/sync/test/integration/encryption_helper.h b/chrome/browser/sync/test/integration/encryption_helper.h index 02ed85e0..5809d1af 100644 --- a/chrome/browser/sync/test/integration/encryption_helper.h +++ b/chrome/browser/sync/test/integration/encryption_helper.h
@@ -10,6 +10,8 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" +#include "chrome/browser/sync/test/integration/status_change_checker.h" +#include "components/sync/driver/trusted_vault_client.h" #include "components/sync/protocol/nigori_specifics.pb.h" #include "components/sync/syncable/directory_cryptographer.h" #include "components/sync/test/fake_server/fake_server.h" @@ -105,6 +107,22 @@ const bool desired_state_; }; +// Checker used to block until trusted vault keys are changed. +class TrustedVaultKeysChangedStateChecker : public StatusChangeChecker { + public: + explicit TrustedVaultKeysChangedStateChecker( + syncer::ProfileSyncService* service); + ~TrustedVaultKeysChangedStateChecker() override; + + bool IsExitConditionSatisfied(std::ostream* os) override; + + private: + void OnKeysChanged(); + + bool keys_changed_; + std::unique_ptr<syncer::TrustedVaultClient::Subscription> subscription_; +}; + // Helper for setting scrypt-related feature flags. // NOTE: DO NOT INSTANTIATE THIS CLASS IN THE TEST BODY FOR INTEGRATION TESTS! // That causes data races, see crbug.com/915219. Instead, instantiate it in the
diff --git a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc index 468404a4..015d6de 100644 --- a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
@@ -14,6 +14,7 @@ #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "chrome/browser/sync/sync_ui_util.h" +#include "chrome/browser/sync/test/integration/cookie_helper.h" #include "chrome/browser/sync/test/integration/encryption_helper.h" #include "chrome/browser/sync/test/integration/passwords_helper.h" #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" @@ -677,6 +678,60 @@ EXPECT_FALSE(sync_ui_util::ShouldShowSyncKeysMissingError(GetSyncService(0))); } +IN_PROC_BROWSER_TEST_F( + SingleClientNigoriWithWebApiTest, + PRE_ShouldClearEncryptionKeysFromTheWebWhenSigninCookiesCleared) { + const std::string kTestEncryptionKey = "testpassphrase1"; + const GURL retrieval_url = + GetTrustedVaultRetrievalURL(*embedded_test_server(), kTestEncryptionKey); + + ASSERT_TRUE(SetupClients()); + + // Explicitly add signin cookie (normally it would be done during the keys + // retrieval or before it). + cookie_helper::AddSigninCookie(GetProfile(0)); + + TrustedVaultKeysChangedStateChecker keys_fetched_checker(GetSyncService(0)); + // Mimic opening a web page where the user can interact with the retrieval + // flow, while the user is signed out. + sync_ui_util::OpenTabForSyncKeyRetrievalWithURLForTesting(GetBrowser(0), + retrieval_url); + ASSERT_THAT(GetBrowser(0)->tab_strip_model()->GetActiveWebContents(), + NotNull()); + + // Wait until the title changes to "OK" via Javascript, which indicates + // completion. + PageTitleChecker title_checker( + /*expected_title=*/"OK", + GetBrowser(0)->tab_strip_model()->GetActiveWebContents()); + EXPECT_TRUE(title_checker.Wait()); + EXPECT_TRUE(keys_fetched_checker.Wait()); + + // Mimic signin cookie clearing. + TrustedVaultKeysChangedStateChecker keys_cleared_checker(GetSyncService(0)); + cookie_helper::DeleteSigninCookies(GetProfile(0)); + EXPECT_TRUE(keys_cleared_checker.Wait()); +} + +IN_PROC_BROWSER_TEST_F( + SingleClientNigoriWithWebApiTest, + ShouldClearEncryptionKeysFromTheWebWhenSigninCookiesCleared) { + const std::string kTestEncryptionKey = "testpassphrase1"; + + // Mimic the account being already using a trusted vault passphrase. + encryption_helper::SetNigoriInFakeServer( + GetFakeServer(), BuildTrustedVaultNigoriSpecifics({kTestEncryptionKey})); + + // Sign in and start sync. + ASSERT_TRUE(SetupSync()); + + EXPECT_TRUE(GetSyncService(0) + ->GetUserSettings() + ->IsTrustedVaultKeyRequiredForPreferredDataTypes()); + EXPECT_FALSE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS)); + EXPECT_TRUE(sync_ui_util::ShouldShowSyncKeysMissingError(GetSyncService(0))); +} + // Same as SingleClientNigoriWithWebApiTest but does NOT override // switches::kGaiaUrl, which means the embedded test server gets treated as // untrusted origin.
diff --git a/chrome/browser/sync/trusted_vault_client_android.cc b/chrome/browser/sync/trusted_vault_client_android.cc index a8a068d..b778dc4b 100644 --- a/chrome/browser/sync/trusted_vault_client_android.cc +++ b/chrome/browser/sync/trusted_vault_client_android.cc
@@ -103,6 +103,10 @@ NOTREACHED(); } +void TrustedVaultClientAndroid::RemoveAllStoredKeys() { + // StoreKeys() not supported on Android, nothing to remove. +} + void TrustedVaultClientAndroid::MarkKeysAsStale( const CoreAccountInfo& account_info, base::OnceCallback<void(bool)> cb) {
diff --git a/chrome/browser/sync/trusted_vault_client_android.h b/chrome/browser/sync/trusted_vault_client_android.h index 9ca98fea..a3101045 100644 --- a/chrome/browser/sync/trusted_vault_client_android.h +++ b/chrome/browser/sync/trusted_vault_client_android.h
@@ -55,6 +55,7 @@ void StoreKeys(const std::string& gaia_id, const std::vector<std::vector<uint8_t>>& keys, int last_key_version) override; + void RemoveAllStoredKeys() override; void MarkKeysAsStale(const CoreAccountInfo& account_info, base::OnceCallback<void(bool)> cb) override;
diff --git a/chrome/browser/task_manager/providers/render_process_host_task_provider.cc b/chrome/browser/task_manager/providers/render_process_host_task_provider.cc index 8629b0e..e24aa460 100644 --- a/chrome/browser/task_manager/providers/render_process_host_task_provider.cc +++ b/chrome/browser/task_manager/providers/render_process_host_task_provider.cc
@@ -25,16 +25,9 @@ namespace task_manager { -RenderProcessHostTaskProvider::RenderProcessHostTaskProvider() { - registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, - content::NotificationService::AllBrowserContextsAndSources()); - registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, - content::NotificationService::AllBrowserContextsAndSources()); - registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, - content::NotificationService::AllBrowserContextsAndSources()); -} +RenderProcessHostTaskProvider::RenderProcessHostTaskProvider() = default; -RenderProcessHostTaskProvider::~RenderProcessHostTaskProvider() {} +RenderProcessHostTaskProvider::~RenderProcessHostTaskProvider() = default; Task* RenderProcessHostTaskProvider::GetTaskOfUrlRequest(int child_id, int route_id) { @@ -59,11 +52,20 @@ // from the notification service. } } + + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, + content::NotificationService::AllBrowserContextsAndSources()); + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, + content::NotificationService::AllBrowserContextsAndSources()); + registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, + content::NotificationService::AllBrowserContextsAndSources()); } void RenderProcessHostTaskProvider::StopUpdating() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + registrar_.RemoveAll(); + // Then delete all tasks (if any). tasks_by_rph_id_.clear(); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 62846310..bb7698b 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3676,8 +3676,6 @@ "app_list/arc/arc_app_icon.h", "app_list/arc/arc_app_icon_descriptor.cc", "app_list/arc/arc_app_icon_descriptor.h", - "app_list/arc/arc_app_icon_loader.cc", - "app_list/arc/arc_app_icon_loader.h", "app_list/arc/arc_app_launcher.cc", "app_list/arc/arc_app_launcher.h", "app_list/arc/arc_app_list_prefs.cc",
diff --git a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.cc b/chrome/browser/ui/app_list/arc/arc_app_icon_loader.cc deleted file mode 100644 index bde46f8..0000000 --- a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" -#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" -#include "ui/gfx/image/image_skia_operations.h" - -ArcAppIconLoader::ArcAppIconLoader(Profile* profile, - int icon_size_in_dip, - AppIconLoaderDelegate* delegate) - : AppIconLoader(profile, icon_size_in_dip, delegate), - arc_prefs_(ArcAppListPrefs::Get(profile)) { - DCHECK(arc_prefs_); - arc_prefs_->AddObserver(this); -} - -ArcAppIconLoader::~ArcAppIconLoader() { - arc_prefs_->RemoveObserver(this); -} - -bool ArcAppIconLoader::CanLoadImageForApp(const std::string& app_id) { - if (icon_map_.find(app_id) != icon_map_.end()) - return true; - return arc::IsArcItem(profile(), app_id); -} - -void ArcAppIconLoader::FetchImage(const std::string& app_id) { - if (icon_map_.find(app_id) != icon_map_.end()) - return; // Already loading the image. - - // Note, ARC icon is available only for 48x48 dips. In case - // |icon_size_in_dip_| differs from this size, re-scale is required. - std::unique_ptr<ArcAppIcon> icon = - std::make_unique<ArcAppIcon>(profile(), app_id, icon_size_in_dip(), this); - icon->LoadSupportedScaleFactors(); - icon_map_[app_id] = std::move(icon); - UpdateImage(app_id); -} - -void ArcAppIconLoader::ClearImage(const std::string& app_id) { - icon_map_.erase(app_id); -} - -void ArcAppIconLoader::UpdateImage(const std::string& app_id) { - AppIDToIconMap::iterator it = icon_map_.find(app_id); - if (it == icon_map_.end()) - return; - - gfx::ImageSkia image = it->second->image_skia(); - DCHECK_EQ(icon_size_in_dip(), image.width()); - DCHECK_EQ(icon_size_in_dip(), image.height()); - - std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = - arc_prefs_->GetApp(app_id); - if (app_info && app_info->suspended) { - image = - gfx::ImageSkiaOperations::CreateHSLShiftedImage(image, {-1, 0, 0.6}); - } - - delegate()->OnAppImageUpdated(app_id, image); -} - -void ArcAppIconLoader::OnIconUpdated(ArcAppIcon* icon) { - UpdateImage(icon->app_id()); -} - -void ArcAppIconLoader::OnAppStatesChanged( - const std::string& app_id, - const ArcAppListPrefs::AppInfo& app_info) { - AppIDToIconMap::const_iterator it = icon_map_.find(app_id); - if (it == icon_map_.end()) - return; - - UpdateImage(app_id); -} - -void ArcAppIconLoader::OnAppIconUpdated( - const std::string& app_id, - const ArcAppIconDescriptor& descriptor) { - if (descriptor.dip_size != icon_size_in_dip()) - return; - AppIDToIconMap::const_iterator it = icon_map_.find(app_id); - if (it == icon_map_.end()) - return; - it->second->LoadForScaleFactor(descriptor.scale_factor); -}
diff --git a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.h b/chrome/browser/ui/app_list/arc/arc_app_icon_loader.h deleted file mode 100644 index f87a3ef..0000000 --- a/chrome/browser/ui/app_list/arc/arc_app_icon_loader.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_ICON_LOADER_H_ -#define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_ICON_LOADER_H_ - -#include <map> -#include <memory> -#include <string> - -#include "base/macros.h" -#include "chrome/browser/ui/app_icon_loader.h" -#include "chrome/browser/ui/app_list/arc/arc_app_icon.h" -#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" - -class Profile; - -// ARC++ icon provider for the apps. It can support multiple ARC++ apps. This -// observes apps changes and updates icons accordingly. -class ArcAppIconLoader : public AppIconLoader, - public ArcAppListPrefs::Observer, - public ArcAppIcon::Observer { - public: - ArcAppIconLoader(Profile* profile, - int icon_size_in_dip, - AppIconLoaderDelegate* delegate); - ~ArcAppIconLoader() override; - - // Overrides AppIconLoader: - bool CanLoadImageForApp(const std::string& app_id) override; - void FetchImage(const std::string& id) override; - void ClearImage(const std::string& id) override; - void UpdateImage(const std::string& id) override; - - // Overrides ArcAppListPrefs::Observer: - void OnAppStatesChanged(const std::string& app_id, - const ArcAppListPrefs::AppInfo& app_info) override; - void OnAppIconUpdated(const std::string& id, - const ArcAppIconDescriptor& descriptor) override; - - // Overrides ArcAppIcon::Observer: - void OnIconUpdated(ArcAppIcon* icon) override; - - private: - using AppIDToIconMap = std::map<std::string, std::unique_ptr<ArcAppIcon>>; - - // Unowned pointer. - ArcAppListPrefs* const arc_prefs_; - - AppIDToIconMap icon_map_; - - DISALLOW_COPY_AND_ASSIGN(ArcAppIconLoader); -}; - -#endif // CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_ICON_LOADER_H_
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index 7f73f67..ec092be 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -44,7 +44,6 @@ #include "chrome/browser/ui/app_list/app_service/app_service_app_item.h" #include "chrome/browser/ui/app_list/app_service/app_service_app_model_builder.h" #include "chrome/browser/ui/app_list/arc/arc_app_icon.h" -#include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" #include "chrome/browser/ui/app_list/arc/arc_app_launcher.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc index 90e4972..14fab3a6 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -37,7 +37,6 @@ #include "chrome/browser/ui/app_list/app_list_client_impl.h" #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" #include "chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.h" -#include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/app_list/md_icon_normalizer.h" #include "chrome/browser/ui/apps/app_info_dialog.h"
diff --git a/chrome/browser/ui/page_info/page_info.cc b/chrome/browser/ui/page_info/page_info.cc index de37567..895d919 100644 --- a/chrome/browser/ui/page_info/page_info.cc +++ b/chrome/browser/ui/page_info/page_info.cc
@@ -35,7 +35,6 @@ #include "chrome/browser/content_settings/local_shared_objects_container.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/infobars/infobar_service.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" #include "chrome/browser/permissions/permission_manager.h" #include "chrome/browser/profiles/profile.h" @@ -56,6 +55,7 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permission_result.h" #include "components/permissions/permission_uma_util.h"
diff --git a/chrome/browser/ui/page_info/page_info_ui.h b/chrome/browser/ui/page_info/page_info_ui.h index 90619d77..5b1dc497 100644 --- a/chrome/browser/ui/page_info/page_info_ui.h +++ b/chrome/browser/ui/page_info/page_info_ui.h
@@ -11,10 +11,10 @@ #include "base/strings/string16.h" #include "build/build_config.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/ui/page_info/page_info.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/permissions/chooser_context_base.h" #include "components/safe_browsing/buildflags.h" #include "ui/gfx/native_widget_types.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc index c261dc1..94d7f2b 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc
@@ -50,10 +50,6 @@ : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} void SetUp() override { - scoped_feature_list_.InitWithFeatures( - {network::features::kFetchMetadata, - network::features::kFetchMetadataDestination}, - {}); InProcessBrowserTest::SetUp(); }
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc index ae89330e..8e9bd6a 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
@@ -52,6 +52,11 @@ } void ShowUi(const std::string& name) override { +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + // The extensions menu can appear offscreen on Linux, so verifying bounds + // makes the tests flaky. + set_should_verify_dialog_bounds(false); +#endif ui_test_name_ = name; if (name == "ReloadPageBubble") {
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc index 7d1a3d0..b6e4718 100644 --- a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc +++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view.cc
@@ -133,9 +133,9 @@ } gfx::Size PermissionPromptBubbleView::CalculatePreferredSize() const { - const int width = std::min(views::View::CalculatePreferredSize().width(), - ChromeLayoutProvider::Get()->GetDistanceMetric( - DISTANCE_BUBBLE_PREFERRED_WIDTH)); + const int width = ChromeLayoutProvider::Get()->GetDistanceMetric( + DISTANCE_BUBBLE_PREFERRED_WIDTH) - + margins().width(); return gfx::Size(width, GetHeightForWidth(width)); }
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 4638f862..fc3f52cf 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -577,6 +577,8 @@ } public_saml_url_fetcher_.reset(); + was_security_token_pin_canceled_ = false; + frame_state_ = FRAME_STATE_LOADING; CallJS("login.GaiaSigninScreen.loadAuthExtension", params); } @@ -782,11 +784,14 @@ << net::ErrorToShortString(error_code); return; } - if (error_code == net::ERR_TIMED_OUT && - is_security_token_pin_dialog_running()) { - // Timeout errors are expected when the security token PIN is not entered by - // the user on time. In that case, return the user back to the first sign-in - // step instead of showing the network error screen. + if ((was_security_token_pin_canceled_ && error_code == net::ERR_FAILED) || + (is_security_token_pin_dialog_running() && + error_code == net::ERR_TIMED_OUT)) { + // Specific errors are expected when the security token PIN is aborted + // (either with a generic failure if the user canceled the dialog, or with a + // timeout error if the user didn't enter it on time). In that case, return + // the user back to the first sign-in step instead of showing the network + // error screen. ReloadGaia(/*force_reload=*/true); return; } @@ -1116,6 +1121,7 @@ return; } + was_security_token_pin_canceled_ = user_input.empty(); if (user_input.empty()) { security_token_pin_entered_callback_.Reset(); std::move(security_token_pin_dialog_closed_callback_).Run();
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h index 42d1e9f0..ff64497 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -446,6 +446,9 @@ // Is non-empty iff the dialog is active. SecurityTokenPinDialogClosedCallback security_token_pin_dialog_closed_callback_; + // Whether the PIN dialog shown during the current authentication attempt was + // canceled by the user. + bool was_security_token_pin_canceled_ = false; // Handler for |samlChallengeMachineKey| request. std::unique_ptr<SamlChallengeKeyHandler> saml_challenge_key_handler_;
diff --git a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc index 2f06f0d..9100315 100644 --- a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc
@@ -4,8 +4,10 @@ #include "chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h" +#include "base/command_line.h" #include "chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/constants/chromeos_switches.h" #include "components/login/localized_values_builder.h" namespace chromeos { @@ -55,6 +57,14 @@ &MarketingOptInScreenHandler::HandleAllSet); } +void MarketingOptInScreenHandler::GetAdditionalParameters( + base::DictionaryValue* parameters) { + parameters->SetBoolean("enableMarketingOptIn", + base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kEnableMarketingOptInScreen)); + BaseScreenHandler::GetAdditionalParameters(parameters); +} + void MarketingOptInScreenHandler::HandleAllSet( bool play_communications_opt_in, bool tips_communications_opt_in) {
diff --git a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h index 8038b22..50ae413 100644 --- a/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
@@ -56,6 +56,7 @@ // BaseScreenHandler: void Initialize() override; void RegisterMessages() override; + void GetAdditionalParameters(base::DictionaryValue* parameters) override; // WebUI event handler. void HandleAllSet(bool play_communications_opt_in,
diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc index 943ebee..31439866 100644 --- a/chrome/browser/ui/webui/policy_ui_handler.cc +++ b/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -918,7 +918,7 @@ #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) if (updater_policies_) { base::Value updater_policies(base::Value::Type::DICTIONARY); - updater_policies.SetStringKey("name", "Updater Policies"); + updater_policies.SetStringKey("name", "Google Update Policies"); updater_policies.SetKey("policyNames", GetGoogleUpdatePolicyNames()); names.SetKey("updater", std::move(updater_policies)); }
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index b5d43d9..bad12e3 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/hid/hid_chooser_context_factory.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/media/unified_autoplay_config.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" #include "chrome/browser/permissions/permission_manager.h" #include "chrome/browser/serial/serial_chooser_context.h" @@ -46,6 +45,7 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/crx_file/id_util.h" +#include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permission_uma_util.h" #include "components/permissions/permission_util.h"
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h index f665a452..63cb145 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -13,7 +13,6 @@ #include "base/containers/flat_set.h" #include "base/scoped_observer.h" #include "chrome/browser/browsing_data/cookies_tree_model.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_observer.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" @@ -21,6 +20,7 @@ #include "chrome/browser/web_applications/web_app_registrar.h" #include "components/content_settings/core/browser/content_settings_observer.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/permissions/chooser_context_base.h" #include "content/public/browser/host_zoom_map.h" #include "ppapi/buildflags/buildflags.h"
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index f7d8670..14d5a4b 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -26,7 +26,6 @@ #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/infobars/infobar_service.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/permissions/chooser_context_base_mock_permission_observer.h" #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" #include "chrome/browser/ui/browser_window.h" @@ -45,6 +44,7 @@ #include "components/content_settings/core/common/pref_names.h" #include "components/history/core/browser/history_service.h" #include "components/infobars/core/infobar.h" +#include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permission_uma_util.h" #include "components/sync_preferences/testing_pref_service_syncable.h"
diff --git a/chrome/browser/ui/webui/site_settings_helper.cc b/chrome/browser/ui/webui/site_settings_helper.cc index d81d8f1..c5ccbfe 100644 --- a/chrome/browser/ui/webui/site_settings_helper.cc +++ b/chrome/browser/ui/webui/site_settings_helper.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/hid/hid_chooser_context.h" #include "chrome/browser/hid/hid_chooser_context_factory.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/permissions/permission_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/serial/serial_chooser_context.h" @@ -28,6 +27,7 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_utils.h" +#include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_result.h" #include "components/prefs/pref_service.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h"
diff --git a/chrome/browser/ui/webui/site_settings_helper_unittest.cc b/chrome/browser/ui/webui/site_settings_helper_unittest.cc index 7f23d9b..18ddbba 100644 --- a/chrome/browser/ui/webui/site_settings_helper_unittest.cc +++ b/chrome/browser/ui/webui/site_settings_helper_unittest.cc
@@ -8,7 +8,6 @@ #include "base/guid.h" #include "base/json/json_reader.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/common/pref_names.h" @@ -19,6 +18,7 @@ #include "components/content_settings/core/common/pref_names.h" #include "components/content_settings/core/test/content_settings_mock_provider.h" #include "components/content_settings/core/test/content_settings_test_utils.h" +#include "components/permissions/chooser_context_base.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_task_environment.h" #include "extensions/browser/extension_registry.h"
diff --git a/chrome/browser/upgrade_detector/build_state.cc b/chrome/browser/upgrade_detector/build_state.cc index 70af1de..d6d3ca5 100644 --- a/chrome/browser/upgrade_detector/build_state.cc +++ b/chrome/browser/upgrade_detector/build_state.cc
@@ -47,6 +47,11 @@ observers_.RemoveObserver(observer); } +bool BuildState::HasObserver(const BuildStateObserver* observer) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return observers_.HasObserver(observer); +} + void BuildState::NotifyObserversOnUpdate() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (auto& observer : observers_)
diff --git a/chrome/browser/upgrade_detector/build_state.h b/chrome/browser/upgrade_detector/build_state.h index 35b3ce6a..23666d52 100644 --- a/chrome/browser/upgrade_detector/build_state.h +++ b/chrome/browser/upgrade_detector/build_state.h
@@ -70,6 +70,7 @@ void AddObserver(BuildStateObserver* observer); void RemoveObserver(const BuildStateObserver* observer); + bool HasObserver(const BuildStateObserver* observer) const; private: void NotifyObserversOnUpdate();
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc index bb0cfc86..8bba3f2 100644 --- a/chrome/browser/usb/usb_chooser_context.cc +++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -16,6 +16,7 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/usb/usb_blocklist.h" #include "chrome/common/pref_names.h" @@ -131,9 +132,9 @@ void UsbChooserContext::DeviceObserver::OnDeviceManagerConnectionError() {} UsbChooserContext::UsbChooserContext(Profile* profile) - : ChooserContextBase(profile, - ContentSettingsType::USB_GUARD, - ContentSettingsType::USB_CHOOSER_DATA), + : ChooserContextBase(ContentSettingsType::USB_GUARD, + ContentSettingsType::USB_CHOOSER_DATA, + HostContentSettingsMapFactory::GetForProfile(profile)), is_incognito_(profile->IsOffTheRecord()) { #if defined(OS_CHROMEOS) bool is_signin_profile = chromeos::ProfileHelper::IsSigninProfile(profile);
diff --git a/chrome/browser/usb/usb_chooser_context.h b/chrome/browser/usb/usb_chooser_context.h index 505b24e..519c7d0 100644 --- a/chrome/browser/usb/usb_chooser_context.h +++ b/chrome/browser/usb/usb_chooser_context.h
@@ -17,8 +17,8 @@ #include "base/observer_list.h" #include "base/values.h" #include "build/build_config.h" -#include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/usb/usb_policy_allowed_devices.h" +#include "components/permissions/chooser_context_base.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -27,6 +27,8 @@ #include "services/device/public/mojom/usb_manager_client.mojom.h" #include "url/origin.h" +class Profile; + class UsbChooserContext : public ChooserContextBase, public device::mojom::UsbDeviceManagerClient { public:
diff --git a/chrome/common/extensions/docs/templates/articles/xhr.html b/chrome/common/extensions/docs/templates/articles/xhr.html index 80a77543..c1ee41b 100644 --- a/chrome/common/extensions/docs/templates/articles/xhr.html +++ b/chrome/common/extensions/docs/templates/articles/xhr.html
@@ -243,19 +243,3 @@ adding either the <code>connect-src</code> or <code>default-src</code> directives. </p> - -<h2 id="origin-neither-GET-nor-HEAD">Origin header for requests with neither -GET nor HEAD methods</h2> - -<p>A request with an HTTP method that is neither GET nor HEAD (such as POST) -always has an Origin header, regardless of whether the request is cross-origin. -<span class="availability">Starting from Chrome 80</span>, the origin of -the destination URL, not the extension's security origin, is attached to the -header if all of the following conditions are met: -<ul> -<li>The request is made in a frame with the extension's security origin, such as -the background page, the popup, or an extension tab.</li> -<li>The request has a method that is neither GET nor HEAD.</li> -<li>The extension has cross-origin permission to the destination URL.</li> -</ul> -</p>
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index e2e4951..7a48e12 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -171,9 +171,9 @@ #include "extensions/renderer/dispatcher.h" #include "extensions/renderer/guest_view/mime_handler_view/mime_handler_view_container_manager.h" #include "extensions/renderer/renderer_extension_registry.h" +#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/public/web/web_view.h" -#include "ui/native_theme/native_theme.h" #endif #if BUILDFLAG(ENABLE_PLUGINS) @@ -900,8 +900,12 @@ if (GURL(frame->GetDocument().Url()).host_piece() == extension_misc::kPdfExtensionId) { if (!base::FeatureList::IsEnabled(features::kWebUIDarkMode)) { - ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( - ui::NativeTheme::PreferredColorScheme::kLight); + auto* render_view = render_frame->GetRenderView(); + auto* web_view = render_view ? render_view->GetWebView() : nullptr; + if (web_view) { + web_view->GetSettings()->SetPreferredColorScheme( + blink::PreferredColorScheme::kLight); + } } } else if (info.name == ASCIIToUTF16(ChromeContentClient::kPDFExtensionPluginName)) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 78a90d1..d1ca426 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2274,6 +2274,7 @@ "../browser/chromeos/login/screens/fingerprint_setup_browsertest.cc", "../browser/chromeos/login/screens/gesture_navigation_screen_browsertest.cc", "../browser/chromeos/login/screens/hid_detection_screen_browsertest.cc", + "../browser/chromeos/login/screens/marketing_opt_in_screen_browsertest.cc", "../browser/chromeos/login/screens/mock_arc_terms_of_service_screen.cc", "../browser/chromeos/login/screens/mock_arc_terms_of_service_screen.h", "../browser/chromeos/login/screens/mock_demo_preferences_screen.cc", @@ -6205,6 +6206,8 @@ "../browser/sync/test/integration/await_match_status_change_checker.h", "../browser/sync/test/integration/bookmarks_helper.cc", "../browser/sync/test/integration/bookmarks_helper.h", + "../browser/sync/test/integration/cookie_helper.cc", + "../browser/sync/test/integration/cookie_helper.h", "../browser/sync/test/integration/dictionary_helper.cc", "../browser/sync/test/integration/dictionary_helper.h", "../browser/sync/test/integration/dictionary_load_observer.cc", @@ -6277,8 +6280,10 @@ "//components/sync", "//components/sync:test_support_model", "//components/sync/test/fake_server", + "//content/public/browser", "//content/test:test_support", "//net", + "//services/network/public/mojom", "//skia", ]
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java index 459ccab9..471ffb46 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/Features.java
@@ -10,6 +10,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.test.util.AnnotationRule; +import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; import java.lang.annotation.Annotation; @@ -88,12 +89,14 @@ private void applyForJUnit() { ChromeFeatureList.setTestFeatures(mRegisteredState); + CachedFeatureFlags.setFeaturesForTesting(mRegisteredState); } private void applyForInstrumentation() { ChromeFeatureList.setTestCanUseDefaultsForTesting(); mergeFeatureLists("enable-features", true); mergeFeatureLists("disable-features", false); + CachedFeatureFlags.setFeaturesForTesting(mRegisteredState); } /** @@ -123,6 +126,7 @@ sInstance = null; ChromeFeatureList.setTestFeatures(null); ChromeFeatureList.resetTestCanUseDefaultsForTesting(); + CachedFeatureFlags.resetFlagsForTesting(); } /**
diff --git a/chrome/test/data/android/render_tests/TabGroupUiTest.10th_tab_selected.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/TabGroupUiTest.10th_tab_selected.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..056c61a --- /dev/null +++ b/chrome/test/data/android/render_tests/TabGroupUiTest.10th_tab_selected.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +661913928237b92a6e9b775bc6b25e9a9bfd70d8 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/TabGroupUiTest.10th_tab_selected.Nexus_5X-23.png.sha1 b/chrome/test/data/android/render_tests/TabGroupUiTest.10th_tab_selected.Nexus_5X-23.png.sha1 new file mode 100644 index 0000000..3e95b19b --- /dev/null +++ b/chrome/test/data/android/render_tests/TabGroupUiTest.10th_tab_selected.Nexus_5X-23.png.sha1
@@ -0,0 +1 @@ +df99ffecab9d4e5a9f14aa251a0c4d34d71a8abe \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/TabGroupUiTest.11th_tab_selected.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/TabGroupUiTest.11th_tab_selected.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..056c61a --- /dev/null +++ b/chrome/test/data/android/render_tests/TabGroupUiTest.11th_tab_selected.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +661913928237b92a6e9b775bc6b25e9a9bfd70d8 \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/TabGroupUiTest.11th_tab_selected.Nexus_5X-23.png.sha1 b/chrome/test/data/android/render_tests/TabGroupUiTest.11th_tab_selected.Nexus_5X-23.png.sha1 new file mode 100644 index 0000000..3e95b19b --- /dev/null +++ b/chrome/test/data/android/render_tests/TabGroupUiTest.11th_tab_selected.Nexus_5X-23.png.sha1
@@ -0,0 +1 @@ +df99ffecab9d4e5a9f14aa251a0c4d34d71a8abe \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/TabGroupUiTest.5th_tab_selected.Nexus_5-19.png.sha1 b/chrome/test/data/android/render_tests/TabGroupUiTest.5th_tab_selected.Nexus_5-19.png.sha1 new file mode 100644 index 0000000..0fa0e96 --- /dev/null +++ b/chrome/test/data/android/render_tests/TabGroupUiTest.5th_tab_selected.Nexus_5-19.png.sha1
@@ -0,0 +1 @@ +edb4497eafe8220b91051e45f71bc8710c0cadcb \ No newline at end of file
diff --git a/chrome/test/data/android/render_tests/TabGroupUiTest.5th_tab_selected.Nexus_5X-23.png.sha1 b/chrome/test/data/android/render_tests/TabGroupUiTest.5th_tab_selected.Nexus_5X-23.png.sha1 new file mode 100644 index 0000000..3a2d652 --- /dev/null +++ b/chrome/test/data/android/render_tests/TabGroupUiTest.5th_tab_selected.Nexus_5X-23.png.sha1
@@ -0,0 +1 @@ +fb7e128ac8cf0a030f4e80fb50cd5500f6cbb3ab \ No newline at end of file
diff --git a/chrome/test/data/prefers-color-scheme.html b/chrome/test/data/prefers-color-scheme.html new file mode 100644 index 0000000..f8913c1 --- /dev/null +++ b/chrome/test/data/prefers-color-scheme.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>FAIL</title> +<script> + if (window.matchMedia("(prefers-color-scheme: light)").matches) { + document.title = "light"; + } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { + document.title = "dark"; + } else if (window.matchMedia("(prefers-color-scheme: no-preference)").matches) { + document.title = "no-preference"; + } +</script>
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js index dd2cf78..68359bc2 100644 --- a/chrome/test/data/webui/settings/site_list_tests.js +++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -1044,7 +1044,7 @@ setup(function() { cookieException = { category: settings.ContentSettingsTypes.COOKIES, - embeddingOrigin: 'http://foo.com', + embeddingOrigin: settings.SITE_EXCEPTION_WILDCARD, incognito: false, setting: settings.ContentSetting.BLOCK, enforcement: '', @@ -1116,7 +1116,7 @@ }) .then(function(args) { assertEquals(newValue, args[0]); - assertEquals(newValue, args[1]); + assertEquals(settings.SITE_EXCEPTION_WILDCARD, args[1]); assertEquals(settings.ContentSettingsTypes.COOKIES, args[2]); assertEquals(cookieException.setting, args[3]); assertEquals(cookieException.incognito, args[4]);
diff --git a/chrome/test/data/webui/tab_strip/tab_swiper_test.js b/chrome/test/data/webui/tab_strip/tab_swiper_test.js index f22c99f..5f971563 100644 --- a/chrome/test/data/webui/tab_strip/tab_swiper_test.js +++ b/chrome/test/data/webui/tab_strip/tab_swiper_test.js
@@ -25,7 +25,7 @@ tabSwiper.startObserving(); }); - test('swiping progresses the animation', () => { + test('swiping does not progress the animation', () => { // Set margin top 0 to avoid offsetting the bounding client rect. document.body.style.margin = 0; @@ -47,30 +47,24 @@ let startTop = tabElement.getBoundingClientRect().top; assertEquals(startTop, 0); - // Swipe was enough to start animating the position. + // Swiping did not start the animation. pointerState.clientY = startY - (TRANSLATE_ANIMATION_THRESHOLD_PX + 1); tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState)); assertEquals(tabElStyle.maxWidth, `${tabWidth}px`); - let top = tabElement.getBoundingClientRect().top; - assertTrue(top < startTop && top > -1 * SWIPE_FINISH_THRESHOLD_PX); + assertEquals(startTop, tabElement.getBoundingClientRect().top); - // Swipe was enough to start animating max width and opacity. + // Swipe was enough to close but did not yet animate. pointerState.clientY = startY - (SWIPE_START_THRESHOLD_PX + 1); tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState)); - assertTrue( - parseInt(tabElStyle.maxWidth) > 0 && - parseInt(tabElStyle.maxWidth) < tabWidth); - assertTrue( - parseFloat(tabElStyle.opacity) > 0 && - parseFloat(tabElStyle.opacity) < 1); + assertEquals(tabWidth, parseInt(tabElStyle.maxWidth, 10)); + assertEquals('1', tabElStyle.opacity); - // Swipe was enough to finish animating. + // Verify animation still not progressed. pointerState.clientY = startY - (SWIPE_FINISH_THRESHOLD_PX + 1); tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState)); - assertEquals(tabElStyle.maxWidth, '0px'); - assertEquals(tabElStyle.opacity, '0'); - assertEquals( - tabElement.getBoundingClientRect().top, -SWIPE_FINISH_THRESHOLD_PX); + assertEquals(tabWidth, parseInt(tabElStyle.maxWidth, 10)); + assertEquals('1', tabElStyle.opacity); + assertEquals(startTop, tabElement.getBoundingClientRect().top); }); test('finishing the swipe animation fires an event', async () => { @@ -86,24 +80,6 @@ await firedEventPromise; }); - test('swiping enough and releasing finishes the animation', async () => { - const firedEventPromise = eventToPromise('swipe', tabElement); - - const tabElStyle = window.getComputedStyle(tabElement); - const startY = 50; - - const pointerState = {clientY: 50, pointerId: 1}; - tabElement.dispatchEvent(new PointerEvent('pointerdown', pointerState)); - - pointerState.clientY = startY - (SWIPE_START_THRESHOLD_PX + 1); - pointerState.movementY = 1; /* Any non-0 value here is fine. */ - tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState)); - tabElement.dispatchEvent(new PointerEvent('pointerup', pointerState)); - await firedEventPromise; - assertEquals(tabElStyle.maxWidth, '0px'); - assertEquals(tabElStyle.opacity, '0'); - }); - test('swiping and letting go before resets animation', () => { tabElement.style.setProperty('--tabstrip-tab-width', '100px'); const tabElStyle = window.getComputedStyle(tabElement); @@ -121,7 +97,7 @@ assertEquals(tabElStyle.opacity, '1'); }); - test('swiping fast enough finishes playing the animation', async () => { + test('swiping fast enough fires an event', async () => { const tabElStyle = window.getComputedStyle(tabElement); const firedEventPromise = eventToPromise('swipe', tabElement); const startY = 50; @@ -136,8 +112,6 @@ tabElement.dispatchEvent(new PointerEvent('pointerup', pointerState)); await firedEventPromise; - assertEquals(tabElStyle.maxWidth, '0px'); - assertEquals(tabElStyle.opacity, '0'); }); test('pointerdown should reset the animation time', async () => {
diff --git a/chromeos/dbus/kerberos/fake_kerberos_client.cc b/chromeos/dbus/kerberos/fake_kerberos_client.cc index 04938c42..4b60b9f 100644 --- a/chromeos/dbus/kerberos/fake_kerberos_client.cc +++ b/chromeos/dbus/kerberos/fake_kerberos_client.cc
@@ -121,14 +121,14 @@ if (it != accounts_.end()) { it->is_managed |= request.is_managed(); PostResponse(std::move(callback), kerberos::ERROR_DUPLICATE_PRINCIPAL_NAME, - mTaskDelay); + task_delay_); return; } AccountData data(request.principal_name()); data.is_managed = request.is_managed(); accounts_.push_back(data); - PostResponse(std::move(callback), kerberos::ERROR_NONE, mTaskDelay); + PostResponse(std::move(callback), kerberos::ERROR_NONE, task_delay_); } void FakeKerberosClient::RemoveAccount( @@ -146,7 +146,7 @@ } MapAccountData(response.mutable_accounts()); - PostProtoResponse(std::move(callback), response, mTaskDelay); + PostProtoResponse(std::move(callback), response, task_delay_); } void FakeKerberosClient::ClearAccounts( @@ -183,7 +183,7 @@ kerberos::ClearAccountsResponse response; MapAccountData(response.mutable_accounts()); response.set_error(kerberos::ERROR_NONE); - PostProtoResponse(std::move(callback), response, mTaskDelay); + PostProtoResponse(std::move(callback), response, task_delay_); } void FakeKerberosClient::ListAccounts( @@ -193,7 +193,7 @@ kerberos::ListAccountsResponse response; MapAccountData(response.mutable_accounts()); response.set_error(kerberos::ERROR_NONE); - PostProtoResponse(std::move(callback), response, mTaskDelay); + PostProtoResponse(std::move(callback), response, task_delay_); } void FakeKerberosClient::SetConfig(const kerberos::SetConfigRequest& request, @@ -202,19 +202,19 @@ AccountData* data = GetAccountData(request.principal_name()); if (!data) { PostResponse(std::move(callback), kerberos::ERROR_UNKNOWN_PRINCIPAL_NAME, - mTaskDelay); + task_delay_); return; } kerberos::ConfigErrorInfo error_info = ValidateConfigLines(request.krb5conf()); if (error_info.code() != kerberos::CONFIG_ERROR_NONE) { - PostResponse(std::move(callback), kerberos::ERROR_BAD_CONFIG, mTaskDelay); + PostResponse(std::move(callback), kerberos::ERROR_BAD_CONFIG, task_delay_); return; } data->krb5conf = request.krb5conf(); - PostResponse(std::move(callback), kerberos::ERROR_NONE, mTaskDelay); + PostResponse(std::move(callback), kerberos::ERROR_NONE, task_delay_); } void FakeKerberosClient::ValidateConfig( @@ -229,7 +229,7 @@ ? kerberos::ERROR_BAD_CONFIG : kerberos::ERROR_NONE); *response.mutable_error_info() = std::move(error_info); - PostProtoResponse(std::move(callback), response, mTaskDelay); + PostProtoResponse(std::move(callback), response, task_delay_); } void FakeKerberosClient::AcquireKerberosTgt( @@ -240,7 +240,7 @@ AccountData* data = GetAccountData(request.principal_name()); if (!data) { PostResponse(std::move(callback), kerberos::ERROR_UNKNOWN_PRINCIPAL_NAME, - mTaskDelay); + task_delay_); return; } @@ -271,13 +271,21 @@ // Reject empty passwords. if (password.empty()) { - PostResponse(std::move(callback), kerberos::ERROR_BAD_PASSWORD, mTaskDelay); + PostResponse(std::move(callback), kerberos::ERROR_BAD_PASSWORD, + task_delay_); + return; + } + + if (simulated_number_of_network_failures_ > 0) { + simulated_number_of_network_failures_--; + PostResponse(std::move(callback), kerberos::ERROR_NETWORK_PROBLEM, + task_delay_); return; } // It worked! Magic! data->has_tgt = true; - PostResponse(std::move(callback), kerberos::ERROR_NONE, mTaskDelay); + PostResponse(std::move(callback), kerberos::ERROR_NONE, task_delay_); } void FakeKerberosClient::GetKerberosFiles( @@ -287,7 +295,7 @@ AccountData* data = GetAccountData(request.principal_name()); if (!data) { PostResponse(std::move(callback), kerberos::ERROR_UNKNOWN_PRINCIPAL_NAME, - mTaskDelay); + task_delay_); return; } @@ -297,7 +305,7 @@ response.mutable_files()->set_krb5conf("Fake Kerberos configuration"); } response.set_error(kerberos::ERROR_NONE); - PostProtoResponse(std::move(callback), response, mTaskDelay); + PostProtoResponse(std::move(callback), response, task_delay_); } void FakeKerberosClient::ConnectToKerberosFileChangedSignal( @@ -315,7 +323,7 @@ } void FakeKerberosClient::SetTaskDelay(base::TimeDelta delay) { - mTaskDelay = delay; + task_delay_ = delay; } void FakeKerberosClient::StartRecordingFunctionCalls() { @@ -335,6 +343,11 @@ return accounts_.size(); } +void FakeKerberosClient::SetSimulatedNumberOfNetworkFailures( + int number_of_failures) { + simulated_number_of_network_failures_ = number_of_failures; +} + void FakeKerberosClient::MaybeRecordFunctionCallForTesting( const char* function_name) { if (!recorded_function_calls_)
diff --git a/chromeos/dbus/kerberos/fake_kerberos_client.h b/chromeos/dbus/kerberos/fake_kerberos_client.h index 0fd8a512..860e8f7 100644 --- a/chromeos/dbus/kerberos/fake_kerberos_client.h +++ b/chromeos/dbus/kerberos/fake_kerberos_client.h
@@ -53,6 +53,7 @@ void StartRecordingFunctionCalls() override; std::string StopRecordingAndGetRecordedFunctionCalls() override; std::size_t GetNumberOfAccounts() const override; + void SetSimulatedNumberOfNetworkFailures(int number_of_failures) override; private: using RepeatedAccountField = @@ -108,7 +109,11 @@ base::Optional<std::string> recorded_function_calls_; // Fake delay for any asynchronous operation. - base::TimeDelta mTaskDelay = base::TimeDelta::FromMilliseconds(100); + base::TimeDelta task_delay_ = base::TimeDelta::FromMilliseconds(100); + + // The simulated number of network failures on |AcquireKerberosTgt()| (for + // testing). + int simulated_number_of_network_failures_ = 0; KerberosFilesChangedCallback kerberos_files_changed_callback_; KerberosTicketExpiringCallback kerberos_ticket_expiring_callback_;
diff --git a/chromeos/dbus/kerberos/kerberos_client.h b/chromeos/dbus/kerberos/kerberos_client.h index 54b7523..bccf68d 100644 --- a/chromeos/dbus/kerberos/kerberos_client.h +++ b/chromeos/dbus/kerberos/kerberos_client.h
@@ -61,6 +61,12 @@ // Returns the number of accounts currently saved. virtual std::size_t GetNumberOfAccounts() const = 0; + // Sets the simulated number of network failures for |AcquireKerberosTgt()|. + // The default value is zero. This value should be set when testing the + // exponential backoff retry for adding managed accounts. + virtual void SetSimulatedNumberOfNetworkFailures( + int number_of_failures) = 0; + protected: virtual ~TestInterface() {} };
diff --git a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc index d3c17e23..6b96be9 100644 --- a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc +++ b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc
@@ -259,12 +259,18 @@ return; } - if (features::ShouldUseV2DeviceSync()) { + if (features::ShouldUseV1DeviceSync()) { + local_instance_id_ = local_device_metadata->instance_id.empty() + ? base::nullopt + : base::make_optional<std::string>( + local_device_metadata->instance_id); + local_legacy_device_id_ = local_device_metadata->GetDeviceId().empty() + ? base::nullopt + : base::make_optional<std::string>( + local_device_metadata->GetDeviceId()); + } else { DCHECK(!local_device_metadata->instance_id.empty()); local_instance_id_ = local_device_metadata->instance_id; - } else { - DCHECK(!local_device_metadata->GetDeviceId().empty()); - local_legacy_device_id_ = local_device_metadata->GetDeviceId(); } expiring_device_cache_->UpdateRemoteDevice(*local_device_metadata);
diff --git a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h index 281fb4a..239a831 100644 --- a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h +++ b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h
@@ -125,9 +125,13 @@ base::Optional<std::string> local_instance_id_; - // TODO(https://crbug.com/951969): Only track local Instance ID after v2 - // DeviceSync is launched, when the local device is guaranteed to have an - // Instance ID. + // TODO(https://crbug.com/1019206): Track only the local Instance ID after v1 + // DeviceSync is disabled, when the local device is guaranteed to have an + // Instance ID. Note: When v1 and v2 DeviceSync are running in parallel, if we + // are still waiting for the first v2 DeviceSync to successfully complete, it + // is possible that only v1 device data--which does not contain Instance + // IDs--is loaded by the RemoteDeviceProvider. In that case, the local device + // will not have an Instance ID until the very first v2 DeviceSync succeeds. base::Optional<std::string> local_legacy_device_id_; base::WeakPtrFactory<DeviceSyncClientImpl> weak_ptr_factory_{this};
diff --git a/components/bookmarks/browser/bookmark_codec.cc b/components/bookmarks/browser/bookmark_codec.cc index bbf771a..6d6aa53 100644 --- a/components/bookmarks/browser/bookmark_codec.cc +++ b/components/bookmarks/browser/bookmark_codec.cc
@@ -42,8 +42,6 @@ const char BookmarkCodec::kDateModifiedKey[] = "date_modified"; const char BookmarkCodec::kChildrenKey[] = "children"; const char BookmarkCodec::kMetaInfo[] = "meta_info"; -const char BookmarkCodec::kSyncTransactionVersion[] = - "sync_transaction_version"; const char BookmarkCodec::kTypeURL[] = "url"; const char BookmarkCodec::kTypeFolder[] = "folder"; const char BookmarkCodec::kSyncMetadata[] = "sync_metadata"; @@ -55,9 +53,7 @@ : ids_reassigned_(false), guids_reassigned_(false), ids_valid_(true), - maximum_id_(0), - model_sync_transaction_version_( - BookmarkNode::kInvalidSyncTransactionVersion) {} + maximum_id_(0) {} BookmarkCodec::~BookmarkCodec() = default; @@ -66,7 +62,6 @@ const std::string& sync_metadata_str) { return Encode(model->bookmark_bar_node(), model->other_node(), model->mobile_node(), model->root_node()->GetMetaInfoMap(), - model->root_node()->sync_transaction_version(), sync_metadata_str); } @@ -75,7 +70,6 @@ const BookmarkNode* other_folder_node, const BookmarkNode* mobile_folder_node, const BookmarkNode::MetaInfoMap* model_meta_info_map, - int64_t sync_transaction_version, const std::string& sync_metadata_str) { ids_reassigned_ = false; guids_reassigned_ = false; @@ -86,11 +80,6 @@ roots->Set(kMobileBookmarkFolderNameKey, EncodeNode(mobile_folder_node)); if (model_meta_info_map) roots->Set(kMetaInfo, EncodeMetaInfo(*model_meta_info_map)); - if (sync_transaction_version != - BookmarkNode::kInvalidSyncTransactionVersion) { - roots->SetString(kSyncTransactionVersion, - base::NumberToString(sync_transaction_version)); - } auto main = std::make_unique<base::DictionaryValue>(); main->SetInteger(kVersionKey, kCurrentVersion); FinalizeChecksum(); @@ -167,11 +156,6 @@ const BookmarkNode::MetaInfoMap* meta_info_map = node->GetMetaInfoMap(); if (meta_info_map) value->Set(kMetaInfo, EncodeMetaInfo(*meta_info_map)); - if (node->sync_transaction_version() != - BookmarkNode::kInvalidSyncTransactionVersion) { - value->SetString(kSyncTransactionVersion, - base::NumberToString(node->sync_transaction_version())); - } return std::move(value); } @@ -244,15 +228,7 @@ ReassignIDsHelper(mobile_folder_node); } - if (!DecodeMetaInfo(*roots_d_value, &model_meta_info_map_, - &model_sync_transaction_version_)) - return false; - - std::string sync_transaction_version_str; - if (roots_d_value->GetString(kSyncTransactionVersion, - &sync_transaction_version_str) && - !base::StringToInt64(sync_transaction_version_str, - &model_sync_transaction_version_)) + if (!DecodeMetaInfo(*roots_d_value, &model_meta_info_map_)) return false; std::string sync_metadata_str_base64; @@ -415,28 +391,17 @@ node->SetTitle(title); node->set_date_added(Time::FromInternalValue(internal_time)); - int64_t sync_transaction_version = node->sync_transaction_version(); BookmarkNode::MetaInfoMap meta_info_map; - if (!DecodeMetaInfo(value, &meta_info_map, &sync_transaction_version)) + if (!DecodeMetaInfo(value, &meta_info_map)) return false; node->SetMetaInfoMap(meta_info_map); - std::string sync_transaction_version_str; - if (value.GetString(kSyncTransactionVersion, &sync_transaction_version_str) && - !base::StringToInt64(sync_transaction_version_str, - &sync_transaction_version)) - return false; - - node->set_sync_transaction_version(sync_transaction_version); - return true; } bool BookmarkCodec::DecodeMetaInfo(const base::DictionaryValue& value, - BookmarkNode::MetaInfoMap* meta_info_map, - int64_t* sync_transaction_version) { + BookmarkNode::MetaInfoMap* meta_info_map) { DCHECK(meta_info_map); - DCHECK(sync_transaction_version); meta_info_map->clear(); const base::Value* meta_info; @@ -464,18 +429,6 @@ return false; DecodeMetaInfoHelper(*meta_info_dict, std::string(), meta_info_map); - // Previously sync transaction version was stored in the meta info field - // using this key. If the key is present when decoding, set the sync - // transaction version to its value, then delete the field. - if (deserialized_holder) { - const char kBookmarkTransactionVersionKey[] = "sync.transaction_version"; - auto it = meta_info_map->find(kBookmarkTransactionVersionKey); - if (it != meta_info_map->end()) { - base::StringToInt64(it->second, sync_transaction_version); - meta_info_map->erase(it); - } - } - return true; }
diff --git a/components/bookmarks/browser/bookmark_codec.h b/components/bookmarks/browser/bookmark_codec.h index 279528d..017ca98 100644 --- a/components/bookmarks/browser/bookmark_codec.h +++ b/components/bookmarks/browser/bookmark_codec.h
@@ -51,7 +51,6 @@ const BookmarkNode* other_folder_node, const BookmarkNode* mobile_folder_node, const BookmarkNode::MetaInfoMap* model_meta_info_map, - int64_t sync_transaction_version, const std::string& sync_metadata_str); // Decodes the previously encoded value to the specified nodes as well as @@ -81,11 +80,6 @@ return model_meta_info_map_; } - // Return the sync transaction version of the bookmark model root. - int64_t model_sync_transaction_version() const { - return model_sync_transaction_version_; - } - // Returns whether the IDs were reassigned during decoding. Always returns // false after encoding. bool ids_reassigned() const { return ids_reassigned_; } @@ -110,7 +104,6 @@ static const char kDateModifiedKey[]; static const char kChildrenKey[]; static const char kMetaInfo[]; - static const char kSyncTransactionVersion[]; // Allows the BookmarkClient to read and a write a string blob from the JSON // file. That string captures the bookmarks sync metadata. static const char kSyncMetadata[]; @@ -154,14 +147,10 @@ BookmarkNode* parent, BookmarkNode* node); - // Decodes the meta info from the supplied value. If the meta info contains - // a "sync.transaction_version" key, the value of that field will be stored - // in the sync_transaction_version variable, then deleted. This is for - // backward-compatibility reasons. - // meta_info_map and sync_transaction_version must not be NULL. + // Decodes the meta info from the supplied value. meta_info_map must not be + // nullptr. bool DecodeMetaInfo(const base::DictionaryValue& value, - BookmarkNode::MetaInfoMap* meta_info_map, - int64_t* sync_transaction_version); + BookmarkNode::MetaInfoMap* meta_info_map); // Decodes the meta info from the supplied sub-node dictionary. The values // found will be inserted in meta_info_map with the given prefix added to the @@ -221,9 +210,6 @@ // Meta info set on bookmark model root. BookmarkNode::MetaInfoMap model_meta_info_map_; - // Sync transaction version set on bookmark model root. - int64_t model_sync_transaction_version_; - DISALLOW_COPY_AND_ASSIGN(BookmarkCodec); };
diff --git a/components/bookmarks/browser/bookmark_codec_unittest.cc b/components/bookmarks/browser/bookmark_codec_unittest.cc index 3b3f298..9e2fe1fe 100644 --- a/components/bookmarks/browser/bookmark_codec_unittest.cc +++ b/components/bookmarks/browser/bookmark_codec_unittest.cc
@@ -184,8 +184,6 @@ sync_metadata_str); model->set_next_node_id(max_id); AsMutable(model->root_node())->SetMetaInfoMap(codec->model_meta_info_map()); - AsMutable(model->root_node()) - ->set_sync_transaction_version(codec->model_sync_transaction_version()); return result; } @@ -452,28 +450,6 @@ EXPECT_FALSE(child->GetMetaInfo("other_key", &meta_value)); } -TEST_F(BookmarkCodecTest, EncodeAndDecodeSyncTransactionVersion) { - // Add sync transaction version and encode. - std::unique_ptr<BookmarkModel> model(CreateTestModel2()); - model->SetNodeSyncTransactionVersion(model->root_node(), 1); - const BookmarkNode* bbn = model->bookmark_bar_node(); - model->SetNodeSyncTransactionVersion(bbn->children()[1].get(), 42); - - std::string checksum; - std::unique_ptr<base::Value> value = - EncodeHelper(model.get(), /*sync_metadata_str=*/std::string(), &checksum); - ASSERT_TRUE(value.get() != nullptr); - - // Decode and verify. - model = DecodeHelper(*value, checksum, &checksum, false, - /*sync_metadata_str=*/nullptr); - EXPECT_EQ(1, model->root_node()->sync_transaction_version()); - bbn = model->bookmark_bar_node(); - EXPECT_EQ(42, bbn->children()[1]->sync_transaction_version()); - EXPECT_EQ(BookmarkNode::kInvalidSyncTransactionVersion, - bbn->children()[0]->sync_transaction_version()); -} - // Verifies that we can still decode the old codec format after changing the // way meta info is stored. TEST_F(BookmarkCodecTest, CanDecodeMetaInfoAsString) { @@ -490,20 +466,11 @@ ASSERT_TRUE(Decode(&decoder, *root.get(), model.get(), /*sync_metadata_str=*/nullptr)); - EXPECT_EQ(1, model->root_node()->sync_transaction_version()); const BookmarkNode* bbn = model->bookmark_bar_node(); - EXPECT_EQ(BookmarkNode::kInvalidSyncTransactionVersion, - bbn->children()[0]->sync_transaction_version()); - EXPECT_EQ(42, bbn->children()[1]->sync_transaction_version()); - const char kSyncTransactionVersionKey[] = "sync.transaction_version"; const char kNormalKey[] = "key"; const char kNestedKey[] = "nested.key"; std::string meta_value; - EXPECT_FALSE( - model->root_node()->GetMetaInfo(kSyncTransactionVersionKey, &meta_value)); - EXPECT_FALSE( - bbn->children()[1]->GetMetaInfo(kSyncTransactionVersionKey, &meta_value)); EXPECT_TRUE(bbn->children()[0]->GetMetaInfo(kNormalKey, &meta_value)); EXPECT_EQ("value", meta_value); EXPECT_TRUE(bbn->children()[1]->GetMetaInfo(kNormalKey, &meta_value));
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index ffbcd66..b1825f4c 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -502,20 +502,6 @@ non_cloned_keys_.insert(key); } -void BookmarkModel::SetNodeSyncTransactionVersion( - const BookmarkNode* node, - int64_t sync_transaction_version) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(client_->CanSyncNode(node)); - - if (sync_transaction_version == node->sync_transaction_version()) - return; - - AsMutable(node)->set_sync_transaction_version(sync_transaction_version); - if (store_) - store_->ScheduleSave(); -} - void BookmarkModel::OnFaviconsChanged(const std::set<GURL>& page_urls, const GURL& icon_url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -895,8 +881,6 @@ VisibilityComparator(client_.get())); root_->SetMetaInfoMap(details->model_meta_info_map()); - root_->set_sync_transaction_version( - details->model_sync_transaction_version()); loaded_ = true; client_->DecodeBookmarkSyncMetadata(
diff --git a/components/bookmarks/browser/bookmark_model.h b/components/bookmarks/browser/bookmark_model.h index 60845af..672e75e 100644 --- a/components/bookmarks/browser/bookmark_model.h +++ b/components/bookmarks/browser/bookmark_model.h
@@ -304,10 +304,6 @@ return non_cloned_keys_; } - // Sets the sync transaction version of |node|. - void SetNodeSyncTransactionVersion(const BookmarkNode* node, - int64_t sync_transaction_version); - // Notify BookmarkModel that the favicons for the given page URLs (e.g. // http://www.google.com) and the given icon URL (e.g. // http://www.google.com/favicon.ico) have changed. It is valid to call
diff --git a/components/bookmarks/browser/bookmark_node.cc b/components/bookmarks/browser/bookmark_node.cc index f7928c82..c2c1dc68 100644 --- a/components/bookmarks/browser/bookmark_node.cc +++ b/components/bookmarks/browser/bookmark_node.cc
@@ -46,7 +46,6 @@ // BookmarkNode --------------------------------------------------------------- // static -const int64_t BookmarkNode::kInvalidSyncTransactionVersion = -1; const char BookmarkNode::kRootNodeGuid[] = "00000000-0000-4000-a000-000000000001"; const char BookmarkNode::kBookmarkBarNodeGuid[] =
diff --git a/components/bookmarks/browser/bookmark_node.h b/components/bookmarks/browser/bookmark_node.h index 0f2a600..6366123 100644 --- a/components/bookmarks/browser/bookmark_node.h +++ b/components/bookmarks/browser/bookmark_node.h
@@ -44,7 +44,6 @@ typedef std::map<std::string, std::string> MetaInfoMap; - static const int64_t kInvalidSyncTransactionVersion; static const char kRootNodeGuid[]; static const char kBookmarkBarNodeGuid[]; static const char kOtherBookmarksNodeGuid[]; @@ -125,11 +124,6 @@ // Returns NULL if there are no values in the map. const MetaInfoMap* GetMetaInfoMap() const; - void set_sync_transaction_version(int64_t sync_transaction_version) { - sync_transaction_version_ = sync_transaction_version; - } - int64_t sync_transaction_version() const { return sync_transaction_version_; } - // TitledUrlNode interface methods. const base::string16& GetTitledUrlNodeTitle() const override; const GURL& GetTitledUrlNodeUrl() const override; @@ -218,9 +212,6 @@ // A map that stores arbitrary meta information about the node. std::unique_ptr<MetaInfoMap> meta_info_map_; - // The sync transaction version. - int64_t sync_transaction_version_ = kInvalidSyncTransactionVersion; - const bool is_permanent_node_; DISALLOW_COPY_AND_ASSIGN(BookmarkNode);
diff --git a/components/bookmarks/browser/bookmark_storage.cc b/components/bookmarks/browser/bookmark_storage.cc index 5611c16a..9b8ba38 100644 --- a/components/bookmarks/browser/bookmark_storage.cc +++ b/components/bookmarks/browser/bookmark_storage.cc
@@ -141,8 +141,6 @@ details->set_ids_reassigned(codec.ids_reassigned()); details->set_guids_reassigned(codec.guids_reassigned()); details->set_model_meta_info_map(codec.model_meta_info_map()); - details->set_model_sync_transaction_version( - codec.model_sync_transaction_version()); UMA_HISTOGRAM_TIMES("Bookmarks.DecodeTime", TimeTicks::Now() - start_time); int64_t size = 0; @@ -202,9 +200,7 @@ BookmarkLoadDetails::BookmarkLoadDetails(BookmarkClient* client) : load_managed_node_callback_(client->GetLoadManagedNodeCallback()), - index_(std::make_unique<TitledUrlIndex>()), - model_sync_transaction_version_( - BookmarkNode::kInvalidSyncTransactionVersion) { + index_(std::make_unique<TitledUrlIndex>()) { // WARNING: do NOT add |client| as a member. Much of this code runs on another // thread, and |client_| is not thread safe, and/or may be destroyed before // this.
diff --git a/components/bookmarks/browser/bookmark_storage.h b/components/bookmarks/browser/bookmark_storage.h index 3f18b59d..41b4d2ec 100644 --- a/components/bookmarks/browser/bookmark_storage.h +++ b/components/bookmarks/browser/bookmark_storage.h
@@ -70,13 +70,6 @@ model_meta_info_map_ = meta_info_map; } - int64_t model_sync_transaction_version() const { - return model_sync_transaction_version_; - } - void set_model_sync_transaction_version(int64_t sync_transaction_version) { - model_sync_transaction_version_ = sync_transaction_version; - } - // Max id of the nodes. void set_max_id(int64_t max_id) { max_id_ = max_id; } int64_t max_id() const { return max_id_; } @@ -128,7 +121,6 @@ LoadManagedNodeCallback load_managed_node_callback_; std::unique_ptr<TitledUrlIndex> index_; BookmarkNode::MetaInfoMap model_meta_info_map_; - int64_t model_sync_transaction_version_; int64_t max_id_ = 1; std::string computed_checksum_; std::string stored_checksum_;
diff --git a/components/invalidation/impl/BUILD.gn b/components/invalidation/impl/BUILD.gn index 81090093..a9d5aae 100644 --- a/components/invalidation/impl/BUILD.gn +++ b/components/invalidation/impl/BUILD.gn
@@ -115,8 +115,8 @@ if (!is_android) { # Non-Android tests. sources += [ - "object_id_invalidation_map_unittest.cc", "single_object_invalidation_set_unittest.cc", + "topic_invalidation_map_unittest.cc", "unacked_invalidation_set_unittest.cc", ] }
diff --git a/components/invalidation/impl/object_id_invalidation_map_unittest.cc b/components/invalidation/impl/object_id_invalidation_map_unittest.cc deleted file mode 100644 index 0021d2c8..0000000 --- a/components/invalidation/impl/object_id_invalidation_map_unittest.cc +++ /dev/null
@@ -1,105 +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 "components/invalidation/public/object_id_invalidation_map.h" - -#include <memory> - -#include "google/cacheinvalidation/types.pb.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace syncer { - -namespace { - -class ObjectIdInvalidationMapTest : public testing::Test { - public: - ObjectIdInvalidationMapTest() - : kIdOne(ipc::invalidation::ObjectSource::TEST, "one"), - kIdTwo(ipc::invalidation::ObjectSource::TEST, "two"), - kInv1(Invalidation::Init(kIdOne, 10, "ten")) { - set1.insert(kIdOne); - set2.insert(kIdTwo); - all_set.insert(kIdOne); - all_set.insert(kIdTwo); - - one_invalidation.Insert(kInv1); - invalidate_all = ObjectIdInvalidationMap::InvalidateAll(all_set); - } - - protected: - const invalidation::ObjectId kIdOne; - const invalidation::ObjectId kIdTwo; - const Invalidation kInv1; - - ObjectIdSet set1; - ObjectIdSet set2; - ObjectIdSet all_set; - ObjectIdInvalidationMap empty; - ObjectIdInvalidationMap one_invalidation; - ObjectIdInvalidationMap invalidate_all; -}; - -TEST_F(ObjectIdInvalidationMapTest, Empty) { - EXPECT_TRUE(empty.Empty()); - EXPECT_FALSE(one_invalidation.Empty()); - EXPECT_FALSE(invalidate_all.Empty()); -} - -TEST_F(ObjectIdInvalidationMapTest, Equality) { - ObjectIdInvalidationMap empty2; - EXPECT_TRUE(empty == empty2); - - ObjectIdInvalidationMap one_invalidation2; - one_invalidation2.Insert(kInv1); - EXPECT_TRUE(one_invalidation == one_invalidation2); - - EXPECT_FALSE(empty == invalidate_all); -} - -TEST_F(ObjectIdInvalidationMapTest, GetObjectIds) { - EXPECT_EQ(ObjectIdSet(), empty.GetObjectIds()); - EXPECT_EQ(set1, one_invalidation.GetObjectIds()); - EXPECT_EQ(all_set, invalidate_all.GetObjectIds()); -} - -TEST_F(ObjectIdInvalidationMapTest, GetSubsetWithObjectIds) { - EXPECT_TRUE(empty.GetSubsetWithObjectIds(set1).Empty()); - - EXPECT_TRUE(one_invalidation.GetSubsetWithObjectIds(set1) == - one_invalidation); - EXPECT_TRUE(one_invalidation.GetSubsetWithObjectIds(all_set) == - one_invalidation); - EXPECT_TRUE(one_invalidation.GetSubsetWithObjectIds(set2).Empty()); - - EXPECT_TRUE(invalidate_all.GetSubsetWithObjectIds(ObjectIdSet()).Empty()); -} - -TEST_F(ObjectIdInvalidationMapTest, SerializeEmpty) { - std::unique_ptr<base::ListValue> value = empty.ToValue(); - ASSERT_TRUE(value.get()); - ObjectIdInvalidationMap deserialized; - deserialized.ResetFromValue(*value); - EXPECT_TRUE(empty == deserialized); -} - -TEST_F(ObjectIdInvalidationMapTest, SerializeOneInvalidation) { - std::unique_ptr<base::ListValue> value = one_invalidation.ToValue(); - ASSERT_TRUE(value.get()); - ObjectIdInvalidationMap deserialized; - deserialized.ResetFromValue(*value); - EXPECT_TRUE(one_invalidation == deserialized); -} - -TEST_F(ObjectIdInvalidationMapTest, SerializeInvalidateAll) { - std::unique_ptr<base::ListValue> value = invalidate_all.ToValue(); - ASSERT_TRUE(value.get()); - ObjectIdInvalidationMap deserialized; - deserialized.ResetFromValue(*value); - EXPECT_TRUE(invalidate_all == deserialized); -} - -} // namespace - -} // namespace syncer
diff --git a/components/invalidation/impl/topic_invalidation_map_unittest.cc b/components/invalidation/impl/topic_invalidation_map_unittest.cc new file mode 100644 index 0000000..11173a4 --- /dev/null +++ b/components/invalidation/impl/topic_invalidation_map_unittest.cc
@@ -0,0 +1,84 @@ +// Copyright 2020 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/invalidation/public/topic_invalidation_map.h" + +#include <memory> + +#include "google/cacheinvalidation/types.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer { + +namespace { + +// TODO(crbug.com/1056651): some methods aren't covered by tests, it's likely +// worth adding them (especially for ToValue(), which is passed to js code). +class TopicInvalidationMapTest : public testing::Test { + public: + TopicInvalidationMapTest() + : kTopicOne("one"), + kTopicTwo("two"), + kInv1(Invalidation::Init(kTopicOne, 10, "ten")) { + set1_.insert(kTopicOne); + set2_.insert(kTopicTwo); + all_set_.insert(kTopicOne); + all_set_.insert(kTopicTwo); + + one_invalidation_.Insert(kInv1); + invalidate_all_.Insert(Invalidation::InitUnknownVersion(kTopicOne)); + invalidate_all_.Insert(Invalidation::InitUnknownVersion(kTopicTwo)); + } + + protected: + const Topic kTopicOne; + const Topic kTopicTwo; + const Invalidation kInv1; + + TopicSet set1_; + TopicSet set2_; + TopicSet all_set_; + TopicInvalidationMap empty_; + TopicInvalidationMap one_invalidation_; + TopicInvalidationMap invalidate_all_; +}; + +TEST_F(TopicInvalidationMapTest, Empty) { + EXPECT_TRUE(empty_.Empty()); + EXPECT_FALSE(one_invalidation_.Empty()); + EXPECT_FALSE(invalidate_all_.Empty()); +} + +TEST_F(TopicInvalidationMapTest, Equality) { + // TODO(crbug.com/1056651): equality operator is only used in tests, so maybe + // factor it away from the TopicInvalidationMap. + TopicInvalidationMap empty2; + EXPECT_EQ(empty_, empty2); + + TopicInvalidationMap one_invalidation_2; + one_invalidation_2.Insert(kInv1); + EXPECT_EQ(one_invalidation_, one_invalidation_2); + + EXPECT_FALSE(empty_ == invalidate_all_); +} + +TEST_F(TopicInvalidationMapTest, GetTopics) { + EXPECT_EQ(TopicSet(), empty_.GetTopics()); + EXPECT_EQ(set1_, one_invalidation_.GetTopics()); + EXPECT_EQ(all_set_, invalidate_all_.GetTopics()); +} + +TEST_F(TopicInvalidationMapTest, GetSubsetWithTopics) { + EXPECT_TRUE(empty_.GetSubsetWithTopics(set1_).Empty()); + + EXPECT_EQ(one_invalidation_.GetSubsetWithTopics(set1_), one_invalidation_); + EXPECT_EQ(one_invalidation_.GetSubsetWithTopics(all_set_), one_invalidation_); + EXPECT_TRUE(one_invalidation_.GetSubsetWithTopics(set2_).Empty()); + + EXPECT_TRUE(invalidate_all_.GetSubsetWithTopics(TopicSet()).Empty()); +} + +} // namespace + +} // namespace syncer
diff --git a/components/invalidation/public/BUILD.gn b/components/invalidation/public/BUILD.gn index fafda47..0089d81 100644 --- a/components/invalidation/public/BUILD.gn +++ b/components/invalidation/public/BUILD.gn
@@ -20,8 +20,6 @@ "invalidation_util.h", "invalidator_state.cc", "invalidator_state.h", - "object_id_invalidation_map.cc", - "object_id_invalidation_map.h", "single_object_invalidation_set.cc", "single_object_invalidation_set.h", "topic_invalidation_map.cc",
diff --git a/components/invalidation/public/object_id_invalidation_map.cc b/components/invalidation/public/object_id_invalidation_map.cc deleted file mode 100644 index 253c8c4..0000000 --- a/components/invalidation/public/object_id_invalidation_map.cc +++ /dev/null
@@ -1,123 +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 "components/invalidation/public/object_id_invalidation_map.h" - -#include <stddef.h> - -#include "base/json/json_string_value_serializer.h" - -namespace syncer { - -// static -ObjectIdInvalidationMap ObjectIdInvalidationMap::InvalidateAll( - const ObjectIdSet& ids) { - ObjectIdInvalidationMap invalidate_all; - for (auto it = ids.begin(); it != ids.end(); ++it) { - invalidate_all.Insert(Invalidation::InitUnknownVersion(*it)); - } - return invalidate_all; -} - -ObjectIdInvalidationMap::ObjectIdInvalidationMap() {} - -ObjectIdInvalidationMap::ObjectIdInvalidationMap( - const ObjectIdInvalidationMap& other) = default; - -ObjectIdInvalidationMap::~ObjectIdInvalidationMap() {} - -ObjectIdSet ObjectIdInvalidationMap::GetObjectIds() const { - ObjectIdSet ret; - for (auto it = map_.begin(); it != map_.end(); ++it) { - ret.insert(it->first); - } - return ret; -} - -bool ObjectIdInvalidationMap::Empty() const { - return map_.empty(); -} - -void ObjectIdInvalidationMap::Insert(const Invalidation& invalidation) { - map_[invalidation.object_id()].Insert(invalidation); -} - -ObjectIdInvalidationMap ObjectIdInvalidationMap::GetSubsetWithObjectIds( - const ObjectIdSet& ids) const { - IdToListMap new_map; - for (auto it = ids.begin(); it != ids.end(); ++it) { - auto lookup = map_.find(*it); - if (lookup != map_.end()) { - new_map[*it] = lookup->second; - } - } - return ObjectIdInvalidationMap(new_map); -} - -const SingleObjectInvalidationSet& ObjectIdInvalidationMap::ForObject( - invalidation::ObjectId id) const { - auto lookup = map_.find(id); - DCHECK(lookup != map_.end()); - DCHECK(!lookup->second.IsEmpty()); - return lookup->second; -} - -void ObjectIdInvalidationMap::GetAllInvalidations( - std::vector<syncer::Invalidation>* out) const { - for (auto it = map_.begin(); it != map_.end(); ++it) { - out->insert(out->begin(), it->second.begin(), it->second.end()); - } -} -void ObjectIdInvalidationMap::AcknowledgeAll() const { - for (auto it1 = map_.begin(); it1 != map_.end(); ++it1) { - for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) { - it2->Acknowledge(); - } - } -} - -bool ObjectIdInvalidationMap::operator==( - const ObjectIdInvalidationMap& other) const { - return map_ == other.map_; -} - -std::unique_ptr<base::ListValue> ObjectIdInvalidationMap::ToValue() const { - std::unique_ptr<base::ListValue> value(new base::ListValue()); - for (auto it1 = map_.begin(); it1 != map_.end(); ++it1) { - for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) { - value->Append(it2->ToValue()); - } - } - return value; -} - -bool ObjectIdInvalidationMap::ResetFromValue(const base::ListValue& value) { - map_.clear(); - for (size_t i = 0; i < value.GetSize(); ++i) { - const base::DictionaryValue* dict; - if (!value.GetDictionary(i, &dict)) { - return false; - } - std::unique_ptr<Invalidation> invalidation = - Invalidation::InitFromValue(*dict); - if (!invalidation) { - return false; - } - Insert(*invalidation); - } - return true; -} - -std::string ObjectIdInvalidationMap::ToString() const { - std::string output; - JSONStringValueSerializer serializer(&output); - serializer.set_pretty_print(true); - serializer.Serialize(*ToValue()); - return output; -} - -ObjectIdInvalidationMap::ObjectIdInvalidationMap(const IdToListMap& map) - : map_(map) {} - -} // namespace syncer
diff --git a/components/invalidation/public/object_id_invalidation_map.h b/components/invalidation/public/object_id_invalidation_map.h deleted file mode 100644 index 140b330..0000000 --- a/components/invalidation/public/object_id_invalidation_map.h +++ /dev/null
@@ -1,78 +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 COMPONENTS_INVALIDATION_PUBLIC_OBJECT_ID_INVALIDATION_MAP_H_ -#define COMPONENTS_INVALIDATION_PUBLIC_OBJECT_ID_INVALIDATION_MAP_H_ - -#include <map> -#include <memory> -#include <vector> - -#include "components/invalidation/public/invalidation.h" -#include "components/invalidation/public/invalidation_export.h" -#include "components/invalidation/public/invalidation_util.h" -#include "components/invalidation/public/single_object_invalidation_set.h" - -namespace syncer { - -// A set of notifications with some helper methods to organize them by object ID -// and version number. -class INVALIDATION_EXPORT ObjectIdInvalidationMap { - public: - // Creates an invalidation map that includes an 'unknown version' - // invalidation for each specified ID in |ids|. - static ObjectIdInvalidationMap InvalidateAll(const ObjectIdSet& ids); - - ObjectIdInvalidationMap(); - ObjectIdInvalidationMap(const ObjectIdInvalidationMap& other); - ~ObjectIdInvalidationMap(); - - // Returns set of ObjectIds for which at least one invalidation is present. - ObjectIdSet GetObjectIds() const; - - // Returns true if this map contains no invalidations. - bool Empty() const; - - // Returns true if both maps contain the same set of invalidations. - bool operator==(const ObjectIdInvalidationMap& other) const; - - // Inserts a new invalidation into this map. - void Insert(const Invalidation& invalidation); - - // Returns a new map containing the subset of invaliations from this map - // whose IDs were in the specified |ids| set. - ObjectIdInvalidationMap GetSubsetWithObjectIds(const ObjectIdSet& ids) const; - - // Returns the subset of invalidations with IDs matching |id|. - const SingleObjectInvalidationSet& ForObject( - invalidation::ObjectId id) const; - - // Returns the contents of this map in a single vector. - void GetAllInvalidations(std::vector<syncer::Invalidation>* out) const; - - // Call Acknowledge() on all contained Invalidations. - void AcknowledgeAll() const; - - // Serialize this map to a value. - std::unique_ptr<base::ListValue> ToValue() const; - - // Deserialize the value into a map and use it to re-initialize this object. - bool ResetFromValue(const base::ListValue& value); - - // Prints the contentes of this map as a human-readable string. - std::string ToString() const; - - private: - typedef std::map<invalidation::ObjectId, - SingleObjectInvalidationSet, - ObjectIdLessThan> IdToListMap; - - ObjectIdInvalidationMap(const IdToListMap& map); - - IdToListMap map_; -}; - -} // namespace syncer - -#endif // COMPONENTS_INVALIDATION_PUBLIC_OBJECT_ID_INVALIDATION_MAP_H_
diff --git a/components/invalidation/public/topic_invalidation_map.cc b/components/invalidation/public/topic_invalidation_map.cc index 70c9c95f..05938d2 100644 --- a/components/invalidation/public/topic_invalidation_map.cc +++ b/components/invalidation/public/topic_invalidation_map.cc
@@ -6,8 +6,7 @@ #include <stddef.h> -#include "base/json/json_string_value_serializer.h" -#include "components/invalidation/public/object_id_invalidation_map.h" +#include "base/values.h" namespace syncer { @@ -35,7 +34,7 @@ TopicInvalidationMap TopicInvalidationMap::GetSubsetWithTopics( const Topics& topics) const { - TopicToListMap new_map; + std::map<Topic, SingleObjectInvalidationSet> new_map; for (const auto& topic : topics) { auto lookup = map_.find(topic.first); if (lookup != map_.end()) { @@ -45,6 +44,18 @@ return TopicInvalidationMap(new_map); } +TopicInvalidationMap TopicInvalidationMap::GetSubsetWithTopics( + const TopicSet& topics) const { + std::map<Topic, SingleObjectInvalidationSet> new_map; + for (const auto& topic : topics) { + auto lookup = map_.find(topic); + if (lookup != map_.end()) { + new_map[topic] = lookup->second; + } + } + return TopicInvalidationMap(new_map); +} + const SingleObjectInvalidationSet& TopicInvalidationMap::ForTopic( Topic topic) const { auto lookup = map_.find(topic); @@ -82,54 +93,8 @@ return value; } -bool TopicInvalidationMap::ResetFromValue(const base::ListValue& value) { - map_.clear(); - for (size_t i = 0; i < value.GetSize(); ++i) { - const base::DictionaryValue* dict; - if (!value.GetDictionary(i, &dict)) { - return false; - } - std::unique_ptr<Invalidation> invalidation = - Invalidation::InitFromValue(*dict); - if (!invalidation) { - return false; - } - Insert(*invalidation); - } - return true; -} - -std::string TopicInvalidationMap::ToString() const { - std::string output; - JSONStringValueSerializer serializer(&output); - serializer.set_pretty_print(true); - serializer.Serialize(*ToValue()); - return output; -} - -TopicInvalidationMap::TopicInvalidationMap(const TopicToListMap& map) +TopicInvalidationMap::TopicInvalidationMap( + const std::map<Topic, SingleObjectInvalidationSet>& map) : map_(map) {} -TopicInvalidationMap ConvertObjectIdInvalidationMapToTopicInvalidationMap( - ObjectIdInvalidationMap object_ids_map) { - TopicInvalidationMap topics_map; - std::vector<Invalidation> invalidations; - object_ids_map.GetAllInvalidations(&invalidations); - for (const auto& invalidation : invalidations) { - topics_map.Insert(invalidation); - } - return topics_map; -} - -ObjectIdInvalidationMap ConvertTopicInvalidationMapToObjectIdInvalidationMap( - const TopicInvalidationMap& topics_map) { - ObjectIdInvalidationMap object_ids_map; - std::vector<Invalidation> invalidations; - topics_map.GetAllInvalidations(&invalidations); - for (const auto& invalidation : invalidations) { - object_ids_map.Insert(invalidation); - } - return object_ids_map; -} - } // namespace syncer
diff --git a/components/invalidation/public/topic_invalidation_map.h b/components/invalidation/public/topic_invalidation_map.h index e72ae32..3999311 100644 --- a/components/invalidation/public/topic_invalidation_map.h +++ b/components/invalidation/public/topic_invalidation_map.h
@@ -14,8 +14,11 @@ #include "components/invalidation/public/invalidation_util.h" #include "components/invalidation/public/single_object_invalidation_set.h" +namespace base { +class ListValue; +} // namespace base + namespace syncer { -class ObjectIdInvalidationMap; // A set of notifications with some helper methods to organize them by object ID // and version number. @@ -38,11 +41,17 @@ void Insert(const Invalidation& invalidation); // Returns a new map containing the subset of invaliations from this map - // whose IDs were in the specified |ids| set. - TopicInvalidationMap GetSubsetWithTopics(const Topics& ids) const; + // whose topic were in the specified |topics|. + // TODO(crbug.com/1029698): replace all usages with the version below and + // remove this method. + TopicInvalidationMap GetSubsetWithTopics(const Topics& topics) const; - // Returns the subset of invalidations with IDs matching |id|. - const SingleObjectInvalidationSet& ForTopic(Topic id) const; + // Returns a new map containing the subset of invaliations from this map + // whose topic were in the specified |topics|. + TopicInvalidationMap GetSubsetWithTopics(const TopicSet& topics) const; + + // Returns the subset of invalidations with Topic matching |topic|. + const SingleObjectInvalidationSet& ForTopic(Topic topic) const; // Returns the contents of this map in a single vector. void GetAllInvalidations(std::vector<syncer::Invalidation>* out) const; @@ -50,29 +59,16 @@ // Call Acknowledge() on all contained Invalidations. void AcknowledgeAll() const; - // Serialize this map to a value. + // Serialize this map to a value. Used to expose value on + // chrome://invalidations page. std::unique_ptr<base::ListValue> ToValue() const; - // Deserialize the value into a map and use it to re-initialize this object. - bool ResetFromValue(const base::ListValue& value); - - // Prints the contentes of this map as a human-readable string. - std::string ToString() const; - private: - typedef std::map<Topic, SingleObjectInvalidationSet> TopicToListMap; + TopicInvalidationMap(const std::map<Topic, SingleObjectInvalidationSet>& map); - TopicInvalidationMap(const TopicToListMap& map); - - TopicToListMap map_; + std::map<Topic, SingleObjectInvalidationSet> map_; }; -TopicInvalidationMap ConvertObjectIdInvalidationMapToTopicInvalidationMap( - ObjectIdInvalidationMap object_ids_map); - -ObjectIdInvalidationMap ConvertTopicInvalidationMapToObjectIdInvalidationMap( - const TopicInvalidationMap& topics_map); - } // namespace syncer #endif // COMPONENTS_INVALIDATION_PUBLIC_TOPIC_INVALIDATION_MAP_H_
diff --git a/components/offline_pages/core/background/change_requests_state_task.h b/components/offline_pages/core/background/change_requests_state_task.h index 5ce3c74..4251f6d 100644 --- a/components/offline_pages/core/background/change_requests_state_task.h +++ b/components/offline_pages/core/background/change_requests_state_task.h
@@ -26,10 +26,9 @@ RequestQueueStore::UpdateCallback callback); ~ChangeRequestsStateTask() override; + private: // TaskQueue::Task implementation. void Run() override; - - private: // Step 1. Reading the requests. void ReadRequests(); // Step 2. Updates available requests.
diff --git a/components/offline_pages/core/background/change_requests_state_task_unittest.cc b/components/offline_pages/core/background/change_requests_state_task_unittest.cc index 85f4e96e..f5b977c2 100644 --- a/components/offline_pages/core/background/change_requests_state_task_unittest.cc +++ b/components/offline_pages/core/background/change_requests_state_task_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/request_queue_store.h" @@ -85,7 +86,7 @@ &store_, request_ids, SavePageRequest::RequestState::PAUSED, base::BindOnce(&ChangeRequestsStateTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -104,7 +105,7 @@ &store_, request_ids, SavePageRequest::RequestState::PAUSED, base::BindOnce(&ChangeRequestsStateTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -125,7 +126,7 @@ &store_, request_ids, SavePageRequest::RequestState::PAUSED, base::BindOnce(&ChangeRequestsStateTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); ASSERT_EQ(2UL, last_result()->item_statuses.size()); @@ -163,7 +164,7 @@ &store_, request_ids, SavePageRequest::RequestState::PAUSED, base::BindOnce(&ChangeRequestsStateTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(0UL, last_result()->item_statuses.size()); @@ -179,7 +180,7 @@ &store_, request_ids, SavePageRequest::RequestState::PAUSED, base::BindOnce(&ChangeRequestsStateTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); ASSERT_EQ(2UL, last_result()->item_statuses.size());
diff --git a/components/offline_pages/core/background/cleanup_task.h b/components/offline_pages/core/background/cleanup_task.h index 3a900112..9aa6891 100644 --- a/components/offline_pages/core/background/cleanup_task.h +++ b/components/offline_pages/core/background/cleanup_task.h
@@ -30,10 +30,9 @@ RequestCoordinatorEventLogger* logger); ~CleanupTask() override; + private: // TaskQueue::Task implementation, starts the async chain void Run() override; - - private: // Step 1. get results from the store void GetRequests();
diff --git a/components/offline_pages/core/background/cleanup_task_unittest.cc b/components/offline_pages/core/background/cleanup_task_unittest.cc index 2a6260ed..5857a3b2 100644 --- a/components/offline_pages/core/background/cleanup_task_unittest.cc +++ b/components/offline_pages/core/background/cleanup_task_unittest.cc
@@ -8,6 +8,7 @@ #include <set> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/offliner_policy.h" @@ -177,7 +178,7 @@ QueueRequests(request1, request2); // Initiate cleanup. - task()->Run(); + task()->Execute(base::DoNothing()); PumpLoop(); // See what is left in the queue, should be just the other request. @@ -199,7 +200,7 @@ QueueRequests(request1, request2); // Initiate cleanup. - task()->Run(); + task()->Execute(base::DoNothing()); PumpLoop(); // See what is left in the queue, should be just the other request. @@ -221,7 +222,7 @@ QueueRequests(request1, request2); // Initiate cleanup. - task()->Run(); + task()->Execute(base::DoNothing()); PumpLoop(); // See what is left in the queue, should be just the other request. @@ -246,7 +247,7 @@ QueueRequests(request1, request2); // Initiate cleanup. - task()->Run(); + task()->Execute(base::DoNothing()); PumpLoop(); // See what is left in the queue, request1 should be left in the queue even
diff --git a/components/offline_pages/core/background/get_requests_task.h b/components/offline_pages/core/background/get_requests_task.h index e5b079e..edf6800 100644 --- a/components/offline_pages/core/background/get_requests_task.h +++ b/components/offline_pages/core/background/get_requests_task.h
@@ -20,10 +20,9 @@ RequestQueueStore::GetRequestsCallback callback); ~GetRequestsTask() override; + private: // Task implementation: void Run() override; - - private: // Step 1: Read the requests from he store. void ReadRequest(); // Step 2: Calls the callback with result, completes the task.
diff --git a/components/offline_pages/core/background/get_requests_task_unittest.cc b/components/offline_pages/core/background/get_requests_task_unittest.cc index 13b8e17d..6355f9307 100644 --- a/components/offline_pages/core/background/get_requests_task_unittest.cc +++ b/components/offline_pages/core/background/get_requests_task_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/request_queue_store.h" @@ -87,7 +88,7 @@ GetRequestsTask task(&store_, base::BindOnce(&GetRequestsTaskTest::GetRequestsCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); EXPECT_TRUE(callback_called()); EXPECT_TRUE(last_call_successful()); @@ -101,7 +102,7 @@ GetRequestsTask task(&store_, base::BindOnce(&GetRequestsTaskTest::GetRequestsCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); EXPECT_TRUE(callback_called()); EXPECT_TRUE(last_call_successful());
diff --git a/components/offline_pages/core/background/initialize_store_task.h b/components/offline_pages/core/background/initialize_store_task.h index 772dc63..9b155a3 100644 --- a/components/offline_pages/core/background/initialize_store_task.h +++ b/components/offline_pages/core/background/initialize_store_task.h
@@ -28,10 +28,9 @@ RequestQueueStore::InitializeCallback callback); ~InitializeStoreTask() override; + private: // TaskQueue::Task implementation. void Run() override; - - private: // Step 1. Initialize store. void InitializeStore(); // Step 2a. Completes initialization if successful or tries to reset if there
diff --git a/components/offline_pages/core/background/initialize_store_task_unittest.cc b/components/offline_pages/core/background/initialize_store_task_unittest.cc index 289637d7..a62a228 100644 --- a/components/offline_pages/core/background/initialize_store_task_unittest.cc +++ b/components/offline_pages/core/background/initialize_store_task_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/request_queue_store.h" @@ -41,7 +42,7 @@ InitializeStoreTask task( &store_, base::BindOnce(&InitializeStoreTaskTest::InitializeCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); EXPECT_TRUE(callback_called()); EXPECT_TRUE(last_call_successful()); @@ -54,7 +55,7 @@ InitializeStoreTask task( &store_, base::BindOnce(&InitializeStoreTaskTest::InitializeCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); @@ -71,7 +72,7 @@ InitializeStoreTask task( &store_, base::BindOnce(&InitializeStoreTaskTest::InitializeCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); EXPECT_TRUE(callback_called()); EXPECT_FALSE(last_call_successful());
diff --git a/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc index 63b23b4..b0a2e5c 100644 --- a/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/change_requests_state_task.h" @@ -84,7 +85,7 @@ &store_, kRequestId1, base::BindOnce(&MarkAttemptAbortedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -103,7 +104,7 @@ &store_, kRequestId1, base::BindOnce(&MarkAttemptAbortedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - start_request_task.Run(); + start_request_task.Execute(base::DoNothing()); PumpLoop(); ClearResults(); @@ -112,7 +113,7 @@ base::BindOnce(&MarkAttemptAbortedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -132,7 +133,7 @@ &store_, kRequestId2, base::BindOnce(&MarkAttemptAbortedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -151,7 +152,7 @@ &store_, kRequestId1, base::BindOnce(&MarkAttemptAbortedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - start_request_task.Run(); + start_request_task.Execute(base::DoNothing()); PumpLoop(); ClearResults(); @@ -162,7 +163,7 @@ &store_, requests, SavePageRequest::RequestState::PAUSED, base::BindOnce(&MarkAttemptAbortedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - pauseTask.Run(); + pauseTask.Execute(base::DoNothing()); PumpLoop(); // Abort the task, the state should not change from PAUSED. @@ -171,7 +172,7 @@ base::BindOnce(&MarkAttemptAbortedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - abortTask.Run(); + abortTask.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size());
diff --git a/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc index 2bfe026..a66e68d 100644 --- a/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/bind.h" +#include "base/bind_helpers.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/request_queue_task_test_base.h" #include "components/offline_pages/core/background/test_request_queue_store.h" @@ -71,7 +72,7 @@ base::BindOnce(&MarkAttemptCompletedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -93,7 +94,7 @@ &store_, kRequestId2, FailState::CANNOT_DOWNLOAD, base::BindOnce(&MarkAttemptCompletedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size());
diff --git a/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc index ee1c8d8..eac1ad1e 100644 --- a/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/request_queue_store.h" @@ -68,7 +69,7 @@ &store_, kRequestId1, base::BindOnce(&MarkAttemptStartedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -89,7 +90,7 @@ // Current time for verification. base::Time before_time = OfflineTimeNow(); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -114,7 +115,7 @@ &store_, kRequestId2, base::BindOnce(&MarkAttemptStartedTaskTest::ChangeRequestsStateCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size());
diff --git a/components/offline_pages/core/background/pick_request_task.h b/components/offline_pages/core/background/pick_request_task.h index 7332891..e44e205 100644 --- a/components/offline_pages/core/background/pick_request_task.h +++ b/components/offline_pages/core/background/pick_request_task.h
@@ -57,10 +57,10 @@ ~PickRequestTask() override; + private: // TaskQueue::Task implementation, starts the async chain void Run() override; - private: // Step 1. get the requests void GetRequests();
diff --git a/components/offline_pages/core/background/pick_request_task_unittest.cc b/components/offline_pages/core/background/pick_request_task_unittest.cc index d923e28..831f091 100644 --- a/components/offline_pages/core/background/pick_request_task_unittest.cc +++ b/components/offline_pages/core/background/pick_request_task_unittest.cc
@@ -122,9 +122,14 @@ PickRequestTask* task() { return task_.get(); } - void TaskCompletionCallback(Task* completed_task); + base::OnceClosure TaskCompletionCallback() { + return base::BindOnce(&PickRequestTaskTest::OnTaskComplete, + base::Unretained(this)); + } protected: + void OnTaskComplete() { task_complete_called_ = true; } + std::unique_ptr<RequestNotifierStub> notifier_; std::unique_ptr<SavePageRequest> last_picked_; std::unique_ptr<OfflinerPolicy> policy_; @@ -155,10 +160,6 @@ PumpLoop(); } -void PickRequestTaskTest::TaskCompletionCallback(Task* completed_task) { - task_complete_called_ = true; -} - void PickRequestTaskTest::RequestPicked( const SavePageRequest& request, std::unique_ptr<std::vector<SavePageRequest>> available_requests, @@ -204,13 +205,10 @@ base::BindOnce(&PickRequestTaskTest::RequestCountCallback, base::Unretained(this)), conditions, disabled_requests_, &prioritized_requests_)); - task_->SetTaskCompletionCallbackForTesting( - base::BindRepeating(&PickRequestTaskTest::TaskCompletionCallback, - base::Unretained(this))); } TEST_F(PickRequestTaskTest, PickFromEmptyQueue) { - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); // Pump the loop again to give the async queue the opportunity to return @@ -240,7 +238,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId2, last_picked_->request_id()); @@ -261,7 +259,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId1, last_picked_->request_id()); @@ -287,7 +285,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId1, last_picked_->request_id()); @@ -311,7 +309,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId2, last_picked_->request_id()); @@ -335,7 +333,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId1, last_picked_->request_id()); @@ -360,7 +358,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId2, last_picked_->request_id()); @@ -380,7 +378,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId1, last_picked_->request_id()); @@ -406,7 +404,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId2, last_picked_->request_id()); @@ -432,7 +430,7 @@ QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); EXPECT_EQ(kRequestId2, last_picked_->request_id()); @@ -461,7 +459,7 @@ // Add test requests on the Queue. QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); // Pump the loop again to give the async queue the opportunity to return @@ -493,7 +491,7 @@ // Add test requests on the Queue. QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); // Pump the loop again to give the async queue the opportunity to return @@ -531,7 +529,7 @@ // Add test requests on the Queue. QueueRequests(request1, request2); - task()->Run(); + task()->Execute(TaskCompletionCallback()); PumpLoop(); // Pump the loop again to give the async queue the opportunity to return
diff --git a/components/offline_pages/core/background/reconcile_task.h b/components/offline_pages/core/background/reconcile_task.h index 100d1c05..0a2b5203 100644 --- a/components/offline_pages/core/background/reconcile_task.h +++ b/components/offline_pages/core/background/reconcile_task.h
@@ -24,11 +24,11 @@ RequestQueueStore::UpdateCallback callback); ~ReconcileTask() override; + private: // TaskQueue::Task implementation: // Starts the async chain. void Run() override; - private: // Step 1. Get results from the store. void GetRequests();
diff --git a/components/offline_pages/core/background/reconcile_task_unittest.cc b/components/offline_pages/core/background/reconcile_task_unittest.cc index 6a94916..47308aa 100644 --- a/components/offline_pages/core/background/reconcile_task_unittest.cc +++ b/components/offline_pages/core/background/reconcile_task_unittest.cc
@@ -8,6 +8,7 @@ #include <set> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/request_coordinator.h" @@ -126,7 +127,7 @@ QueueRequests(request1, request2); // Initiate cleanup. - task()->Run(); + task()->Execute(base::DoNothing()); PumpLoop(); // See what is left in the queue, should be just the other request. @@ -161,7 +162,7 @@ QueueRequests(request1, request2); // Initiate cleanup. - task()->Run(); + task()->Execute(base::DoNothing()); PumpLoop(); // See what is left in the queue, should be just the other request.
diff --git a/components/offline_pages/core/background/remove_requests_task.h b/components/offline_pages/core/background/remove_requests_task.h index 85229ea48..e9ced3e 100644 --- a/components/offline_pages/core/background/remove_requests_task.h +++ b/components/offline_pages/core/background/remove_requests_task.h
@@ -24,10 +24,9 @@ RequestQueueStore::UpdateCallback callback); ~RemoveRequestsTask() override; + private: // TaskQueue::Task implementation. void Run() override; - - private: // Step 1. Removes requests from the store. void RemoveRequests(); // Step for early termination, that builds failure result.
diff --git a/components/offline_pages/core/background/remove_requests_task_unittest.cc b/components/offline_pages/core/background/remove_requests_task_unittest.cc index bf2c6c8..de815d1 100644 --- a/components/offline_pages/core/background/remove_requests_task_unittest.cc +++ b/components/offline_pages/core/background/remove_requests_task_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/request_queue_store.h" @@ -83,7 +84,7 @@ &store_, request_ids, base::BindOnce(&RemoveRequestsTaskTest::RemoveRequestsCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -102,7 +103,7 @@ &store_, request_ids, base::BindOnce(&RemoveRequestsTaskTest::RemoveRequestsCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(1UL, last_result()->item_statuses.size()); @@ -122,7 +123,7 @@ &store_, request_ids, base::BindOnce(&RemoveRequestsTaskTest::RemoveRequestsCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(2UL, last_result()->item_statuses.size()); @@ -145,7 +146,7 @@ &store_, request_ids, base::BindOnce(&RemoveRequestsTaskTest::RemoveRequestsCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(0UL, last_result()->item_statuses.size()); @@ -161,7 +162,7 @@ &store_, request_ids, base::BindOnce(&RemoveRequestsTaskTest::RemoveRequestsCallback, base::Unretained(this))); - task.Run(); + task.Execute(base::DoNothing()); PumpLoop(); ASSERT_TRUE(last_result()); EXPECT_EQ(2UL, last_result()->item_statuses.size());
diff --git a/components/offline_pages/core/background/update_request_task.h b/components/offline_pages/core/background/update_request_task.h index 7871ec1..d1e44f14 100644 --- a/components/offline_pages/core/background/update_request_task.h +++ b/components/offline_pages/core/background/update_request_task.h
@@ -25,10 +25,9 @@ RequestQueueStore::UpdateCallback callback); ~UpdateRequestTask() override; + protected: // TaskQueue::Task implementation. void Run() override; - - protected: // Step 1. Reading the requests. void ReadRequest(); // Step 2. Work is done in the implementation step.
diff --git a/components/offline_pages/core/model/add_page_task.h b/components/offline_pages/core/model/add_page_task.h index 70bb11a..3ce6adec 100644 --- a/components/offline_pages/core/model/add_page_task.h +++ b/components/offline_pages/core/model/add_page_task.h
@@ -30,10 +30,10 @@ AddPageTaskCallback callback); ~AddPageTask() override; + private: // Task implementation. void Run() override; - private: void OnAddPageDone(ItemActionStatus status); void InformAddPageDone(AddPageResult result);
diff --git a/components/offline_pages/core/model/cleanup_visuals_task.h b/components/offline_pages/core/model/cleanup_visuals_task.h index 56ae19b..83ddd26d 100644 --- a/components/offline_pages/core/model/cleanup_visuals_task.h +++ b/components/offline_pages/core/model/cleanup_visuals_task.h
@@ -30,10 +30,10 @@ CleanupVisualsCallback complete_callback); ~CleanupVisualsTask() override; + private: // Task implementation: void Run() override; - private: void Complete(Result result); OfflinePageMetadataStore* store_; base::Time now_;
diff --git a/components/offline_pages/core/model/clear_storage_task.h b/components/offline_pages/core/model/clear_storage_task.h index f67f6f9..927c038 100644 --- a/components/offline_pages/core/model/clear_storage_task.h +++ b/components/offline_pages/core/model/clear_storage_task.h
@@ -50,10 +50,10 @@ ClearStorageCallback callback); ~ClearStorageTask() override; + private: // Task implementation. void Run() override; - private: void OnGetStorageStatsDone(const ArchiveManager::StorageStats& stats); void OnClearPagesDone(std::pair<size_t, DeletePageResult> result); void InformClearStorageDone(size_t pages_cleared, ClearStorageResult result);
diff --git a/components/offline_pages/core/model/delete_page_task.h b/components/offline_pages/core/model/delete_page_task.h index 0ff39b4..5bb209d9 100644 --- a/components/offline_pages/core/model/delete_page_task.h +++ b/components/offline_pages/core/model/delete_page_task.h
@@ -60,9 +60,6 @@ ~DeletePageTask() override; - // Task implementation. - void Run() override; - // Deletes a single page from the database. This function reads // from the database and should be called from within an // |SqlStoreBase::Execute()| call. @@ -78,6 +75,9 @@ using DeleteFunction = base::OnceCallback<DeletePageTaskResult(sql::Database*)>; + // Task implementation. + void Run() override; + // Making the constructor private, in order to use static methods to create // tasks. DeletePageTask(OfflinePageMetadataStore* store,
diff --git a/components/offline_pages/core/model/get_pages_task.h b/components/offline_pages/core/model/get_pages_task.h index 4a49bb00..efb64633 100644 --- a/components/offline_pages/core/model/get_pages_task.h +++ b/components/offline_pages/core/model/get_pages_task.h
@@ -37,9 +37,6 @@ ~GetPagesTask() override; - // Task implementation: - void Run() override; - // Reads and returns all pages matching |criteria|. This function reads // from the database and should be called from within an // |SqlStoreBase::Execute()| call. @@ -48,6 +45,9 @@ sql::Database* db); private: + // Task implementation: + void Run() override; + void CompleteWithResult(ReadResult result); OfflinePageMetadataStore* store_;
diff --git a/components/offline_pages/core/model/get_visuals_task.h b/components/offline_pages/core/model/get_visuals_task.h index 2d8a984..6c71169 100644 --- a/components/offline_pages/core/model/get_visuals_task.h +++ b/components/offline_pages/core/model/get_visuals_task.h
@@ -27,12 +27,12 @@ CompleteCallback complete_callback); ~GetVisualsTask() override; - // Task implementation: - void Run() override; - private: typedef std::unique_ptr<OfflinePageVisuals> Result; + // Task implementation: + void Run() override; + void Complete(Result result); OfflinePageMetadataStore* store_;
diff --git a/components/offline_pages/core/model/mark_page_accessed_task.h b/components/offline_pages/core/model/mark_page_accessed_task.h index 0efaf782..c93e7f2 100644 --- a/components/offline_pages/core/model/mark_page_accessed_task.h +++ b/components/offline_pages/core/model/mark_page_accessed_task.h
@@ -27,10 +27,10 @@ const base::Time& access_time); ~MarkPageAccessedTask() override; + private: // Task implementation. void Run() override; - private: void OnMarkPageAccessedDone(bool result); // The metadata store used to update the page. Not owned.
diff --git a/components/offline_pages/core/model/persistent_page_consistency_check_task.h b/components/offline_pages/core/model/persistent_page_consistency_check_task.h index 051fca15..9997ec0 100644 --- a/components/offline_pages/core/model/persistent_page_consistency_check_task.h +++ b/components/offline_pages/core/model/persistent_page_consistency_check_task.h
@@ -46,10 +46,10 @@ PersistentPageConsistencyCheckCallback callback); ~PersistentPageConsistencyCheckTask() override; + private: // Task implementation: void Run() override; - private: void OnPersistentPageConsistencyCheckDone(CheckResult result); // The store containing the offline pages. Not owned.
diff --git a/components/offline_pages/core/model/startup_maintenance_task.h b/components/offline_pages/core/model/startup_maintenance_task.h index bab8ca6..dc197756 100644 --- a/components/offline_pages/core/model/startup_maintenance_task.h +++ b/components/offline_pages/core/model/startup_maintenance_task.h
@@ -23,10 +23,10 @@ ArchiveManager* archive_manager); ~StartupMaintenanceTask() override; + private: // Task implementation: void Run() override; - private: void OnStartupMaintenanceDone(bool result); // The store containing the offline pages. Not owned.
diff --git a/components/offline_pages/core/model/store_visuals_task.h b/components/offline_pages/core/model/store_visuals_task.h index 4909ec9..8674c3d 100644 --- a/components/offline_pages/core/model/store_visuals_task.h +++ b/components/offline_pages/core/model/store_visuals_task.h
@@ -40,10 +40,10 @@ std::string favicon, CompleteCallback callback); + private: // Task implementation: void Run() override; - private: StoreVisualsTask(OfflinePageMetadataStore* store, int64_t offline_id, std::string thumbnail,
diff --git a/components/offline_pages/core/model/update_publish_id_task.h b/components/offline_pages/core/model/update_publish_id_task.h index 338735bf..75b1d09 100644 --- a/components/offline_pages/core/model/update_publish_id_task.h +++ b/components/offline_pages/core/model/update_publish_id_task.h
@@ -31,10 +31,10 @@ base::OnceCallback<void(bool)> callback); ~UpdatePublishIdTask() override; + private: // Task implementation. void Run() override; - private: void OnUpdatePublishIdDone(bool result); // The metadata store used to update the page. Not owned.
diff --git a/components/offline_pages/core/model/visuals_availability_task.h b/components/offline_pages/core/model/visuals_availability_task.h index 5fa290c..a9a8089 100644 --- a/components/offline_pages/core/model/visuals_availability_task.h +++ b/components/offline_pages/core/model/visuals_availability_task.h
@@ -25,10 +25,10 @@ VisualsAvailableCallback exists_callback); ~VisualsAvailabilityTask() override; + private: // Task implementation: void Run() override; - private: void OnVisualsAvailable(VisualsAvailability availability); OfflinePageMetadataStore* store_;
diff --git a/components/offline_pages/core/offline_page_metadata_store_test_util.cc b/components/offline_pages/core/offline_page_metadata_store_test_util.cc index b31d621..aedaaf5 100644 --- a/components/offline_pages/core/offline_page_metadata_store_test_util.cc +++ b/components/offline_pages/core/offline_page_metadata_store_test_util.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/callback_forward.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" @@ -74,7 +75,7 @@ result = cb_result; run_loop.Quit(); })); - task->Run(); + task->Execute(base::DoNothing()); run_loop.Run(); EXPECT_EQ(AddPageResult::SUCCESS, result); } @@ -107,7 +108,7 @@ page = new OfflinePageItem(cb_pages[0]); run_loop.Quit(); }))); - task->Run(); + task->Execute(base::DoNothing()); run_loop.Run(); return base::WrapUnique<OfflinePageItem>(page); }
diff --git a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.h b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.h index 0764f6b..a5f9682 100644 --- a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.h +++ b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task.h
@@ -38,10 +38,8 @@ const std::string& name_space, const std::vector<PrefetchURL>& prefetch_urls); ~AddUniqueUrlsTask() override; - - void Run() override; - private: + void Run() override; void OnUrlsAdded(Result result); // Dispatcher to call back to with results. Not owned.
diff --git a/components/offline_pages/core/prefetch/tasks/download_archives_task.h b/components/offline_pages/core/prefetch/tasks/download_archives_task.h index 5e41e87..6cab857 100644 --- a/components/offline_pages/core/prefetch/tasks/download_archives_task.h +++ b/components/offline_pages/core/prefetch/tasks/download_archives_task.h
@@ -47,9 +47,8 @@ PrefService* prefs); ~DownloadArchivesTask() override; - void Run() override; - private: + void Run() override; void SendItemsToPrefetchDownloader( std::unique_ptr<ItemsToDownload> items_to_download);
diff --git a/components/offline_pages/core/prefetch/tasks/download_cleanup_task.h b/components/offline_pages/core/prefetch/tasks/download_cleanup_task.h index 65276a1..599512892 100644 --- a/components/offline_pages/core/prefetch/tasks/download_cleanup_task.h +++ b/components/offline_pages/core/prefetch/tasks/download_cleanup_task.h
@@ -35,9 +35,8 @@ success_downloads); ~DownloadCleanupTask() override; - void Run() override; - private: + void Run() override; void OnFinished(bool success); PrefetchDispatcher* prefetch_dispatcher_; // Outlives this class.
diff --git a/components/offline_pages/core/prefetch/tasks/download_completed_task.h b/components/offline_pages/core/prefetch/tasks/download_completed_task.h index 2b0505b7..0b770e1 100644 --- a/components/offline_pages/core/prefetch/tasks/download_completed_task.h +++ b/components/offline_pages/core/prefetch/tasks/download_completed_task.h
@@ -22,8 +22,6 @@ const PrefetchDownloadResult& download_result); ~DownloadCompletedTask() override; - void Run() override; - struct UpdateInfo { // True if the row was updated. bool success = false; @@ -32,6 +30,7 @@ }; private: + void Run() override; void OnPrefetchItemUpdated(bool successful_download, UpdateInfo update_info); PrefetchDispatcher* prefetch_dispatcher_; // Outlives this class.
diff --git a/components/offline_pages/core/prefetch/tasks/finalize_dismissed_url_suggestion_task.h b/components/offline_pages/core/prefetch/tasks/finalize_dismissed_url_suggestion_task.h index 789c3f0e..2ccdc98 100644 --- a/components/offline_pages/core/prefetch/tasks/finalize_dismissed_url_suggestion_task.h +++ b/components/offline_pages/core/prefetch/tasks/finalize_dismissed_url_suggestion_task.h
@@ -34,9 +34,8 @@ const ClientId& client_id); ~FinalizeDismissedUrlSuggestionTask() override; - void Run() override; - private: + void Run() override; void OnComplete(bool removed); PrefetchStore* prefetch_store_;
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_reconcile_task.h b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_reconcile_task.h index 6189937..e5dd7134 100644 --- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_reconcile_task.h +++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_reconcile_task.h
@@ -25,10 +25,9 @@ PrefetchNetworkRequestFactory* request_factory); ~GeneratePageBundleReconcileTask() override; + private: // Task implementation. void Run() override; - - private: void FinishedUpdate(bool success); PrefetchStore* prefetch_store_;
diff --git a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h index 766af07e..0669805 100644 --- a/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h +++ b/components/offline_pages/core/prefetch/tasks/generate_page_bundle_task.h
@@ -31,10 +31,9 @@ PrefetchRequestFinishedCallback callback); ~GeneratePageBundleTask() override; + private: // Task implementation. void Run() override; - - private: void StartGeneratePageBundle(std::unique_ptr<UrlAndIds> url_and_ids); PrefetchDispatcher* prefetch_dispatcher_;
diff --git a/components/offline_pages/core/prefetch/tasks/get_operation_task.h b/components/offline_pages/core/prefetch/tasks/get_operation_task.h index 9ca54a4..0bbe745 100644 --- a/components/offline_pages/core/prefetch/tasks/get_operation_task.h +++ b/components/offline_pages/core/prefetch/tasks/get_operation_task.h
@@ -36,10 +36,9 @@ GetOperationFinishedCallback callback); ~GetOperationTask() override; + private: // Task implementation. void Run() override; - - private: void StartGetOperationRequests(OperationResultList list); PrefetchStore* prefetch_store_;
diff --git a/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h b/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h index 8febe50..09fbdbb 100644 --- a/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h +++ b/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h
@@ -34,10 +34,9 @@ ResultCallback callback); ~GetVisualsInfoTask() override; + private: // Task implementation. void Run() override; - - private: void CompleteTaskAndForwardResult(Result result); PrefetchStore* prefetch_store_; int64_t offline_id_;
diff --git a/components/offline_pages/core/prefetch/tasks/import_archives_task.h b/components/offline_pages/core/prefetch/tasks/import_archives_task.h index ddbe7b2a4..88f124e 100644 --- a/components/offline_pages/core/prefetch/tasks/import_archives_task.h +++ b/components/offline_pages/core/prefetch/tasks/import_archives_task.h
@@ -23,9 +23,8 @@ PrefetchImporter* prefetch_importer); ~ImportArchivesTask() override; - void Run() override; - private: + void Run() override; void OnArchivesRetrieved( std::unique_ptr<std::vector<PrefetchArchiveInfo>> archive);
diff --git a/components/offline_pages/core/prefetch/tasks/import_cleanup_task.h b/components/offline_pages/core/prefetch/tasks/import_cleanup_task.h index d41b874..4d60844a 100644 --- a/components/offline_pages/core/prefetch/tasks/import_cleanup_task.h +++ b/components/offline_pages/core/prefetch/tasks/import_cleanup_task.h
@@ -22,9 +22,8 @@ PrefetchImporter* prefetch_importer); ~ImportCleanupTask() override; - void Run() override; - private: + void Run() override; void OnPrefetchItemUpdated(bool row_was_updated); PrefetchStore* prefetch_store_; // Outlives this class.
diff --git a/components/offline_pages/core/prefetch/tasks/import_completed_task.h b/components/offline_pages/core/prefetch/tasks/import_completed_task.h index 27468f6..3b548e5 100644 --- a/components/offline_pages/core/prefetch/tasks/import_completed_task.h +++ b/components/offline_pages/core/prefetch/tasks/import_completed_task.h
@@ -25,9 +25,8 @@ bool success); ~ImportCompletedTask() override; - void Run() override; - private: + void Run() override; void OnStateUpdatedToFinished(bool success); PrefetchDispatcher* prefetch_dispatcher_; // Outlives this class.
diff --git a/components/offline_pages/core/prefetch/tasks/mark_operation_done_task.h b/components/offline_pages/core/prefetch/tasks/mark_operation_done_task.h index b37c3b6..8b6b830 100644 --- a/components/offline_pages/core/prefetch/tasks/mark_operation_done_task.h +++ b/components/offline_pages/core/prefetch/tasks/mark_operation_done_task.h
@@ -40,9 +40,6 @@ const std::string& operation_name); ~MarkOperationDoneTask() override; - // Task implementation. - void Run() override; - StoreResult store_result() const { return std::get<0>(result_); } // Number of rows changed, or -1 if there was a store error (or not yet @@ -50,6 +47,8 @@ int64_t change_count() const { return std::get<1>(result_); } private: + // Task implementation. + void Run() override; void MarkOperationDone(int updated_entry_count); void Done(TaskResult result);
diff --git a/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.h b/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.h index dc57d6b..5ce7536 100644 --- a/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.h +++ b/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.h
@@ -23,10 +23,9 @@ explicit MetricsFinalizationTask(PrefetchStore* prefetch_store); ~MetricsFinalizationTask() override; + private: // Task implementation. void Run() override; - - private: void MetricsFinalized(bool result); PrefetchStore* prefetch_store_;
diff --git a/components/offline_pages/core/prefetch/tasks/page_bundle_update_task.h b/components/offline_pages/core/prefetch/tasks/page_bundle_update_task.h index 2d096863..af1e26a4 100644 --- a/components/offline_pages/core/prefetch/tasks/page_bundle_update_task.h +++ b/components/offline_pages/core/prefetch/tasks/page_bundle_update_task.h
@@ -43,10 +43,9 @@ const std::vector<RenderPageInfo>& pages); ~PageBundleUpdateTask() override; + private: // Task implementation. void Run() override; - - private: void FinishedWork(PageBundleUpdateResult result); // Owned by PrefetchService which also transitively owns |this|, so raw
diff --git a/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task.h b/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task.h index 039718d..844a429d 100644 --- a/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task.h +++ b/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task.h
@@ -24,9 +24,8 @@ PrefetchNetworkRequestFactory* request_factory); ~SentGetOperationCleanupTask() override; - void Run() override; - private: + void Run() override; void OnFinished(bool success); PrefetchStore* prefetch_store_; // Outlives this class.
diff --git a/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h b/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h index e441e4fd..dfded34 100644 --- a/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h +++ b/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h
@@ -34,12 +34,11 @@ PrefetchStore* prefetch_store); ~StaleEntryFinalizerTask() override; - void Run() override; - // Will be set to true upon after an error-free run. Result final_status() const { return final_status_; } private: + void Run() override; void OnFinished(Result result); // Not owned.
diff --git a/components/offline_pages/task/closure_task.h b/components/offline_pages/task/closure_task.h index ae5ede5..013f2141 100644 --- a/components/offline_pages/task/closure_task.h +++ b/components/offline_pages/task/closure_task.h
@@ -16,9 +16,10 @@ public: ClosureTask(base::OnceClosure closure); ~ClosureTask() override; - void Run() override; private: + void Run() override; + base::OnceClosure closure_; };
diff --git a/components/offline_pages/task/task.cc b/components/offline_pages/task/task.cc index c662a9b..4198454 100644 --- a/components/offline_pages/task/task.cc +++ b/components/offline_pages/task/task.cc
@@ -6,28 +6,30 @@ #include <utility> +#include "base/logging.h" + namespace offline_pages { -Task::Task() {} - -Task::~Task() {} - -void Task::SetTaskCompletionCallbackForTesting( - TaskCompletionCallback task_completion_callback) { - SetTaskCompletionCallback(std::move(task_completion_callback)); +Task::Task() = default; +Task::~Task() { + // This may happen when tearing-down the |TaskQueue|. + DLOG_IF(WARNING, started_ && !completed_) + << "Task being destroyed before completion"; } -void Task::SetTaskCompletionCallback( - TaskCompletionCallback task_completion_callback) { - // Attempts to enforce that SetTaskCompletionCallback is at most called once. - DCHECK(task_completion_callback_.is_null()); - DCHECK(!task_completion_callback.is_null()); - task_completion_callback_ = std::move(task_completion_callback); +void Task::Execute(base::OnceClosure complete_callback) { + DCHECK(!started_); + started_ = true; + task_completion_callback_ = std::move(complete_callback); + Run(); } void Task::TaskComplete() { + DCHECK(started_); + DCHECK(!completed_); + completed_ = true; if (!task_completion_callback_.is_null()) - std::move(task_completion_callback_).Run(this); + std::move(task_completion_callback_).Run(); } } // namespace offline_pages
diff --git a/components/offline_pages/task/task.h b/components/offline_pages/task/task.h index a071ffa..2f1d8cf 100644 --- a/components/offline_pages/task/task.h +++ b/components/offline_pages/task/task.h
@@ -6,68 +6,32 @@ #define COMPONENTS_OFFLINE_PAGES_TASK_TASK_H_ #include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" namespace offline_pages { -// Task interface for consumers of the TaskQueue. Implements a mechanism for -// task completion. -// -// To create your own Task: -// * Derive your new task from offline_pages::Task. -// * Implement your task with as many async operations on the controlled -// resource as is required. (In general the smaller the task the better.) -// * Whenever the task is terminated, call |Task::TaskComplete|. This step is -// mandatory to ensure |TaskQueue| can pick another task. It should be called -// once, but in every situation when task is exited. -// * To schedule task for execution call |TaskQueue::AddTask|. -// -// If there is a chance that a task callback will come after the task is -// destroyed, it is up to the task to actually implement mechanism to deal with -// that, such as using a |base::WeakPtrFactory|. +// A task which may run asynchronous steps. Its primary purpose is to implement +// operations to be inserted into a |TaskQueue|, however, tasks can also be run +// outside of a |TaskQueue|. class Task { public: - // Signature of the method to be called by a task, when its work is done. - typedef base::OnceCallback<void(Task*)> TaskCompletionCallback; - Task(); virtual ~Task(); + Task(const Task&) = delete; + Task& operator=(const Task&) = delete; - // Entry point to the task. This is used by the queue to start the task, and - // first step of the task should be implemented by overloading this method. - // The task should define an additional method for every asynchronous step, - // with each step setting up the next step as a callback. - virtual void Run() = 0; - - // Sets the callback normally used by |TaskQueue| for testing. See - // |SetTaskCompletionCallback| for details. - void SetTaskCompletionCallbackForTesting( - TaskCompletionCallback task_completion_callback); + void Execute(base::OnceClosure complete_callback); protected: - // Tasks must call |TaskComplete| as their last step. This will cause - // |TaskQueue| to schedule the task's destruction and start another task if - // one is available. + // Entry point to the task. Called by |Execute()| to perform the task. + // Must call |TaskComplete()| as the final step. + virtual void Run() = 0; + + // Tasks must call |TaskComplete()| as their last step. void TaskComplete(); - private: - friend class TaskQueue; - - // Allows |TaskQueue| to set the |task_completion_callback| that will be used - // to inform it when the task is done. If the task is run outside of the - // |TaskQueue| and completion callback is not set, it will also work. - // - // Note: The callback implementation is responsible for scheduling work with - // the appropriate task runner and not to cause side effects to the |Task| - // calling into |TaskComplete|. - void SetTaskCompletionCallback( - TaskCompletionCallback task_completion_callback); - - // Completion callback for this task set by |SetTaskCompletionCallback|. - TaskCompletionCallback task_completion_callback_; - - DISALLOW_COPY_AND_ASSIGN(Task); + base::OnceClosure task_completion_callback_; + bool completed_ = false; + bool started_ = false; }; } // namespace offline_pages
diff --git a/components/offline_pages/task/task_queue.cc b/components/offline_pages/task/task_queue.cc index 13e5790..12173f8 100644 --- a/components/offline_pages/task/task_queue.cc +++ b/components/offline_pages/task/task_queue.cc
@@ -23,8 +23,6 @@ void TaskQueue::AddTask(std::unique_ptr<Task> task) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - task->SetTaskCompletionCallback(base::BindOnce( - &TaskCompletedCallback, task_runner_, weak_ptr_factory_.GetWeakPtr())); tasks_.push(std::move(task)); StartTaskIfAvailable(); } @@ -61,7 +59,9 @@ } void TaskQueue::RunCurrentTask() { - current_task_->Run(); + current_task_->Execute(base::BindOnce(&TaskCompletedCallback, task_runner_, + weak_ptr_factory_.GetWeakPtr(), + current_task_.get())); } // static
diff --git a/components/offline_pages/task/task_unittest.cc b/components/offline_pages/task/task_unittest.cc index 6bdb771..3bc87c1 100644 --- a/components/offline_pages/task/task_unittest.cc +++ b/components/offline_pages/task/task_unittest.cc
@@ -7,53 +7,78 @@ #include <memory> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/task/test_task.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { - +namespace { using TaskState = TestTask::TaskState; +class ClosureStub { + public: + base::OnceClosure Bind() { + return base::BindOnce(&ClosureStub::Done, base::Unretained(this)); + } + bool called() const { return called_; } + + private: + void Done() { called_ = true; } + bool called_ = false; +}; + +class NestingTask : public Task { + public: + explicit NestingTask(NestingTask* child) : child_(child) {} + void Run() override { + if (child_) { + child_->Execute( + base::BindOnce(&NestingTask::NestedTaskDone, base::Unretained(this))); + } else { + completed_ = true; + TaskComplete(); + } + } + + bool completed() const { return completed_; } + + private: + void NestedTaskDone() { + completed_ = true; + TaskComplete(); + } + + NestingTask* child_ = nullptr; + bool completed_ = false; +}; + class OfflineTaskTest : public testing::Test { public: OfflineTaskTest(); - void TaskCompleted(Task* task); void PumpLoop(); - - Task* completed_task() const { return completed_task_; } - private: - Task* completed_task_; scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; }; OfflineTaskTest::OfflineTaskTest() - : completed_task_(nullptr), - task_runner_(new base::TestSimpleTaskRunner), + : task_runner_(new base::TestSimpleTaskRunner), task_runner_handle_(task_runner_) {} void OfflineTaskTest::PumpLoop() { task_runner_->RunUntilIdle(); } -void OfflineTaskTest::TaskCompleted(Task* task) { - auto set_task_callback = [](Task** t_ptr, Task* t) { *t_ptr = t; }; - task_runner_->PostTask( - FROM_HERE, base::BindOnce(set_task_callback, &completed_task_, task)); -} - TEST_F(OfflineTaskTest, RunTaskStepByStep) { ConsumedResource resource; TestTask task(&resource); - task.SetTaskCompletionCallbackForTesting( - base::BindOnce(&OfflineTaskTest::TaskCompleted, base::Unretained(this))); EXPECT_EQ(TaskState::NOT_STARTED, task.state()); - task.Run(); + ClosureStub complete; + task.Execute(complete.Bind()); EXPECT_EQ(TaskState::STEP_1, task.state()); EXPECT_TRUE(resource.HasNextStep()); resource.CompleteStep(); @@ -62,14 +87,14 @@ resource.CompleteStep(); EXPECT_EQ(TaskState::COMPLETED, task.state()); PumpLoop(); - EXPECT_EQ(completed_task(), &task); + EXPECT_TRUE(complete.called()); } TEST_F(OfflineTaskTest, LeaveEarly) { ConsumedResource resource; TestTask task(&resource, true /* leave early */); EXPECT_EQ(TaskState::NOT_STARTED, task.state()); - task.Run(); + task.Execute(base::DoNothing()); EXPECT_EQ(TaskState::STEP_1, task.state()); EXPECT_TRUE(resource.HasNextStep()); resource.CompleteStep(); @@ -79,4 +104,14 @@ EXPECT_FALSE(resource.HasNextStep()); } +TEST_F(OfflineTaskTest, RunNestedTask) { + NestingTask child(nullptr); + NestingTask parent(&child); + + parent.Execute(base::DoNothing()); + EXPECT_TRUE(child.completed()); + EXPECT_TRUE(parent.completed()); +} + +} // namespace } // namespace offline_pages
diff --git a/components/offline_pages/task/test_task_runner.cc b/components/offline_pages/task/test_task_runner.cc index 5ebdc31..59a1251 100644 --- a/components/offline_pages/task/test_task_runner.cc +++ b/components/offline_pages/task/test_task_runner.cc
@@ -18,9 +18,8 @@ void TestTaskRunner::RunTask(Task* task) { DCHECK(task); base::RunLoop run_loop; - task->SetTaskCompletionCallbackForTesting(base::BindOnce( - [](base::RunLoop* run_loop, Task*) { run_loop->Quit(); }, &run_loop)); - task->Run(); + task->Execute(base::BindOnce( + [](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop)); run_loop.Run(); }
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index 1af2f68a..34e2ea45e 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -131,9 +131,10 @@ "OmniboxSuggestionTransparencyOptions", base::FEATURE_DISABLED_BY_DEFAULT}; // Feature to enable clipboard provider to suggest copied text. +// TODO(gangwu): Remove this feature flag after full launched in Android. const base::Feature kEnableClipboardProviderTextSuggestions{ "OmniboxEnableClipboardProviderTextSuggestions", -#if defined(OS_IOS) +#if defined(OS_IOS) || defined(OS_ANDROID) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/components/password_manager/core/browser/multi_store_password_save_manager.cc b/components/password_manager/core/browser/multi_store_password_save_manager.cc index a864d20..0c9d481 100644 --- a/components/password_manager/core/browser/multi_store_password_save_manager.cc +++ b/components/password_manager/core/browser/multi_store_password_save_manager.cc
@@ -51,7 +51,7 @@ MultiStorePasswordSaveManager::~MultiStorePasswordSaveManager() = default; FormSaver* MultiStorePasswordSaveManager::GetFormSaverForGeneration() { - return IsAccountStoreActive() && account_store_form_saver_ + return IsAccountStoreEnabled() && account_store_form_saver_ ? account_store_form_saver_.get() : form_saver_.get(); } @@ -69,21 +69,20 @@ switch (pending_credentials_.in_store) { case PasswordForm::Store::kAccountStore: - if (account_store_form_saver_ && IsAccountStoreActive()) + if (account_store_form_saver_ && IsAccountStoreEnabled()) { account_store_form_saver_->Save( pending_credentials_, AccountStoreMatches(matches), old_password); + } + // TODO(crbug.com/1012203): Record UMA for how many passwords get dropped + // here. In rare cases it could happen that the user *was* opted in when + // the save dialog was shown, but now isn't anymore. break; case PasswordForm::Store::kProfileStore: form_saver_->Save(pending_credentials_, ProfileStoreMatches(matches), old_password); break; case PasswordForm::Store::kNotSet: - if (account_store_form_saver_ && IsAccountStoreActive()) - account_store_form_saver_->Save( - pending_credentials_, AccountStoreMatches(matches), old_password); - else - form_saver_->Save(pending_credentials_, ProfileStoreMatches(matches), - old_password); + NOTREACHED(); break; } } @@ -95,7 +94,7 @@ // update operation is no-op. form_saver_->Update(pending_credentials_, ProfileStoreMatches(matches), old_password); - if (account_store_form_saver_ && IsAccountStoreActive()) { + if (account_store_form_saver_ && IsAccountStoreEnabled()) { account_store_form_saver_->Update( pending_credentials_, AccountStoreMatches(matches), old_password); } @@ -104,7 +103,7 @@ void MultiStorePasswordSaveManager::PermanentlyBlacklist( const PasswordStore::FormDigest& form_digest) { DCHECK(!client_->IsIncognito()); - if (account_store_form_saver_ && IsAccountStoreActive() && + if (account_store_form_saver_ && IsAccountStoreEnabled() && client_->GetPasswordFeatureManager()->GetDefaultPasswordStore() == PasswordForm::Store::kAccountStore) { account_store_form_saver_->PermanentlyBlacklist(form_digest); @@ -118,7 +117,7 @@ // Try to unblacklist in both stores anyway because if credentials don't // exist, the unblacklist operation is no-op. form_saver_->Unblacklist(form_digest); - if (account_store_form_saver_ && IsAccountStoreActive()) { + if (account_store_form_saver_ && IsAccountStoreEnabled()) { account_store_form_saver_->Unblacklist(form_digest); } } @@ -130,9 +129,8 @@ return result; } -bool MultiStorePasswordSaveManager::IsAccountStoreActive() { - return client_->GetPasswordSyncState() == - password_manager::ACCOUNT_PASSWORDS_ACTIVE_NORMAL_ENCRYPTION; +bool MultiStorePasswordSaveManager::IsAccountStoreEnabled() { + return client_->GetPasswordFeatureManager()->IsOptedInForAccountStorage(); } void MultiStorePasswordSaveManager::MoveCredentialsToAccountStore() {
diff --git a/components/password_manager/core/browser/multi_store_password_save_manager.h b/components/password_manager/core/browser/multi_store_password_save_manager.h index 1dfac4c3..a7bceef 100644 --- a/components/password_manager/core/browser/multi_store_password_save_manager.h +++ b/components/password_manager/core/browser/multi_store_password_save_manager.h
@@ -45,7 +45,7 @@ FormSaver* GetFormSaverForGeneration() override; private: - bool IsAccountStoreActive(); + bool IsAccountStoreEnabled(); const std::unique_ptr<FormSaver> account_store_form_saver_; DISALLOW_COPY_AND_ASSIGN(MultiStorePasswordSaveManager);
diff --git a/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc b/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc index b1dfc6ca..a3a59507 100644 --- a/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc +++ b/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc
@@ -67,8 +67,6 @@ MockPasswordManagerClient() = default; ~MockPasswordManagerClient() override = default; - MOCK_CONST_METHOD0(GetPasswordSyncState, SyncState()); - MOCK_CONST_METHOD0(IsMainFrameSecure, bool()); private: @@ -171,15 +169,10 @@ fetcher_->NotifyFetchCompleted(); } - void SetAccountStoreActive(bool is_active) { - if (is_active) { - ON_CALL(*client(), GetPasswordSyncState()) - .WillByDefault(Return( - password_manager::ACCOUNT_PASSWORDS_ACTIVE_NORMAL_ENCRYPTION)); - return; - } - ON_CALL(*client(), GetPasswordSyncState()) - .WillByDefault(Return(password_manager::SYNCING_NORMAL_ENCRYPTION)); + void SetAccountStoreEnabled(bool is_enabled) { + ON_CALL(*client()->GetPasswordFeatureManager(), + IsOptedInForAccountStorage()) + .WillByDefault(Return(is_enabled)); } void SetDefaultPasswordStore(const autofill::PasswordForm::Store& store) { @@ -218,8 +211,8 @@ }; TEST_F(MultiStorePasswordSaveManagerTest, - SaveInAccountStoreWhenAccountStoreActive) { - SetAccountStoreActive(/*is_active=*/true); + SaveInAccountStoreWhenAccountStoreEnabled) { + SetAccountStoreEnabled(/*is_enabled=*/true); fetcher()->NotifyFetchCompleted(); @@ -240,8 +233,8 @@ } TEST_F(MultiStorePasswordSaveManagerTest, - DoNotSaveInAccountStoreWhenAccountStoreInactive) { - SetAccountStoreActive(/*is_active=*/false); + DoNotSaveInAccountStoreWhenAccountStoreDisabled) { + SetAccountStoreEnabled(/*is_enabled=*/false); fetcher()->NotifyFetchCompleted(); @@ -262,7 +255,7 @@ } TEST_F(MultiStorePasswordSaveManagerTest, SaveInProfileStore) { - SetAccountStoreActive(/*is_active=*/true); + SetAccountStoreEnabled(/*is_enabled=*/true); fetcher()->NotifyFetchCompleted(); @@ -283,50 +276,8 @@ } TEST_F(MultiStorePasswordSaveManagerTest, - SaveInAccountStoreByDefaultIfAccountStoreIsActive) { - SetAccountStoreActive(/*is_active=*/true); - - fetcher()->NotifyFetchCompleted(); - - PasswordForm parsed_submitted_form(parsed_submitted_form_); - - password_save_manager()->CreatePendingCredentials( - parsed_submitted_form, observed_form_, submitted_form_, - /*is_http_auth=*/false, - /*is_credential_api_save=*/false); - - EXPECT_TRUE(password_save_manager()->IsNewLogin()); - - EXPECT_CALL(*mock_profile_form_saver(), Save(_, _, _)).Times(0); - EXPECT_CALL(*mock_account_form_saver(), Save(_, _, _)); - - password_save_manager()->Save(observed_form_, parsed_submitted_form); -} - -TEST_F(MultiStorePasswordSaveManagerTest, - SaveInProfileStoreByDefaultIfAccountStoreIsInactive) { - SetAccountStoreActive(/*is_active=*/false); - - fetcher()->NotifyFetchCompleted(); - - PasswordForm parsed_submitted_form(parsed_submitted_form_); - - password_save_manager()->CreatePendingCredentials( - parsed_submitted_form, observed_form_, submitted_form_, - /*is_http_auth=*/false, - /*is_credential_api_save=*/false); - - EXPECT_TRUE(password_save_manager()->IsNewLogin()); - - EXPECT_CALL(*mock_profile_form_saver(), Save(_, _, _)); - EXPECT_CALL(*mock_account_form_saver(), Save(_, _, _)).Times(0); - - password_save_manager()->Save(observed_form_, parsed_submitted_form); -} - -TEST_F(MultiStorePasswordSaveManagerTest, UpdateBothStoresIfCredentialsExistInAccountStoreOnly) { - SetAccountStoreActive(/*is_active=*/true); + SetAccountStoreEnabled(/*is_enabled=*/true); PasswordForm saved_match_in_account_store(saved_match_); saved_match_in_account_store.username_value = @@ -349,7 +300,7 @@ TEST_F(MultiStorePasswordSaveManagerTest, UpdateBothStoresIfCredentialsExistInProfileStoreOnly) { - SetAccountStoreActive(/*is_active=*/true); + SetAccountStoreEnabled(/*is_enabled=*/true); PasswordForm saved_match_in_profile_store(saved_match_); saved_match_in_profile_store.username_value = @@ -372,7 +323,7 @@ TEST_F(MultiStorePasswordSaveManagerTest, UpdateBothStoresIfCredentialsExistInBothStoreOnly) { - SetAccountStoreActive(/*is_active=*/true); + SetAccountStoreEnabled(/*is_enabled=*/true); PasswordForm saved_match_in_profile_store(saved_match_); saved_match_in_profile_store.username_value = @@ -397,8 +348,8 @@ } TEST_F(MultiStorePasswordSaveManagerTest, - PresaveGeneratedPasswordInAccountStoreIfAccountStoreActive) { - SetAccountStoreActive(/*is_active=*/true); + PresaveGeneratedPasswordInAccountStoreIfAccountStoreEnabled) { + SetAccountStoreEnabled(/*is_enabled=*/true); fetcher()->NotifyFetchCompleted(); EXPECT_CALL(*mock_profile_form_saver(), Save(_, _, _)).Times(0); @@ -408,8 +359,8 @@ } TEST_F(MultiStorePasswordSaveManagerTest, - PresaveGeneratedPasswordInProfileStoreIfAccountStoreInactive) { - SetAccountStoreActive(/*is_active=*/false); + PresaveGeneratedPasswordInProfileStoreIfAccountStoreDisabled) { + SetAccountStoreEnabled(/*is_enabled=*/false); fetcher()->NotifyFetchCompleted(); EXPECT_CALL(*mock_profile_form_saver(), Save(_, _, _)); @@ -420,7 +371,7 @@ TEST_F(MultiStorePasswordSaveManagerTest, SaveInAccountStoreWhenPSLMatchExistsInTheAccountStore) { - SetAccountStoreActive(/*is_active=*/true); + SetAccountStoreEnabled(/*is_enabled=*/true); PasswordForm psl_saved_match(psl_saved_match_); psl_saved_match.in_store = PasswordForm::Store::kAccountStore; SetNonFederatedAndNotifyFetchCompleted({&psl_saved_match}); @@ -438,7 +389,7 @@ TEST_F(MultiStorePasswordSaveManagerTest, SaveInProfileStoreWhenPSLMatchExistsInTheProfileStore) { - SetAccountStoreActive(/*is_active=*/true); + SetAccountStoreEnabled(/*is_enabled=*/true); PasswordForm psl_saved_match(psl_saved_match_); psl_saved_match.in_store = PasswordForm::Store::kProfileStore; SetNonFederatedAndNotifyFetchCompleted({&psl_saved_match}); @@ -455,7 +406,7 @@ } TEST_F(MultiStorePasswordSaveManagerTest, UnblacklistInBothStores) { - SetAccountStoreActive(/*is_active=*/true); + SetAccountStoreEnabled(/*is_enabled=*/true); const PasswordStore::FormDigest form_digest(saved_match_); EXPECT_CALL(*mock_profile_form_saver(), Unblacklist(form_digest)); @@ -465,8 +416,8 @@ } TEST_F(MultiStorePasswordSaveManagerTest, - BlacklistInAccountStoreWhenAccountStoreActive) { - SetAccountStoreActive(/*is_active=*/true); + BlacklistInAccountStoreWhenAccountStoreEnabled) { + SetAccountStoreEnabled(/*is_enabled=*/true); const PasswordStore::FormDigest form_digest(saved_match_); SetDefaultPasswordStore(PasswordForm::Store::kAccountStore); @@ -477,8 +428,8 @@ } TEST_F(MultiStorePasswordSaveManagerTest, - BlacklistInProfileStoreAlthoughAccountStoreActive) { - SetAccountStoreActive(/*is_active=*/true); + BlacklistInProfileStoreAlthoughAccountStoreEnabled) { + SetAccountStoreEnabled(/*is_enabled=*/true); const PasswordStore::FormDigest form_digest(saved_match_); SetDefaultPasswordStore(PasswordForm::Store::kProfileStore); @@ -489,8 +440,8 @@ } TEST_F(MultiStorePasswordSaveManagerTest, - BlacklistInProfileStoreWhenAccountStoreInactive) { - SetAccountStoreActive(/*is_active=*/false); + BlacklistInProfileStoreWhenAccountStoreDisabled) { + SetAccountStoreEnabled(/*is_enabled=*/false); const PasswordStore::FormDigest form_digest(saved_match_); SetDefaultPasswordStore(PasswordForm::Store::kAccountStore);
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index f0a621a..2182a834 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -380,6 +380,8 @@ ON_CALL(mock_autofill_download_manager_, StartUploadRequest(_, _, _, _, _, _)) .WillByDefault(Return(true)); + ON_CALL(*client_.GetPasswordFeatureManager(), GetDefaultPasswordStore) + .WillByDefault(Return(PasswordForm::Store::kProfileStore)); fetcher_.reset(new FakeFormFetcher()); fetcher_->Fetch();
diff --git a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc index 4ecabb0e..6140e80 100644 --- a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc +++ b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
@@ -317,6 +317,8 @@ ON_CALL(mock_autofill_download_manager_, StartUploadRequest(_, _, _, _, _, _)) .WillByDefault(Return(true)); + ON_CALL(*client_.GetPasswordFeatureManager(), GetDefaultPasswordStore) + .WillByDefault(Return(PasswordForm::Store::kProfileStore)); } PasswordForm Parse(const FormData& form_data) {
diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn index 4067cac..590b4c39 100644 --- a/components/permissions/BUILD.gn +++ b/components/permissions/BUILD.gn
@@ -4,6 +4,8 @@ source_set("permissions") { sources = [ + "chooser_context_base.cc", + "chooser_context_base.h", "features.cc", "features.h", "notification_permission_ui_selector.h",
diff --git a/chrome/browser/permissions/chooser_context_base.cc b/components/permissions/chooser_context_base.cc similarity index 95% rename from chrome/browser/permissions/chooser_context_base.cc rename to components/permissions/chooser_context_base.cc index 7355eee9..68831a6 100644 --- a/chrome/browser/permissions/chooser_context_base.cc +++ b/components/permissions/chooser_context_base.cc
@@ -2,26 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/permissions/chooser_context_base.h" +#include "components/permissions/chooser_context_base.h" #include <utility> #include "base/values.h" -#include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/profiles/profile.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "url/origin.h" const char kObjectListKey[] = "chosen-objects"; ChooserContextBase::ChooserContextBase( - Profile* profile, const ContentSettingsType guard_content_settings_type, - const ContentSettingsType data_content_settings_type) + const ContentSettingsType data_content_settings_type, + HostContentSettingsMap* host_content_settings_map) : guard_content_settings_type_(guard_content_settings_type), data_content_settings_type_(data_content_settings_type), - host_content_settings_map_( - HostContentSettingsMapFactory::GetForProfile(profile)) { + host_content_settings_map_(host_content_settings_map) { DCHECK(host_content_settings_map_); }
diff --git a/chrome/browser/permissions/chooser_context_base.h b/components/permissions/chooser_context_base.h similarity index 94% rename from chrome/browser/permissions/chooser_context_base.h rename to components/permissions/chooser_context_base.h index 1f322b0..ba22419 100644 --- a/chrome/browser/permissions/chooser_context_base.h +++ b/components/permissions/chooser_context_base.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 CHROME_BROWSER_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_ -#define CHROME_BROWSER_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_ +#ifndef COMPONENTS_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_ +#define COMPONENTS_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_ #include <memory> #include <string> @@ -19,7 +19,6 @@ #include "url/gurl.h" class HostContentSettingsMap; -class Profile; namespace url { class Origin; @@ -64,9 +63,9 @@ void AddObserver(PermissionObserver* observer); void RemoveObserver(PermissionObserver* observer); - ChooserContextBase(Profile* profile, - ContentSettingsType guard_content_settings_type, - ContentSettingsType data_content_settings_type); + ChooserContextBase(ContentSettingsType guard_content_settings_type, + ContentSettingsType data_content_settings_type, + HostContentSettingsMap* host_content_settings_map); ~ChooserContextBase() override; // Checks whether |requesting_origin| can request permission to access objects @@ -143,4 +142,4 @@ HostContentSettingsMap* const host_content_settings_map_; }; -#endif // CHROME_BROWSER_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_ +#endif // COMPONENTS_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_
diff --git a/components/policy/core/browser/policy_conversions.cc b/components/policy/core/browser/policy_conversions.cc index f31846d..abc3f77e 100644 --- a/components/policy/core/browser/policy_conversions.cc +++ b/components/policy/core/browser/policy_conversions.cc
@@ -195,7 +195,7 @@ #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) Value ArrayPolicyConversions::GetUpdaterPolicies() { Value chrome_policies_data(Value::Type::DICTIONARY); - chrome_policies_data.SetKey("name", Value("Updater Policies")); + chrome_policies_data.SetKey("name", Value("Google Update Policies")); chrome_policies_data.SetKey("id", Value("updater")); chrome_policies_data.SetKey("policies", client()->GetUpdaterPolicies()); return chrome_policies_data;
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 9712543..b1e6c03 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -19833,7 +19833,7 @@ 'dynamic_refresh': True, 'per_profile': False, }, - 'example_value': True, + 'example_value': 0, 'id': 650, 'caption': '''Enable Ambient Authentication for profile types.''', 'tags': [], @@ -19851,7 +19851,7 @@ Note that, ambient authentication is always allowed on regular profiles. - If the policy is left not set, then the Incognito and Guest sessions will not be able to ambiently authenticate in the future releases of <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>, as they will be disallowed.''' + In <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> version 81 and later, if the policy is left not set, ambient authentication will be enabled in regular sessions only.''' }, { 'name': 'PaymentMethodQueryEnabled',
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc index bf5e60fe..c39d430 100644 --- a/components/signin/core/browser/account_reconcilor.cc +++ b/components/signin/core/browser/account_reconcilor.cc
@@ -351,14 +351,6 @@ return base::WrapUnique(new ScopedSyncedDataDeletion(this)); } -GoogleServiceAuthError AccountReconcilor::GetReconcileError() const { - return error_during_last_reconcile_; -} - -bool AccountReconcilor::IsReconcileEnabled() const { - return delegate_->IsReconcileEnabled(); -} - void AccountReconcilor::AddObserver(Observer* observer) { observer_list_.AddObserver(observer); }
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h index a190eee..5bf5fdfc 100644 --- a/components/signin/core/browser/account_reconcilor.h +++ b/components/signin/core/browser/account_reconcilor.h
@@ -123,16 +123,6 @@ // from being invalidated during the deletion. std::unique_ptr<ScopedSyncedDataDeletion> GetScopedSyncDataDeletion(); - // Returns the 'Most severe' error encountered during the last attempt to - // reconcile (after the state is already set to ACCOUNT_RECONCILOR_OK or - // ACCOUNT_RECONCILOR_ERROR). - // If the last reconciliation attempt was successful, this will be - // |GoogleServiceAuthError::State::NONE|. - GoogleServiceAuthError GetReconcileError() const; - - // Returns true if the reconcilor is enabled. - bool IsReconcileEnabled() const; - private: friend class AccountReconcilorTest; friend class DiceBrowserTest;
diff --git a/components/sync/driver/file_based_trusted_vault_client.cc b/components/sync/driver/file_based_trusted_vault_client.cc index f7f0210..c5b1b33 100644 --- a/components/sync/driver/file_based_trusted_vault_client.cc +++ b/components/sync/driver/file_based_trusted_vault_client.cc
@@ -98,6 +98,11 @@ WriteToDisk(data_, file_path_); } + void RemoveAllStoredKeys() { + base::DeleteFile(file_path_, /*recursive=*/false); + data_.Clear(); + } + private: friend class base::RefCountedThreadSafe<Backend>; @@ -156,6 +161,13 @@ observer_list_.Notify(); } +void FileBasedTrustedVaultClient::RemoveAllStoredKeys() { + TriggerLazyInitializationIfNeeded(); + backend_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&Backend::RemoveAllStoredKeys, backend_)); + observer_list_.Notify(); +} + void FileBasedTrustedVaultClient::MarkKeysAsStale( const CoreAccountInfo& account_info, base::OnceCallback<void(bool)> cb) {
diff --git a/components/sync/driver/file_based_trusted_vault_client.h b/components/sync/driver/file_based_trusted_vault_client.h index edab496..6550494d 100644 --- a/components/sync/driver/file_based_trusted_vault_client.h +++ b/components/sync/driver/file_based_trusted_vault_client.h
@@ -38,6 +38,7 @@ void StoreKeys(const std::string& gaia_id, const std::vector<std::vector<uint8_t>>& keys, int last_key_version) override; + void RemoveAllStoredKeys() override; void MarkKeysAsStale(const CoreAccountInfo& account_info, base::OnceCallback<void(bool)> cb) override;
diff --git a/components/sync/driver/file_based_trusted_vault_client_unittest.cc b/components/sync/driver/file_based_trusted_vault_client_unittest.cc index cfa297c..5721bb1 100644 --- a/components/sync/driver/file_based_trusted_vault_client_unittest.cc +++ b/components/sync/driver/file_based_trusted_vault_client_unittest.cc
@@ -182,6 +182,29 @@ ElementsAre(kKey2, kKey3)); } +TEST_F(FileBasedTrustedVaultClientTest, ShouldRemoveAllStoredKeys) { + const std::string kGaiaId1 = "user1"; + const std::string kGaiaId2 = "user2"; + const std::vector<uint8_t> kKey1 = {0, 1, 2, 3, 4}; + const std::vector<uint8_t> kKey2 = {1, 2, 3, 4}; + const std::vector<uint8_t> kKey3 = {2, 3, 4}; + + client_.StoreKeys(kGaiaId1, {kKey1}, /*last_key_version=*/0); + client_.StoreKeys(kGaiaId2, {kKey2, kKey3}, /*last_key_version=*/1); + + // Wait until the last write completes. + WaitForFlush(); + client_.RemoveAllStoredKeys(); + + // Wait until the last write completes. + WaitForFlush(); + + // Keys should be removed from both in-memory and disk storages. + EXPECT_THAT(FetchKeysAndWait(kGaiaId1), IsEmpty()); + EXPECT_THAT(FetchKeysAndWait(kGaiaId2), IsEmpty()); + EXPECT_FALSE(base::PathExists(file_path_)); +} + } // namespace } // namespace syncer
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index fbeafe7..ad41ba7 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -1652,6 +1652,10 @@ accounts_in_cookie_jar_info.signed_in_accounts, base::NullCallback()); } +void ProfileSyncService::OnAccountsCookieDeletedByUserAction() { + sync_client_->GetTrustedVaultClient()->RemoveAllStoredKeys(); +} + void ProfileSyncService::OnAccountsInCookieUpdatedWithCallback( const std::vector<gaia::ListedAccount>& signed_in_accounts, base::OnceClosure callback) {
diff --git a/components/sync/driver/profile_sync_service.h b/components/sync/driver/profile_sync_service.h index db80d76..7fa5db1 100644 --- a/components/sync/driver/profile_sync_service.h +++ b/components/sync/driver/profile_sync_service.h
@@ -197,6 +197,7 @@ void OnAccountsInCookieUpdated( const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info, const GoogleServiceAuthError& error) override; + void OnAccountsCookieDeletedByUserAction() override; // Similar to above but with a callback that will be invoked on completion. void OnAccountsInCookieUpdatedWithCallback(
diff --git a/components/sync/driver/sync_service_crypto.cc b/components/sync/driver/sync_service_crypto.cc index 0665630..7928b31 100644 --- a/components/sync/driver/sync_service_crypto.cc +++ b/components/sync/driver/sync_service_crypto.cc
@@ -50,6 +50,11 @@ NOTREACHED(); } + void RemoveAllStoredKeys() override { + // Never invoked by SyncServiceCrypto. + NOTREACHED(); + } + void MarkKeysAsStale(const CoreAccountInfo& account_info, base::OnceCallback<void(bool)> cb) override { std::move(cb).Run(false);
diff --git a/components/sync/driver/sync_service_crypto_unittest.cc b/components/sync/driver/sync_service_crypto_unittest.cc index 18b0ccd5..bd09de0 100644 --- a/components/sync/driver/sync_service_crypto_unittest.cc +++ b/components/sync/driver/sync_service_crypto_unittest.cc
@@ -193,6 +193,11 @@ observer_list_.Notify(); } + void RemoveAllStoredKeys() override { + gaia_id_to_cached_keys_.clear(); + observer_list_.Notify(); + } + void MarkKeysAsStale(const CoreAccountInfo& account_info, base::OnceCallback<void(bool)> cb) override { const std::string& gaia_id = account_info.gaia;
diff --git a/components/sync/driver/trusted_vault_client.h b/components/sync/driver/trusted_vault_client.h index bc10282..28b2178 100644 --- a/components/sync/driver/trusted_vault_client.h +++ b/components/sync/driver/trusted_vault_client.h
@@ -61,6 +61,11 @@ const std::vector<std::vector<uint8_t>>& keys, int last_key_version) = 0; + // Allows implementation to remove all previously stored keys. + // Implementations must erase all keys saved during StoreKeys() call. Used + // when accounts cookies deleted by the user action. + virtual void RemoveAllStoredKeys() = 0; + private: DISALLOW_COPY_AND_ASSIGN(TrustedVaultClient); };
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc index 231a1e46..9835513 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -43,7 +43,14 @@ Image(gpu::SharedImageFactory* factory, gpu::SharedImageRepresentationFactory* representation_factory) : factory_(factory), representation_factory_(representation_factory) {} - ~Image() = default; + ~Image() { + // TODO(vasilyt): As we are going to delete image anyway we should be able + // to abort write to avoid unnecessary flush to submit semaphores. + if (scoped_skia_write_access_) { + EndWriteSkia(); + } + DCHECK(!scoped_skia_write_access_); + } bool Initialize(const gfx::Size& size, const gfx::ColorSpace& color_space,
diff --git a/components/viz/service/display_embedder/skia_output_device_dawn.cc b/components/viz/service/display_embedder/skia_output_device_dawn.cc index b5b1513..8b41500 100644 --- a/components/viz/service/display_embedder/skia_output_device_dawn.cc +++ b/components/viz/service/display_embedder/skia_output_device_dawn.cc
@@ -87,7 +87,7 @@ DCHECK(backend_target.isValid()); sk_surface_ = SkSurface::MakeFromBackendRenderTarget( context_provider_->GetGrContext(), backend_target, - capabilities_.output_surface_origin == SurfaceOrigin::kTopLeft + capabilities_.output_surface_origin == gfx::SurfaceOrigin::kTopLeft ? kTopLeft_GrSurfaceOrigin : kBottomLeft_GrSurfaceOrigin, kSurfaceColorType, sk_color_space_, /*surfaceProps=*/nullptr);
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 55f2a0d..5f77dab 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -288,6 +288,11 @@ RunCSSTest(FILE_PATH_LITERAL("table-display-other.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityCSSDataTableDisplayOther) { + RunCSSTest(FILE_PATH_LITERAL("table-data-display-other.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSTransform) { RunCSSTest(FILE_PATH_LITERAL("transform.html")); }
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc index 85796696..b9941e3 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.cc +++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -288,10 +288,12 @@ bool WebBluetoothServiceImpl::IsDevicePaired( const std::string& device_address) { - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (!delegate) + return false; return delegate->GetWebBluetoothDeviceId(render_frame_host_, device_address) .IsValid(); } @@ -536,10 +538,12 @@ auto client = scanning_clients_.begin(); while (client != scanning_clients_.end()) { auto device = blink::mojom::WebBluetoothDevice::New(); - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (!delegate) + return; device->id = delegate->AddScannedDevice(render_frame_host_, device_address); } else { @@ -707,13 +711,15 @@ RemoteServerConnectCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - bool is_connect_allowed; - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { - is_connect_allowed = - delegate->HasDevicePermission(render_frame_host_, device_id); + bool is_connect_allowed = false; + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (delegate) { + is_connect_allowed = + delegate->HasDevicePermission(render_frame_host_, device_id); + } } else { is_connect_allowed = allowed_devices().IsAllowedToGATTConnect(device_id); } @@ -1502,10 +1508,16 @@ DVLOG(1) << "Device: " << device->GetNameForDisplay(); auto web_bluetooth_device = blink::mojom::WebBluetoothDevice::New(); - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (!delegate) { + std::move(callback).Run( + blink::mojom::WebBluetoothResult::WEB_BLUETOOTH_NOT_SUPPORTED, + /*device=*/nullptr); + return; + } web_bluetooth_device->id = delegate->GrantServiceAccessPermission( render_frame_host_, device, options.get()); } else { @@ -1660,12 +1672,15 @@ CacheQueryResult WebBluetoothServiceImpl::QueryCacheForDevice( const blink::WebBluetoothDeviceId& device_id) { - std::string device_address; - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { - device_address = delegate->GetDeviceAddress(render_frame_host_, device_id); + std::string device_address = ""; + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (delegate) { + device_address = + delegate->GetDeviceAddress(render_frame_host_, device_id); + } } else { device_address = allowed_devices().GetDeviceAddress(device_id); } @@ -1698,12 +1713,14 @@ } blink::WebBluetoothDeviceId device_id; - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { - device_id = delegate->GetWebBluetoothDeviceId(render_frame_host_, - device_iter->second); + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (delegate) { + device_id = delegate->GetWebBluetoothDeviceId(render_frame_host_, + device_iter->second); + } } else { const blink::WebBluetoothDeviceId* device_id_ptr = allowed_devices().GetDeviceId(device_iter->second); @@ -1900,10 +1917,12 @@ bool WebBluetoothServiceImpl::IsAllowedToAccessAtLeastOneService( const blink::WebBluetoothDeviceId& device_id) { - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (!delegate) + return false; return delegate->IsAllowedToAccessAtLeastOneService(render_frame_host_, device_id); } else { @@ -1914,10 +1933,12 @@ bool WebBluetoothServiceImpl::IsAllowedToAccessService( const blink::WebBluetoothDeviceId& device_id, const device::BluetoothUUID& service) { - BluetoothDelegate* delegate = - GetContentClient()->browser()->GetBluetoothDelegate(); - if (delegate && base::FeatureList::IsEnabled( - features::kWebBluetoothNewPermissionsBackend)) { + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + BluetoothDelegate* delegate = + GetContentClient()->browser()->GetBluetoothDelegate(); + if (!delegate) + return false; return delegate->IsAllowedToAccessService(render_frame_host_, device_id, service); } else {
diff --git a/content/browser/frame_host/sec_fetch_browsertest.cc b/content/browser/frame_host/sec_fetch_browsertest.cc index b966f10..11a96411 100644 --- a/content/browser/frame_host/sec_fetch_browsertest.cc +++ b/content/browser/frame_host/sec_fetch_browsertest.cc
@@ -31,12 +31,7 @@ class SecFetchBrowserTest : public ContentBrowserTest { public: SecFetchBrowserTest() - : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) { - feature_list_.InitWithFeatures( - {network::features::kFetchMetadata, - network::features::kFetchMetadataDestination}, - {}); - } + : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} void SetUpOnMainThread() override { host_resolver()->AddRule("*", "127.0.0.1");
diff --git a/content/browser/loader/browser_initiated_resource_request.cc b/content/browser/loader/browser_initiated_resource_request.cc index e88d4aa..d9cbc45 100644 --- a/content/browser/loader/browser_initiated_resource_request.cc +++ b/content/browser/loader/browser_initiated_resource_request.cc
@@ -22,19 +22,6 @@ namespace content { -bool IsFetchMetadataEnabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalWebPlatformFeatures) || - base::FeatureList::IsEnabled(network::features::kFetchMetadata); -} - -bool IsFetchMetadataDestinationEnabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalWebPlatformFeatures) || - base::FeatureList::IsEnabled( - network::features::kFetchMetadataDestination); -} - void UpdateAdditionalHeadersForBrowserInitiatedRequest( net::HttpRequestHeaders* headers, BrowserContext* browser_context,
diff --git a/content/browser/loader/browser_initiated_resource_request.h b/content/browser/loader/browser_initiated_resource_request.h index 89df8474..f18f548e 100644 --- a/content/browser/loader/browser_initiated_resource_request.h +++ b/content/browser/loader/browser_initiated_resource_request.h
@@ -19,14 +19,6 @@ class BrowserContext; -// Returns true if either of FetchMetadata or experimental-web-platform-features -// is enabled. -bool IsFetchMetadataEnabled(); - -// Returns true if either of FetchMetadataDestination or -// experimental-web-platform-features is enabled. -bool IsFetchMetadataDestinationEnabled(); - // Sets request headers appropriate for browser-initiated resource requests, // i.e., requests for navigations and dedicated/shared/service worker // scripts.
diff --git a/content/browser/plugin_private_storage_helper.cc b/content/browser/plugin_private_storage_helper.cc index 015731fb8..5210bea 100644 --- a/content/browser/plugin_private_storage_helper.cc +++ b/content/browser/plugin_private_storage_helper.cc
@@ -267,9 +267,9 @@ begin_(begin), end_(end), callback_(std::move(callback)) {} - ~PluginPrivateDataDeletionHelper() {} + ~PluginPrivateDataDeletionHelper() = default; - void CheckOriginsOnFileTaskRunner(const std::set<GURL>& origins); + void CheckOriginsOnFileTaskRunner(const std::set<url::Origin>& origins); private: // Keeps track of the pending work. When |task_count_| goes to 0 then @@ -287,7 +287,7 @@ }; void PluginPrivateDataDeletionHelper::CheckOriginsOnFileTaskRunner( - const std::set<GURL>& origins) { + const std::set<url::Origin>& origins) { DCHECK(filesystem_context_->default_file_task_runner() ->RunsTasksInCurrentSequence()); IncrementTaskCount(); @@ -306,7 +306,7 @@ // for this origin. base::File::Error error; base::FilePath path = obfuscated_file_util->GetDirectoryForOriginAndType( - url::Origin::Create(origin), "", false, &error); + origin, "", false, &error); if (error != base::File::FILE_OK) { DLOG(ERROR) << "Unable to read directory for " << origin; continue; @@ -326,7 +326,7 @@ IncrementTaskCount(); PluginPrivateDataByOriginChecker* helper = new PluginPrivateDataByOriginChecker( - filesystem_context_.get(), origin.GetOrigin(), + filesystem_context_.get(), origin.GetURL().GetOrigin(), plugin_path.BaseName().MaybeAsASCII(), begin_, end_, decrement_callback); base::PostTask( @@ -389,7 +389,7 @@ void ClearPluginPrivateDataOnFileTaskRunner( scoped_refptr<storage::FileSystemContext> filesystem_context, - const GURL& storage_origin, + const GURL& storage_origin_url, StoragePartition::OriginMatcherFunction origin_matcher, const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, const base::Time begin, @@ -397,7 +397,7 @@ base::OnceClosure callback) { DCHECK(filesystem_context->default_file_task_runner() ->RunsTasksInCurrentSequence()); - DVLOG(3) << "Clearing plugin data for origin: " << storage_origin; + DVLOG(3) << "Clearing plugin data for origin: " << storage_origin_url; storage::FileSystemBackend* backend = filesystem_context->GetFileSystemBackend( @@ -405,7 +405,7 @@ storage::FileSystemQuotaUtil* quota_util = backend->GetQuotaUtil(); // Determine the set of origins used. - std::set<GURL> origins; + std::set<url::Origin> origins; quota_util->GetOriginsForTypeOnFileTaskRunner( storage::kFileSystemTypePluginPrivate, &origins); @@ -417,9 +417,10 @@ // If a specific origin is provided, then check that it is in the list // returned and remove all the other origins. - if (!storage_origin.is_empty()) { - DCHECK(!origin_matcher) << "Only 1 of |storage_origin| and " + if (!storage_origin_url.is_empty()) { + DCHECK(!origin_matcher) << "Only 1 of |storage_origin_url| and " "|origin_matcher| should be specified."; + url::Origin storage_origin = url::Origin::Create(storage_origin_url); if (!base::Contains(origins, storage_origin)) { // Nothing matches, so nothing to do. std::move(callback).Run(); @@ -433,14 +434,13 @@ // If a filter is provided, determine which origins match. if (origin_matcher) { - DCHECK(storage_origin.is_empty()) - << "Only 1 of |storage_origin| and |origin_matcher| should be " + DCHECK(storage_origin_url.is_empty()) + << "Only 1 of |storage_origin_url| and |origin_matcher| should be " "specified."; - std::set<GURL> origins_to_check; + std::set<url::Origin> origins_to_check; origins_to_check.swap(origins); for (const auto& origin : origins_to_check) { - if (origin_matcher.Run(url::Origin::Create(origin), - special_storage_policy.get())) + if (origin_matcher.Run(origin, special_storage_policy.get())) origins.insert(origin); }
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 0fcd5010..9a4917a 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3238,7 +3238,6 @@ switches::kEnableWebGLDraftExtensions, switches::kEnableWebGLImageChromium, switches::kFileUrlPathAlias, - switches::kForceDarkMode, switches::kForceDeviceScaleFactor, switches::kForceDisableWebRtcApmInAudioService, switches::kForceDisplayColorProfile,
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 0baf858..eb751d2 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -307,6 +307,9 @@ } gfx::NativeView RenderWidgetHostViewChildFrame::GetNativeView() { + if (!frame_connector_) + return nullptr; + RenderWidgetHostView* parent_view = frame_connector_->GetParentRenderWidgetHostView(); return parent_view ? parent_view->GetNativeView() : nullptr;
diff --git a/content/browser/scheduler/OWNERS b/content/browser/scheduler/OWNERS index 23e7c0a8..17d283a 100644 --- a/content/browser/scheduler/OWNERS +++ b/content/browser/scheduler/OWNERS
@@ -2,3 +2,6 @@ carlscab@chromium.org eseckler@chromium.org skyostil@chromium.org + +# TEAM: scheduler-dev@chromium.org +# COMPONENT: Internals>TaskScheduling
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index 4b23c04e..9677816 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -560,10 +560,10 @@ storage::FileSystemQuotaUtil* quota_util = backend->GetQuotaUtil(); // Determine the set of origins used. - std::set<GURL> origins; + std::set<url::Origin> origins; quota_util->GetOriginsForTypeOnFileTaskRunner( storage::kFileSystemTypePluginPrivate, &origins); - *data_exists_for_origin = origins.find(origin.GetURL()) != origins.end(); + *data_exists_for_origin = origins.find(origin) != origins.end(); // AwaitCompletionHelper and MessageLoop don't work on a // SequencedTaskRunner, so post a task on the IO thread.
diff --git a/content/browser/theme_helper.cc b/content/browser/theme_helper.cc index 817f085..adc7df0 100644 --- a/content/browser/theme_helper.cc +++ b/content/browser/theme_helper.cc
@@ -27,7 +27,6 @@ mojom::UpdateSystemColorInfoParams::New(); params->is_dark_mode = native_theme->ShouldUseDarkColors(); params->is_high_contrast = native_theme->UsesHighContrastColors(); - params->preferred_color_scheme = native_theme->GetPreferredColorScheme(); const auto& colors = native_theme->GetSystemColors(); params->colors.insert(colors.begin(), colors.end());
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index e6abd33d..749dca3 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -592,6 +592,7 @@ is_overlay_content_(false), showing_context_menu_(false), text_autosizer_page_info_({0, 0, 1.f}), + native_theme_observer_(this), had_inner_webcontents_(false) { frame_tree_.SetFrameRemoveListener(base::BindRepeating( &WebContentsImpl::OnFrameRemoved, base::Unretained(this))); @@ -603,6 +604,11 @@ display_cutout_host_impl_ = std::make_unique<DisplayCutoutHostImpl>(this); #endif + ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForWeb(); + native_theme_observer_.Add(native_theme); + using_dark_colors_ = native_theme->ShouldUseDarkColors(); + preferred_color_scheme_ = native_theme->GetPreferredColorScheme(); + // ConversionHost takes a weak ref on |this|, so it must be created outside of // the initializer list. conversion_host_ = std::make_unique<ConversionHost>(this); @@ -7484,6 +7490,27 @@ GetMainFrame()->SetVisibilityForChildViews(visible); } +void WebContentsImpl::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) { + DCHECK(native_theme_observer_.IsObserving(observed_theme)); + + bool using_dark_colors = observed_theme->ShouldUseDarkColors(); + ui::NativeTheme::PreferredColorScheme preferred_color_scheme = + observed_theme->GetPreferredColorScheme(); + bool preferences_changed = false; + + if (using_dark_colors_ != using_dark_colors) { + using_dark_colors_ = using_dark_colors; + preferences_changed = true; + } + if (preferred_color_scheme_ != preferred_color_scheme) { + preferred_color_scheme_ = preferred_color_scheme; + preferences_changed = true; + } + + if (preferences_changed) + NotifyPreferencesChanged(); +} + mojom::FrameInputHandler* WebContentsImpl::GetFocusedFrameInputHandler() { auto* focused_frame = GetFocusedFrame(); if (!focused_frame)
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index d2a7473..47e0887d 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -22,6 +22,7 @@ #include "base/observer_list.h" #include "base/optional.h" #include "base/process/process.h" +#include "base/scoped_observer.h" #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" @@ -75,6 +76,7 @@ #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" #include "ui/native_theme/native_theme.h" +#include "ui/native_theme/native_theme_observer.h" #if defined(OS_ANDROID) #include "content/public/browser/android/child_process_importance.h" @@ -155,7 +157,8 @@ public blink::mojom::ColorChooserFactory, public NotificationObserver, public NavigationControllerDelegate, - public NavigatorDelegate { + public NavigatorDelegate, + public ui::NativeThemeObserver { public: class FriendWrapper; @@ -1583,6 +1586,9 @@ // |current_fullscreen_frame_| and notify observers whenever it changes. void FullscreenFrameSetUpdated(); + // ui::NativeThemeObserver: + void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override; + // Sets the visibility to |new_visibility| and propagates this to the // renderer side, taking into account the current capture state. This // can be called with the current visibility to effect capturing @@ -1973,6 +1979,15 @@ // with OOPIF renderers. blink::WebTextAutosizerPageInfo text_autosizer_page_info_; + // Observe native theme for changes to dark mode, and preferred color scheme. + // Used to notify the renderer of preferred color scheme changes. + ScopedObserver<ui::NativeTheme, ui::NativeThemeObserver> + native_theme_observer_; + + bool using_dark_colors_ = false; + ui::NativeTheme::PreferredColorScheme preferred_color_scheme_ = + ui::NativeTheme::PreferredColorScheme::kNoPreference; + // TODO(crbug.com/934637): Remove this field when pdf/any inner web contents // user gesture is properly propagated. This is a temporary fix for history // intervention to be disabled for pdfs (crbug.com/965434).
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 68dc281c..97e66822 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -181,10 +181,6 @@ {wf::EnableWebXRHitTest, features::kWebXrHitTest, kUseFeatureState}, {wf::EnableWebXRIncubations, features::kWebXrIncubations, kEnableOnly}, - {wf::EnableFetchMetadata, network::features::kFetchMetadata, - kUseFeatureState}, - {wf::EnableFetchMetadataDestination, - network::features::kFetchMetadataDestination, kUseFeatureState}, {wf::EnableUserActivationPostMessageTransfer, features::kUserActivationPostMessageTransfer, kUseFeatureState}, {wf::EnableUserActivationSameOriginVisibility, @@ -546,8 +542,6 @@ // these features. if (enable_experimental_web_platform_features) { WebRuntimeFeatures::EnableNetInfoDownlinkMax(true); - WebRuntimeFeatures::EnableFetchMetadata(true); - WebRuntimeFeatures::EnableFetchMetadataDestination(true); } WebRuntimeFeatures::EnableBackForwardCache(
diff --git a/content/child/webthemeengine_impl_android.cc b/content/child/webthemeengine_impl_android.cc index fe90e3f..db48cdcd 100644 --- a/content/child/webthemeengine_impl_android.cc +++ b/content/child/webthemeengine_impl_android.cc
@@ -177,17 +177,4 @@ ui::NativeTheme::GetInstanceForWeb()->set_high_contrast( forced_colors == blink::ForcedColors::kActive); } - -blink::PreferredColorScheme WebThemeEngineAndroid::PreferredColorScheme() - const { - ui::NativeTheme::PreferredColorScheme preferred_color_scheme = - ui::NativeTheme::GetInstanceForWeb()->GetPreferredColorScheme(); - return WebPreferredColorScheme(preferred_color_scheme); -} - -void WebThemeEngineAndroid::SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) { - ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( - NativePreferredColorScheme(preferred_color_scheme)); -} } // namespace content
diff --git a/content/child/webthemeengine_impl_android.h b/content/child/webthemeengine_impl_android.h index 95e2744..b8c713e 100644 --- a/content/child/webthemeengine_impl_android.h +++ b/content/child/webthemeengine_impl_android.h
@@ -24,9 +24,6 @@ blink::WebColorScheme color_scheme) override; blink::ForcedColors GetForcedColors() const override; void SetForcedColors(const blink::ForcedColors forced_colors) override; - blink::PreferredColorScheme PreferredColorScheme() const override; - void SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) override; }; } // namespace content
diff --git a/content/child/webthemeengine_impl_conversions.cc b/content/child/webthemeengine_impl_conversions.cc index 47ebce82..ce5773a6 100644 --- a/content/child/webthemeengine_impl_conversions.cc +++ b/content/child/webthemeengine_impl_conversions.cc
@@ -117,28 +117,5 @@ } } -ui::NativeTheme::PreferredColorScheme NativePreferredColorScheme( - blink::PreferredColorScheme preferred_color_scheme) { - switch (preferred_color_scheme) { - case blink::PreferredColorScheme::kDark: - return ui::NativeTheme::PreferredColorScheme::kDark; - case blink::PreferredColorScheme::kLight: - return ui::NativeTheme::PreferredColorScheme::kLight; - case blink::PreferredColorScheme::kNoPreference: - return ui::NativeTheme::PreferredColorScheme::kNoPreference; - } -} - -blink::PreferredColorScheme WebPreferredColorScheme( - ui::NativeTheme::PreferredColorScheme preferred_color_scheme) { - switch (preferred_color_scheme) { - case ui::NativeTheme::PreferredColorScheme::kDark: - return blink::PreferredColorScheme::kDark; - case ui::NativeTheme::PreferredColorScheme::kLight: - return blink::PreferredColorScheme::kLight; - case ui::NativeTheme::PreferredColorScheme::kNoPreference: - return blink::PreferredColorScheme::kNoPreference; - } -} } // namespace content
diff --git a/content/child/webthemeengine_impl_conversions.h b/content/child/webthemeengine_impl_conversions.h index 4d7dbba..fdd2e56 100644 --- a/content/child/webthemeengine_impl_conversions.h +++ b/content/child/webthemeengine_impl_conversions.h
@@ -27,12 +27,6 @@ CONTENT_EXPORT ui::NativeTheme::SystemThemeColor NativeSystemThemeColor( blink::WebThemeEngine::SystemThemeColor theme_color); -CONTENT_EXPORT ui::NativeTheme::PreferredColorScheme NativePreferredColorScheme( - blink::PreferredColorScheme preferred_color_scheme); - -CONTENT_EXPORT blink::PreferredColorScheme WebPreferredColorScheme( - ui::NativeTheme::PreferredColorScheme preferred_color_scheme); - } // namespace content #endif // CONTENT_CHILD_WEBTHEMEENGINE_IMPL_CONVERSIONS_H_
diff --git a/content/child/webthemeengine_impl_default.cc b/content/child/webthemeengine_impl_default.cc index e3d3ef5..0691820 100644 --- a/content/child/webthemeengine_impl_default.cc +++ b/content/child/webthemeengine_impl_default.cc
@@ -250,17 +250,4 @@ forced_colors == blink::ForcedColors::kActive); } -blink::PreferredColorScheme WebThemeEngineDefault::PreferredColorScheme() - const { - ui::NativeTheme::PreferredColorScheme preferred_color_scheme = - ui::NativeTheme::GetInstanceForWeb()->GetPreferredColorScheme(); - return WebPreferredColorScheme(preferred_color_scheme); -} - -void WebThemeEngineDefault::SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) { - ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( - NativePreferredColorScheme(preferred_color_scheme)); -} - } // namespace content
diff --git a/content/child/webthemeengine_impl_default.h b/content/child/webthemeengine_impl_default.h index 1f08f67..755a6d8a 100644 --- a/content/child/webthemeengine_impl_default.h +++ b/content/child/webthemeengine_impl_default.h
@@ -41,9 +41,6 @@ #endif blink::ForcedColors GetForcedColors() const override; void SetForcedColors(const blink::ForcedColors forced_colors) override; - blink::PreferredColorScheme PreferredColorScheme() const override; - void SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) override; }; } // namespace content
diff --git a/content/child/webthemeengine_impl_mac.cc b/content/child/webthemeengine_impl_mac.cc index 5ac4e20a..dbd8f0b 100644 --- a/content/child/webthemeengine_impl_mac.cc +++ b/content/child/webthemeengine_impl_mac.cc
@@ -18,16 +18,4 @@ forced_colors_ = forced_colors; } -blink::PreferredColorScheme WebThemeEngineMac::PreferredColorScheme() const { - ui::NativeTheme::PreferredColorScheme preferred_color_scheme = - ui::NativeTheme::GetInstanceForWeb()->GetPreferredColorScheme(); - return WebPreferredColorScheme(preferred_color_scheme); -} - -void WebThemeEngineMac::SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) { - ui::NativeTheme::GetInstanceForWeb()->set_preferred_color_scheme( - NativePreferredColorScheme(preferred_color_scheme)); -} - } // namespace content
diff --git a/content/child/webthemeengine_impl_mac.h b/content/child/webthemeengine_impl_mac.h index adfd539..81f1d06 100644 --- a/content/child/webthemeengine_impl_mac.h +++ b/content/child/webthemeengine_impl_mac.h
@@ -15,9 +15,6 @@ blink::ForcedColors GetForcedColors() const override; void SetForcedColors(const blink::ForcedColors forced_colors) override; - blink::PreferredColorScheme PreferredColorScheme() const override; - void SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) override; private: blink::ForcedColors forced_colors_ = blink::ForcedColors::kNone;
diff --git a/content/common/native_types.mojom b/content/common/native_types.mojom index 6d7f52c..e8015a1 100644 --- a/content/common/native_types.mojom +++ b/content/common/native_types.mojom
@@ -89,7 +89,4 @@ struct SyntheticPointerAction; [Native] -enum PreferredColorScheme; - -[Native] enum SystemThemeColor;
diff --git a/content/common/native_types.typemap b/content/common/native_types.typemap index 6f11569..20a1fb2 100644 --- a/content/common/native_types.typemap +++ b/content/common/native_types.typemap
@@ -78,7 +78,6 @@ "content.mojom.InputEventAckState=::content::InputEventAckState", "content.mojom.NetworkConnectionType=::net::NetworkChangeNotifier::ConnectionType", "content.mojom.PointerType=::blink::WebPointerProperties::PointerType", - "content.mojom.PreferredColorScheme=::ui::NativeTheme::PreferredColorScheme", "content.mojom.ScrollGranularity=::ui::ScrollGranularity", "content.mojom.SyntheticPinch=::content::SyntheticPinchGestureParams", "content.mojom.SyntheticPointerAction=::content::SyntheticPointerActionListParams",
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index f6a1f8c..87d7a5b 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom
@@ -180,7 +180,6 @@ struct UpdateSystemColorInfoParams { bool is_dark_mode; bool is_high_contrast; - PreferredColorScheme preferred_color_scheme; // uint32 represents a SkColor in the map. map<SystemThemeColor, uint32> colors; };
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 72594b5..7aa8ff0 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -78,8 +78,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::ScrollerStyle, blink::kScrollerStyleOverlay) #endif -IPC_ENUM_TRAITS_MAX_VALUE(ui::NativeTheme::PreferredColorScheme, - ui::NativeTheme::PreferredColorScheme::kMaxValue) IPC_ENUM_TRAITS_MAX_VALUE(ui::NativeTheme::SystemThemeColor, ui::NativeTheme::SystemThemeColor::kMaxValue)
diff --git a/content/public/browser/browser_task_traits.h b/content/public/browser/browser_task_traits.h index cb0637e..7645fd6 100644 --- a/content/public/browser/browser_task_traits.h +++ b/content/public/browser/browser_task_traits.h
@@ -23,10 +23,14 @@ // Semantic annotations which tell the scheduler what type of task it's dealing // with. This will be used by the scheduler for dynamic prioritization and for -// attribution in traces, etc... +// attribution in traces, etc... In general, BrowserTaskType::kDefault is what +// you want (it's implicit if you don't specify this trait). Only explicitly +// specify this trait if you carefully isolated a set of tasks that have no +// ordering requirements with anything else (in doubt, consult with +// scheduler-dev@chromium.org). // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.browser enum class BrowserTaskType { - // A catch all tasks that don't fit the types below. + // A catch all for tasks that don't fit the types below. kDefault, // Critical startup tasks.
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h index 7a3c0c0c..1df0ec45 100644 --- a/content/public/common/common_param_traits_macros.h +++ b/content/public/common/common_param_traits_macros.h
@@ -76,6 +76,9 @@ content::AutoplayPolicy, content::AutoplayPolicy::kNoUserGestureRequired, content::AutoplayPolicy::kDocumentUserActivationRequired) +IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::PreferredColorScheme, + blink::PreferredColorScheme::kNoPreference, + blink::PreferredColorScheme::kMaxValue) IPC_STRUCT_TRAITS_BEGIN(blink::WebRect) IPC_STRUCT_TRAITS_MEMBER(x) @@ -233,6 +236,7 @@ IPC_STRUCT_TRAITS_MEMBER(media_controls_enabled) IPC_STRUCT_TRAITS_MEMBER(do_not_update_selection_on_mutating_selection_range) IPC_STRUCT_TRAITS_MEMBER(autoplay_policy) + IPC_STRUCT_TRAITS_MEMBER(preferred_color_scheme) IPC_STRUCT_TRAITS_MEMBER(low_priority_iframes_threshold) IPC_STRUCT_TRAITS_MEMBER(picture_in_picture_enabled) IPC_STRUCT_TRAITS_MEMBER(translate_service_available)
diff --git a/content/public/common/web_preferences.cc b/content/public/common/web_preferences.cc index 60b12f8..8d1b50f 100644 --- a/content/public/common/web_preferences.cc +++ b/content/public/common/web_preferences.cc
@@ -223,6 +223,7 @@ media_controls_enabled(true), do_not_update_selection_on_mutating_selection_range(false), autoplay_policy(AutoplayPolicy::kDocumentUserActivationRequired), + preferred_color_scheme(blink::PreferredColorScheme::kNoPreference), low_priority_iframes_threshold(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN), picture_in_picture_enabled(true), translate_service_available(false),
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h index 062d138..76cb05a1 100644 --- a/content/public/common/web_preferences.h +++ b/content/public/common/web_preferences.h
@@ -14,6 +14,7 @@ #include "build/build_config.h" #include "content/common/content_export.h" #include "net/nqe/effective_connection_type.h" +#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/mojom/v8_cache_options.mojom.h" #include "ui/base/pointer/pointer_device.h" #include "url/gurl.h" @@ -311,6 +312,12 @@ // Defines the current autoplay policy. AutoplayPolicy autoplay_policy; + // The preferred color scheme for the web content. The scheme is used to + // evaluate the prefers-color-scheme media query and resolve UA color scheme + // to be used based on the supported-color-schemes META tag and CSS property. + blink::PreferredColorScheme preferred_color_scheme = + blink::PreferredColorScheme::kNoPreference; + // Network quality threshold below which resources from iframes are assigned // either kVeryLow or kVeryLow Blink priority. net::EffectiveConnectionType low_priority_iframes_threshold;
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc index 3564a38..dd0de3f 100644 --- a/content/renderer/input/render_widget_input_handler.cc +++ b/content/renderer/input/render_widget_input_handler.cc
@@ -682,8 +682,8 @@ widget_->layer_tree_host()->GetSwapPromiseManager(), nullptr); auto scoped_event_metrics_monitor = widget_->layer_tree_host()->GetScopedEventMetricsMonitor( - {ui::WebEventTypeToEventType(input_event.GetType()), - input_event.TimeStamp()}); + {ui::WebEventTypeToEventType(gesture_event->GetType()), + gesture_event->TimeStamp()}); widget_->GetWebWidget()->HandleInputEvent( blink::WebCoalescedInputEvent(*gesture_event.get())); }
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 9aa93fb..8c0fe45 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1992,8 +1992,7 @@ mojom::UpdateSystemColorInfoParamsPtr params) { bool did_system_color_info_change = ui::NativeTheme::GetInstanceForWeb()->UpdateSystemColorInfo( - params->is_dark_mode, params->is_high_contrast, - params->preferred_color_scheme, params->colors); + params->is_dark_mode, params->is_high_contrast, params->colors); if (did_system_color_info_change) { blink::SystemColorsChanged(); blink::ColorSchemeChanged();
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 2235e7b..8d235493 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -860,6 +860,7 @@ prefs.data_saver_holdback_web_api_enabled); settings->SetLazyLoadEnabled(prefs.lazy_load_enabled); + settings->SetPreferredColorScheme(prefs.preferred_color_scheme); for (const auto& ect_distance_pair : prefs.lazy_frame_loading_distance_thresholds_px) {
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index c7bfe84..778c599 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -291,9 +291,6 @@ GetContentClient()->renderer()->OverrideThemeEngine(); if (!theme_engine) theme_engine = BlinkPlatformImpl::ThemeEngine(); - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kForceDarkMode)) - theme_engine->SetPreferredColorScheme(blink::PreferredColorScheme::kDark); return theme_engine; }
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 450b90d4..92c49392 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -158,6 +158,8 @@ "browser/web_test/fake_bluetooth_chooser.h", "browser/web_test/fake_bluetooth_chooser_factory.cc", "browser/web_test/fake_bluetooth_chooser_factory.h", + "browser/web_test/fake_bluetooth_delegate.cc", + "browser/web_test/fake_bluetooth_delegate.h", "browser/web_test/fake_bluetooth_scanning_prompt.cc", "browser/web_test/fake_bluetooth_scanning_prompt.h", "browser/web_test/leak_detector.cc",
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 9ec9470..5a8689e 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -298,6 +298,17 @@ return new ShellSpeechRecognitionManagerDelegate(); } +void ShellContentBrowserClient::OverrideWebkitPrefs( + RenderViewHost* render_view_host, + WebPreferences* prefs) { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceDarkMode)) { + prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; + } else { + prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; + } +} + base::FilePath ShellContentBrowserClient::GetFontLookupTableCacheDir() { return browser_context()->GetPath().Append( FILE_PATH_LITERAL("FontLookupTableCache"));
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index 618eb3b..92c77f2 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -58,6 +58,8 @@ std::unique_ptr<ClientCertificateDelegate> delegate) override; SpeechRecognitionManagerDelegate* CreateSpeechRecognitionManagerDelegate() override; + void OverrideWebkitPrefs(RenderViewHost* render_view_host, + WebPreferences* prefs) override; base::FilePath GetFontLookupTableCacheDir() override; DevToolsManagerDelegate* GetDevToolsManagerDelegate() override; mojo::Remote<::media::mojom::MediaService> RunSecondaryMediaService()
diff --git a/content/shell/browser/web_test/blink_test_controller.cc b/content/shell/browser/web_test/blink_test_controller.cc index 546b4cc..c898b1d1 100644 --- a/content/shell/browser/web_test/blink_test_controller.cc +++ b/content/shell/browser/web_test/blink_test_controller.cc
@@ -10,6 +10,7 @@ #include <algorithm> #include <iostream> #include <memory> +#include <queue> #include <set> #include <utility> #include <vector> @@ -575,6 +576,7 @@ WebTestContentBrowserClient::Get()->SetPopupBlockingEnabled(false); WebTestContentBrowserClient::Get()->ResetMockClipboardHost(); WebTestContentBrowserClient::Get()->SetScreenOrientationChanged(false); + WebTestContentBrowserClient::Get()->ResetFakeBluetoothDelegate(); navigation_history_dump_ = ""; pixel_dump_.reset(); actual_pixel_hash_ = ""; @@ -614,6 +616,12 @@ } else { ApplyWebTestDefaultPreferences(prefs); } + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceDarkMode)) { + prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark; + } else { + prefs->preferred_color_scheme = blink::PreferredColorScheme::kLight; + } } void BlinkTestController::OpenURL(const GURL& url) {
diff --git a/content/shell/browser/web_test/fake_bluetooth_delegate.cc b/content/shell/browser/web_test/fake_bluetooth_delegate.cc new file mode 100644 index 0000000..4f02cca --- /dev/null +++ b/content/shell/browser/web_test/fake_bluetooth_delegate.cc
@@ -0,0 +1,139 @@ +// Copyright 2020 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/shell/browser/web_test/fake_bluetooth_delegate.h" + +#include "content/public/browser/web_contents.h" +#include "device/bluetooth/bluetooth_device.h" +#include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h" +#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h" +#include "url/origin.h" + +using blink::WebBluetoothDeviceId; +using device::BluetoothDevice; +using device::BluetoothUUID; + +namespace content { + +// public +FakeBluetoothDelegate::FakeBluetoothDelegate() = default; +FakeBluetoothDelegate::~FakeBluetoothDelegate() = default; + +WebBluetoothDeviceId FakeBluetoothDelegate::GetWebBluetoothDeviceId( + RenderFrameHost* frame, + const std::string& device_address) { + auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame); + auto it = device_address_to_id_map.find(device_address); + if (it != device_address_to_id_map.end()) + return it->second; + return {}; +} + +std::string FakeBluetoothDelegate::GetDeviceAddress( + RenderFrameHost* frame, + const WebBluetoothDeviceId& device_id) { + auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame); + for (auto& entry : device_address_to_id_map) { + if (entry.second == device_id) + return entry.first; + } + return std::string(); +} + +blink::WebBluetoothDeviceId FakeBluetoothDelegate::AddScannedDevice( + RenderFrameHost* frame, + const std::string& device_address) { + return GetOrCreateDeviceIdForDeviceAddress(frame, device_address); +} + +WebBluetoothDeviceId FakeBluetoothDelegate::GrantServiceAccessPermission( + RenderFrameHost* frame, + const BluetoothDevice* device, + const blink::mojom::WebBluetoothRequestDeviceOptions* options) { + WebBluetoothDeviceId device_id = + GetOrCreateDeviceIdForDeviceAddress(frame, device->GetAddress()); + device_id_to_name_map_[device_id] = + device->GetName() ? *device->GetName() : std::string(); + GrantUnionOfServicesForDevice(device_id, options); + return device_id; +} + +bool FakeBluetoothDelegate::HasDevicePermission( + RenderFrameHost* frame, + const WebBluetoothDeviceId& device_id) { + return base::Contains(device_id_to_services_map_, device_id); +} + +bool FakeBluetoothDelegate::IsAllowedToAccessService( + RenderFrameHost* frame, + const WebBluetoothDeviceId& device_id, + const BluetoothUUID& service) { + auto id_to_services_it = device_id_to_services_map_.find(device_id); + if (id_to_services_it == device_id_to_services_map_.end()) + return false; + + return base::Contains(id_to_services_it->second, service); +} + +bool FakeBluetoothDelegate::IsAllowedToAccessAtLeastOneService( + RenderFrameHost* frame, + const WebBluetoothDeviceId& device_id) { + auto id_to_services_it = device_id_to_services_map_.find(device_id); + if (id_to_services_it == device_id_to_services_map_.end()) + return false; + + return !id_to_services_it->second.empty(); +} + +WebBluetoothDeviceId FakeBluetoothDelegate::GetOrCreateDeviceIdForDeviceAddress( + RenderFrameHost* frame, + const std::string& device_address) { + WebBluetoothDeviceId device_id; + auto& device_address_to_id_map = GetAddressToIdMapForOrigin(frame); + auto it = device_address_to_id_map.find(device_address); + if (it != device_address_to_id_map.end()) { + device_id = it->second; + } else { + device_id = WebBluetoothDeviceId::Create(); + device_address_to_id_map[device_address] = device_id; + } + return device_id; +} + +void FakeBluetoothDelegate::GrantUnionOfServicesForDevice( + const WebBluetoothDeviceId& device_id, + const blink::mojom::WebBluetoothRequestDeviceOptions* options) { + if (!options) + return; + + // Create an entry for |device_id| in |device_id_to_services_map_| to indicate + // that the site can attempt to GATT connect even if |options| does not + // contain any services. + base::flat_set<BluetoothUUID>& granted_services = + device_id_to_services_map_[device_id]; + if (options->filters) { + for (const blink::mojom::WebBluetoothLeScanFilterPtr& filter : + options->filters.value()) { + if (!filter->services) + continue; + + for (const BluetoothUUID& uuid : filter->services.value()) + granted_services.insert(uuid); + } + } + + for (const BluetoothUUID& uuid : options->optional_services) + granted_services.insert(uuid); +} + +FakeBluetoothDelegate::AddressToIdMap& +FakeBluetoothDelegate::GetAddressToIdMapForOrigin(RenderFrameHost* frame) { + auto* web_contents = WebContents::FromRenderFrameHost(frame); + auto origin_pair = + std::make_pair(frame->GetLastCommittedOrigin(), + web_contents->GetMainFrame()->GetLastCommittedOrigin()); + return device_address_to_id_map_for_origin_[origin_pair]; +} + +} // namespace content
diff --git a/content/shell/browser/web_test/fake_bluetooth_delegate.h b/content/shell/browser/web_test/fake_bluetooth_delegate.h new file mode 100644 index 0000000..1b80b79f --- /dev/null +++ b/content/shell/browser/web_test/fake_bluetooth_delegate.h
@@ -0,0 +1,103 @@ +// Copyright 2020 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_SHELL_BROWSER_WEB_TEST_FAKE_BLUETOOTH_DELEGATE_H_ +#define CONTENT_SHELL_BROWSER_WEB_TEST_FAKE_BLUETOOTH_DELEGATE_H_ + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "base/containers/flat_set.h" +#include "content/public/browser/bluetooth_delegate.h" +#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-forward.h" + +namespace blink { +class WebBluetoothDeviceId; +} // namespace blink + +namespace device { +class BluetoothDevice; +class BluetoothUUID; +} // namespace device + +namespace url { +class Origin; +} // namespace url + +namespace content { + +class RenderFrameHost; + +// Fakes Web Bluetooth permissions for web tests by emulating Chrome's +// implementation. +class FakeBluetoothDelegate : public BluetoothDelegate { + public: + FakeBluetoothDelegate(); + ~FakeBluetoothDelegate() override; + + // Move-only class. + FakeBluetoothDelegate(const FakeBluetoothDelegate&) = delete; + FakeBluetoothDelegate& operator=(const FakeBluetoothDelegate&) = delete; + + // BluetoothDelegate implementation: + blink::WebBluetoothDeviceId GetWebBluetoothDeviceId( + RenderFrameHost* frame, + const std::string& device_address) override; + std::string GetDeviceAddress(RenderFrameHost* frame, + const blink::WebBluetoothDeviceId&) override; + blink::WebBluetoothDeviceId AddScannedDevice( + RenderFrameHost* frame, + const std::string& device_address) override; + blink::WebBluetoothDeviceId GrantServiceAccessPermission( + RenderFrameHost* frame, + const device::BluetoothDevice* device, + const blink::mojom::WebBluetoothRequestDeviceOptions* options) override; + bool HasDevicePermission( + RenderFrameHost* frame, + const blink::WebBluetoothDeviceId& device_id) override; + bool IsAllowedToAccessService(RenderFrameHost* frame, + const blink::WebBluetoothDeviceId& device_id, + const device::BluetoothUUID& service) override; + bool IsAllowedToAccessAtLeastOneService( + RenderFrameHost* frame, + const blink::WebBluetoothDeviceId& device_id) override; + + private: + using AddressToIdMap = std::map<std::string, blink::WebBluetoothDeviceId>; + using OriginPair = std::pair<url::Origin, url::Origin>; + using IdToServicesMap = std::map<blink::WebBluetoothDeviceId, + base::flat_set<device::BluetoothUUID>>; + using IdToNameMap = std::map<blink::WebBluetoothDeviceId, std::string>; + + // Finds an existing WebBluetoothDeviceId for |device_address| for |frame| or + // creates a new ID for the Bluetooth device on the current frame. + blink::WebBluetoothDeviceId GetOrCreateDeviceIdForDeviceAddress( + RenderFrameHost* frame, + const std::string& device_address); + + // Adds the union of |options->filters->services| and + // |options->optional_services| to the allowed services for |device_id|. + void GrantUnionOfServicesForDevice( + const blink::WebBluetoothDeviceId& device_id, + const blink::mojom::WebBluetoothRequestDeviceOptions* options); + AddressToIdMap& GetAddressToIdMapForOrigin(RenderFrameHost* frame); + + // Maps origins to their own maps of device address to device ID. + // If a given origin and device address does not have an associated device ID, + // then the origin does not have permission to access the device. + std::map<OriginPair, AddressToIdMap> device_address_to_id_map_for_origin_; + + // These map device IDs to their set of allowed services and device names. + // Since devices IDs are randomly generated, it is very unlikely that two + // unique devices will share the same ID. Therefore, these maps contain all of + // the service permissions and device names from all of the origins. + IdToServicesMap device_id_to_services_map_; + IdToNameMap device_id_to_name_map_; +}; + +} // namespace content + +#endif // CONTENT_SHELL_BROWSER_WEB_TEST_FAKE_BLUETOOTH_DELEGATE_H_
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.cc b/content/shell/browser/web_test/web_test_content_browser_client.cc index b899d61..730790e 100644 --- a/content/shell/browser/web_test/web_test_content_browser_client.cc +++ b/content/shell/browser/web_test/web_test_content_browser_client.cc
@@ -30,6 +30,7 @@ #include "content/shell/browser/web_test/blink_test_controller.h" #include "content/shell/browser/web_test/fake_bluetooth_chooser.h" #include "content/shell/browser/web_test/fake_bluetooth_chooser_factory.h" +#include "content/shell/browser/web_test/fake_bluetooth_delegate.h" #include "content/shell/browser/web_test/mojo_web_test_helper.h" #include "content/shell/browser/web_test/web_test_bluetooth_fake_adapter_setter_impl.h" #include "content/shell/browser/web_test/web_test_browser_context.h" @@ -355,6 +356,16 @@ switches::kRunWebTests); } +BluetoothDelegate* WebTestContentBrowserClient::GetBluetoothDelegate() { + if (!fake_bluetooth_delegate_) + fake_bluetooth_delegate_ = std::make_unique<FakeBluetoothDelegate>(); + return fake_bluetooth_delegate_.get(); +} + +void WebTestContentBrowserClient::ResetFakeBluetoothDelegate() { + fake_bluetooth_delegate_.reset(); +} + content::TtsControllerDelegate* WebTestContentBrowserClient::GetTtsControllerDelegate() { return WebTestTtsControllerDelegate::GetInstance();
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.h b/content/shell/browser/web_test/web_test_content_browser_client.h index 0992408..aaf3b8fe 100644 --- a/content/shell/browser/web_test/web_test_content_browser_client.h +++ b/content/shell/browser/web_test/web_test_content_browser_client.h
@@ -6,6 +6,8 @@ #define CONTENT_SHELL_BROWSER_WEB_TEST_WEB_TEST_CONTENT_BROWSER_CLIENT_H_ #include <memory> +#include <string> +#include <vector> #include "content/public/common/client_hints.mojom.h" #include "content/shell/browser/shell_content_browser_client.h" @@ -20,6 +22,7 @@ class FakeBluetoothChooser; class FakeBluetoothChooserFactory; +class FakeBluetoothDelegate; class MockClipboardHost; class MockPlatformNotificationService; class WebTestBrowserContext; @@ -39,6 +42,7 @@ // Retrieves the last created FakeBluetoothChooser instance. std::unique_ptr<FakeBluetoothChooser> GetNextFakeBluetoothChooser(); + void ResetFakeBluetoothDelegate(); // ContentBrowserClient overrides. void RenderProcessWillLaunch(RenderProcessHost* host) override; @@ -75,7 +79,7 @@ service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) override; bool CanAcceptUntrustedExchangesIfNeeded() override; - + BluetoothDelegate* GetBluetoothDelegate() override; content::TtsControllerDelegate* GetTtsControllerDelegate() override; content::TtsPlatform* GetTtsPlatform() override; bool CanEnterFullscreenWithoutUserActivation() override; @@ -112,6 +116,7 @@ // Stores the FakeBluetoothChooserFactory that produces FakeBluetoothChoosers. std::unique_ptr<FakeBluetoothChooserFactory> fake_bluetooth_chooser_factory_; + std::unique_ptr<FakeBluetoothDelegate> fake_bluetooth_delegate_; std::unique_ptr<MockClipboardHost> mock_clipboard_host_; };
diff --git a/content/test/data/accessibility/css/table-data-display-other-expected-blink.txt b/content/test/data/accessibility/css/table-data-display-other-expected-blink.txt new file mode 100644 index 0000000..a6bd31b --- /dev/null +++ b/content/test/data/accessibility/css/table-data-display-other-expected-blink.txt
@@ -0,0 +1,25 @@ +rootWebArea +++genericContainer ignored +++++table tableRowCount=2 tableColumnCount=3 +++++++rowGroup ignored +++++++++row tableRowIndex=0 +++++++++++columnHeader name='1' tableCellColumnIndex=0 tableCellRowIndex=0 +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++columnHeader name='2' tableCellColumnIndex=1 tableCellRowIndex=0 +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++columnHeader name='3' tableCellColumnIndex=2 tableCellRowIndex=0 +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++rowGroup ignored +++++++++row tableRowIndex=1 +++++++++++cell name='a' tableCellColumnIndex=0 tableCellRowIndex=1 +++++++++++++staticText name='a' +++++++++++++++inlineTextBox name='a' +++++++++++cell name='b' tableCellColumnIndex=1 tableCellRowIndex=1 +++++++++++++staticText name='b' +++++++++++++++inlineTextBox name='b' +++++++++++cell name='c' tableCellColumnIndex=2 tableCellRowIndex=1 +++++++++++++staticText name='c' +++++++++++++++inlineTextBox name='c'
diff --git a/content/test/data/accessibility/css/table-data-display-other.html b/content/test/data/accessibility/css/table-data-display-other.html new file mode 100644 index 0000000..948b224 --- /dev/null +++ b/content/test/data/accessibility/css/table-data-display-other.html
@@ -0,0 +1,26 @@ +<!-- +@BLINK-ALLOW:tableColumnCount* +@BLINK-ALLOW:tableRowCount* +@BLINK-ALLOW:table*Index* +--> +<!-- Ensure that a table with display styles and other semantic table markup + is still exposed as a data table.. --> +<style> +table, thead, tbody, tr, td { display: flex; } +</style> +<table> + <thead> + <tr> + <th>1</th> + <th>2</th> + <th>3</th> + </tr> + </thead> + <tbody> + <tr> + <td>a</td> + <td>b</td> + <td>c</td> + </tr> + </tbody> +</table>
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 4de85b3..0a00b8c 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
@@ -201,6 +201,7 @@ # Win / NVIDIA GeForce GTX 1660 / D3D11 flaky failures crbug.com/angleproject/4377 [ d3d11 win nvidia-0x2184 ] conformance/attribs/gl-vertex-attrib-unconsumed-out-of-bounds.html [ RetryOnFailure ] +crbug.com/1057635 [ d3d11 win nvidia-0x2184 ] deqp/functional/gles3/framebufferblit/depth_stencil.html [ RetryOnFailure ] # WIN / OpenGL / NVIDIA failures crbug.com/963205 [ win nvidia opengl passthrough ] conformance/extensions/webgl-compressed-texture-s3tc.html [ RetryOnFailure ]
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md index 5ace1f2..5c8f0b3 100644 --- a/docs/threading_and_tasks.md +++ b/docs/threading_and_tasks.md
@@ -455,8 +455,10 @@ Methods that take `base::TaskTraits` can be be passed `{}` when default traits are sufficient. Default traits are appropriate for tasks that: -- Don’t block (ref. MayBlock and WithBaseSyncPrimitives). -- Prefer inheriting the current priority to specifying their own. +- Don’t block (ref. MayBlock and WithBaseSyncPrimitives); +- Pertain to user-blocking activity; + (explicitly or implicitly by having an ordering dependency with a component + that does) - Can either block shutdown or be skipped on shutdown (thread pool is free to choose a fitting default). Tasks that don’t match this description must be posted with explicit TaskTraits. @@ -470,14 +472,12 @@ Below are some examples of how to specify `base::TaskTraits`. ```cpp -// This task has no explicit TaskTraits. It cannot block. Its priority -// is inherited from the calling context (e.g. if it is posted from -// a BEST_EFFORT task, it will have a BEST_EFFORT priority). It will either -// block shutdown or be skipped on shutdown. +// This task has no explicit TaskTraits. It cannot block. Its priority is +// USER_BLOCKING. It will either block shutdown or be skipped on shutdown. base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(...)); -// This task has the highest priority. The thread pool will try to -// run it before USER_VISIBLE and BEST_EFFORT tasks. +// This task has the highest priority. The thread pool will schedule it before +// USER_VISIBLE and BEST_EFFORT tasks. base::ThreadPool::PostTask( FROM_HERE, {base::TaskPriority::USER_BLOCKING}, base::BindOnce(...));
diff --git a/infra/config/buckets/ci.star b/infra/config/buckets/ci.star index d64145e..7594814 100644 --- a/infra/config/buckets/ci.star +++ b/infra/config/buckets/ci.star
@@ -1186,7 +1186,7 @@ ci.fyi_mac_builder( name = 'Mac Builder Next', cores = None, - os = os.MAC_10_14, + os = None, ) ci.fyi_mac_builder(
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index 8effa41..e31660a 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -3452,7 +3452,6 @@ swarming_tags: "vpython:native-python-wrapper" dimensions: "builder:Mac Builder Next" dimensions: "cpu:x86-64" - dimensions: "os:Mac-10.14" recipe: < name: "chromium" cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
diff --git a/ios/build/bots/OWNERS b/ios/build/bots/OWNERS index e39778a..1ed7b5b 100644 --- a/ios/build/bots/OWNERS +++ b/ios/build/bots/OWNERS
@@ -1,5 +1,4 @@ justincohen@chromium.org -kkhorimoto@chromium.org rohitrao@chromium.org sdefresne@chromium.org sergeyberezin@chromium.org
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 2e45cee..fe0ecaa 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -133,7 +133,6 @@ #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.h" -#import "ios/chrome/browser/url_loading/app_url_loading_service.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/url_loading/url_loading_service.h" #import "ios/chrome/browser/url_loading/url_loading_service_factory.h" @@ -417,7 +416,6 @@ @implementation MainController // Defined by MainControllerGuts. -@synthesize appURLLoadingService; @synthesize dismissingTabSwitcher = _dismissingTabSwitcher; @synthesize restoreHelper = _restoreHelper; @@ -605,16 +603,14 @@ // This is per-window code. DCHECK(!self.browserViewWrangler); - - self.appURLLoadingService = new AppUrlLoadingService(); - self.appURLLoadingService->SetDelegate(self.sceneController); + DCHECK(self.sceneController.appURLLoadingService); self.browserViewWrangler = [[BrowserViewWrangler alloc] initWithBrowserState:self.mainBrowserState webStateListObserver:self.sceneController applicationCommandEndpoint:self.sceneController browsingDataCommandEndpoint:self - appURLLoadingService:self.appURLLoadingService]; + appURLLoadingService:self.sceneController.appURLLoadingService]; // Ensure the main tab model is created. This also creates the BVC. [self.browserViewWrangler createMainBrowser]; @@ -780,12 +776,21 @@ } - (void)stopChromeMain { + // This code is per-window. + // Teardown UI state that is associated with scenes. [self.sceneController teardownUI]; [_mainCoordinator stop]; _mainCoordinator = nil; + // Invariant: The UI is stopped before the model is shutdown. + DCHECK(!_mainCoordinator); + [self.browserViewWrangler shutdown]; + self.browserViewWrangler = nil; + + // End of per-window code. + [_spotlightManager shutdown]; _spotlightManager = nil; @@ -800,11 +805,6 @@ self.mainBrowserState)); } - // Invariant: The UI is stopped before the model is shutdown. - DCHECK(!_mainCoordinator); - [self.browserViewWrangler shutdown]; - self.browserViewWrangler = nil; - _extensionSearchEngineDataUpdater = nullptr; ios::GetChromeBrowserProvider()
diff --git a/ios/chrome/app/main_controller_guts.h b/ios/chrome/app/main_controller_guts.h index 3c09eae..91c67f7 100644 --- a/ios/chrome/app/main_controller_guts.h +++ b/ios/chrome/app/main_controller_guts.h
@@ -19,17 +19,12 @@ @class TabGridCoordinator; @protocol BrowserInterfaceProvider; @protocol TabSwitcher; -class AppUrlLoadingService; // TODO(crbug.com/1012697): Remove this protocol when SceneController is // operational. Move the private internals back into MainController, and pass // ownership of Scene-related objects to SceneController. @protocol MainControllerGuts -// The application level component for url loading. Is passed down to -// browser state level UrlLoadingService instances. -@property(nonatomic, assign) AppUrlLoadingService* appURLLoadingService; - // If YES, the tab switcher is currently active. @property(nonatomic, assign, getter=isTabSwitcherActive) BOOL tabSwitcherIsActive;
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm index 2ac5bbc..e0e48ef 100644 --- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm +++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -36,7 +36,6 @@ #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" #include "ios/chrome/browser/send_tab_to_self/send_tab_to_self_client_service_factory.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h" #include "ios/chrome/browser/signin/about_signin_internals_factory.h" #include "ios/chrome/browser/signin/account_consistency_service_factory.h" #include "ios/chrome/browser/signin/account_reconcilor_factory.h" @@ -121,7 +120,6 @@ SigninClientFactory::GetInstance(); SnapshotCacheFactory::GetInstance(); SyncSetupServiceFactory::GetInstance(); - TabRestoreServiceDelegateImplIOSFactory::GetInstance(); TextToSpeechPlaybackControllerFactory::GetInstance(); TranslateAcceptLanguagesFactory::GetInstance(); UnifiedConsentServiceFactory::GetInstance();
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper.mm index 6783519b..702ba68 100644 --- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper.mm +++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper.mm
@@ -25,7 +25,8 @@ // Returns true if navigation URL repesents Chrome's New Tab Page. bool IsNptUrl(const GURL& url) { return url.GetOrigin() == kChromeUINewTabURL || - (url.SchemeIs(url::kAboutScheme) && url.path() == "//newtab"); + (url.SchemeIs(url::kAboutScheme) && + (url.path() == "//newtab" || url.path() == "//newtab/")); } }
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm index ba200c40..757f48b 100644 --- a/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm +++ b/ios/chrome/browser/crash_report/breadcrumbs/breadcrumb_manager_tab_helper_unittest.mm
@@ -146,6 +146,25 @@ << events.front(); } +// Tests metadata for about://newtab/ NTP navigation. +TEST_F(BreadcrumbManagerTabHelperTest, AboutNewTabNavigationStart2) { + BreadcrumbManagerTabHelper::CreateForWebState(&first_web_state_); + ASSERT_EQ(0ul, breadcrumb_service_->GetEvents(0).size()); + + web::FakeNavigationContext context; + context.SetUrl(GURL("about://newtab/")); + first_web_state_.OnNavigationStarted(&context); + std::list<std::string> events = breadcrumb_service_->GetEvents(0); + ASSERT_EQ(1ul, events.size()); + + EXPECT_NE(std::string::npos, events.front().find(base::StringPrintf( + "%s%lld", kBreadcrumbDidStartNavigation, + context.GetNavigationId()))) + << events.front(); + EXPECT_NE(std::string::npos, events.front().find(kBreadcrumbNtpNavigation)) + << events.front(); +} + // Tests unique ID in DidStartNavigation and DidStartNavigation. TEST_F(BreadcrumbManagerTabHelperTest, NavigationUniqueId) { BreadcrumbManagerTabHelper::CreateForWebState(&first_web_state_);
diff --git a/ios/chrome/browser/main/BUILD.gn b/ios/chrome/browser/main/BUILD.gn index 48c9fde05..a97707c 100644 --- a/ios/chrome/browser/main/BUILD.gn +++ b/ios/chrome/browser/main/BUILD.gn
@@ -43,6 +43,7 @@ "//ios/chrome/browser/crash_report/breadcrumbs:feature_flags", "//ios/chrome/browser/infobars/overlays/browser_agent:browser_agent_util", "//ios/chrome/browser/metrics:metrics_browser_agent", + "//ios/chrome/browser/sessions", "//ios/chrome/browser/sessions:restoration_agent", "//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/sessions:session_service",
diff --git a/ios/chrome/browser/main/browser_agent_util.mm b/ios/chrome/browser/main/browser_agent_util.mm index 1b9e8df..618c022d 100644 --- a/ios/chrome/browser/main/browser_agent_util.mm +++ b/ios/chrome/browser/main/browser_agent_util.mm
@@ -10,6 +10,7 @@ #include "ios/chrome/browser/crash_report/breadcrumbs/features.h" #include "ios/chrome/browser/infobars/overlays/browser_agent/infobar_overlay_browser_agent_util.h" #import "ios/chrome/browser/metrics/tab_usage_recorder_browser_agent.h" +#import "ios/chrome/browser/sessions/live_tab_context_browser_agent.h" #import "ios/chrome/browser/sessions/session_restoration_browser_agent.h" #import "ios/chrome/browser/sessions/session_service_ios.h" #include "ios/chrome/browser/tabs/synced_window_delegate_browser_agent.h" @@ -25,6 +26,7 @@ if (base::FeatureList::IsEnabled(kLogBreadcrumbs)) { BreadcrumbManagerBrowserAgent::CreateForBrowser(browser); } + LiveTabContextBrowserAgent::CreateForBrowser(browser); TabInsertionBrowserAgent::CreateForBrowser(browser); AttachInfobarOverlayBrowserAgent(browser); SyncedWindowDelegateBrowserAgent::CreateForBrowser(browser);
diff --git a/ios/chrome/browser/sessions/BUILD.gn b/ios/chrome/browser/sessions/BUILD.gn index fc3ea07..6086716e 100644 --- a/ios/chrome/browser/sessions/BUILD.gn +++ b/ios/chrome/browser/sessions/BUILD.gn
@@ -11,20 +11,19 @@ "ios_chrome_tab_restore_service_client.mm", "ios_chrome_tab_restore_service_factory.cc", "ios_chrome_tab_restore_service_factory.h", - "tab_restore_service_delegate_impl_ios.h", - "tab_restore_service_delegate_impl_ios.mm", - "tab_restore_service_delegate_impl_ios_factory.h", - "tab_restore_service_delegate_impl_ios_factory.mm", + "live_tab_context_browser_agent.h", + "live_tab_context_browser_agent.mm", ] + public_deps = [ "//components/sessions" ] deps = [ ":serialisation", "//base", "//components/keyed_service/core", "//components/keyed_service/ios", - "//components/sessions", "//components/tab_groups", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/main:public", "//ios/chrome/browser/tabs", "//ios/chrome/browser/web_state_list", "//ios/public/provider/chrome/browser",
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm index 8e72ac4..d2c3a35 100644 --- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm +++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
@@ -11,11 +11,11 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h" #include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h" +#include "ios/chrome/browser/main/browser.h" +#include "ios/chrome/browser/main/browser_list.h" +#include "ios/chrome/browser/main/browser_list_factory.h" +#include "ios/chrome/browser/sessions/live_tab_context_browser_agent.h" #include "ios/chrome/browser/tabs/synced_window_delegate_browser_agent.h" -#import "ios/chrome/browser/tabs/tab_model.h" -#import "ios/chrome/browser/tabs/tab_model_list.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #include "url/gurl.h" @@ -26,7 +26,7 @@ namespace { sessions::LiveTabContext* FindLiveTabContextWithCondition( - base::RepeatingCallback<bool(TabModel*)> condition) { + base::RepeatingCallback<bool(Browser*)> condition) { std::vector<ChromeBrowserState*> browser_states = GetApplicationContext() ->GetChromeBrowserStateManager() @@ -34,28 +34,17 @@ for (ChromeBrowserState* browser_state : browser_states) { DCHECK(!browser_state->IsOffTheRecord()); - NSArray<TabModel*>* tab_models; - - tab_models = TabModelList::GetTabModelsForChromeBrowserState(browser_state); - for (TabModel* tab_model : tab_models) { - if (condition.Run(tab_model)) { - return TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState( - browser_state); + BrowserList* browsers = + BrowserListFactory::GetForBrowserState(browser_state); + for (Browser* browser : browsers->AllRegularBrowsers()) { + if (condition.Run(browser)) { + return LiveTabContextBrowserAgent::FromBrowser(browser); } } - if (!browser_state->HasOffTheRecordChromeBrowserState()) - continue; - - ChromeBrowserState* otr_browser_state = - browser_state->GetOffTheRecordChromeBrowserState(); - - tab_models = - TabModelList::GetTabModelsForChromeBrowserState(otr_browser_state); - for (TabModel* tab_model : tab_models) { - if (condition.Run(tab_model)) { - return TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState( - browser_state); + for (Browser* browser : browsers->AllIncognitoBrowsers()) { + if (condition.Run(browser)) { + return LiveTabContextBrowserAgent::FromBrowser(browser); } } } @@ -76,8 +65,8 @@ const gfx::Rect& /* bounds */, ui::WindowShowState /* show_state */, const std::string& /* workspace */) { - return TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState( - browser_state_); + NOTREACHED() << "Tab restore service attempting to create a new window."; + return nullptr; } sessions::LiveTabContext* @@ -87,8 +76,8 @@ static_cast<const sessions::IOSLiveTab*>(tab); return FindLiveTabContextWithCondition(base::Bind( - [](const web::WebState* web_state, TabModel* tab_model) { - WebStateList* web_state_list = tab_model.webStateList; + [](const web::WebState* web_state, Browser* browser) { + WebStateList* web_state_list = browser->GetWebStateList(); const int index = web_state_list->GetIndexOfWebState(web_state); return index != WebStateList::kInvalidIndex; }, @@ -99,9 +88,10 @@ IOSChromeTabRestoreServiceClient::FindLiveTabContextWithID( SessionID desired_id) { return FindLiveTabContextWithCondition(base::Bind( - [](SessionID desired_id, TabModel* tab_model) { - DCHECK(tab_model.syncedWindowDelegate); - return tab_model.syncedWindowDelegate->GetSessionId() == desired_id; + [](SessionID desired_id, Browser* browser) { + SyncedWindowDelegateBrowserAgent* syncedWindowDelegate = + SyncedWindowDelegateBrowserAgent::FromBrowser(browser); + return syncedWindowDelegate->GetSessionId() == desired_id; }, desired_id)); }
diff --git a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h similarity index 69% rename from ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h rename to ios/chrome/browser/sessions/live_tab_context_browser_agent.h index 6504043..792ffd3 100644 --- a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h +++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h
@@ -2,33 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_DELEGATE_IMPL_IOS_H_ -#define IOS_CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_DELEGATE_IMPL_IOS_H_ +#ifndef IOS_CHROME_BROWSER_SESSIONS_LIVE_TAB_CONTEXT_BROWSER_AGENT_H_ +#define IOS_CHROME_BROWSER_SESSIONS_LIVE_TAB_CONTEXT_BROWSER_AGENT_H_ #include <string> #include <vector> -#include "base/macros.h" #include "components/keyed_service/core/keyed_service.h" #include "components/sessions/core/live_tab_context.h" -#include "components/tab_groups/tab_group_id.h" -#include "components/tab_groups/tab_group_visual_data.h" +#include "ios/chrome/browser/main/browser_observer.h" +#include "ios/chrome/browser/main/browser_user_data.h" -class ChromeBrowserState; class WebStateList; // Implementation of sessions::LiveTabContext which uses an instance // of TabModel in order to fulfil its duties. -class TabRestoreServiceDelegateImplIOS : public sessions::LiveTabContext, - public KeyedService { +class LiveTabContextBrowserAgent + : public sessions::LiveTabContext, + public BrowserUserData<LiveTabContextBrowserAgent> { public: - explicit TabRestoreServiceDelegateImplIOS(ChromeBrowserState* browser_state); - ~TabRestoreServiceDelegateImplIOS() override; + // Not copiable or movable. + LiveTabContextBrowserAgent(const LiveTabContextBrowserAgent&) = delete; + LiveTabContextBrowserAgent& operator=(const LiveTabContextBrowserAgent&) = + delete; + ~LiveTabContextBrowserAgent() override; - // Overridden from KeyedService: - void Shutdown() override {} - - // Overridden from sessions::LiveTabContext: + // Sessions::LiveTabContext: void ShowBrowserWindow() override; SessionID GetSessionID() const override; int GetTabCount() const override; @@ -70,13 +69,13 @@ void CloseTab() override; private: - // Retrieves the current |WebStateList| corresponding to |browser_state_|; - WebStateList* GetWebStateList() const; + explicit LiveTabContextBrowserAgent(Browser* browser); + friend class BrowserUserData<LiveTabContextBrowserAgent>; + BROWSER_USER_DATA_KEY_DECL(); - ChromeBrowserState* browser_state_; // weak + ChromeBrowserState* browser_state_; + WebStateList* web_state_list_; SessionID session_id_; - - DISALLOW_COPY_AND_ASSIGN(TabRestoreServiceDelegateImplIOS); }; -#endif // IOS_CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_DELEGATE_IMPL_IOS_H_ +#endif // IOS_CHROME_BROWSER_SESSIONS_LIVE_TAB_CONTEXT_BROWSER_AGENT_H_
diff --git a/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm new file mode 100644 index 0000000..4123db6 --- /dev/null +++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm
@@ -0,0 +1,146 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/sessions/live_tab_context_browser_agent.h" + +#include <memory> +#include <utility> + +#include "base/logging.h" +#include "base/optional.h" +#include "base/strings/sys_string_conversions.h" +#include "components/sessions/core/session_types.h" +#include "components/tab_groups/tab_group_id.h" +#include "components/tab_groups/tab_group_visual_data.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/sessions/session_util.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_opener.h" +#import "ios/web/public/web_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +BROWSER_USER_DATA_KEY_IMPL(LiveTabContextBrowserAgent) + +LiveTabContextBrowserAgent::LiveTabContextBrowserAgent(Browser* browser) + : browser_state_(browser->GetBrowserState()), + web_state_list_(browser->GetWebStateList()), + session_id_(SessionID::NewUnique()) {} + +LiveTabContextBrowserAgent::~LiveTabContextBrowserAgent() {} + +void LiveTabContextBrowserAgent::ShowBrowserWindow() { + // No need to do anything here, as the singleton browser "window" is already + // shown. +} + +SessionID LiveTabContextBrowserAgent::GetSessionID() const { + return session_id_; +} + +int LiveTabContextBrowserAgent::GetTabCount() const { + return web_state_list_->count(); +} + +int LiveTabContextBrowserAgent::GetSelectedIndex() const { + return web_state_list_->active_index(); +} + +std::string LiveTabContextBrowserAgent::GetAppName() const { + return std::string(); +} + +sessions::LiveTab* LiveTabContextBrowserAgent::GetLiveTabAt(int index) const { + return nullptr; +} + +sessions::LiveTab* LiveTabContextBrowserAgent::GetActiveLiveTab() const { + return nullptr; +} + +bool LiveTabContextBrowserAgent::IsTabPinned(int index) const { + // Not supported by iOS. + return false; +} + +base::Optional<tab_groups::TabGroupId> +LiveTabContextBrowserAgent::GetTabGroupForTab(int index) const { + // Not supported by iOS. + return base::nullopt; +} + +const tab_groups::TabGroupVisualData* +LiveTabContextBrowserAgent::GetVisualDataForGroup( + const tab_groups::TabGroupId& group) const { + // Since we never return a group from GetTabGroupForTab(), this should never + // be called. + NOTREACHED(); + return nullptr; +} + +void LiveTabContextBrowserAgent::SetVisualDataForGroup( + const tab_groups::TabGroupId& group, + const tab_groups::TabGroupVisualData& visual_data) { + // Not supported on iOS. +} + +const gfx::Rect LiveTabContextBrowserAgent::GetRestoredBounds() const { + // Not supported by iOS. + return gfx::Rect(); +} + +ui::WindowShowState LiveTabContextBrowserAgent::GetRestoredState() const { + // Not supported by iOS. + return ui::SHOW_STATE_NORMAL; +} + +std::string LiveTabContextBrowserAgent::GetWorkspace() const { + // Not supported by iOS. + return std::string(); +} + +sessions::LiveTab* LiveTabContextBrowserAgent::AddRestoredTab( + const std::vector<sessions::SerializedNavigationEntry>& navigations, + int tab_index, + int selected_navigation, + const std::string& extension_app_id, + base::Optional<tab_groups::TabGroupId> group, + const tab_groups::TabGroupVisualData& group_visual_data, + bool select, + bool pin, + bool from_last_session, + const sessions::PlatformSpecificTabData* tab_platform_data, + const std::string& user_agent_override) { + // TODO(crbug.com/661636): Handle tab-switch animation somehow... + web_state_list_->InsertWebState( + tab_index, + session_util::CreateWebStateWithNavigationEntries( + browser_state_, selected_navigation, navigations), + WebStateList::INSERT_FORCE_INDEX | WebStateList::INSERT_ACTIVATE, + WebStateOpener()); + return nullptr; +} + +sessions::LiveTab* LiveTabContextBrowserAgent::ReplaceRestoredTab( + const std::vector<sessions::SerializedNavigationEntry>& navigations, + base::Optional<tab_groups::TabGroupId> group, + int selected_navigation, + bool from_last_session, + const std::string& extension_app_id, + const sessions::PlatformSpecificTabData* tab_platform_data, + const std::string& user_agent_override) { + web_state_list_->ReplaceWebStateAt( + web_state_list_->active_index(), + session_util::CreateWebStateWithNavigationEntries( + browser_state_, selected_navigation, navigations)); + + return nullptr; +} + +void LiveTabContextBrowserAgent::CloseTab() { + web_state_list_->CloseWebStateAt(web_state_list_->active_index(), + WebStateList::CLOSE_USER_ACTION); +}
diff --git a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm deleted file mode 100644 index a3eee23..0000000 --- a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.mm +++ /dev/null
@@ -1,156 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h" - -#include <memory> -#include <utility> - -#include "base/logging.h" -#include "base/optional.h" -#include "base/strings/sys_string_conversions.h" -#include "components/sessions/core/session_types.h" -#include "components/tab_groups/tab_group_id.h" -#include "components/tab_groups/tab_group_visual_data.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/sessions/session_util.h" -#import "ios/chrome/browser/tabs/tab_model.h" -#import "ios/chrome/browser/tabs/tab_model_list.h" -#import "ios/chrome/browser/web_state_list/web_state_list.h" -#import "ios/chrome/browser/web_state_list/web_state_opener.h" -#import "ios/web/public/web_state.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -TabRestoreServiceDelegateImplIOS::TabRestoreServiceDelegateImplIOS( - ChromeBrowserState* browser_state) - : browser_state_(browser_state), session_id_(SessionID::NewUnique()) {} - -TabRestoreServiceDelegateImplIOS::~TabRestoreServiceDelegateImplIOS() {} - -WebStateList* TabRestoreServiceDelegateImplIOS::GetWebStateList() const { - TabModel* tab_model = - TabModelList::GetLastActiveTabModelForChromeBrowserState(browser_state_); - DCHECK([tab_model webStateList]); - return [tab_model webStateList]; -} - -void TabRestoreServiceDelegateImplIOS::ShowBrowserWindow() { - // No need to do anything here, as the singleton browser "window" is already - // shown. -} - -SessionID TabRestoreServiceDelegateImplIOS::GetSessionID() const { - return session_id_; -} - -int TabRestoreServiceDelegateImplIOS::GetTabCount() const { - return GetWebStateList()->count(); -} - -int TabRestoreServiceDelegateImplIOS::GetSelectedIndex() const { - return GetWebStateList()->active_index(); -} - -std::string TabRestoreServiceDelegateImplIOS::GetAppName() const { - return std::string(); -} - -sessions::LiveTab* TabRestoreServiceDelegateImplIOS::GetLiveTabAt( - int index) const { - return nullptr; -} - -sessions::LiveTab* TabRestoreServiceDelegateImplIOS::GetActiveLiveTab() const { - return nullptr; -} - -bool TabRestoreServiceDelegateImplIOS::IsTabPinned(int index) const { - // Not supported by iOS. - return false; -} - -base::Optional<tab_groups::TabGroupId> -TabRestoreServiceDelegateImplIOS::GetTabGroupForTab(int index) const { - // Not supported by iOS. - return base::nullopt; -} - -const tab_groups::TabGroupVisualData* -TabRestoreServiceDelegateImplIOS::GetVisualDataForGroup( - const tab_groups::TabGroupId& group) const { - // Since we never return a group from GetTabGroupForTab(), this should never - // be called. - NOTREACHED(); - return nullptr; -} - -void TabRestoreServiceDelegateImplIOS::SetVisualDataForGroup( - const tab_groups::TabGroupId& group, - const tab_groups::TabGroupVisualData& visual_data) { - // Not supported on iOS. -} - -const gfx::Rect TabRestoreServiceDelegateImplIOS::GetRestoredBounds() const { - // Not supported by iOS. - return gfx::Rect(); -} - -ui::WindowShowState TabRestoreServiceDelegateImplIOS::GetRestoredState() const { - // Not supported by iOS. - return ui::SHOW_STATE_NORMAL; -} - -std::string TabRestoreServiceDelegateImplIOS::GetWorkspace() const { - // Not supported by iOS. - return std::string(); -} - -sessions::LiveTab* TabRestoreServiceDelegateImplIOS::AddRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - int tab_index, - int selected_navigation, - const std::string& extension_app_id, - base::Optional<tab_groups::TabGroupId> group, - const tab_groups::TabGroupVisualData& group_visual_data, - bool select, - bool pin, - bool from_last_session, - const sessions::PlatformSpecificTabData* tab_platform_data, - const std::string& user_agent_override) { - // TODO(crbug.com/661636): Handle tab-switch animation somehow... - WebStateList* web_state_list = GetWebStateList(); - web_state_list->InsertWebState( - tab_index, - session_util::CreateWebStateWithNavigationEntries( - browser_state_, selected_navigation, navigations), - WebStateList::INSERT_FORCE_INDEX | WebStateList::INSERT_ACTIVATE, - WebStateOpener()); - return nullptr; -} - -sessions::LiveTab* TabRestoreServiceDelegateImplIOS::ReplaceRestoredTab( - const std::vector<sessions::SerializedNavigationEntry>& navigations, - base::Optional<tab_groups::TabGroupId> group, - int selected_navigation, - bool from_last_session, - const std::string& extension_app_id, - const sessions::PlatformSpecificTabData* tab_platform_data, - const std::string& user_agent_override) { - WebStateList* web_state_list = GetWebStateList(); - web_state_list->ReplaceWebStateAt( - web_state_list->active_index(), - session_util::CreateWebStateWithNavigationEntries( - browser_state_, selected_navigation, navigations)); - - return nullptr; -} - -void TabRestoreServiceDelegateImplIOS::CloseTab() { - WebStateList* web_state_list = GetWebStateList(); - web_state_list->CloseWebStateAt(web_state_list->active_index(), - WebStateList::CLOSE_USER_ACTION); -}
diff --git a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h deleted file mode 100644 index 4f38c54..0000000 --- a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h +++ /dev/null
@@ -1,38 +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 IOS_CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_DELEGATE_IMPL_IOS_FACTORY_H_ -#define IOS_CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_DELEGATE_IMPL_IOS_FACTORY_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/no_destructor.h" -#include "components/keyed_service/ios/browser_state_keyed_service_factory.h" - -class ChromeBrowserState; -class TabRestoreServiceDelegateImplIOS; - -class TabRestoreServiceDelegateImplIOSFactory - : public BrowserStateKeyedServiceFactory { - public: - static TabRestoreServiceDelegateImplIOS* GetForBrowserState( - ChromeBrowserState* browser_state); - - static TabRestoreServiceDelegateImplIOSFactory* GetInstance(); - - private: - friend class base::NoDestructor<TabRestoreServiceDelegateImplIOSFactory>; - - TabRestoreServiceDelegateImplIOSFactory(); - ~TabRestoreServiceDelegateImplIOSFactory() override; - - // BrowserStateKeyedServiceFactory implementation. - std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; - - DISALLOW_COPY_AND_ASSIGN(TabRestoreServiceDelegateImplIOSFactory); -}; - -#endif // IOS_CHROME_BROWSER_SESSIONS_TAB_RESTORE_SERVICE_DELEGATE_IMPL_IOS_FACTORY_H_
diff --git a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.mm b/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.mm deleted file mode 100644 index 1bfe79f..0000000 --- a/ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.mm +++ /dev/null
@@ -1,47 +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 "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h" - -#include <memory> - -#include "base/no_destructor.h" -#include "components/keyed_service/ios/browser_state_dependency_manager.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -// static -TabRestoreServiceDelegateImplIOS* -TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState( - ChromeBrowserState* browser_state) { - return static_cast<TabRestoreServiceDelegateImplIOS*>( - GetInstance()->GetServiceForBrowserState(browser_state, true)); -} - -// static -TabRestoreServiceDelegateImplIOSFactory* -TabRestoreServiceDelegateImplIOSFactory::GetInstance() { - static base::NoDestructor<TabRestoreServiceDelegateImplIOSFactory> instance; - return instance.get(); -} - -TabRestoreServiceDelegateImplIOSFactory:: - TabRestoreServiceDelegateImplIOSFactory() - : BrowserStateKeyedServiceFactory( - "TabRestoreServiceDelegateImplIOS", - BrowserStateDependencyManager::GetInstance()) {} - -TabRestoreServiceDelegateImplIOSFactory:: - ~TabRestoreServiceDelegateImplIOSFactory() {} - -std::unique_ptr<KeyedService> -TabRestoreServiceDelegateImplIOSFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - return std::make_unique<TabRestoreServiceDelegateImplIOS>( - ChromeBrowserState::FromBrowserState(context)); -}
diff --git a/ios/chrome/browser/sync/profile_sync_service_factory.cc b/ios/chrome/browser/sync/profile_sync_service_factory.cc index 488a2bed..e5457e6c 100644 --- a/ios/chrome/browser/sync/profile_sync_service_factory.cc +++ b/ios/chrome/browser/sync/profile_sync_service_factory.cc
@@ -34,7 +34,6 @@ #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" -#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #include "ios/chrome/browser/signin/about_signin_internals_factory.h" #include "ios/chrome/browser/signin/identity_manager_factory.h" #include "ios/chrome/browser/sync/consent_auditor_factory.h"
diff --git a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/BUILD.gn b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/BUILD.gn index 9be29c9..a3fd4159 100644 --- a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/BUILD.gn
@@ -9,7 +9,34 @@ sources = [ "advanced_settings_signin_coordinator.h", "advanced_settings_signin_coordinator.mm", + "advanced_settings_signin_mediator.h", + "advanced_settings_signin_mediator.mm", + "advanced_settings_signin_navigation_controller.h", + "advanced_settings_signin_navigation_controller.mm", ] public_deps = [ "//ios/chrome/browser/ui/authentication/signin:signin_headers" ] + deps = [ + ":constants", + "//components/sync", + "//components/unified_consent", + "//ios/chrome/app/strings", + "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/signin", + "//ios/chrome/browser/sync", + "//ios/chrome/browser/ui/alert_coordinator", + "//ios/chrome/browser/ui/authentication/signin:signin_protected", + "//ios/chrome/browser/ui/settings:settings_controller_protocol", + "//ios/chrome/browser/ui/settings/google_services:constants", + "//ios/web/public", + "//ui/base", + ] +} + +source_set("constants") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "advanced_settings_signin_constants.h", + "advanced_settings_signin_constants.mm", + ] }
diff --git a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.h b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.h new file mode 100644 index 0000000..9f7ad185 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.h
@@ -0,0 +1,16 @@ +// 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 IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_CONSTANTS_H_ +#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_CONSTANTS_H_ + +#import <Foundation/Foundation.h> + +// The accessibility identifier for the navigation "Confirm" button. +extern NSString* const kSyncSettingsConfirmButtonId; + +// The accessibility identifier for the navigation "Cancel" button. +extern NSString* const kSyncSettingsCancelButtonId; + +#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.mm b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.mm similarity index 79% rename from ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.mm rename to ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.mm index cbda4646..4c66df3 100644 --- a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.mm +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.h" +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_coordinator.mm index e7fa086..5eef2a7ec 100644 --- a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_coordinator.mm +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_coordinator.mm
@@ -4,20 +4,241 @@ #import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_coordinator.h" +#import "base/metrics/user_metrics.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/signin/authentication_service.h" +#import "ios/chrome/browser/signin/authentication_service_factory.h" +#import "ios/chrome/browser/sync/profile_sync_service_factory.h" +#import "ios/chrome/browser/sync/sync_setup_service.h" +#import "ios/chrome/browser/sync/sync_setup_service_factory.h" +#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.h" +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.h" +#import "ios/chrome/browser/ui/authentication/signin/signin_coordinator+protected.h" +#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.h" +#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_mode.h" +#import "ios/chrome/grit/ios_strings.h" +#import "ui/base/l10n/l10n_util_mac.h" + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +using base::RecordAction; +using base::UserMetricsAction; +using l10n_util::GetNSString; + +@interface AdvancedSettingsSigninCoordinator () < + AdvancedSettingsSigninNavigationControllerNavigationDelegate, + UIAdaptivePresentationControllerDelegate> + +// Advanced settings sign-in mediator. +@property(nonatomic, strong) + AdvancedSettingsSigninMediator* advancedSettingsSigninMediator; +// View controller presented by this coordinator. +@property(nonatomic, strong) AdvancedSettingsSigninNavigationController* + advancedSettingsSigninNavigationController; +// Google services settings coordinator. +@property(nonatomic, strong) + GoogleServicesSettingsCoordinator* googleServicesSettingsCoordinator; +// Confirm cancel sign-in/sync dialog. +@property(nonatomic, strong) + AlertCoordinator* cancelConfirmationAlertCoordinator; + +@end + @implementation AdvancedSettingsSigninCoordinator -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - browser:(Browser*)browser { - self = [super initWithBaseViewController:viewController browser:browser]; - if (self) { - // TODO(crbug.com/971989): Needs implementation. - NOTIMPLEMENTED(); +#pragma mark - SigninCoordinator + +- (void)start { + [super start]; + self.advancedSettingsSigninNavigationController = + [[AdvancedSettingsSigninNavigationController alloc] init]; + self.advancedSettingsSigninNavigationController.modalPresentationStyle = + UIModalPresentationFormSheet; + self.advancedSettingsSigninNavigationController.navigationDelegate = self; + + // Init and start Google settings coordinator. + GoogleServicesSettingsMode mode = + GoogleServicesSettingsModeAdvancedSigninSettings; + self.googleServicesSettingsCoordinator = [[GoogleServicesSettingsCoordinator + alloc] + initWithBaseViewController:self.advancedSettingsSigninNavigationController + browser:self.browser + mode:mode]; + self.googleServicesSettingsCoordinator.navigationController = + self.advancedSettingsSigninNavigationController; + [self.googleServicesSettingsCoordinator start]; + + // Create the mediator. + SyncSetupService* syncSetupService = + SyncSetupServiceFactory::GetForBrowserState(self.browserState); + AuthenticationService* authenticationService = + AuthenticationServiceFactory::GetForBrowserState(self.browserState); + syncer::SyncService* syncService = + ProfileSyncServiceFactory::GetForBrowserState(self.browserState); + self.advancedSettingsSigninMediator = [[AdvancedSettingsSigninMediator alloc] + initWithSyncSetupService:syncSetupService + authenticationService:authenticationService + syncService:syncService + prefService:self.browserState->GetPrefs()]; + self.advancedSettingsSigninNavigationController.presentationController + .delegate = self; + + // Present the navigation controller that now contains the Google settings + // view controller. + [self.baseViewController + presentViewController:self.advancedSettingsSigninNavigationController + animated:YES + completion:nil]; +} + +- (void)interruptWithAction:(SigninCoordinatorInterruptAction)action + completion:(ProceduralBlock)completion { + DCHECK(self.advancedSettingsSigninNavigationController); + [self.googleServicesSettingsCoordinator stop]; + self.googleServicesSettingsCoordinator = nil; + switch (action) { + case SigninCoordinatorInterruptActionNoDismiss: + [self finishedWithSigninResult:SigninCoordinatorResultInterrupted]; + if (completion) { + completion(); + } + break; + case SigninCoordinatorInterruptActionDismissWithoutAnimation: + [self dismissViewControllerAndFinishWithResult: + SigninCoordinatorResultInterrupted + animated:NO + completion:completion]; + break; + case SigninCoordinatorInterruptActionDismissWithAnimation: + [self dismissViewControllerAndFinishWithResult: + SigninCoordinatorResultInterrupted + animated:YES + completion:completion]; + break; } - return self; +} + +- (BOOL)isSettingsViewPresented { + // TODO(crbug.com/971989): Remove this method. + return YES; +} + +#pragma mark - Private + +// Called when a button of |self.cancelConfirmationAlertCoordinator| is pressed. +- (void)cancelConfirmationWithShouldCancelSignin:(BOOL)shouldCancelSignin { + DCHECK(self.cancelConfirmationAlertCoordinator); + [self.cancelConfirmationAlertCoordinator stop]; + self.cancelConfirmationAlertCoordinator = nil; + if (shouldCancelSignin) { + [self dismissViewControllerAndFinishWithResult: + SigninCoordinatorResultCanceledByUser + animated:YES + completion:nil]; + } else { + RecordAction( + UserMetricsAction("Signin_Signin_CancelCancelAdvancedSyncSettings")); + } +} + +// Dismisses the current view controller with |animated|, triggers the +// coordinator cleanup and then calls |completion|. +- (void)dismissViewControllerAndFinishWithResult:(SigninCoordinatorResult)result + animated:(BOOL)animated + completion:(ProceduralBlock)completion { + DCHECK_EQ(self.advancedSettingsSigninNavigationController, + self.baseViewController.presentedViewController); + __weak __typeof(self) weakSelf = self; + ProceduralBlock dismissCompletion = ^() { + [weakSelf finishedWithSigninResult:result]; + if (completion) { + completion(); + } + }; + [self.baseViewController dismissViewControllerAnimated:animated + completion:dismissCompletion]; +} + +// Does the cleanup once the view has been dismissed, calls the metrics and +// calls |runCompletionCallbackWithSigninResult:identity:| to finish the +// sign-in. +- (void)finishedWithSigninResult:(SigninCoordinatorResult)signinResult { + DCHECK(self.advancedSettingsSigninNavigationController); + DCHECK(self.advancedSettingsSigninMediator); + [self.advancedSettingsSigninMediator + saveUserPreferenceForSigninResult:signinResult]; + self.advancedSettingsSigninNavigationController = nil; + self.advancedSettingsSigninMediator = nil; + [self.googleServicesSettingsCoordinator stop]; + self.googleServicesSettingsCoordinator = nil; + SyncSetupService* syncSetupService = + SyncSetupServiceFactory::GetForBrowserState(self.browserState); + DCHECK(!syncSetupService->HasUncommittedChanges()) + << "-[GoogleServicesSettingsCoordinator stop] should commit sync " + "changes."; + AuthenticationService* authService = + AuthenticationServiceFactory::GetForBrowserState(self.browserState); + ChromeIdentity* identity = authService->GetAuthenticatedIdentity(); + [self runCompletionCallbackWithSigninResult:signinResult identity:identity]; +} + +- (void)showCancelConfirmationAlert { + DCHECK(!self.cancelConfirmationAlertCoordinator); + RecordAction(UserMetricsAction("Signin_Signin_CancelAdvancedSyncSettings")); + self.cancelConfirmationAlertCoordinator = [[AlertCoordinator alloc] + initWithBaseViewController:self.advancedSettingsSigninNavigationController + title: + GetNSString( + IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_TITLE) + message: + GetNSString( + IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_MESSAGE)]; + __weak __typeof(self) weakSelf = self; + [self.cancelConfirmationAlertCoordinator + addItemWithTitle: + GetNSString( + IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_BACK_BUTTON) + action:^{ + [weakSelf cancelConfirmationWithShouldCancelSignin:NO]; + } + style:UIAlertActionStyleCancel]; + [self.cancelConfirmationAlertCoordinator + addItemWithTitle: + GetNSString( + IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_CANCEL_SYNC_BUTTON) + action:^{ + [weakSelf cancelConfirmationWithShouldCancelSignin:YES]; + } + style:UIAlertActionStyleDefault]; + [self.cancelConfirmationAlertCoordinator start]; +} + +#pragma mark - AdvancedSettingsSigninNavigationControllerNavigationDelegate + +- (void)navigationCancelButtonWasTapped { + [self showCancelConfirmationAlert]; +} + +- (void)navigationConfirmButtonWasTapped { + DCHECK(!self.cancelConfirmationAlertCoordinator); + [self dismissViewControllerAndFinishWithResult:SigninCoordinatorResultSuccess + animated:YES + completion:nil]; +} + +#pragma mark - UIAdaptivePresentationControllerDelegate + +- (BOOL)presentationControllerShouldDismiss: + (UIPresentationController*)presentationController { + return NO; +} + +- (void)presentationControllerDidAttemptToDismiss: + (UIPresentationController*)presentationController { + [self showCancelConfirmationAlert]; } @end
diff --git a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.h b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.h new file mode 100644 index 0000000..74713f5 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.h
@@ -0,0 +1,38 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_MEDIATOR_H_ +#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_MEDIATOR_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/authentication/signin/signin_enums.h" + +@class AdvancedSettingsSigninMediator; +@class AdvancedSettingsSigninNavigationController; +class AuthenticationService; +class PrefService; +class SyncSetupService; +namespace syncer { +class SyncService; +} + +// Mediator for the advanced settings sign-in flow. +@interface AdvancedSettingsSigninMediator : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithSyncSetupService:(SyncSetupService*)syncSetupService + authenticationService: + (AuthenticationService*)authenticationService + syncService:(syncer::SyncService*)syncService + prefService:(PrefService*)prefService + NS_DESIGNATED_INITIALIZER; + +// Saves the user sync preferences. +- (void)saveUserPreferenceForSigninResult:(SigninCoordinatorResult)signinResult; + +@end + +#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.mm b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.mm new file mode 100644 index 0000000..5d667daa --- /dev/null +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.mm
@@ -0,0 +1,89 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_mediator.h" + +#import "base/metrics/user_metrics.h" +#import "components/sync/driver/sync_service.h" +#import "components/unified_consent/unified_consent_metrics.h" +#import "ios/chrome/browser/signin/authentication_service.h" +#import "ios/chrome/browser/sync/sync_setup_service.h" +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using base::RecordAction; +using base::UserMetricsAction; +using syncer::SyncFirstSetupCompleteSource; +using unified_consent::metrics::RecordSyncSetupDataTypesHistrogam; + +@interface AdvancedSettingsSigninMediator () + +@property(nonatomic, assign, readonly) SyncSetupService* syncSetupService; +@property(nonatomic, assign, readonly) + AuthenticationService* authenticationService; +@property(nonatomic, assign, readonly) syncer::SyncService* syncService; +// Browser state preference service. +@property(nonatomic, assign, readonly) PrefService* prefService; + +@end + +@implementation AdvancedSettingsSigninMediator + +#pragma mark - Public + +- (instancetype)initWithSyncSetupService:(SyncSetupService*)syncSetupService + authenticationService: + (AuthenticationService*)authenticationService + syncService:(syncer::SyncService*)syncService + prefService:(PrefService*)prefService { + self = [super init]; + if (self) { + DCHECK(syncSetupService); + DCHECK(authenticationService); + DCHECK(syncService); + DCHECK(prefService); + _syncSetupService = syncSetupService; + _authenticationService = authenticationService; + _syncService = syncService; + _prefService = prefService; + } + return self; +} + +- (void)saveUserPreferenceForSigninResult: + (SigninCoordinatorResult)signinResult { + switch (signinResult) { + case SigninCoordinatorResultSuccess: { + RecordAction( + UserMetricsAction("Signin_Signin_ConfirmAdvancedSyncSettings")); + RecordSyncSetupDataTypesHistrogam(self.syncService->GetUserSettings(), + self.prefService); + if (self.syncSetupService->IsSyncEnabled()) { + // FirstSetupComplete flag should be only turned on when the user agrees + // to start Sync. + self.syncSetupService->PrepareForFirstSyncSetup(); + self.syncSetupService->SetFirstSetupComplete( + SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM); + } + break; + } + case SigninCoordinatorResultCanceledByUser: + RecordAction( + UserMetricsAction("Signin_Signin_ConfirmCancelAdvancedSyncSettings")); + self.syncSetupService->CommitSyncChanges(); + self.authenticationService->SignOut(signin_metrics::ABORT_SIGNIN, + /*force_clear_browsing_data=*/false, + nil); + break; + case SigninCoordinatorResultInterrupted: + RecordAction( + UserMetricsAction("Signin_Signin_AbortAdvancedSyncSettings")); + break; + } +} + +@end
diff --git a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.h b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.h new file mode 100644 index 0000000..dde8bf7 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.h
@@ -0,0 +1,32 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_NAVIGATION_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_NAVIGATION_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +// Delegate for AdvancedSettingsSigninNavigationController to receive navigation +// button events. +@protocol + AdvancedSettingsSigninNavigationControllerNavigationDelegate <NSObject> + +// Called when the navigation canceled button was tapped. +- (void)navigationCancelButtonWasTapped; + +// Called when the navigation confirm button was tapped. +- (void)navigationConfirmButtonWasTapped; + +@end + +// View controller to present the Google services settings. +@interface AdvancedSettingsSigninNavigationController : UINavigationController + +@property(nonatomic, weak) + id<AdvancedSettingsSigninNavigationControllerNavigationDelegate> + navigationDelegate; + +@end + +#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_ADVANCED_SETTINGS_SIGNIN_ADVANCED_SETTINGS_SIGNIN_NAVIGATION_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.mm b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.mm new file mode 100644 index 0000000..a3e5524 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.mm
@@ -0,0 +1,83 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_navigation_controller.h" + +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.h" +#import "ios/chrome/browser/ui/settings/settings_controller_protocol.h" +#import "ios/chrome/grit/ios_strings.h" +#import "ui/base/l10n/l10n_util_mac.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using l10n_util::GetNSString; + +@implementation AdvancedSettingsSigninNavigationController + +#pragma mark - UINavigationController + +// Calls |viewControllerWasPopped| for the popped view controller. +- (UIViewController*)popViewControllerAnimated:(BOOL)animated { + UIViewController* poppedViewController = + [super popViewControllerAnimated:animated]; + if ([poppedViewController + respondsToSelector:@selector(viewControllerWasPopped)]) { + [poppedViewController performSelector:@selector(viewControllerWasPopped)]; + } + return poppedViewController; +} + +- (void)pushViewController:(UIViewController*)viewController + animated:(BOOL)animated { + [super pushViewController:viewController animated:animated]; + if (self.viewControllers.count == 1) { + viewController.navigationItem.leftBarButtonItem = + [self navigationCancelButton]; + viewController.navigationItem.rightBarButtonItem = + [self navigationConfirmButton]; + } +} + +#pragma mark - Private + +// Creates a cancel button for the navigation item. +- (UIBarButtonItem*)navigationCancelButton { + UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(onNavigationCancelButton)]; + cancelButton.accessibilityIdentifier = kSyncSettingsCancelButtonId; + return cancelButton; +} + +// Creates a confirmation button for the navigation item. +- (UIBarButtonItem*)navigationConfirmButton { + UIBarButtonItem* confirmButton = [[UIBarButtonItem alloc] + initWithTitle:GetNSString( + IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CONFIRM_MAIN_BUTTON) + style:UIBarButtonItemStyleDone + target:self + action:@selector(onNavigationConfirmButton)]; + confirmButton.accessibilityIdentifier = kSyncSettingsConfirmButtonId; + return confirmButton; +} + +#pragma mark - Button events + +// Called by the cancel button from the navigation controller. Shows the cancel +// alert dialog. +- (void)onNavigationCancelButton { + [self.navigationDelegate navigationCancelButtonWasTapped]; +} + +// Called by the confirm button from tne navigation controller. Validates the +// sync preferences chosen by the user, starts the sync, close the completion +// callback and closes the advanced sign-in settings. +- (void)onNavigationConfirmButton { + [self.navigationDelegate navigationConfirmButtonWasTapped]; +} + +@end
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h index 8699b24..99bf9a2 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h +++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.h
@@ -32,6 +32,12 @@ // This completion needs to be set before calling -[SigninCoordinator start]. @property(nonatomic, copy) SigninCoordinatorCompletionCallback signinCompletion; +// Returns YES if the Google services settings view is presented. +// TODO(crbug.com/971989): This property exists for the implementation +// transition. +@property(nonatomic, assign, readonly, getter=isSettingsViewPresented) + BOOL settingsViewPresented; + // Returns a coordinator for user sign-in workflow. // |viewController| presents the sign-in. // |identity| is the identity preselected with the sign-in opens.
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm index 5cc26d0..4c4b11c3 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm
@@ -118,6 +118,13 @@ DCHECK(!self.signinCompletion); } +#pragma mark - Properties + +- (BOOL)isSettingsViewPresented { + // TODO(crbug.com/971989): Remove this method. + return NO; +} + #pragma mark - Private - (void)runCompletionCallbackWithSigninResult:
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/BUILD.gn b/ios/chrome/browser/ui/authentication/signin/user_signin/BUILD.gn index aff9e18..453d0fb 100644 --- a/ios/chrome/browser/ui/authentication/signin/user_signin/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/BUILD.gn
@@ -7,6 +7,8 @@ source_set("user_signin") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "gradient_view.h", + "gradient_view.mm", "user_signin_coordinator.h", "user_signin_coordinator.mm", "user_signin_mediator.h",
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.h b/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.h new file mode 100644 index 0000000..984c1f0 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.h
@@ -0,0 +1,21 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_USER_SIGNIN_GRADIENT_VIEW_H_ +#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_USER_SIGNIN_GRADIENT_VIEW_H_ + +#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> + +// A UIView showing a vertical gradient from transparent to opaque using the +// system background color. +@interface GradientView : UIView + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_USER_SIGNIN_GRADIENT_VIEW_H_
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.mm new file mode 100644 index 0000000..831d0d94 --- /dev/null +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.mm
@@ -0,0 +1,62 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.h" + +#import "base/mac/foundation_util.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation GradientView + +#pragma mark - Public + ++ (Class)layerClass { + return [CAGradientLayer class]; +} + +- (instancetype)init { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.userInteractionEnabled = NO; + } + return self; +} + +- (CAGradientLayer*)gradientLayer { + return base::mac::ObjCCastStrict<CAGradientLayer>(self.layer); +} + +- (void)traitCollectionDidChange: + (nullable UITraitCollection*)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + if (@available(iOS 13, *)) { + if ([self.traitCollection + hasDifferentColorAppearanceComparedToTraitCollection: + previousTraitCollection]) { + [self updateColors]; + } + } +} + +#pragma mark - Private + +- (void)updateColors { + [CATransaction begin]; + // If this isn't set, the changes here are automatically animated. The other + // color changes for dark mode don't animate, however, so there ends up being + // visual desyncing. + [CATransaction setDisableActions:YES]; + + self.gradientLayer.colors = @[ + (id)[UIColor.cr_systemBackgroundColor colorWithAlphaComponent:0].CGColor, + (id)UIColor.cr_systemBackgroundColor.CGColor + ]; + [CATransaction commit]; +} + +@end
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm index d666bea..47c2a13 100644 --- a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
@@ -180,9 +180,9 @@ ^(SigninCoordinatorResult signinResult, ChromeIdentity* identity) { if (signinResult == SigninCoordinatorResultSuccess) { weakSelf.unifiedConsentCoordinator.selectedIdentity = identity; - [weakSelf.addAccountSigninCoordinator stop]; - weakSelf.addAccountSigninCoordinator = nil; } + [weakSelf.addAccountSigninCoordinator stop]; + weakSelf.addAccountSigninCoordinator = nil; }; [self.addAccountSigninCoordinator start]; }
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm index e8ec4e4..e1f9406b 100644 --- a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.h" #import "base/logging.h" +#import "ios/chrome/browser/ui/authentication/signin/user_signin/gradient_view.h" #import "ios/chrome/browser/ui/util/rtl_geometry.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" @@ -25,6 +26,7 @@ // Layout constants for buttons. struct AuthenticationViewConstants { + CGFloat GradientHeight; CGFloat ButtonHeight; CGFloat ButtonHorizontalPadding; CGFloat ButtonTopPadding; @@ -32,6 +34,7 @@ }; const AuthenticationViewConstants kCompactConstants = { + 40, // GradientHeight 36, // ButtonHeight 16, // ButtonHorizontalPadding 16, // ButtonTopPadding @@ -39,6 +42,7 @@ }; const AuthenticationViewConstants kRegularConstants = { + kCompactConstants.GradientHeight, 1.5 * kCompactConstants.ButtonHeight, 32, // ButtonHorizontalPadding 32, // ButtonTopPadding @@ -66,6 +70,9 @@ // Property that denotes whether the unified consent screen reached bottom has // triggered. @property(nonatomic, assign) BOOL hasUnifiedConsentScreenReachedBottom; +// Gradient used to hide text that is close to the bottom of the screen. This +// gives users the hint that there is more to scroll through. +@property(nonatomic, strong) GradientView* gradientView; @end @@ -126,28 +133,57 @@ [self addConfirmationButtonToView]; [self embedUserConsentView]; + [self addActivityIndicatorToView]; [self addSkipSigninButtonToView]; + [self.view addSubview:self.gradientView]; + // The layout constraints should be added at the end once all of the views // have been created. AuthenticationViewConstants constants = self.authenticationViewConstants; + + // Embedded view constraints. AddSameConstraintsWithInsets( self.unifiedConsentViewController.view, self.view, ChromeDirectionalEdgeInsetsMake(0, 0, - constants.ButtonHeight + + 2 * constants.ButtonHeight + constants.ButtonBottomPadding + constants.ButtonTopPadding, 0)); + + // Skip sign-in button constraints. AddSameConstraintsToSidesWithInsets( self.skipSigninButton, self.view, LayoutSides::kBottom | LayoutSides::kLeading, - ChromeDirectionalEdgeInsetsMake(0, constants.ButtonHorizontalPadding, - constants.ButtonBottomPadding, 0)); + ChromeDirectionalEdgeInsetsMake( + 0, constants.ButtonHorizontalPadding, + constants.ButtonBottomPadding + constants.ButtonHeight, 0)); + + // Activity indicator constraints. + AddSameCenterConstraints(self.view, self.activityIndicator); + + // Confirmation button constraints. AddSameConstraintsToSidesWithInsets( self.confirmationButton, self.view, LayoutSides::kBottom | LayoutSides::kTrailing, - ChromeDirectionalEdgeInsetsMake(0, 0, constants.ButtonBottomPadding, - constants.ButtonHorizontalPadding)); + ChromeDirectionalEdgeInsetsMake( + 0, 0, constants.ButtonBottomPadding + constants.ButtonHeight, + constants.ButtonHorizontalPadding)); + + // Gradient layer constraints. + self.gradientView.translatesAutoresizingMaskIntoConstraints = NO; + [NSLayoutConstraint activateConstraints:@[ + [self.gradientView.bottomAnchor + constraintEqualToAnchor:self.unifiedConsentViewController.view + .bottomAnchor], + [self.gradientView.leadingAnchor + constraintEqualToAnchor:self.view.leadingAnchor], + [self.gradientView.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor], + + [self.gradientView.heightAnchor + constraintEqualToConstant:constants.GradientHeight], + ]]; } #pragma mark - Properties @@ -181,6 +217,16 @@ return isRegularSizeClass ? kRegularConstants : kCompactConstants; } +// Sets up gradient that masks text when the iOS device size is a compact size. +// This is to hint to the user that there is additional text below the end of +// the screen. +- (UIView*)gradientView { + if (!_gradientView) { + _gradientView = [[GradientView alloc] init]; + } + return _gradientView; +} + #pragma mark - Subviews // Sets up activity indicator properties and adds it to the view.
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 75ccad7..fbe077cc 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -3058,6 +3058,7 @@ _contextMenuCoordinator = [[ContextMenuCoordinator alloc] initWithBaseViewController:self + browser:self.browser title:params.menu_title inView:params.view atLocation:params.location]; @@ -3875,11 +3876,12 @@ const std::unique_ptr<sessions::TabRestoreService::Entry>& entry = tabRestoreService->entries().front(); // Only handle the TAB type. + // TODO(crbug.com/1056596) : Support WINDOW restoration under multi-window. if (entry->type != sessions::TabRestoreService::TAB) return; [self.dispatcher openURLInNewTab:[OpenNewTabCommand command]]; - RestoreTab(entry->id, WindowOpenDisposition::CURRENT_TAB, self.browserState); + RestoreTab(entry->id, WindowOpenDisposition::CURRENT_TAB, self.browser); } #pragma mark - MainContentUI @@ -3912,7 +3914,13 @@ [[OmniboxGeolocationController sharedInstance] locationBarDidBecomeFirstResponder:self.browserState]; - [self.primaryToolbarCoordinator transitionToLocationBarFocusedState:YES]; + // On the non-incognito NTP, the primaryToolbarCoordinator focuses the + // location bar itself when focusing the fakebox (while animating the + // fakebox). On all other pages, the fakebox is focused here after the + // location bar becomes first responder. + if (!IsVisibleURLNewTabPage(self.currentWebState) || self.isOffTheRecord) { + [self.primaryToolbarCoordinator transitionToLocationBarFocusedState:YES]; + } } - (void)locationBarDidResignFirstResponder {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm index 91c8406..1603476 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -450,12 +450,19 @@ if (self.disableScrollAnimation) return; + // Focus the location bar if the omnibox is not already focused. + if (!self.omniboxFocused) { + // Only animated the location bar focus if the header is scrolled to the + // top. + BOOL animated = [self.delegate isScrolledToTop]; + [self.dispatcher focusLocationBarWithAnimation:animated]; + } + void (^animations)() = nil; if (![self.delegate isScrolledToTop]) { // Only trigger the fake omnibox animation if the header isn't scrolled to // the top. Otherwise just rely on the normal animation. self.disableScrollAnimation = YES; - [self.dispatcher focusOmniboxNoAnimation]; NamedGuide* omniboxGuide = [NamedGuide guideWithName:kOmniboxGuide view:self.headerView]; // Layout the owning view to make sure that the constrains are applied.
diff --git a/ios/chrome/browser/ui/context_menu/BUILD.gn b/ios/chrome/browser/ui/context_menu/BUILD.gn index d45a02a..d02973ff 100644 --- a/ios/chrome/browser/ui/context_menu/BUILD.gn +++ b/ios/chrome/browser/ui/context_menu/BUILD.gn
@@ -25,6 +25,8 @@ deps = [ ":context_menu", "//base", + "//base/test:test_support", + "//ios/chrome/browser/main:test_support", "//testing/gtest", ] }
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.h b/ios/chrome/browser/ui/context_menu/context_menu_coordinator.h index 165fe61f..2d11d71a 100644 --- a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.h +++ b/ios/chrome/browser/ui/context_menu/context_menu_coordinator.h
@@ -25,6 +25,7 @@ // location, the context menu will originate from |location| in |view|. // Context menu will be presented from |viewController|. - (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser title:(NSString*)title inView:(UIView*)view atLocation:(CGPoint)location
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.mm b/ios/chrome/browser/ui/context_menu/context_menu_coordinator.mm index fbf0a14..4a55d5c2 100644 --- a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.mm +++ b/ios/chrome/browser/ui/context_menu/context_menu_coordinator.mm
@@ -24,10 +24,11 @@ @implementation ContextMenuCoordinator - (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser title:(NSString*)title inView:(UIView*)view atLocation:(CGPoint)location { - self = [super initWithBaseViewController:viewController browserState:nullptr]; + self = [super initWithBaseViewController:viewController browser:browser]; if (self) { _alertCoordinator = [[ActionSheetCoordinator alloc] initWithBaseViewController:viewController
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_coordinator_unittest.mm b/ios/chrome/browser/ui/context_menu/context_menu_coordinator_unittest.mm index ff9c7a5..4cc2fc1 100644 --- a/ios/chrome/browser/ui/context_menu/context_menu_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/context_menu/context_menu_coordinator_unittest.mm
@@ -7,6 +7,8 @@ #import <UIKit/UIKit.h> #import "base/mac/foundation_util.h" +#import "base/test/task_environment.h" +#import "ios/chrome/browser/main/test_browser.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -24,6 +26,7 @@ [window_ makeKeyAndVisible]; view_controller_ = [[UIViewController alloc] init]; [window_ setRootViewController:view_controller_]; + browser_ = std::make_unique<TestBrowser>(); } ~ContextMenuCoordinatorTest() override { @@ -31,16 +34,20 @@ } protected: + base::test::TaskEnvironment task_environment_; + UIWindow* previous_key_window_; ContextMenuCoordinator* menu_coordinator_; UIWindow* window_; UIViewController* view_controller_; + std::unique_ptr<Browser> browser_; }; // Tests the context menu reports as visible after presenting. TEST_F(ContextMenuCoordinatorTest, ValidateIsVisible) { menu_coordinator_ = [[ContextMenuCoordinator alloc] initWithBaseViewController:view_controller_ + browser:browser_.get() title:@"Context Menu" inView:view_controller_.view atLocation:CGPointZero]; @@ -52,6 +59,7 @@ TEST_F(ContextMenuCoordinatorTest, ValidateDismissalOnStop) { menu_coordinator_ = [[ContextMenuCoordinator alloc] initWithBaseViewController:view_controller_ + browser:browser_.get() title:nil inView:view_controller_.view atLocation:CGPointZero]; @@ -64,6 +72,7 @@ TEST_F(ContextMenuCoordinatorTest, ValidateActions) { menu_coordinator_ = [[ContextMenuCoordinator alloc] initWithBaseViewController:view_controller_ + browser:browser_.get() title:nil inView:view_controller_.view atLocation:CGPointZero]; @@ -98,6 +107,7 @@ TEST_F(ContextMenuCoordinatorTest, CancelButtonExists) { menu_coordinator_ = [[ContextMenuCoordinator alloc] initWithBaseViewController:view_controller_ + browser:browser_.get() title:nil inView:view_controller_.view atLocation:CGPointZero]; @@ -121,6 +131,7 @@ NSString* title = @"Context Menu Title"; menu_coordinator_ = [[ContextMenuCoordinator alloc] initWithBaseViewController:view_controller_ + browser:browser_.get() title:title inView:view_controller_.view atLocation:location];
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn index a8a1bff..ae9f0c5 100644 --- a/ios/chrome/browser/ui/history/BUILD.gn +++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -81,6 +81,7 @@ "//ios/chrome/app/strings", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/main:public", "//ios/chrome/browser/metrics:metrics_internal", "//ios/chrome/browser/sync", "//ios/chrome/browser/ui/collection_view/cells",
diff --git a/ios/chrome/browser/ui/history/history_coordinator.mm b/ios/chrome/browser/ui/history/history_coordinator.mm index 8abcdfa..c5ca7a0 100644 --- a/ios/chrome/browser/ui/history/history_coordinator.mm +++ b/ios/chrome/browser/ui/history/history_coordinator.mm
@@ -61,8 +61,7 @@ - (void)start { // Initialize and configure HistoryTableViewController. self.historyTableViewController = [[HistoryTableViewController alloc] init]; - self.historyTableViewController.browserState = - self.browser->GetBrowserState(); + self.historyTableViewController.browser = self.browser; self.historyTableViewController.loadStrategy = self.loadStrategy; // Initialize and set HistoryMediator
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.h b/ios/chrome/browser/ui/history/history_table_view_controller.h index f401ba9..965014d9 100644 --- a/ios/chrome/browser/ui/history/history_table_view_controller.h +++ b/ios/chrome/browser/ui/history/history_table_view_controller.h
@@ -9,7 +9,7 @@ #include "ios/chrome/browser/ui/history/history_consumer.h" -class ChromeBrowserState; +class Browser; enum class UrlLoadStrategy; @class ContextMenuCoordinator; @@ -21,8 +21,8 @@ @interface HistoryTableViewController : ChromeTableViewController <HistoryConsumer, UIAdaptivePresentationControllerDelegate> -// The ViewController's BrowserState. -@property(nonatomic, assign) ChromeBrowserState* browserState; +// The ViewController's Browser. +@property(nonatomic, assign) Browser* browser; // Abstraction to communicate with HistoryService and WebHistoryService. // Not owned by HistoryTableViewController. @property(nonatomic, assign) history::BrowsingHistoryService* historyService;
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm index beb01f7..c3321ca 100644 --- a/ios/chrome/browser/ui/history/history_table_view_controller.mm +++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -13,6 +13,7 @@ #include "components/url_formatter/url_formatter.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/metrics/new_tab_page_uma.h" #include "ios/chrome/browser/sync/sync_setup_service.h" #include "ios/chrome/browser/sync/sync_setup_service_factory.h" @@ -253,7 +254,7 @@ // If history sync is enabled and there hasn't been a response from synced // history, try fetching again. SyncSetupService* syncSetupService = - SyncSetupServiceFactory::GetForBrowserState(_browserState); + SyncSetupServiceFactory::GetForBrowserState(_browser->GetBrowserState()); if (syncSetupService->IsSyncEnabled() && syncSetupService->IsDataTypeActive(syncer::HISTORY_DELETE_DIRECTIVES) && queryResultsInfo.sync_timed_out) { @@ -998,6 +999,7 @@ base::SysUTF16ToNSString(url_formatter::FormatUrl(entry.URL)); self.contextMenuCoordinator = [[ContextMenuCoordinator alloc] initWithBaseViewController:self.navigationController + browser:_browser title:menuTitle inView:self.tableView atLocation:touchLocation]; @@ -1037,7 +1039,8 @@ base::UserMetricsAction("MobileHistoryPage_EntryLinkOpenNewTab")); UrlLoadParams params = UrlLoadParams::InNewTab(URL); [self.delegate dismissHistoryWithCompletion:^{ - UrlLoadingServiceFactory::GetForBrowserState(_browserState)->Load(params); + UrlLoadingServiceFactory::GetForBrowserState(_browser->GetBrowserState()) + ->Load(params); [self.presentationDelegate showActiveRegularTabFromHistory]; }]; } @@ -1049,7 +1052,8 @@ UrlLoadParams params = UrlLoadParams::InNewTab(URL); params.in_incognito = YES; [self.delegate dismissHistoryWithCompletion:^{ - UrlLoadingServiceFactory::GetForBrowserState(_browserState)->Load(params); + UrlLoadingServiceFactory::GetForBrowserState(_browser->GetBrowserState()) + ->Load(params); [self.presentationDelegate showActiveIncognitoTabFromHistory]; }]; } @@ -1059,13 +1063,14 @@ // Opens URL in the current tab and dismisses the history view. - (void)openURL:(const GURL&)URL { // TODO(crbug.com/1032550) : Update this call to pass in the current WebState. - new_tab_page_uma::RecordAction(_browserState, + new_tab_page_uma::RecordAction(_browser->GetBrowserState(), new_tab_page_uma::ACTION_OPENED_HISTORY_ENTRY); UrlLoadParams params = UrlLoadParams::InCurrentTab(URL); params.web_params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK; params.load_strategy = self.loadStrategy; [self.delegate dismissHistoryWithCompletion:^{ - UrlLoadingServiceFactory::GetForBrowserState(_browserState)->Load(params); + UrlLoadingServiceFactory::GetForBrowserState(_browser->GetBrowserState()) + ->Load(params); [self.presentationDelegate showActiveRegularTabFromHistory]; }]; }
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn index 18bcb57..56797e6 100644 --- a/ios/chrome/browser/ui/location_bar/BUILD.gn +++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -51,6 +51,7 @@ "//ios/chrome/browser/ui/badges", "//ios/chrome/browser/ui/badges:public", "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/elements", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen:ui",
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h index ed2e84a..fb32c215 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
@@ -5,16 +5,12 @@ #ifndef IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_COORDINATOR_H_ #define IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_COORDINATOR_H_ -#import <UIKit/UIKit.h> +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" #import "ios/chrome/browser/ui/location_bar/location_bar_url_loader.h" #import "ios/chrome/browser/ui/omnibox/location_bar_delegate.h" #import "ios/chrome/browser/ui/toolbar/public/omnibox_focuser.h" -@class CommandDispatcher; -@protocol ApplicationCommands; -class Browser; -@protocol BrowserCommands; @protocol EditViewAnimatee; @protocol LocationBarAnimatee; @protocol OmniboxPopupPresenterDelegate; @@ -22,17 +18,20 @@ // Location bar coordinator. @interface LocationBarCoordinator - : NSObject<LocationBarURLLoader, OmniboxFocuser> + : ChromeCoordinator <LocationBarURLLoader, OmniboxFocuser> -// Command dispatcher. -@property(nonatomic, strong) CommandDispatcher* commandDispatcher; +// Unavailable, use -initWithBaseViewController:browser:. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + NS_UNAVAILABLE; + +// Unavailable, use -initWithBaseViewController:browser:. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState:(ChromeBrowserState*)browserState + NS_UNAVAILABLE; + // View controller containing the omnibox. @property(nonatomic, strong, readonly) UIViewController* locationBarViewController; -// The location bar's Browser. -@property(nonatomic, assign) Browser* browser; -// The dispatcher for this view controller. -@property(nonatomic, weak) CommandDispatcher* dispatcher; // Delegate for this coordinator. // TODO(crbug.com/799446): Change this. @property(nonatomic, weak) id<ToolbarCoordinatorDelegate> delegate; @@ -40,11 +39,6 @@ @property(nonatomic, weak) id<OmniboxPopupPresenterDelegate> popupPresenterDelegate; -// Start this coordinator. -- (void)start; -// Stop this coordinator. -- (void)stop; - // Indicates whether the popup has results to show or not. - (BOOL)omniboxPopupHasAutocompleteResults;
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm index a97cac924..d2a9e42 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -123,15 +123,15 @@ } - (void)start { - DCHECK(self.commandDispatcher); DCHECK(self.browser); if (self.started) return; - [self.commandDispatcher startDispatchingToTarget:self - forProtocol:@protocol(OmniboxFocuser)]; - [self.commandDispatcher + [self.browser->GetCommandDispatcher() + startDispatchingToTarget:self + forProtocol:@protocol(OmniboxFocuser)]; + [self.browser->GetCommandDispatcher() startDispatchingToTarget:self forProtocol:@protocol(LoadQueryCommands)]; @@ -140,9 +140,12 @@ self.viewController = [[LocationBarViewController alloc] init]; self.viewController.incognito = isIncognito; self.viewController.delegate = self; + // TODO(crbug.com/1045047): Use HandlerForProtocol after commands protocol + // clean up. self.viewController.dispatcher = static_cast<id<ActivityServiceCommands, BrowserCommands, - ApplicationCommands, LoadQueryCommands>>(self.dispatcher); + ApplicationCommands, LoadQueryCommands>>( + self.browser->GetCommandDispatcher()); self.viewController.voiceSearchEnabled = ios::GetChromeBrowserProvider() ->GetVoiceSearchProvider() ->IsVoiceSearchEnabled(); @@ -182,9 +185,11 @@ // Create BadgeMediator and set the viewController as its consumer. self.badgeMediator = [[BadgeMediator alloc] initWithBrowser:self.browser]; self.badgeMediator.consumer = self.badgeViewController; + // TODO(crbug.com/1045047): Use HandlerForProtocol after commands protocol + // clean up. self.badgeMediator.dispatcher = static_cast<id<InfobarCommands, BrowserCoordinatorCommands>>( - self.dispatcher); + self.browser->GetCommandDispatcher()); buttonFactory.delegate = self.badgeMediator; FullscreenController* fullscreenController = FullscreenController::FromBrowserState(self.browserState); @@ -209,7 +214,7 @@ - (void)stop { if (!self.started) return; - [self.commandDispatcher stopDispatchingToTarget:self]; + [self.browser->GetCommandDispatcher() stopDispatchingToTarget:self]; // The popup has to be destroyed before the location bar. [self.omniboxPopupCoordinator stop]; [self.omniboxCoordinator stop];
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm index 3c6cff3..b6ad669 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator_unittest.mm
@@ -18,7 +18,6 @@ #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" #import "ios/chrome/browser/main/test_browser.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" -#import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/toolbar/toolbar_coordinator_delegate.h" #include "ios/chrome/browser/url_loading/test_url_loading_service.h" #include "ios/chrome/browser/url_loading/url_loading_params.h" @@ -109,10 +108,10 @@ delegate_ = [[TestToolbarCoordinatorDelegate alloc] init]; - coordinator_ = [[LocationBarCoordinator alloc] init]; - coordinator_.browser = browser_.get(); + coordinator_ = [[LocationBarCoordinator alloc] + initWithBaseViewController:nil + browser:browser_.get()]; coordinator_.delegate = delegate_; - coordinator_.commandDispatcher = [[CommandDispatcher alloc] init]; } void TearDown() override {
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index a6a9495..9519759 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -149,6 +149,8 @@ @implementation SceneController @synthesize settingsNavigationController; //< From AppNavigation protocol. +@synthesize appURLLoadingService = + _appURLLoadingService; //< From SceneControllerGuts - (instancetype)initWithSceneState:(SceneState*)sceneState { self = [super init]; @@ -162,6 +164,9 @@ << "The window must be created by the scene delegate"; self.sceneState.window = [[ChromeOverlayWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + + _appURLLoadingService = new AppUrlLoadingService(); + _appURLLoadingService->SetDelegate(self); } } return self; @@ -339,7 +344,7 @@ params.from_chrome = command.fromChrome; params.user_initiated = command.userInitiated; params.should_focus_omnibox = command.shouldFocusOmnibox; - self.mainController.appURLLoadingService->LoadUrlInNewTab(params); + self.appURLLoadingService->LoadUrlInNewTab(params); } // TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher.
diff --git a/ios/chrome/browser/ui/main/scene_controller_guts.h b/ios/chrome/browser/ui/main/scene_controller_guts.h index a8053f3..f444b52 100644 --- a/ios/chrome/browser/ui/main/scene_controller_guts.h +++ b/ios/chrome/browser/ui/main/scene_controller_guts.h
@@ -10,6 +10,7 @@ #include "ios/chrome/app/application_delegate/startup_information.h" #import "ios/chrome/app/application_delegate/tab_opening.h" #import "ios/chrome/browser/procedural_block_types.h" +#import "ios/chrome/browser/url_loading/app_url_loading_service.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" @@ -18,6 +19,10 @@ @protocol SceneControllerGuts <WebStateListObserving> +// The scene level component for url loading. Is passed down to +// browser state level UrlLoadingService instances. +@property(nonatomic, assign) AppUrlLoadingService* appURLLoadingService; + - (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion dismissOmnibox:(BOOL)dismissOmnibox;
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index 79269c47..615d6f9 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -18,9 +18,8 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/metrics/new_tab_page_uma.h" +#include "ios/chrome/browser/sessions/live_tab_context_browser_agent.h" #include "ios/chrome/browser/sessions/session_util.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h" #include "ios/chrome/browser/sync/session_sync_service_factory.h" #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h" #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_consumer.h" @@ -943,6 +942,7 @@ return; // Only TAB type is handled. + // TODO(crbug.com/1056596) : Support WINDOW restoration under multi-window. DCHECK_EQ(entry->type, sessions::TabRestoreService::TAB); base::RecordAction( base::UserMetricsAction("MobileRecentTabManagerRecentTabOpened")); @@ -956,7 +956,7 @@ WindowOpenDisposition disposition = self.isIncognito ? WindowOpenDisposition::NEW_FOREGROUND_TAB : self.restoredTabDisposition; - RestoreTab(entry->id, disposition, self.browserState); + RestoreTab(entry->id, disposition, self.browser); [self.presentationDelegate showActiveRegularTabFromRecentTabs]; } @@ -1060,6 +1060,7 @@ // Present sheet/popover using controller that is added to view hierarchy. self.contextMenuCoordinator = [[ContextMenuCoordinator alloc] initWithBaseViewController:self + browser:self.browser title:nil inView:self.tableView atLocation:viewCoordinate];
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 50b34cf8..c721e6bc 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -29,6 +29,7 @@ "//ios/public/provider/chrome/browser/user_feedback", "//ui/base", ] + public_deps = [ ":settings_controller_protocol" ] } source_set("settings_root_constants") { @@ -193,6 +194,12 @@ ] } +source_set("settings_controller_protocol") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ "settings_controller_protocol.h" ] + frameworks = [ "UIKit.framework" ] +} + source_set("constants") { configs += [ "//build/config/compiler:enable_arc" ] sources = [
diff --git a/ios/chrome/browser/ui/settings/google_services/BUILD.gn b/ios/chrome/browser/ui/settings/google_services/BUILD.gn index 4d738b5..fd4130ad 100644 --- a/ios/chrome/browser/ui/settings/google_services/BUILD.gn +++ b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
@@ -7,10 +7,6 @@ sources = [ "accounts_table_view_controller.h", "accounts_table_view_controller.mm", - "advanced_signin_settings_coordinator.h", - "advanced_signin_settings_coordinator.mm", - "advanced_signin_settings_navigation_controller.h", - "advanced_signin_settings_navigation_controller.mm", "google_services_settings_command_handler.h", "google_services_settings_consumer.h", "google_services_settings_coordinator.h", @@ -60,6 +56,7 @@ "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/authentication/cells", + "//ios/chrome/browser/ui/authentication/signin/advanced_settings_signin", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/icons", @@ -79,8 +76,10 @@ "//ios/public/provider/chrome/browser/signin", "//ui/base", ] - allow_circular_includes_from = - [ "//ios/chrome/browser/ui/signin_interaction" ] + allow_circular_includes_from = [ + "//ios/chrome/browser/ui/signin_interaction", + "//ios/chrome/browser/ui/authentication/signin/advanced_settings_signin", + ] } source_set("constants") { @@ -88,8 +87,6 @@ sources = [ "accounts_table_view_controller_constants.h", "accounts_table_view_controller_constants.mm", - "advanced_signin_settings_constants.h", - "advanced_signin_settings_constants.mm", "google_services_settings_constants.h", "google_services_settings_constants.mm", "manage_sync_settings_constants.h",
diff --git a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.h b/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.h deleted file mode 100644 index 3522162..0000000 --- a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_CONSTANTS_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_CONSTANTS_H_ - -#import <Foundation/Foundation.h> - -// The accessibility identifier for the navigation "Confirm" button. -extern NSString* const kSyncSettingsConfirmButtonId; - -// The accessibility identifier for the navigation "Cancel" button. -extern NSString* const kSyncSettingsCancelButtonId; - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.h b/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.h deleted file mode 100644 index 9fbc1fa7..0000000 --- a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_COORDINATOR_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_COORDINATOR_H_ - -#import "base/ios/block_types.h" -#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" - -@class AdvancedSigninSettingsCoordinator; - -// AdvancedSigninSettingsCoordinator delegate. -@protocol AdvancedSigninSettingsCoordinatorDelegate <NSObject> - -// Called when the user closes AdvancedSigninSettingsCoordinator. -// |signedin|, YES if the view is confirmed or aborted, and NO if the view is -// canceled. -- (void)advancedSigninSettingsCoordinatorDidClose: - (AdvancedSigninSettingsCoordinator*)coordinator - signedin:(BOOL)signedin; - -@end - -// Shows the Google services settings in a navigation controller, so the user -// can update their sync settings before sync starts (or sign-out). -@interface AdvancedSigninSettingsCoordinator : ChromeCoordinator - -// Delegate. -@property(nonatomic, weak) id<AdvancedSigninSettingsCoordinatorDelegate> - delegate; - -// Aborts the sign-in flow, and calls the delegate. Aborting the Advanced -// sync settings doesn't sign out the user. The sync is left unsetup and doesn't -// start. This method does nothing if called twice. -// |dismiss|, dismisses the view controller if YES. -// |animated|, the view is animated if YES. -// |completion|, this completion block is called after the view is dismissed. -// It will be called even the view is already dismissed. The value -// can be nil. -- (void)abortWithDismiss:(BOOL)dismiss - animated:(BOOL)animated - completion:(ProceduralBlock)completion; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.mm deleted file mode 100644 index 46b8d09c4..0000000 --- a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.mm +++ /dev/null
@@ -1,293 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.h" - -#import <UIKit/UIKit.h> - -#include "base/logging.h" -#include "base/metrics/user_metrics.h" -#include "components/signin/public/base/signin_metrics.h" -#include "components/strings/grit/components_strings.h" -#include "components/sync/driver/sync_service.h" -#include "components/unified_consent/unified_consent_metrics.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/main/browser.h" -#import "ios/chrome/browser/signin/authentication_service.h" -#import "ios/chrome/browser/signin/authentication_service_factory.h" -#include "ios/chrome/browser/sync/profile_sync_service_factory.h" -#include "ios/chrome/browser/sync/sync_setup_service.h" -#include "ios/chrome/browser/sync/sync_setup_service_factory.h" -#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" -#import "ios/chrome/browser/ui/icons/chrome_icon.h" -#import "ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.h" -#import "ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.h" -#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.h" -#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_mode.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ui/base/l10n/l10n_util_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -using l10n_util::GetNSString; - -// Advanced sign-in settings result. -typedef NS_ENUM(NSInteger, AdvancedSigninSettingsCoordinatorResult) { - // The user confirmed the advanced sync settings. - AdvancedSyncSettingsCoordinatorResultConfirm, - // The user canceled the advanced sync settings. - AdvancedSigninSettingsCoordinatorResultCancel, - // Chrome aborted the advanced sync settings. - AdvancedSigninSettingsCoordinatorResultInterrupted, -}; - -@interface AdvancedSigninSettingsCoordinator () < - UIAdaptivePresentationControllerDelegate> - -// Google services settings coordinator. -@property(nonatomic, strong) - GoogleServicesSettingsCoordinator* googleServicesSettingsCoordinator; -// Advanced signin settings navigation controller. -@property(nonatomic, strong) AdvancedSigninSettingsNavigationController* - advancedSigninSettingsNavigationController; -// Confirm cancel sign-in/sync dialog. -@property(nonatomic, strong) - AlertCoordinator* cancelConfirmationAlertCoordinator; - -@end - -@implementation AdvancedSigninSettingsCoordinator - -- (void)start { - // Create the navigation controller. - self.advancedSigninSettingsNavigationController = - [[AdvancedSigninSettingsNavigationController alloc] init]; - - // Shorter name to make line wrapping better. - AdvancedSigninSettingsNavigationController* controller = - self.advancedSigninSettingsNavigationController; - controller.modalPresentationStyle = UIModalPresentationFormSheet; - controller.presentationController.delegate = self; - - // Init and start Google settings coordinator. - GoogleServicesSettingsMode mode = - GoogleServicesSettingsModeAdvancedSigninSettings; - self.googleServicesSettingsCoordinator = - [[GoogleServicesSettingsCoordinator alloc] - initWithBaseViewController:controller - browser:self.browser - mode:mode]; - self.googleServicesSettingsCoordinator.navigationController = controller; - // Starting the coordinator will add its view controller to the navigation - // controller. - [self.googleServicesSettingsCoordinator start]; - - // Set navigation items for settings coordinator. - self.googleServicesSettingsCoordinator.viewController.navigationItem - .leftBarButtonItem = [self navigationCancelButton]; - self.googleServicesSettingsCoordinator.viewController.navigationItem - .rightBarButtonItem = [self navigationConfirmButton]; - - // Present the navigation controller that now contains the Google settings - // view controller. - [self.baseViewController presentViewController:controller - animated:YES - completion:nil]; -} - -- (void)abortWithDismiss:(BOOL)dismiss - animated:(BOOL)animated - completion:(ProceduralBlock)completion { - if (!self.advancedSigninSettingsNavigationController) { - if (completion) { - completion(); - } - return; - } - DCHECK_EQ(self.advancedSigninSettingsNavigationController, - self.baseViewController.presentedViewController); - if (dismiss) { - [self dismissViewControllerAndFinishWithResult: - AdvancedSigninSettingsCoordinatorResultInterrupted - animated:animated - completion:completion]; - } else { - [self - finishedWithResult:AdvancedSigninSettingsCoordinatorResultInterrupted]; - if (completion) { - completion(); - } - } -} - -#pragma mark - UIAdaptivePresentationControllerDelegate - -- (BOOL)presentationControllerShouldDismiss: - (UIPresentationController*)presentationController { - return NO; -} - -- (void)presentationControllerDidAttemptToDismiss: - (UIPresentationController*)presentationController { - [self showDismissAlertDialog]; -} - -#pragma mark - Private - -// Called once the view controller has been removed (if needed). -// |result|, YES if the user accepts to sync. -- (void)finishedWithResult:(AdvancedSigninSettingsCoordinatorResult)result { - DCHECK(self.advancedSigninSettingsNavigationController); - SyncSetupService* syncSetupService = - SyncSetupServiceFactory::GetForBrowserState( - self.browser->GetBrowserState()); - switch (result) { - case AdvancedSyncSettingsCoordinatorResultConfirm: { - base::RecordAction( - base::UserMetricsAction("Signin_Signin_ConfirmAdvancedSyncSettings")); - syncer::SyncService* syncService = - ProfileSyncServiceFactory::GetForBrowserState( - self.browser->GetBrowserState()); - unified_consent::metrics::RecordSyncSetupDataTypesHistrogam( - syncService->GetUserSettings(), - self.browser->GetBrowserState()->GetPrefs()); - if (syncSetupService->IsSyncEnabled()) { - // FirstSetupComplete flag should be only turned on when the user agrees - // to start Sync. - syncSetupService->PrepareForFirstSyncSetup(); - syncSetupService->SetFirstSetupComplete( - syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM); - } - break; - } - case AdvancedSigninSettingsCoordinatorResultCancel: - base::RecordAction(base::UserMetricsAction( - "Signin_Signin_ConfirmCancelAdvancedSyncSettings")); - syncSetupService->CommitSyncChanges(); - AuthenticationServiceFactory::GetForBrowserState( - self.browser->GetBrowserState()) - ->SignOut(signin_metrics::ABORT_SIGNIN, - /*force_clear_browsing_data=*/false, nil); - break; - case AdvancedSigninSettingsCoordinatorResultInterrupted: - base::RecordAction( - base::UserMetricsAction("Signin_Signin_AbortAdvancedSyncSettings")); - break; - } - [self.googleServicesSettingsCoordinator stop]; - self.googleServicesSettingsCoordinator.delegate = nil; - self.googleServicesSettingsCoordinator = nil; - DCHECK(!syncSetupService->HasUncommittedChanges()) - << "-[GoogleServicesSettingsCoordinator stop] should commit sync " - "changes."; - BOOL signedin = result != AdvancedSigninSettingsCoordinatorResultCancel; - [self.delegate advancedSigninSettingsCoordinatorDidClose:self - signedin:signedin]; - self.advancedSigninSettingsNavigationController = nil; -} - -// This method should be moved to the view controller. -- (UIBarButtonItem*)navigationCancelButton { - UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] - initWithBarButtonSystemItem:UIBarButtonSystemItemCancel - target:self - action:@selector(showDismissAlertDialog)]; - cancelButton.accessibilityIdentifier = kSyncSettingsCancelButtonId; - return cancelButton; -} - -// This method should be moved to the view controller. -- (UIBarButtonItem*)navigationConfirmButton { - UIBarButtonItem* confirmButton = [[UIBarButtonItem alloc] - initWithTitle:GetNSString( - IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CONFIRM_MAIN_BUTTON) - style:UIBarButtonItemStyleDone - target:self - action:@selector(navigationConfirmButtonAction)]; - confirmButton.accessibilityIdentifier = kSyncSettingsConfirmButtonId; - return confirmButton; -} - -// Presents an UIAlert to ask the user if wants to cancel the sign-in. -- (void)showDismissAlertDialog { - base::RecordAction( - base::UserMetricsAction("Signin_Signin_CancelAdvancedSyncSettings")); - self.cancelConfirmationAlertCoordinator = [[AlertCoordinator alloc] - initWithBaseViewController:self.advancedSigninSettingsNavigationController - title: - GetNSString( - IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_TITLE) - message: - GetNSString( - IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_MESSAGE)]; - __weak __typeof(self) weakSelf = self; - [self.cancelConfirmationAlertCoordinator - addItemWithTitle: - GetNSString( - IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_BACK_BUTTON) - action:^{ - [weakSelf alertButtonActionWithCancelSync:NO]; - } - style:UIAlertActionStyleCancel]; - [self.cancelConfirmationAlertCoordinator - addItemWithTitle: - GetNSString( - IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_CANCEL_SYNC_BUTTON) - action:^{ - [weakSelf alertButtonActionWithCancelSync:YES]; - } - style:UIAlertActionStyleDefault]; - [self.cancelConfirmationAlertCoordinator start]; -} - -// Called by the confirm button from tne navigation controller. Validates the -// sync preferences chosen by the user, starts the sync, close the completion -// callback and closes the advanced sign-in settings. -- (void)navigationConfirmButtonAction { - DCHECK_EQ(self.advancedSigninSettingsNavigationController, - self.baseViewController.presentedViewController); - [self dismissViewControllerAndFinishWithResult: - AdvancedSyncSettingsCoordinatorResultConfirm - animated:YES - completion:nil]; -} - -// Called when a button of |self.cancelConfirmationAlertCoordinator| is pressed. -- (void)alertButtonActionWithCancelSync:(BOOL)cancelSync { - DCHECK(self.cancelConfirmationAlertCoordinator); - [self.cancelConfirmationAlertCoordinator stop]; - self.cancelConfirmationAlertCoordinator = nil; - if (cancelSync) { - [self dismissViewControllerAndFinishWithResult: - AdvancedSigninSettingsCoordinatorResultCancel - animated:YES - completion:nil]; - } else { - base::RecordAction(base::UserMetricsAction( - "Signin_Signin_CancelCancelAdvancedSyncSettings")); - } -} - -// Dismisses the current view controller with animation, and calls -// -[self finishedWithResult:] with |result|. -- (void)dismissViewControllerAndFinishWithResult: - (AdvancedSigninSettingsCoordinatorResult)result - animated:(BOOL)animated - completion:(ProceduralBlock)completion { - DCHECK_EQ(self.advancedSigninSettingsNavigationController, - self.baseViewController.presentedViewController); - __weak __typeof(self) weakSelf = self; - ProceduralBlock dismissCompletion = ^() { - [weakSelf finishedWithResult:result]; - if (completion) { - completion(); - } - }; - [self.baseViewController dismissViewControllerAnimated:animated - completion:dismissCompletion]; -} - -@end
diff --git a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.h b/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.h deleted file mode 100644 index 8e520b0..0000000 --- a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.h +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_NAVIGATION_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_NAVIGATION_CONTROLLER_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" - -// View controller to related to AdvancedSigninSettingsCoordinator. -@interface AdvancedSigninSettingsNavigationController - : SettingsNavigationController - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_GOOGLE_SERVICES_ADVANCED_SIGNIN_SETTINGS_NAVIGATION_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.mm deleted file mode 100644 index dbad3c6..0000000 --- a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.mm +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_navigation_controller.h" - -#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation AdvancedSigninSettingsNavigationController - -- (UIViewController*)popViewControllerAnimated:(BOOL)animated { - UIViewController* poppedViewController = - [super popViewControllerAnimated:animated]; - if ([poppedViewController - respondsToSelector:@selector(viewControllerWasPopped)]) { - [poppedViewController performSelector:@selector(viewControllerWasPopped)]; - } - return poppedViewController; -} - -@end
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.mm index 038415b..7362c7a 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.mm
@@ -272,6 +272,7 @@ - (void)manageSyncSettingsCoordinatorWasPopped: (ManageSyncSettingsCoordinator*)coordinator { DCHECK_EQ(self.manageSyncSettingsCoordinator, coordinator); + [self.manageSyncSettingsCoordinator stop]; self.manageSyncSettingsCoordinator = nil; }
diff --git a/ios/chrome/browser/ui/settings/settings_controller_protocol.h b/ios/chrome/browser/ui/settings/settings_controller_protocol.h new file mode 100644 index 0000000..22ec1e10 --- /dev/null +++ b/ios/chrome/browser/ui/settings/settings_controller_protocol.h
@@ -0,0 +1,24 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_SETTINGS_CONTROLLER_PROTOCOL_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_SETTINGS_CONTROLLER_PROTOCOL_H_ + +#import <UIKit/UIKit.h> + +// Protocol for settings view controllers. +@protocol SettingsControllerProtocol <NSObject> + +@optional + +// Notifies the controller that the settings screen is being dismissed. +- (void)settingsWillBeDismissed; + +// Notifies the controller that is popped out from the settings navigation +// controller. +- (void)viewControllerWasPopped; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SETTINGS_CONTROLLER_PROTOCOL_H_
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.h b/ios/chrome/browser/ui/settings/settings_navigation_controller.h index da9bb71..baf9feb 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.h +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.h
@@ -8,6 +8,7 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/commands/application_commands.h" +#import "ios/chrome/browser/ui/settings/settings_controller_protocol.h" class Browser; @protocol BrowserCommands; @@ -18,19 +19,6 @@ // The accessibility identifier for the settings' "Done" button. extern NSString* const kSettingsDoneButtonId; -@protocol SettingsControllerProtocol<NSObject> - -@optional - -// Notifies the controller that the settings screen is being dismissed. -- (void)settingsWillBeDismissed; - -// Notifies the controller that is popped out from the settings navigation -// controller. -- (void)viewControllerWasPopped; - -@end - @protocol SettingsNavigationControllerDelegate<NSObject> // Informs the delegate that the settings navigation controller should be
diff --git a/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm b/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm index e8a8ea7..8c06a003 100644 --- a/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm +++ b/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm
@@ -11,7 +11,6 @@ #import "ios/chrome/browser/ui/authentication/authentication_ui_util.h" #import "ios/chrome/browser/ui/authentication/signin/signin_coordinator.h" #import "ios/chrome/browser/ui/commands/application_commands.h" -#import "ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.h" #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_controller.h" #import "ios/chrome/browser/ui/signin_interaction/signin_interaction_presenting.h" @@ -19,9 +18,7 @@ #error "This file requires ARC support." #endif -@interface SigninInteractionCoordinator () < - AdvancedSigninSettingsCoordinatorDelegate, - SigninInteractionPresenting> +@interface SigninInteractionCoordinator () <SigninInteractionPresenting> // Coordinator to present alerts. @property(nonatomic, strong) AlertCoordinator* alertCoordinator; @@ -43,10 +40,6 @@ // Sign-in completion. @property(nonatomic, copy) signin_ui::CompletionCallback signinCompletion; -// Advanced sign-in settings coordinator. -@property(nonatomic, strong) - AdvancedSigninSettingsCoordinator* advancedSigninSettingsCoordinator; - @end @implementation SigninInteractionCoordinator @@ -130,28 +123,24 @@ - (void)cancel { [self.controller cancel]; [self interrupSigninCoordinatorWithAction: - SigninCoordinatorInterruptActionNoDismiss]; - [self.advancedSigninSettingsCoordinator abortWithDismiss:NO - animated:YES - completion:nil]; + SigninCoordinatorInterruptActionNoDismiss + completion:nil]; } - (void)cancelAndDismiss { [self.controller cancelAndDismiss]; [self interrupSigninCoordinatorWithAction: - SigninCoordinatorInterruptActionDismissWithAnimation]; - [self.advancedSigninSettingsCoordinator abortWithDismiss:YES - animated:YES - completion:nil]; + SigninCoordinatorInterruptActionDismissWithAnimation + completion:nil]; } - (void)abortAndDismissSettingsViewAnimated:(BOOL)animated completion:(ProceduralBlock)completion { DCHECK(!self.controller); - DCHECK(self.advancedSigninSettingsCoordinator); - [self.advancedSigninSettingsCoordinator abortWithDismiss:YES - animated:animated - completion:completion]; + SigninCoordinatorInterruptAction action = + animated ? SigninCoordinatorInterruptActionDismissWithAnimation + : SigninCoordinatorInterruptActionDismissWithoutAnimation; + [self interrupSigninCoordinatorWithAction:action completion:completion]; } #pragma mark - Properties @@ -161,17 +150,7 @@ } - (BOOL)isSettingsViewPresented { - return self.advancedSigninSettingsCoordinator != nil; -} - -#pragma mark - AdvancedSigninSettingsCoordinatorDelegate - -- (void)advancedSigninSettingsCoordinatorDidClose: - (AdvancedSigninSettingsCoordinator*)coordinator - signedin:(BOOL)signedin { - DCHECK_EQ(self.advancedSigninSettingsCoordinator, coordinator); - self.advancedSigninSettingsCoordinator = nil; - [self signinDoneWithSuccess:signedin]; + return self.coordinator.isSettingsViewPresented; } #pragma mark - SigninInteractionPresenting @@ -280,14 +259,25 @@ // Shows the advanced sign-in settings UI. - (void)showAdvancedSigninSettings { - DCHECK(!self.advancedSigninSettingsCoordinator); + DCHECK(!self.coordinator); DCHECK(self.presentingViewController); - self.advancedSigninSettingsCoordinator = - [[AdvancedSigninSettingsCoordinator alloc] - initWithBaseViewController:self.presentingViewController - browser:self.browser]; - self.advancedSigninSettingsCoordinator.delegate = self; - [self.advancedSigninSettingsCoordinator start]; + self.coordinator = [SigninCoordinator + advancedSettingsSigninCoordinatorWithBaseViewController: + self.presentingViewController + browser:self.browser]; + __weak SigninInteractionCoordinator* weakSelf = self; + self.coordinator.signinCompletion = + ^(SigninCoordinatorResult signinResult, ChromeIdentity* identity) { + [weakSelf advancedSigninDoneWithSigninResult:signinResult]; + }; + [self.coordinator start]; +} + +- (void)advancedSigninDoneWithSigninResult: + (SigninCoordinatorResult)signinResult { + [self.coordinator stop]; + self.coordinator = nil; + [self signinDoneWithSuccess:signinResult == SigninCoordinatorResultSuccess]; } // Called when the sign-in is done. @@ -299,18 +289,19 @@ self.signinCompletion(success); self.signinCompletion = nil; } - [self.advancedSigninSettingsCoordinator stop]; - self.advancedSigninSettingsCoordinator = nil; - self.presentingViewController = nil; } - (void)interrupSigninCoordinatorWithAction: - (SigninCoordinatorInterruptAction)action { + (SigninCoordinatorInterruptAction)action + completion:(ProceduralBlock)completion { __weak __typeof(self) weakSelf = self; ProceduralBlock interruptCompletion = ^() { // |weakSelf.coordinator.signinCompletion| is called before this interrupt // block. The signin completion has to set |coordinator| to nil. DCHECK(!weakSelf.coordinator); + if (completion) { + completion(); + } }; [self.coordinator interruptWithAction:action completion:interruptCompletion]; }
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm index ef0ad8b..b2adc68 100644 --- a/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm +++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm
@@ -159,16 +159,10 @@ #pragma mark - FakeboxFocuser -- (void)focusOmniboxNoAnimation { - self.enableAnimationsForOmniboxFocus = NO; - [self fakeboxFocused]; +- (void)focusLocationBarWithAnimation:(BOOL)animated { + self.enableAnimationsForOmniboxFocus = animated; + [self transitionToLocationBarFocusedState:YES]; self.enableAnimationsForOmniboxFocus = YES; - // If the pasteboard is containing a URL, the omnibox popup suggestions are - // displayed as soon as the omnibox is focused. - // If the fake omnibox animation is triggered at the same time, it is possible - // to see the NTP going up where the real omnibox should be displayed. - if ([self.locationBarCoordinator omniboxPopupHasAutocompleteResults]) - [self onFakeboxAnimationComplete]; } - (void)fakeboxFocused { @@ -214,12 +208,9 @@ // Sets the location bar up. - (void)setUpLocationBar { - self.locationBarCoordinator = [[LocationBarCoordinator alloc] init]; - - self.locationBarCoordinator.browser = self.browser; - self.locationBarCoordinator.dispatcher = self.browser->GetCommandDispatcher(); - self.locationBarCoordinator.commandDispatcher = - self.browser->GetCommandDispatcher(); + self.locationBarCoordinator = + [[LocationBarCoordinator alloc] initWithBaseViewController:nil + browser:self.browser]; self.locationBarCoordinator.delegate = self.delegate; self.locationBarCoordinator.popupPresenterDelegate = self.popupPresenterDelegate;
diff --git a/ios/chrome/browser/ui/toolbar/public/fakebox_focuser.h b/ios/chrome/browser/ui/toolbar/public/fakebox_focuser.h index 59808d55..998d9711 100644 --- a/ios/chrome/browser/ui/toolbar/public/fakebox_focuser.h +++ b/ios/chrome/browser/ui/toolbar/public/fakebox_focuser.h
@@ -10,8 +10,8 @@ // This protocol provides callbacks for focusing and blurring the fake omnibox // on NTP. @protocol FakeboxFocuser -// Focuses the omnibox without animations. -- (void)focusOmniboxNoAnimation; +// Focuses the location bar. +- (void)focusLocationBarWithAnimation:(BOOL)animated; // Give focus to the omnibox, but indicate that the focus event was initiated // from the fakebox on the Google landing page. - (void)fakeboxFocused;
diff --git a/ios/chrome/browser/url_loading/url_loading_util.h b/ios/chrome/browser/url_loading/url_loading_util.h index 05f373a..cfdc1592 100644 --- a/ios/chrome/browser/url_loading/url_loading_util.h +++ b/ios/chrome/browser/url_loading/url_loading_util.h
@@ -10,6 +10,7 @@ #include "components/sessions/core/session_id.h" #include "ui/base/window_open_disposition.h" +class Browser; class ChromeBrowserState; class GURL; @@ -31,6 +32,6 @@ // into |browser_state|. void RestoreTab(const SessionID session_id, WindowOpenDisposition disposition, - ChromeBrowserState* browser_state); + Browser* browser); #endif // IOS_CHROME_BROWSER_URL_LOADING_URL_LOADING_UTIL_H_
diff --git a/ios/chrome/browser/url_loading/url_loading_util.mm b/ios/chrome/browser/url_loading/url_loading_util.mm index dda8de5d7..6d4c40cf 100644 --- a/ios/chrome/browser/url_loading/url_loading_util.mm +++ b/ios/chrome/browser/url_loading/url_loading_util.mm
@@ -12,8 +12,7 @@ #import "ios/chrome/browser/prerender/prerender_service.h" #import "ios/chrome/browser/prerender/prerender_service_factory.h" #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h" -#include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h" +#include "ios/chrome/browser/sessions/live_tab_context_browser_agent.h" #import "ios/chrome/browser/web/load_timing_tab_helper.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/web/public/web_state.h" @@ -47,12 +46,19 @@ void RestoreTab(const SessionID session_id, WindowOpenDisposition disposition, - ChromeBrowserState* browser_state) { - TabRestoreServiceDelegateImplIOS* delegate = - TabRestoreServiceDelegateImplIOSFactory::GetForBrowserState( - browser_state); + Browser* browser) { + // iOS Chrome doesn't yet support restoring tabs to new windows. + // TODO(crbug.com/1056596) : Support WINDOW restoration under multi-window. + DCHECK(disposition != WindowOpenDisposition::NEW_WINDOW); + LiveTabContextBrowserAgent* context = + LiveTabContextBrowserAgent::FromBrowser(browser); + // Passing a nil context into RestoreEntryById can result in the restore + // service requesting a new window. This is unsupported on iOS (see above + // TODO). + DCHECK(context); + ChromeBrowserState* browser_state = + browser->GetBrowserState()->GetOriginalChromeBrowserState(); sessions::TabRestoreService* restoreService = - IOSChromeTabRestoreServiceFactory::GetForBrowserState( - browser_state->GetOriginalChromeBrowserState()); - restoreService->RestoreEntryById(delegate, session_id, disposition); + IOSChromeTabRestoreServiceFactory::GetForBrowserState(browser_state); + restoreService->RestoreEntryById(context, session_id, disposition); }
diff --git a/ios/chrome/browser/web/navigation_egtest.mm b/ios/chrome/browser/web/navigation_egtest.mm index 2ef84eef..cab4855 100644 --- a/ios/chrome/browser/web/navigation_egtest.mm +++ b/ios/chrome/browser/web/navigation_egtest.mm
@@ -562,8 +562,7 @@ // Tests that navigating forward from a WebUI URL works when resuming from // session restore. This is a regression test for https://crbug.com/814790. -// Flaky: https://crbug.com/1054372 -- (void)DISABLED_testRestoreHistoryToWebUIAndNavigateForward { +- (void)testRestoreHistoryToWebUIAndNavigateForward { GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); const GURL destinationURL = self.testServer->GetURL(kSimpleFileBasedTestURL); [ChromeEarlGrey loadURL:GURL("chrome://version")]; @@ -603,8 +602,7 @@ // Tests that restoring a placeholder URL is correctly restored. This is a // regression test from http://crbug.com/1011758. -// Flaky: https://crbug.com/1054372 -- (void)DISABLED_testRestoreHistoryToPlaceholderURL { +- (void)testRestoreHistoryToPlaceholderURL { GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); const GURL destinationURL("chrome://crash"); [ChromeEarlGrey loadURL:destinationURL];
diff --git a/ios/chrome/credential_provider_extension/credential_provider_extension_localize_strings_config.plist b/ios/chrome/credential_provider_extension/credential_provider_extension_localize_strings_config.plist index 6a72e8e..c79a398 100644 --- a/ios/chrome/credential_provider_extension/credential_provider_extension_localize_strings_config.plist +++ b/ios/chrome/credential_provider_extension/credential_provider_extension_localize_strings_config.plist
@@ -16,6 +16,8 @@ <string>IDS_IOS_CREDENTIAL_PROVIDER_CONSENT_ENABLE_BUTTON_TITLE</string> <string>IDS_IOS_CREDENTIAL_PROVIDER_CONSENT_SUBTITLE</string> <string>IDS_IOS_CREDENTIAL_PROVIDER_CONSENT_TITLE</string> + <string>IDS_IOS_CREDENTIAL_PROVIDER_EMPTY_CREDENTIALS_SUBTITLE</string> + <string>IDS_IOS_CREDENTIAL_PROVIDER_EMPTY_CREDENTIALS_TITLE</string> <string>IDS_IOS_CREDENTIAL_PROVIDER_EXTENSION_CANCEL</string> <string>IDS_IOS_CREDENTIAL_PROVIDER_STALE_CREDENTIALS_SUBTITLE</string> <string>IDS_IOS_CREDENTIAL_PROVIDER_STALE_CREDENTIALS_TITLE</string>
diff --git a/ios/chrome/credential_provider_extension/strings/ios_credential_provider_extension_strings.grd b/ios/chrome/credential_provider_extension/strings/ios_credential_provider_extension_strings.grd index 7e8b504..d9b6c6d 100644 --- a/ios/chrome/credential_provider_extension/strings/ios_credential_provider_extension_strings.grd +++ b/ios/chrome/credential_provider_extension/strings/ios_credential_provider_extension_strings.grd
@@ -166,6 +166,12 @@ <message name="IDS_IOS_CREDENTIAL_PROVIDER_CONSENT_TITLE" desc="Title for consent screen. 'AutoFill' matches what Apple shows in settings. For other languages see: Settings > Safari > AutoFill." meaning="Title to show when enabling the extension"> AutoFill Chrome Passwords </message> + <message name="IDS_IOS_CREDENTIAL_PROVIDER_EMPTY_CREDENTIALS_SUBTITLE" desc="Subtitle for empty credentials screen" meaning="Subtitle to show when a user has no credentials available."> + Save some passwords in Chrome to get started. If you already have passwords stored in your Google account, sign in to Chrome and turn on sync to see them here. + </message> + <message name="IDS_IOS_CREDENTIAL_PROVIDER_EMPTY_CREDENTIALS_TITLE" desc="Title for empty credentials screen." meaning="Title to show when a user has no credentials available."> + No Chrome Passwords + </message> <message name="IDS_IOS_CREDENTIAL_PROVIDER_EXTENSION_CANCEL" desc="Title for cancel buttons" meaning="Title for buttons meant to cancel an action [Length: 10 chars]"> Cancel </message>
diff --git a/ios/chrome/credential_provider_extension/ui/BUILD.gn b/ios/chrome/credential_provider_extension/ui/BUILD.gn index d2ee457..dec1cfb 100644 --- a/ios/chrome/credential_provider_extension/ui/BUILD.gn +++ b/ios/chrome/credential_provider_extension/ui/BUILD.gn
@@ -6,6 +6,8 @@ sources = [ "consent_view_controller.h", "consent_view_controller.mm", + "empty_credentials_view_controller.h", + "empty_credentials_view_controller.mm", "stale_credentials_view_controller.h", "stale_credentials_view_controller.mm", ]
diff --git a/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.h b/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.h new file mode 100644 index 0000000..9d798c42 --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.h
@@ -0,0 +1,13 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_CREDENTIAL_PROVIDER_EXTENSION_UI_EMPTY_CREDENTIALS_VIEW_CONTROLLER_H_ +#define IOS_CHROME_CREDENTIAL_PROVIDER_EXTENSION_UI_EMPTY_CREDENTIALS_VIEW_CONTROLLER_H_ + +#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h" + +@interface EmptyCredentialsViewController : ConfirmationAlertViewController +@end + +#endif // IOS_CHROME_CREDENTIAL_PROVIDER_EXTENSION_UI_EMPTY_CREDENTIALS_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.mm b/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.mm new file mode 100644 index 0000000..0351e54e --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.mm
@@ -0,0 +1,30 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation EmptyCredentialsViewController + +#pragma mark - Public + +- (void)loadView { + self.imageName = @"empty_credentials_illustration"; + self.helpButtonAvailable = NO; + self.primaryActionAvailable = NO; + NSString* titleString = + NSLocalizedString(@"IDS_IOS_CREDENTIAL_PROVIDER_EMPTY_CREDENTIALS_TITLE", + @"The title in the empty credentials screen."); + NSString* subtitleString = NSLocalizedString( + @"IDS_IOS_CREDENTIAL_PROVIDER_EMPTY_CREDENTIALS_SUBTITLE", + @"The subtitle in the empty credentials screen."); + self.titleString = titleString; + self.subtitleString = subtitleString; + [super loadView]; +} + +@end
diff --git a/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn b/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn index 81dfaa9..13e48c5 100644 --- a/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn +++ b/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn
@@ -8,6 +8,7 @@ group("resources") { deps = [ ":consent_illustration", + ":empty_credentials_illustration", ":stale_credentials_illustration", ] } @@ -20,6 +21,14 @@ ] } +imageset("empty_credentials_illustration") { + sources = [ + "empty_credentials_illustration.imageset/Contents.json", + "empty_credentials_illustration.imageset/illustration_dark.png", + "empty_credentials_illustration.imageset/illustration_light.png", + ] +} + imageset("stale_credentials_illustration") { sources = [ "stale_credentials_illustration.imageset/Contents.json",
diff --git a/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/Contents.json b/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/Contents.json new file mode 100644 index 0000000..e5b1b4d6 --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/Contents.json
@@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "illustration_light.png" + }, + { + "idiom" : "universal", + "filename" : "illustration_dark.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ] + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file
diff --git a/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/illustration_dark.png b/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/illustration_dark.png new file mode 100644 index 0000000..dc7bb7b --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/illustration_dark.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/illustration_light.png b/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/illustration_light.png new file mode 100644 index 0000000..9edcfcba --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/no_data_illustration.imageset/illustration_light.png Binary files differ
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 7665b29..9bc0146 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -253,6 +253,7 @@ "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/authentication:authentication", "//ios/chrome/browser/ui/authentication/cells", + "//ios/chrome/browser/ui/authentication/signin/advanced_settings_signin:constants", "//ios/chrome/browser/ui/autofill:autofill_ui", "//ios/chrome/browser/ui/autofill/manual_fill", "//ios/chrome/browser/ui/autofill/manual_fill:manual_fill_ui", @@ -392,6 +393,7 @@ "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/authentication:eg_app_support+eg2", "//ios/chrome/browser/ui/authentication/cells", + "//ios/chrome/browser/ui/authentication/signin/advanced_settings_signin:constants", "//ios/chrome/browser/ui/autofill:autofill_ui", "//ios/chrome/browser/ui/autofill:eg_app_support+eg2", "//ios/chrome/browser/ui/autofill/manual_fill",
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm index ec78272..1968237 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -9,6 +9,7 @@ #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/autofill/form_suggestion_constants.h" #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_constants.h" +#import "ios/chrome/browser/ui/authentication/signin/advanced_settings_signin/advanced_settings_signin_constants.h" #import "ios/chrome/browser/ui/autofill/manual_fill/address_view_controller.h" #import "ios/chrome/browser/ui/autofill/manual_fill/card_coordinator.h" #import "ios/chrome/browser/ui/autofill/manual_fill/card_view_controller.h" @@ -38,7 +39,6 @@ #import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_ui_constants.h" #import "ios/chrome/browser/ui/settings/credit_card_scanner/credit_card_scanner_view_controller.h" #import "ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller_constants.h" -#import "ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_constants.h" #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_constants.h" #import "ios/chrome/browser/ui/settings/import_data_table_view_controller.h" #import "ios/chrome/browser/ui/settings/password/passwords_table_view_constants.h"
diff --git a/ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni b/ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni index f1a1a9c..f8806ec 100644 --- a/ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni +++ b/ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni
@@ -137,9 +137,12 @@ ios_eg2_test(target_name) { forward_variables_from(invoker, [ - "xcode_test_application_name", "deps", "data_deps", + "executable_args", + "retries", + "shards", + "xcode_test_application_name", ]) xctest_bundle_principal_class = "ChromeEGTestBundleMain"
diff --git a/ios/third_party/earl_grey/ios_eg_test.gni b/ios/third_party/earl_grey/ios_eg_test.gni index 82024fb..64bade8 100644 --- a/ios/third_party/earl_grey/ios_eg_test.gni +++ b/ios/third_party/earl_grey/ios_eg_test.gni
@@ -2,14 +2,25 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/ios/ios_test_runner_wrapper.gni") import("//build/config/ios/rules.gni") import("//ios/build/chrome_build.gni") import("//ios/public/provider/chrome/browser/build_config.gni") # EarlGrey tests are just XCTests that also depends on EarlGrey. template("ios_eg_test") { - ios_xctest_test(target_name) { - forward_variables_from(invoker, "*") + _target_name = target_name + _test_target = "${target_name}_test" + ios_xctest_test(_test_target) { + forward_variables_from(invoker, + "*", + [ + "executable_args", + "retries", + "shards", + "xctest", + "xcode_parallelization", + ]) if (!defined(bundle_deps)) { bundle_deps = [] } @@ -28,6 +39,55 @@ "//ios/third_party/earl_grey:earl_grey+link", "//ios/third_party/ochamcrest:ochamcrest+link", ] + + # TODO(crbug.com/1056328) Because we change the target name, the subnodes + # are going to append with the _test in the naming, which won't be backwards + # compatible during migration from iOS recipe to Chromium. + output_name = "${_target_name}" + } + + ios_test_runner_wrapper(target_name) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "executable_args", + "retries", + "shards", + "xctest", + "xcode_parallelization", + ]) + + _root_build_dir = rebase_path("${root_build_dir}", root_build_dir) + + # include the test target above as data_deps + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":${_test_target}" ] + + if (!defined(executable_args)) { + executable_args = [] + } + + # EG test apps are *.app format. No host, but required xctest and may need + # xcode-parallelization + executable_args += [ + "--app", + "@WrappedPath(${_root_build_dir}/${target_name}.app)", + ] + + # Default xctest to true for EG tests. If set, only set arg if value = true + if (!defined(xctest) || (defined(xctest) && xctest)) { + executable_args += [ "--xctest" ] + } + + # Default xcode_parallelization to true for EG tests. + if (!defined(xcode_parallelization) || + (defined(xcode_parallelization) && xcode_parallelization)) { + executable_args += [ "--xcode-parallelization" ] + } } }
diff --git a/ios/third_party/earl_grey2/ios_eg2_test.gni b/ios/third_party/earl_grey2/ios_eg2_test.gni index 02dd117..5f2c44f 100644 --- a/ios/third_party/earl_grey2/ios_eg2_test.gni +++ b/ios/third_party/earl_grey2/ios_eg2_test.gni
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/ios/ios_test_runner_wrapper.gni") import("//build/config/ios/rules.gni") import("//ios/build/chrome_build.gni") import("//ios/public/provider/chrome/browser/build_config.gni") @@ -63,7 +64,9 @@ defined(invoker.deps), "deps must be defined for $target_name to include at least one earl grey test file.") - ios_xcuitest_test(target_name) { + _target_name = target_name + _test_target = "${target_name}_test" + ios_xcuitest_test(_test_target) { forward_variables_from(invoker, [ "xcode_test_application_name", @@ -77,6 +80,51 @@ deps = [] } deps += [ "//ios/third_party/earl_grey2:test_lib" ] + + # TODO(crbug.com/1056328) Because we change the target name, the subnodes + # are going to append with the _test in the naming, which won't be backwards + # compatible during migration from iOS recipe to Chromium. + output_name = "${_target_name}" + } + + ios_test_runner_wrapper(target_name) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "executable_args", + "retries", + "shards", + "xcode_test_application_name", + ]) + _root_build_dir = rebase_path("${root_build_dir}", root_build_dir) + + if (!defined(data_deps)) { + data_deps = [] + } + + # Include the top ios_eg2_test target, and the host app + data_deps += [ ":${_test_target}" ] + + if (!defined(executable_args)) { + executable_args = [] + } + + # EG2 tests app are bundled as *-Runner.app, while the host app is bundled + # as *.app. + executable_args += [ + "--app", + "@WrappedPath(${_root_build_dir}/${target_name}-Runner.app)", + ] + executable_args += [ + "--host-app", + "@WrappedPath(${_root_build_dir}/${xcode_test_application_name}.app)", + ] + + # All EG2 tests require xcode-parallelization. EG2 doesn't use xctest, so we + # leave undefined + executable_args += [ "--xcode-parallelization" ] } }
diff --git a/media/audio/pulse/audio_manager_pulse.cc b/media/audio/pulse/audio_manager_pulse.cc index 829846f..1024ada3 100644 --- a/media/audio/pulse/audio_manager_pulse.cc +++ b/media/audio/pulse/audio_manager_pulse.cc
@@ -160,7 +160,7 @@ const std::string& device_id, const LogCallback& log_callback) { DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); - return MakeInputStream(params, device_id); + return MakeInputStream(params, device_id, log_callback); } AudioInputStream* AudioManagerPulse::MakeLowLatencyInputStream( @@ -168,7 +168,7 @@ const std::string& device_id, const LogCallback& log_callback) { DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); - return MakeInputStream(params, device_id); + return MakeInputStream(params, device_id, log_callback); } std::string AudioManagerPulse::GetDefaultInputDeviceID() { @@ -246,15 +246,18 @@ AudioOutputStream* AudioManagerPulse::MakeOutputStream( const AudioParameters& params, const std::string& device_id, - const LogCallback& log_callback) { + LogCallback log_callback) { DCHECK(!device_id.empty()); - return new PulseAudioOutputStream(params, device_id, this, log_callback); + return new PulseAudioOutputStream(params, device_id, this, + std::move(log_callback)); } AudioInputStream* AudioManagerPulse::MakeInputStream( - const AudioParameters& params, const std::string& device_id) { - return new PulseAudioInputStream(this, device_id, params, - input_mainloop_, input_context_); + const AudioParameters& params, + const std::string& device_id, + LogCallback log_callback) { + return new PulseAudioInputStream(this, device_id, params, input_mainloop_, + input_context_, std::move(log_callback)); } void AudioManagerPulse::UpdateNativeAudioHardwareInfo() {
diff --git a/media/audio/pulse/audio_manager_pulse.h b/media/audio/pulse/audio_manager_pulse.h index 256c163..4e10d88 100644 --- a/media/audio/pulse/audio_manager_pulse.h +++ b/media/audio/pulse/audio_manager_pulse.h
@@ -90,11 +90,12 @@ // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream. AudioOutputStream* MakeOutputStream(const AudioParameters& params, const std::string& device_id, - const LogCallback& log_callback); + LogCallback log_callback); // Called by MakeLinearInputStream and MakeLowLatencyInputStream. AudioInputStream* MakeInputStream(const AudioParameters& params, - const std::string& device_id); + const std::string& device_id, + LogCallback log_callback); // Updates |native_input_sample_rate_| and |native_channel_count_|. void UpdateNativeAudioHardwareInfo();
diff --git a/media/audio/pulse/pulse_input.cc b/media/audio/pulse/pulse_input.cc index 8afeadc..ed42cdb 100644 --- a/media/audio/pulse/pulse_input.cc +++ b/media/audio/pulse/pulse_input.cc
@@ -7,6 +7,7 @@ #include <stdint.h> #include "base/logging.h" +#include "base/strings/stringprintf.h" #include "media/audio/audio_device_description.h" #include "media/audio/pulse/audio_manager_pulse.h" #include "media/audio/pulse/pulse_util.h" @@ -14,19 +15,37 @@ namespace media { +namespace { + +PRINTF_FORMAT(2, 3) +void SendLogMessage(const AudioManagerBase::LogCallback& callback, + const char* format, + ...) { + if (callback.is_null()) + return; + va_list args; + va_start(args, format); + callback.Run("PAIS::" + base::StringPrintV(format, args)); + va_end(args); +} + +} // namespace + using pulse::AutoPulseLock; using pulse::WaitForOperationCompletion; // Number of blocks of buffers used in the |fifo_|. const int kNumberOfBlocksBufferInFifo = 2; -PulseAudioInputStream::PulseAudioInputStream(AudioManagerPulse* audio_manager, - const std::string& device_name, - const AudioParameters& params, - pa_threaded_mainloop* mainloop, - pa_context* context) +PulseAudioInputStream::PulseAudioInputStream( + AudioManagerPulse* audio_manager, + const std::string& device_name, + const AudioParameters& params, + pa_threaded_mainloop* mainloop, + pa_context* context, + AudioManager::LogCallback log_callback) : audio_manager_(audio_manager), - callback_(NULL), + callback_(nullptr), device_name_(device_name), params_(params), channels_(0), @@ -38,10 +57,13 @@ kNumberOfBlocksBufferInFifo), pa_mainloop_(mainloop), pa_context_(context), - handle_(NULL) { + log_callback_(std::move(log_callback)), + handle_(nullptr) { DCHECK(mainloop); DCHECK(context); CHECK(params_.IsValid()); + SendLogMessage(log_callback_, "%s({device_id=%s}, {params=[%s]})", __func__, + device_name.c_str(), params.AsHumanReadableString().c_str()); } PulseAudioInputStream::~PulseAudioInputStream() { @@ -52,13 +74,19 @@ bool PulseAudioInputStream::Open() { DCHECK(thread_checker_.CalledOnValidThread()); + SendLogMessage(log_callback_, "%s()", __func__); if (device_name_ == AudioDeviceDescription::kDefaultDeviceId && - audio_manager_->DefaultSourceIsMonitor()) + audio_manager_->DefaultSourceIsMonitor()) { + SendLogMessage(log_callback_, "%s => (ERROR: can't open monitor device)", + __func__); return false; + } AutoPulseLock auto_lock(pa_mainloop_); if (!pulse::CreateInputStream(pa_mainloop_, pa_context_, &handle_, params_, device_name_, &StreamNotifyCallback, this)) { + SendLogMessage(log_callback_, "%s => (ERROR: failed to open PA stream)", + __func__); return false; } @@ -71,6 +99,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(callback); DCHECK(handle_); + SendLogMessage(log_callback_, "%s()", __func__); // AGC needs to be started out of the lock. StartAgc(); @@ -97,6 +126,7 @@ void PulseAudioInputStream::Stop() { DCHECK(thread_checker_.CalledOnValidThread()); + SendLogMessage(log_callback_, "%s()", __func__); AutoPulseLock auto_lock(pa_mainloop_); if (!stream_started_) return; @@ -118,23 +148,24 @@ } // Stop the stream. - pa_stream_set_read_callback(handle_, NULL, NULL); + pa_stream_set_read_callback(handle_, nullptr, nullptr); operation = pa_stream_cork(handle_, 1, &pulse::StreamSuccessCallback, pa_mainloop_); if (!WaitForOperationCompletion(pa_mainloop_, operation, pa_context_, handle_)) { callback_->OnError(); } - callback_ = NULL; + callback_ = nullptr; } void PulseAudioInputStream::Close() { DCHECK(thread_checker_.CalledOnValidThread()); + SendLogMessage(log_callback_, "%s()", __func__); { AutoPulseLock auto_lock(pa_mainloop_); if (handle_) { // Disable all the callbacks before disconnecting. - pa_stream_set_state_callback(handle_, NULL, NULL); + pa_stream_set_state_callback(handle_, nullptr, nullptr); pa_operation* operation = pa_stream_flush(handle_, &pulse::StreamSuccessCallback, pa_mainloop_); WaitForOperationCompletion(pa_mainloop_, operation, pa_context_, handle_); @@ -144,7 +175,7 @@ // Release PulseAudio structures. pa_stream_unref(handle_); - handle_ = NULL; + handle_ = nullptr; } } @@ -161,9 +192,10 @@ AutoPulseLock auto_lock(pa_mainloop_); if (!handle_) return; + SendLogMessage(log_callback_, "%s({volume=%.2f})", __func__, volume); size_t index = pa_stream_get_device_index(handle_); - pa_operation* operation = NULL; + pa_operation* operation = nullptr; if (!channels_) { // Get the number of channels for the source only when the |channels_| is 0. // We are assuming the stream source is not changed on the fly here. @@ -172,7 +204,9 @@ if (!WaitForOperationCompletion(pa_mainloop_, operation, pa_context_, handle_) || !channels_) { - DLOG(WARNING) << "Failed to get the number of channels for the source"; + SendLogMessage(log_callback_, + "%s => (WARNING: failed to read number of channels)", + __func__); return; } } @@ -180,7 +214,7 @@ pa_cvolume pa_volume; pa_cvolume_set(&pa_volume, channels_, volume); operation = pa_context_set_source_volume_by_index( - pa_context_, index, &pa_volume, NULL, NULL); + pa_context_, index, &pa_volume, nullptr, nullptr); // Don't need to wait for this task to complete. pa_operation_unref(operation); @@ -309,7 +343,7 @@ params_.sample_rate())); do { size_t length = 0; - const void* data = NULL; + const void* data = nullptr; pa_stream_peek(handle_, &data, &length); if (!data || length == 0) break;
diff --git a/media/audio/pulse/pulse_input.h b/media/audio/pulse/pulse_input.h index 56b3906..6287ec8 100644 --- a/media/audio/pulse/pulse_input.h +++ b/media/audio/pulse/pulse_input.h
@@ -14,6 +14,7 @@ #include "media/audio/agc_audio_stream.h" #include "media/audio/audio_device_name.h" #include "media/audio/audio_io.h" +#include "media/audio/audio_manager.h" #include "media/base/audio_block_fifo.h" #include "media/base/audio_parameters.h" @@ -27,7 +28,8 @@ const std::string& device_name, const AudioParameters& params, pa_threaded_mainloop* mainloop, - pa_context* context); + pa_context* context, + AudioManager::LogCallback log_callback); ~PulseAudioInputStream() override; @@ -76,7 +78,12 @@ // PulseAudio API structs. pa_threaded_mainloop* pa_mainloop_; // Weak. + pa_context* pa_context_; // Weak. + + // Callback to send log messages to registered clients. + AudioManager::LogCallback log_callback_; + pa_stream* handle_; base::ThreadChecker thread_checker_;
diff --git a/media/audio/pulse/pulse_output.cc b/media/audio/pulse/pulse_output.cc index 65f307e4..40a390c 100644 --- a/media/audio/pulse/pulse_output.cc +++ b/media/audio/pulse/pulse_output.cc
@@ -63,7 +63,7 @@ const AudioParameters& params, const std::string& device_id, AudioManagerBase* manager, - const AudioManager::LogCallback log_callback) + AudioManager::LogCallback log_callback) : params_(AudioParameters(params.format(), params.channel_layout(), params.sample_rate(),
diff --git a/media/audio/pulse/pulse_output.h b/media/audio/pulse/pulse_output.h index 4e58ad5..59ce6168 100644 --- a/media/audio/pulse/pulse_output.h +++ b/media/audio/pulse/pulse_output.h
@@ -43,7 +43,7 @@ PulseAudioOutputStream(const AudioParameters& params, const std::string& device_id, AudioManagerBase* manager, - const AudioManager::LogCallback log_callback); + AudioManager::LogCallback log_callback); ~PulseAudioOutputStream() override;
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc index db4b1d1..8df4203 100644 --- a/media/audio/win/audio_low_latency_input_win.cc +++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -34,6 +34,11 @@ constexpr uint32_t KSAUDIO_SPEAKER_UNSUPPORTED = 0; +// Converts a COM error into a human-readable string. +std::string ErrorToString(HRESULT hresult) { + return CoreAudioUtil::ErrorToString(hresult); +} + // Errors when initializing the audio client related to the audio format. Split // by whether we're using format conversion or not. Used for reporting stats - // do not renumber entries. @@ -88,14 +93,65 @@ } } +const char* StreamOpenResultToString( + WASAPIAudioInputStream::StreamOpenResult result) { + switch (result) { + case WASAPIAudioInputStream::OPEN_RESULT_OK: + return "OK"; + case WASAPIAudioInputStream::OPEN_RESULT_CREATE_INSTANCE: + return "CREATE_INSTANCE"; + case WASAPIAudioInputStream::OPEN_RESULT_NO_ENDPOINT: + return "NO_ENDPOINT"; + case WASAPIAudioInputStream::OPEN_RESULT_NO_STATE: + return "NO_STATE"; + case WASAPIAudioInputStream::OPEN_RESULT_DEVICE_NOT_ACTIVE: + return "DEVICE_NOT_ACTIVE"; + case WASAPIAudioInputStream::OPEN_RESULT_ACTIVATION_FAILED: + return "ACTIVATION_FAILED"; + case WASAPIAudioInputStream::OPEN_RESULT_FORMAT_NOT_SUPPORTED: + return "FORMAT_NOT_SUPPORTED"; + case WASAPIAudioInputStream::OPEN_RESULT_AUDIO_CLIENT_INIT_FAILED: + return "AUDIO_CLIENT_INIT_FAILED"; + case WASAPIAudioInputStream::OPEN_RESULT_GET_BUFFER_SIZE_FAILED: + return "GET_BUFFER_SIZE_FAILED"; + case WASAPIAudioInputStream::OPEN_RESULT_LOOPBACK_ACTIVATE_FAILED: + return "LOOPBACK_ACTIVATE_FAILED"; + case WASAPIAudioInputStream::OPEN_RESULT_LOOPBACK_INIT_FAILED: + return "LOOPBACK_INIT_FAILED"; + case WASAPIAudioInputStream::OPEN_RESULT_SET_EVENT_HANDLE: + return "SET_EVENT_HANDLE"; + case WASAPIAudioInputStream::OPEN_RESULT_NO_CAPTURE_CLIENT: + return "NO_CAPTURE_CLIENT"; + case WASAPIAudioInputStream::OPEN_RESULT_NO_AUDIO_VOLUME: + return "NO_AUDIO_VOLUME"; + case WASAPIAudioInputStream::OPEN_RESULT_OK_WITH_RESAMPLING: + return "OK_WITH_RESAMPLING"; + } + return "UNKNOWN"; +} + +std::string GetOpenLogString(WASAPIAudioInputStream::StreamOpenResult result, + HRESULT hr, + WAVEFORMATEXTENSIBLE input_format, + WAVEFORMATEX output_format) { + return base::StringPrintf( + "WAIS::Open => (ERROR: result=%s, hresult=%#lx, input_format=[%s], " + "output_format=[%s])", + StreamOpenResultToString(result), hr, + CoreAudioUtil::WaveFormatToString(&input_format).c_str(), + CoreAudioUtil::WaveFormatToString(&output_format).c_str()); +} + } // namespace WASAPIAudioInputStream::WASAPIAudioInputStream( AudioManagerWin* manager, const AudioParameters& params, const std::string& device_id, - const AudioManager::LogCallback& log_callback) - : manager_(manager), device_id_(device_id), log_callback_(log_callback) { + AudioManager::LogCallback log_callback) + : manager_(manager), + device_id_(device_id), + log_callback_(std::move(log_callback)) { DCHECK(manager_); DCHECK(!device_id_.empty()); DCHECK(!log_callback_.is_null()); @@ -103,10 +159,13 @@ DCHECK(params.channel_layout() == CHANNEL_LAYOUT_MONO || params.channel_layout() == CHANNEL_LAYOUT_STEREO || params.channel_layout() == CHANNEL_LAYOUT_DISCRETE); + SendLogMessage("%s({device_id=%s}, {params=[%s]})", __func__, + device_id.c_str(), params.AsHumanReadableString().c_str()); // Load the Avrt DLL if not already loaded. Required to support MMCSS. bool avrt_init = avrt::Initialize(); - DCHECK(avrt_init) << "Failed to load the Avrt.dll"; + if (!avrt_init) + SendLogMessage("%s => (WARNING: failed to load Avrt.dll)", __func__); const SampleFormat kSampleFormat = kSampleFormatS16; @@ -117,7 +176,6 @@ // to fit the current input audio device. If so, a FIFO and/or and audio // converter might be needed to ensure that the output format of this stream // matches what the client asks for. - DVLOG(1) << params.AsHumanReadableString(); WAVEFORMATEX* format = &input_format_.Format; format->wFormatTag = WAVE_FORMAT_EXTENSIBLE; format->nChannels = params.channels(); @@ -133,7 +191,8 @@ input_format_.dwChannelMask = ChannelLayoutToChannelConfig(params.channel_layout()); input_format_.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - DVLOG(1) << "Input: " << CoreAudioUtil::WaveFormatToString(&input_format_); + SendLogMessage("%s => (audio engine format=[%s])", __func__, + CoreAudioUtil::WaveFormatToString(&input_format_).c_str()); // Set up the fixed output format based on |params|. Will not be changed and // does not required an extended wave format structure since any multi-channel @@ -145,7 +204,8 @@ output_format_.nBlockAlign = format->nBlockAlign; output_format_.nAvgBytesPerSec = format->nAvgBytesPerSec; output_format_.cbSize = 0; - DVLOG(1) << "Output: " << CoreAudioUtil::WaveFormatToString(&output_format_); + SendLogMessage("%s => (audio sink format=[%s])", __func__, + CoreAudioUtil::WaveFormatToString(&output_format_).c_str()); // Size in bytes of each audio frame. frame_size_bytes_ = format->nBlockAlign; @@ -154,8 +214,10 @@ // endpoint device in each capture event. packet_size_bytes_ = params.GetBytesPerBuffer(kSampleFormat); packet_size_frames_ = packet_size_bytes_ / format->nBlockAlign; - DVLOG(1) << "Number of bytes per audio frame : " << frame_size_bytes_; - DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; + SendLogMessage( + "%s => (packet size=[%zu bytes/%zu audio frames/%.3f milliseconds])", + __func__, packet_size_bytes_, packet_size_frames_, + params.GetBufferDuration().InMillisecondsF()); // All events are auto-reset events and non-signaled initially. @@ -175,16 +237,13 @@ bool WASAPIAudioInputStream::Open() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Verify that we are not already opened. + SendLogMessage("%s([opened=%s])", __func__, opened_ ? "true" : "false"); if (opened_) { - log_callback_.Run("WASAPIAIS::Open: already open"); return false; } - // Obtain a reference to the IMMDevice interface of the capturing - // device with the specified unique identifier or role which was - // set at construction. + // Obtain a reference to the IMMDevice interface of the capturing device with + // the specified unique identifier or role which was set at construction. HRESULT hr = SetCaptureDevice(); if (FAILED(hr)) { ReportOpenResult(hr); @@ -231,7 +290,8 @@ void WASAPIAudioInputStream::Start(AudioInputCallback* callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(callback); - DLOG_IF(ERROR, !opened_) << "Open() has not been called successfully"; + SendLogMessage("%s([opened=%s, started=%s])", __func__, + opened_ ? "true" : "false", started_ ? "true" : "false"); if (!opened_) return; @@ -243,7 +303,8 @@ // Valid volume levels are in the range 0.0 to 1.0. // See http://crbug.com/1014443 for details why this is needed. if (GetVolume() == 0.0) { - DLOG(WARNING) << "Input audio session starts with zero volume"; + SendLogMessage("%s => (WARNING: Input audio session starts at zero volume)", + __func__); audio_session_starts_at_zero_volume_ = true; } @@ -279,18 +340,15 @@ // Start streaming data between the endpoint buffer and the audio engine. HRESULT hr = audio_client_->Start(); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to start input streaming."; - log_callback_.Run(base::StringPrintf( - "WASAPIAIS::Start: Failed to start audio client, hresult = %#lx", hr)); + SendLogMessage("%s => (ERROR: IAudioClient::Start=[%s])", __func__, + ErrorToString(hr).c_str()); } if (SUCCEEDED(hr) && audio_render_client_for_loopback_.Get()) { hr = audio_render_client_for_loopback_->Start(); if (FAILED(hr)) - log_callback_.Run(base::StringPrintf( - "WASAPIAIS::Start: Failed to start render client for loopback, " - "hresult = %#lx", - hr)); + SendLogMessage("%s => (ERROR: IAudioClient::Start=[%s] (loopback))", + __func__, ErrorToString(hr).c_str()); } started_ = SUCCEEDED(hr); @@ -298,7 +356,7 @@ void WASAPIAudioInputStream::Stop() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DVLOG(1) << "WASAPIAudioInputStream::Stop()"; + SendLogMessage("%s([started=%s])", __func__, started_ ? "true" : "false"); if (!started_) return; @@ -328,7 +386,8 @@ // Stop the input audio streaming. HRESULT hr = audio_client_->Stop(); if (FAILED(hr)) { - LOG(ERROR) << "Failed to stop input streaming."; + SendLogMessage("%s => (ERROR: IAudioClient::Stop=[%s])", __func__, + ErrorToString(hr).c_str()); } // Wait until the thread completes and perform cleanup. @@ -343,8 +402,6 @@ if (add_uma_histogram) { base::UmaHistogramBoolean("Media.Audio.InputVolumeStartsAtZeroWin", audio_session_starts_at_zero_volume_); - DVLOG(1) << "Media.Audio.InputVolumeStartsAtZeroWin: " - << audio_session_starts_at_zero_volume_; audio_session_starts_at_zero_volume_ = false; } @@ -353,7 +410,7 @@ } void WASAPIAudioInputStream::Close() { - DVLOG(1) << "WASAPIAudioInputStream::Close()"; + SendLogMessage("%s()", __func__); // It is valid to call Close() before calling open or Start(). // It is also valid to call Close() after Start() has been called. Stop(); @@ -369,7 +426,7 @@ } double WASAPIAudioInputStream::GetMaxVolume() { - // Verify that Open() has been called succesfully, to ensure that an audio + // Verify that Open() has been called successfully, to ensure that an audio // session exists and that an ISimpleAudioVolume interface has been created. DLOG_IF(ERROR, !opened_) << "Open() has not been called successfully"; if (!opened_) @@ -384,8 +441,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_GE(volume, 0.0); DCHECK_LE(volume, 1.0); - - DLOG_IF(ERROR, !opened_) << "Open() has not been called successfully"; + SendLogMessage("%s({volume=%.2f} [opened=%s])", __func__, volume, + opened_ ? "true" : "false"); if (!opened_) return; @@ -393,8 +450,10 @@ // 0.0 to 1.0. Ignore volume-change events. HRESULT hr = simple_audio_volume_->SetMasterVolume(static_cast<float>(volume), nullptr); - if (FAILED(hr)) - DLOG(WARNING) << "Failed to set new input master volume."; + if (FAILED(hr)) { + SendLogMessage("%s => (ERROR: ISimpleAudioVolume::SetMasterVolume=[%s])", + __func__, ErrorToString(hr).c_str()); + } // Update the AGC volume level based on the last setting above. Note that, // the volume-level resolution is not infinite and it is therefore not @@ -412,8 +471,10 @@ // Retrieve the current volume level. The value is in the range 0.0 to 1.0. float level = 0.0f; HRESULT hr = simple_audio_volume_->GetMasterVolume(&level); - if (FAILED(hr)) - DLOG(WARNING) << "Failed to get input master volume."; + if (FAILED(hr)) { + SendLogMessage("%s => (ERROR: ISimpleAudioVolume::GetMasterVolume=[%s])", + __func__, ErrorToString(hr).c_str()); + } return static_cast<double>(level); } @@ -427,8 +488,10 @@ // Retrieves the current muting state for the audio session. BOOL is_muted = FALSE; HRESULT hr = simple_audio_volume_->GetMute(&is_muted); - if (FAILED(hr)) - DLOG(WARNING) << "Failed to get input master volume."; + if (FAILED(hr)) { + SendLogMessage("%s => (ERROR: ISimpleAudioVolume::GetMute=[%s])", __func__, + ErrorToString(hr).c_str()); + } return is_muted != FALSE; } @@ -438,6 +501,15 @@ // Not supported. Do nothing. } +void WASAPIAudioInputStream::SendLogMessage(const char* format, ...) { + if (log_callback_.is_null()) + return; + va_list args; + va_start(args, format); + log_callback_.Run("WAIS::" + base::StringPrintV(format, args)); + va_end(args); +} + void WASAPIAudioInputStream::Run() { ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); @@ -452,7 +524,9 @@ // Failed to enable MMCSS on this thread. It is not fatal but can lead // to reduced QoS at high load. DWORD err = GetLastError(); - LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ")."; + LOG(ERROR) << "WAIS::" << __func__ + << " => (ERROR: Failed to enable MMCSS (error code=" << err + << "))"; } // Allocate a buffer with a size that enables us to take care of cases like: @@ -476,7 +550,6 @@ DCHECK(!fifo_); fifo_.reset(new AudioBlockFifo(input_format_.Format.nChannels, packet_size_frames_, buffers_required)); - DVLOG(1) << "AudioBlockFifo buffer count: " << buffers_required; bool recording = true; @@ -552,7 +625,9 @@ // rely on the next WaitForMultipleObjects? Do we expect the next wait to be // successful sometimes? if (FAILED(hr)) { - DLOG(ERROR) << "Failed to get data from the capture buffer"; + LOG(ERROR) << "WAIS::" << __func__ + << " => (ERROR: IAudioCaptureClient::GetBuffer=[" + << ErrorToString(hr).c_str() << "])"; break; } @@ -607,7 +682,12 @@ } hr = audio_capture_client_->ReleaseBuffer(num_frames_to_read); - DLOG_IF(ERROR, FAILED(hr)) << "Failed to release capture buffer"; + if (FAILED(hr)) { + LOG(ERROR) << "WAIS::" << __func__ + << " => (ERROR: IAudioCaptureClient::ReleaseBuffer=[" + << ErrorToString(hr).c_str() << "])"; + break; + } // Get a cached AGC volume level which is updated once every second on the // audio manager thread. Note that, |volume| is also updated each time @@ -652,6 +732,7 @@ HRESULT WASAPIAudioInputStream::SetCaptureDevice() { DCHECK_EQ(OPEN_RESULT_OK, open_result_); DCHECK(!endpoint_device_.Get()); + SendLogMessage("%s()", __func__); Microsoft::WRL::ComPtr<IMMDeviceEnumerator> enumerator; HRESULT hr = ::CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, @@ -729,6 +810,7 @@ } bool WASAPIAudioInputStream::DesiredFormatIsSupported(HRESULT* hr) { + SendLogMessage("%s()", __func__); // An application that uses WASAPI to manage shared-mode streams can rely // on the audio engine to perform only limited format conversions. The audio // engine can convert between a standard PCM sample size used by the @@ -742,12 +824,15 @@ HRESULT hresult = audio_client_->IsFormatSupported( AUDCLNT_SHAREMODE_SHARED, reinterpret_cast<const WAVEFORMATEX*>(&input_format_), &closest_match); - DLOG_IF(ERROR, hresult == S_FALSE) - << "Format is not supported but a closest match exists."; - if (FAILED(hresult)) - LOG(ERROR) << "Input format is not supported: " << std::hex << hresult; + if (FAILED(hresult)) { + SendLogMessage("%s => (ERROR: IAudioClient::IsFormatSupported=[%s])", + __func__, ErrorToString(hresult).c_str()); + } if (hresult == S_FALSE) { + SendLogMessage( + "%s => (WARNING: Format is not supported but a closest match exists)", + __func__); // Change the format we're going to ask for to better match with what the OS // can provide. If we succeed in initializing the audio client in this // format and are able to convert from this format, we will do that @@ -771,10 +856,10 @@ input_format->nSamplesPerSec * input_format->nBlockAlign; if (IsSupportedFormatForConversion(&input_format_)) { - DVLOG(1) << "Will convert captured audio: \n" - << CoreAudioUtil::WaveFormatToString(&input_format_) << " ==> \n" - << CoreAudioUtil::WaveFormatToString(&output_format_); - + SendLogMessage( + "%s => (WARNING: Captured audio will be converted: [%s] ==> [%s])", + __func__, CoreAudioUtil::WaveFormatToString(&input_format_).c_str(), + CoreAudioUtil::WaveFormatToString(&output_format_).c_str()); SetupConverterAndStoreFormatInfo(); // Indicate that we're good to go with a close match. @@ -826,12 +911,16 @@ imperfect_buffer_size_conversion_ = std::modf(new_frames_per_buffer, &new_frames_per_buffer) != 0.0; - DVLOG_IF(1, imperfect_buffer_size_conversion_) - << "Audio capture data conversion: Need to inject fifo"; + if (imperfect_buffer_size_conversion_) { + SendLogMessage("%s => (WARNING: Audio capture conversion requires a FIFO)", + __func__); + } } HRESULT WASAPIAudioInputStream::InitializeAudioEngine() { DCHECK_EQ(OPEN_RESULT_OK, open_result_); + SendLogMessage("%s()", __func__); + DWORD flags; // Use event-driven mode only for regular input devices. For loopback the // EVENTCALLBACK flag is specified when initializing @@ -850,8 +939,6 @@ // however cases when there are glitches anyway and it's avoided by setting a // larger buffer size. The larger size does not create higher latency for // properly implemented drivers. - DVLOG(1) << "Audio format used in IAudioClient::Initialize: " - << CoreAudioUtil::WaveFormatToString(&input_format_); HRESULT hr = audio_client_->Initialize( AUDCLNT_SHAREMODE_SHARED, flags, 100 * 1000 * 10, // Buffer duration, 100 ms expressed in 100-ns units. @@ -862,6 +949,8 @@ : nullptr); if (FAILED(hr)) { + SendLogMessage("%s => (ERROR: IAudioClient::Initialize=[%s])", __func__, + ErrorToString(hr).c_str()); open_result_ = OPEN_RESULT_AUDIO_CLIENT_INIT_FAILED; base::UmaHistogramSparse("Media.Audio.Capture.Win.InitError", hr); MaybeReportFormatRelatedInitError(hr); @@ -877,15 +966,14 @@ open_result_ = OPEN_RESULT_GET_BUFFER_SIZE_FAILED; return hr; } - -#ifndef NDEBUG const int endpoint_buffer_size_ms = static_cast<double>(endpoint_buffer_size_frames_ * 1000) / input_format_.Format.nSamplesPerSec + - 0.5; // Round to closest integer - DVLOG(1) << "Endpoint buffer size: " << endpoint_buffer_size_frames_ - << " frames (" << endpoint_buffer_size_ms << " ms)"; + 0.5; + SendLogMessage("%s => (endpoint_buffer_size_frames=%u (%d ms))", __func__, + endpoint_buffer_size_frames_, endpoint_buffer_size_ms); +#ifndef NDEBUG // The period between processing passes by the audio engine is fixed for a // particular audio endpoint device and represents the smallest processing // quantum for the audio engine. This period plus the stream latency between @@ -926,6 +1014,7 @@ // // http://msdn.microsoft.com/en-us/library/windows/desktop/dd316551(v=vs.85).aspx if (AudioDeviceDescription::IsLoopbackDevice(device_id_)) { + SendLogMessage("%s => (WARNING: loopback mode is selected", __func__); hr = endpoint_device_->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, &audio_render_client_for_loopback_); if (FAILED(hr)) { @@ -971,36 +1060,25 @@ open_result_ = OPEN_RESULT_NO_AUDIO_VOLUME; audio_client_->GetService(IID_PPV_ARGS(&audio_clock_)); - if (!audio_clock_) - LOG(WARNING) << "IAudioClock unavailable, capture times may be inaccurate."; + if (!audio_clock_) { + SendLogMessage( + "%s => (WARNING: IAudioClock unavailable, capture times will be " + "inaccurate)", + __func__); + } return hr; } -void WASAPIAudioInputStream::ReportOpenResult(HRESULT hr) const { - DCHECK(!opened_); // This method must be called before we set this flag. +void WASAPIAudioInputStream::ReportOpenResult(HRESULT hr) { + DCHECK(!opened_); UMA_HISTOGRAM_ENUMERATION("Media.Audio.Capture.Win.Open", open_result_, OPEN_RESULT_MAX + 1); if (open_result_ != OPEN_RESULT_OK && open_result_ != OPEN_RESULT_OK_WITH_RESAMPLING) { - log_callback_.Run(base::StringPrintf( - "WASAPIAIS::Open: failed, result = %d, hresult = %#lx, " - "input format = %#x/%d/%ld/%d/%d/%ld/%d, " - "output format = %#x/%d/%ld/%d/%d/%ld/%d", - // clang-format off - open_result_, hr, - input_format_.Format.wFormatTag, input_format_.Format.nChannels, - input_format_.Format.nSamplesPerSec, - input_format_.Format.wBitsPerSample, - input_format_.Format.nBlockAlign, input_format_.Format.nAvgBytesPerSec, - input_format_.Format.cbSize, - output_format_.wFormatTag, output_format_.nChannels, - output_format_.nSamplesPerSec, - output_format_.wBitsPerSample, - output_format_.nBlockAlign, - output_format_.nAvgBytesPerSec, - output_format_.cbSize)); - // clang-format on + SendLogMessage( + "%s", GetOpenLogString(open_result_, hr, input_format_, output_format_) + .c_str()); } } @@ -1043,14 +1121,11 @@ void WASAPIAudioInputStream::ReportAndResetGlitchStats() { UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Capture.Glitches", total_glitches_); - double lost_frames_ms = (total_lost_frames_ * 1000) / input_format_.Format.nSamplesPerSec; - std::string log_message = base::StringPrintf( - "WASAPIAIS: Total glitches=%d. Total frames lost=%llu (%.0lf ms).", - total_glitches_, total_lost_frames_, lost_frames_ms); - log_callback_.Run(log_message); - + SendLogMessage( + "%s => (total glitches=[%d], total frames lost=[%llu/%.0lf ms])", + __func__, total_glitches_, total_lost_frames_, lost_frames_ms); if (total_glitches_ != 0) { UMA_HISTOGRAM_LONG_TIMES("Media.Audio.Capture.LostFramesInMs", base::TimeDelta::FromMilliseconds(lost_frames_ms)); @@ -1061,7 +1136,6 @@ base::TimeDelta::FromMilliseconds(largest_glitch_ms), base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(1), 50); - DLOG(WARNING) << log_message; } expected_next_device_position_ = 0;
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h index d28cca49..417c22f 100644 --- a/media/audio/win/audio_low_latency_input_win.h +++ b/media/audio/win/audio_low_latency_input_win.h
@@ -91,65 +91,6 @@ public base::DelegateSimpleThread::Delegate, public AudioConverter::InputCallback { public: - // The ctor takes all the usual parameters, plus |manager| which is the - // the audio manager who is creating this object. - WASAPIAudioInputStream(AudioManagerWin* manager, - const AudioParameters& params, - const std::string& device_id, - const AudioManager::LogCallback& log_callback); - - // The dtor is typically called by the AudioManager only and it is usually - // triggered by calling AudioInputStream::Close(). - ~WASAPIAudioInputStream() override; - - // Implementation of AudioInputStream. - bool Open() override; - void Start(AudioInputCallback* callback) override; - void Stop() override; - void Close() override; - double GetMaxVolume() override; - void SetVolume(double volume) override; - double GetVolume() override; - bool IsMuted() override; - void SetOutputDeviceForAec(const std::string& output_device_id) override; - - bool started() const { return started_; } - - private: - // DelegateSimpleThread::Delegate implementation. - void Run() override; - - // Pulls capture data from the endpoint device and pushes it to the sink. - void PullCaptureDataAndPushToSink(); - - // Issues the OnError() callback to the |sink_|. - void HandleError(HRESULT err); - - // The Open() method is divided into these sub methods. - HRESULT SetCaptureDevice(); - HRESULT GetAudioEngineStreamFormat(); - // Returns whether the desired format is supported or not and writes the - // result of a failing system call to |*hr|, or S_OK if successful. If this - // function returns false with |*hr| == S_FALSE, the OS supports a closest - // match but we don't support conversion to it. - bool DesiredFormatIsSupported(HRESULT* hr); - void SetupConverterAndStoreFormatInfo(); - HRESULT InitializeAudioEngine(); - void ReportOpenResult(HRESULT hr) const; - // Reports stats for format related audio client initilization - // (IAudioClient::Initialize) errors, that is if |hr| is an error related to - // the format. - void MaybeReportFormatRelatedInitError(HRESULT hr) const; - - // AudioConverter::InputCallback implementation. - double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override; - - // Detects and counts glitches based on |device_position|. - void UpdateGlitchCount(UINT64 device_position); - - // Reports glitch stats and resets associated variables. - void ReportAndResetGlitchStats(); - // Used to track down where we fail during initialization which at the // moment seems to be happening frequently and we're not sure why. // The reason might be expected (e.g. trying to open "default" on a machine @@ -175,6 +116,67 @@ OPEN_RESULT_MAX = OPEN_RESULT_OK_WITH_RESAMPLING }; + // The ctor takes all the usual parameters, plus |manager| which is the + // the audio manager who is creating this object. + WASAPIAudioInputStream(AudioManagerWin* manager, + const AudioParameters& params, + const std::string& device_id, + AudioManager::LogCallback log_callback); + + // The dtor is typically called by the AudioManager only and it is usually + // triggered by calling AudioInputStream::Close(). + ~WASAPIAudioInputStream() override; + + // Implementation of AudioInputStream. + bool Open() override; + void Start(AudioInputCallback* callback) override; + void Stop() override; + void Close() override; + double GetMaxVolume() override; + void SetVolume(double volume) override; + double GetVolume() override; + bool IsMuted() override; + void SetOutputDeviceForAec(const std::string& output_device_id) override; + + bool started() const { return started_; } + + private: + void SendLogMessage(const char* format, ...) PRINTF_FORMAT(2, 3); + + // DelegateSimpleThread::Delegate implementation. + void Run() override; + + // Pulls capture data from the endpoint device and pushes it to the sink. + void PullCaptureDataAndPushToSink(); + + // Issues the OnError() callback to the |sink_|. + void HandleError(HRESULT err); + + // The Open() method is divided into these sub methods. + HRESULT SetCaptureDevice(); + HRESULT GetAudioEngineStreamFormat(); + // Returns whether the desired format is supported or not and writes the + // result of a failing system call to |*hr|, or S_OK if successful. If this + // function returns false with |*hr| == S_FALSE, the OS supports a closest + // match but we don't support conversion to it. + bool DesiredFormatIsSupported(HRESULT* hr); + void SetupConverterAndStoreFormatInfo(); + HRESULT InitializeAudioEngine(); + void ReportOpenResult(HRESULT hr); + // Reports stats for format related audio client initialization + // (IAudioClient::Initialize) errors, that is if |hr| is an error related to + // the format. + void MaybeReportFormatRelatedInitError(HRESULT hr) const; + + // AudioConverter::InputCallback implementation. + double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override; + + // Detects and counts glitches based on |device_position|. + void UpdateGlitchCount(UINT64 device_position); + + // Reports glitch stats and resets associated variables. + void ReportAndResetGlitchStats(); + // Our creator, the audio manager needs to be notified when we close. AudioManagerWin* const manager_; @@ -283,7 +285,7 @@ std::unique_ptr<AudioBus> convert_bus_; bool imperfect_buffer_size_conversion_ = false; - // Callback to send log messages. + // Callback to send log messages to registered clients. AudioManager::LogCallback log_callback_; // For detecting and reporting glitches.
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc index 490c843..b8da03b9 100644 --- a/media/audio/win/audio_low_latency_output_win.cc +++ b/media/audio/win/audio_low_latency_output_win.cc
@@ -16,6 +16,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" @@ -35,6 +36,28 @@ namespace media { +namespace { + +// Converts a COM error into a human-readable string. +std::string ErrorToString(HRESULT hresult) { + return CoreAudioUtil::ErrorToString(hresult); +} + +const char* RoleToString(const ERole role) { + switch (role) { + case eConsole: + return "Console"; + case eMultimedia: + return "Multimedia"; + case eCommunications: + return "Communications"; + default: + return "Unsupported"; + } +} + +} // namespace + // static AUDCLNT_SHAREMODE WASAPIAudioOutputStream::GetShareMode() { @@ -44,10 +67,12 @@ return AUDCLNT_SHAREMODE_SHARED; } -WASAPIAudioOutputStream::WASAPIAudioOutputStream(AudioManagerWin* manager, - const std::string& device_id, - const AudioParameters& params, - ERole device_role) +WASAPIAudioOutputStream::WASAPIAudioOutputStream( + AudioManagerWin* manager, + const std::string& device_id, + const AudioParameters& params, + ERole device_role, + AudioManager::LogCallback log_callback) : creating_thread_id_(base::PlatformThread::CurrentId()), manager_(manager), format_(), @@ -61,7 +86,8 @@ device_role_(device_role), share_mode_(GetShareMode()), num_written_frames_(0), - source_(NULL) { + source_(nullptr), + log_callback_(std::move(log_callback)) { DCHECK(manager_); // The empty string is used to indicate a default device and the @@ -70,14 +96,14 @@ DCHECK_NE(device_id_, AudioDeviceDescription::kDefaultDeviceId); DCHECK_NE(device_id_, AudioDeviceDescription::kCommunicationsDeviceId); - DVLOG(1) << "WASAPIAudioOutputStream::WASAPIAudioOutputStream()"; - DVLOG_IF(1, share_mode_ == AUDCLNT_SHAREMODE_EXCLUSIVE) - << "Core Audio (WASAPI) EXCLUSIVE MODE is enabled."; - DVLOG(1) << params.AsHumanReadableString(); + SendLogMessage("%s({device_id=%s}, {params=[%s]}, {role=%s})", __func__, + device_id.c_str(), params.AsHumanReadableString().c_str(), + RoleToString(device_role)); // Load the Avrt DLL if not already loaded. Required to support MMCSS. bool avrt_init = avrt::Initialize(); - DCHECK(avrt_init) << "Failed to load the avrt.dll"; + if (!avrt_init) + SendLogMessage("%s => (WARNING: failed to load Avrt.dll)", __func__); audio_bus_ = AudioBus::Create(params); @@ -99,17 +125,16 @@ format_.Samples.wValidBitsPerSample = format->wBitsPerSample; format_.dwChannelMask = CoreAudioUtil::GetChannelConfig(device_id, eRender); format_.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - DVLOG(1) << "Format: " << CoreAudioUtil::WaveFormatToString(&format_); + SendLogMessage("%s => (audio engine format=[%s])", __func__, + CoreAudioUtil::WaveFormatToString(&format_).c_str()); // Store size (in different units) of audio packets which we expect to // get from the audio endpoint device in each render event. packet_size_frames_ = params.frames_per_buffer(); packet_size_bytes_ = params.GetBytesPerBuffer(kSampleFormatF32); - DVLOG(1) << "Number of bytes per audio frame : " << format->nBlockAlign; - DVLOG(1) << "Number of audio frames per packet: " << packet_size_frames_; - DVLOG(1) << "Number of bytes per packet : " << packet_size_bytes_; - DVLOG(1) << "Number of milliseconds per packet: " - << params.GetBufferDuration().InMillisecondsF(); + SendLogMessage("%s => (packet size=[%zu bytes/%zu audio frames/%.3f ms])", + __func__, packet_size_bytes_, packet_size_frames_, + params.GetBufferDuration().InMillisecondsF()); AudioParameters::HardwareCapabilities hardware_capabilities = params.hardware_capabilities().value_or( @@ -127,11 +152,11 @@ // Create the event which the audio engine will signal each time // a buffer becomes ready to be processed by the client. - audio_samples_render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL)); + audio_samples_render_event_.Set(CreateEvent(nullptr, FALSE, FALSE, nullptr)); DCHECK(audio_samples_render_event_.IsValid()); // Create the event which will be set in Stop() when capturing shall stop. - stop_render_event_.Set(CreateEvent(NULL, FALSE, FALSE, NULL)); + stop_render_event_.Set(CreateEvent(nullptr, FALSE, FALSE, nullptr)); DCHECK(stop_render_event_.IsValid()); } @@ -140,8 +165,8 @@ } bool WASAPIAudioOutputStream::Open() { - DVLOG(1) << "WASAPIAudioOutputStream::Open()"; DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_); + SendLogMessage("%s([opened=%s])", __func__, opened_ ? "true" : "false"); if (opened_) return true; @@ -153,14 +178,15 @@ Microsoft::WRL::ComPtr<IAudioClient> audio_client( CoreAudioUtil::CreateClient(device_id_, eRender, device_role_)); - - if (!audio_client.Get()) + if (!audio_client.Get()) { + SendLogMessage("%s => (ERROR: CAU::CreateClient failed)", __func__); return false; + } // Extra sanity to ensure that the provided device format is still valid. if (!CoreAudioUtil::IsFormatSupported(audio_client.Get(), share_mode_, &format_)) { - LOG(ERROR) << "Audio parameters are not supported."; + SendLogMessage("%s => (ERROR: CAU::IsFormatSupported failed)", __func__); return false; } @@ -171,9 +197,12 @@ hr = CoreAudioUtil::SharedModeInitialize( audio_client.Get(), &format_, audio_samples_render_event_.Get(), requested_iaudioclient3_buffer_size_, &endpoint_buffer_size_frames_, - communications_device ? &kCommunicationsSessionId : NULL); - if (FAILED(hr)) + communications_device ? &kCommunicationsSessionId : nullptr); + if (FAILED(hr)) { + SendLogMessage("%s => (ERROR: IAudioClient::SharedModeInitialize=[%s])", + __func__, ErrorToString(hr).c_str()); return false; + } REFERENCE_TIME device_period = 0; if (FAILED(CoreAudioUtil::GetDevicePeriod( @@ -186,6 +215,8 @@ CoreAudioUtil::ReferenceTimeToTimeDelta(device_period) .InSecondsF() + 0.5); + SendLogMessage("%s => (preferred_frames_per_buffer=[%d audio frames])", + __func__, preferred_frames_per_buffer); // Packet size should always be an even divisor of the device period for // best performance; things will still work otherwise, but may glitch for a @@ -207,14 +238,14 @@ // Log a warning in these cases so we can help users in the field. // Examples: 48kHz => 960 % 480, 44.1kHz => 896 % 448 or 882 % 441. if (preferred_frames_per_buffer % packet_size_frames_) { - LOG(WARNING) - << "Using WASAPI output with a non-optimal buffer size, glitches from" - << " back to back shared memory reads and partial fills of WASAPI" - << " output buffers may occur. Buffer size of " - << packet_size_frames_ << " is not an even divisor of " - << preferred_frames_per_buffer; + SendLogMessage( + "%s => (WARNING: Using output audio with a non-optimal buffer size)", + __func__); } } else { + SendLogMessage( + "%s => (WARNING: Using exclusive mode can lead to bad performance)", + __func__); // TODO(henrika): break out to CoreAudioUtil::ExclusiveModeInitialize() // when removing the enable-exclusive-audio flag. hr = ExclusiveModeInitialization(audio_client.Get(), @@ -237,8 +268,10 @@ // a rendering endpoint buffer. Microsoft::WRL::ComPtr<IAudioRenderClient> audio_render_client = CoreAudioUtil::CreateRenderClient(audio_client.Get()); - if (!audio_render_client.Get()) + if (!audio_render_client.Get()) { + SendLogMessage("%s => (ERROR: CAU::CreateRenderClient failed)", __func__); return false; + } // Store valid COM interfaces. audio_client_ = audio_client; @@ -246,7 +279,8 @@ hr = audio_client_->GetService(IID_PPV_ARGS(&audio_clock_)); if (FAILED(hr)) { - LOG(ERROR) << "Failed to get IAudioClock service."; + SendLogMessage("%s => (ERROR: IAudioClient::GetService(IAudioClock)=[%s])", + __func__, ErrorToString(hr).c_str()); return false; } @@ -264,6 +298,8 @@ DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_); CHECK(callback); CHECK(opened_); + SendLogMessage("%s([opened=%s, started=%s])", __func__, + opened_ ? "true" : "false", render_thread_ ? "true" : "false"); if (render_thread_) { CHECK_EQ(callback, source_); @@ -289,16 +325,17 @@ if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) { if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence( audio_client_.Get(), audio_render_client_.Get())) { - DLOG(WARNING) << "Failed to prepare endpoint buffers with silence. " - "Attempting recovery with a new IAudioClient and " - "IAudioRenderClient."; - + // Failed to prepare endpoint buffers with silence. Attempting recovery + // with a new IAudioClient and IAudioRenderClient." + SendLogMessage( + "%s => (WARNING: CAU::FillRenderEndpointBufferWithSilence failed)", + __func__); opened_ = false; audio_client_.Reset(); audio_render_client_.Reset(); if (!Open() || !CoreAudioUtil::FillRenderEndpointBufferWithSilence( audio_client_.Get(), audio_render_client_.Get())) { - DLOG(ERROR) << "Failed recovery of audio clients; Start() failed."; + SendLogMessage("%s => (ERROR: Recovery attempt failed)", __func__); callback->OnError(AudioSourceCallback::ErrorType::kUnknown); return; } @@ -317,7 +354,8 @@ base::SimpleThread::Options(base::ThreadPriority::REALTIME_AUDIO))); render_thread_->Start(); if (!render_thread_->HasBeenStarted()) { - LOG(ERROR) << "Failed to start WASAPI render thread."; + SendLogMessage("%s => (ERROR: Failed to start \"wasapi_render_thread\")", + __func__); StopThread(); callback->OnError(AudioSourceCallback::ErrorType::kUnknown); return; @@ -326,7 +364,8 @@ // Start streaming data between the endpoint buffer and the audio engine. HRESULT hr = audio_client_->Start(); if (FAILED(hr)) { - PLOG(ERROR) << "Failed to start output streaming: " << std::hex << hr; + SendLogMessage("%s => (ERROR: IAudioClient::Start=[%s])", __func__, + ErrorToString(hr).c_str()); StopThread(); callback->OnError(AudioSourceCallback::ErrorType::kUnknown); } @@ -335,13 +374,17 @@ void WASAPIAudioOutputStream::Stop() { DVLOG(1) << "WASAPIAudioOutputStream::Stop()"; DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_); + SendLogMessage("%s([started=%s])", __func__, + render_thread_ ? "true" : "false"); + if (!render_thread_) return; // Stop output audio streaming. HRESULT hr = audio_client_->Stop(); if (FAILED(hr)) { - PLOG(ERROR) << "Failed to stop output streaming: " << std::hex << hr; + SendLogMessage("%s => (ERROR: IAudioClient::Stop=[%s])", __func__, + ErrorToString(hr).c_str()); source_->OnError(AudioSourceCallback::ErrorType::kUnknown); } @@ -352,7 +395,8 @@ // Flush all pending data and reset the audio clock stream position to 0. hr = audio_client_->Reset(); if (FAILED(hr)) { - PLOG(ERROR) << "Failed to reset streaming: " << std::hex << hr; + SendLogMessage("%s => (ERROR: IAudioClient::Reset=[%s])", __func__, + ErrorToString(hr).c_str()); callback->OnError(AudioSourceCallback::ErrorType::kUnknown); } @@ -366,12 +410,17 @@ UINT32 num_queued_frames = 0; audio_client_->GetCurrentPadding(&num_queued_frames); DCHECK_EQ(0u, num_queued_frames); + if (num_queued_frames > 0) { + SendLogMessage("%s => (WARNING: Buffers are not cleared correctly)", + __func__); + } } } void WASAPIAudioOutputStream::Close() { DVLOG(1) << "WASAPIAudioOutputStream::Close()"; DCHECK_EQ(GetCurrentThreadId(), creating_thread_id_); + SendLogMessage("%s()", __func__); session_listener_.reset(); @@ -389,7 +438,7 @@ void WASAPIAudioOutputStream::Flush() {} void WASAPIAudioOutputStream::SetVolume(double volume) { - DVLOG(1) << "SetVolume(volume=" << volume << ")"; + SendLogMessage("%s({volume=%.2f})", __func__, volume); float volume_float = static_cast<float>(volume); if (volume_float < 0.0f || volume_float > 1.0f) { return; @@ -398,10 +447,18 @@ } void WASAPIAudioOutputStream::GetVolume(double* volume) { - DVLOG(1) << "GetVolume()"; *volume = static_cast<double>(volume_); } +void WASAPIAudioOutputStream::SendLogMessage(const char* format, ...) { + if (log_callback_.is_null()) + return; + va_list args; + va_start(args, format); + log_callback_.Run("WAOS::" + base::StringPrintV(format, args)); + va_end(args); +} + void WASAPIAudioOutputStream::Run() { ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); @@ -416,7 +473,9 @@ // Failed to enable MMCSS on this thread. It is not fatal but can lead // to reduced QoS at high load. DWORD err = GetLastError(); - LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ")."; + LOG(ERROR) << "WAOS::" << __func__ + << " => (ERROR: Failed to enable MMCSS (error code=" << err + << "))"; } HRESULT hr = S_FALSE; @@ -431,8 +490,11 @@ // the audio device. The GetFrequency() method reports a constant frequency. hr = audio_clock_->GetFrequency(&device_frequency); error = FAILED(hr); - PLOG_IF(ERROR, error) << "Failed to acquire IAudioClock interface: " - << std::hex << hr; + if (error) { + LOG(ERROR) << "WAOS::" << __func__ + << " => (ERROR: IAudioClock::GetFrequency=[" + << ErrorToString(hr).c_str() << "])"; + } // Keep rendering audio until the stop event or the stream-switch event // is signaled. An error event can also break the main thread loop. @@ -457,7 +519,8 @@ } if (playing && error) { - LOG(ERROR) << "WASAPI rendering failed."; + LOG(ERROR) << "WAOS::" << __func__ + << " => (ERROR: WASAPI rendering failed)"; // Stop audio rendering since something has gone wrong in our main thread // loop. Note that, we are still in a "started" state, hence a Stop() call @@ -471,7 +534,8 @@ // Disable MMCSS. if (mm_task && !avrt::AvRevertMmThreadCharacteristics(mm_task)) { - PLOG(WARNING) << "Failed to disable MMCSS"; + LOG(WARNING) << "WAOS::" << __func__ + << " => (WARNING: Failed to disable MMCSS)"; } } @@ -480,7 +544,7 @@ HRESULT hr = S_FALSE; UINT32 num_queued_frames = 0; - uint8_t* audio_data = NULL; + uint8_t* audio_data = nullptr; // Contains how much new data we can write to the buffer without // the risk of overwriting previously written data that the audio @@ -494,8 +558,9 @@ num_available_frames = endpoint_buffer_size_frames_ - num_queued_frames; if (FAILED(hr)) { - DLOG(ERROR) << "Failed to retrieve amount of available space: " - << std::hex << hr; + LOG(ERROR) << "WAOS::" << __func__ + << " => (ERROR: IAudioClient::GetCurrentPadding=[" + << ErrorToString(hr).c_str() << "])"; return false; } } else { @@ -538,8 +603,9 @@ hr = audio_render_client_->GetBuffer(packet_size_frames_, &audio_data); if (FAILED(hr)) { - DLOG(ERROR) << "Failed to use rendering audio buffer: " - << std::hex << hr; + LOG(ERROR) << "WAOS::" << __func__ + << " => (ERROR: IAudioRenderClient::GetBuffer=[" + << ErrorToString(hr).c_str() << "])"; return false; } @@ -608,6 +674,9 @@ // by 10.0 since 10x100ns = 1us. delay_timestamp += base::TimeDelta::FromMicroseconds(qpc_position * 0.1); } else { + LOG(ERROR) << "WAOS::" << __func__ + << " => (ERROR: IAudioClock::GetPosition=[" + << ErrorToString(hr).c_str() << "])"; // Use a delay of zero. delay_timestamp = base::TimeTicks::Now(); } @@ -649,8 +718,8 @@ static_cast<REFERENCE_TIME>(f * 10000.0 + 0.5); DWORD stream_flags = AUDCLNT_STREAMFLAGS_NOPERSIST; - bool use_event = (event_handle != NULL && - event_handle != INVALID_HANDLE_VALUE); + bool use_event = + (event_handle != nullptr && event_handle != INVALID_HANDLE_VALUE); if (use_event) stream_flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK; DVLOG(2) << "stream_flags: 0x" << std::hex << stream_flags; @@ -664,12 +733,9 @@ // Following the Initialize call for a rendering stream, the caller should // fill the first of the two buffers before starting the stream. HRESULT hr = S_FALSE; - hr = client->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, - stream_flags, - requested_buffer_duration, - requested_buffer_duration, - reinterpret_cast<WAVEFORMATEX*>(&format_), - NULL); + hr = client->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, stream_flags, + requested_buffer_duration, requested_buffer_duration, + reinterpret_cast<WAVEFORMATEX*>(&format_), nullptr); if (FAILED(hr)) { if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) { LOG(ERROR) << "AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED"; @@ -734,7 +800,7 @@ ResetEvent(stop_render_event_.Get()); } - source_ = NULL; + source_ = nullptr; } void WASAPIAudioOutputStream::ReportAndResetStats() { @@ -749,6 +815,11 @@ UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Render.LargestGlitchMs", largest_glitch_.InMilliseconds()); } + SendLogMessage( + "%s => (num_glitches_detected=[%d], cumulative_audio_lost=[%llu ms], " + "largest_glitch=[%llu ms])", + __func__, num_glitches_detected_, cumulative_audio_lost_.InMilliseconds(), + largest_glitch_.InMilliseconds()); num_glitches_detected_ = 0; cumulative_audio_lost_ = base::TimeDelta(); largest_glitch_ = base::TimeDelta();
diff --git a/media/audio/win/audio_low_latency_output_win.h b/media/audio/win/audio_low_latency_output_win.h index 7dcfaa5..7447419 100644 --- a/media/audio/win/audio_low_latency_output_win.h +++ b/media/audio/win/audio_low_latency_output_win.h
@@ -111,6 +111,7 @@ #include "base/win/scoped_com_initializer.h" #include "base/win/scoped_handle.h" #include "media/audio/audio_io.h" +#include "media/audio/win/audio_manager_win.h" #include "media/base/audio_parameters.h" #include "media/base/media_export.h" @@ -129,7 +130,8 @@ WASAPIAudioOutputStream(AudioManagerWin* manager, const std::string& device_id, const AudioParameters& params, - ERole device_role); + ERole device_role, + AudioManager::LogCallback log_callback); // The dtor is typically called by the AudioManager only and it is usually // triggered by calling AudioOutputStream::Close(). @@ -151,6 +153,8 @@ bool started() const { return render_thread_.get() != NULL; } private: + void SendLogMessage(const char* format, ...) PRINTF_FORMAT(2, 3); + // DelegateSimpleThread::Delegate implementation. void Run() override; @@ -247,6 +251,9 @@ // Pointer to the client that will deliver audio samples to be played out. AudioSourceCallback* source_; + // Callback to send log messages to registered clients. + AudioManager::LogCallback log_callback_; + // An IAudioClient interface which enables a client to create and initialize // an audio stream between an audio application and the audio engine. Microsoft::WRL::ComPtr<IAudioClient> audio_client_;
diff --git a/media/audio/win/audio_manager_win.cc b/media/audio/win/audio_manager_win.cc index 92989314..2e1477d2 100644 --- a/media/audio/win/audio_manager_win.cc +++ b/media/audio/win/audio_manager_win.cc
@@ -241,7 +241,7 @@ communications || device_id == AudioDeviceDescription::kDefaultDeviceId ? std::string() : device_id, - params, communications ? eCommunications : eConsole); + params, communications ? eCommunications : eConsole, log_callback); } // Factory for the implementations of AudioInputStream for AUDIO_PCM_LINEAR @@ -261,7 +261,6 @@ const std::string& device_id, const LogCallback& log_callback) { // Used for both AUDIO_PCM_LOW_LATENCY and AUDIO_PCM_LINEAR. - DVLOG(1) << "MakeLowLatencyInputStream: " << device_id; return new WASAPIAudioInputStream(this, params, device_id, log_callback); }
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc index aa84f51..676959a 100644 --- a/media/audio/win/core_audio_util_win.cc +++ b/media/audio/win/core_audio_util_win.cc
@@ -4,6 +4,7 @@ #include "media/audio/win/core_audio_util_win.h" +#include <comdef.h> #include <devicetopology.h> #include <functiondiscoverykeys_devpkey.h> #include <objbase.h> @@ -684,7 +685,15 @@ return g_is_supported; } -// CoreAudioUtil implementation. +std::string CoreAudioUtil::ErrorToString(HRESULT hresult) { + const _com_error error(hresult); + // If the HRESULT is within the range 0x80040200 to 0x8004FFFF, the WCode() + // method returns the HRESULT minus 0x80040200; otherwise, it returns zero. + return base::StringPrintf("HRESULT: 0x%08lX, WCode: %u, message: \"%s\"", + error.Error(), error.WCode(), + base::UTF16ToUTF8(error.ErrorMessage()).c_str()); +} + std::string CoreAudioUtil::WaveFormatToString(const WaveFormatWrapper format) { // Start with the WAVEFORMATEX part. std::string wave_format = base::StringPrintf(
diff --git a/media/audio/win/core_audio_util_win.h b/media/audio/win/core_audio_util_win.h index 1a797e3..f60e9c9 100644 --- a/media/audio/win/core_audio_util_win.h +++ b/media/audio/win/core_audio_util_win.h
@@ -66,6 +66,9 @@ // it is safe to call from other threads. static bool IsSupported(); + // Converts a COM error into a human-readable string. + static std::string ErrorToString(HRESULT hresult); + // Prints/logs all fields of the format structure in |format|. // Also supports extended versions (WAVEFORMATEXTENSIBLE). static std::string WaveFormatToString(WaveFormatWrapper format);
diff --git a/media/formats/mp2t/es_adapter_video.cc b/media/formats/mp2t/es_adapter_video.cc index a086afa..70e7a59 100644 --- a/media/formats/mp2t/es_adapter_video.cc +++ b/media/formats/mp2t/es_adapter_video.cc
@@ -25,10 +25,9 @@ // to emulate the H264 dpb bumping process. static const size_t kHistorySize = 5; -EsAdapterVideo::EsAdapterVideo( - const NewVideoConfigCB& new_video_config_cb, - const EmitBufferCB& emit_buffer_cb) - : new_video_config_cb_(new_video_config_cb), +EsAdapterVideo::EsAdapterVideo(NewVideoConfigCB new_video_config_cb, + const EmitBufferCB& emit_buffer_cb) + : new_video_config_cb_(std::move(new_video_config_cb)), emit_buffer_cb_(emit_buffer_cb), has_valid_config_(false), has_valid_frame_(false), @@ -36,8 +35,7 @@ base::TimeDelta::FromMilliseconds(kDefaultFrameDurationMs)), buffer_index_(0), has_valid_initial_timestamp_(false), - discarded_frame_count_(0) { -} + discarded_frame_count_(0) {} EsAdapterVideo::~EsAdapterVideo() { }
diff --git a/media/formats/mp2t/es_adapter_video.h b/media/formats/mp2t/es_adapter_video.h index 793b441f..5c9b69b 100644 --- a/media/formats/mp2t/es_adapter_video.h +++ b/media/formats/mp2t/es_adapter_video.h
@@ -33,12 +33,12 @@ // creating a hole in the video timeline. class MEDIA_EXPORT EsAdapterVideo { public: - typedef base::Callback<void(const VideoDecoderConfig&)> NewVideoConfigCB; + using NewVideoConfigCB = + base::RepeatingCallback<void(const VideoDecoderConfig&)>; typedef base::Callback<void(scoped_refptr<StreamParserBuffer>)> EmitBufferCB; - EsAdapterVideo( - const NewVideoConfigCB& new_video_config_cb, - const EmitBufferCB& emit_buffer_cb); + EsAdapterVideo(NewVideoConfigCB new_video_config_cb, + const EmitBufferCB& emit_buffer_cb); ~EsAdapterVideo(); // Force the emission of the pending video buffers. @@ -68,7 +68,7 @@ // (this one must be a key frame). void ReplaceDiscardedFrames(const StreamParserBuffer& stream_parser_buffer); - NewVideoConfigCB new_video_config_cb_; + const NewVideoConfigCB new_video_config_cb_; EmitBufferCB emit_buffer_cb_; bool has_valid_config_;
diff --git a/media/formats/mp2t/es_parser_h264.cc b/media/formats/mp2t/es_parser_h264.cc index 5532d8f2..66e458c 100644 --- a/media/formats/mp2t/es_parser_h264.cc +++ b/media/formats/mp2t/es_parser_h264.cc
@@ -177,9 +177,9 @@ // 3 bytes for the start code + 1 byte for the NALU type. const int kMinAUDSize = 4; -EsParserH264::EsParserH264(const NewVideoConfigCB& new_video_config_cb, +EsParserH264::EsParserH264(NewVideoConfigCB new_video_config_cb, const EmitBufferCB& emit_buffer_cb) - : es_adapter_(new_video_config_cb, emit_buffer_cb), + : es_adapter_(std::move(new_video_config_cb), emit_buffer_cb), h264_parser_(new H264Parser()), current_access_unit_pos_(0), next_access_unit_pos_(0) @@ -192,11 +192,11 @@ } #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) -EsParserH264::EsParserH264(const NewVideoConfigCB& new_video_config_cb, +EsParserH264::EsParserH264(NewVideoConfigCB new_video_config_cb, const EmitBufferCB& emit_buffer_cb, EncryptionScheme init_encryption_scheme, const GetDecryptConfigCB& get_decrypt_config_cb) - : es_adapter_(new_video_config_cb, emit_buffer_cb), + : es_adapter_(std::move(new_video_config_cb), emit_buffer_cb), h264_parser_(new H264Parser()), current_access_unit_pos_(0), next_access_unit_pos_(0),
diff --git a/media/formats/mp2t/es_parser_h264.h b/media/formats/mp2t/es_parser_h264.h index 76b37dc..785d659 100644 --- a/media/formats/mp2t/es_parser_h264.h +++ b/media/formats/mp2t/es_parser_h264.h
@@ -40,12 +40,13 @@ // class MEDIA_EXPORT EsParserH264 : public EsParser { public: - typedef base::Callback<void(const VideoDecoderConfig&)> NewVideoConfigCB; + using NewVideoConfigCB = + base::RepeatingCallback<void(const VideoDecoderConfig&)>; - EsParserH264(const NewVideoConfigCB& new_video_config_cb, + EsParserH264(NewVideoConfigCB new_video_config_cb, const EmitBufferCB& emit_buffer_cb); #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES) - EsParserH264(const NewVideoConfigCB& new_video_config_cb, + EsParserH264(NewVideoConfigCB new_video_config_cb, const EmitBufferCB& emit_buffer_cb, EncryptionScheme init_encryption_scheme, const GetDecryptConfigCB& get_decrypt_config_cb);
diff --git a/media/formats/mp2t/mp2t_stream_parser.cc b/media/formats/mp2t/mp2t_stream_parser.cc index 2c7165d..67fa5971 100644 --- a/media/formats/mp2t/mp2t_stream_parser.cc +++ b/media/formats/mp2t/mp2t_stream_parser.cc
@@ -395,12 +395,12 @@ } std::unique_ptr<EsParser> Mp2tStreamParser::CreateH264Parser(int pes_pid) { - auto on_video_config_changed = base::Bind( + auto on_video_config_changed = base::BindRepeating( &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid); auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer, base::Unretained(this), pes_pid); - return std::make_unique<EsParserH264>(on_video_config_changed, + return std::make_unique<EsParserH264>(std::move(on_video_config_changed), on_emit_video_buffer); } @@ -435,7 +435,7 @@ std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedH264Parser( int pes_pid, bool emit_clear_buffers) { - auto on_video_config_changed = base::Bind( + auto on_video_config_changed = base::BindRepeating( &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid); auto on_emit_video_buffer = base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer, base::Unretained(this), pes_pid); @@ -444,8 +444,8 @@ : base::Bind(&Mp2tStreamParser::GetDecryptConfig, base::Unretained(this)); return std::make_unique<EsParserH264>( - on_video_config_changed, on_emit_video_buffer, initial_encryption_scheme_, - get_decrypt_config); + std::move(on_video_config_changed), on_emit_video_buffer, + initial_encryption_scheme_, get_decrypt_config); } std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedAacParser(
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc index 9cf47f0..263ac45 100644 --- a/net/android/network_change_notifier_android.cc +++ b/net/android/network_change_notifier_android.cc
@@ -91,11 +91,12 @@ class NetworkChangeNotifierAndroid::BlockingThreadObjects { public: BlockingThreadObjects() - : address_tracker_(base::DoNothing(), - base::DoNothing(), - // We're only interested in tunnel interface changes. - base::Bind(NotifyNetworkChangeNotifierObservers), - std::unordered_set<std::string>()) {} + : address_tracker_( + base::DoNothing(), + base::DoNothing(), + // We're only interested in tunnel interface changes. + base::BindRepeating(NotifyNetworkChangeNotifierObservers), + std::unordered_set<std::string>()) {} void Init() { address_tracker_.Init();
diff --git a/net/android/network_change_notifier_android_unittest.cc b/net/android/network_change_notifier_android_unittest.cc index 6eeb9e4..1960ee98 100644 --- a/net/android/network_change_notifier_android_unittest.cc +++ b/net/android/network_change_notifier_android_unittest.cc
@@ -161,8 +161,9 @@ ~BaseNetworkChangeNotifierAndroidTest() override {} void RunTest( - const base::Callback<int(void)>& notifications_count_getter, - const base::Callback<ConnectionType(void)>& connection_type_getter) { + const base::RepeatingCallback<int(void)>& notifications_count_getter, + const base::RepeatingCallback<ConnectionType(void)>& + connection_type_getter) { EXPECT_EQ(0, notifications_count_getter.Run()); EXPECT_EQ(NetworkChangeNotifier::CONNECTION_UNKNOWN, connection_type_getter.Run()); @@ -310,10 +311,10 @@ // delegate's observers are instances of NetworkChangeNotifierAndroid. TEST_F(NetworkChangeNotifierDelegateAndroidTest, DelegateObserverNotified) { // Test the logic with a single observer. - RunTest(base::Bind(&NetworkChangeNotifierDelegateAndroidObserver:: - type_notifications_count, - base::Unretained(&delegate_observer_)), - base::Bind( + RunTest(base::BindRepeating(&NetworkChangeNotifierDelegateAndroidObserver:: + type_notifications_count, + base::Unretained(&delegate_observer_)), + base::BindRepeating( &NetworkChangeNotifierDelegateAndroid::GetCurrentConnectionType, base::Unretained(&delegate_))); // Check that *all* the observers are notified. Both observers should have the @@ -329,10 +330,12 @@ // NetworkChangeNotifierAndroid should reflect that state. TEST_F(NetworkChangeNotifierAndroidTest, NotificationsSentToNetworkChangeNotifierAndroid) { - RunTest(base::Bind(&NetworkChangeNotifierObserver::notifications_count, - base::Unretained(&connection_type_observer_)), - base::Bind(&NetworkChangeNotifierAndroid::GetCurrentConnectionType, - base::Unretained(¬ifier_))); + RunTest( + base::BindRepeating(&NetworkChangeNotifierObserver::notifications_count, + base::Unretained(&connection_type_observer_)), + base::BindRepeating( + &NetworkChangeNotifierAndroid::GetCurrentConnectionType, + base::Unretained(¬ifier_))); } // When a NetworkChangeNotifierAndroid's connection state changes, it should @@ -340,10 +343,9 @@ TEST_F(NetworkChangeNotifierAndroidTest, NotificationsSentToClientsOfNetworkChangeNotifier) { RunTest( - base::Bind( - &NetworkChangeNotifierObserver::notifications_count, - base::Unretained(&connection_type_observer_)), - base::Bind(&NetworkChangeNotifier::GetConnectionType)); + base::BindRepeating(&NetworkChangeNotifierObserver::notifications_count, + base::Unretained(&connection_type_observer_)), + base::BindRepeating(&NetworkChangeNotifier::GetConnectionType)); // Check that *all* the observers are notified. EXPECT_EQ(connection_type_observer_.notifications_count(), other_connection_type_observer_.notifications_count());
diff --git a/net/base/address_tracker_linux.cc b/net/base/address_tracker_linux.cc index 888281e..ffb6e6ef211 100644 --- a/net/base/address_tracker_linux.cc +++ b/net/base/address_tracker_linux.cc
@@ -156,9 +156,9 @@ threads_waiting_for_connection_type_initialization_(0) {} AddressTrackerLinux::AddressTrackerLinux( - const base::Closure& address_callback, - const base::Closure& link_callback, - const base::Closure& tunnel_callback, + const base::RepeatingClosure& address_callback, + const base::RepeatingClosure& link_callback, + const base::RepeatingClosure& tunnel_callback, const std::unordered_set<std::string>& ignored_interfaces) : get_interface_name_(GetInterfaceName), address_callback_(address_callback),
diff --git a/net/base/address_tracker_linux.h b/net/base/address_tracker_linux.h index a2c11162..a18450d 100644 --- a/net/base/address_tracker_linux.h +++ b/net/base/address_tracker_linux.h
@@ -55,9 +55,9 @@ // interfaces used to connect to the internet can cause critical network // changed signals to be lost allowing incorrect stale state to persist. AddressTrackerLinux( - const base::Closure& address_callback, - const base::Closure& link_callback, - const base::Closure& tunnel_callback, + const base::RepeatingClosure& address_callback, + const base::RepeatingClosure& link_callback, + const base::RepeatingClosure& tunnel_callback, const std::unordered_set<std::string>& ignored_interfaces); virtual ~AddressTrackerLinux(); @@ -151,9 +151,9 @@ // overridden by tests. GetInterfaceNameFunction get_interface_name_; - base::Closure address_callback_; - base::Closure link_callback_; - base::Closure tunnel_callback_; + base::RepeatingClosure address_callback_; + base::RepeatingClosure link_callback_; + base::RepeatingClosure tunnel_callback_; // Note that |watcher_| must be inactive when |netlink_fd_| is closed. base::ScopedFD netlink_fd_;
diff --git a/net/cert/cert_verify_proc_builtin_unittest.cc b/net/cert/cert_verify_proc_builtin_unittest.cc index 847f21f..29ba255 100644 --- a/net/cert/cert_verify_proc_builtin_unittest.cc +++ b/net/cert/cert_verify_proc_builtin_unittest.cc
@@ -41,9 +41,9 @@ }; std::unique_ptr<test_server::HttpResponse> HangRequestAndCallback( - base::Closure callback, + base::OnceClosure callback, const test_server::HttpRequest& request) { - callback.Run(); + std::move(callback).Run(); return std::make_unique<test_server::HungResponse>(); } @@ -55,7 +55,7 @@ const std::string& message, scoped_refptr<base::TaskRunner> main_task_runner, const test_server::HttpRequest& request) { - main_task_runner->PostTask(FROM_HERE, base::Bind(FailTest, message)); + main_task_runner->PostTask(FROM_HERE, base::BindOnce(FailTest, message)); auto response = std::make_unique<test_server::BasicHttpResponse>(); response->set_code(HTTP_NOT_ACCEPTABLE); return response; @@ -191,7 +191,7 @@ for (int i = expected_request_count; i < expected_request_count + 1; ++i) { std::string path = base::StringPrintf("/failtest/%i", i); crl_urls.emplace_back(test_server.GetURL(path)); - test_server.RegisterRequestHandler(base::Bind( + test_server.RegisterRequestHandler(base::BindRepeating( &test_server::HandlePrefixedRequest, path, base::BindRepeating(FailRequestAndFailTest, "additional request made after deadline exceeded", @@ -261,7 +261,7 @@ for (int i = expected_request_count; i < expected_request_count + 1; ++i) { std::string path = base::StringPrintf("/failtest/%i", i); ocsp_urls.emplace_back(test_server.GetURL(path)); - test_server.RegisterRequestHandler(base::Bind( + test_server.RegisterRequestHandler(base::BindRepeating( &test_server::HandlePrefixedRequest, path, base::BindRepeating(FailRequestAndFailTest, "additional request made after deadline exceeded",
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 5054c4b6..9663b25 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -2411,7 +2411,7 @@ ASSERT_EQ(1, counter->callback_count()); // NULL callback is safe. - cm->FlushStore(base::Closure()); + cm->FlushStore(base::OnceClosure()); base::RunLoop().RunUntilIdle(); ASSERT_EQ(0, store->flush_count());
diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc index e6970469..9da60b3 100644 --- a/net/disk_cache/disk_cache_test_base.cc +++ b/net/disk_cache/disk_cache_test_base.cc
@@ -248,14 +248,14 @@ EXPECT_THAT(cb.GetResult(rv), IsOk()); } -void DiskCacheTestWithCache::RunTaskForTest(const base::Closure& closure) { +void DiskCacheTestWithCache::RunTaskForTest(base::OnceClosure closure) { if (memory_only_ || !cache_impl_) { - closure.Run(); + std::move(closure).Run(); return; } net::TestCompletionCallback cb; - int rv = cache_impl_->RunTaskForTest(closure, cb.callback()); + int rv = cache_impl_->RunTaskForTest(std::move(closure), cb.callback()); EXPECT_THAT(cb.GetResult(rv), IsOk()); } @@ -311,16 +311,17 @@ if (memory_only_ || !cache_impl_) return; - RunTaskForTest(base::Bind(&disk_cache::BackendImpl::TrimForTest, - base::Unretained(cache_impl_), empty)); + RunTaskForTest(base::BindOnce(&disk_cache::BackendImpl::TrimForTest, + base::Unretained(cache_impl_), empty)); } void DiskCacheTestWithCache::TrimDeletedListForTest(bool empty) { if (memory_only_ || !cache_impl_) return; - RunTaskForTest(base::Bind(&disk_cache::BackendImpl::TrimDeletedListForTest, - base::Unretained(cache_impl_), empty)); + RunTaskForTest( + base::BindOnce(&disk_cache::BackendImpl::TrimDeletedListForTest, + base::Unretained(cache_impl_), empty)); } void DiskCacheTestWithCache::AddDelay() {
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h index 9d00822e..f7b5395b 100644 --- a/net/disk_cache/disk_cache_test_base.h +++ b/net/disk_cache/disk_cache_test_base.h
@@ -155,7 +155,7 @@ int DoomEntriesSince(const base::Time initial_time); std::unique_ptr<TestIterator> CreateIterator(); void FlushQueueForTest(); - void RunTaskForTest(const base::Closure& closure); + void RunTaskForTest(base::OnceClosure closure); int ReadData(disk_cache::Entry* entry, int index, int offset, net::IOBuffer* buf, int len); int WriteData(disk_cache::Entry* entry, int index, int offset,
diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc index 41e24783..1e3226a 100644 --- a/net/disk_cache/entry_unittest.cc +++ b/net/disk_cache/entry_unittest.cc
@@ -164,10 +164,8 @@ ASSERT_TRUE(nullptr != entry); // The bulk of the test runs from within the callback, on the cache thread. - RunTaskForTest(base::Bind(&DiskCacheEntryTest::InternalSyncIOBackground, - base::Unretained(this), - entry)); - + RunTaskForTest(base::BindOnce(&DiskCacheEntryTest::InternalSyncIOBackground, + base::Unretained(this), entry)); entry->Doom(); entry->Close(); @@ -400,9 +398,8 @@ ASSERT_THAT(CreateEntry("the first key", &entry), IsOk()); // The bulk of the test runs from within the callback, on the cache thread. - RunTaskForTest(base::Bind(&DiskCacheEntryTest::ExternalSyncIOBackground, - base::Unretained(this), - entry)); + RunTaskForTest(base::BindOnce(&DiskCacheEntryTest::ExternalSyncIOBackground, + base::Unretained(this), entry)); entry->Doom(); entry->Close();
diff --git a/net/http/structured_headers.cc b/net/http/structured_headers.cc index eca50ed..8075e869 100644 --- a/net/http/structured_headers.cc +++ b/net/http/structured_headers.cc
@@ -305,7 +305,8 @@ // Parses a Token ([SH09] 4.2.10, [SH15] 4.2.6). base::Optional<Item> ReadToken() { - if (input_.empty() || !base::IsAsciiAlpha(input_.front())) { + if (input_.empty() || + !(base::IsAsciiAlpha(input_.front()) || input_.front() == '*')) { LogParseError("ReadToken", "ALPHA"); return base::nullopt; } @@ -538,7 +539,8 @@ if (value.is_token()) { // Serializes a Token ([SH15] 4.1.7). if (!value.GetString().size() || - !base::IsAsciiAlpha(value.GetString().front())) + !(base::IsAsciiAlpha(value.GetString().front()) || + value.GetString().front() == '*')) return false; if (value.GetString().find_first_not_of(kTokenChars15) != std::string::npos)
diff --git a/net/http/structured_headers_unittest.cc b/net/http/structured_headers_unittest.cc index 285675a..d234d72 100644 --- a/net/http/structured_headers_unittest.cc +++ b/net/http/structured_headers_unittest.cc
@@ -61,6 +61,7 @@ {"bad token - item", "abc$@%!", base::nullopt}, {"leading whitespace", " foo", Token("foo"), "foo"}, {"trailing whitespace", "foo ", Token("foo"), "foo"}, + {"leading asterisk", "*foo", Token("*foo")}, // Number {"basic integer", "42", Integer(42L)}, {"zero integer", "0", Integer(0L)}, @@ -427,6 +428,7 @@ "*iQ==*"}, {"non-ASCII binary", "*/+Ah*", Item("\xFF\xE0!", Item::kByteSequenceType)}, {"base64url binary", "*_-Ah*", base::nullopt}, + {"token with leading asterisk", "*foo", base::nullopt}, }; // For Structured Headers Draft 15 @@ -763,7 +765,6 @@ {"begins with colon", ":token"}, {"begins with percent", "%token"}, {"begins with period", ".token"}, - {"begins with asterisk", "*token"}, {"begins with slash", "/token"}, }; for (const auto& bad_token : bad_tokens) {
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index cc91356..6a4a8b45 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -183,8 +183,9 @@ NetworkChangeNotifier::AddConnectionTypeObserver(this); throughput_analyzer_.reset(new nqe::internal::ThroughputAnalyzer( this, params_.get(), base::ThreadTaskRunnerHandle::Get(), - base::Bind(&NetworkQualityEstimator::OnNewThroughputObservationAvailable, - weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating( + &NetworkQualityEstimator::OnNewThroughputObservationAvailable, + weak_ptr_factory_.GetWeakPtr()), tick_clock_, net_log_)); watcher_factory_.reset(new nqe::internal::SocketWatcherFactory(
diff --git a/net/nqe/throughput_analyzer.h b/net/nqe/throughput_analyzer.h index 5e3e14c..a5378cf8 100644 --- a/net/nqe/throughput_analyzer.h +++ b/net/nqe/throughput_analyzer.h
@@ -20,7 +20,7 @@ #include "net/log/net_log_with_source.h" namespace { -typedef base::Callback<void(int32_t)> ThroughputObservationCallback; +typedef base::RepeatingCallback<void(int32_t)> ThroughputObservationCallback; } namespace base {
diff --git a/net/nqe/throughput_analyzer_unittest.cc b/net/nqe/throughput_analyzer_unittest.cc index 3a6b50a..8d6b87e 100644 --- a/net/nqe/throughput_analyzer_unittest.cc +++ b/net/nqe/throughput_analyzer_unittest.cc
@@ -59,7 +59,7 @@ network_quality_estimator, params, base::ThreadTaskRunnerHandle::Get(), - base::Bind( + base::BindRepeating( &TestThroughputAnalyzer::OnNewThroughputObservationAvailable, base::Unretained(this)), tick_clock,
diff --git a/services/device/serial/serial_io_handler.cc b/services/device/serial/serial_io_handler.cc index 23346a7..a68b67c5 100644 --- a/services/device/serial/serial_io_handler.cc +++ b/services/device/serial/serial_io_handler.cc
@@ -162,10 +162,13 @@ return true; } +void SerialIoHandler::PreClose() {} + void SerialIoHandler::Close(base::OnceClosure callback) { if (file_.IsValid()) { CancelRead(mojom::SerialReceiveError::DISCONNECTED); CancelWrite(mojom::SerialSendError::DISCONNECTED); + PreClose(); base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
diff --git a/services/device/serial/serial_io_handler.h b/services/device/serial/serial_io_handler.h index 8cd8c59d..b70906f 100644 --- a/services/device/serial/serial_io_handler.h +++ b/services/device/serial/serial_io_handler.h
@@ -136,6 +136,9 @@ // Performs platform-specific, one-time port configuration on open. virtual bool PostOpen(); + // Performs platform-specific operations before |file_| is closed. + virtual void PreClose(); + // Called by the implementation to signal that the active read has completed. // WARNING: Calling this method can destroy the SerialIoHandler instance // if the associated I/O operation was the only thing keeping it alive.
diff --git a/services/device/serial/serial_io_handler_posix.cc b/services/device/serial/serial_io_handler_posix.cc index 13ab169..452d8153 100644 --- a/services/device/serial/serial_io_handler_posix.cc +++ b/services/device/serial/serial_io_handler_posix.cc
@@ -295,6 +295,11 @@ #endif } +void SerialIoHandlerPosix::PreClose() { + StopWatchingFileRead(); + StopWatchingFileWrite(); +} + SerialIoHandlerPosix::SerialIoHandlerPosix( const base::FilePath& port, scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
diff --git a/services/device/serial/serial_io_handler_posix.h b/services/device/serial/serial_io_handler_posix.h index 39d187c..3d69c6d0 100644 --- a/services/device/serial/serial_io_handler_posix.h +++ b/services/device/serial/serial_io_handler_posix.h
@@ -30,6 +30,7 @@ void CancelWriteImpl() override; bool ConfigurePortImpl() override; bool PostOpen() override; + void PreClose() override; bool Flush() const override; mojom::SerialPortControlSignalsPtr GetControlSignals() const override; bool SetControlSignals(
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index e938cfa9..8727935 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -59,16 +59,6 @@ const base::Feature kDelayRequestsOnMultiplexedConnections{ "DelayRequestsOnMultiplexedConnections", base::FEATURE_ENABLED_BY_DEFAULT}; -// Implementation of https://mikewest.github.io/sec-metadata/ -const base::Feature kFetchMetadata{"FetchMetadata", - base::FEATURE_ENABLED_BY_DEFAULT}; - -// The `Sec-Fetch-Dest` header is split out from the main "FetchMetadata" -// feature so we can ship the broader feature without this specifific bit -// while we continue discussion. -const base::Feature kFetchMetadataDestination{"FetchMetadataDestination", - base::FEATURE_ENABLED_BY_DEFAULT}; - // When kRequestInitiatorSiteLock is enabled, then CORB, CORP and Sec-Fetch-Site // will validate network::ResourceRequest::request_initiator against // network::mojom::URLLoaderFactoryParams::request_initiator_site_lock.
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h index 95590a9..29f15af 100644 --- a/services/network/public/cpp/features.h +++ b/services/network/public/cpp/features.h
@@ -29,10 +29,6 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kDelayRequestsOnMultiplexedConnections; COMPONENT_EXPORT(NETWORK_CPP) -extern const base::Feature kFetchMetadata; -COMPONENT_EXPORT(NETWORK_CPP) -extern const base::Feature kFetchMetadataDestination; -COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kRequestInitiatorSiteLock; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kPauseBrowserInitiatedHeavyTrafficForP2P;
diff --git a/services/network/sec_header_helpers.cc b/services/network/sec_header_helpers.cc index c14fddb..a02160b2 100644 --- a/services/network/sec_header_helpers.cc +++ b/services/network/sec_header_helpers.cc
@@ -153,8 +153,6 @@ const mojom::URLLoaderFactoryParams& factory_params) { DCHECK(request); DCHECK_NE(0u, request->url_chain().size()); - if (!base::FeatureList::IsEnabled(features::kFetchMetadata)) - return; // Only append the header to potentially trustworthy URLs. const GURL& target_url = @@ -172,9 +170,6 @@ const GURL& pending_redirect_url) { DCHECK(request); - if (!base::FeatureList::IsEnabled(features::kFetchMetadata)) - return; - // If our redirect destination is not trusted it would not have had sec-ch- or // sec-fetch- prefixed headers added to it. Our previous hops may have added // these headers if the current url is trustworthy though so we should try to
diff --git a/storage/browser/file_system/file_system_quota_client.cc b/storage/browser/file_system/file_system_quota_client.cc index 8718c845..0fa79a6 100644 --- a/storage/browser/file_system/file_system_quota_client.cc +++ b/storage/browser/file_system/file_system_quota_client.cc
@@ -36,10 +36,10 @@ FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); if (!quota_util) return; - std::set<GURL> origins; + std::set<url::Origin> origins; quota_util->GetOriginsForTypeOnFileTaskRunner(type, &origins); for (auto origin : origins) - origins_ptr->insert(url::Origin::Create(origin)); + origins_ptr->insert(origin); } void GetOriginsForHostOnFileTaskRunner(FileSystemContext* context, @@ -52,10 +52,10 @@ FileSystemQuotaUtil* quota_util = context->GetQuotaUtil(type); if (!quota_util) return; - std::set<GURL> origins; + std::set<url::Origin> origins; quota_util->GetOriginsForHostOnFileTaskRunner(type, host, &origins); for (auto origin : origins) - origins_ptr->insert(url::Origin::Create(origin)); + origins_ptr->insert(origin); } void DidGetFileSystemQuotaClientOrigins(
diff --git a/storage/browser/file_system/file_system_quota_util.h b/storage/browser/file_system/file_system_quota_util.h index dfaa6f0f..94f66d8 100644 --- a/storage/browser/file_system/file_system_quota_util.h +++ b/storage/browser/file_system/file_system_quota_util.h
@@ -14,7 +14,6 @@ #include "base/files/file.h" #include "base/memory/scoped_refptr.h" #include "storage/common/file_system/file_system_types.h" -#include "url/gurl.h" namespace url { class Origin; @@ -46,12 +45,14 @@ QuotaManagerProxy* proxy, FileSystemType type) = 0; - virtual void GetOriginsForTypeOnFileTaskRunner(FileSystemType type, - std::set<GURL>* origins) = 0; + virtual void GetOriginsForTypeOnFileTaskRunner( + FileSystemType type, + std::set<url::Origin>* origins) = 0; - virtual void GetOriginsForHostOnFileTaskRunner(FileSystemType type, - const std::string& host, - std::set<GURL>* origins) = 0; + virtual void GetOriginsForHostOnFileTaskRunner( + FileSystemType type, + const std::string& host, + std::set<url::Origin>* origins) = 0; // Returns the amount of data used for the origin for usage tracking. virtual int64_t GetOriginUsageOnFileTaskRunner(
diff --git a/storage/browser/file_system/plugin_private_file_system_backend.cc b/storage/browser/file_system/plugin_private_file_system_backend.cc index 0625582..084b305 100644 --- a/storage/browser/file_system/plugin_private_file_system_backend.cc +++ b/storage/browser/file_system/plugin_private_file_system_backend.cc
@@ -253,20 +253,20 @@ void PluginPrivateFileSystemBackend::GetOriginsForTypeOnFileTaskRunner( FileSystemType type, - std::set<GURL>* origins) { + std::set<url::Origin>* origins) { if (!CanHandleType(type)) return; std::unique_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( obfuscated_file_util()->CreateOriginEnumerator()); base::Optional<url::Origin> origin; while ((origin = enumerator->Next()).has_value()) - origins->insert(origin->GetURL()); + origins->insert(origin.value()); } void PluginPrivateFileSystemBackend::GetOriginsForHostOnFileTaskRunner( FileSystemType type, const std::string& host, - std::set<GURL>* origins) { + std::set<url::Origin>* origins) { if (!CanHandleType(type)) return; std::unique_ptr<ObfuscatedFileUtil::AbstractOriginEnumerator> enumerator( @@ -274,7 +274,7 @@ base::Optional<url::Origin> origin; while ((origin = enumerator->Next()).has_value()) { if (host == net::GetHostOrSpecFromURL(origin->GetURL())) - origins->insert(origin->GetURL()); + origins->insert(origin.value()); } }
diff --git a/storage/browser/file_system/plugin_private_file_system_backend.h b/storage/browser/file_system/plugin_private_file_system_backend.h index 8a0b161..cd26fea8 100644 --- a/storage/browser/file_system/plugin_private_file_system_backend.h +++ b/storage/browser/file_system/plugin_private_file_system_backend.h
@@ -110,11 +110,13 @@ void PerformStorageCleanupOnFileTaskRunner(FileSystemContext* context, QuotaManagerProxy* proxy, FileSystemType type) override; - void GetOriginsForTypeOnFileTaskRunner(FileSystemType type, - std::set<GURL>* origins) override; - void GetOriginsForHostOnFileTaskRunner(FileSystemType type, - const std::string& host, - std::set<GURL>* origins) override; + void GetOriginsForTypeOnFileTaskRunner( + FileSystemType type, + std::set<url::Origin>* origins) override; + void GetOriginsForHostOnFileTaskRunner( + FileSystemType type, + const std::string& host, + std::set<url::Origin>* origins) override; int64_t GetOriginUsageOnFileTaskRunner(FileSystemContext* context, const url::Origin& origin, FileSystemType type) override;
diff --git a/storage/browser/file_system/sandbox_file_system_backend_delegate.cc b/storage/browser/file_system/sandbox_file_system_backend_delegate.cc index d9fce8b..c1bb191 100644 --- a/storage/browser/file_system/sandbox_file_system_backend_delegate.cc +++ b/storage/browser/file_system/sandbox_file_system_backend_delegate.cc
@@ -371,14 +371,14 @@ void SandboxFileSystemBackendDelegate::GetOriginsForTypeOnFileTaskRunner( FileSystemType type, - std::set<GURL>* origins) { + std::set<url::Origin>* origins) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); DCHECK(origins); std::unique_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); base::Optional<url::Origin> origin; while ((origin = enumerator->Next()).has_value()) { if (enumerator->HasFileSystemType(type)) - origins->insert(origin->GetURL()); + origins->insert(origin.value()); } switch (type) { case kFileSystemTypeTemporary: @@ -395,7 +395,7 @@ void SandboxFileSystemBackendDelegate::GetOriginsForHostOnFileTaskRunner( FileSystemType type, const std::string& host, - std::set<GURL>* origins) { + std::set<url::Origin>* origins) { DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); DCHECK(origins); std::unique_ptr<OriginEnumerator> enumerator(CreateOriginEnumerator()); @@ -403,7 +403,7 @@ while ((origin = enumerator->Next()).has_value()) { if (host == net::GetHostOrSpecFromURL(origin->GetURL()) && enumerator->HasFileSystemType(type)) - origins->insert(origin->GetURL()); + origins->insert(origin.value()); } }
diff --git a/storage/browser/file_system/sandbox_file_system_backend_delegate.h b/storage/browser/file_system/sandbox_file_system_backend_delegate.h index 9de2196..affeed7 100644 --- a/storage/browser/file_system/sandbox_file_system_backend_delegate.h +++ b/storage/browser/file_system/sandbox_file_system_backend_delegate.h
@@ -138,11 +138,13 @@ void PerformStorageCleanupOnFileTaskRunner(FileSystemContext* context, QuotaManagerProxy* proxy, FileSystemType type) override; - void GetOriginsForTypeOnFileTaskRunner(FileSystemType type, - std::set<GURL>* origins) override; - void GetOriginsForHostOnFileTaskRunner(FileSystemType type, - const std::string& host, - std::set<GURL>* origins) override; + void GetOriginsForTypeOnFileTaskRunner( + FileSystemType type, + std::set<url::Origin>* origins) override; + void GetOriginsForHostOnFileTaskRunner( + FileSystemType type, + const std::string& host, + std::set<url::Origin>* origins) override; int64_t GetOriginUsageOnFileTaskRunner(FileSystemContext* context, const url::Origin& origin, FileSystemType type) override;
diff --git a/storage/browser/test/test_file_system_backend.cc b/storage/browser/test/test_file_system_backend.cc index bfe59b70..60e4621 100644 --- a/storage/browser/test/test_file_system_backend.cc +++ b/storage/browser/test/test_file_system_backend.cc
@@ -82,14 +82,16 @@ return scoped_refptr<QuotaReservation>(); } - void GetOriginsForTypeOnFileTaskRunner(FileSystemType type, - std::set<GURL>* origins) override { + void GetOriginsForTypeOnFileTaskRunner( + FileSystemType type, + std::set<url::Origin>* origins) override { NOTREACHED(); } - void GetOriginsForHostOnFileTaskRunner(FileSystemType type, - const std::string& host, - std::set<GURL>* origins) override { + void GetOriginsForHostOnFileTaskRunner( + FileSystemType type, + const std::string& host, + std::set<url::Origin>* origins) override { NOTREACHED(); }
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 0a932d8..72517d8 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -184,6 +184,22 @@ }, { "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 15 + }, + "test": "browser_tests", + "test_target": "//chrome/test:browser_tests" + }, + { + "args": [ "--enable-features=NetworkService" ], "merge": { @@ -226,6 +242,22 @@ }, { "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 2 + }, + "test": "content_browsertests", + "test_target": "//content/test:content_browsertests" + }, + { + "args": [ "--enable-features=NetworkService" ], "merge": { @@ -241,6 +273,21 @@ }, { "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_browsertests", + "test_target": "//extensions:extensions_browsertests" + }, + { + "args": [ "--enable-features=NetworkService" ], "merge": { @@ -256,6 +303,22 @@ "test_target": "//chrome/test:interactive_ui_tests" }, { + "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_interactive_ui_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 3 + }, + "test": "interactive_ui_tests", + "test_target": "//chrome/test:interactive_ui_tests" + }, + { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -318,6 +381,22 @@ }, { "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 15 + }, + "test": "browser_tests", + "test_target": "//chrome/test:browser_tests" + }, + { + "args": [ "--enable-features=NetworkService,NetworkServiceInProcess" ], "merge": { @@ -333,6 +412,53 @@ "test_target": "//content/test:content_browsertests" }, { + "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 2 + }, + "test": "content_browsertests", + "test_target": "//content/test:content_browsertests" + }, + { + "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_extensions_browsertests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "extensions_browsertests", + "test_target": "//extensions:extensions_browsertests" + }, + { + "args": [ + "--enable-features=StorageServiceOutOfProcess" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "storage_service_unsandboxed_interactive_ui_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 3 + }, + "test": "interactive_ui_tests", + "test_target": "//chrome/test:interactive_ui_tests" + }, + { "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -10170,42 +10296,6 @@ } ] }, - "test": "boringssl_crypto_tests", - "test_target": "//third_party/boringssl:boringssl_crypto_tests" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "arm64", - "inside_docker": "1", - "os": "Ubuntu-16.04" - } - ] - }, - "test": "boringssl_ssl_tests", - "test_target": "//third_party/boringssl:boringssl_ssl_tests" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "arm64", - "inside_docker": "1", - "os": "Ubuntu-16.04" - } - ] - }, "test": "cast_runner_browsertests", "test_target": "//fuchsia/runners:cast_runner_browsertests" }, @@ -10247,27 +10337,6 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.cc_unittests.filter" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "arm64", - "inside_docker": "1", - "os": "Ubuntu-16.04" - } - ] - }, - "test": "cc_unittests", - "test_target": "//cc:cc_unittests" - }, - { - "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_unittests.filter" ], "merge": { @@ -10603,24 +10672,6 @@ "test_target": "//ui/base:ui_base_unittests" }, { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "arm64", - "inside_docker": "1", - "os": "Ubuntu-16.04" - } - ] - }, - "test": "url_unittests", - "test_target": "//url:url_unittests" - }, - { "args": [ "--child-arg=--ozone-platform=headless" ],
diff --git a/testing/buildbot/filters/android.emulator.chrome_public_test_apk.filter b/testing/buildbot/filters/android.emulator.chrome_public_test_apk.filter index 905aed3..90dfc65 100644 --- a/testing/buildbot/filters/android.emulator.chrome_public_test_apk.filter +++ b/testing/buildbot/filters/android.emulator.chrome_public_test_apk.filter
@@ -1,13 +1,11 @@ -# crbug/1036553 --org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTabMenuDismissedOnOrientationChange --org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTranslateCompactInfoBarAppears --org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTranslateCompactInfoBarOverflowMenus --org.chromium.chrome.browser.translate.TranslateCompactInfoBarTest.testTranslateCompactInfoBarReopenOnTarget - # crbug/1036571 +-org.chromium.shape_detection.BarcodeDetectionImplTest.testDetectBarcodeWithHint +-org.chromium.shape_detection.BarcodeDetectionImplTest.testDetectBarcodeWithoutHint -org.chromium.shape_detection.FaceDetectionImplTest.testDetectRotatedFaceWithGmsCore +-org.chromium.shape_detection.FaceDetectionImplTest.testDetectValidImageWithGmsCore -org.chromium.shape_detection.TextDetectionImplTest.testDetectSucceedsOnValidBitmap -org.chromium.chrome.browser.shape_detection.ShapeDetectionTest.testBarcodeDetection +-org.chromium.chrome.browser.shape_detection.ShapeDetectionTest.testTextDetection # crbug/1017141 -org.chromium.chrome.browser.tasks.tab_management.TabSwitcherMultiWindowTest.testMoveTabsAcrossWindow_GTS_WithoutGroup @@ -19,8 +17,14 @@ # vr tests do not apply to emulator -org.chromium.chrome.browser.hardware_acceleration.ManifestHWATest.testAccelerationDisabled -# crbug/1017141 --org.chromium.chrome.browser.tasks.tab_management.TabSwitcherMultiWindowTest.testMoveTabsAcrossWindow_GTS_WithoutGroup - # crbug/1032118 -org.chromium.chrome.browser.notifications.StandardNotificationBuilderTest.testSetAll + +# crbug/1036551 +-org.chromium.chrome.browser.tabmodel.TabModelMergingTest.testMergeOnColdStartIntoChromeTabbedActivity2 + +# crbug/1036459 +-org.chromium.chrome.browser.ntp.NewTabPageTest.testFocusFakebox + +# crbug/1040088 +-org.chromium.chrome.browser.payments.PaymentRequestRetryTest.testRetryWithShippingAddressErrorsAndPayerErrors
diff --git a/testing/buildbot/filters/gpu.skiarenderer_vulkan_content_browsertests.filter b/testing/buildbot/filters/gpu.skiarenderer_vulkan_content_browsertests.filter index 866f90a..9791d6f 100644 --- a/testing/buildbot/filters/gpu.skiarenderer_vulkan_content_browsertests.filter +++ b/testing/buildbot/filters/gpu.skiarenderer_vulkan_content_browsertests.filter
@@ -2,7 +2,3 @@ -NavigationBrowserTest.HistoryBackCancelPendingNavigationUserGesture/1 -SitePerProcessBrowserTest.* -TextFragmentAnchorBrowserTest.DisabledOnScriptNavigation/0 - -# crbug.com/1037939 --BackForwardCacheBrowserTest.VideoSuspendAndResume --P/CompositorImplBrowserTestRefreshRate.VideoPreference/0
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 6ebfb05..41257da 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -382,6 +382,7 @@ # https://crbug.com/1054545 'Fuchsia ARM64', 'Fuchsia x64', + 'fuchsia-fyi-arm64-rel', ], }, 'boringssl_ssl_tests': { @@ -389,6 +390,7 @@ # https://crbug.com/1054545 'Fuchsia ARM64', 'Fuchsia x64', + 'fuchsia-fyi-arm64-rel', ], }, 'breakpad_unittests': { @@ -569,6 +571,7 @@ 'remove_from': [ 'Fuchsia ARM64', # https://crbug.com/1046552 'Fuchsia x64', # https://crbug.com/1046552 + 'fuchsia-fyi-arm64-rel', ], }, 'checkbins': { @@ -2165,6 +2168,7 @@ # crbug.com/1054240 'Fuchsia ARM64', 'Fuchsia x64', + 'fuchsia-fyi-arm64-rel', ], }, 'video_decode_accelerator_gl_unittest': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 7d2c0008..73ff3b3 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3275,6 +3275,42 @@ }, }, + 'storage_service_gtests': { + 'storage_service_unsandboxed_browser_tests': { + 'args': [ + '--enable-features=StorageServiceOutOfProcess', + ], + 'swarming': { + 'shards': 15, + }, + 'test': 'browser_tests', + }, + 'storage_service_unsandboxed_content_browsertests': { + 'args': [ + '--enable-features=StorageServiceOutOfProcess', + ], + 'swarming': { + 'shards': 2, + }, + 'test': 'content_browsertests', + }, + 'storage_service_unsandboxed_extensions_browsertests': { + 'args': [ + '--enable-features=StorageServiceOutOfProcess', + ], + 'test': 'extensions_browsertests', + }, + 'storage_service_unsandboxed_interactive_ui_tests': { + 'args': [ + '--enable-features=StorageServiceOutOfProcess' + ], + 'swarming': { + 'shards': 3, + }, + 'test': 'interactive_ui_tests', + }, + }, + 'swangle_gtests': { 'angle_deqp_egl_tests': { 'args': [ @@ -4401,6 +4437,7 @@ 'aura_gtests', 'mojo_chromiumos_specific_gtests', 'network_service_gtests', + 'storage_service_gtests', ], 'mojo_linux_gtests': [ @@ -4410,6 +4447,7 @@ 'mojo_windows_specific_gtests', 'network_service_fyi_gtests', 'network_service_in_process_gtests', + 'storage_service_gtests', ], 'network_service_extra_gtests': [
diff --git a/testing/iossim/BUILD.gn b/testing/iossim/BUILD.gn index 71a20741..0358723 100644 --- a/testing/iossim/BUILD.gn +++ b/testing/iossim/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/ios/ios_sdk.gni") import("//build/config/mac/mac_sdk.gni") if (current_toolchain == host_toolchain) { @@ -16,4 +17,8 @@ sources = [ get_label_info(":iossim($host_toolchain)", "root_out_dir") + "/iossim" ] } +} else { + group("iossim") { + public_deps = [ ":iossim($default_toolchain)" ] + } }
diff --git a/testing/test.gni b/testing/test.gni index 2b4e0f7f..eda4330 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -23,6 +23,12 @@ import("//build/config/chromeos/rules.gni") } +if (is_ios) { + import("//build/config/ios/ios_sdk.gni") + import("//build/config/ios/ios_test_runner_wrapper.gni") + import("//build/config/ios/rules.gni") +} + # Define a test as an executable (or apk on Android) with the "testonly" flag # set. # Variable: @@ -227,9 +233,6 @@ output_name = _exec_target } } else if (is_ios) { - import("//build/config/ios/ios_sdk.gni") - import("//build/config/ios/rules.gni") - declare_args() { # Keep the unittest-as-xctest functionality defaulted to off until the # bots are updated to handle it properly. @@ -239,6 +242,31 @@ } _test_target = target_name + _wrapper_output_name = "run_${target_name}" + ios_test_runner_wrapper(_wrapper_output_name) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "executable_args", + "retries", + "shards", + ]) + + _root_build_dir = rebase_path("${root_build_dir}", root_build_dir) + + if (!defined(executable_args)) { + executable_args = [] + } + executable_args += [ + "--app", + "@WrappedPath(${_root_build_dir}/${_test_target}.app)", + ] + + wrapper_output_name = "${_wrapper_output_name}" + } + _resources_bundle_data = target_name + "_resources_bundle_data" bundle_data(_resources_bundle_data) { @@ -281,6 +309,13 @@ bundle_deps = [] } bundle_deps += [ ":$_resources_bundle_data" ] + + if (!defined(data_deps)) { + data_deps = [] + } + + # Include the generate_wrapper as part of data_deps + data_deps += [ ":${_wrapper_output_name}" ] } } else if (is_chromeos && cros_board != "") { # Building for a cros board (ie: not linux-chromeos).
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b610d1c..004dead 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -93,21 +93,6 @@ ] } ], - "AndroidClipboardTextSuggestions": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "OmniboxEnableClipboardProviderTextSuggestions" - ] - } - ] - } - ], "AndroidInProductHelpContextualSearchPromotePanelOpen": [ { "platforms": [ @@ -495,26 +480,6 @@ ] } ], - "AppendFrameOriginToNetworkIsolationKey": [ - { - "platforms": [ - "android", - "android_webview", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "AppendFrameOriginToNetworkIsolationKey" - ] - } - ] - } - ], "AssumeOverlapAfterFixedOrStickyPosition": [ { "platforms": [ @@ -5205,9 +5170,11 @@ ], "experiments": [ { - "name": "Enabled", + "name": "Enabled_Stable", "enable_features": [ - "SplitCacheByNetworkIsolationKey" + "AppendFrameOriginToNetworkIsolationKey", + "SplitCacheByNetworkIsolationKey", + "UseRegistrableDomainInNetworkIsolationKey" ] } ] @@ -5861,29 +5828,10 @@ ] } ], - "UseRegistrableDomainInNetworkIsolationKey": [ - { - "platforms": [ - "android", - "android_webview", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "UseRegistrableDomainInNetworkIsolationKey" - ] - } - ] - } - ], "UseSkiaRenderer": [ { "platforms": [ + "android", "linux", "windows" ],
diff --git a/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc b/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc index b3d9ba9..7ba88c0 100644 --- a/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc +++ b/third_party/blink/common/bluetooth/web_bluetooth_device_id.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h" +#include <utility> + #include "base/base64.h" #include "base/strings/string_util.h" #include "crypto/random.h" @@ -83,6 +85,11 @@ return !(*this == device_id); } +bool WebBluetoothDeviceId::operator<( + const WebBluetoothDeviceId& device_id) const { + return str() < device_id.str(); +} + std::ostream& operator<<(std::ostream& out, const WebBluetoothDeviceId& device_id) { return out << device_id.str();
diff --git a/third_party/blink/perf_tests/css/CustomPropertiesPendingSubstitution.html b/third_party/blink/perf_tests/css/CustomPropertiesPendingSubstitution.html new file mode 100644 index 0000000..88b1871 --- /dev/null +++ b/third_party/blink/perf_tests/css/CustomPropertiesPendingSubstitution.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<script src="../resources/runner.js"></script> +<script src="resources/utils.js"></script> +<link help="https://drafts.csswg.org/css-variables/#pending-substitution-value"> +<div id="container" style="height: 100px; overflow: hidden"></div> +<script> + createDOMTree(container, 2, 3); + applyCSSRule(':root { --border: 4mm ridge rgba(170, 50, 220, .6); }'); + applyCSSRule(':root { --margin: 1px 2px 3px 4px; }'); + applyCSSRule(':root { --padding: 1px 2px 3px 4px; }'); + applyCSSRule(':root { --background: content-box radial-gradient(crimson, skyblue); }'); + + const sequence_size = 2000; + + function create_var_sequence() { + let chain = []; + for (let i = 0; i < sequence_size; ++i) { + chain.push(`var(--v${i}, )`); + } + return chain.join(' '); + } + + applyCSSRule(`div { border: ${create_var_sequence()} var(--border); }`); + applyCSSRule(`div { margin: ${create_var_sequence()} var(--margin); }`); + applyCSSRule(`div { padding: ${create_var_sequence()} var(--padding); }`); + applyCSSRule(`div { background: ${create_var_sequence()} var(--bakground); }`); + + PerfTestRunner.measureTime({ + description: 'Measure impact of resolving pending-substitution-values', + run: function() { + container.style.setProperty('display', 'none'); + forceStyleRecalc(container); + container.style.setProperty('display', 'block'); + forceStyleRecalc(container); + } + }); +</script>
diff --git a/third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h b/third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h index 5d00935..0177372 100644 --- a/third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h +++ b/third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h
@@ -41,6 +41,7 @@ bool operator==(const WebBluetoothDeviceId& device_id) const; bool operator!=(const WebBluetoothDeviceId& device_id) const; + bool operator<(const WebBluetoothDeviceId& device_id) const; private: std::string device_id_;
diff --git a/third_party/blink/public/common/css/preferred_color_scheme.h b/third_party/blink/public/common/css/preferred_color_scheme.h index b86c667e..d14dde5 100644 --- a/third_party/blink/public/common/css/preferred_color_scheme.h +++ b/third_party/blink/public/common/css/preferred_color_scheme.h
@@ -12,6 +12,7 @@ kNoPreference, kDark, kLight, + kMaxValue = kLight, }; } // namespace blink
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index 0fda7e0..c2a6fca 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -165,9 +165,7 @@ BLINK_PLATFORM_EXPORT static void EnableLazyImageLoadingMetadataFetch(bool); BLINK_PLATFORM_EXPORT static void EnableScriptedSpeechRecognition(bool); BLINK_PLATFORM_EXPORT static void EnableScriptedSpeechSynthesis(bool); - BLINK_PLATFORM_EXPORT static void EnableFetchMetadata(bool); BLINK_PLATFORM_EXPORT static void EnableAutoLazyLoadOnReloads(bool); - BLINK_PLATFORM_EXPORT static void EnableFetchMetadataDestination(bool); BLINK_PLATFORM_EXPORT static void EnableSharedArrayBuffer(bool); BLINK_PLATFORM_EXPORT static void EnableSharedWorker(bool); BLINK_PLATFORM_EXPORT static void EnableTextFragmentAnchor(bool);
diff --git a/third_party/blink/public/platform/web_theme_engine.h b/third_party/blink/public/platform/web_theme_engine.h index ecd3c9f..19523a8 100644 --- a/third_party/blink/public/platform/web_theme_engine.h +++ b/third_party/blink/public/platform/web_theme_engine.h
@@ -34,7 +34,6 @@ #include "base/optional.h" #include "base/time/time.h" #include "third_party/blink/public/common/css/forced_colors.h" -#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/platform/web_color_scheme.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_scrollbar_overlay_color_theme.h" @@ -233,11 +232,6 @@ virtual ForcedColors GetForcedColors() const { return ForcedColors::kNone; } virtual void SetForcedColors(const blink::ForcedColors forced_colors) {} - virtual blink::PreferredColorScheme PreferredColorScheme() const { - return PreferredColorScheme::kNoPreference; - } - virtual void SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) {} }; } // namespace blink
diff --git a/third_party/blink/public/web/web_settings.h b/third_party/blink/public/web/web_settings.h index 1fe16cd..9a47e89b9 100644 --- a/third_party/blink/public/web/web_settings.h +++ b/third_party/blink/public/web/web_settings.h
@@ -34,6 +34,7 @@ #include <unicode/uscript.h> #include "third_party/blink/public/common/css/navigation_controls.h" +#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/platform/pointer_properties.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_effective_connection_type.h" @@ -293,6 +294,7 @@ virtual void SetLazyImageFirstKFullyLoad3G(int) = 0; virtual void SetLazyImageFirstKFullyLoad4G(int) = 0; virtual void SetForceDarkModeEnabled(bool) = 0; + virtual void SetPreferredColorScheme(PreferredColorScheme) = 0; virtual void SetNavigationControls(NavigationControls) = 0; protected:
diff --git a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h index 0731143..9f2cb82c 100644 --- a/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h +++ b/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
@@ -213,7 +213,7 @@ V8StringResource<mode> string(value); if (!string.Prepare(isolate, exception_state)) return String(); - return GetStringFromTrustedHTML(string, execution_context, + return TrustedTypesCheckForHTML(string, execution_context, exception_state); } } @@ -235,7 +235,7 @@ V8StringResource<mode> string(value); if (!string.Prepare(isolate, exception_state)) return String(); - return GetStringFromTrustedScript(string, execution_context, + return TrustedTypesCheckForScript(string, execution_context, exception_state); } } @@ -257,7 +257,7 @@ V8StringResource<mode> string(value); if (!string.Prepare(isolate, exception_state)) return String(); - return GetStringFromTrustedScriptURL(string, execution_context, + return TrustedTypesCheckForScriptURL(string, execution_context, exception_state); } }
diff --git a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc index 075b2083..769795b 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
@@ -219,15 +219,13 @@ if (try_catch.HasCaught()) return false; - // To report InvalidStateError Exception, when the constructor returns some - // different object + // Report a TypeError Exception if the constructor returns a different object. if (result != &element) { const String& message = "custom element constructors must call super() first and must " "not return a different object"; - v8::Local<v8::Value> exception = V8ThrowDOMException::CreateOrEmpty( - script_state_->GetIsolate(), DOMExceptionCode::kInvalidStateError, - message); + v8::Local<v8::Value> exception = + V8ThrowException::CreateTypeError(script_state_->GetIsolate(), message); if (!exception.IsEmpty()) V8ScriptRunner::ReportException(isolate, exception); return false;
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc b/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc index 04fd5ae..3fca5b2 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc
@@ -128,8 +128,7 @@ // During upgrade an element has invoked the same constructor // before calling 'super' and that invocation has poached the // element. - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "this instance is already constructed"); + exception_state.ThrowTypeError("This instance is already constructed"); return; } }
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index 8cb1276..696a6170 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -413,7 +413,7 @@ return {false, v8::MaybeLocal<v8::String>()}; } - String stringified_source = GetStringFromTrustedScript( + String stringified_source = TrustedTypesCheckForScript( string_or_trusted_script, ToExecutionContext(context), exception_state); if (exception_state.HadException()) { exception_state.ClearException();
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index b603f6f0..8759ba0 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -11,6 +11,7 @@ "+base/memory/scoped_policy.h", "+base/memory/scoped_refptr.h", "+base/metrics/field_trial_params.h", + "+base/numerics/ranges.h", "+base/strings/stringprintf.h", "+base/synchronization/waitable_event.h", "+base/task/sequence_manager/task_time_observer.h",
diff --git a/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc b/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc index 405e1b1..d8073d5 100644 --- a/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc +++ b/third_party/blink/renderer/core/accessibility/apply_dark_mode_test.cc
@@ -65,9 +65,8 @@ ScopedCSSColorSchemeForTest css_feature_scope(true); ScopedMetaColorSchemeForTest meta_feature_scope(true); GetDocument().GetSettings()->SetForceDarkModeEnabled(true); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); GetDocument().head()->SetInnerHTMLFromString(R"HTML( <meta name="color-scheme" content="dark"> )HTML");
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 678a929e..9453376 100644 --- a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc +++ b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
@@ -26,6 +26,7 @@ const InvalidationLists& invalidation_lists, ContainerNode& node) { DCHECK(node.InActiveDocument()); + DCHECK(!node.GetDocument().InStyleRecalc()); bool requires_descendant_invalidation = false; if (node.GetStyleChangeType() < kSubtreeStyleChange) {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser.cc b/third_party/blink/renderer/core/css/parser/css_parser.cc index 925df43..4cf1abc 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser.cc
@@ -259,14 +259,6 @@ if (!StyleColor::IsSystemColor(id)) return false; - if (!RuntimeEnabledFeatures::LinkSystemColorsEnabled() && - (id == CSSValueID::kLinktext || id == CSSValueID::kVisitedtext)) { - return false; - } else if (!RuntimeEnabledFeatures::NewSystemColorsEnabled() && - (id == CSSValueID::kActivetext || id == CSSValueID::kField || - id == CSSValueID::kFieldtext)) { - return false; - } color = LayoutTheme::GetTheme().SystemColor(id, color_scheme); return true; }
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc index 0d766a9..c2034ea 100644 --- a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc +++ b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
@@ -928,15 +928,6 @@ if (!isValueAllowedInMode(id, context.Mode())) return nullptr; CSSIdentifierValue* color = ConsumeIdent(range); - if (!RuntimeEnabledFeatures::LinkSystemColorsEnabled() && - (color->GetValueID() == CSSValueID::kLinktext || - color->GetValueID() == CSSValueID::kVisitedtext)) { - return nullptr; - } else if (!RuntimeEnabledFeatures::NewSystemColorsEnabled() && - (id == CSSValueID::kActivetext || id == CSSValueID::kField || - id == CSSValueID::kFieldtext)) { - return nullptr; - } return color; } RGBA32 color = Color::kTransparent;
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc index 1a0ac3c..ed90e6fd 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -490,6 +490,7 @@ return cssvalue::CSSUnsetValue::Create(); } + resolver.shorthand_cache_.value = &value; resolver.shorthand_cache_.parsed_properties = std::move(parsed_properties); }
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index 6bc6616..fd300fb 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -104,11 +104,10 @@ viewport_resolver_ = MakeGarbageCollected<ViewportStyleResolver>(document); if (IsMaster()) global_rule_set_ = MakeGarbageCollected<CSSGlobalRuleSet>(); - if (Platform::Current() && Platform::Current()->ThemeEngine()) { - preferred_color_scheme_ = - Platform::Current()->ThemeEngine()->PreferredColorScheme(); + if (auto* settings = GetDocument().GetSettings()) + preferred_color_scheme_ = settings->GetPreferredColorScheme(); + if (Platform::Current() && Platform::Current()->ThemeEngine()) forced_colors_ = Platform::Current()->ThemeEngine()->GetForcedColors(); - } } StyleEngine::~StyleEngine() = default; @@ -894,6 +893,26 @@ bool StyleEngine::ShouldSkipInvalidationFor(const Element& element) const { if (!element.InActiveDocument()) return true; + if (GetDocument().InStyleRecalc()) { +#if DCHECK_IS_ON() + // TODO(futhark): The InStyleRecalc() if-guard above should have been a + // DCHECK(!InStyleRecalc()), but there are a couple of cases where we try to + // invalidate style from style recalc: + // + // 1. We may animate the class attribute of an SVG element and change it + // during style recalc when applying the animation effect. + // 2. We may call SetInlineStyle on elements in a UA shadow tree as part of + // style recalc. For instance from HTMLImageFallbackHelper. + // + // If there are more cases, we need to adjust the DCHECKs below, but ideally + // The origin of these invalidations should be fixed. + if (!element.IsSVGElement()) { + DCHECK(element.ContainingShadowRoot()); + DCHECK(element.ContainingShadowRoot()->IsUserAgent()); + } +#endif // DCHECK_IS_ON() + return true; + } if (GetDocument().GetStyleChangeType() == kSubtreeStyleChange) return true; Element* root = GetDocument().documentElement(); @@ -2017,7 +2036,7 @@ forced_colors_ = web_theme_engine->GetForcedColors(); PreferredColorScheme old_preferred_color_scheme = preferred_color_scheme_; - preferred_color_scheme_ = web_theme_engine->PreferredColorScheme(); + preferred_color_scheme_ = settings->GetPreferredColorScheme(); if (const auto* overrides = GetDocument().GetPage()->GetMediaFeatureOverrides()) { MediaQueryExpValue value = overrides->GetOverride("prefers-color-scheme");
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index 3275154..e750feac 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -586,9 +586,9 @@ // scheme is used to opt-out of forced darkening. Member<const CSSValue> meta_color_scheme_; - // The preferred color scheme is set in WebThemeEngine, but may be overridden - // by the ForceDarkMode setting where the preferred_color_scheme_ will be set - // to kNoPreference to avoid dark styling to be applied before auto darkening. + // The preferred color scheme is set in settings, but may be overridden by the + // ForceDarkMode setting where the preferred_color_scheme_ will be set to + // kNoPreference to avoid dark styling to be applied before auto darkening. PreferredColorScheme preferred_color_scheme_ = PreferredColorScheme::kNoPreference;
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 e404e25..637302e 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -1493,9 +1493,8 @@ } TEST_F(StyleEngineTest, MediaQueriesChangeColorScheme) { - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); GetDocument().body()->SetInnerHTMLFromString(R"HTML( <style> @@ -1512,8 +1511,7 @@ GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 128, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( @@ -1522,9 +1520,8 @@ TEST_F(StyleEngineTest, MediaQueriesChangeColorSchemeForcedDarkMode) { GetDocument().GetSettings()->SetForceDarkModeEnabled(true); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); GetDocument().body()->SetInnerHTMLFromString(R"HTML( <style> @@ -1589,7 +1586,7 @@ GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); - ColorSchemeHelper color_scheme_helper; + ColorSchemeHelper color_scheme_helper(GetDocument()); color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 128, 0), @@ -1624,18 +1621,16 @@ )HTML"); // ForcedColors = kNone, PreferredColorScheme = kLight - ColorSchemeHelper color_scheme_helper; + ColorSchemeHelper color_scheme_helper(GetDocument()); color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kNone); - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kLight); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(255, 0, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); // ForcedColors = kNone, PreferredColorScheme = kDark - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 128, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( @@ -1650,15 +1645,14 @@ // ForcedColors = kActive, PreferredColorScheme = kNoPreference color_scheme_helper.SetPreferredColorScheme( - GetDocument(), PreferredColorScheme::kNoPreference); + PreferredColorScheme::kNoPreference); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(255, 255, 0), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( GetCSSPropertyColor())); // ForcedColors = kActive, PreferredColorScheme = kLight - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kLight); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); UpdateAllLifecyclePhases(); EXPECT_EQ(MakeRGB(0, 0, 255), GetDocument().body()->GetComputedStyle()->VisitedDependentColor( @@ -1666,11 +1660,10 @@ } TEST_F(StyleEngineTest, MediaQueriesColorSchemeOverride) { - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); EXPECT_EQ(PreferredColorScheme::kLight, - Platform::Current()->ThemeEngine()->PreferredColorScheme()); + GetDocument().GetSettings()->GetPreferredColorScheme()); GetDocument().body()->SetInnerHTMLFromString(R"HTML( <style> @@ -2130,9 +2123,8 @@ TEST_F(StyleEngineTest, ColorSchemeBaseBackgroundChange) { ScopedCSSColorSchemeForTest enable_color_scheme(true); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(Color::kWhite, GetDocument().View()->BaseBackgroundColor()); @@ -2148,9 +2140,8 @@ ScopedCSSColorSchemeForTest enable_color_scheme(true); ScopedCSSColorSchemeUARenderingForTest enable_color_scheme_ua(true); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); GetDocument().documentElement()->SetInlineStyleProperty( CSSPropertyID::kColorScheme, "light dark"); @@ -2524,9 +2515,8 @@ TEST_F(StyleEngineTest, InitialColorChange) { // Set color scheme to light. - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); GetDocument().body()->SetInnerHTMLFromString(R"HTML( <style> @@ -2552,8 +2542,7 @@ initial_style->VisitedDependentColor(GetCSSPropertyColor())); // Change color scheme to dark. - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); document_element_style = GetDocument().documentElement()->GetComputedStyle();
diff --git a/third_party/blink/renderer/core/css/svg.css b/third_party/blink/renderer/core/css/svg.css index 6337533..15438d9 100644 --- a/third_party/blink/renderer/core/css/svg.css +++ b/third_party/blink/renderer/core/css/svg.css
@@ -95,10 +95,6 @@ https://drafts.csswg.org/css-color-adjust-1/#forced-colors-properties */ @media forced-colors { - svg:root { - color: CanvasText; - } - svg { forced-color-adjust: none; }
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 81494da..822aa14e 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -4353,7 +4353,7 @@ for (const String& string : text) builder.Append(string); String string = - GetStringFromTrustedHTML(builder.ToString(), this, exception_state); + TrustedTypesCheckForHTML(builder.ToString(), this, exception_state); if (exception_state.HadException()) return; @@ -4370,7 +4370,7 @@ for (const String& string : text) builder.Append(string); String string = - GetStringFromTrustedHTML(builder.ToString(), this, exception_state); + TrustedTypesCheckForHTML(builder.ToString(), this, exception_state); if (exception_state.HadException()) return;
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc index 01fd1e0..981a673 100644 --- a/third_party/blink/renderer/core/dom/document_test.cc +++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -1145,9 +1145,8 @@ } TEST_F(DocumentTest, PrefersColorSchemeChanged) { - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); UpdateAllLifecyclePhasesForTest(); auto* list = GetDocument().GetMediaQueryMatcher().MatchMedia( @@ -1157,8 +1156,7 @@ EXPECT_FALSE(listener->IsNotified()); - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhasesForTest(); GetDocument().ServiceScriptedAnimations(base::TimeTicks());
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index b83762c..907aed66 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2247,9 +2247,9 @@ QualifiedName q_name = QualifiedName::Null(); std::tie(index, q_name) = LookupAttributeQNameInternal(local_name); - String trusted_value = GetStringFromSpecificTrustedType( - value, ExpectedTrustedTypeForAttribute(q_name), - GetDocument().ToExecutionContext(), exception_state); + String trusted_value = + TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(q_name), value, + GetDocument().ToExecutionContext(), exception_state); if (exception_state.HadException()) return; @@ -2280,9 +2280,9 @@ ? GetElementData()->Attributes().FindIndex(name) : kNotFound; - String trusted_value = GetStringFromSpecificTrustedType( - value, ExpectedTrustedTypeForAttribute(name), - GetDocument().ToExecutionContext(), exception_state); + String trusted_value = + TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(name), value, + GetDocument().ToExecutionContext(), exception_state); if (exception_state.HadException()) return; @@ -2300,7 +2300,8 @@ void Element::setAttribute( const AtomicString& local_name, - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& string_or_TT, + const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& + string_or_trusted, ExceptionState& exception_state) { if (!Document::IsValidName(local_name)) { exception_state.ThrowDOMException( @@ -2313,8 +2314,8 @@ wtf_size_t index; QualifiedName q_name = QualifiedName::Null(); std::tie(index, q_name) = LookupAttributeQNameInternal(local_name); - String value = GetStringFromSpecificTrustedType( - string_or_TT, ExpectedTrustedTypeForAttribute(q_name), + String value = TrustedTypesCheckFor( + ExpectedTrustedTypeForAttribute(q_name), string_or_trusted, GetDocument().ToExecutionContext(), exception_state); if (exception_state.HadException()) return; @@ -2350,7 +2351,7 @@ // starting with "on", including e.g. "one". We use this pattern elsewhere // (e.g. in IsEventHandlerAttribute) but it's not ideal. Consider using // the event attribute of the resulting AttributeTriggers. - return SpecificTrustedType::kTrustedScript; + return SpecificTrustedType::kScript; } return SpecificTrustedType::kNone; @@ -2360,7 +2361,7 @@ const StringOrTrustedHTML& stringOrHTML, ExceptionState& exception_state) { String valueString = - GetStringFromTrustedHTML(stringOrHTML, &GetDocument(), exception_state); + TrustedTypesCheckForHTML(stringOrHTML, &GetDocument(), exception_state); if (!exception_state.HadException()) { setAttribute(name, AtomicString(valueString)); } @@ -2369,7 +2370,7 @@ void Element::setAttribute(const QualifiedName& name, const StringOrTrustedScript& stringOrScript, ExceptionState& exception_state) { - String valueString = GetStringFromTrustedScript( + String valueString = TrustedTypesCheckForScript( stringOrScript, GetDocument().ToExecutionContext(), exception_state); if (!exception_state.HadException()) { setAttribute(name, AtomicString(valueString)); @@ -2379,7 +2380,7 @@ void Element::setAttribute(const QualifiedName& name, const StringOrTrustedScriptURL& stringOrURL, ExceptionState& exception_state) { - String valueString = GetStringFromTrustedScriptURL( + String valueString = TrustedTypesCheckForScriptURL( stringOrURL, GetDocument().ToExecutionContext(), exception_state); if (!exception_state.HadException()) { setAttribute(name, AtomicString(valueString)); @@ -3919,10 +3920,9 @@ SynchronizeAllAttributes(); const UniqueElementData& element_data = EnsureUniqueElementData(); - String value = GetStringFromSpecificTrustedType( - attr_node->value(), + String value = TrustedTypesCheckFor( ExpectedTrustedTypeForAttribute(attr_node->GetQualifiedName()), - GetDocument().ToExecutionContext(), exception_state); + attr_node->value(), GetDocument().ToExecutionContext(), exception_state); if (exception_state.HadException()) return nullptr; @@ -4033,15 +4033,16 @@ void Element::setAttributeNS( const AtomicString& namespace_uri, const AtomicString& qualified_name, - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& string_or_TT, + const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& + string_or_trusted, ExceptionState& exception_state) { QualifiedName parsed_name = g_any_name; if (!ParseAttributeName(parsed_name, namespace_uri, qualified_name, exception_state)) return; - String value = GetStringFromSpecificTrustedType( - string_or_TT, ExpectedTrustedTypeForAttribute(parsed_name), + String value = TrustedTypesCheckFor( + ExpectedTrustedTypeForAttribute(parsed_name), string_or_trusted, GetDocument().ToExecutionContext(), exception_state); if (exception_state.HadException()) return; @@ -4693,7 +4694,7 @@ void Element::setInnerHTML(const StringOrTrustedHTML& string_or_html, ExceptionState& exception_state) { String html = - GetStringFromTrustedHTML(string_or_html, &GetDocument(), exception_state); + TrustedTypesCheckForHTML(string_or_html, &GetDocument(), exception_state); if (!exception_state.HadException()) { SetInnerHTMLFromString(html, exception_state); } @@ -4758,7 +4759,7 @@ void Element::setOuterHTML(const StringOrTrustedHTML& string_or_html, ExceptionState& exception_state) { String html = - GetStringFromTrustedHTML(string_or_html, &GetDocument(), exception_state); + TrustedTypesCheckForHTML(string_or_html, &GetDocument(), exception_state); if (!exception_state.HadException()) { SetOuterHTMLFromString(html, exception_state); } @@ -4908,7 +4909,7 @@ const StringOrTrustedHTML& string_or_html, ExceptionState& exception_state) { String markup = - GetStringFromTrustedHTML(string_or_html, &GetDocument(), exception_state); + TrustedTypesCheckForHTML(string_or_html, &GetDocument(), exception_state); if (!exception_state.HadException()) { insertAdjacentHTML(where, markup, exception_state); }
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index 7a197a00..a5b34d8 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -826,7 +826,7 @@ ? node_or_string.GetAsString() : node_or_string.GetAsNode()->textContent(); - string_value = GetStringFromTrustedScript( + string_value = TrustedTypesCheckForScript( string_value, document.ToExecutionContext(), exception_state); if (exception_state.HadException()) return nullptr;
diff --git a/third_party/blink/renderer/core/dom/range.cc b/third_party/blink/renderer/core/dom/range.cc index 8aa5076..ce2ec76 100644 --- a/third_party/blink/renderer/core/dom/range.cc +++ b/third_party/blink/renderer/core/dom/range.cc
@@ -973,7 +973,7 @@ Document& document = start_.Container().GetDocument(); String markup = - GetStringFromTrustedHTML(string_or_html, &document, exception_state); + TrustedTypesCheckForHTML(string_or_html, &document, exception_state); if (!exception_state.HadException()) { return createContextualFragmentFromString(markup, exception_state); }
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc index aaa3849..afd186608 100644 --- a/third_party/blink/renderer/core/dom/shadow_root.cc +++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -132,7 +132,7 @@ void ShadowRoot::setInnerHTML(const StringOrTrustedHTML& stringOrHtml, ExceptionState& exception_state) { String html = - GetStringFromTrustedHTML(stringOrHtml, &GetDocument(), exception_state); + TrustedTypesCheckForHTML(stringOrHtml, &GetDocument(), exception_state); if (!exception_state.HadException()) { SetInnerHTMLFromString(html, exception_state); }
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.cc b/third_party/blink/renderer/core/exported/web_settings_impl.cc index ce3bb3a..075b02a 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.cc +++ b/third_party/blink/renderer/core/exported/web_settings_impl.cc
@@ -770,6 +770,11 @@ settings_->SetForceDarkModeEnabled(enabled); } +void WebSettingsImpl::SetPreferredColorScheme( + PreferredColorScheme color_scheme) { + settings_->SetPreferredColorScheme(color_scheme); +} + void WebSettingsImpl::SetNavigationControls( NavigationControls navigation_controls) { settings_->SetNavigationControls(navigation_controls);
diff --git a/third_party/blink/renderer/core/exported/web_settings_impl.h b/third_party/blink/renderer/core/exported/web_settings_impl.h index 9720f98..deb6bb3 100644 --- a/third_party/blink/renderer/core/exported/web_settings_impl.h +++ b/third_party/blink/renderer/core/exported/web_settings_impl.h
@@ -220,6 +220,7 @@ void SetLazyImageFirstKFullyLoad4G(int) override; void SetForceDarkModeEnabled(bool) override; + void SetPreferredColorScheme(PreferredColorScheme) override; void SetNavigationControls(NavigationControls) override; bool RenderVSyncNotificationEnabled() const {
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 8f101d341..33fc2074 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -581,9 +581,8 @@ ScopedCSSColorSchemeForTest enable_color_scheme(true); WebViewImpl* web_view = web_view_helper_.Initialize(); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(*(web_view->GetPage()), - PreferredColorScheme::kLight); + ColorSchemeHelper color_scheme_helper(*(web_view->GetPage())); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); web_view->SetBaseBackgroundColor(SK_ColorBLUE); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); @@ -595,8 +594,7 @@ LocalFrameView* frame_view = web_view->MainFrameImpl()->GetFrame()->View(); EXPECT_EQ(Color(0, 0, 255), frame_view->BaseBackgroundColor()); - color_scheme_helper.SetPreferredColorScheme(*(web_view->GetPage()), - PreferredColorScheme::kDark); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhases(); EXPECT_EQ(Color::kBlack, frame_view->BaseBackgroundColor()); @@ -606,8 +604,7 @@ web_view->SetBaseBackgroundColor(SK_ColorBLUE); EXPECT_EQ(Color::kBlack, frame_view->BaseBackgroundColor()); - color_scheme_helper.SetPreferredColorScheme(*(web_view->GetPage()), - PreferredColorScheme::kLight); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight); UpdateAllLifecyclePhases(); EXPECT_EQ(Color(0, 0, 255), frame_view->BaseBackgroundColor()); }
diff --git a/third_party/blink/renderer/core/frame/settings.h b/third_party/blink/renderer/core/frame/settings.h index 1793196..eeb0560 100644 --- a/third_party/blink/renderer/core/frame/settings.h +++ b/third_party/blink/renderer/core/frame/settings.h
@@ -32,6 +32,7 @@ #include "base/macros.h" #include "third_party/blink/public/common/css/navigation_controls.h" +#include "third_party/blink/public/common/css/preferred_color_scheme.h" #include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" #include "third_party/blink/public/platform/pointer_properties.h" #include "third_party/blink/public/platform/web_effective_connection_type.h"
diff --git a/third_party/blink/renderer/core/frame/settings.json5 b/third_party/blink/renderer/core/frame/settings.json5 index 6f330231..f93688ff 100644 --- a/third_party/blink/renderer/core/frame/settings.json5 +++ b/third_party/blink/renderer/core/frame/settings.json5
@@ -1048,6 +1048,15 @@ type: "int", }, + // Preferred color scheme from the OS/application passed to the renderer for + // evaluating the prefers-color-scheme media query. + { + name: "preferredColorScheme", + initial: "PreferredColorScheme::kNoPreference", + invalidate: "ColorScheme", + type: "PreferredColorScheme", + }, + // Preferred motion-reduction setting from the OS/application passed to the // renderer for evaluating the prefers-reduced-motion media query. {
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc index 3db933d..c4a2319 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -2747,9 +2747,8 @@ ScopedCSSColorSchemeForTest color_scheme_enabled(true); ScopedCSSColorSchemeUARenderingForTest color_scheme_ua_enabled(true); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(*(WebView().GetPage()), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(*(WebView().GetPage())); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); WebView().MainFrameWidget()->Resize(WebSize(400, 600)); const VisualViewport& visual_viewport =
diff --git a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc index 01db5a95..dcb8551 100644 --- a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc +++ b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
@@ -156,7 +156,7 @@ const HeapVector<ScriptValue>& arguments, ExceptionState& exception_state) { ExecutionContext* execution_context = event_target.GetExecutionContext(); - String handler = GetStringFromTrustedScript( + String handler = TrustedTypesCheckForScript( string_or_trusted_script, execution_context, exception_state); if (exception_state.HadException()) return 0; @@ -211,7 +211,7 @@ const HeapVector<ScriptValue>& arguments, ExceptionState& exception_state) { ExecutionContext* execution_context = event_target.GetExecutionContext(); - String handler = GetStringFromTrustedScript( + String handler = TrustedTypesCheckForScript( string_or_trusted_script, execution_context, exception_state); if (exception_state.HadException()) return 0;
diff --git a/third_party/blink/renderer/core/html/html_embed_element.cc b/third_party/blink/renderer/core/html/html_embed_element.cc index f27a829..0b78fee 100644 --- a/third_party/blink/renderer/core/html/html_embed_element.cc +++ b/third_party/blink/renderer/core/html/html_embed_element.cc
@@ -52,7 +52,7 @@ const AttrNameToTrustedType& HTMLEmbedElement::GetCheckedAttributeTypes() const { DEFINE_STATIC_LOCAL(AttrNameToTrustedType, attribute_map, - ({{"src", SpecificTrustedType::kTrustedScriptURL}})); + ({{"src", SpecificTrustedType::kScriptURL}})); return attribute_map; }
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 657c7d3..5b06845 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -64,7 +64,7 @@ const AttrNameToTrustedType& HTMLIFrameElement::GetCheckedAttributeTypes() const { DEFINE_STATIC_LOCAL(AttrNameToTrustedType, attribute_map, - ({{"srcdoc", SpecificTrustedType::kTrustedHTML}})); + ({{"srcdoc", SpecificTrustedType::kHTML}})); return attribute_map; }
diff --git a/third_party/blink/renderer/core/html/html_meta_element_test.cc b/third_party/blink/renderer/core/html/html_meta_element_test.cc index 39e8faf..3b7298f 100644 --- a/third_party/blink/renderer/core/html/html_meta_element_test.cc +++ b/third_party/blink/renderer/core/html/html_meta_element_test.cc
@@ -225,9 +225,8 @@ } TEST_F(HTMLMetaElementTest, ColorSchemeForcedDarkeningAndMQ) { - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); auto* media_query = GetDocument().GetMediaQueryMatcher().MatchMedia( "(prefers-color-scheme: dark)");
diff --git a/third_party/blink/renderer/core/html/html_object_element.cc b/third_party/blink/renderer/core/html/html_object_element.cc index fe93dcdb..8ff7344 100644 --- a/third_party/blink/renderer/core/html/html_object_element.cc +++ b/third_party/blink/renderer/core/html/html_object_element.cc
@@ -66,8 +66,8 @@ const AttrNameToTrustedType& HTMLObjectElement::GetCheckedAttributeTypes() const { DEFINE_STATIC_LOCAL(AttrNameToTrustedType, attribute_map, - ({{"data", SpecificTrustedType::kTrustedScriptURL}, - {"codebase", SpecificTrustedType::kTrustedScriptURL}})); + ({{"data", SpecificTrustedType::kScriptURL}, + {"codebase", SpecificTrustedType::kScriptURL}})); return attribute_map; }
diff --git a/third_party/blink/renderer/core/html/html_script_element.cc b/third_party/blink/renderer/core/html/html_script_element.cc index e539c8f..cdf74725 100644 --- a/third_party/blink/renderer/core/html/html_script_element.cc +++ b/third_party/blink/renderer/core/html/html_script_element.cc
@@ -53,7 +53,7 @@ const AttrNameToTrustedType& HTMLScriptElement::GetCheckedAttributeTypes() const { DEFINE_STATIC_LOCAL(AttrNameToTrustedType, attribute_map, - ({{"src", SpecificTrustedType::kTrustedScriptURL}})); + ({{"src", SpecificTrustedType::kScriptURL}})); return attribute_map; } @@ -136,7 +136,7 @@ void HTMLScriptElement::setInnerText( const StringOrTrustedScript& string_or_trusted_script, ExceptionState& exception_state) { - String value = GetStringFromTrustedScript(string_or_trusted_script, + String value = TrustedTypesCheckForScript(string_or_trusted_script, GetDocument().ToExecutionContext(), exception_state); if (!exception_state.HadException()) { @@ -151,7 +151,7 @@ void HTMLScriptElement::setTextContent( const StringOrTrustedScript& string_or_trusted_script, ExceptionState& exception_state) { - String value = GetStringFromTrustedScript(string_or_trusted_script, + String value = TrustedTypesCheckForScript(string_or_trusted_script, GetDocument().ToExecutionContext(), exception_state); if (!exception_state.HadException()) {
diff --git a/third_party/blink/renderer/core/html/resources/forced_colors.css b/third_party/blink/renderer/core/html/resources/forced_colors.css index c35e7e7..8f71b5c5 100644 --- a/third_party/blink/renderer/core/html/resources/forced_colors.css +++ b/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -11,7 +11,6 @@ @media forced-colors { body { background-color: Canvas; - color: CanvasText; fill: currentColor; }
diff --git a/third_party/blink/renderer/core/layout/layout_theme_test.cc b/third_party/blink/renderer/core/layout/layout_theme_test.cc index 4e57faa..f4c315b 100644 --- a/third_party/blink/renderer/core/layout/layout_theme_test.cc +++ b/third_party/blink/renderer/core/layout/layout_theme_test.cc
@@ -104,9 +104,8 @@ style->VisitedDependentColor(GetCSSPropertyColor())); // Change color scheme to dark. - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); UpdateAllLifecyclePhasesForTest(); style = dark_element->GetComputedStyle();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc index f0f7d81..f770adf6 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -30,7 +30,7 @@ } scoped_refptr<const NGLayoutResult> NGFieldsetLayoutAlgorithm::Layout() { - // TODO(almaher): Handle fragmentation for fieldset children. + // TODO(almaher): Finish fragmentation for legends. // Layout of a fieldset container consists of two parts: Create a child // fragment for the rendered legend (if any), and create a child fragment for @@ -65,8 +65,30 @@ container_builder_.SetIsInitialColumnBalancingPass(); } + scoped_refptr<const NGBlockBreakToken> content_break_token; + bool has_seen_all_children = false; + if (const auto* token = BreakToken()) { + const auto child_tokens = token->ChildBreakTokens(); + if (wtf_size_t break_token_count = child_tokens.size()) { + scoped_refptr<const NGBlockBreakToken> child_token = + To<NGBlockBreakToken>(child_tokens[0]); + if (child_token) { + DCHECK(!child_token->InputNode().IsRenderedLegend()); + content_break_token = child_token; + } + // There shouldn't be any additional break tokens. + DCHECK_EQ(child_tokens.size(), 1u); + } + + if (token->HasSeenAllChildren()) { + has_seen_all_children = true; + container_builder_.SetHasSeenAllChildren(); + } + } + // TODO(vmpstr): Skip child (including legend) layout for fieldset elements. - if (NGBlockNode legend = Node().GetRenderedLegend()) { + NGBlockNode legend = Node().GetRenderedLegend(); + if (!content_break_token && legend && !has_seen_all_children) { // Lay out the legend. While the fieldset container normally ignores its // padding, the legend is laid out within what would have been the content // box had the fieldset been a regular block with no weirdness. @@ -111,42 +133,54 @@ } container_builder_.AddChild(physical_fragment, legend_offset); + DCHECK(!physical_fragment.BreakToken()); } NGBoxStrut borders_with_legend = borders; borders_with_legend.block_start = block_start_padding_edge; + LogicalSize adjusted_padding_box_size = + ShrinkAvailableSize(border_box_size, borders_with_legend); + if (IsResumingLayout(BreakToken())) + borders_with_legend.block_start = LayoutUnit(); LayoutUnit intrinsic_block_size = borders_with_legend.BlockSum(); // Proceed with normal fieldset children (excluding the rendered legend). They // all live inside an anonymous child box of the fieldset container. - if (auto fieldset_content = Node().GetFieldsetContent()) { - LogicalSize adjusted_padding_box_size = - ShrinkAvailableSize(border_box_size, borders_with_legend); - auto child_space = - CreateConstraintSpaceForFieldsetContent(adjusted_padding_box_size); - auto result = fieldset_content.Layout(child_space, BreakToken()); + auto fieldset_content = Node().GetFieldsetContent(); + if (fieldset_content && (content_break_token || !has_seen_all_children)) { + auto child_space = CreateConstraintSpaceForFieldsetContent( + fieldset_content, adjusted_padding_box_size, + borders_with_legend.block_start); + auto result = + fieldset_content.Layout(child_space, content_break_token.get()); // TODO(layout-dev): Handle abortions caused by block fragmentation. DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess); - const auto& physical_fragment = result->PhysicalFragment(); - container_builder_.AddChild(physical_fragment, - borders_with_legend.StartOffset()); + container_builder_.AddResult(*result, borders_with_legend.StartOffset()); + const auto& physical_fragment = result->PhysicalFragment(); intrinsic_block_size += NGFragment(writing_mode, physical_fragment).BlockSize(); - } else { + container_builder_.SetHasSeenAllChildren(); + } + if (!fieldset_content) { // There was no anonymous child to provide the padding, so we have to add it // ourselves. + container_builder_.SetHasSeenAllChildren(); intrinsic_block_size += padding.BlockSum(); } intrinsic_block_size = ClampIntrinsicBlockSize( ConstraintSpace(), Node(), adjusted_border_padding, intrinsic_block_size); + LayoutUnit consumed_block_size = + BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit(); + // Recompute the block-axis size now that we know our content size. - border_box_size.block_size = ComputeBlockSizeForFragment( - ConstraintSpace(), Style(), border_padding_, intrinsic_block_size); + border_box_size.block_size = + ComputeBlockSizeForFragment(ConstraintSpace(), Style(), border_padding_, + intrinsic_block_size + consumed_block_size); // The above computation utility knows nothing about fieldset weirdness. The // legend may eat from the available content box block size. Make room for @@ -161,9 +195,6 @@ std::max(border_box_size.block_size, minimum_border_box_block_size); } - LayoutUnit consumed_block_size = - BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit(); - // TODO(almaher): end border and padding may overflow the parent // fragmentainer, and we should avoid that. LayoutUnit block_size = border_box_size.block_size - consumed_block_size; @@ -239,7 +270,9 @@ const NGConstraintSpace NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForFieldsetContent( - LogicalSize padding_box_size) { + NGBlockNode fieldset_content, + LogicalSize padding_box_size, + LayoutUnit block_offset) { NGConstraintSpaceBuilder builder(ConstraintSpace(), ConstraintSpace().GetWritingMode(), /* is_new_fc */ true); @@ -247,6 +280,12 @@ builder.SetPercentageResolutionSize( ConstraintSpace().PercentageResolutionSize()); builder.SetIsFixedBlockSize(padding_box_size.block_size != kIndefiniteSize); + + if (ConstraintSpace().HasBlockFragmentation()) { + SetupFragmentation(ConstraintSpace(), fieldset_content, block_offset, + &builder, /* is_new_fc */ true); + builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal()); + } return builder.ToConstraintSpace(); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h index 35b6ada..b3f8f0e1 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
@@ -32,7 +32,9 @@ NGBlockNode legend, LogicalSize available_size); const NGConstraintSpace CreateConstraintSpaceForFieldsetContent( - LogicalSize padding_box_size); + NGBlockNode fieldset_content, + LogicalSize padding_box_size, + LayoutUnit block_offset); const NGBoxStrut border_padding_; };
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc index 44355539..4979bb575 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
@@ -574,5 +574,131 @@ ASSERT_FALSE(fragment->BreakToken()); } +// Tests that a fieldset with auto height will fragment when its content reaches +// the fragmentation line. +TEST_F(NGFieldsetLayoutAlgorithmTest, FieldsetContentFragmentationAutoHeight) { + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <style> + #fieldset { + border:3px solid; margin:0; padding:10px; width: 150px; + } + #child { + margin:0; width: 50px; height: 500px; + } + </style> + <fieldset id="fieldset"> + <div id="child"></child> + </fieldset> + )HTML"); + + LayoutUnit kFragmentainerSpaceAvailable(200); + + NGBlockNode node(ToLayoutBox(GetLayoutObjectByElementId("fieldset"))); + NGConstraintSpace space = ConstructBlockLayoutTestConstraintSpace( + WritingMode::kHorizontalTb, TextDirection::kLtr, + LogicalSize(LayoutUnit(1000), kIndefiniteSize), false, + node.CreatesNewFormattingContext(), kFragmentainerSpaceAvailable); + + scoped_refptr<const NGPhysicalBoxFragment> fragment = + NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm(node, space); + ASSERT_FALSE(fragment->BreakToken()->IsFinished()); + + String dump = DumpFragmentTree(fragment.get()); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:176x200 + offset:3,3 size:170x197 + offset:10,10 size:50x187 +)DUMP"; + EXPECT_EQ(expectation, dump); + + fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm( + node, space, fragment->BreakToken()); + ASSERT_FALSE(fragment->BreakToken()->IsFinished()); + + dump = DumpFragmentTree(fragment.get()); + expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:176x200 + offset:3,0 size:170x200 + offset:10,0 size:50x200 +)DUMP"; + EXPECT_EQ(expectation, dump); + + fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm( + node, space, fragment->BreakToken()); + ASSERT_FALSE(fragment->BreakToken()); + + dump = DumpFragmentTree(fragment.get()); + expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:176x126 + offset:3,0 size:170x123 + offset:10,0 size:50x113 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +// Tests that a fieldset with a set height will fragment when its content +// reaches the fragmentation line. +TEST_F(NGFieldsetLayoutAlgorithmTest, FieldsetContentFragmentation) { + SetBodyInnerHTML(R"HTML( + <!DOCTYPE html> + <style> + #fieldset { + border:3px solid; margin:0; padding:10px; width: 150px; height: 100px; + } + #child { + margin:0; width: 50px; height: 500px; + } + </style> + <fieldset id="fieldset"> + <div id="child"></child> + </fieldset> + )HTML"); + + LayoutUnit kFragmentainerSpaceAvailable(200); + + NGBlockNode node(ToLayoutBox(GetLayoutObjectByElementId("fieldset"))); + NGConstraintSpace space = ConstructBlockLayoutTestConstraintSpace( + WritingMode::kHorizontalTb, TextDirection::kLtr, + LogicalSize(LayoutUnit(1000), kIndefiniteSize), false, + node.CreatesNewFormattingContext(), kFragmentainerSpaceAvailable); + + scoped_refptr<const NGPhysicalBoxFragment> fragment = + NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm(node, space); + ASSERT_FALSE(fragment->BreakToken()->IsFinished()); + + String dump = DumpFragmentTree(fragment.get()); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:176x126 + offset:3,3 size:170x120 + offset:10,10 size:50x187 +)DUMP"; + EXPECT_EQ(expectation, dump); + + fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm( + node, space, fragment->BreakToken()); + ASSERT_FALSE(fragment->BreakToken()->IsFinished()); + + dump = DumpFragmentTree(fragment.get()); + expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:176x0 + offset:3,0 size:170x0 + offset:10,0 size:50x200 +)DUMP"; + EXPECT_EQ(expectation, dump); + + fragment = NGBaseLayoutAlgorithmTest::RunFieldsetLayoutAlgorithm( + node, space, fragment->BreakToken()); + ASSERT_FALSE(fragment->BreakToken()); + + dump = DumpFragmentTree(fragment.get()); + expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:176x0 + offset:3,0 size:170x0 + offset:10,0 size:50x113 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + } // anonymous namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc index d46860e..7562c57 100644 --- a/third_party/blink/renderer/core/layout/scrollbars_test.cc +++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -75,19 +75,8 @@ return painted_color_scheme_[part]; } - blink::PreferredColorScheme PreferredColorScheme() const override { - return preferred_color_scheme_; - } - - void SetPreferredColorScheme( - const blink::PreferredColorScheme preferred_color_scheme) override { - preferred_color_scheme_ = preferred_color_scheme; - } - private: std::array<WebColorScheme, kPartProgressBar + 1> painted_color_scheme_; - blink::PreferredColorScheme preferred_color_scheme_ = - blink::PreferredColorScheme::kNoPreference; }; constexpr int StubWebThemeEngine::kMinimumHorizontalLength; @@ -2832,9 +2821,8 @@ </div> )HTML"); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); Compositor().BeginFrame();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc index 20a540c..da375b6 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
@@ -84,7 +84,7 @@ void LayoutSVGContainer::AddChild(LayoutObject* child, LayoutObject* before_child) { LayoutSVGModelObject::AddChild(child, before_child); - SVGResourcesCache::ClientWasAddedToTree(*child, child->StyleRef()); + SVGResourcesCache::ClientWasAddedToTree(*child); bool should_isolate_descendants = (child->IsBlendingAllowed() && child->StyleRef().HasBlendMode()) ||
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc index 78e884af..09e1acd 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
@@ -145,7 +145,7 @@ void LayoutSVGInline::AddChild(LayoutObject* child, LayoutObject* before_child) { LayoutInline::AddChild(child, before_child); - SVGResourcesCache::ClientWasAddedToTree(*child, child->StyleRef()); + SVGResourcesCache::ClientWasAddedToTree(*child); if (LayoutSVGText* text_layout_object = LayoutSVGText::LocateLayoutSVGTextAncestor(this))
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc index a39d5b6..eeaf8f2 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -336,7 +336,7 @@ void LayoutSVGRoot::AddChild(LayoutObject* child, LayoutObject* before_child) { LayoutReplaced::AddChild(child, before_child); - SVGResourcesCache::ClientWasAddedToTree(*child, child->StyleRef()); + SVGResourcesCache::ClientWasAddedToTree(*child); bool should_isolate_descendants = (child->IsBlendingAllowed() && child->StyleRef().HasBlendMode()) || @@ -383,7 +383,7 @@ void LayoutSVGRoot::InsertedIntoTree() { LayoutReplaced::InsertedIntoTree(); - SVGResourcesCache::ClientWasAddedToTree(*this, StyleRef()); + SVGResourcesCache::ClientWasAddedToTree(*this); } void LayoutSVGRoot::WillBeRemovedFromTree() {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc index bbfd3b0..a0539f0 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
@@ -428,7 +428,7 @@ void LayoutSVGText::AddChild(LayoutObject* child, LayoutObject* before_child) { LayoutSVGBlock::AddChild(child, before_child); - SVGResourcesCache::ClientWasAddedToTree(*child, child->StyleRef()); + SVGResourcesCache::ClientWasAddedToTree(*child); SubtreeChildWasAdded(); }
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources_cache.cc b/third_party/blink/renderer/core/layout/svg/svg_resources_cache.cc index 58d59417..98eec5c 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_resources_cache.cc +++ b/third_party/blink/renderer/core/layout/svg/svg_resources_cache.cc
@@ -194,8 +194,7 @@ layout_object, true); } -void SVGResourcesCache::ClientWasAddedToTree(LayoutObject& layout_object, - const ComputedStyle& new_style) { +void SVGResourcesCache::ClientWasAddedToTree(LayoutObject& layout_object) { if (!layout_object.GetNode()) return; LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation( @@ -204,7 +203,8 @@ if (!LayoutObjectCanHaveResources(layout_object)) return; SVGResourcesCache& cache = ResourcesCache(layout_object.GetDocument()); - if (cache.AddResourcesFromLayoutObject(layout_object, new_style)) + if (cache.AddResourcesFromLayoutObject(layout_object, + layout_object.StyleRef())) layout_object.SetNeedsPaintPropertyUpdate(); }
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources_cache.h b/third_party/blink/renderer/core/layout/svg/svg_resources_cache.h index e95be4d..fe545ef7 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_resources_cache.h +++ b/third_party/blink/renderer/core/layout/svg/svg_resources_cache.h
@@ -42,8 +42,7 @@ static SVGResources* CachedResourcesForLayoutObject(const LayoutObject&); // Called from all SVG layoutObjects addChild() methods. - static void ClientWasAddedToTree(LayoutObject&, - const ComputedStyle& new_style); + static void ClientWasAddedToTree(LayoutObject&); // Called from all SVG layoutObjects removeChild() methods. static void ClientWillBeRemovedFromTree(LayoutObject&);
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.cc b/third_party/blink/renderer/core/loader/frame_load_request.cc index f3191fd..b4b1838 100644 --- a/third_party/blink/renderer/core/loader/frame_load_request.cc +++ b/third_party/blink/renderer/core/loader/frame_load_request.cc
@@ -45,7 +45,7 @@ const ResourceRequest& resource_request) : origin_document_(origin_document), should_send_referrer_(kMaybeSendReferrer) { - resource_request_.CopyHeadFrom(&resource_request); + resource_request_.CopyHeadFrom(resource_request); resource_request_.SetHttpBody(resource_request.HttpBody()); resource_request_.SetMode(network::mojom::RequestMode::kNavigate); resource_request_.SetCredentialsMode(
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index abcce7db..4ab46f3 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -1093,8 +1093,9 @@ last_ancestor = current; current->child_needs_compositing_inputs_update_ = true; if (Compositor() && - (current != initial_layer && - current->GetLayoutObject().ShouldApplyStrictContainment())) + (current != initial_layer || + !current->GetLayoutObject().IsStickyPositioned()) && + current->GetLayoutObject().ShouldApplyStrictContainment()) break; }
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index c714e3f..9b48f61 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -27,7 +27,9 @@ #include <memory> #include <utility> +#include "base/metrics/histogram_functions.h" #include "base/numerics/clamped_math.h" +#include "base/numerics/ranges.h" #include "build/build_config.h" #include "cc/input/overscroll_behavior.h" #include "third_party/blink/renderer/core/animation/css/css_animation_data.h" @@ -1337,6 +1339,23 @@ SetColorInternal(v); } +bool ComputedStyle::SetEffectiveZoom(float f) { + // Clamp the effective zoom value to a smaller (but hopeful still large + // enough) range, to avoid overflow in derived computations. + float clamped_effective_zoom = clampTo<float>(f, 1e-6, 1e6); + if (EffectiveZoom() == clamped_effective_zoom) + return false; + SetInternalEffectiveZoom(clamped_effective_zoom); + // Record UMA for the effective zoom in order to assess the relative + // importance of sub-pixel behavior, and related features and bugs. + // Clamp to a max of 400%, to make the histogram behave better at no + // real cost to our understanding of the zooms in use. + base::UmaHistogramSparse( + "Blink.EffectiveZoom", + base::ClampToRange<float>(clamped_effective_zoom * 100, 0, 400)); + return true; +} + static FloatRoundedRect::Radii CalcRadiiFor(const LengthSize& top_left, const LengthSize& top_right, const LengthSize& bottom_left,
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 8c487e58..01503206 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -909,7 +909,7 @@ SetZIndexInternal(0); } - bool SetEffectiveZoom(float); + CORE_EXPORT bool SetEffectiveZoom(float); float EffectiveZoom() const; // -webkit-clip-path @@ -2986,16 +2986,6 @@ FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, CustomPropertiesEqual_Data); }; -inline bool ComputedStyle::SetEffectiveZoom(float f) { - // Clamp the effective zoom value to a smaller (but hopeful still large - // enough) range, to avoid overflow in derived computations. - float clamped_effective_zoom = clampTo<float>(f, 1e-6, 1e6); - if (EffectiveZoom() == clamped_effective_zoom) - return false; - SetInternalEffectiveZoom(clamped_effective_zoom); - return true; -} - inline float ComputedStyle::EffectiveZoom() const { return InternalEffectiveZoom(); }
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc index f304eb9..8978518 100644 --- a/third_party/blink/renderer/core/style/computed_style_test.cc +++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -529,9 +529,8 @@ std::make_unique<DummyPageHolder>(IntSize(0, 0), nullptr); const ComputedStyle* initial = &ComputedStyle::InitialStyle(); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(dummy_page_holder_->GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(dummy_page_holder_->GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); StyleResolverState state(dummy_page_holder_->GetDocument(), *dummy_page_holder_->GetDocument().documentElement(), initial, initial); @@ -570,9 +569,8 @@ CSSPropertyID::kColor, "-internal-light-dark-color(black, white)", ua_context); - ColorSchemeHelper color_scheme_helper; - color_scheme_helper.SetPreferredColorScheme(dummy_page_holder_->GetDocument(), - PreferredColorScheme::kDark); + ColorSchemeHelper color_scheme_helper(dummy_page_holder_->GetDocument()); + color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kDark); StyleResolverState state(dummy_page_holder_->GetDocument(), *dummy_page_holder_->GetDocument().documentElement(), initial, initial);
diff --git a/third_party/blink/renderer/core/svg/svg_script_element.cc b/third_party/blink/renderer/core/svg/svg_script_element.cc index 4aaa601..79ea6d9 100644 --- a/third_party/blink/renderer/core/svg/svg_script_element.cc +++ b/third_party/blink/renderer/core/svg/svg_script_element.cc
@@ -181,11 +181,11 @@ const AttrNameToTrustedType& SVGScriptElement::GetCheckedAttributeTypes() const { - DEFINE_STATIC_LOCAL(AttrNameToTrustedType, attribute_map, - ({ - {svg_names::kHrefAttr.LocalName(), - SpecificTrustedType::kTrustedScriptURL}, - })); + DEFINE_STATIC_LOCAL( + AttrNameToTrustedType, attribute_map, + ({ + {svg_names::kHrefAttr.LocalName(), SpecificTrustedType::kScriptURL}, + })); return attribute_map; }
diff --git a/third_party/blink/renderer/core/testing/color_scheme_helper.cc b/third_party/blink/renderer/core/testing/color_scheme_helper.cc index f673819..2101c0c 100644 --- a/third_party/blink/renderer/core/testing/color_scheme_helper.cc +++ b/third_party/blink/renderer/core/testing/color_scheme_helper.cc
@@ -7,35 +7,36 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_theme_engine.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/page/page.h" namespace blink { -ColorSchemeHelper::ColorSchemeHelper() { +ColorSchemeHelper::ColorSchemeHelper(Document& document) + : settings_(*document.GetSettings()) { DCHECK(Platform::Current() && Platform::Current()->ThemeEngine()); web_theme_engine_ = Platform::Current()->ThemeEngine(); - default_preferred_color_scheme_ = web_theme_engine_->PreferredColorScheme(); + default_preferred_color_scheme_ = settings_.GetPreferredColorScheme(); + default_forced_colors_ = web_theme_engine_->GetForcedColors(); +} + +ColorSchemeHelper::ColorSchemeHelper(Page& page) + : settings_(page.GetSettings()) { + DCHECK(Platform::Current() && Platform::Current()->ThemeEngine()); + web_theme_engine_ = Platform::Current()->ThemeEngine(); + default_preferred_color_scheme_ = settings_.GetPreferredColorScheme(); default_forced_colors_ = web_theme_engine_->GetForcedColors(); } ColorSchemeHelper::~ColorSchemeHelper() { // Reset preferred color scheme and forced colors to their original values. - web_theme_engine_->SetPreferredColorScheme(default_preferred_color_scheme_); + settings_.SetPreferredColorScheme(default_preferred_color_scheme_); web_theme_engine_->SetForcedColors(default_forced_colors_); } void ColorSchemeHelper::SetPreferredColorScheme( - Document& document, const PreferredColorScheme preferred_color_scheme) { - web_theme_engine_->SetPreferredColorScheme(preferred_color_scheme); - document.ColorSchemeChanged(); -} - -void ColorSchemeHelper::SetPreferredColorScheme( - Page& page, - const PreferredColorScheme preferred_color_scheme) { - web_theme_engine_->SetPreferredColorScheme(preferred_color_scheme); - page.ColorSchemeChanged(); + settings_.SetPreferredColorScheme(preferred_color_scheme); } void ColorSchemeHelper::SetForcedColors(Document& document,
diff --git a/third_party/blink/renderer/core/testing/color_scheme_helper.h b/third_party/blink/renderer/core/testing/color_scheme_helper.h index 3059873..25df460e 100644 --- a/third_party/blink/renderer/core/testing/color_scheme_helper.h +++ b/third_party/blink/renderer/core/testing/color_scheme_helper.h
@@ -12,6 +12,7 @@ class Document; class Page; +class Settings; class WebThemeEngine; // ColorSchemeHelper is used to update the values of PreferredColorScheme and @@ -19,20 +20,18 @@ // and ForcedColors back to their default values upon deconstruction. class ColorSchemeHelper { public: - ColorSchemeHelper(); + ColorSchemeHelper(Document& document); + ColorSchemeHelper(Page& page); ~ColorSchemeHelper(); void SetPreferredColorScheme( - Document& document, - const PreferredColorScheme preferred_color_scheme); - void SetPreferredColorScheme( - Page& page, const PreferredColorScheme preferred_color_scheme); void SetForcedColors(Document& document, const ForcedColors forced_colors); void SetForcedColors(Page& page, const ForcedColors forced_colors); private: WebThemeEngine* web_theme_engine_ = nullptr; + Settings& settings_; PreferredColorScheme default_preferred_color_scheme_ = PreferredColorScheme::kNoPreference; ForcedColors default_forced_colors_ = ForcedColors::kNone;
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc index 1531aec59..b459828e 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.cc
@@ -140,20 +140,18 @@ bool is_not_property : 1; bool is_not_attribute : 1; } kTypeTable[] = { - {"embed", "src", nullptr, SpecificTrustedType::kTrustedScriptURL}, - {"iframe", "srcdoc", nullptr, SpecificTrustedType::kTrustedHTML}, - {"object", "codeBase", nullptr, SpecificTrustedType::kTrustedScriptURL}, - {"object", "data", nullptr, SpecificTrustedType::kTrustedScriptURL}, - {"script", "innerText", nullptr, SpecificTrustedType::kTrustedScript, false, + {"embed", "src", nullptr, SpecificTrustedType::kScriptURL}, + {"iframe", "srcdoc", nullptr, SpecificTrustedType::kHTML}, + {"object", "codeBase", nullptr, SpecificTrustedType::kScriptURL}, + {"object", "data", nullptr, SpecificTrustedType::kScriptURL}, + {"script", "innerText", nullptr, SpecificTrustedType::kScript, false, true}, + {"script", "src", nullptr, SpecificTrustedType::kScriptURL}, + {"script", "text", nullptr, SpecificTrustedType::kScript, false, true}, + {"script", "textContent", nullptr, SpecificTrustedType::kScript, false, true}, - {"script", "src", nullptr, SpecificTrustedType::kTrustedScriptURL}, - {"script", "text", nullptr, SpecificTrustedType::kTrustedScript, false, - true}, - {"script", "textContent", nullptr, SpecificTrustedType::kTrustedScript, - false, true}, - {"*", "innerHTML", nullptr, SpecificTrustedType::kTrustedHTML, false, true}, - {"*", "outerHTML", nullptr, SpecificTrustedType::kTrustedHTML, false, true}, - {"*", "on*", nullptr, SpecificTrustedType::kTrustedScript, true, false}, + {"*", "innerHTML", nullptr, SpecificTrustedType::kHTML, false, true}, + {"*", "outerHTML", nullptr, SpecificTrustedType::kHTML, false, true}, + {"*", "on*", nullptr, SpecificTrustedType::kScript, true, false}, }; // Does a type table entry match a property? @@ -185,11 +183,11 @@ String getTrustedTypeName(SpecificTrustedType type) { switch (type) { - case SpecificTrustedType::kTrustedHTML: + case SpecificTrustedType::kHTML: return "TrustedHTML"; - case SpecificTrustedType::kTrustedScript: + case SpecificTrustedType::kScript: return "TrustedScript"; - case SpecificTrustedType::kTrustedScriptURL: + case SpecificTrustedType::kScriptURL: return "TrustedScriptURL"; case SpecificTrustedType::kNone: return String();
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc index 7393364..43c6a563 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
@@ -27,7 +27,6 @@ namespace { enum TrustedTypeViolationKind { - kAnyTrustedTypeAssignment, kTrustedHTMLAssignment, kTrustedScriptAssignment, kTrustedScriptURLAssignment, @@ -45,8 +44,6 @@ const char* GetMessage(TrustedTypeViolationKind kind) { switch (kind) { - case kAnyTrustedTypeAssignment: - return "This document requires any trusted type assignment."; case kTrustedHTMLAssignment: return "This document requires 'TrustedHTML' assignment."; case kTrustedScriptAssignment: @@ -149,7 +146,7 @@ : nullptr; } -// Functionally identical to GetStringFromTrustedScript(const String&, ..), but +// Functionally identical to TrustedTypesCheckForScript(const String&, ..), but // to be called outside of regular script execution. This is required for both // GetStringForScriptExecution & TrustedTypesCheckForJavascriptURLinNavigation, // and has a number of additional parameters to enable proper error reporting @@ -230,143 +227,33 @@ !ContentSecurityPolicy::ShouldBypassMainWorld(execution_context); } -String GetStringFromTrustedType( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& - string_or_trusted_type, - const ExecutionContext* execution_context, - ExceptionState& exception_state) { - DCHECK(!string_or_trusted_type.IsNull()); - - if (string_or_trusted_type.IsString() && - RequireTrustedTypesCheck(execution_context)) { - TrustedTypeFail( - kAnyTrustedTypeAssignment, execution_context, exception_state, - GetStringFromTrustedTypeWithoutCheck(string_or_trusted_type)); - return g_empty_string; - } - - if (string_or_trusted_type.IsTrustedHTML()) - return string_or_trusted_type.GetAsTrustedHTML()->toString(); - if (string_or_trusted_type.IsTrustedScript()) - return string_or_trusted_type.GetAsTrustedScript()->toString(); - if (string_or_trusted_type.IsTrustedScriptURL()) - return string_or_trusted_type.GetAsTrustedScriptURL()->toString(); - - return string_or_trusted_type.GetAsString(); -} - -String GetStringFromTrustedTypeWithoutCheck( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& - string_or_trusted_type) { - if (string_or_trusted_type.IsTrustedHTML()) - return string_or_trusted_type.GetAsTrustedHTML()->toString(); - if (string_or_trusted_type.IsTrustedScript()) - return string_or_trusted_type.GetAsTrustedScript()->toString(); - if (string_or_trusted_type.IsTrustedScriptURL()) - return string_or_trusted_type.GetAsTrustedScriptURL()->toString(); - if (string_or_trusted_type.IsString()) - return string_or_trusted_type.GetAsString(); - - return g_empty_string; -} - -String GetStringFromSpecificTrustedType( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& - string_or_trusted_type, - SpecificTrustedType specific_trusted_type, - const ExecutionContext* execution_context, - ExceptionState& exception_state) { - switch (specific_trusted_type) { - case SpecificTrustedType::kNone: - return GetStringFromTrustedTypeWithoutCheck(string_or_trusted_type); - case SpecificTrustedType::kTrustedHTML: { - StringOrTrustedHTML string_or_trusted_html = - string_or_trusted_type.IsTrustedHTML() - ? StringOrTrustedHTML::FromTrustedHTML( - string_or_trusted_type.GetAsTrustedHTML()) - : StringOrTrustedHTML::FromString( - GetStringFromTrustedTypeWithoutCheck( - string_or_trusted_type)); - return GetStringFromTrustedHTML(string_or_trusted_html, execution_context, - exception_state); - } - case SpecificTrustedType::kTrustedScript: { - StringOrTrustedScript string_or_trusted_script = - string_or_trusted_type.IsTrustedScript() - ? StringOrTrustedScript::FromTrustedScript( - string_or_trusted_type.GetAsTrustedScript()) - : StringOrTrustedScript::FromString( - GetStringFromTrustedTypeWithoutCheck( - string_or_trusted_type)); - return GetStringFromTrustedScript(string_or_trusted_script, - execution_context, exception_state); - } - case SpecificTrustedType::kTrustedScriptURL: { - StringOrTrustedScriptURL string_or_trusted_script_url = - string_or_trusted_type.IsTrustedScriptURL() - ? StringOrTrustedScriptURL::FromTrustedScriptURL( - string_or_trusted_type.GetAsTrustedScriptURL()) - : StringOrTrustedScriptURL::FromString( - GetStringFromTrustedTypeWithoutCheck( - string_or_trusted_type)); - return GetStringFromTrustedScriptURL(string_or_trusted_script_url, - execution_context, exception_state); - } - } -} - -String GetStringFromSpecificTrustedType( - const String& string, - SpecificTrustedType specific_trusted_type, - const ExecutionContext* execution_context, - ExceptionState& exception_state) { - if (specific_trusted_type == SpecificTrustedType::kNone) - return string; - return GetStringFromSpecificTrustedType( - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL::FromString(string), - specific_trusted_type, execution_context, exception_state); -} - -String GetStringFromTrustedHTML(StringOrTrustedHTML string_or_trusted_html, - const ExecutionContext* execution_context, - ExceptionState& exception_state) { - DCHECK(!string_or_trusted_html.IsNull()); - - if (string_or_trusted_html.IsTrustedHTML()) { - return string_or_trusted_html.GetAsTrustedHTML()->toString(); - } - - return GetStringFromTrustedHTML(string_or_trusted_html.GetAsString(), - execution_context, exception_state); -} - -String GetStringFromTrustedHTML(const String& string, +String TrustedTypesCheckForHTML(const String& html, const ExecutionContext* execution_context, ExceptionState& exception_state) { bool require_trusted_type = RequireTrustedTypesCheck(execution_context); if (!require_trusted_type) { - return string; + return html; } TrustedTypePolicy* default_policy = GetDefaultPolicy(execution_context); if (!default_policy) { if (TrustedTypeFail(kTrustedHTMLAssignment, execution_context, - exception_state, string)) { + exception_state, html)) { return g_empty_string; } - return string; + return html; } if (!default_policy->HasCreateHTML()) { if (TrustedTypeFail(kTrustedHTMLAssignmentAndNoDefaultPolicyExisted, - execution_context, exception_state, string)) { + execution_context, exception_state, html)) { return g_empty_string; } else { - return string; + return html; } } TrustedHTML* result = - default_policy->CreateHTML(execution_context->GetIsolate(), string, + default_policy->CreateHTML(execution_context->GetIsolate(), html, HeapVector<ScriptValue>(), exception_state); if (exception_state.HadException()) { return g_empty_string; @@ -374,82 +261,60 @@ if (result->toString().IsNull()) { if (TrustedTypeFail(kTrustedHTMLAssignmentAndDefaultPolicyFailed, - execution_context, exception_state, string)) { + execution_context, exception_state, html)) { return g_empty_string; } else { - return string; + return html; } } return result->toString(); } -String GetStringFromTrustedHTML(StringOrTrustedHTML string_or_trusted_html, +String TrustedTypesCheckForHTML(StringOrTrustedHTML string_or_trusted_html, const Document* document, ExceptionState& exception_state) { - return GetStringFromTrustedHTML( + return TrustedTypesCheckForHTML( string_or_trusted_html, document ? document->ToExecutionContext() : nullptr, exception_state); } -String GetStringFromTrustedHTML(const String& string, +String TrustedTypesCheckForHTML(const String& html, const Document* document, ExceptionState& exception_state) { - return GetStringFromTrustedHTML( - string, document ? document->ToExecutionContext() : nullptr, + return TrustedTypesCheckForHTML( + html, document ? document->ToExecutionContext() : nullptr, exception_state); } -String GetStringFromTrustedScript( - StringOrTrustedScript string_or_trusted_script, - const ExecutionContext* execution_context, - ExceptionState& exception_state) { - // To remain compatible with legacy behaviour, HTMLElement uses extended IDL - // attributes to allow for nullable union of (DOMString or TrustedScript). - // Thus, this method is required to handle the case where - // string_or_trusted_script.IsNull(), unlike the various similar methods in - // this file. - - if (string_or_trusted_script.IsTrustedScript()) { - return string_or_trusted_script.GetAsTrustedScript()->toString(); - } - - if (string_or_trusted_script.IsNull()) { - string_or_trusted_script = - StringOrTrustedScript::FromString(g_empty_string); - } - return GetStringFromTrustedScript(string_or_trusted_script.GetAsString(), - execution_context, exception_state); -} - -String GetStringFromTrustedScript(const String& potential_script, +String TrustedTypesCheckForScript(const String& script, const ExecutionContext* execution_context, ExceptionState& exception_state) { bool require_trusted_type = RequireTrustedTypesCheck(execution_context); if (!require_trusted_type) { - return potential_script; + return script; } TrustedTypePolicy* default_policy = GetDefaultPolicy(execution_context); if (!default_policy) { if (TrustedTypeFail(kTrustedScriptAssignment, execution_context, - exception_state, potential_script)) { + exception_state, script)) { return g_empty_string; } - return potential_script; + return script; } if (!default_policy->HasCreateScript()) { if (TrustedTypeFail(kTrustedScriptAssignmentAndNoDefaultPolicyExisted, - execution_context, exception_state, potential_script)) { + execution_context, exception_state, script)) { return g_empty_string; } else { - return potential_script; + return script; } } - TrustedScript* result = default_policy->CreateScript( - execution_context->GetIsolate(), potential_script, - HeapVector<ScriptValue>(), exception_state); + TrustedScript* result = + default_policy->CreateScript(execution_context->GetIsolate(), script, + HeapVector<ScriptValue>(), exception_state); DCHECK_EQ(!result, exception_state.HadException()); if (exception_state.HadException()) { return g_empty_string; @@ -457,59 +322,45 @@ if (result->toString().IsNull()) { if (TrustedTypeFail(kTrustedScriptAssignmentAndDefaultPolicyFailed, - execution_context, exception_state, potential_script)) { + execution_context, exception_state, script)) { return g_empty_string; } else { - return potential_script; + return script; } } return result->toString(); } -String GetStringFromTrustedScriptURL( - StringOrTrustedScriptURL string_or_trusted_script_url, - const ExecutionContext* execution_context, - ExceptionState& exception_state) { - DCHECK(!string_or_trusted_script_url.IsNull()); - if (string_or_trusted_script_url.IsTrustedScriptURL()) { - return string_or_trusted_script_url.GetAsTrustedScriptURL()->toString(); - } - DCHECK(string_or_trusted_script_url.IsString()); - return GetStringFromTrustedScriptURL( - string_or_trusted_script_url.GetAsString(), execution_context, - exception_state); -} - -String GetStringFromTrustedScriptURL(const String& string, +String TrustedTypesCheckForScriptURL(const String& script_url, const ExecutionContext* execution_context, ExceptionState& exception_state) { bool require_trusted_type = RequireTrustedTypesCheck(execution_context) && RuntimeEnabledFeatures::TrustedDOMTypesEnabled(execution_context); if (!require_trusted_type) { - return string; + return script_url; } TrustedTypePolicy* default_policy = GetDefaultPolicy(execution_context); if (!default_policy) { if (TrustedTypeFail(kTrustedScriptURLAssignment, execution_context, - exception_state, string)) { + exception_state, script_url)) { return g_empty_string; } - return string; + return script_url; } if (!default_policy->HasCreateScriptURL()) { if (TrustedTypeFail(kTrustedScriptURLAssignmentAndNoDefaultPolicyExisted, - execution_context, exception_state, string)) { + execution_context, exception_state, script_url)) { return g_empty_string; } else { - return string; + return script_url; } } TrustedScriptURL* result = default_policy->CreateScriptURL( - execution_context->GetIsolate(), string, HeapVector<ScriptValue>(), + execution_context->GetIsolate(), script_url, HeapVector<ScriptValue>(), exception_state); if (exception_state.HadException()) { @@ -518,16 +369,106 @@ if (result->toString().IsNull()) { if (TrustedTypeFail(kTrustedScriptURLAssignmentAndDefaultPolicyFailed, - execution_context, exception_state, string)) { + execution_context, exception_state, script_url)) { return g_empty_string; } else { - return string; + return script_url; } } return result->toString(); } +String TrustedTypesCheckFor( + SpecificTrustedType type, + const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& trusted, + const ExecutionContext* execution_context, + ExceptionState& exception_state) { + // Whatever happens below, we will need the string value: + String value; + if (trusted.IsTrustedHTML()) { + value = trusted.GetAsTrustedHTML()->toString(); + } else if (trusted.IsTrustedScript()) { + value = trusted.GetAsTrustedScript()->toString(); + } else if (trusted.IsTrustedScriptURL()) { + value = trusted.GetAsTrustedScriptURL()->toString(); + } else if (trusted.IsString()) { + value = trusted.GetAsString(); + } // else: trusted.IsNull(). But we don't have anything to do in that case. + + // The check passes if we have the proper trusted type: + if (type == SpecificTrustedType::kNone || + (trusted.IsTrustedHTML() && type == SpecificTrustedType::kHTML) || + (trusted.IsTrustedScript() && type == SpecificTrustedType::kScript) || + (trusted.IsTrustedScriptURL() && + type == SpecificTrustedType::kScriptURL)) { + return value; + } + + // In all other cases: run the full check against the string value. + return TrustedTypesCheckFor(type, value, execution_context, exception_state); +} + +String TrustedTypesCheckForHTML(StringOrTrustedHTML trusted, + const ExecutionContext* execution_context, + ExceptionState& exception_state) { + DCHECK(!trusted.IsNull()); + if (trusted.IsTrustedHTML()) { + return trusted.GetAsTrustedHTML()->toString(); + } + return TrustedTypesCheckForHTML(trusted.GetAsString(), execution_context, + exception_state); +} + +String TrustedTypesCheckForScript(StringOrTrustedScript trusted, + const ExecutionContext* execution_context, + ExceptionState& exception_state) { + // To remain compatible with legacy behaviour, HTMLElement uses extended IDL + // attributes to allow for nullable union of (DOMString or TrustedScript). + // Thus, this method is required to handle the case where + // string_or_trusted_script.IsNull(), unlike the various similar methods in + // this file. + if (trusted.IsTrustedScript()) { + return trusted.GetAsTrustedScript()->toString(); + } + if (trusted.IsNull()) { + trusted = StringOrTrustedScript::FromString(g_empty_string); + } + return TrustedTypesCheckForScript(trusted.GetAsString(), execution_context, + exception_state); +} +String TrustedTypesCheckForScriptURL(StringOrTrustedScriptURL trusted, + const ExecutionContext* execution_context, + ExceptionState& exception_state) { + DCHECK(!trusted.IsNull()); + if (trusted.IsTrustedScriptURL()) { + return trusted.GetAsTrustedScriptURL()->toString(); + } + return TrustedTypesCheckForScriptURL(trusted.GetAsString(), execution_context, + exception_state); +} + +String TrustedTypesCheckFor(SpecificTrustedType type, + const String& trusted, + const ExecutionContext* execution_context, + ExceptionState& exception_state) { + switch (type) { + case SpecificTrustedType::kHTML: + return TrustedTypesCheckForHTML(trusted, execution_context, + exception_state); + case SpecificTrustedType::kScript: + return TrustedTypesCheckForScript(trusted, execution_context, + exception_state); + case SpecificTrustedType::kScriptURL: + return TrustedTypesCheckForScriptURL(trusted, execution_context, + exception_state); + case SpecificTrustedType::kNone: + return trusted; + } + NOTREACHED(); + return ""; +} + String CORE_EXPORT GetStringForScriptExecution(const String& script, Document* doc) { return GetStringFromScriptHelper(script, doc, "script", "text",
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h index 1533b58d..152a10b 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h +++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
@@ -20,68 +20,62 @@ enum class SpecificTrustedType { kNone, - kTrustedHTML, - kTrustedScript, - kTrustedScriptURL, + kHTML, + kScript, + kScriptURL, }; -String CORE_EXPORT GetStringFromTrustedType( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&, - const ExecutionContext*, - ExceptionState&); - -String CORE_EXPORT GetStringFromTrustedTypeWithoutCheck( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&); - -String CORE_EXPORT GetStringFromSpecificTrustedType( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&, - SpecificTrustedType, - const ExecutionContext*, - ExceptionState&); - -String CORE_EXPORT GetStringFromSpecificTrustedType(const String&, - SpecificTrustedType, - const ExecutionContext*, - ExceptionState&); - -String CORE_EXPORT GetStringFromTrustedHTML(StringOrTrustedHTML, - const ExecutionContext*, - ExceptionState&); - -String GetStringFromTrustedHTML(const String&, - const ExecutionContext*, - ExceptionState&); - // TODO(crbug.com/1029822): Temporary helpers to ease migrating ExecutionContext // to LocalDOMWindow. -String CORE_EXPORT GetStringFromTrustedHTML(StringOrTrustedHTML, +CORE_EXPORT String TrustedTypesCheckForHTML(StringOrTrustedHTML, const Document*, ExceptionState&); -String GetStringFromTrustedHTML(const String&, +String TrustedTypesCheckForHTML(const String&, const Document*, ExceptionState&); -String CORE_EXPORT GetStringFromTrustedScript(StringOrTrustedScript, +// Perform Trusted Type checks, with the IDL union types as input. All of these +// will call String& versions below to do the heavy lifting. +CORE_EXPORT String TrustedTypesCheckFor( + SpecificTrustedType, + const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL&, + const ExecutionContext*, + ExceptionState&) WARN_UNUSED_RESULT; +String TrustedTypesCheckForHTML(StringOrTrustedHTML, + const ExecutionContext*, + ExceptionState&) WARN_UNUSED_RESULT; +CORE_EXPORT String TrustedTypesCheckForScript(StringOrTrustedScript, const ExecutionContext*, - ExceptionState&); - -String CORE_EXPORT GetStringFromTrustedScript(const String&, - const ExecutionContext*, - ExceptionState&); - -String CORE_EXPORT GetStringFromTrustedScriptURL(StringOrTrustedScriptURL, + ExceptionState&) + WARN_UNUSED_RESULT; +CORE_EXPORT String TrustedTypesCheckForScriptURL(StringOrTrustedScriptURL, const ExecutionContext*, - ExceptionState&); + ExceptionState&) + WARN_UNUSED_RESULT; -String CORE_EXPORT GetStringFromTrustedScriptURL(const String&, - const ExecutionContext*, - ExceptionState&); +// Perform Trusted Type checks, for a dynamically or statically determined +// type. +// Returns the effective value (which may have been modified by the "default" +// policy. We use WARN_UNUSED_RESULT to prevent erroneous usage. +String TrustedTypesCheckFor(SpecificTrustedType, + const String&, + const ExecutionContext*, + ExceptionState&) WARN_UNUSED_RESULT; +String TrustedTypesCheckForHTML(const String&, + const ExecutionContext*, + ExceptionState&) WARN_UNUSED_RESULT; +String TrustedTypesCheckForScript(const String&, + const ExecutionContext*, + ExceptionState&) WARN_UNUSED_RESULT; +String TrustedTypesCheckForScriptURL(const String&, + const ExecutionContext*, + ExceptionState&) WARN_UNUSED_RESULT; -// Functionally equivalent to GetStringFromTrustedScript(const String&, ...), +// Functionally equivalent to TrustedTypesCheckForScript(const String&, ...), // but with setup & error handling suitable for the asynchronous execution // cases. String TrustedTypesCheckForJavascriptURLinNavigation(const String&, Document*); -String CORE_EXPORT GetStringForScriptExecution(const String&, Document*); +CORE_EXPORT String GetStringForScriptExecution(const String&, Document*); // Determine whether a Trusted Types check is needed in this execution context. // @@ -90,7 +84,7 @@ // immediately imply "okay" this method can be used. // Example: To determine whether 'eval' may pass, one needs to also take CSP // into account. -bool CORE_EXPORT RequireTrustedTypesCheck(const ExecutionContext*); +CORE_EXPORT bool RequireTrustedTypesCheck(const ExecutionContext*); } // namespace blink
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc index c2f4e3bca..36f4c9a 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util_test.cc
@@ -22,33 +22,7 @@ namespace blink { -// Functions for checking throwing cases. -void GetStringFromTrustedTypeThrows( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& - string_or_trusted_type) { - auto* document = MakeGarbageCollected<Document>(); - document->GetContentSecurityPolicy()->DidReceiveHeader( - "trusted-types *", network::mojom::ContentSecurityPolicyType::kEnforce, - network::mojom::ContentSecurityPolicySource::kMeta); - DummyExceptionStateForTesting exception_state; - ASSERT_FALSE(exception_state.HadException()); - String s = GetStringFromTrustedType( - string_or_trusted_type, document->ToExecutionContext(), exception_state); - EXPECT_FALSE(exception_state.HadException()); - - document->GetContentSecurityPolicy()->DidReceiveHeader( - "require-trusted-types-for 'script'", - network::mojom::ContentSecurityPolicyType::kEnforce, - network::mojom::ContentSecurityPolicySource::kMeta); - ASSERT_FALSE(exception_state.HadException()); - String s1 = GetStringFromTrustedType( - string_or_trusted_type, document->ToExecutionContext(), exception_state); - EXPECT_TRUE(exception_state.HadException()); - EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>()); - exception_state.ClearException(); -} - -void GetStringFromTrustedHTMLThrows( +void TrustedTypesCheckForHTMLThrows( const StringOrTrustedHTML& string_or_trusted_html) { auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600)); Document& document = dummy_page_holder->GetDocument(); @@ -58,7 +32,7 @@ V8TestingScope scope; DummyExceptionStateForTesting exception_state; ASSERT_FALSE(exception_state.HadException()); - String s = GetStringFromTrustedHTML(string_or_trusted_html, &document, + String s = TrustedTypesCheckForHTML(string_or_trusted_html, &document, exception_state); EXPECT_FALSE(exception_state.HadException()); @@ -67,14 +41,14 @@ network::mojom::ContentSecurityPolicyType::kEnforce, network::mojom::ContentSecurityPolicySource::kMeta); ASSERT_FALSE(exception_state.HadException()); - String s1 = GetStringFromTrustedHTML(string_or_trusted_html, &document, + String s1 = TrustedTypesCheckForHTML(string_or_trusted_html, &document, exception_state); EXPECT_TRUE(exception_state.HadException()); EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>()); exception_state.ClearException(); } -void GetStringFromTrustedScriptThrows( +void TrustedTypesCheckForScriptThrows( const StringOrTrustedScript& string_or_trusted_script) { auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600)); Document& document = dummy_page_holder->GetDocument(); @@ -84,7 +58,7 @@ V8TestingScope scope; DummyExceptionStateForTesting exception_state; ASSERT_FALSE(exception_state.HadException()); - String s = GetStringFromTrustedScript( + String s = TrustedTypesCheckForScript( string_or_trusted_script, document.ToExecutionContext(), exception_state); EXPECT_FALSE(exception_state.HadException()); @@ -93,14 +67,14 @@ network::mojom::ContentSecurityPolicyType::kEnforce, network::mojom::ContentSecurityPolicySource::kMeta); ASSERT_FALSE(exception_state.HadException()); - String s1 = GetStringFromTrustedScript( + String s1 = TrustedTypesCheckForScript( string_or_trusted_script, document.ToExecutionContext(), exception_state); EXPECT_TRUE(exception_state.HadException()); EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>()); exception_state.ClearException(); } -void GetStringFromTrustedScriptURLThrows( +void TrustedTypesCheckForScriptURLThrows( const StringOrTrustedScriptURL& string_or_trusted_script_url) { auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600)); Document& document = dummy_page_holder->GetDocument(); @@ -110,7 +84,7 @@ V8TestingScope scope; DummyExceptionStateForTesting exception_state; ASSERT_FALSE(exception_state.HadException()); - String s = GetStringFromTrustedScriptURL(string_or_trusted_script_url, + String s = TrustedTypesCheckForScriptURL(string_or_trusted_script_url, document.ToExecutionContext(), exception_state); EXPECT_FALSE(exception_state.HadException()); @@ -120,7 +94,7 @@ network::mojom::ContentSecurityPolicyType::kEnforce, network::mojom::ContentSecurityPolicySource::kMeta); ASSERT_FALSE(exception_state.HadException()); - String s1 = GetStringFromTrustedScriptURL(string_or_trusted_script_url, + String s1 = TrustedTypesCheckForScriptURL(string_or_trusted_script_url, document.ToExecutionContext(), exception_state); EXPECT_TRUE(exception_state.HadException()); @@ -128,22 +102,7 @@ exception_state.ClearException(); } -// Functions for checking non-throwing cases. -void GetStringFromTrustedTypeWorks( - const StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL& - string_or_trusted_type, - String expected) { - auto* document = MakeGarbageCollected<Document>(); - document->GetContentSecurityPolicy()->DidReceiveHeader( - "trusted-types *", network::mojom::ContentSecurityPolicyType::kEnforce, - network::mojom::ContentSecurityPolicySource::kMeta); - DummyExceptionStateForTesting exception_state; - String s = GetStringFromTrustedType( - string_or_trusted_type, document->ToExecutionContext(), exception_state); - ASSERT_EQ(s, expected); -} - -void GetStringFromTrustedHTMLWorks( +void TrustedTypesCheckForHTMLWorks( const StringOrTrustedHTML& string_or_trusted_html, String expected) { auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600)); @@ -153,12 +112,12 @@ network::mojom::ContentSecurityPolicySource::kMeta); V8TestingScope scope; DummyExceptionStateForTesting exception_state; - String s = GetStringFromTrustedHTML(string_or_trusted_html, &document, + String s = TrustedTypesCheckForHTML(string_or_trusted_html, &document, exception_state); ASSERT_EQ(s, expected); } -void GetStringFromTrustedScriptWorks( +void TrustedTypesCheckForScriptWorks( const StringOrTrustedScript& string_or_trusted_script, String expected) { auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600)); @@ -168,12 +127,12 @@ network::mojom::ContentSecurityPolicySource::kMeta); V8TestingScope scope; DummyExceptionStateForTesting exception_state; - String s = GetStringFromTrustedScript( + String s = TrustedTypesCheckForScript( string_or_trusted_script, document.ToExecutionContext(), exception_state); ASSERT_EQ(s, expected); } -void GetStringFromTrustedScriptURLWorks( +void TrustedTypesCheckForScriptURLWorks( const StringOrTrustedScriptURL& string_or_trusted_script_url, String expected) { auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600)); @@ -183,139 +142,52 @@ network::mojom::ContentSecurityPolicySource::kMeta); V8TestingScope scope; DummyExceptionStateForTesting exception_state; - String s = GetStringFromTrustedScriptURL(string_or_trusted_script_url, + String s = TrustedTypesCheckForScriptURL(string_or_trusted_script_url, document.ToExecutionContext(), exception_state); ASSERT_EQ(s, expected); } -// GetStringFromTrustedType() tests -TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedHTML) { - auto* html = MakeGarbageCollected<TrustedHTML>("A string"); - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL trusted_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL::FromTrustedHTML( - html); - GetStringFromTrustedTypeWorks(trusted_value, "A string"); -} - -TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedScript) { - auto* script = MakeGarbageCollected<TrustedScript>("A string"); - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL trusted_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL::FromTrustedScript( - script); - GetStringFromTrustedTypeWorks(trusted_value, "A string"); -} - -TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedScriptURL) { - String url_address = "http://www.example.com/"; - auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address); - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL trusted_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL:: - FromTrustedScriptURL(script_url); - GetStringFromTrustedTypeWorks(trusted_value, "http://www.example.com/"); -} - -TEST(TrustedTypesUtilTest, GetStringFromTrustedType_TrustedScriptURL_Relative) { - String url_address = "relative/url.html"; - auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address); - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL trusted_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL:: - FromTrustedScriptURL(script_url); - GetStringFromTrustedTypeWorks(trusted_value, "relative/url.html"); -} - -TEST(TrustedTypesUtilTest, GetStringFromTrustedType_String) { - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL string_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL::FromString( - "A string"); - GetStringFromTrustedTypeThrows(string_value); -} - -// GetStringFromTrustedTypeWithoutCheck() tests -TEST(TrustedTypesUtilTest, GetStringFromTrustedTypeWithoutCheck_TrustedHTML) { - auto* html = MakeGarbageCollected<TrustedHTML>("A string"); - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL trusted_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL::FromTrustedHTML( - html); - String s = GetStringFromTrustedTypeWithoutCheck(trusted_value); - ASSERT_EQ(s, "A string"); -} - -TEST(TrustedTypesUtilTest, GetStringFromTrustedTypeWithoutCheck_TrustedScript) { - auto* script = MakeGarbageCollected<TrustedScript>("A string"); - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL trusted_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL::FromTrustedScript( - script); - String s = GetStringFromTrustedTypeWithoutCheck(trusted_value); - ASSERT_EQ(s, "A string"); -} - -TEST(TrustedTypesUtilTest, - GetStringFromTrustedTypeWithoutCheck_TrustedScriptURL) { - String url_address = "http://www.example.com/"; - auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address); - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL trusted_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL:: - FromTrustedScriptURL(script_url); - String s = GetStringFromTrustedTypeWithoutCheck(trusted_value); - ASSERT_EQ(s, "http://www.example.com/"); -} - -TEST(TrustedTypesUtilTest, GetStringFromTrustedTypeWithoutCheck_String) { - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL string_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL::FromString( - "A string"); - String s = GetStringFromTrustedTypeWithoutCheck(string_value); - ASSERT_EQ(s, "A string"); -} - -TEST(TrustedTypesUtilTest, GetStringFromTrustedTypeWithoutCheck_Null) { - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL null_value = - StringOrTrustedHTMLOrTrustedScriptOrTrustedScriptURL(); - String s = GetStringFromTrustedTypeWithoutCheck(null_value); - ASSERT_EQ(s, ""); -} - -// GetStringFromTrustedHTML tests -TEST(TrustedTypesUtilTest, GetStringFromTrustedHTML_TrustedHTML) { +// TrustedTypesCheckForHTML tests +TEST(TrustedTypesUtilTest, TrustedTypesCheckForHTML_TrustedHTML) { auto* html = MakeGarbageCollected<TrustedHTML>("A string"); StringOrTrustedHTML trusted_value = StringOrTrustedHTML::FromTrustedHTML(html); - GetStringFromTrustedHTMLWorks(trusted_value, "A string"); + TrustedTypesCheckForHTMLWorks(trusted_value, "A string"); } -TEST(TrustedTypesUtilTest, GetStringFromTrustedHTML_String) { +TEST(TrustedTypesUtilTest, TrustedTypesCheckForHTML_String) { StringOrTrustedHTML string_value = StringOrTrustedHTML::FromString("A string"); - GetStringFromTrustedHTMLThrows(string_value); + TrustedTypesCheckForHTMLThrows(string_value); } -// GetStringFromTrustedScript tests -TEST(TrustedTypesUtilTest, GetStringFromTrustedScript_TrustedScript) { +// TrustedTypesCheckForScript tests +TEST(TrustedTypesUtilTest, TrustedTypesCheckForScript_TrustedScript) { auto* script = MakeGarbageCollected<TrustedScript>("A string"); StringOrTrustedScript trusted_value = StringOrTrustedScript::FromTrustedScript(script); - GetStringFromTrustedScriptWorks(trusted_value, "A string"); + TrustedTypesCheckForScriptWorks(trusted_value, "A string"); } -TEST(TrustedTypesUtilTest, GetStringFromTrustedScript_String) { +TEST(TrustedTypesUtilTest, TrustedTypesCheckForScript_String) { StringOrTrustedScript string_value = StringOrTrustedScript::FromString("A string"); - GetStringFromTrustedScriptThrows(string_value); + TrustedTypesCheckForScriptThrows(string_value); } -// GetStringFromTrustedScriptURL tests -TEST(TrustedTypesUtilTest, GetStringFromTrustedScriptURL_TrustedScriptURL) { +// TrustedTypesCheckForScriptURL tests +TEST(TrustedTypesUtilTest, TrustedTypesCheckForScriptURL_TrustedScriptURL) { String url_address = "http://www.example.com/"; auto* script_url = MakeGarbageCollected<TrustedScriptURL>(url_address); StringOrTrustedScriptURL trusted_value = StringOrTrustedScriptURL::FromTrustedScriptURL(script_url); - GetStringFromTrustedScriptURLWorks(trusted_value, "http://www.example.com/"); + TrustedTypesCheckForScriptURLWorks(trusted_value, "http://www.example.com/"); } -TEST(TrustedTypesUtilTest, GetStringFromTrustedScriptURL_String) { +TEST(TrustedTypesUtilTest, TrustedTypesCheckForScriptURL_String) { StringOrTrustedScriptURL string_value = StringOrTrustedScriptURL::FromString("A string"); - GetStringFromTrustedScriptURLThrows(string_value); + TrustedTypesCheckForScriptURLThrows(string_value); } } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index b9480613..bb08f9e 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -174,7 +174,7 @@ ExceptionState& exception_state) { Vector<String> string_urls; for (const StringOrTrustedScriptURL& stringOrUrl : urls) { - String string_url = GetStringFromTrustedScriptURL( + String string_url = TrustedTypesCheckForScriptURL( stringOrUrl, GetExecutionContext(), exception_state); if (exception_state.HadException()) return;
diff --git a/third_party/blink/renderer/core/xml/dom_parser.cc b/third_party/blink/renderer/core/xml/dom_parser.cc index 9890fa3..a60e49c8 100644 --- a/third_party/blink/renderer/core/xml/dom_parser.cc +++ b/third_party/blink/renderer/core/xml/dom_parser.cc
@@ -32,7 +32,7 @@ Document* DOMParser::parseFromString(const StringOrTrustedHTML& stringOrHTML, const String& type, ExceptionState& exception_state) { - String value = GetStringFromTrustedHTML(stringOrHTML, context_document_, + String value = TrustedTypesCheckForHTML(stringOrHTML, context_document_, exception_state); if (!exception_state.HadException()) { return parseFromStringInternal(value, type);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index 3bd5e9c3..3f2530d 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -2436,27 +2436,17 @@ if (HasAOMPropertyOrARIAAttribute(AOMStringProperty::kRole, role)) return true; - if (!layout_object_->IsTable()) - return false; - // When a section of the document is contentEditable, all tables should be // treated as data tables, otherwise users may not be able to work with rich // text editors that allow creating and editing tables. if (GetNode() && HasEditableStyle(*GetNode())) return true; - // If there's no node, it's definitely a layout table. This happens - // when table CSS styles are used without a complete table DOM structure. - LayoutNGTableInterface* table = - ToInterface<LayoutNGTableInterface>(layout_object_); - table->RecalcSectionsIfNeeded(); - Node* table_node = layout_object_->GetNode(); - // This employs a heuristic to determine if this table should appear. // Only "data" tables should be exposed as tables. // Unfortunately, there is no good way to determine the difference // between a "layout" table and a "data" table. - auto* table_element = DynamicTo<HTMLTableElement>(table_node); + auto* table_element = DynamicTo<HTMLTableElement>(GetNode()); if (!table_element) return false; @@ -2474,6 +2464,23 @@ if (Traversal<HTMLTableColElement>::FirstChild(*table_element)) return true; + // Everything from here forward uses cell style info, but only if a CSS table. + // If this code is reached for a <table> with another display type, consider + // this to be a layout table. + // TODO(accessibility) consider rewriting the following cell inspection code + // using purely DOM methods, such as table->rows()->Item(index)->cells(). + if (!layout_object_->IsTable()) + return false; + + // If there's no node, it's definitely a layout table. This happens + // when table CSS styles are used without a complete table DOM structure. + LayoutNGTableInterface* table = + ToInterface<LayoutNGTableInterface>(layout_object_); + table->RecalcSectionsIfNeeded(); + Node* table_node = layout_object_->GetNode(); + if (!table_node) + return false; + // go through the cell's and check for tell-tale signs of "data" table status // cells have borders, or use attributes like headers, abbr, scope or axis table->RecalcSectionsIfNeeded();
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_client.cc b/third_party/blink/renderer/modules/mediastream/user_media_client.cc index d38d10f..f40e32f 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_client.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_client.cc
@@ -148,8 +148,8 @@ int request_id = g_next_request_id++; blink::WebRtcLogMessage(base::StringPrintf( - "UMCI::RequestUserMedia. request_id=%d, audio constraints=%s, " - "video constraints=%s", + "UMCI::RequestUserMedia({request_id=%d}, {audio constraints=%s}, " + "{video constraints=%s})", request_id, user_media_request->AudioConstraints().ToString().Utf8().c_str(), user_media_request->VideoConstraints().ToString().Utf8().c_str()));
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc index 58bc919..620c1af 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
@@ -6,6 +6,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_video_frame.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/peerconnection/rtc_encoded_video_stream_transformer.h" #include "third_party/webrtc/api/video/encoded_frame.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc index c985294..150ecb9c 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
@@ -9,6 +9,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_video_frame.h" #include "third_party/blink/renderer/core/streams/writable_stream.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc index 2fd082a..0e063a2f 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -1967,6 +1967,25 @@ return String(); } +bool RTCPeerConnection::canTrickleIceCandidates(bool& is_null) const { + is_null = true; + if (closed_ || !peer_handler_->RemoteDescription()) { + return false; + } + webrtc::PeerConnectionInterface* native_connection = + peer_handler_->NativePeerConnection(); + if (!native_connection) { + return false; + } + absl::optional<bool> can_trickle = + native_connection->can_trickle_ice_candidates(); + if (!can_trickle) { + return false; + } + is_null = false; + return *can_trickle; +} + void RTCPeerConnection::restartIce() { if (closed_) return;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h index 5759cfe..e32be36 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
@@ -227,6 +227,8 @@ String connectionState() const; + bool canTrickleIceCandidates(bool&) const; + void restartIce(); // A local stream is any stream associated with a sender.
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl index 2ccb2bd..65dbef0 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
@@ -83,7 +83,7 @@ readonly attribute RTCIceGatheringState iceGatheringState; readonly attribute RTCIceConnectionState iceConnectionState; readonly attribute RTCPeerConnectionState connectionState; - // readonly attribute boolean? canTrickleIceCandidates; + readonly attribute boolean? canTrickleIceCandidates; void restartIce(); [CallWith=ScriptState] RTCConfiguration getConfiguration(); [CallWith=ScriptState, RaisesException] void setConfiguration(RTCConfiguration configuration);
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index ddd3314..c6d562bd 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -505,14 +505,6 @@ RuntimeEnabledFeatures::SetExpensiveBackgroundTimerThrottlingEnabled(enable); } -void WebRuntimeFeatures::EnableFetchMetadata(bool enable) { - RuntimeEnabledFeatures::SetFetchMetadataEnabled(enable); -} - -void WebRuntimeFeatures::EnableFetchMetadataDestination(bool enable) { - RuntimeEnabledFeatures::SetFetchMetadataDestinationEnabled(enable); -} - void WebRuntimeFeatures::EnableTimerThrottlingForBackgroundTabs(bool enable) { RuntimeEnabledFeatures::SetTimerThrottlingForBackgroundTabsEnabled(enable); }
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 ce8819c4..e2b35ca 100644 --- a/third_party/blink/renderer/platform/exported/web_url_request.cc +++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -117,7 +117,7 @@ DCHECK_EQ(owned_resource_request_.get(), resource_request_); DCHECK(owned_resource_request_->IsNull()); DCHECK(this != &r); - resource_request_->CopyHeadFrom(r.resource_request_); + resource_request_->CopyHeadFrom(*r.resource_request_); resource_request_->SetHttpBody(r.resource_request_->HttpBody()); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc index c858317..4a887fa 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -490,7 +490,7 @@ DCHECK(!request.IsNull()); CHECK(!is_revalidation_start_forbidden_); is_revalidating_ = true; - resource_request_.CopyFrom(request); + resource_request_.CopyHeadFrom(request); status_ = ResourceStatus::kNotStarted; }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 29fe8ba1..cc3431e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -2090,7 +2090,7 @@ // TODO(dtapuska): revisit this when we have a better way to re-dispatch // requests. ResourceRequest request; - request.CopyFrom(stale_resource->GetResourceRequest()); + request.CopyHeadFrom(stale_resource->GetResourceRequest()); FetchParameters params(std::move(request)); params.SetStaleRevalidation(true); params.MutableResourceRequest().SetSkipServiceWorker(true);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc index 9e136c3..a7b4142a 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -113,8 +113,8 @@ *this = src; } -void ResourceRequest::CopyHeadFrom(const ResourceRequestHead* src) { - this->ResourceRequestHead::operator=(*src); +void ResourceRequest::CopyHeadFrom(const ResourceRequestHead& src) { + this->ResourceRequestHead::operator=(src); } std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h index ca9b3fe..be58e01 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -557,7 +557,7 @@ // TODO(yoichio): Use move semantics as much as possible. // See crbug.com/787704. void CopyFrom(const ResourceRequest&); - void CopyHeadFrom(const ResourceRequestHead*); + void CopyHeadFrom(const ResourceRequestHead&); // Constructs a new ResourceRequest for a redirect from this instance. std::unique_ptr<ResourceRequest> CreateRedirectRequest(
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 37c5051..8031be3 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -721,14 +721,6 @@ name: "FeaturePolicyVibrateFeature" }, { - name: "FetchMetadata", - status: "stable" - }, - { - name: "FetchMetadataDestination", - status: "experimental" - }, - { // Also enabled when blink::features::kFileHandlingAPI is overridden // on the command line (or via chrome://flags). name: "FileHandling", @@ -959,10 +951,6 @@ // Enabled by features::kLegacyWindowsDWriteFontFallback; }, { - name: "LinkSystemColors", - status: "stable", - }, - { name:"ManualSlotting", status:"experimental", }, @@ -1137,10 +1125,6 @@ name: "NewRemotePlaybackPipeline", }, { - name: "NewSystemColors", - status: "stable", - }, - { name: "NoIdleEncodingForWebTests", status: "test", },
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index e89b8ef..9907e90 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -56,6 +56,8 @@ crbug.com/906791 external/wpt/fullscreen/api/element-ready-check-allowed-cross-origin-manual.sub.html [ Timeout ] crbug.com/860713 external/wpt/bluetooth/requestDevice/cross-origin-iframe.sub.https.html [ Failure Timeout ] crbug.com/860713 external/wpt/bluetooth/requestDevice/request-from-sandboxed-iframe.https.html [ Failure Timeout ] +crbug.com/860713 virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/requestDevice/cross-origin-iframe.sub.https.html [ Failure Timeout ] +crbug.com/860713 virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/requestDevice/request-from-sandboxed-iframe.https.html [ Failure Timeout ] # The following tests would pass with User Activation Delegation. crbug.com/928838 external/wpt/html/user-activation/activation-transfer-with-click.tentative.html [ Failure ] @@ -6277,7 +6279,8 @@ # Enable scroll-snap tests on impl thread # These are currently failing on Mac which needs more investigation, snap-scrolls-visual-viewport seems flaky -crbug.com/878878 [ Mac ] virtual/threaded/fast/scroll-snap/snaps-after-keyboard-scrolling.html [ Timeout ] +crbug.com/878878 [ Mac ] virtual/threaded/fast/scroll-snap/snaps-after-keyboard-scrolling.html [ Pass Timeout ] +crbug.com/878878 [ Win10 ] virtual/threaded/fast/scroll-snap/snaps-after-keyboard-scrolling.html [ Pass Timeout ] crbug.com/878878 [ Mac ] virtual/threaded/fast/scroll-snap/snaps-after-scrollbar-scrolling.html [ Timeout ] crbug.com/878878 [ Mac ] virtual/threaded/fast/scroll-snap/snaps-for-different-key-granularity.html [ Timeout ] @@ -6753,3 +6756,5 @@ crbug.com/1057822 http/tests/misc/synthetic-gesture-initiated-in-cross-origin-frame.html [ Pass Failure ] crbug.com/1057807 http/tests/misc/destroy-middle-click-locked-target-crash.html [ Pass Timeout ] +crbug.com/1057351 virtual/threaded-no-composited-antialiasing/animations/responsive/interpolation/offset-rotate-responsive.html [ Pass Failure ] +crbug.com/1057351 virtual/threaded-no-composited-antialiasing/animations/stability/empty-keyframes.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 6770420..4aab5a1 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -731,5 +731,10 @@ "prefix": "storage-access-api", "bases": [ "external/wpt/storage-access-api" ], "args": [ "--enable-features=StorageAccessAPI" ] + }, + { + "prefix": "web-bluetooth-new-permissions-backend", + "bases": ["bluetooth", "external/wpt/bluetooth"], + "args": ["--enable-features=WebBluetoothNewPermissionsBackend"] } ]
diff --git a/third_party/blink/web_tests/custom-elements/constructor-may-poach-upgrading-element.html b/third_party/blink/web_tests/custom-elements/constructor-may-poach-upgrading-element.html index fce72a8..bda6d9a 100644 --- a/third_party/blink/web_tests/custom-elements/constructor-may-poach-upgrading-element.html +++ b/third_party/blink/web_tests/custom-elements/constructor-may-poach-upgrading-element.html
@@ -61,9 +61,7 @@ 'the recursive "new" should steal the upgrade candidate'); assert_equals(poacher, invocations[0], 'the recursize "new" should happen first'); - assert_true(invocations[1] instanceof w.DOMException, - 'the super call should have thrown a DOMException'); - assert_equals(invocations[1].name, 'InvalidStateError', - 'the exception should be an InvalidStateError'); + assert_true(invocations[1] instanceof w.TypeError, + 'the super call should have thrown a TypeError'); }, 'HTMLElement constructor: poach upgrade candidate'); </script>
diff --git a/third_party/blink/web_tests/custom-elements/spec/construct.html b/third_party/blink/web_tests/custom-elements/spec/construct.html index 11e3fce..658efc4 100644 --- a/third_party/blink/web_tests/custom-elements/spec/construct.html +++ b/third_party/blink/web_tests/custom-elements/spec/construct.html
@@ -146,7 +146,7 @@ } w.customElements.define('a-a', A); let d = w.document.createElement('div'); - assert_reports(window, 'INVALID_STATE_ERR', () => { + assert_reports_js(window, TypeError, () => { d.innerHTML = '<a-a>'; }, 'Creating an element that is already constructed marker should report ' + 'InvalidStateError'); @@ -171,7 +171,7 @@ } w.customElements.define('a-a', A); w.document.body.appendChild(e); - assert_array_equals(errors, ['InvalidStateError'], 'Upgrading an element ' + - 'that is already constructed marker should throw InvalidStateError'); + assert_array_equals(errors, ['TypeError'], 'Upgrading an element ' + + 'that is already constructed marker should throw TypeError'); }, 'Already constructed marker, upgrade element'); </script>
diff --git a/third_party/blink/web_tests/custom-elements/spec/report-the-exception.html b/third_party/blink/web_tests/custom-elements/spec/report-the-exception.html index 06b3b2ad..d4e7230 100644 --- a/third_party/blink/web_tests/custom-elements/spec/report-the-exception.html +++ b/third_party/blink/web_tests/custom-elements/spec/report-the-exception.html
@@ -147,11 +147,6 @@ assert_equals(error.error.name, 'TypeError'); } -function assert_invalid_state_dom_error_event(error) { - assert_not_muted_error_event(error); - assert_equals(error.error.name, 'InvalidStateError'); -} - test_with_window((w) => { // "create an element" 6.1.3, throw a TypeError. // https://dom.spec.whatwg.org/#concept-create-element @@ -160,10 +155,10 @@ constructor_returns_bad_object + instantiate); test_with_window((w) => { - // "upgrade an element" 10, throw an InvalidStateError DOMException. + // "upgrade an element" 10, throw a TypeError. // https://html.spec.whatwg.org/multipage/scripting.html#upgrades w.document.body.innerHTML = instantiate; - assert_invalid_state_dom_error_event(w.errors[0]); + assert_type_error_event(w.errors[0]); }, 'Upgrade reaction invokes the constructor that returns a bad object', constructor_returns_bad_object); </script>
diff --git a/third_party/blink/web_tests/custom-elements/spec/resources/custom-elements-helpers.js b/third_party/blink/web_tests/custom-elements/spec/resources/custom-elements-helpers.js index 44871eeb..7de434d1 100644 --- a/third_party/blink/web_tests/custom-elements/spec/resources/custom-elements-helpers.js +++ b/third_party/blink/web_tests/custom-elements/spec/resources/custom-elements-helpers.js
@@ -70,3 +70,26 @@ // accessed by throwing the error assert_throws(expected_error, () => { throw errors[0]; }); } + +// Asserts that func synchronously invokes the error event handler in w +// with the expected error. +function assert_reports_js(w, expected_error, func, description) { + let old_onerror = w.onerror; + let errors = []; + w.onerror = (event, source, line_number, column_number, error) => { + errors.push(error); + return true; // the error is handled + }; + try { + func(); + } catch (e) { + assert_unreached(`should report, not throw, an exception: ${e}`); + } finally { + w.onerror = old_onerror; + } + assert_equals(errors.length, 1, 'only one error should have been reported'); + assert_true( + typeof errors[0] === 'object' && errors[0] !== null, + 'got something other than an error'); + assert_equals(expected_error.name, errors[0].name); +}
diff --git a/third_party/blink/web_tests/custom-elements/spec/upgrade-element.html b/third_party/blink/web_tests/custom-elements/spec/upgrade-element.html index 8d728cb64..27f9f92d 100644 --- a/third_party/blink/web_tests/custom-elements/spec/upgrade-element.html +++ b/third_party/blink/web_tests/custom-elements/spec/upgrade-element.html
@@ -115,7 +115,7 @@ } } w.customElements.define('a-a', X); - assert_array_equals(error_log, ['InvalidStateError'], 'returning object that is different from element should throw "InvalidStateError"'); + assert_array_equals(error_log, ['TypeError'], 'returning object that is different from element should throw "TypeError"'); }, 'Upgrading an element with constructor that returns different object'); </script> </body>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json index f84f24e7d..3546f46 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -164560,9 +164560,6 @@ "html/cross-origin-embedder-policy/data.https.html.headers": [ [] ], - "html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https-expected.txt": [ - [] - ], "html/cross-origin-embedder-policy/javascript.https.html.headers": [ [] ], @@ -193660,9 +193657,15 @@ "workers/modules/resources/static-import-script-block-cross-origin.js": [ [] ], + "workers/modules/resources/static-import-syntax-error.js": [ + [] + ], "workers/modules/resources/static-import-worker.js": [ [] ], + "workers/modules/resources/syntax-error.js": [ + [] + ], "workers/modules/shared-worker-import-meta-expected.txt": [ [] ], @@ -236237,6 +236240,12 @@ {} ] ], + "css/css-values/update-subpixel-rem-unit.html": [ + [ + "css/css-values/update-subpixel-rem-unit.html", + {} + ] + ], "css/css-values/urls/empty.html": [ [ "css/css-values/urls/empty.html", @@ -371169,6 +371178,12 @@ {} ] ], + "workers/modules/dedicated-worker-parse-error-failure.html": [ + [ + "workers/modules/dedicated-worker-parse-error-failure.html", + {} + ] + ], "workers/modules/shared-worker-import-blob-url.any.js": [ [ "workers/modules/shared-worker-import-blob-url.any.html", @@ -469310,6 +469325,10 @@ "5869e9e6072910301ba41746f03eaf297079d98e", "testharness" ], + "css/css-values/update-subpixel-rem-unit.html": [ + "98d4f00f92ae90165dd9b0c82cf0496523bc9c2a", + "testharness" + ], "css/css-values/urls/empty.html": [ "3ab7079396c517d7abd6334b0cfadf7eda471115", "testharness" @@ -500910,10 +500929,6 @@ "6604450991a122e3e241e40b1b9e0516c525389d", "support" ], - "html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https-expected.txt": [ - "c2bc85a1f5b9f7005f1240f2625530d7435acb10", - "support" - ], "html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html": [ "2559de839a304dce0c2700dc4f8ee0002de04332", "testharness" @@ -508671,11 +508686,11 @@ "reftest" ], "html/rendering/unmapped-attributes-expected.txt": [ - "4179bfbb0420e5141741be44c2c7ea211b24247d", + "5fb804bc64d52fdef34d989a596be1564e8da682", "support" ], "html/rendering/unmapped-attributes.html": [ - "3f457eb492f0b72b2a9c5891e8784d0b69958b38", + "5824f836f0d654c116a55a252dfbda5fc6e5bbc8", "testharness" ], "html/rendering/widgets/appearance/default-styles-expected.txt": [ @@ -606747,7 +606762,7 @@ "testharness" ], "workers/modules/dedicated-worker-import-failure.html": [ - "33eeea261893bc2d920bb348efff7a07f264729f", + "4c705e73251f41d8b7ff796cda5a5629968ec130", "testharness" ], "workers/modules/dedicated-worker-import-meta-expected.txt": [ @@ -606778,6 +606793,10 @@ "bb37a18f2cc93312fd10fd7e0ed64d7be738a45f", "testharness" ], + "workers/modules/dedicated-worker-parse-error-failure.html": [ + "99eae49fc91296c55c51fb772bc4d46058ea0693", + "testharness" + ], "workers/modules/resources/dynamic-import-and-then-static-import-worker.js": [ "527702f551174f8f2578fce16c7854351126e3a5", "support" @@ -606942,10 +606961,18 @@ "82be8e7ce72edab7050b14cccc658ff39ddfe632", "support" ], + "workers/modules/resources/static-import-syntax-error.js": [ + "3a20e792c455ee53c26066f99afd79b041a46fb6", + "support" + ], "workers/modules/resources/static-import-worker.js": [ "19a347999d386fd4df8dc831c6d164b27630ef7a", "support" ], + "workers/modules/resources/syntax-error.js": [ + "8c5c4df671bcc3f75ac1e474fc651927e57e8701", + "support" + ], "workers/modules/shared-worker-import-blob-url.any.js": [ "f56c1a5525f8c46e5d06f6549b3f355c4ccb4a0a", "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/upgrading/Node-cloneNode-expected.txt b/third_party/blink/web_tests/external/wpt/custom-elements/upgrading/Node-cloneNode-expected.txt deleted file mode 100644 index 6ad8ab1..0000000 --- a/third_party/blink/web_tests/external/wpt/custom-elements/upgrading/Node-cloneNode-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -This is a testharness.js-based test. -PASS Node.prototype.cloneNode(false) must be able to clone a custom element -PASS Node.prototype.cloneNode(false) must be able to clone as a autonomous custom element when it contains is attribute -PASS Node.prototype.cloneNode(false) must be able to clone as a customized built-in element when it has an inconsistent "is" attribute -PASS Node.prototype.cloneNode(false) must be able to clone a custom element inside an iframe -PASS Node.prototype.cloneNode(true) must be able to clone a descendent custom element -PASS Node.prototype.cloneNode(true) must set parentNode, previousSibling, and nextSibling before upgrading custom elements -FAIL HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call assert_equals: expected "TypeError" but got "InvalidStateError" -FAIL HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call assert_equals: expected "TypeError" but got "InvalidStateError" -FAIL Upgrading a custom element must throw TypeError when the custom element's constructor returns another element assert_equals: expected "TypeError" but got "InvalidStateError" -PASS Inserting an element must not try to upgrade a custom element when it had already failed to upgrade once -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/upgrading/upgrading-parser-created-element-expected.txt b/third_party/blink/web_tests/external/wpt/custom-elements/upgrading/upgrading-parser-created-element-expected.txt deleted file mode 100644 index c520307..0000000 --- a/third_party/blink/web_tests/external/wpt/custom-elements/upgrading/upgrading-parser-created-element-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This is a testharness.js-based test. -PASS Element.prototype.createElement must add an unresolved custom element to the upgrade candidates map -FAIL HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call assert_equals: expected "TypeError" but got "InvalidStateError" -FAIL HTMLElement constructor must throw an TypeError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call assert_equals: expected "TypeError" but got "InvalidStateError" -FAIL Upgrading a custom element must throw an TypeError when the returned element is not SameValue as the upgraded element assert_equals: expected "TypeError" but got "InvalidStateError" -FAIL Upgrading a custom element whose constructor returns a Text node must throw assert_equals: expected "TypeError" but got "InvalidStateError" -FAIL Upgrading a custom element whose constructor returns an Element must throw assert_equals: expected "TypeError" but got "InvalidStateError" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-alt-crash-001.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-alt-crash-001.html new file mode 100644 index 0000000..b057967 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-alt-crash-001.html
@@ -0,0 +1,15 @@ +<!doctype html> +<title>Crash test: img alt rendering in combination with style attribute selector</title> +<link rel="help" href="https://crbug.com/1057210"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + img { display: block; width: 100px; } + [style] + * {} +</style> +<img id="img" alt="alternative text"> +<script> + test(() => { + assert_equals(getComputedStyle(img).width, "100px"); + }, "Should not crash."); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes-expected.txt b/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes-expected.txt index 4179bfbb..5fb804b 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes-expected.txt +++ b/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 54 tests; 46 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 62 tests; 54 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS We should be in standards mode PASS Subframe should be in quirks mode PASS <table hspace> should not be mapped to style marginLeft in CSS1Compat mode @@ -26,6 +26,14 @@ PASS <iframe border> should not be mapped to style borderBottomWidth in BackCompat mode PASS <iframe border> should not be mapped to style borderLeftWidth in CSS1Compat mode PASS <iframe border> should not be mapped to style borderLeftWidth in BackCompat mode +PASS <iframe hspace> should not be mapped to style marginLeft in CSS1Compat mode +PASS <iframe hspace> should not be mapped to style marginLeft in BackCompat mode +PASS <iframe hspace> should not be mapped to style marginRight in CSS1Compat mode +PASS <iframe hspace> should not be mapped to style marginRight in BackCompat mode +PASS <iframe vspace> should not be mapped to style marginTop in CSS1Compat mode +PASS <iframe vspace> should not be mapped to style marginTop in BackCompat mode +PASS <iframe vspace> should not be mapped to style marginBottom in CSS1Compat mode +PASS <iframe vspace> should not be mapped to style marginBottom in BackCompat mode PASS <marquee border> should not be mapped to style borderTopWidth in CSS1Compat mode PASS <marquee border> should not be mapped to style borderTopWidth in BackCompat mode PASS <marquee border> should not be mapped to style borderRightWidth in CSS1Compat mode
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes.html b/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes.html index 3f457eb..5824f83 100644 --- a/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes.html +++ b/third_party/blink/web_tests/external/wpt/html/rendering/unmapped-attributes.html
@@ -52,6 +52,10 @@ [ newElem("iframe"), "border", "borderRightWidth" ], [ newElem("iframe"), "border", "borderBottomWidth" ], [ newElem("iframe"), "border", "borderLeftWidth" ], + [ newElem("iframe"), "hspace", "marginLeft" ], + [ newElem("iframe"), "hspace", "marginRight" ], + [ newElem("iframe"), "vspace", "marginTop" ], + [ newElem("iframe"), "vspace", "marginBottom" ], [ newElem("marquee"), "border", "borderTopWidth" ], [ newElem("marquee"), "border", "borderRightWidth" ], [ newElem("marquee"), "border", "borderBottomWidth" ],
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-canTrickleIceCandidates-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-canTrickleIceCandidates-expected.txt deleted file mode 100644 index e7d8297..0000000 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-canTrickleIceCandidates-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL canTrickleIceCandidates property is null prior to setRemoteDescription assert_equals: canTrickleIceCandidates property is null expected (object) null but got (undefined) undefined -FAIL canTrickleIceCandidates property is true after setRemoteDescription with a=ice-options:trickle assert_true: canTrickleIceCandidates property is true after setRemoteDescription expected true got undefined -FAIL canTrickleIceCandidates property is false after setRemoteDescription without a=ice-options:trickle assert_false: canTrickleIceCandidates property is false after setRemoteDescription expected false got undefined -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-constructor-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-constructor-expected.txt deleted file mode 100644 index 79341f7..0000000 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-constructor-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -This is a testharness.js-based test. -PASS RTCPeerConnection.length -PASS new RTCPeerConnection() -PASS new RTCPeerConnection(null) -PASS new RTCPeerConnection(undefined) -PASS new RTCPeerConnection({}) -PASS new RTCPeerConnection({ certificates: null }) -PASS new RTCPeerConnection({ certificates: undefined }) -PASS new RTCPeerConnection({ certificates: [] }) -PASS new RTCPeerConnection({ certificates: [null] }) -PASS new RTCPeerConnection({ certificates: [undefined] }) -PASS new RTCPeerConnection({ iceCandidatePoolSize: toNumberThrows }) -PASS localDescription initial value -PASS currentLocalDescription initial value -PASS pendingLocalDescription initial value -PASS remoteDescription initial value -PASS currentRemoteDescription initial value -PASS pendingRemoteDescription initial value -PASS signalingState initial value -PASS iceGatheringState initial value -PASS iceConnectionState initial value -PASS connectionState initial value -FAIL canTrickleIceCandidates initial value assert_equals: expected (object) null but got (undefined) undefined -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt index 482ce5fe..a416ef5 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 496 tests; 472 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 496 tests; 474 PASS, 22 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS idl_test validation PASS Test driver for asyncInitCertificate @@ -38,7 +38,7 @@ PASS RTCPeerConnection interface: attribute iceGatheringState PASS RTCPeerConnection interface: attribute iceConnectionState PASS RTCPeerConnection interface: attribute connectionState -FAIL RTCPeerConnection interface: attribute canTrickleIceCandidates assert_true: The prototype object must have a property "canTrickleIceCandidates" expected true got false +PASS RTCPeerConnection interface: attribute canTrickleIceCandidates PASS RTCPeerConnection interface: operation restartIce() PASS RTCPeerConnection interface: operation getConfiguration() FAIL RTCPeerConnection interface: operation setConfiguration(optional RTCConfiguration) assert_equals: property has wrong .length expected 0 but got 1 @@ -89,7 +89,7 @@ PASS RTCPeerConnection interface: new RTCPeerConnection() must inherit property "iceGatheringState" with the proper type PASS RTCPeerConnection interface: new RTCPeerConnection() must inherit property "iceConnectionState" with the proper type PASS RTCPeerConnection interface: new RTCPeerConnection() must inherit property "connectionState" with the proper type -FAIL RTCPeerConnection interface: new RTCPeerConnection() must inherit property "canTrickleIceCandidates" with the proper type assert_inherits: property "canTrickleIceCandidates" not found in prototype chain +PASS RTCPeerConnection interface: new RTCPeerConnection() must inherit property "canTrickleIceCandidates" with the proper type PASS RTCPeerConnection interface: new RTCPeerConnection() must inherit property "restartIce()" with the proper type PASS RTCPeerConnection interface: new RTCPeerConnection() must inherit property "getConfiguration()" with the proper type PASS RTCPeerConnection interface: new RTCPeerConnection() must inherit property "setConfiguration(optional RTCConfiguration)" with the proper type
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/dynamic-scripts-expected.txt b/third_party/blink/web_tests/http/tests/devtools/startup/dynamic-scripts-expected.txt deleted file mode 100644 index b129381..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/dynamic-scripts-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -Tests that scripts for dynamically added script elements are shown in sources panel if inspector is opened after the scripts were loaded. https://bugs.webkit.org/show_bug.cgi?id=99324 - -UISourceCodes: - dynamic-script.js - dynamic-scripts.html - evalSourceURL.js - scriptElementContentSourceURL.js -
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/dynamic-scripts.js b/third_party/blink/web_tests/http/tests/devtools/startup/dynamic-scripts.js deleted file mode 100644 index 602d8e35..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/dynamic-scripts.js +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - await TestRunner.setupStartupTest('resources/dynamic-scripts.html'); - TestRunner.addResult( - `Tests that scripts for dynamically added script elements are shown in sources panel if inspector is opened after the scripts were loaded. https://bugs.webkit.org/show_bug.cgi?id=99324\n`); - await TestRunner.loadModule('sources_test_runner'); - - SourcesTestRunner.startDebuggerTest(step2); - - function step2() { - TestRunner.deprecatedRunAfterPendingDispatches(step3); - } - - function step3() { - var panel = UI.panels.sources; - var uiSourceCodes = Workspace.workspace.uiSourceCodesForProjectType(Workspace.projectTypes.Network); - var urls = uiSourceCodes.map(function(uiSourceCode) { - return uiSourceCode.name(); - }); - urls.sort(); - - var whiteList = [ - 'dynamic-script.js', 'dynamic-scripts.html', 'evalSourceURL.js', 'scriptElementContentSourceURL.js' - ]; - function filter(url) { - for (var i = 0; i < whiteList.length; ++i) { - if (url.indexOf(whiteList[i]) !== -1) - return true; - } - - return false; - } - urls = urls.filter(filter); - - TestRunner.addResult('UISourceCodes:'); - for (var i = 0; i < urls.length; ++i) - TestRunner.addResult(' ' + urls[i]); - SourcesTestRunner.completeDebuggerTest(); - } -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/main-resource-content-expected.txt b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/main-resource-content-expected.txt deleted file mode 100644 index 2a38b660..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/main-resource-content-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -Tests main resource content is correctly loaded and decoded using correct encoding. - -Requesting content: -Resource url: http://127.0.0.1:8000/devtools/startup/resource-tree/resources/main-resource-content-frame.html -Resource content: <html> -<body> -SUCCESS -</body> -</html> - -Requesting utf8 content: -Resource url: http://127.0.0.1:8000/devtools/startup/resource-tree/resources/main-resource-content-frame-utf8.php -Resource content: <html> -<body> -The following word is written using cyrillic letters and should look like "SUCCESS": SUССЕSS. -</body> -</html> - -
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/main-resource-content.js b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/main-resource-content.js deleted file mode 100644 index 75e2ad4..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/main-resource-content.js +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - await TestRunner.setupStartupTest('resources/main-resource-content.html'); - TestRunner.addResult(`Tests main resource content is correctly loaded and decoded using correct encoding.\n`); - await TestRunner.loadModule('application_test_runner'); - - ApplicationTestRunner.runAfterResourcesAreFinished( - ['main-resource-content-frame-utf8.php', 'main-resource-content-frame.html'], step2); - - async function step2() { - TestRunner.addResult('Requesting content: '); - var resource = ApplicationTestRunner.resourceMatchingURL('main-resource-content-frame.html'); - var content = await TestRunner.PageAgent.getResourceContent(resource.frameId, resource.url); - - TestRunner.assertTrue(!!content, 'No content available.'); - TestRunner.addResult('Resource url: ' + resource.url); - TestRunner.addResult('Resource content: ' + content); - - TestRunner.addResult('Requesting utf8 content: '); - resource = ApplicationTestRunner.resourceMatchingURL('main-resource-content-frame-utf8.php'); - content = await TestRunner.PageAgent.getResourceContent(resource.frameId, resource.url); - - TestRunner.assertTrue(!!content, 'No content available.'); - TestRunner.addResult('Resource url: ' + resource.url); - TestRunner.addResult('Resource content: ' + content); - TestRunner.completeTest(); - } -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resource-tree-mimetype-expected.txt b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resource-tree-mimetype-expected.txt deleted file mode 100644 index 9d8ac30..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resource-tree-mimetype-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -Tests that resources panel correctly shows mime type when it loads data from memory cache. https://bugs.webkit.org/show_bug.cgi?id=63701 - -image text/html http://127.0.0.1:8000/devtools/devtools/resource-tree/resources/empty.png -stylesheet text/html http://127.0.0.1:8000/devtools/devtools/resource-tree/resources/styles-initial.css -document text/html http://127.0.0.1:8000/devtools/startup/resource-tree/resources/resource-tree-mimetype.html -
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resource-tree-mimetype.js b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resource-tree-mimetype.js deleted file mode 100644 index 90e2508..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resource-tree-mimetype.js +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - await TestRunner.setupStartupTest('resources/resource-tree-mimetype.html'); - TestRunner.addResult( - `Tests that resources panel correctly shows mime type when it loads data from memory cache. https://bugs.webkit.org/show_bug.cgi?id=63701\n`); - await TestRunner.loadModule('application_test_runner'); - - function format(resource) { - return resource.resourceType().name() + ' ' + resource.mimeType + ' ' + resource.url; - } - - ApplicationTestRunner.dumpResources(format); - TestRunner.completeTest(); -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content-frame-utf8.php b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content-frame-utf8.php deleted file mode 100644 index fa6ed63a..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content-frame-utf8.php +++ /dev/null
@@ -1,8 +0,0 @@ -<? -header('Content-Type: text/html; charset=utf-8'); -?> -<html> -<body> -The following word is written using cyrillic letters and should look like "SUCCESS": SUССЕSS. -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content-frame.html b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content-frame.html deleted file mode 100644 index 8e47a386..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content-frame.html +++ /dev/null
@@ -1,5 +0,0 @@ -<html> -<body> -SUCCESS -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content.html b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content.html deleted file mode 100644 index 3545de5a..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/main-resource-content.html +++ /dev/null
@@ -1,4 +0,0 @@ -<body onload="testRunner.inspectSecondaryWindow()"> -<iframe src="main-resource-content-frame.html"></iframe> -<iframe src="main-resource-content-frame-utf8.php"></iframe> -</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/resource-tree-mimetype.html b/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/resource-tree-mimetype.html deleted file mode 100644 index e2cf16a..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resource-tree/resources/resource-tree-mimetype.html +++ /dev/null
@@ -1,21 +0,0 @@ -<html> -<head> -<link rel="stylesheet" href="../../../devtools/resource-tree/resources/styles-initial.css"> -<script> -function onload() -{ - // This test enumerates all resources currently registered, potentially - // including ones no longer reachable, but not yet garbage collected - // and finalized. - // - // To ensure stable test output, perform a GC right here to flush out - // the finalizable resources. - gc(); - testRunner.inspectSecondaryWindow(); -} -</script> -</head> -<body onload="onload()"> -<img src="../../../devtools/resource-tree/resources/empty.png"> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resources/dynamic-script.js b/third_party/blink/web_tests/http/tests/devtools/startup/resources/dynamic-script.js deleted file mode 100644 index fb9fb81..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resources/dynamic-script.js +++ /dev/null
@@ -1,5 +0,0 @@ -function fooDynamicScript() -{ -} - -scriptLoaded();
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/resources/dynamic-scripts.html b/third_party/blink/web_tests/http/tests/devtools/startup/resources/dynamic-scripts.html deleted file mode 100644 index 9d77cc89..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/resources/dynamic-scripts.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> -<html> -<head> -<script> -function appendDynamicScriptElement(src, content) -{ - var scriptElement = document.createElement("script"); - if (src) - scriptElement.src = src; - else - scriptElement.textContent = content; - document.head.appendChild(scriptElement); -} - -function loadScripts() -{ - var sourceURLComment = "\n //# sourceURL="; - window.eval("function fooEval() {}"); - window.eval("function fooEvalSourceURL() {}" + sourceURLComment + "evalSourceURL.js"); - appendDynamicScriptElement("", "function fooScriptElementContent1() {}"); - appendDynamicScriptElement("", "function fooScriptElementContent2() {}"); - appendDynamicScriptElement("", "function fooScriptElementContentSourceURL() {}" + sourceURLComment + "scriptElementContentSourceURL.js"); - appendDynamicScriptElement("dynamic-script.js"); -} - -function scriptLoaded() -{ - testRunner.inspectSecondaryWindow(); -} -</script> -</head> -<body onload="loadScripts()"> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/linkifier-expected.txt b/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/linkifier-expected.txt deleted file mode 100644 index 469c415..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/linkifier-expected.txt +++ /dev/null
@@ -1,31 +0,0 @@ -Tests that Linkifier works correctly. - -listeners added on raw source code: 1 -original location: linkifier.html:9 -pretty printed location: linkifier.html:formatted:11 -pretty printed content: -<html> - <head> - <script> - // It is important that script starts on line 5 (zero-based 4) - function nonFormattedFunction() { - var i = 2 + 2; - var a = 4; - return a + i; - } - - function dummyScript() { - console.log("dummy string"); - } - - function onload() { - testRunner.inspectSecondaryWindow(); - } - </script> - </head> - <body onload="onload()"></body> -</html> - -reverted location: linkifier.html:9 -listeners removed from raw source code: 1 -
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/linkifier.js b/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/linkifier.js deleted file mode 100644 index 937b1c5..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/linkifier.js +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - await TestRunner.setupStartupTest('resources/linkifier.html'); - TestRunner.addResult(`Tests that Linkifier works correctly.\n`); - await TestRunner.loadModule('sources_test_runner'); - await TestRunner.showPanel('sources'); - - var resourceURL = TestRunner.url('resources/linkifier.html'); - - var scriptFormatter; - var linkifier; - var link; - var script; - var uiSourceCode; - - SourcesTestRunner.scriptFormatter().then(startDebuggerTest); - - function startDebuggerTest(sf) { - scriptFormatter = sf; - SourcesTestRunner.startDebuggerTest(waitForScripts); - } - - function waitForScripts() { - SourcesTestRunner.showScriptSource('linkifier.html', debuggerTest); - } - - async function debuggerTest() { - for (var scriptCandidate of TestRunner.debuggerModel.scripts()) { - if (scriptCandidate.sourceURL === resourceURL && scriptCandidate.lineOffset === 4) { - script = scriptCandidate; - break; - } - } - - uiSourceCode = Workspace.workspace.uiSourceCodeForURL(resourceURL); - - linkifier = new Components.Linkifier(); - var count1 = liveLocationsCount(); - link = linkifier.linkifyScriptLocation( - SDK.targetManager.mainTarget(), null, resourceURL, 8, 0, 'dummy-class'); - // The script location in the link is a live location that may be unresolved. - await TestRunner.waitForPendingLiveLocationUpdates(); - var count2 = liveLocationsCount(); - - TestRunner.addResult('listeners added on raw source code: ' + (count2 - count1)); - TestRunner.addResult('original location: ' + link.textContent); - TestRunner.addSniffer(Sources.ScriptFormatterEditorAction.prototype, '_updateButton', uiSourceCodeScriptFormatted); - scriptFormatter._toggleFormatScriptSource(); - } - - async function uiSourceCodeScriptFormatted() { - TestRunner.addResult('pretty printed location: ' + link.textContent); - var formattedContent = (await Formatter.sourceFormatter._formattedSourceCodes.get(uiSourceCode).formatData.formattedSourceCode.requestContent()).content; - TestRunner.addResult('pretty printed content:'); - TestRunner.addResult(formattedContent); - await Formatter.sourceFormatter.discardFormattedUISourceCode(UI.panels.sources.visibleView.uiSourceCode()); - await TestRunner.waitForPendingLiveLocationUpdates(); - TestRunner.addResult('reverted location: ' + link.textContent); - - var count1 = liveLocationsCount(); - linkifier.reset(); - var count2 = liveLocationsCount(); - - TestRunner.addResult('listeners removed from raw source code: ' + (count1 - count2)); - - SourcesTestRunner.completeDebuggerTest(); - } - - function liveLocationsCount() { - var modelData = Bindings.debuggerWorkspaceBinding._debuggerModelToData.get(script.debuggerModel); - var locations = modelData._locations.get(script); - return locations.size; - } -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/resources/linkifier.html b/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/resources/linkifier.html deleted file mode 100644 index 024b7667..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/resources/linkifier.html +++ /dev/null
@@ -1,20 +0,0 @@ -<html> -<head> - - -<script>// It is important that script starts on line 5 (zero-based 4) -function nonFormattedFunction() { var i = 2 + 2; var a = 4; return a + i; } - -function dummyScript() -{ - console.log("dummy string"); -} - -function onload() -{ - testRunner.inspectSecondaryWindow(); -} -</script> -</head> -<body onload="onload()"></body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/resources/script-formatter-breakpoints-inline-with-sourceURL.html b/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/resources/script-formatter-breakpoints-inline-with-sourceURL.html deleted file mode 100644 index 15e45b7..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/resources/script-formatter-breakpoints-inline-with-sourceURL.html +++ /dev/null
@@ -1,19 +0,0 @@ -<html> -<head> -<script> - function functionInInlineScriptWithSourceURL() { - - - console.log("Hello!"); - - let x = 10; - - return x; - - } -//# sourceURL=named-inline-script.js -</script> -</head> -<body onload="testRunner.inspectSecondaryWindow()"> -</body> -</html>
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-inline-with-sourceURL-expected.txt b/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-inline-with-sourceURL-expected.txt deleted file mode 100644 index c05ee21..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-inline-with-sourceURL-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -Tests the script formatting is working with breakpoints for inline scripts with #sourceURL=. - - -Running: testSetup - -Running: testBreakpointsInOriginalAndFormattedSource -Script execution paused. -Breakpoint sidebar pane while paused in raw -named-inline-script.js:5checked breakpoint hit console.log("Hello!"); -Script execution resumed. -Script execution paused. -Breakpoint sidebar pane while paused in pretty printed -named-inline-script.js:formatted:3checked breakpoint hit console.log("Hello!"); -Breakpoint sidebar pane while paused after removing breakpoint in pretty printed and closing pretty printed -No breakpoints -Breakpoint sidebar pane while paused in original script again -named-inline-script.js:5checked breakpoint hit console.log("Hello!"); -Script execution resumed. -
diff --git a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-inline-with-sourceURL.js b/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-inline-with-sourceURL.js deleted file mode 100644 index d63a2b38..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/startup/sources/debugger/script-formatter-breakpoints-inline-with-sourceURL.js +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - await TestRunner.setupStartupTest('resources/script-formatter-breakpoints-inline-with-sourceURL.html'); - TestRunner.addResult(`Tests the script formatting is working with breakpoints for inline scripts with #sourceURL=.\n`); - await TestRunner.loadModule('sources_test_runner'); - await TestRunner.showPanel('sources'); - - Bindings.breakpointManager._storage._breakpoints = new Map(); - let panel = UI.panels.sources; - let scriptFormatter; - let sourceFrame; - let formattedSourceFrame; - - SourcesTestRunner.runDebuggerTestSuite([ - function testSetup(next) { - SourcesTestRunner.scriptFormatter().then(function(sf) { - scriptFormatter = sf; - next(); - }); - }, - - async function testBreakpointsInOriginalAndFormattedSource(next) { - SourcesTestRunner.showScriptSource('named-inline-script.js', didShowScriptSource); - - async function didShowScriptSource(frame) { - sourceFrame = frame; - await SourcesTestRunner.setBreakpoint(sourceFrame, 4, '', true); // Lines here are zero based. - Promise.all([SourcesTestRunner.waitBreakpointSidebarPane(true), SourcesTestRunner.waitUntilPausedPromise()]) - .then(pausedInFunctionInInlineScriptWithSourceURL); - TestRunner.evaluateInPageWithTimeout('functionInInlineScriptWithSourceURL()'); - } - - function pausedInFunctionInInlineScriptWithSourceURL(callFrames) { - SourcesTestRunner.dumpBreakpointSidebarPane('while paused in raw'); - SourcesTestRunner.resumeExecution(resumed); - } - - function resumed() { - TestRunner.addSniffer( - Sources.ScriptFormatterEditorAction.prototype, '_updateButton', uiSourceCodeScriptFormatted); - scriptFormatter._toggleFormatScriptSource(); - } - - function uiSourceCodeScriptFormatted() { - // There should be a breakpoint in functionInInlineScriptWithSourceURL although script is pretty-printed. - Promise.all([SourcesTestRunner.waitBreakpointSidebarPane(true), SourcesTestRunner.waitUntilPausedPromise()]) - .then(pausedInFunctionInInlineScriptWithSourceURLAgain); - TestRunner.evaluateInPageWithTimeout('functionInInlineScriptWithSourceURL()'); - } - - function pausedInFunctionInInlineScriptWithSourceURLAgain(callFrames) { - SourcesTestRunner.dumpBreakpointSidebarPane('while paused in pretty printed'); - SourcesTestRunner.showScriptSource('named-inline-script.js:formatted', didShowFormattedScriptSource); - } - - async function didShowFormattedScriptSource(frame) { - formattedSourceFrame = frame; - SourcesTestRunner.removeBreakpoint(formattedSourceFrame, 2); // Lines here are zero based. - await Formatter.sourceFormatter.discardFormattedUISourceCode(formattedSourceFrame.uiSourceCode()); - SourcesTestRunner.waitBreakpointSidebarPane().then(onBreakpointsUpdated); - } - - async function onBreakpointsUpdated() { - SourcesTestRunner.dumpBreakpointSidebarPane('while paused after removing breakpoint in pretty printed and closing pretty printed'); - await SourcesTestRunner.setBreakpoint(sourceFrame, 4, '', true); // Lines here are zero based. - Promise.all([SourcesTestRunner.waitBreakpointSidebarPane(true), SourcesTestRunner.waitUntilPausedPromise()]) - .then(pausedInFunctionInInlineScriptWithSourceURLThirdTime); - TestRunner.evaluateInPageWithTimeout('functionInInlineScriptWithSourceURL()'); - } - - function pausedInFunctionInInlineScriptWithSourceURLThirdTime() { - SourcesTestRunner.dumpBreakpointSidebarPane('while paused in original script again'); - SourcesTestRunner.removeBreakpoint(sourceFrame, 4); // Lines here are zero based. - SourcesTestRunner.resumeExecution(next); - } - } - ]); -})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/user-metrics-perf-expected.txt b/third_party/blink/web_tests/http/tests/devtools/user-metrics-perf-expected.txt deleted file mode 100644 index b17c0e959..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/user-metrics-perf-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -Tests list of user metrics performance codes and invocations. - -recordPanelLoaded: -Performance mark: DevTools.Launch.Console -Performance histogram: DevTools.Launch.Console - positive duration?: true -Performance mark: DevTools.Launch.Elements -Performance histogram: DevTools.Launch.Elements - positive duration?: true -Performance mark: DevTools.Launch.Network -Performance histogram: DevTools.Launch.Network - positive duration?: true -Performance mark: DevTools.Launch.Sources -Performance histogram: DevTools.Launch.Sources - positive duration?: true - -Test that loading the tool only triggers the marker: -Performance mark: DevTools.Launch.Console -Performance mark: DevTools.Launch.Elements -Performance mark: DevTools.Launch.Network -Performance mark: DevTools.Launch.Sources -
diff --git a/third_party/blink/web_tests/http/tests/devtools/user-metrics-perf.js b/third_party/blink/web_tests/http/tests/devtools/user-metrics-perf.js deleted file mode 100644 index f42057d2..0000000 --- a/third_party/blink/web_tests/http/tests/devtools/user-metrics-perf.js +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(async function() { - TestRunner.addResult(`Tests list of user metrics performance codes and invocations.\n`); - - const testHistogramRecording = (panel, histogram, expectHistogram, testExecutor) => { - let recordHistogramComplete; - performance.mark = function(name) { - TestRunner.addResult(`Performance mark: ${name}`); - if (!expectHistogram) - recordHistogramComplete(); - }; - InspectorFrontendHost.recordPerformanceHistogram = function(name, duration) { - TestRunner.addResult(`Performance histogram: ${name} - positive duration?: ${duration > 0}`); - recordHistogramComplete(); - }; - - return new Promise((resolve, reject) => { - Host.userMetrics._firedLaunchHistogram = undefined; - Host.userMetrics.setLaunchPanel(panel); - testExecutor(panel, histogram); - recordHistogramComplete = resolve; - }); - }; - - const testPanelLoaded = (panel, histogram) => - testHistogramRecording(panel, histogram, true, Host.userMetrics.panelLoaded.bind(Host.userMetrics)); - - const testShowView = (panel, histogram) => - testHistogramRecording(panel, histogram, false, UI.viewManager.showView.bind(UI.viewManager)); - - TestRunner.addResult('recordPanelLoaded:'); - await testPanelLoaded('console', 'DevTools.Launch.Console'); - await testPanelLoaded('elements', 'DevTools.Launch.Elements'); - await testPanelLoaded('network', 'DevTools.Launch.Network'); - await testPanelLoaded('sources', 'DevTools.Launch.Sources'); - - TestRunner.addResult('\nTest that loading the tool only triggers the marker:'); - await testShowView('console', 'DevTools.Launch.Console'); - await testShowView('elements', 'DevTools.Launch.Elements'); - await testShowView('network', 'DevTools.Launch.Network'); - await testShowView('sources', 'DevTools.Launch.Sources'); - - TestRunner.completeTest(); -})();
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 3a92de1..0a8da78 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5346,6 +5346,7 @@ interface RTCPeerConnection : EventTarget static method generateCertificate attribute @@toStringTag + getter canTrickleIceCandidates getter connectionState getter currentLocalDescription getter currentRemoteDescription @@ -9182,6 +9183,7 @@ interface webkitRTCPeerConnection : EventTarget static method generateCertificate attribute @@toStringTag + getter canTrickleIceCandidates getter connectionState getter currentLocalDescription getter currentRemoteDescription
diff --git a/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/README.md b/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/README.md new file mode 100644 index 0000000..dd5209b --- /dev/null +++ b/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/README.md
@@ -0,0 +1,15 @@ +# Web Bluetooth New Permissions Backend + +This virtual test suite runs content_shell with +`--enable-features=WebBluetoothNewPermissionsBackend`. This flag enables the +Web Bluetooth tests to use the +[`FakeBluetoothDelegate`](https://source.chromium.org/chromium/chromium/src/+/master:content/shell/browser/web_test/fake_bluetooth_delegate.h) +interface for granting and checking permissions. This class emulates the +behavior of the new Web Bluetooth permissions backend based on +[`ChooserContextBase`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/permissions/chooser_context_base.h). + +The new permissions backend is implemented as part of the [Web Bluetooth +Persistent Permissions project](https://docs.google.com/document/d/1h3uAVXJARHrNWaNACUPiQhLt7XI-fFFQoARSs1WgMDM). + +TODO(https://crbug.com/589228): Remove this virtual test suite when the +`WebBluetoothNewPermissionsBackend` flag is enabled by default. \ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/bluetooth/README.txt b/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/bluetooth/README.txt new file mode 100644 index 0000000..a43806c --- /dev/null +++ b/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/bluetooth/README.txt
@@ -0,0 +1,4 @@ +This directory includes Web Bluetooth tests that use the [out of date Web +Bluetooth test API](https://webbluetoothcg.github.io/web-bluetooth/tests.html) +as well as some tests using the [redesigned test +API](https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY). \ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/README.txt b/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/README.txt new file mode 100644 index 0000000..c49c2d09 --- /dev/null +++ b/third_party/blink/web_tests/virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/README.txt
@@ -0,0 +1,5 @@ +This directory includes Web Bluetooth tests that use the [redesigned Web +Bluetooth test +API](https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY) +and are available in +[web-platform-tests/wpt](https://github.com/web-platform-tests/wpt). \ No newline at end of file
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 cca7abed..e5688dd 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
@@ -6336,6 +6336,7 @@ interface RTCPeerConnection : EventTarget static method generateCertificate attribute @@toStringTag + getter canTrickleIceCandidates getter connectionState getter currentLocalDescription getter currentRemoteDescription @@ -11447,6 +11448,7 @@ interface webkitRTCPeerConnection : EventTarget static method generateCertificate attribute @@toStringTag + getter canTrickleIceCandidates getter connectionState getter currentLocalDescription getter currentRemoteDescription
diff --git a/tools/binary_size/diagnose_bloat.py b/tools/binary_size/diagnose_bloat.py index cfb49ab..881399c 100755 --- a/tools/binary_size/diagnose_bloat.py +++ b/tools/binary_size/diagnose_bloat.py
@@ -334,6 +334,9 @@ gn_args += ' treat_warnings_as_errors=false' # Speed things up a bit by skipping lint & errorprone. gn_args += ' disable_android_lint=true' + # Down from default of 2 to speed up compile and use less disk. + # Compiles need at least symbol_level=1 for pak whitelist to work. + gn_args += ' symbol_level=1' gn_args += ' use_errorprone_java_compiler=false' gn_args += ' use_goma=%s' % str(self.use_goma).lower() gn_args += ' target_os="%s"' % self.target_os
diff --git a/tools/chrome_proxy/webdriver/https_previews.py b/tools/chrome_proxy/webdriver/https_previews.py index d3de090..2cc99ae 100644 --- a/tools/chrome_proxy/webdriver/https_previews.py +++ b/tools/chrome_proxy/webdriver/https_previews.py
@@ -22,7 +22,10 @@ class HttpsPreviews(IntegrationTest): def EnableLitePageServerPreviewsAndInit(self, t): - t.EnableChromeFeature('Previews') + t.AddChromeArg('--force-fieldtrials=Previews/Enabled') + # Skip optimization guide models to trigger lite page redirect preview. + t.AddChromeArg('--force-fieldtrial-params=' + 'Previews.Enabled:override_should_show_preview_check/true') t.EnableChromeFeature('LitePageServerPreviews') # RLH and NoScript may disable use of LitePageRedirect Previews. @@ -34,6 +37,8 @@ t.AddChromeArg('--ignore-previews-blacklist') t.AddChromeArg('--force-effective-connection-type=2G') t.AddChromeArg('--ignore-litepage-redirect-optimization-blacklist') + t.AddChromeArg('--litepage_redirect_overrides_page_hints') + t.SetExperiment('external_chrome_integration_test') # Wait for the server probe to complete before starting the test, otherwise
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 3083dad..0c1c5029 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -1310,6 +1310,7 @@ vals.get('cros_passthrough', False)) is_mac = self.platform == 'darwin' is_msan = 'is_msan=true' in vals['gn_args'] + is_ios = 'target_os="ios"' in vals['gn_args'] err = '' for f in files: @@ -1319,6 +1320,11 @@ if is_android: break + # iOS has generated directories in gn data items. + # Skipping for iOS instead of listing all apps. + if is_ios: + break + # Skip a few existing violations that need to be cleaned up. Each of # these will lead to incorrect incremental builds if their directory # contents change. Do not add to this list.
diff --git a/tools/metrics/histograms/README.md b/tools/metrics/histograms/README.md index 4ad9b88..2ab10eb 100644 --- a/tools/metrics/histograms/README.md +++ b/tools/metrics/histograms/README.md
@@ -261,16 +261,20 @@ You can also easily emit any ratio as a linear histogram (for equally sized buckets). -For such histograms, you should think carefully about _when_ the values are -emitted. Normally, you should emit values periodically at a set time interval, -such as every 5 minutes. Conversely, we strongly discourage emitting values -based on event triggers. For example, we do not recommend recording a ratio -at the end of a video playback. +For such histograms, you want each value recorded to cover approximately +the same span of time. This typically means emitting values periodically +at a set time interval, such as every 5 minutes. We do not recommend +recording a ratio at the end of a video playback, as lengths of videos +vary greatly. -Why? You typically cannot make decisions based on histograms whose values are -recorded in response to an event, because such metrics can conflate heavy usage -with light usage. It's easier to reason about metrics that route around this -source of bias. +It is okay to emit at the end of an animation sequence when what's being +animated is fixed / known. In this case, each value will represent +roughly the same span of time. + +Why? You typically cannot make decisions based on histograms whose +values are recorded in response to an event that varies in length, +because such metrics can conflate heavy usage with light usage. It's +easier to reason about metrics that route around this source of bias. Many developers have been bitten by this. For example, it was previously common to emit an actions-per-minute ratio whenever Chrome was backgrounded.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 3b085c9..24eea7ae 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -8811,6 +8811,25 @@ </summary> </histogram> +<histogram base="true" name="Ash.NavigationWidget.AnimationSmoothness" + units="%" expires_after="M85"> +<!-- Name completed by histogram suffixes + name="HotseatTransitionType" --> + +<!-- Name completed by histogram suffixes + name="NavigationWidgetElement" --> + + <owner>anasalazar@chromium.org</owner> + <owner>newcomer@chromium.org</owner> + <summary> + Relative smoothness of animations of the navigation widget's elements, which + are the widget itself and its child views. 100% represents ideally smooth 60 + frames per second. 50% represents only 30 frames per second is achieved + during the animations. Recorded every time an animation is triggered in the + Navigation Widget. We record this metric for each element separately. + </summary> +</histogram> + <histogram name="Ash.NightLight.AutoNightLightNotificationShown" enum="BooleanShown" expires_after="2020-12-02"> <owner>afakhry@chromium.org</owner> @@ -17266,6 +17285,16 @@ <summary>Image codec inferred during decode.</summary> </histogram> +<histogram name="Blink.EffectiveZoom" units="%" expires_after="2021-03-01"> + <owner>schenney@chromium.org</owner> + <owner>paint-dev@chromium.org</owner> + <summary> + The EffectiveZoom as reported by ComputedStyle in a Blink renderer. The + value is reported each time the effective zoom is set to a new value. The + maximum zoom reported is 400% to keep the histogram of reasonable size. + </summary> +</histogram> + <histogram name="Blink.EventListenerDuration.Resize" units="microseconds" expires_after="2018-01-17"> <obsolete> @@ -102846,9 +102875,6 @@ <histogram name="OAuth2Login.PostMergeVerification" enum="PostMergeVerificationOutcome" expires_after="M78"> - <obsolete> - Removed 2020-02-04 - </obsolete> <owner>tbarzic@chromium.org</owner> <summary> Outcome of Chrome OS GAIA cookie post-merge session verification process. It @@ -102859,9 +102885,6 @@ <histogram name="OAuth2Login.PreMergeVerification" enum="PostMergeVerificationOutcome" expires_after="M78"> - <obsolete> - Removed 2020-02-04 - </obsolete> <owner>tbarzic@chromium.org</owner> <summary> Outcome of Chrome OS GAIA cookie pre-merge session verification process. It @@ -139467,6 +139490,9 @@ <histogram name="Scheduling.Renderer.MainAndImplFrameTimeDelta2" units="microseconds" expires_after="M81"> + <obsolete> + This is no longer usefull and would not be replaced. as of 02/2020 + </obsolete> <owner>vmiura@chromium.org</owner> <owner>sadrul@chromium.org</owner> <summary> @@ -186242,6 +186268,7 @@ label="Transition to the shown hotseat"/> <affected-histogram name="Ash.HotseatTransition.AnimationSmoothness"/> <affected-histogram name="Ash.HotseatWidgetAnimation.AnimationSmoothness"/> + <affected-histogram name="Ash.NavigationWidget.AnimationSmoothness"/> </histogram_suffixes> <histogram_suffixes name="HstsState" separator="."> @@ -188283,6 +188310,14 @@ <affected-histogram name="Navigation.TimeToReadyToCommit2.Subframe"/> </histogram_suffixes> +<histogram_suffixes name="NavigationWidgetElement" separator="." + ordering="prefix,2"> + <suffix name="BackButton" label="Navigation widget's back button"/> + <suffix name="HomeButton" label="Navigation widget's home button"/> + <suffix name="Widget" label="Navigation widget"/> + <affected-histogram name="Ash.NavigationWidget.AnimationSmoothness"/> +</histogram_suffixes> + <histogram_suffixes name="Net.BidirectionalStreamExperiment" separator="."> <suffix name="HTTP2" label="Bidirectional stream that use HTTP2 protocol"/> <owner>mef@chromium.org</owner>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv index 6b561d9..5c5debbb 100644 --- a/tools/perf/benchmark.csv +++ b/tools/perf/benchmark.csv
@@ -59,7 +59,7 @@ system_health.common_mobile,"charliea@chromium.org, sullivan@chromium.org, tdresser@chromium.org, chrome-speed-metrics-dev@chromium.org",Speed>Metrics>SystemHealthRegressions,https://bit.ly/system-health-benchmarks,"2016,2018,2019,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy" system_health.memory_desktop,"pasko@chromium.org, crouleau@chromium.org, chrome-android-perf-status@chromium.org",,https://bit.ly/system-health-benchmarks,"2016,2018,2019,2020,accessibility,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy,keyboard_input,scroll,tabs_switching,webgl" system_health.memory_mobile,"pasko@chromium.org, crouleau@chromium.org, chrome-android-perf-status@chromium.org",,https://bit.ly/system-health-benchmarks,"2016,2018,2019,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy" -system_health.webview_startup,"oksamyt@chromium.org, torne@chromium.org, changwan@chromium.org",Mobile>WebView>Perf,,"2016,health_check" +system_health.webview_startup,"oksamyt@chromium.org, torne@chromium.org, changwan@chromium.org",Mobile>WebView>Perf,,2016 tab_switching.typical_25,vovoy@chromium.org,OS>Performance,,"2016,tabs_switching" tracing.tracing_with_background_memory_infra,ssid@chromium.org,,, tracing_perftests,"kkraynov@chromium.org, primiano@chromium.org",,,
diff --git a/tools/perf/benchmark_schedules.csv b/tools/perf/benchmark_schedules.csv index c5ae105..4b1a856d 100644 --- a/tools/perf/benchmark_schedules.csv +++ b/tools/perf/benchmark_schedules.csv
@@ -3,8 +3,8 @@ benchmark name,total device usage hours per cycle,platforms count (unabridged),platforms count (abridged),platforms where unabridged,platforms where abridged rendering.mobile,8.67,3,0,"Android Nexus5X WebView Perf, android-pixel2-perf, android-pixel2_webview-perf", rendering.desktop,6.89,5,1,"linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",Win 7 Nvidia GPU Perf -system_health.common_mobile,5.00,5,2,"Android Nexus5X WebView Perf, android-go-perf, android-go_webview-perf, android-pixel2-perf, android-pixel2_webview-perf","Android Nexus5 Perf, android-pixel2_weblayer-perf" -system_health.memory_mobile,4.71,5,1,"Android Nexus5X WebView Perf, android-go-perf, android-go_webview-perf, android-pixel2-perf, android-pixel2_webview-perf",android-pixel2_weblayer-perf +system_health.common_mobile,4.63,5,2,"Android Nexus5X WebView Perf, android-go-perf, android-go_webview-perf, android-pixel2-perf, android-pixel2_webview-perf","Android Nexus5 Perf, android-pixel2_weblayer-perf" +system_health.memory_mobile,4.55,5,1,"Android Nexus5X WebView Perf, android-go-perf, android-go_webview-perf, android-pixel2-perf, android-pixel2_webview-perf",android-pixel2_weblayer-perf v8.browsing_mobile,3.87,5,0,"Android Nexus5X WebView Perf, android-go-perf, android-go_webview-perf, android-pixel2-perf, android-pixel2_webview-perf", system_health.common_desktop,3.23,5,0,"linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf", system_health.memory_desktop,2.66,5,0,"linux-perf, mac-10_12_laptop_low_end-perf, mac-10_13_laptop_high_end-perf, win-10-perf, win-10_laptop_low_end-perf",
diff --git a/tools/perf/core/shard_maps/timing_data/android-pixel2_weblayer-perf_timing.json b/tools/perf/core/shard_maps/timing_data/android-pixel2_weblayer-perf_timing.json index 9a3883d..785059c 100644 --- a/tools/perf/core/shard_maps/timing_data/android-pixel2_weblayer-perf_timing.json +++ b/tools/perf/core/shard_maps/timing_data/android-pixel2_weblayer-perf_timing.json
@@ -16,187 +16,27 @@ "name": "startup.mobile/maps_pwa:with_http_cache" }, { - "duration": "23.0", - "name": "system_health.common_mobile/background:media:imgur:2019" - }, - { - "duration": "21.0", - "name": "system_health.common_mobile/background:search:google:2019" - }, - { "duration": "3.0", "name": "system_health.common_mobile/background:tools:gmail:2019" }, { - "duration": "54.0", - "name": "system_health.common_mobile/browse:media:youtube:2019" - }, - { "duration": "49.0", "name": "system_health.common_mobile/browse:news:cnn:2018" }, { - "duration": "35.0", - "name": "system_health.common_mobile/browse:news:qq:2019" - }, - { - "duration": "49.0", - "name": "system_health.common_mobile/browse:shopping:avito:2019" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:chrome:blank" - }, - { - "duration": "19.0", - "name": "system_health.common_mobile/load:games:bubbles:2019" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:games:lazors" - }, - { - "duration": "25.0", - "name": "system_health.common_mobile/load:games:spychase:2018" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:media:google_images:2018" - }, - { - "duration": "22.0", - "name": "system_health.common_mobile/load:media:imgur:2018" - }, - { "duration": "20.0", "name": "system_health.common_mobile/load:media:youtube:2018" }, { - "duration": "21.0", - "name": "system_health.common_mobile/load:news:irctc:2019" - }, - { - "duration": "26.0", - "name": "system_health.common_mobile/load:news:nytimes:2019" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:news:reddit:2019" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:news:washingtonpost:2019" - }, - { - "duration": "21.0", - "name": "system_health.common_mobile/load:search:baidu:2018" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:search:ebay:2018" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:search:taobao:2019" - }, - { - "duration": "19.0", - "name": "system_health.common_mobile/load:tools:docs:2019" - }, - { - "duration": "20.0", - "name": "system_health.common_mobile/load:tools:stackoverflow:2018" - }, - { - "duration": "28.0", - "name": "system_health.memory_mobile/background:media:imgur:2019" - }, - { - "duration": "26.0", - "name": "system_health.memory_mobile/background:search:google:2019" - }, - { "duration": "0.0", "name": "system_health.memory_mobile/background:tools:gmail:2019" }, { - "duration": "57.0", - "name": "system_health.memory_mobile/browse:media:youtube:2019" - }, - { "duration": "52.0", "name": "system_health.memory_mobile/browse:news:cnn:2018" }, { - "duration": "39.0", - "name": "system_health.memory_mobile/browse:news:qq:2019" - }, - { - "duration": "52.0", - "name": "system_health.memory_mobile/browse:shopping:avito:2019" - }, - { - "duration": "24.0", - "name": "system_health.memory_mobile/load:chrome:blank" - }, - { - "duration": "24.0", - "name": "system_health.memory_mobile/load:games:bubbles:2019" - }, - { - "duration": "25.0", - "name": "system_health.memory_mobile/load:games:lazors" - }, - { - "duration": "28.0", - "name": "system_health.memory_mobile/load:games:spychase:2018" - }, - { - "duration": "24.0", - "name": "system_health.memory_mobile/load:media:google_images:2018" - }, - { - "duration": "26.0", - "name": "system_health.memory_mobile/load:media:imgur:2018" - }, - { "duration": "24.0", "name": "system_health.memory_mobile/load:media:youtube:2018" - }, - { - "duration": "25.0", - "name": "system_health.memory_mobile/load:news:irctc:2019" - }, - { - "duration": "29.0", - "name": "system_health.memory_mobile/load:news:nytimes:2019" - }, - { - "duration": "25.0", - "name": "system_health.memory_mobile/load:news:reddit:2019" - }, - { - "duration": "24.0", - "name": "system_health.memory_mobile/load:news:washingtonpost:2019" - }, - { - "duration": "26.0", - "name": "system_health.memory_mobile/load:search:baidu:2018" - }, - { - "duration": "25.0", - "name": "system_health.memory_mobile/load:search:ebay:2018" - }, - { - "duration": "24.0", - "name": "system_health.memory_mobile/load:search:taobao:2019" - }, - { - "duration": "24.0", - "name": "system_health.memory_mobile/load:tools:docs:2019" - }, - { - "duration": "24.0", - "name": "system_health.memory_mobile/load:tools:stackoverflow:2018" } ] \ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/android_nexus5_perf_timing.json b/tools/perf/core/shard_maps/timing_data/android_nexus5_perf_timing.json index 4a45949..f87bd05 100644 --- a/tools/perf/core/shard_maps/timing_data/android_nexus5_perf_timing.json +++ b/tools/perf/core/shard_maps/timing_data/android_nexus5_perf_timing.json
@@ -40,98 +40,18 @@ "name": "startup.mobile/maps_pwa:with_http_cache" }, { - "duration": "43.0", - "name": "system_health.common_mobile/background:media:imgur:2019" - }, - { - "duration": "42.0", - "name": "system_health.common_mobile/background:search:google:2019" - }, - { "duration": "52.0", "name": "system_health.common_mobile/background:tools:gmail:2019" }, { - "duration": "77.0", - "name": "system_health.common_mobile/browse:media:youtube:2019" - }, - { "duration": "135.0", "name": "system_health.common_mobile/browse:news:cnn:2018" }, { - "duration": "55.0", - "name": "system_health.common_mobile/browse:news:qq:2019" - }, - { - "duration": "76.0", - "name": "system_health.common_mobile/browse:shopping:avito:2019" - }, - { - "duration": "33.0", - "name": "system_health.common_mobile/load:chrome:blank" - }, - { - "duration": "31.0", - "name": "system_health.common_mobile/load:games:bubbles:2019" - }, - { - "duration": "34.0", - "name": "system_health.common_mobile/load:games:lazors" - }, - { - "duration": "39.0", - "name": "system_health.common_mobile/load:games:spychase:2018" - }, - { - "duration": "32.0", - "name": "system_health.common_mobile/load:media:google_images:2018" - }, - { - "duration": "39.0", - "name": "system_health.common_mobile/load:media:imgur:2018" - }, - { "duration": "32.0", "name": "system_health.common_mobile/load:media:youtube:2018" }, { - "duration": "41.0", - "name": "system_health.common_mobile/load:news:irctc:2019" - }, - { - "duration": "58.0", - "name": "system_health.common_mobile/load:news:nytimes:2019" - }, - { - "duration": "34.0", - "name": "system_health.common_mobile/load:news:reddit:2019" - }, - { - "duration": "32.0", - "name": "system_health.common_mobile/load:news:washingtonpost:2019" - }, - { - "duration": "42.0", - "name": "system_health.common_mobile/load:search:baidu:2018" - }, - { - "duration": "33.0", - "name": "system_health.common_mobile/load:search:ebay:2018" - }, - { - "duration": "30.0", - "name": "system_health.common_mobile/load:search:taobao:2019" - }, - { - "duration": "30.0", - "name": "system_health.common_mobile/load:tools:docs:2019" - }, - { - "duration": "32.0", - "name": "system_health.common_mobile/load:tools:stackoverflow:2018" - }, - { "duration": "110.0", "name": "components_perftests/_gtest_" },
diff --git a/tools/perf/cycletime_contributions.csv b/tools/perf/cycletime_contributions.csv index 1fa803c..65dc4fd 100644 --- a/tools/perf/cycletime_contributions.csv +++ b/tools/perf/cycletime_contributions.csv
@@ -2,7 +2,7 @@ View a prettier version of this at,https://docs.google.com/spreadsheets/d/15pJY4cxtM2NVNFKQDgDnoT5PLo0Nm5Td-Ov-5PZefAw platform,Android Nexus5 Perf,Android Nexus5X WebView Perf,Win 7 Nvidia GPU Perf,Win 7 Perf,android-go-perf,android-go_webview-perf,android-pixel2-perf,android-pixel2_weblayer-perf,android-pixel2_webview-perf,linux-perf,mac-10_12_laptop_low_end-perf,mac-10_13_laptop_high_end-perf,win-10-perf,win-10_laptop_low_end-perf shards,16,16,4,4,19,13,35,4,21,26,26,26,26,26 -idealized cycle time (hours),0.07,0.47,0.31,0.03,0.40,0.16,0.76,0.11,0.28,0.31,0.44,0.35,0.44,0.71 +idealized cycle time (hours),0.04,0.47,0.31,0.03,0.40,0.16,0.76,0.03,0.28,0.31,0.44,0.35,0.44,0.71 angle_perftests,0.000,0.000,0.276,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.042,0.000 base_perftests,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.006,0.000,0.006,0.006,0.000 blink_perf.accessibility,0.000,0.001,0.000,0.000,0.000,0.000,0.001,0.000,0.001,0.001,0.001,0.001,0.001,0.001 @@ -49,9 +49,9 @@ speedometer2-future,0.000,0.002,0.000,0.000,0.000,0.000,0.001,0.000,0.001,0.001,0.002,0.002,0.001,0.003 startup.mobile,0.019,0.000,0.000,0.000,0.018,0.000,0.059,0.022,0.000,0.000,0.000,0.000,0.000,0.000 system_health.common_desktop,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.042,0.052,0.042,0.045,0.067 -system_health.common_mobile,0.037,0.052,0.000,0.000,0.130,0.078,0.050,0.039,0.028,0.000,0.000,0.000,0.000,0.000 +system_health.common_mobile,0.008,0.052,0.000,0.000,0.130,0.078,0.050,0.005,0.028,0.000,0.000,0.000,0.000,0.000 system_health.memory_desktop,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.030,0.044,0.036,0.040,0.055 -system_health.memory_mobile,0.000,0.048,0.000,0.000,0.129,0.074,0.052,0.045,0.031,0.000,0.000,0.000,0.000,0.000 +system_health.memory_mobile,0.000,0.048,0.000,0.000,0.129,0.074,0.052,0.005,0.031,0.000,0.000,0.000,0.000,0.000 system_health.webview_startup,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000 tab_switching.typical_25,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000 tracing.tracing_with_background_memory_infra,0.000,0.002,0.000,0.000,0.000,0.000,0.002,0.000,0.001,0.002,0.003,0.002,0.003,0.004
diff --git a/tools/perf/page_sets/system_health/background_stories.py b/tools/perf/page_sets/system_health/background_stories.py index 8d351aac..13dedb6 100644 --- a/tools/perf/page_sets/system_health/background_stories.py +++ b/tools/perf/page_sets/system_health/background_stories.py
@@ -31,7 +31,7 @@ class BackgroundGoogleStory2019(_BackgroundStory): NAME = 'background:search:google:2019' URL = 'https://www.google.co.uk/#q=tom+cruise+movies' - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [story_tags.YEAR_2019] def _DidLoadDocument(self, action_runner): # Activte the immersive movie browsing experience @@ -64,7 +64,7 @@ NAME = 'background:media:imgur:2019' URL = 'http://imgur.com/gallery/hUita' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [story_tags.YEAR_2019] class BackgroundGmailMobileStory2019(loading_stories.LoadGmailStory2019):
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py index 8b18004..82195ae80 100644 --- a/tools/perf/page_sets/system_health/browsing_stories.py +++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -133,8 +133,9 @@ URL = 'http://edition.cnn.com/' ITEM_SELECTOR = '.cd__content > h3 > a' ITEMS_TO_VISIT = 2 - TAGS = [story_tags.JAVASCRIPT_HEAVY, story_tags.HEALTH_CHECK, - story_tags.YEAR_2018] + TAGS = [ + story_tags.HEALTH_CHECK, story_tags.JAVASCRIPT_HEAVY, story_tags.YEAR_2018 + ] class FacebookMobileStory2019(_ArticleBrowsingStory): @@ -241,8 +242,7 @@ ITEMS_TO_VISIT = 2 SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.INTERNATIONAL, story_tags.HEALTH_CHECK, - story_tags.YEAR_2019] + TAGS = [story_tags.INTERNATIONAL, story_tags.YEAR_2019] class RedditDesktopStory2018(_ArticleBrowsingStory): @@ -570,8 +570,10 @@ IS_SINGLE_PAGE_APP = True ITEM_SELECTOR_INDEX = 3 ITEMS_TO_VISIT = 8 - TAGS = [story_tags.JAVASCRIPT_HEAVY, story_tags.EMERGING_MARKET, - story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [ + story_tags.JAVASCRIPT_HEAVY, story_tags.EMERGING_MARKET, + story_tags.YEAR_2019 + ] class YouTubeDesktopStory2019(_MediaBrowsingStory): @@ -854,8 +856,7 @@ NAME = 'browse:shopping:avito:2019' URL = 'https://www.avito.ru/rossiya' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.EMERGING_MARKET, story_tags.HEALTH_CHECK, - story_tags.YEAR_2019] + TAGS = [story_tags.EMERGING_MARKET, story_tags.YEAR_2019] ITEM_SELECTOR = '._3eXe2' ITEMS_TO_VISIT = 4
diff --git a/tools/perf/page_sets/system_health/chrome_stories.py b/tools/perf/page_sets/system_health/chrome_stories.py index 8adc534..2596a42 100644 --- a/tools/perf/page_sets/system_health/chrome_stories.py +++ b/tools/perf/page_sets/system_health/chrome_stories.py
@@ -13,7 +13,7 @@ """Story that loads the about:blank page.""" NAME = 'load:chrome:blank' URL = 'about:blank' - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2016] + TAGS = [story_tags.YEAR_2016] def _DidLoadDocument(self, action_runner): # Request a RAF and wait for it to be processed to ensure that the metric
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py index 73e864f1..1e6cde0 100644 --- a/tools/perf/page_sets/system_health/loading_stories.py +++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -46,8 +46,7 @@ class LoadBaiduStory2018(_LoadingStory): NAME = 'load:search:baidu:2018' URL = 'https://www.baidu.com/s?word=google' - TAGS = [story_tags.INTERNATIONAL, story_tags.HEALTH_CHECK, - story_tags.YEAR_2018] + TAGS = [story_tags.INTERNATIONAL, story_tags.YEAR_2018] class LoadYahooStory2018(_LoadingStory): @@ -89,8 +88,7 @@ NAME = 'load:search:taobao:2019' URL = 'http://m.intl.taobao.com/' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.INTERNATIONAL, story_tags.HEALTH_CHECK, - story_tags.YEAR_2019] + TAGS = [story_tags.INTERNATIONAL, story_tags.YEAR_2019] class LoadYandexStory2018(_LoadingStory): @@ -102,7 +100,7 @@ class LoadEbayStory2018(_LoadingStory): NAME = 'load:search:ebay:2018' URL = 'https://www.ebay.com/sch/i.html?_nkw=headphones' - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2018] + TAGS = [story_tags.YEAR_2018] ################################################################################ @@ -201,7 +199,7 @@ NAME = 'load:news:nytimes:2019' URL = 'http://mobile.nytimes.com' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [story_tags.YEAR_2019] class LoadQqMobileStory2019(_LoadingStory): @@ -229,14 +227,14 @@ NAME = 'load:news:reddit:2019' URL = 'https://www.reddit.com/r/news/top/?sort=top&t=week' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [story_tags.YEAR_2019] class LoadWashingtonPostMobileStory2019(_LoadingStory): NAME = 'load:news:washingtonpost:2019' URL = 'https://www.washingtonpost.com/pwa' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [story_tags.YEAR_2019] _CONTINUE_FREE_BUTTON_SELECTOR = '.continue-btn.button.free' _ACCEPT_GDPR_SELECTOR = '.agree-ckb' _CONTINUE_TO_SITE_SELECTOR = '.continue-btn.button.accept-consent' @@ -269,8 +267,7 @@ NAME = 'load:news:irctc:2019' URL = 'https://www.irctc.co.in' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY - TAGS = [story_tags.EMERGING_MARKET, story_tags.HEALTH_CHECK, - story_tags.YEAR_2019] + TAGS = [story_tags.EMERGING_MARKET, story_tags.YEAR_2019] def _Login(self, action_runner): # There is an error on replay that pops up the first time. If we @@ -288,8 +285,9 @@ # No way to disable autoplay on desktop. NAME = 'load:media:youtube:2018' URL = 'https://www.youtube.com/watch?v=QGfhS1hfTWw&autoplay=false' - TAGS = [story_tags.EMERGING_MARKET, story_tags.HEALTH_CHECK, - story_tags.YEAR_2018] + TAGS = [ + story_tags.HEALTH_CHECK, story_tags.EMERGING_MARKET, story_tags.YEAR_2018 + ] class LoadDailymotionStory2019(_LoadingStory): @@ -301,7 +299,7 @@ class LoadGoogleImagesStory2018(_LoadingStory): NAME = 'load:media:google_images:2018' URL = 'https://www.google.co.uk/search?tbm=isch&q=love' - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2018] + TAGS = [story_tags.YEAR_2018] class LoadSoundCloudStory2018(_LoadingStory): @@ -321,7 +319,7 @@ class LoadImgurStory2018(_LoadingStory): NAME = 'load:media:imgur:2018' URL = 'http://imgur.com/gallery/5UlBN' - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2018] + TAGS = [story_tags.YEAR_2018] class LoadFlickrStory2018(_LoadingStory): @@ -358,7 +356,7 @@ NAME = 'load:tools:docs:2019' URL = ( 'https://docs.google.com/document/d/1GvzDP-tTLmJ0myRhUAfTYWs3ZUFilUICg8psNHyccwQ/edit?usp=sharing') - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [story_tags.YEAR_2019] class _LoadGmailBaseStory(_LoadingStory): @@ -422,7 +420,7 @@ NAME = 'load:tools:stackoverflow:2018' URL = ( 'https://stackoverflow.com/questions/36827659/compiling-an-application-for-use-in-highly-radioactive-environments') - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2018] + TAGS = [story_tags.YEAR_2018] class LoadDropboxStory2019(_LoadingStory): @@ -464,21 +462,21 @@ NAME = 'load:games:bubbles:2019' URL = ( 'https://games.cdn.famobi.com/html5games/s/smarty-bubbles/v010/?fg_domain=play.famobi.com&fg_uid=d8f24956-dc91-4902-9096-a46cb1353b6f&fg_pid=4638e320-4444-4514-81c4-d80a8c662371&fg_beat=620') - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2019] + TAGS = [story_tags.YEAR_2019] class LoadLazorsStory(_LoadingStory): NAME = 'load:games:lazors' # Using "https://" hangs and shows "This site can't be reached". URL = 'http://www8.games.mobi/games/html5/lazors/lazors.html' - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2016] + TAGS = [story_tags.YEAR_2016] class LoadSpyChaseStory2018(_LoadingStory): NAME = 'load:games:spychase:2018' # Using "https://" shows "Your connection is not private". URL = 'http://playstar.mobi/games/spychase/index.php' - TAGS = [story_tags.HEALTH_CHECK, story_tags.YEAR_2018] + TAGS = [story_tags.YEAR_2018] def _DidLoadDocument(self, action_runner): # The background of the game canvas is set when the "Tap screen to play"
diff --git a/tools/perf/system_health_stories.csv b/tools/perf/system_health_stories.csv index b880f96..1024a46 100644 --- a/tools/perf/system_health_stories.csv +++ b/tools/perf/system_health_stories.csv
@@ -1,9 +1,9 @@ AUTOGENERATED FILE DO NOT EDIT See //tools/perf/core/perf_data_generator.py to make changes Story,Description,Platforms,Tags -background:media:imgur:2019,,mobile,"2019,health_check" +background:media:imgur:2019,,mobile,2019 background:news:nytimes:2019,,mobile,"2019,javascript_heavy" -background:search:google:2019,,mobile,"2019,health_check" +background:search:google:2019,,mobile,2019 background:social:facebook:2019,,mobile,"2019,health_check" background:tools:gmail:2019,,mobile,"2019,health_check" browse:chrome:newtab:2019,Story that loads new tab page and performs searches.,mobile,"2019,emerging_market" @@ -16,7 +16,7 @@ browse:media:imgur:2019,,mobile,"2019,emerging_market" browse:media:pinterest:2018,,desktop,2018 browse:media:tumblr:2018,,desktop,2018 -browse:media:youtube:2019,Load a typical YouTube video then navigate to a next few videos. Stop and,"desktop,mobile","2019,emerging_market,health_check,javascript_heavy" +browse:media:youtube:2019,Load a typical YouTube video then navigate to a next few videos. Stop and,"desktop,mobile","2019,emerging_market,javascript_heavy" browse:media:youtubetv:2019,Load a typical YouTube TV video then navigate to a next few videos. Stop,desktop,2019 browse:news:cnn:2018,The second top website in http://www.alexa.com/topsites/category/News,"desktop,mobile","2018,health_check,javascript_heavy" browse:news:cricbuzz:2019,,mobile,"2019,emerging_market" @@ -25,7 +25,7 @@ browse:news:hackernews:2018,,desktop,2018 browse:news:nytimes:2018,The third top website in http://www.alexa.com/topsites/category/News,desktop,2018 browse:news:nytimes:2019,The third top website in http://www.alexa.com/topsites/category/News,mobile,2019 -browse:news:qq:2019,,mobile,"2019,health_check,international" +browse:news:qq:2019,,mobile,"2019,international" browse:news:reddit:2018,The top website in http://www.alexa.com/topsites/category/News,desktop,2018 browse:news:reddit:2019,,mobile,"2019,health_check" browse:news:toi:2019,,mobile,"2019,emerging_market" @@ -35,7 +35,7 @@ browse:search:google:2018,A typical google search story:,desktop,2018 browse:search:google_india:2018,A typical google search story in India:,desktop,"2018,international" browse:shopping:amazon:2019,,mobile,"2019,emerging_market" -browse:shopping:avito:2019,,mobile,"2019,emerging_market,health_check" +browse:shopping:avito:2019,,mobile,"2019,emerging_market" browse:shopping:flipkart:2019,,mobile,"2019,emerging_market" browse:shopping:lazada:2019,,mobile,"2019,emerging_market" browse:social:facebook:2019,,mobile,"2019,emerging_market" @@ -52,19 +52,19 @@ browse:tools:sheets:2019,,desktop,"2019,health_check,javascript_heavy" browse_accessibility:media:youtube,Tests interacting with the YouTube home page.,desktop,"2016,accessibility,keyboard_input" browse_accessibility:tech:codesearch:2018,Tests scrolling an element within a page.,desktop,"2018,accessibility,scroll" -load:chrome:blank,Story that loads the about:blank page.,"desktop,mobile","2016,health_check" +load:chrome:blank,Story that loads the about:blank page.,"desktop,mobile",2016 load:games:alphabetty:2018,,desktop,2018 -load:games:bubbles:2019,"Load ""smarty bubbles"" game on famobi.com","desktop,mobile","2019,health_check" -load:games:lazors,,"desktop,mobile","2016,health_check" +load:games:bubbles:2019,"Load ""smarty bubbles"" game on famobi.com","desktop,mobile",2019 +load:games:lazors,,"desktop,mobile",2016 load:games:miniclip:2018,,desktop,2018 -load:games:spychase:2018,,"desktop,mobile","2018,health_check" +load:games:spychase:2018,,"desktop,mobile",2018 load:media:9gag,,desktop,2016 load:media:dailymotion:2019,,"desktop,mobile",2019 load:media:facebook_photos:2018,Load a page of rihanna's facebook with a photo.,desktop,2018 load:media:facebook_photos:2019,Load a page of rihanna's facebook with a photo.,mobile,"2019,emerging_market" load:media:flickr:2018,,"desktop,mobile",2018 -load:media:google_images:2018,,"desktop,mobile","2018,health_check" -load:media:imgur:2018,,"desktop,mobile","2018,health_check" +load:media:google_images:2018,,"desktop,mobile",2018 +load:media:imgur:2018,,"desktop,mobile",2018 load:media:soundcloud:2018,,"desktop,mobile",2018 load:media:youtube:2018,,"desktop,mobile","2018,emerging_market,health_check" load:news:bbc:2018,,desktop,2018 @@ -72,23 +72,23 @@ load:news:cnn:2018,,"desktop,mobile","2018,health_check,javascript_heavy" load:news:flipboard,,desktop,2016 load:news:hackernews:2018,,desktop,2018 -load:news:irctc:2019,,mobile,"2019,emerging_market,health_check" +load:news:irctc:2019,,mobile,"2019,emerging_market" load:news:nytimes:2018,,desktop,2018 -load:news:nytimes:2019,,mobile,"2019,health_check" +load:news:nytimes:2019,,mobile,2019 load:news:qq:2018,,desktop,"2018,international" load:news:qq:2019,,mobile,"2019,international" load:news:reddit:2018,,desktop,2018 -load:news:reddit:2019,,mobile,"2019,health_check" -load:news:washingtonpost:2019,,mobile,"2019,health_check" +load:news:reddit:2019,,mobile,2019 +load:news:washingtonpost:2019,,mobile,2019 load:news:wikipedia:2018,,"desktop,mobile","2018,emerging_market" load:search:amazon:2018,,desktop,2018 load:search:amazon:2019,,mobile,2019 -load:search:baidu:2018,,"desktop,mobile","2018,health_check,international" -load:search:ebay:2018,,"desktop,mobile","2018,health_check" +load:search:baidu:2018,,"desktop,mobile","2018,international" +load:search:ebay:2018,,"desktop,mobile",2018 load:search:flipkart:2018,,desktop,"2018,international" load:search:google:2018,,"desktop,mobile",2018 load:search:taobao:2018,,desktop,"2018,international" -load:search:taobao:2019,,mobile,"2019,health_check,international" +load:search:taobao:2019,,mobile,"2019,international" load:search:yahoo:2018,,"desktop,mobile",2018 load:search:yandex:2018,,"desktop,mobile","2018,international" load:social:instagram:2018,,desktop,"2018,health_check" @@ -97,11 +97,11 @@ load:social:twitter:2019,,mobile,2019 load:social:vk:2018,,desktop,"2018,health_check,international" load:tools:chat:2020,,desktop,2020 -load:tools:docs:2019,Load a typical google doc page (2019).,"desktop,mobile","2019,health_check" +load:tools:docs:2019,Load a typical google doc page (2019).,"desktop,mobile",2019 load:tools:drive:2019,,"desktop,mobile","2019,javascript_heavy" load:tools:dropbox:2019,,mobile,2019 load:tools:gmail:2019,,"desktop,mobile","2019,health_check" -load:tools:stackoverflow:2018,Load a typical question & answer page of stackoverflow.com,"desktop,mobile","2018,health_check" +load:tools:stackoverflow:2018,Load a typical question & answer page of stackoverflow.com,"desktop,mobile",2018 load:tools:weather:2019,,"desktop,mobile","2019,health_check,javascript_heavy" load_accessibility:media:wikipedia:2018,"Wikipedia page on Accessibility. Long, but very simple, clean layout.",desktop,"2018,accessibility" load_accessibility:shopping:amazon:2018,Amazon results page. Good example of a site with a data table.,desktop,"2018,accessibility"
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index 23db1a1..0956f07 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -181,9 +181,6 @@ : client_(client), input_handler_(input_handler), synchronous_input_handler_(nullptr), -#if DCHECK_IS_ON() - expect_scroll_update_end_(false), -#endif gesture_scroll_on_impl_thread_(false), scroll_sequence_ignored_(false), touch_result_(kEventDispositionUndefined), @@ -810,9 +807,6 @@ if (scroll_predictor_) scroll_predictor_->ResetOnGestureScrollBegin(gesture_event); -#if DCHECK_IS_ON() - expect_scroll_update_end_ = true; -#endif cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event); cc::InputHandler::ScrollStatus scroll_status; cc::ElementIdType element_id_type = @@ -876,10 +870,6 @@ -gesture_event.data.scroll_update.delta_x, "dy", -gesture_event.data.scroll_update.delta_y); -#if DCHECK_IS_ON() - DCHECK(expect_scroll_update_end_); -#endif - if (scroll_sequence_ignored_) { TRACE_EVENT_INSTANT0("input", "Scroll Sequence Ignored", TRACE_EVENT_SCOPE_THREAD); @@ -898,9 +888,6 @@ if (snap_fling_controller_->HandleGestureScrollUpdate( GetGestureScrollUpdateInfo(gesture_event))) { -#if DCHECK_IS_ON() - expect_scroll_update_end_ = false; -#endif gesture_scroll_on_impl_thread_ = false; return DROP_EVENT; } @@ -938,11 +925,6 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollEnd( const WebGestureEvent& gesture_event) { TRACE_EVENT0("input", "InputHandlerProxy::HandleGestureScrollEnd"); -#if DCHECK_IS_ON() - DCHECK(expect_scroll_update_end_); - expect_scroll_update_end_ = false; -#endif - if (scroll_sequence_ignored_) return DROP_EVENT;
diff --git a/ui/events/blink/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h index 8944072..585ed7028 100644 --- a/ui/events/blink/input_handler_proxy.h +++ b/ui/events/blink/input_handler_proxy.h
@@ -187,9 +187,6 @@ SynchronousInputHandler* synchronous_input_handler_; -#if DCHECK_IS_ON() - bool expect_scroll_update_end_; -#endif bool gesture_scroll_on_impl_thread_; bool gesture_pinch_in_progress_ = false; bool in_inertial_scrolling_ = false;
diff --git a/ui/gfx/transform_util.cc b/ui/gfx/transform_util.cc index 97d58b5..4f2cd39 100644 --- a/ui/gfx/transform_util.cc +++ b/ui/gfx/transform_util.cc
@@ -576,7 +576,7 @@ } Transform TransformBetweenRects(const RectF& src, const RectF& dst) { - DCHECK(!src.IsEmpty() && !dst.IsEmpty()); + DCHECK(!src.IsEmpty()); Transform result; result.Translate(dst.origin() - src.origin()); result.Scale(dst.width() / src.width(), dst.height() / src.height());
diff --git a/ui/gfx/transform_util_unittest.cc b/ui/gfx/transform_util_unittest.cc index 66b6e2f4..5a524d9 100644 --- a/ui/gfx/transform_util_unittest.cc +++ b/ui/gfx/transform_util_unittest.cc
@@ -343,6 +343,9 @@ verify(test_case.first, test_case.second); verify(test_case.second, test_case.first); } + + // Tests the case where the destination is an empty rectangle. + verify(RectF(0.f, 0.f, 3.f, 5.f), RectF()); } } // namespace
diff --git a/ui/native_theme/native_theme.cc b/ui/native_theme/native_theme.cc index 8fb4f241..5049f5bb 100644 --- a/ui/native_theme/native_theme.cc +++ b/ui/native_theme/native_theme.cc
@@ -119,7 +119,6 @@ bool NativeTheme::UpdateSystemColorInfo( bool is_dark_mode, bool is_high_contrast, - PreferredColorScheme preferred_color_scheme, const base::flat_map<SystemThemeColor, uint32_t>& colors) { bool did_system_color_info_change = false; if (is_dark_mode != ShouldUseDarkColors()) { @@ -130,10 +129,6 @@ did_system_color_info_change = true; set_high_contrast(is_high_contrast); } - if (preferred_color_scheme != GetPreferredColorScheme()) { - did_system_color_info_change = true; - set_preferred_color_scheme(preferred_color_scheme); - } for (const auto& color : colors) { if (color.second != GetSystemThemeColor(color.first)) { did_system_color_info_change = true;
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h index 832585d..374bf1f 100644 --- a/ui/native_theme/native_theme.h +++ b/ui/native_theme/native_theme.h
@@ -525,7 +525,6 @@ bool UpdateSystemColorInfo( bool is_dark_mode, bool is_high_contrast, - PreferredColorScheme preferred_color_scheme, const base::flat_map<SystemThemeColor, uint32_t>& colors); protected:
diff --git a/ui/views/animation/bounds_animator.cc b/ui/views/animation/bounds_animator.cc index 87fd3ccb..9959a35 100644 --- a/ui/views/animation/bounds_animator.cc +++ b/ui/views/animation/bounds_animator.cc
@@ -59,7 +59,7 @@ data.animation = CreateAnimation(); data.delegate = std::move(delegate); - if (use_transforms_) { + if (use_transforms_ && !data.start_bounds.IsEmpty()) { // Calculate the target transform. Note that we don't reset the transform if // there already was one, otherwise users will end up with visual bounds // different than what they set. @@ -222,7 +222,7 @@ // Save the data for later clean up. Data data = RemoveFromMaps(view); - if (use_transforms_) { + if (data.target_transform) { // Set the bounds at the end of the animation and reset the transform. view->SetTransform(gfx::Transform()); if (type == AnimationEndType::kEnded) @@ -248,8 +248,7 @@ DCHECK(view); const Data& data = data_[view]; - if (use_transforms_) { - DCHECK(data.target_transform); + if (data.target_transform) { const gfx::Transform current_transform = gfx::Tween::TransformValueBetween( animation->GetCurrentValue(), gfx::Transform(), *data.target_transform); view->SetTransform(current_transform); @@ -282,7 +281,6 @@ void BoundsAnimator::AnimationContainerProgressed( gfx::AnimationContainer* container) { if (!repaint_bounds_.IsEmpty()) { - DCHECK(!use_transforms_); // Adjust for rtl. repaint_bounds_.set_x(parent_->GetMirroredXWithWidthInView( repaint_bounds_.x(), repaint_bounds_.width()));
diff --git a/ui/views/animation/bounds_animator.h b/ui/views/animation/bounds_animator.h index 4a624b1..620145bc 100644 --- a/ui/views/animation/bounds_animator.h +++ b/ui/views/animation/bounds_animator.h
@@ -176,7 +176,9 @@ // transform of the views and therefore skips repainting and relayouting until // the end of the animation. Note that this may not look as good as the // regular version, depending on the content and the source and destination - // bounds. + // bounds. In the case the provided source bounds is empty, we cannot derive a + // transform so that particular view will still use a bounds animation, even + // with this flag on. const bool use_transforms_; base::ObserverList<BoundsAnimatorObserver>::Unchecked observers_;
diff --git a/ui/views/animation/bounds_animator_unittest.cc b/ui/views/animation/bounds_animator_unittest.cc index 22896c8..790c747 100644 --- a/ui/views/animation/bounds_animator_unittest.cc +++ b/ui/views/animation/bounds_animator_unittest.cc
@@ -244,4 +244,28 @@ EXPECT_EQ(repaint_count, child()->repaint_count()); } +// Tests that the transforms option does not crash when a view's bounds start +// off empty. +TEST_F(BoundsAnimatorTest, UseTransformsAnimateViewToEmptySrc) { + RecreateAnimator(/*use_transforms=*/true); + + gfx::Rect initial_bounds(0, 0, 0, 0); + child()->SetBoundsRect(initial_bounds); + gfx::Rect target_bounds(10, 10, 20, 20); + + child()->set_repaint_count(0); + animator()->AnimateViewTo(child(), target_bounds); + animator()->SetAnimationDelegate(child(), + std::make_unique<TestAnimationDelegate>()); + + // The animator should be animating now. + EXPECT_TRUE(animator()->IsAnimating()); + EXPECT_TRUE(animator()->IsAnimating(child())); + + // Run the message loop; the delegate exits the loop when the animation is + // done. + base::RunLoop().Run(); + EXPECT_EQ(target_bounds, child()->bounds()); +} + } // namespace views
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html index 34fc414..b82f4431 100644 --- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html +++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
@@ -149,7 +149,8 @@ --cr-input-input: { font-size: 28px; }; - --cr-input-letter-spacing: var(--cr-input-letter-spacing, 18px); + --cr-input-letter-spacing: var(--pin-keyboard-input-letter-spacing, + 18px); --cr-input-padding-end: 0; --cr-input-padding-start: 0; background-color: white;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java b/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java index a51e0e55..435c18e 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/TopControlsContainerView.java
@@ -265,6 +265,7 @@ mLastHeight = getHeight(); TopControlsContainerViewJni.get().setTopControlsSize(mNativeTopControlsContainerView, TopControlsContainerView.this, mLastWidth, mLastHeight); + setTopControlsOffset(0, mLastHeight); } private void finishTopControlsScroll(int topContentOffsetY) {