diff --git a/.vpython b/.vpython index b67113e5..4332083e 100644 --- a/.vpython +++ b/.vpython
@@ -307,7 +307,7 @@ > wheel: < name: "infra/python/wheels/mozlog-py2_py3" - version: "version:4.2.0" + version: "version:5.0" > wheel: < name: "infra/python/wheels/mozprocess-py2_py3"
diff --git a/BUILD.gn b/BUILD.gn index d2c9c44..670ea64 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -85,6 +85,7 @@ "//tools/ipc_fuzzer:ipc_fuzzer_all", "//tools/metrics:metrics_metadata", "//ui/base:ui_base_unittests", + "//ui/color:color_unittests", "//ui/gfx:gfx_unittests", "//url:url_unittests", ] @@ -829,10 +830,6 @@ ] } - if (use_color_pipeline) { - deps += [ "//ui/color:color_unittests" ] - } - # PFFFT. deps += [ "//third_party/pffft:fuzzers",
diff --git a/DEPS b/DEPS index 56c4cf97..d2c09ce 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': 'c6d0fdfb40987231be61ba3a47f6b34013a04606', + 'skia_revision': 'eced98b5eacf5d2cf4368c26020c0e3032c963f6', # 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': 'e18618490c3aeddf96e36c11b4bffcb5c7f12320', + 'v8_revision': 'ddac4370235572a0d7c8dcf6ef65d1933104c078', # 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': '3f283eb209adf9405721a05e8323bd80069912ad', + 'angle_revision': '27a813089d835c1ad706237c7adf70f5e0e1f59f', # 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': '126720bd2e578fec077a57d877ac64c46b18cd52', + 'swiftshader_revision': '2e6cd9c400d193592e3a1f17aa200e50c152e5d9', # 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': '07fd18460d096895e12a7f8b228cf9d2fbf117d6', + 'devtools_frontend_revision': '4eb885a01e2cb08f764e68bd71dec0663504370e', # 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. @@ -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' + '@' + '181bb9733f8392b5dbea5fe37545f29251268ea6', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8e76ccdb37b004f5a5eaa13e398a9f318c92b9c6', 'condition': 'checkout_linux', }, @@ -1239,7 +1239,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '0fd4f5cda74d29ee13a8942f973c827ec73d7b0d', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'fb875c61cf00ded88a3f46cb562ab943129cb7af', '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' + '@' + '4518a20e14ecb3415c52aecf132d9bc83edaa9c4', + Var('webrtc_git') + '/src.git' + '@' + '589b41e743db232fabde3f24653c76db45d6cedf', '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@3ac359c9ea04878a029df2e976aa4bcf11a273fc', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@040b65bece28b2adc73f3b8cab7e2586dbada447', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/common/crash_reporter/crash_keys.cc b/android_webview/common/crash_reporter/crash_keys.cc index 7898c363..9be81b1 100644 --- a/android_webview/common/crash_reporter/crash_keys.cc +++ b/android_webview/common/crash_reporter/crash_keys.cc
@@ -51,6 +51,8 @@ "mojo-message-error__3", "mojo-message-error__4", "total-discardable-memory-allocated", + // TODO(https://crbug.com/1006814): Remove this. + "IsRenderFrameLive", // GWP-ASan gwp_asan::kMallocCrashKey,
diff --git a/ash/shelf/shelf_navigation_widget.cc b/ash/shelf/shelf_navigation_widget.cc index 93308236..c50a85f 100644 --- a/ash/shelf/shelf_navigation_widget.cc +++ b/ash/shelf/shelf_navigation_widget.cc
@@ -400,7 +400,9 @@ 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_, + /*use_transforms=*/true)), back_button_metrics_reporter_( std::make_unique<NavigationButtonAnimationMetricsReporter>( shelf,
diff --git a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc index dcd6dd0..9555b15 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc +++ b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc
@@ -23,7 +23,7 @@ namespace { // Width of the contextual nudge. -constexpr int kBackgroundWidth = 160; +constexpr int kBackgroundWidth = 320; // Colors of the contextual nudge background gradient. constexpr SkColor kBackgroundStartColor =
diff --git a/build/android/gyp/java_cpp_enum.py b/build/android/gyp/java_cpp_enum.py index 502e071..d787809e 100755 --- a/build/android/gyp/java_cpp_enum.py +++ b/build/android/gyp/java_cpp_enum.py
@@ -69,7 +69,7 @@ # Enums, if given no value, are given the value of the previous enum + 1. if not all(self.entries.values()): prev_enum_value = -1 - for key, value in self.entries.iteritems(): + for key, value in self.entries.items(): if not value: self.entries[key] = prev_enum_value + 1 elif value in self.entries: @@ -102,9 +102,9 @@ def StripEntries(entries): ret = collections.OrderedDict() - for k, v in entries.iteritems(): + for k, v in entries.items(): stripped_key = k.replace(prefix_to_strip, '', 1) - if isinstance(v, basestring): + if isinstance(v, str): stripped_value = v.replace(prefix_to_strip, '') else: stripped_value = v @@ -124,10 +124,10 @@ """Normalize keys in |d| and update references to old keys in |d| values.""" normal_keys = {k: func(k) for k in d} ret = collections.OrderedDict() - for k, v in d.iteritems(): + for k, v in d.items(): # Need to transform values as well when the entry value was explicitly set # (since it could contain references to other enum entry values). - if isinstance(v, basestring): + if isinstance(v, str): for normal_key in normal_keys: v = v.replace(normal_key, normal_keys[normal_key]) ret[normal_keys[k]] = v @@ -368,7 +368,7 @@ enum_template = Template(' int ${NAME} = ${VALUE};') enum_entries_string = [] enum_names = [] - for enum_name, enum_value in enum_definition.entries.iteritems(): + for enum_name, enum_value in enum_definition.entries.items(): values = { 'NAME': enum_name, 'VALUE': enum_value,
diff --git a/build/android/gyp/java_cpp_enum_tests.py b/build/android/gyp/java_cpp_enum_tests.py index 08ef3b87..088c450 100755 --- a/build/android/gyp/java_cpp_enum_tests.py +++ b/build/android/gyp/java_cpp_enum_tests.py
@@ -730,7 +730,7 @@ definition.AppendEntry('B', None) definition.AppendEntry('NAME_LAST', None) definition.Finalize() - self.assertEqual(['A', 'B', 'NAME_LAST'], definition.entries.keys()) + self.assertEqual(['A', 'B', 'NAME_LAST'], list(definition.entries.keys())) def testGenerateThrowsOnEmptyInput(self): with self.assertRaises(Exception):
diff --git a/cc/OWNERS b/cc/OWNERS index 3ef17768..682d6e8 100644 --- a/cc/OWNERS +++ b/cc/OWNERS
@@ -44,6 +44,7 @@ # surfaces kylechar@chromium.org samans@chromium.org +jonross@chromium.org # input, scrolling bokan@chromium.org
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 584aff4..11e1b3d 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -1111,7 +1111,7 @@ scoped_refptr<Layer> root_layer) { SetRootLayer(std::move(root_layer)); - DCHECK(root_layer_->children().empty()); + DCHECK(!root_layer || root_layer_->children().empty()); if (IsUsingLayerLists() && root_layer_) force_use_property_tree_builder_ = true; }
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc index 7e7e7a7..d314bdd 100644 --- a/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -421,12 +421,11 @@ #if !defined(GL_NOT_ON_PLATFORM) ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_TEXTURE}, ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_BITMAP}, -#if !defined(OS_WIN) && !defined(OS_LINUX) // TODO(crbug.com/1046788): The skia readback path doesn't support // RGBA_TEXTURE readback requests yet. Don't run these tests on platforms // that have UseSkiaForGLReadback enabled by default. - ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE}, -#endif + // + // ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE}, ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP}, #endif // !defined(GL_NOT_ON_PLATFORM) #if defined(ENABLE_CC_VULKAN_TESTS) @@ -445,12 +444,11 @@ #if !defined(GL_NOT_ON_PLATFORM) ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_TEXTURE}, ReadbackTestConfig{LayerTreeTest::RENDERER_GL, READBACK_BITMAP}, -#if !defined(OS_WIN) && !defined(OS_LINUX) // TODO(crbug.com/1046788): The skia readback path doesn't support // RGBA_TEXTURE readback requests yet. Don't run these tests on platforms // that have UseSkiaForGLReadback enabled by default. - ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE}, -#endif + // + // ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_TEXTURE}, ReadbackTestConfig{LayerTreeTest::RENDERER_SKIA_GL, READBACK_BITMAP}, #endif // !defined(GL_NOT_ON_PLATFORM) #if defined(ENABLE_CC_VULKAN_TESTS) && !defined(THREAD_SANITIZER) && \
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 3ae509b..a1763a2 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1383,12 +1383,12 @@ "java/src/org/chromium/chrome/browser/settings/homepage/HomepageEditor.java", "java/src/org/chromium/chrome/browser/settings/homepage/HomepageSettings.java", "java/src/org/chromium/chrome/browser/settings/homepage/RadioButtonGroupHomepagePreference.java", - "java/src/org/chromium/chrome/browser/settings/languages/AddLanguageFragment.java", - "java/src/org/chromium/chrome/browser/settings/languages/LanguageItem.java", - "java/src/org/chromium/chrome/browser/settings/languages/LanguageListBaseAdapter.java", - "java/src/org/chromium/chrome/browser/settings/languages/LanguageListPreference.java", - "java/src/org/chromium/chrome/browser/settings/languages/LanguageSettings.java", - "java/src/org/chromium/chrome/browser/settings/languages/LanguagesManager.java", + "java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java", + "java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java", + "java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java", + "java/src/org/chromium/chrome/browser/language/settings/LanguageListPreference.java", + "java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java", + "java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java", "java/src/org/chromium/chrome/browser/settings/password/CallbackDelayer.java", "java/src/org/chromium/chrome/browser/settings/password/DialogManager.java", "java/src/org/chromium/chrome/browser/settings/password/ExportErrorDialogFragment.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/StreamItemTouchCallbacks.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/StreamItemTouchCallbacks.java index 8076c69..f8395d7 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/StreamItemTouchCallbacks.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/internal/StreamItemTouchCallbacks.java
@@ -5,12 +5,13 @@ package org.chromium.chrome.browser.feed.library.basicstream.internal; import android.graphics.Canvas; -import android.support.v4.view.animation.FastOutLinearInInterpolator; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.animation.Interpolator; +import androidx.interpolator.view.animation.FastOutLinearInInterpolator; + import org.chromium.chrome.browser.feed.library.basicstream.internal.viewholders.SwipeableViewHolder; /** {@link ItemTouchHelper.Callback} to allow dismissing cards via swiping. */
diff --git a/chrome/android/java/res/xml/languages_preferences.xml b/chrome/android/java/res/xml/languages_preferences.xml index 5e7dfc6..550563e 100644 --- a/chrome/android/java/res/xml/languages_preferences.xml +++ b/chrome/android/java/res/xml/languages_preferences.xml
@@ -6,7 +6,7 @@ <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> - <org.chromium.chrome.browser.settings.languages.LanguageListPreference + <org.chromium.chrome.browser.language.settings.LanguageListPreference android:key="preferred_languages" android:layout="@layout/languages_preference" android:widgetLayout="@layout/accept_languages_list" />
diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml index f5cccd3c..370468e 100644 --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml
@@ -81,7 +81,7 @@ android:order="14" android:title="@string/prefs_site_settings"/> <Preference - android:fragment="org.chromium.chrome.browser.settings.languages.LanguageSettings" + android:fragment="org.chromium.chrome.browser.language.settings.LanguageSettings" android:key="languages" android:order="15" android:title="@string/language_settings"/>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java index 56a1b97..a107475 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -56,7 +56,6 @@ import org.chromium.chrome.browser.xsurface.SurfaceDependencyProvider; import org.chromium.chrome.browser.xsurface.SurfaceRenderer; import org.chromium.components.browser_ui.widget.FeatureHighlightProvider; -import org.chromium.components.download.DownloadCollectionBridge; import org.chromium.components.signin.AccountManagerDelegate; import org.chromium.components.signin.SystemAccountManagerDelegate; import org.chromium.content_public.browser.UiThreadTaskTraits; @@ -330,13 +329,6 @@ } /** - * @return A new {@link DownloadCollectionBridge} instance. - */ - public DownloadCollectionBridge getDownloadCollectionBridge() { - return DownloadCollectionBridge.getDownloadCollectionBridge(); - } - - /** * @return A new {@link DigitalWellbeingClient} instance. */ public DigitalWellbeingClient createDigitalWellbeingClient() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java index a00cbd2f..ba56290 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/TabbedModeTabDelegateFactory.java
@@ -8,6 +8,7 @@ import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; +import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler; import org.chromium.chrome.browser.share.ShareDelegate; import org.chromium.chrome.browser.tab.Tab; @@ -43,7 +44,7 @@ @Override public ExternalNavigationHandler createExternalNavigationHandler(Tab tab) { - return new ExternalNavigationHandler(tab); + return new ExternalNavigationHandler(new ExternalNavigationDelegateImpl(tab)); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java index 164b30e3..7f2eae4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelContent.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.content.ContentUtils; import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager; +import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.embedder_support.delegate.WebContentsDelegateAndroid; @@ -142,7 +143,7 @@ public InterceptNavigationDelegateImpl() { Tab tab = mActivity.getActivityTab(); mExternalNavHandler = (tab != null && tab.getWebContents() != null) - ? new ExternalNavigationHandler(tab) + ? new ExternalNavigationHandler(new ExternalNavigationDelegateImpl(tab)) : null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java index 04d22c2..304138a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java
@@ -23,9 +23,10 @@ import org.chromium.base.task.AsyncTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.signin.DisplayableProfileData; +import org.chromium.chrome.browser.signin.IdentityServicesProvider; import org.chromium.chrome.browser.signin.ProfileDataCache; import org.chromium.components.signin.AccountManagerFacade; -import org.chromium.components.signin.ChromeSigninController; +import org.chromium.components.signin.base.CoreAccountInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -438,10 +439,10 @@ private String getOwnerEmail() { if (sTestOwnerEmail != null) return sTestOwnerEmail; - ChromeSigninController controller = ChromeSigninController.get(); - Account account = controller.getSignedInUser(); - if (account != null) { - return account.name; + CoreAccountInfo coreAccountInfo = + IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo(); + if (coreAccountInfo != null) { + return coreAccountInfo.getEmail(); } AccountManagerFacade manager = AccountManagerFacade.get(); @@ -504,8 +505,8 @@ DisplayableProfileData profileData = mProfileDataCache.getProfileDataOrDefault(ownerEmail); String name = profileData.getFullNameOrEmail(); if (TextUtils.isEmpty(name) || TextUtils.equals(name, ownerEmail)) { - ChromeSigninController controller = ChromeSigninController.get(); - name = controller.getSignedInAccountName(); + name = CoreAccountInfo.getEmailFrom( + IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo()); } ArrayList<String> telephones = new ArrayList<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java index d0a11e14..9d363dda 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -50,6 +50,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.util.ConversionUtils; +import org.chromium.components.download.DownloadCollectionBridge; import org.chromium.components.download.DownloadState; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.feature_engagement.Tracker; @@ -278,6 +279,7 @@ mHandler = handler; mDownloadSnackbarController = new DownloadSnackbarController(); mOMADownloadHandler = new OMADownloadHandler(applicationContext); + DownloadCollectionBridge.setDownloadDelegate(new DownloadDelegateImpl()); // Note that this technically leaks the native object, however, DownloadManagerService // is a singleton that lives forever and there's no clean shutdown of Chrome on Android. init();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java index 4ed2168..a743d93 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegate.java
@@ -160,4 +160,10 @@ * @return Whether the package is a valid WebAPK package. */ boolean isValidWebApk(String packageName); + + /** + * Gives the embedder a chance to handle the intent via the autofill assistant. + */ + boolean handleWithAutofillAssistant( + ExternalNavigationParams params, Intent targetIntent, String browserFallbackUrl); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java index f86115d..8a18d1d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -39,12 +39,14 @@ import org.chromium.chrome.browser.ChromeTabbedActivity2; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.LaunchIntentDispatcher; +import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantFacade; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.chrome.browser.instantapps.AuthenticatedProxyActivity; import org.chromium.chrome.browser.instantapps.InstantAppsHandler; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabImpl; import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab.TabRedirectHandler; import org.chromium.chrome.browser.webapps.WebappActivity; @@ -644,4 +646,20 @@ public boolean isValidWebApk(String packageName) { return WebApkValidator.isValidWebApk(ContextUtils.getApplicationContext(), packageName); } + + @Override + public boolean handleWithAutofillAssistant( + ExternalNavigationParams params, Intent targetIntent, String browserFallbackUrl) { + if (browserFallbackUrl != null && !params.isIncognito() + && AutofillAssistantFacade.isAutofillAssistantByIntentTriggeringEnabled( + targetIntent) + && isSerpReferrer()) { + if (params.getTab() != null) { + AutofillAssistantFacade.start(((TabImpl) params.getTab()).getActivity(), + targetIntent.getExtras(), browserFallbackUrl); + } + return true; + } + return false; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java index 01ec93b..7dce21e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -27,11 +27,8 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.IntentHandler; -import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantFacade; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.instantapps.InstantAppsHandler; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tab.TabImpl; import org.chromium.chrome.browser.tab.TabRedirectHandler; import org.chromium.chrome.browser.webapps.WebappScopePolicy; import org.chromium.components.embedder_support.util.UrlConstants; @@ -154,15 +151,6 @@ } /** - * A constructor for UrlHandler. - * - * @param tab The tab that initiated the external intent. - */ - public ExternalNavigationHandler(Tab tab) { - this(new ExternalNavigationDelegateImpl(tab)); - } - - /** * Constructs a new instance of {@link ExternalNavigationHandler}, using the injected * {@link ExternalNavigationDelegate}. */ @@ -765,14 +753,7 @@ private boolean handleWithAutofillAssistant( ExternalNavigationParams params, Intent targetIntent, String browserFallbackUrl) { - if (browserFallbackUrl != null && !params.isIncognito() - && AutofillAssistantFacade.isAutofillAssistantByIntentTriggeringEnabled( - targetIntent) - && mDelegate.isSerpReferrer()) { - if (params.getTab() != null) { - AutofillAssistantFacade.start(((TabImpl) params.getTab()).getActivity(), - targetIntent.getExtras(), browserFallbackUrl); - } + if (mDelegate.handleWithAutofillAssistant(params, targetIntent, browserFallbackUrl)) { if (DEBUG) Log.i(TAG, "Handling with Assistant"); return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java index 7d3e6d4..70d2614 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -85,8 +85,6 @@ private static FirstRunActivityObserver sObserver; - private boolean mShowWelcomePage = true; - private String mResultSignInAccountName; private boolean mResultIsDefaultAccount; private boolean mResultShowSignInSettings; @@ -121,12 +119,8 @@ * Defines a sequence of pages to be shown (depending on parameters etc). */ private void createPageSequence() { - // An optional welcome page. - if (mShowWelcomePage) { - mPages.add(new ToSAndUMAFirstRunFragment.Page()); - mFreProgressStates.add(FRE_PROGRESS_WELCOME_SHOWN); - } - + mPages.add(new ToSAndUMAFirstRunFragment.Page()); + mFreProgressStates.add(FRE_PROGRESS_WELCOME_SHOWN); // Other pages will be created by createPostNativePageSequence() after // native has been initialized. } @@ -207,7 +201,6 @@ } mFreProperties = freProperties; - mShowWelcomePage = mFreProperties.getBoolean(SHOW_WELCOME_PAGE); if (TextUtils.isEmpty(mResultSignInAccountName)) { mResultSignInAccountName = mFreProperties.getString( SigninFirstRunFragment.FORCE_SIGNIN_ACCOUNT_TO); @@ -464,7 +457,7 @@ private boolean jumpToPage(int position) { if (sObserver != null) sObserver.onJumpToPage(position); - if (mShowWelcomePage && !didAcceptTermsOfService()) { + if (!didAcceptTermsOfService()) { return position == 0; } if (position >= mPagerAdapter.getCount()) { @@ -478,7 +471,7 @@ private void stopProgressionIfNotAcceptedTermsOfService() { if (mPagerAdapter == null) return; - mPagerAdapter.setStopAtTheFirstPage(mShowWelcomePage && !didAcceptTermsOfService()); + mPagerAdapter.setStopAtTheFirstPage(!didAcceptTermsOfService()); } private void skipPagesIfNecessary() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java index f4f70c1..66b90418 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivityBase.java
@@ -32,8 +32,6 @@ // received by ChromeLauncherActivity.) public static final String EXTRA_CHROME_LAUNCH_INTENT_EXTRAS = "Extra.FreChromeLaunchIntentExtras"; - - static final String SHOW_WELCOME_PAGE = "ShowWelcome"; static final String SHOW_DATA_REDUCTION_PAGE = "ShowDataReduction"; static final String SHOW_SEARCH_ENGINE_PAGE = "ShowSearchEnginePage"; static final String SHOW_SIGNIN_PAGE = "ShowSignIn";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java index 5b48db0..2fe5f65 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -162,8 +162,6 @@ } Bundle freProperties = new Bundle(); - // TODO(https://crbug.com/1056132): Remove the boolean FirstRunActivity.SHOW_WELCOME_PAGE - freProperties.putBoolean(FirstRunActivity.SHOW_WELCOME_PAGE, true); freProperties.putInt(SigninFirstRunFragment.CHILD_ACCOUNT_STATUS, mChildAccountStatus); // Initialize usage and crash reporting according to the default value.
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 838b72e..e5794b2 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
@@ -116,6 +116,7 @@ private static Map<String, Boolean> sBoolValuesReturned = new HashMap<>(); private static Map<String, String> sStringValuesReturned = new HashMap<>(); + private static Map<String, Integer> sIntValuesReturned = new HashMap<>(); private static String sReachedCodeProfilerTrialGroup; /** @@ -262,6 +263,17 @@ parameter.getSharedPreferenceKey(), parameter.getDefaultValue()); } + /** + * TODO(crbug.com/1012975): Move this to IntCachedFieldTrialParameter when + * CachedFeatureFlags is in chrome/browser/flags. + * + * @return the value of the field trial parameter that should be used in this run. + */ + public static int getValue(IntCachedFieldTrialParameter parameter) { + return getConsistentIntValue( + parameter.getSharedPreferenceKey(), parameter.getDefaultValue()); + } + private static void cacheStartSurfaceVariation() { String feature = ChromeFeatureList.getFieldTrialParamByFeature( ChromeFeatureList.START_SURFACE_ANDROID, "start_surface_variation"); @@ -358,6 +370,15 @@ return value; } + static int getConsistentIntValue(String preferenceName, int defaultValue) { + Integer value = sIntValuesReturned.get(preferenceName); + if (value == null) { + value = SharedPreferencesManager.getInstance().readInt(preferenceName, defaultValue); + sIntValuesReturned.put(preferenceName, value); + } + return value; + } + private static String getPrefForFeatureFlag(String featureName) { String grandfatheredPrefKey = sNonDynamicPrefKeys.get(featureName); if (grandfatheredPrefKey == null) { @@ -371,6 +392,7 @@ public static void resetFlagsForTesting() { sBoolValuesReturned.clear(); sStringValuesReturned.clear(); + sIntValuesReturned.clear(); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java index e0dbe65..2c5e6cc7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DuplicateDownloadInfoBar.java
@@ -16,7 +16,6 @@ import android.view.View; import android.webkit.MimeTypeMap; -import org.chromium.base.BuildInfo; import org.chromium.base.ContextUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.task.AsyncTask; @@ -84,11 +83,8 @@ new AsyncTask<String>() { @Override protected String doInBackground() { - if (BuildInfo.isAtLeastQ() - && DownloadCollectionBridge.getDownloadCollectionBridge() - .needToPublishDownload(mFilePath)) { - Uri uri = DownloadCollectionBridge.getDownloadCollectionBridge() - .getDownloadUriForFileName(filename); + if (DownloadCollectionBridge.shouldPublishDownload(mFilePath)) { + Uri uri = DownloadCollectionBridge.getDownloadUriForFileName(filename); return uri == null ? null : uri.toString(); } else { if (file.exists()) return mFilePath;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java index 9970f86..2581366 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -81,7 +81,6 @@ import org.chromium.chrome.browser.webapps.WebApkVersionManager; import org.chromium.chrome.browser.webapps.WebappRegistry; import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory; -import org.chromium.components.download.DownloadCollectionBridge; import org.chromium.components.minidump_uploader.CrashFileManager; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountsChangeObserver; @@ -185,11 +184,6 @@ application, ChromePreferenceKeys.SYNC_SESSIONS_UUID), false); - // Set up the DownloadCollectionBridge early as display names may be immediately retrieved - // after native is loaded. - DownloadCollectionBridge.setDownloadCollectionBridge( - AppHooks.get().getDownloadCollectionBridge()); - // De-jelly can also be controlled by a system property. As sandboxed processes can't // read this property directly, convert it to the equivalent command line flag. if (DeJellyUtils.externallyEnableDeJelly()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java index 1b4b32b..2ef6f00 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java
@@ -22,7 +22,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.settings.languages.LanguageItem; +import org.chromium.chrome.browser.language.settings.LanguageItem; import org.chromium.chrome.browser.translate.TranslateBridge; import org.chromium.components.language.AndroidLanguageMetricsBridge; import org.chromium.components.language.GeoLanguageProviderBridge;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/language/OWNERS new file mode 100644 index 0000000..f1e82d5 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/OWNERS
@@ -0,0 +1 @@ +file://components/language/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/AddLanguageFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/settings/languages/AddLanguageFragment.java rename to chrome/android/java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java index 4f2490b..335168b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/AddLanguageFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java
@@ -2,7 +2,7 @@ // 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.settings.languages; +package org.chromium.chrome.browser.language.settings; import android.app.Activity; import android.content.Context;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageItem.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageItem.java rename to chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java index b1c58fe..511465a8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java
@@ -2,7 +2,7 @@ // 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.settings.languages; +package org.chromium.chrome.browser.language.settings; /** * Simple object representing the language item.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageListBaseAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageListBaseAdapter.java rename to chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java index 70cf5b5..ac858350 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageListBaseAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java
@@ -2,7 +2,7 @@ // 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.settings.languages; +package org.chromium.chrome.browser.language.settings; import android.content.Context; import android.support.v4.view.ViewCompat;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageListPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListPreference.java similarity index 99% rename from chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageListPreference.java rename to chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListPreference.java index c647a0a..11eb1896 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageListPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListPreference.java
@@ -2,7 +2,7 @@ // 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.settings.languages; +package org.chromium.chrome.browser.language.settings; import static org.chromium.components.browser_ui.widget.listmenu.BasicListMenu.buildMenuListItem; import static org.chromium.components.browser_ui.widget.listmenu.BasicListMenu.buildMenuListItemWithEndIcon;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageSettings.java rename to chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java index 2152e65..5b9276f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguageSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
@@ -2,7 +2,7 @@ // 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.settings.languages; +package org.chromium.chrome.browser.language.settings; import android.app.Activity; import android.content.Intent;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguagesManager.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguagesManager.java rename to chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java index 61a484f2..46a8a49 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/languages/LanguagesManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java
@@ -2,7 +2,7 @@ // 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.settings.languages; +package org.chromium.chrome.browser.language.settings; import androidx.annotation.IntDef;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java b/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java index 4d465f0..b64aacd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/permissions/AndroidPermissionRequester.java
@@ -139,6 +139,10 @@ } else if (deniedContentSettings.contains( ContentSettingsType.MEDIASTREAM_CAMERA)) { deniedStringId = R.string.infobar_missing_camera_permission_text; + } else if (deniedContentSettings.contains(ContentSettingsType.AR)) { + // TODO(https://crbug.com/1058055): Use the missing camera permission + // text until we get guidance from UX team. + deniedStringId = R.string.infobar_missing_camera_permission_text; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/website/SiteSettingsCategory.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/website/SiteSettingsCategory.java index da0e67e..a03d640 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/website/SiteSettingsCategory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/website/SiteSettingsCategory.java
@@ -445,10 +445,14 @@ if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_SITE_SETTINGS_UI_REFRESH)) { if (type == ContentSettingsType.GEOLOCATION) { permission_string = R.string.android_location_permission_off; - } else if (type == ContentSettingsType.MEDIASTREAM_CAMERA) { - permission_string = R.string.android_camera_permission_off; } else if (type == ContentSettingsType.MEDIASTREAM_MIC) { permission_string = R.string.android_microphone_permission_off; + } else if (type == ContentSettingsType.MEDIASTREAM_CAMERA) { + permission_string = R.string.android_camera_permission_off; + } else if (type == ContentSettingsType.AR) { + // TODO(https://crbug.com/1058055): Use the missing camera permission + // text until we get guidance from UX team. + permission_string = R.string.android_camera_permission_off; } else if (type == ContentSettingsType.NOTIFICATIONS) { permission_string = R.string.android_notifications_permission_off; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarAnimationCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarAnimationCoordinator.java index 045c79bd3..82fdd94 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarAnimationCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarAnimationCoordinator.java
@@ -9,11 +9,12 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.res.Resources; -import android.support.v4.view.animation.FastOutLinearInInterpolator; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; +import androidx.interpolator.view.animation.FastOutLinearInInterpolator; +import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; + import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java index e1a8ba22..b09bd99c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
@@ -6,7 +6,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.NativeMethods; -import org.chromium.chrome.browser.settings.languages.LanguageItem; +import org.chromium.chrome.browser.language.settings.LanguageItem; import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.WebContents;
diff --git a/chrome/android/java/static_library_dex_reference_workarounds.flags b/chrome/android/java/static_library_dex_reference_workarounds.flags index 3765231..9367e59 100644 --- a/chrome/android/java/static_library_dex_reference_workarounds.flags +++ b/chrome/android/java/static_library_dex_reference_workarounds.flags
@@ -34,6 +34,10 @@ -keep,allowobfuscation class org.chromium.chrome.browser.firstrun.FirstRunPagerAdapter { *; } -keep,allowobfuscation class org.chromium.chrome.browser.init.ChromeBrowserInitializer$** { *; } -keep,allowobfuscation class org.chromium.chrome.browser.init.ProcessInitializationHandler$** { *; } +-keep,allowobfuscation class org.chromium.chrome.browser.language.settings.AddLanguageFragment { *; } +-keep,allowobfuscation class org.chromium.chrome.browser.language.settings.AddLanguageFragment$$Lambda$1 { *; } +-keep,allowobfuscation class org.chromium.chrome.browser.language.settings.AddLanguageFragment$LanguageSearchListAdapter { *; } +-keep,allowobfuscation class org.chromium.chrome.browser.language.settings.LanguageListBaseAdapter { *; } -keep,allowobfuscation class org.chromium.chrome.browser.media.ui.MediaImageCallback { *; } -keep,allowobfuscation class org.chromium.chrome.browser.media.ui.MediaImageManager { *; } -keep,allowobfuscation class org.chromium.chrome.browser.media.ui.MediaNotificationInfo$Builder { *; } @@ -44,8 +48,6 @@ -keep,allowobfuscation class org.chromium.chrome.browser.payments.AndroidPaymentApp$** { *; } -keep,allowobfuscation class org.chromium.chrome.browser.payments.PaymentApp { *; } -keep,allowobfuscation class org.chromium.chrome.browser.photo_picker.PhotoPickerDialog { *; } --keep,allowobfuscation class org.chromium.chrome.browser.preferences.languages.AddLanguageFragment { *; } --keep,allowobfuscation class org.chromium.chrome.browser.preferences.languages.AddLanguageFragment$$Lambda$** { *; } -keep,allowobfuscation class org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataFetcher { *; } -keep,allowobfuscation class org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataPreferences { *; } -keep,allowobfuscation class org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataPreferencesAdvanced { *; } @@ -53,10 +55,6 @@ -keep,allowobfuscation class org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataTabsFragment { *; } -keep,allowobfuscation class org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataTabsFragment$ClearBrowsingDataPagerAdapter { *; } -keep,allowobfuscation class org.chromium.chrome.browser.profiles.Profile { *; } --keep,allowobfuscation class org.chromium.chrome.browser.settings.languages.AddLanguageFragment { *; } --keep,allowobfuscation class org.chromium.chrome.browser.settings.languages.AddLanguageFragment$$Lambda$1 { *; } --keep,allowobfuscation class org.chromium.chrome.browser.settings.languages.AddLanguageFragment$LanguageSearchListAdapter { *; } --keep,allowobfuscation class org.chromium.chrome.browser.settings.languages.LanguageListBaseAdapter { *; } -keep,allowobfuscation class org.chromium.chrome.browser.settings.privacy.ClearBrowsingDataFetcher { *; } -keep,allowobfuscation class org.chromium.chrome.browser.settings.privacy.ClearBrowsingDataPreferences { *; } -keep,allowobfuscation class org.chromium.chrome.browser.settings.privacy.ClearBrowsingDataPreferencesAdvanced { *; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java index 3369e55..709a75e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/PrerenderTest.java
@@ -6,6 +6,7 @@ import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; +import android.os.Build; import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; @@ -66,7 +67,8 @@ @LargeTest @Restriction({RESTRICTION_TYPE_NON_LOW_END_DEVICE}) @Feature({"TabContents"}) - @DisableIf.Build(sdk_is_greater_than = 25, message = "https://crbug.com/1014213") + @DisableIf. + Build(sdk_is_greater_than = Build.VERSION_CODES.M, message = "https://crbug.com/1014213") public void testNoPrerender() throws InterruptedException { String testUrl = mTestServer.getURL( "/chrome/test/data/android/prerender/google.html");
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 c2a5056..957f1f7 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
@@ -66,6 +66,7 @@ import org.chromium.chrome.browser.contextualsearch.ContextualSearchFakeServer.MutableResolvedSearchTerm; import org.chromium.chrome.browser.contextualsearch.ContextualSearchInternalStateController.InternalState; import org.chromium.chrome.browser.contextualsearch.ResolvedSearchTerm.CardTag; +import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler; import org.chromium.chrome.browser.findinpage.FindToolbar; import org.chromium.chrome.browser.firstrun.FirstRunStatus; @@ -124,6 +125,11 @@ "disable-features=" + ChromeFeatureList.CONTEXTUAL_SEARCH_ML_TAP_SUPPRESSION}) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @RetryOnFailure +// +// NOTE -- THIS WHOLE TEST CLASS IS TEMPORARILY DISABLED: +// +@DisabledTest(message = "See https://crbug.com/1058362") +// public class ContextualSearchManagerTest { @Rule public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = @@ -2212,7 +2218,8 @@ @Feature({"ContextualSearch"}) public void testExternalNavigationWithUserGesture() { final ExternalNavigationHandler externalNavHandler = - new ExternalNavigationHandler(mActivityTestRule.getActivity().getActivityTab()); + new ExternalNavigationHandler(new ExternalNavigationDelegateImpl( + mActivityTestRule.getActivity().getActivityTab())); final NavigationParams navigationParams = new NavigationParams( "intent://test/#Intent;scheme=test;package=com.chrome.test;end", "", false /* isPost */, true /* hasUserGesture */, PageTransition.LINK, @@ -2237,7 +2244,8 @@ @Feature({"ContextualSearch"}) public void testRedirectedExternalNavigationWithUserGesture() { final ExternalNavigationHandler externalNavHandler = - new ExternalNavigationHandler(mActivityTestRule.getActivity().getActivityTab()); + new ExternalNavigationHandler(new ExternalNavigationDelegateImpl( + mActivityTestRule.getActivity().getActivityTab())); final NavigationParams initialNavigationParams = new NavigationParams("http://test.com", "", false /* isPost */, true /* hasUserGesture */, PageTransition.LINK, @@ -2271,7 +2279,8 @@ @Feature({"ContextualSearch"}) public void testExternalNavigationWithoutUserGesture() { final ExternalNavigationHandler externalNavHandler = - new ExternalNavigationHandler(mActivityTestRule.getActivity().getActivityTab()); + new ExternalNavigationHandler(new ExternalNavigationDelegateImpl( + mActivityTestRule.getActivity().getActivityTab())); final NavigationParams navigationParams = new NavigationParams( "intent://test/#Intent;scheme=test;package=com.chrome.test;end", "", false /* isPost */, false /* hasUserGesture */, PageTransition.LINK,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java index 2224d352..f3104788 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
@@ -4,9 +4,11 @@ package org.chromium.chrome.browser.externalnav; +import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ResolveInfo; +import android.net.Uri; import android.os.Build; import android.support.test.filters.SmallTest; @@ -19,9 +21,11 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.instantapps.InstantAppsHandler; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.util.browser.Features; import java.util.ArrayList; import java.util.Arrays; @@ -31,8 +35,50 @@ * Instrumentation tests for {@link ExternalNavigationHandler}. */ @RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class ExternalNavigationDelegateImplTest { +@CommandLineFlags + .Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) + @Features.DisableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, + ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) + public class ExternalNavigationDelegateImplTest { + private static final String AUTOFILL_ASSISTANT_INTENT_URL = + "intent://www.example.com#Intent;scheme=https;" + + "B.org.chromium.chrome.browser.autofill_assistant.ENABLED=true;" + + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "=" + + Uri.encode("https://www.example.com") + ";end"; + + class ExternalNavigationDelegateImplForTesting extends ExternalNavigationDelegateImpl { + public ExternalNavigationDelegateImplForTesting() { + super(mActivityTestRule.getActivity().getActivityTab()); + } + + @Override + public boolean isSerpReferrer() { + return mIsSerpReferrer; + } + + public void setIsSerpReferrer(boolean value) { + mIsSerpReferrer = value; + } + + // Convenience for testing that reduces boilerplate in constructing arguments to the + // production method that are common across tests. + public boolean handleWithAutofillAssistant(ExternalNavigationParams params) { + Intent intent; + try { + intent = Intent.parseUri(AUTOFILL_ASSISTANT_INTENT_URL, Intent.URI_INTENT_SCHEME); + } catch (Exception ex) { + Assert.assertTrue(false); + return false; + } + + String fallbackUrl = "https://www.example.com"; + + return handleWithAutofillAssistant(params, intent, fallbackUrl); + } + + private boolean mIsSerpReferrer; + } + @Rule public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = new ChromeActivityTestRule<>(ChromeActivity.class); @@ -194,4 +240,79 @@ public void setUp() throws InterruptedException { mActivityTestRule.startMainActivityOnBlankPage(); } + + @Test + @SmallTest + @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, + ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) + public void + testHandleWithAutofillAssistant_TriggersFromSearch() { + ExternalNavigationDelegateImplForTesting delegate = + new ExternalNavigationDelegateImplForTesting(); + delegate.setIsSerpReferrer(true); + + // Note: Leave the tab of |params| null to ensure that the delegate doesn't ask + // AutofillAssistantFacade to actually start the activity, which this test is not set up + // for. + ExternalNavigationParams params = + new ExternalNavigationParams + .Builder(AUTOFILL_ASSISTANT_INTENT_URL, /*isIncognito=*/false) + .build(); + + Assert.assertTrue(delegate.handleWithAutofillAssistant(params)); + } + + @Test + @SmallTest + @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, + ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) + public void + testHandleWithAutofillAssistant_DoesNotTriggerFromSearchInIncognito() { + ExternalNavigationDelegateImplForTesting delegate = + new ExternalNavigationDelegateImplForTesting(); + delegate.setIsSerpReferrer(true); + + ExternalNavigationParams params = + new ExternalNavigationParams + .Builder(AUTOFILL_ASSISTANT_INTENT_URL, /*isIncognito=*/true) + .build(); + + Assert.assertFalse(delegate.handleWithAutofillAssistant(params)); + } + + @Test + @SmallTest + @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, + ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) + public void + testHandleWithAutofillAssistant_DoesNotTriggerFromDifferentOrigin() { + ExternalNavigationDelegateImplForTesting delegate = + new ExternalNavigationDelegateImplForTesting(); + delegate.setIsSerpReferrer(false); + + ExternalNavigationParams params = + new ExternalNavigationParams + .Builder(AUTOFILL_ASSISTANT_INTENT_URL, /*isIncognito=*/false) + .build(); + + Assert.assertFalse(delegate.handleWithAutofillAssistant(params)); + } + + @Test + @SmallTest + @Features.DisableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, + ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) + public void + testHandleWithAutofillAssistant_DoesNotTriggerWhenFeatureDisabled() { + ExternalNavigationDelegateImplForTesting delegate = + new ExternalNavigationDelegateImplForTesting(); + delegate.setIsSerpReferrer(true); + + ExternalNavigationParams params = + new ExternalNavigationParams + .Builder(AUTOFILL_ASSISTANT_INTENT_URL, /*isIncognito=*/false) + .build(); + + Assert.assertFalse(delegate.handleWithAutofillAssistant(params)); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java index fae6233..08cdce73 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -62,8 +62,6 @@ sdk_is_less_than = Build.VERSION_CODES.LOLLIPOP) @Features.EnableFeatures({ChromeFeatureList.CCT_EXTERNAL_LINK_HANDLING, ChromeFeatureList.INTENT_BLOCK_EXTERNAL_FORM_REDIRECT_NO_GESTURE}) -@Features.DisableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, - ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) public class ExternalNavigationHandlerTest { // clang-format on @Rule @@ -1594,11 +1592,8 @@ @Test @SmallTest - @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, - ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) - public void - testAssistantAutofillIntent_catchNavigationFromGoogleSearch() { - mDelegate.setIsSerpReferrer(true); + public void testAutofillAssistantIntent_handledByDelegate() { + mDelegate.setHandleIntentWithAutofillAssistant(true); checkUrl(AUTOFILL_ASSISTANT_INTENT_URL) .expecting(OverrideUrlLoadingResult.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE); @@ -1608,11 +1603,8 @@ @Test @SmallTest - @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, - ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) - public void - testAssistantAutofillIntent_doNotCatchNavigationInIncognito() { - mDelegate.setIsSerpReferrer(true); + public void testAutofillAssistantIntent_notHandledByDelegate() { + mDelegate.setHandleIntentWithAutofillAssistant(false); checkUrl(AUTOFILL_ASSISTANT_INTENT_URL) .withIsIncognito(true) @@ -1625,38 +1617,6 @@ @Test @SmallTest - @Features.EnableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, - ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) - public void - testAssistantAutofillIntent_doNotCatchNavigationFromDifferentOrigin() { - mDelegate.setIsSerpReferrer(false); - - checkUrl(AUTOFILL_ASSISTANT_INTENT_URL) - .expecting(OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, - START_OTHER_ACTIVITY); - - Assert.assertNotNull(mDelegate.startActivityIntent); - Assert.assertTrue(mDelegate.startActivityIntent.getScheme().startsWith("https")); - } - - @Test - @SmallTest - @Features.DisableFeatures({ChromeFeatureList.AUTOFILL_ASSISTANT, - ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY}) - public void - testAssistantAutofillIntent_doNotCatchNavigationForNonEnabledFeature() { - mDelegate.setIsSerpReferrer(true); - - checkUrl(AUTOFILL_ASSISTANT_INTENT_URL) - .expecting(OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT, - START_OTHER_ACTIVITY); - - Assert.assertNotNull(mDelegate.startActivityIntent); - Assert.assertTrue(mDelegate.startActivityIntent.getScheme().startsWith("https")); - } - - @Test - @SmallTest public void testIntentActionMetrics() { final String intentWithAction = "intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;" @@ -1950,6 +1910,12 @@ return false; } + @Override + public boolean handleWithAutofillAssistant( + ExternalNavigationParams params, Intent targetIntent, String browserFallbackUrl) { + return mHandleWithAutofillAssistant; + } + public void reset() { startActivityIntent = null; startIncognitoIntentCalled = false; @@ -1993,6 +1959,10 @@ mCanHandleWithInstantApp = value; } + public void setHandleIntentWithAutofillAssistant(boolean value) { + mHandleWithAutofillAssistant = value; + } + public void setIsSerpReferrer(boolean value) { mIsSerpReferrer = value; } @@ -2018,6 +1988,7 @@ private String mNewUrlAfterClobbering; private String mReferrerUrlForClobbering; private boolean mCanHandleWithInstantApp; + private boolean mHandleWithAutofillAssistant; private boolean mIsSerpReferrer; private String mPreviousUrl; public boolean mCalledWithProxy;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java index 8b157e2..245d5fb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -194,13 +194,10 @@ Assert.assertEquals(0, mTestObserver.updateCachedEngineCallback.getCallCount()); // Accept the ToS. - if (freProperties.getBoolean(FirstRunActivityBase.SHOW_WELCOME_PAGE)) { - clickButton(mActivity, R.id.terms_accept, "Failed to accept ToS"); - mTestObserver.jumpToPageCallback.waitForCallback( - "Failed to try moving to the next screen", 0); - mTestObserver.acceptTermsOfServiceCallback.waitForCallback( - "Failed to accept the ToS", 0); - } + clickButton(mActivity, R.id.terms_accept, "Failed to accept ToS"); + mTestObserver.jumpToPageCallback.waitForCallback( + "Failed to try moving to the next screen", 0); + mTestObserver.acceptTermsOfServiceCallback.waitForCallback("Failed to accept the ToS", 0); // Acknowledge that Data Saver will be enabled. if (freProperties.getBoolean(FirstRunActivityBase.SHOW_DATA_REDUCTION_PAGE)) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareHelperTest.java deleted file mode 100644 index c59ad01..0000000 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareHelperTest.java +++ /dev/null
@@ -1,158 +0,0 @@ -// 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.share; - -import android.net.Uri; -import android.support.test.filters.SmallTest; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.Callback; -import org.chromium.base.ContentUriUtils; -import org.chromium.base.task.AsyncTask; -import org.chromium.base.test.util.CallbackHelper; -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.chrome.browser.ChromeActivity; -import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.FileProviderHelper; -import org.chromium.chrome.test.ChromeActivityTestRule; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.ui.base.Clipboard; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -/** - * Tests of {@link ShareHelper}. - */ -@RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class ShareHelperTest { - @Rule - public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = - new ChromeActivityTestRule<>(ChromeActivity.class); - - private static final long WAIT_TIMEOUT_SECONDS = 5L; - private static final byte[] TEST_IMAGE_DATA = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - - private class GenerateUriCallback extends CallbackHelper implements Callback<Uri> { - private Uri mImageUri; - - public Uri getImageUri() { - return mImageUri; - } - - @Override - public void onResult(Uri uri) { - mImageUri = uri; - notifyCalled(); - } - } - - private class AsyncTaskRunnableHelper extends CallbackHelper implements Runnable { - @Override - public void run() { - notifyCalled(); - } - } - - @Before - public void setUp() { - mActivityTestRule.startMainActivityFromLauncher(); - ContentUriUtils.setFileProviderUtil(new FileProviderHelper()); - } - - @After - public void tearDown() throws TimeoutException { - Clipboard.getInstance().setText(""); - clearSharedImages(); - } - - private int fileCount(File file) { - if (file.isFile()) { - return 1; - } - - int count = 0; - if (file.isDirectory()) { - for (File f : file.listFiles()) count += fileCount(f); - } - return count; - } - - private boolean filepathExists(File file, String filepath) { - if (file.isFile() && filepath.endsWith(file.getName())) { - return true; - } - - if (file.isDirectory()) { - for (File f : file.listFiles()) { - if (filepathExists(f, filepath)) return true; - } - } - return false; - } - - private Uri generateAnImageToClipboard() throws TimeoutException { - GenerateUriCallback imageCallback = new GenerateUriCallback(); - ShareHelper.generateUriFromData( - mActivityTestRule.getActivity(), TEST_IMAGE_DATA, imageCallback); - imageCallback.waitForCallback(0, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS); - Clipboard.getInstance().setImageUri(imageCallback.getImageUri()); - return imageCallback.getImageUri(); - } - - private void clearSharedImages() throws TimeoutException { - ShareHelper.clearSharedImages(); - - // ShareHelper::clearSharedImages uses AsyncTask.SERIAL_EXECUTOR to schedule a clearing the - // shared folder job, so schedule a new job and wait for the new job finished to make sure - // ShareHelper::clearSharedImages's clearing folder job finished. - AsyncTaskRunnableHelper runnableHelper = new AsyncTaskRunnableHelper(); - AsyncTask.SERIAL_EXECUTOR.execute(runnableHelper); - runnableHelper.waitForCallback(0, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS); - } - - private int fileCountInShareDirectory() throws IOException { - return fileCount(ShareHelper.getSharedFilesDirectory()); - } - - private boolean fileExistsInShareDirectory(Uri fileUri) throws IOException { - return filepathExists(ShareHelper.getSharedFilesDirectory(), fileUri.getPath()); - } - - @Test - @SmallTest - public void clipboardUriDoNotClearTest() throws TimeoutException, IOException { - generateAnImageToClipboard(); - generateAnImageToClipboard(); - Uri clipboardUri = generateAnImageToClipboard(); - Assert.assertEquals(3, fileCountInShareDirectory()); - - clearSharedImages(); - Assert.assertEquals(1, fileCountInShareDirectory()); - Assert.assertTrue(fileExistsInShareDirectory(clipboardUri)); - } - - @Test - @SmallTest - public void clearEverythingIfNoClipboardImageTest() throws TimeoutException, IOException { - generateAnImageToClipboard(); - generateAnImageToClipboard(); - generateAnImageToClipboard(); - Assert.assertEquals(3, fileCountInShareDirectory()); - - Clipboard.getInstance().setText(""); - clearSharedImages(); - Assert.assertEquals(0, fileCountInShareDirectory()); - } -}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java index 4de76bf..c67fc38 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
@@ -19,6 +19,7 @@ import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler; import org.chromium.chrome.browser.externalnav.ExternalNavigationParams; import org.chromium.chrome.test.ChromeActivityTestRule; @@ -72,7 +73,7 @@ class TestExternalNavigationHandler extends ExternalNavigationHandler { public TestExternalNavigationHandler() { - super(mActivity.getActivityTab()); + super(new ExternalNavigationDelegateImpl(mActivity.getActivityTab())); } @Override
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java index edf3ba7..9941d670 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java
@@ -191,13 +191,12 @@ assertFalse(mSequencer.calledSetFirstRunFlowSignInComplete); Bundle bundle = mSequencer.returnedBundle; - assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_WELCOME_PAGE)); assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_SIGNIN_PAGE)); assertFalse(bundle.getBoolean(FirstRunActivityBase.SHOW_DATA_REDUCTION_PAGE)); assertFalse(bundle.getBoolean(FirstRunActivityBase.SHOW_SEARCH_ENGINE_PAGE)); assertEquals(ChildAccountStatus.NOT_CHILD, bundle.getInt(SigninFirstRunFragment.CHILD_ACCOUNT_STATUS)); - assertEquals(5, bundle.size()); + assertEquals(4, bundle.size()); } @Test @@ -219,7 +218,6 @@ assertTrue(mSequencer.calledSetFirstRunFlowSignInComplete); Bundle bundle = mSequencer.returnedBundle; - assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_WELCOME_PAGE)); assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_SIGNIN_PAGE)); assertFalse(bundle.getBoolean(FirstRunActivityBase.SHOW_DATA_REDUCTION_PAGE)); assertFalse(bundle.getBoolean(FirstRunActivityBase.SHOW_SEARCH_ENGINE_PAGE)); @@ -227,7 +225,7 @@ bundle.getInt(SigninFirstRunFragment.CHILD_ACCOUNT_STATUS)); assertEquals( DEFAULT_ACCOUNT, bundle.getString(SigninFirstRunFragment.FORCE_SIGNIN_ACCOUNT_TO)); - assertEquals(6, bundle.size()); + assertEquals(5, bundle.size()); } @Test @@ -249,13 +247,12 @@ assertFalse(mSequencer.calledSetFirstRunFlowSignInComplete); Bundle bundle = mSequencer.returnedBundle; - assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_WELCOME_PAGE)); assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_SIGNIN_PAGE)); assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_DATA_REDUCTION_PAGE)); assertFalse(bundle.getBoolean(FirstRunActivityBase.SHOW_SEARCH_ENGINE_PAGE)); assertEquals(ChildAccountStatus.NOT_CHILD, bundle.getInt(SigninFirstRunFragment.CHILD_ACCOUNT_STATUS)); - assertEquals(5, bundle.size()); + assertEquals(4, bundle.size()); } @Test @@ -277,13 +274,12 @@ assertFalse(mSequencer.calledSetFirstRunFlowSignInComplete); Bundle bundle = mSequencer.returnedBundle; - assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_WELCOME_PAGE)); assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_SIGNIN_PAGE)); assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_DATA_REDUCTION_PAGE)); assertTrue(bundle.getBoolean(FirstRunActivityBase.SHOW_SEARCH_ENGINE_PAGE)); assertEquals(ChildAccountStatus.NOT_CHILD, bundle.getInt(SigninFirstRunFragment.CHILD_ACCOUNT_STATUS)); - assertEquals(5, bundle.size()); + assertEquals(4, bundle.size()); } @Test
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index e90d6f1..f1c2f828 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -1634,7 +1634,7 @@ <message name="IDS_SETTINGS_INTERNET_TETHER_CONNECTION_NOT_NOW_BUTTON" desc="Settings > Internet > Tether Connection Dialog > Button which, when tapped, closes the dialog and does not connect the device."> Not now </message> - <message name="IDS_SETTINGS_INTERNET_TETHER_CONNECTION_CONNECT_BUTTON" desc="Settings > Internet > Tether Connection Dialog > Button which, when tapped, starts a connection attempt to the device."> + <message name="IDS_SETTINGS_INTERNET_TETHER_CONNECTION_CONNECT_BUTTON" desc="Settings > Internet > Tether Connection Dialog > Button which, when tapped, starts a connection attempt to the device."> Connect </message> <message name="IDS_SETTINGS_INTERNET_LOOKING_FOR_MOBILE_NETWORK" desc="Text shown when viewing the Mobile data page when there are no cellular or tether networks available."> @@ -2298,5 +2298,88 @@ <message name="IDS_SETTINGS_SET_DATE_TIME" desc="Label for the button that shows the dialog for setting the system date and time."> Set date and time </message> + + <!-- Device Keyboard page (OS settings) --> + <message name="IDS_SETTINGS_KEYBOARD_TITLE" desc="In Device Settings, the title of the keyboard settings subpage."> + Keyboard + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_LEFT_CTRL" desc="In Device Settings, the label and dropdown list item for the Ctrl key."> + Ctrl + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_LEFT_ALT" desc="In Device Settings, the label and dropdown list item for the Alt key."> + Alt + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_CAPS_LOCK" desc="In Device Settings, the label and dropdown list item for the Caps Lock key."> + Caps Lock + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_COMMAND" desc="In Device Settings, the dropdown list item for the external Command key on Apple keyboards when there's no internal keyboard on the device."> + Command + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_DIAMOND" desc="In Device Settings, the label for the Diamond key."> + Diamond + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_ESCAPE" desc="In Device Settings, the dropdown list item for the Escape key."> + Escape + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_BACKSPACE" desc="In Device Settings, the dropdown list item for the Backspace key."> + Backspace + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_ASSISTANT" desc="In Device Settings, the label and dropdown list item for the Assistant key."> + Assistant + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_DISABLED" desc="In Device Settings, the dropdown list item for a disabled key."> + Disabled + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_COMMAND" desc="In Device Settings, the dropdown list item for the external Command key on Apple keyboards."> + External Command + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_META" desc="In Device Settings, the dropdown list item for the external Meta key (Search key on ChromeOS keyboards, and Windows key on Windows keyboards)."> + External Meta + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_META" desc="In Device Settings, the dropdown list item for the external Meta key (Search key on ChromeOS keyboards, and Windows key on Windows keyboards) when there's no internal keyboard on the device."> + Meta + </message> + <message name="IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS" desc="In Device Settings, the checkbox label for interpreting the top-row keys as function keys instead."> + Treat top-row keys as function keys + </message> + <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_ENABLE" desc="The checkbox label for enabling keyboard auto-repeat."> + Enable auto-repeat + </message> + <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY" desc="The label for the slider for the delay before auto-repeat begins. The delay is the amount of time a key must be held down before auto-repeating begins."> + Delay before repeat + </message> + <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_LONG" desc="The label for the beginning of the auto-repeat delay slider, representing a long delay."> + Long + </message> + <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_SHORT" desc="The label for the end of the auto-repeat delay slider, representing a short delay."> + Short + </message> + <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE" desc="The label for the slider for the auto-repeat rate. The rate is how many times a key repeats per second once auto-repeating has begun."> + Repeat rate + </message> + <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE_SLOW" desc="The label for the beginning of the auto-repeat rate slider, representing a slow repeat rate."> + Slow + </message> + <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_FAST" desc="The label for the end of the auto-repeat rate slider, representing a fast repeat rate."> + Fast + </message> + <message name="IDS_SETTINGS_KEYBOARD_SHOW_SHORTCUT_VIEWER" desc="The link to open the keyboard shortut viewer."> + View keyboard shortcuts + </message> + <message name="IDS_SETTINGS_KEYBOARD_SHOW_LANGUAGE_AND_INPUT" desc="The link to navigate to the language and input method settings."> + Change language and input settings + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_LAUNCHER" desc="In Device Settings, the label and dropdown list item for the Search key on keyboard layouts of newer Chromebooks."> + Launcher + </message> + <message name="IDS_SETTINGS_KEYBOARD_KEY_SEARCH" desc="In Device Settings, the label and dropdown list item for the Search key."> + Search + </message> + <message name="IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_LAYOUT2_DESCRIPTION" desc="In Device Settings, when device uses 2017 keyboard layout, the label describing how to use the top-row keys' original actions when they are set to behave like function keys."> + Hold the Launcher key to switch the behavior of the top-row keys + </message> + <message name="IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_DESCRIPTION" desc="In Device Settings, the label describing how to use the top-row keys' original actions when they are set to behave like function keys."> + Hold the Search key to switch the behavior of the top-row keys + </message> </if> </grit-part> \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index ba4710a3..9c7ea61 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2903,92 +2903,10 @@ <message name="IDS_SETTINGS_DEVICE_TITLE" desc="Name of the settings page which displays device and peripheral settings."> Device </message> - <message name="IDS_SETTINGS_KEYBOARD_TITLE" desc="In Device Settings, the title of the keyboard settings subpage."> - Keyboard - </message> <!-- Touchpad --> <message name="IDS_SETTINGS_SCROLL_LABEL" desc="In Device Settings, the title above the radio buttons to choose the scrolling behavior."> Scrolling </message> - <!-- Keyboard --> - <message name="IDS_SETTINGS_KEYBOARD_KEY_SEARCH" desc="In Device Settings, the label and dropdown list item for the Search key."> - Search - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_LAUNCHER" desc="In Device Settings, the label and dropdown list item for the Search key on keyboard layouts of newer Chromebooks."> - Launcher - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_LEFT_CTRL" desc="In Device Settings, the label and dropdown list item for the Ctrl key."> - Ctrl - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_LEFT_ALT" desc="In Device Settings, the label and dropdown list item for the Alt key."> - Alt - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_CAPS_LOCK" desc="In Device Settings, the label and dropdown list item for the Caps Lock key."> - Caps Lock - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_DIAMOND" desc="In Device Settings, the label for the Diamond key."> - Diamond - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_ESCAPE" desc="In Device Settings, the dropdown list item for the Escape key."> - Escape - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_BACKSPACE" desc="In Device Settings, the dropdown list item for the Backspace key."> - Backspace - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_ASSISTANT" desc="In Device Settings, the label and dropdown list item for the Assistant key."> - Assistant - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_DISABLED" desc="In Device Settings, the dropdown list item for a disabled key."> - Disabled - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_COMMAND" desc="In Device Settings, the dropdown list item for the external Command key on Apple keyboards."> - External Command - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_COMMAND" desc="In Device Settings, the dropdown list item for the external Command key on Apple keyboards when there's no internal keyboard on the device."> - Command - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_META" desc="In Device Settings, the dropdown list item for the external Meta key (Search key on ChromeOS keyboards, and Windows key on Windows keyboards)."> - External Meta - </message> - <message name="IDS_SETTINGS_KEYBOARD_KEY_META" desc="In Device Settings, the dropdown list item for the external Meta key (Search key on ChromeOS keyboards, and Windows key on Windows keyboards) when there's no internal keyboard on the device."> - Meta - </message> - <message name="IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS" desc="In Device Settings, the checkbox label for interpreting the top-row keys as function keys instead."> - Treat top-row keys as function keys - </message> - <message name="IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_DESCRIPTION" desc="In Device Settings, the label describing how to use the top-row keys' original actions when they are set to behave like function keys."> - Hold the Search key to switch the behavior of the top-row keys - </message> - <message name="IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_LAYOUT2_DESCRIPTION" desc="In Device Settings, when device uses 2017 keyboard layout, the label describing how to use the top-row keys' original actions when they are set to behave like function keys."> - Hold the Launcher key to switch the behavior of the top-row keys - </message> - <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_ENABLE" desc="The checkbox label for enabling keyboard auto-repeat."> - Enable auto-repeat - </message> - <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY" desc="The label for the slider for the delay before auto-repeat begins. The delay is the amount of time a key must be held down before auto-repeating begins."> - Delay before repeat - </message> - <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_LONG" desc="The label for the beginning of the auto-repeat delay slider, representing a long delay."> - Long - </message> - <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_SHORT" desc="The label for the end of the auto-repeat delay slider, representing a short delay."> - Short - </message> - <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE" desc="The label for the slider for the auto-repeat rate. The rate is how many times a key repeats per second once auto-repeating has begun."> - Repeat rate - </message> - <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE_SLOW" desc="The label for the beginning of the auto-repeat rate slider, representing a slow repeat rate."> - Slow - </message> - <message name="IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_FAST" desc="The label for the end of the auto-repeat rate slider, representing a fast repeat rate."> - Fast - </message> - <message name="IDS_SETTINGS_KEYBOARD_SHOW_SHORTCUT_VIEWER" desc="The link to open the keyboard shortut viewer."> - View keyboard shortcuts - </message> - <message name="IDS_SETTINGS_KEYBOARD_SHOW_LANGUAGE_AND_INPUT" desc="The link to navigate to the language and input method settings."> - Change language and input settings - </message> <!-- Storage --> <message name="IDS_SETTINGS_STORAGE_TITLE" desc="In Device Settings, the title for storage management.">
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index b4748883..b66d970 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1956,6 +1956,7 @@ "policy/status_collector/device_status_collector.h", "policy/status_collector/enterprise_activity_storage.cc", "policy/status_collector/enterprise_activity_storage.h", + "policy/status_collector/interval_map.h", "policy/status_collector/status_collector.cc", "policy/status_collector/status_collector.h", "policy/status_collector/status_collector_state.cc", @@ -2996,6 +2997,7 @@ "policy/secondary_google_account_signin_policy_handler_unittest.cc", "policy/server_backed_state_keys_broker_unittest.cc", "policy/single_app_install_event_log_unittest.cc", + "policy/status_collector/interval_map_unittest.cc", "policy/status_uploader_unittest.cc", "policy/system_log_uploader_unittest.cc", "policy/system_proxy_settings_policy_handler_unittest.cc",
diff --git a/chrome/browser/chromeos/policy/status_collector/interval_map.h b/chrome/browser/chromeos/policy/status_collector/interval_map.h new file mode 100644 index 0000000..a9db01b --- /dev/null +++ b/chrome/browser/chromeos/policy/status_collector/interval_map.h
@@ -0,0 +1,297 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_INTERVAL_MAP_H_ +#define CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_INTERVAL_MAP_H_ + +#include <algorithm> +#include <functional> +#include <limits> +#include <map> +#include <type_traits> +#include <utility> + +#include "base/logging.h" + +namespace policy { + +// An IntervalMap<KeyType, ValueType> maps every value of KeyType to +// a ValueType, and incrementing, decrementing and setting ranges of values +// has been optimized. The default state is to map all values in +// KeyType to ValueType(). (Which is usually zero.) +// +// Set/Increment operations should generally take +// O(log(N)) + O(M) time where N is the number of intervals in the map and +// M is the number of modified intervals. +// +// Internally, IntervalMap<> uses an std::map, where the beginning of each +// interval is stored along with the value for that interval. Adjacent intervals +// which have the same value are automatically merged. For instance, if you did: +// +// IntervalMap<int, int> tmp; +// tmp.IncrementInterval(2, 5, 2); +// tmp.IncrementInterval(4, 6, 1); +// +// Then: +// tmp[0] = 0 +// tmp[1] = 0 +// tmp[2] = 2 +// tmp[3] = 2 +// tmp[4] = 3 +// tmp[5] = 1 +// tmp[6] = 0 +// +// If you iterate over tmp, you get the following intervals: +// -maxint .. 2 => 0 +// 2 .. 4 => 2 +// 4 .. 5 => 3 +// 5 .. 6 => 1 +// 6 .. maxint => 0 +// +// Internally, this would be stored in a map as: +// -maxint:0, 2:2, 4:3, 5:1, 6:0 +// +// TODO(hubbe): Consider consolidating with media::Ranges. + +// Simple interval class. +// Interval ends are always non-inclusive. +// Please note that end <= begin is a valid (but empty) interval. +template <typename T> +struct Interval { + public: + Interval(const T& begin, const T& end) : begin(begin), end(end) { + static_assert(std::is_integral<T>::value, "Integral types only."); + } + + // May return empty intervals (begin >= end). + Interval Intersect(const Interval& other) const { + return Interval(std::max(begin, other.begin), std::min(end, other.end)); + } + + bool Empty() const { return begin >= end; } + + T begin; + T end; +}; + +// The IntervalMapConstIterator points to an interval in an +// IntervalMap where all values are the same. Calling ++/-- +// goes to the next/previous interval, which is guaranteed to +// have values different from the current interval. +template <typename KeyType, + typename ValueType, + class Compare = std::less<KeyType>, + class NumericLimits = std::numeric_limits<KeyType>> +class IntervalMapConstIterator { + public: + typedef std::map<KeyType, ValueType, Compare> MapType; + IntervalMapConstIterator() { + static_assert(std::is_integral<KeyType>::value, "Integral types only."); + } + IntervalMapConstIterator(const MapType* map, + typename MapType::const_iterator iter) + : map_(map), iter_(iter) { + static_assert(std::is_integral<KeyType>::value, "Integral types only."); + } + + bool operator==(const IntervalMapConstIterator& other) const { + return iter_ == other.iter_; + } + + bool operator!=(const IntervalMapConstIterator& other) const { + return iter_ != other.iter_; + } + + // Returns the beginning of the current interval. + KeyType interval_begin() const { + DCHECK(iter_ != map_->end()); + return iter_->first; + } + + // Returns the end of the current interval, non-inclusive. + KeyType interval_end() const { + DCHECK(iter_ != map_->end()); + typename MapType::const_iterator next = iter_; + ++next; + if (next == map_->end()) { + return NumericLimits::max(); + } else { + return next->first; + } + } + + // Returns the current interval. + Interval<KeyType> interval() const { + return Interval<KeyType>(interval_begin(), interval_end()); + } + + // Returns the value associated with the current interval. + ValueType value() const { + DCHECK(iter_ != map_->end()); + return iter_->second; + } + + // Needed to make the following construct work: + // for (const auto& interval_value_pair : interval_map) + std::pair<Interval<KeyType>, ValueType> operator*() const { + return std::make_pair(interval(), value()); + } + + // Go to the next interval. + // The beginning of the next interval always matches the end of the current + // interval. (But should always have a different value.) + // Not allowed if we're already at map_->end(). + void operator++() { + DCHECK(iter_ != map_->end()); + ++iter_; + } + + // Go to the previous interval. + // The end of the previous interval always matches the beginning of the + // current interval. (But should always have a different value.) + // Not allowed if we're already at map_->begin(). + void operator--() { + DCHECK(iter_ != map_->begin()); + --iter_; + } + + private: + const MapType* map_; + + // Pointer to the entry in the IntervalMap that specifies the + // beginning of the current interval. + typename MapType::const_iterator iter_; +}; + +template <typename KeyType, + typename ValueType, + class Compare = std::less<KeyType>, + class NumericLimits = std::numeric_limits<KeyType>> +class IntervalMap { + public: + typedef std::map<KeyType, ValueType, Compare> MapType; + typedef IntervalMapConstIterator<KeyType, ValueType, Compare, NumericLimits> + const_iterator; + IntervalMap() { + static_assert(std::is_integral<KeyType>::value, "Integral types only."); + // Adding an explicit entry for the default interval is not strictly needed, + // but simplifies the code a lot. + map_[NumericLimits::min()] = ValueType(); + } + + // Returns the value at a particular point. + // Defaults to ValueType(). + ValueType operator[](const KeyType& k) const { + typename MapType::const_iterator i = map_.upper_bound(k); + DCHECK(i != map_.begin()); + --i; + return i->second; + } + + // Increase [from..to) by |how_much|. + void IncrementInterval(KeyType from, KeyType to, ValueType how_much) { + if (to <= from || how_much == 0) + return; + typename MapType::iterator a = MakeEntry(from); + typename MapType::iterator b = MakeEntry(to); + for (typename MapType::iterator i = a; i != b; ++i) { + i->second += how_much; + } + RemoveDuplicates(a); + // b may be invalid + RemoveDuplicates(map_.lower_bound(to)); + } + + // Set [from..to) to |how_much|. + void SetInterval(KeyType from, KeyType to, ValueType how_much) { + if (to <= from) + return; + typename MapType::iterator a = MakeEntry(from); + typename MapType::iterator b = MakeEntry(to); + a->second = how_much; + while (true) { + typename MapType::iterator c = a; + ++c; + if (c == b) { + break; + } else { + map_.erase(c); + } + } + RemoveDuplicates(a); + // b may be invalid + RemoveDuplicates(map_.lower_bound(to)); + } + + // Returns an iterator to the first interval. + // Note, there is always at least one interval. + const_iterator begin() const { return const_iterator(&map(), map_.begin()); } + + // Returns an end marker iterator. + const_iterator end() const { return const_iterator(&map(), map_.end()); } + + // Returns an iterator to the interval containing |k|. + // Always returns a valid iterator. + const_iterator find(KeyType k) const { + typename MapType::const_iterator iter = map_.upper_bound(k); + DCHECK(iter != map_.begin()); + --iter; + return const_iterator(&map(), iter); + } + + bool empty() const { return map().size() == 1; } + void clear() { + map_.clear(); + map_[NumericLimits::min()] = ValueType(); + } + + private: + const MapType& map() const { return map_; } + + // Make an entry in map_ with the key |k| and return it's iterator. + // If such an entry already exists, just re-use it. + // If a new entry is created, it's value will be set to the same + // as the preceding entry, or ValueType() if no preceding entry exists. + // After calling this function, we'll need to call RemoveDuplicates() + // to clean up any duplicates that we made. + typename MapType::iterator MakeEntry(KeyType k) { + auto insert_result = map_.emplace(k, ValueType()); + if (insert_result.second) { + if (insert_result.first != map_.begin()) { + typename MapType::iterator i = insert_result.first; + --i; + insert_result.first->second = i->second; + } + } + return insert_result.first; + } + + // Remove duplicates before and after |i|. + void RemoveDuplicates(typename MapType::iterator i) { + if (i == map_.end()) + return; + + typename MapType::iterator first = i; + typename MapType::iterator second = i; + if (i != map_.begin()) { + --first; + if (first->second == second->second) { + map_.erase(second); + second = first; + } else { + first = second; + } + } + ++second; + if (second != map_.end() && first->second == second->second) { + map_.erase(second); + } + } + + MapType map_; +}; + +} // namespace policy + +#endif // CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_INTERVAL_MAP_H_
diff --git a/chrome/browser/chromeos/policy/status_collector/interval_map_unittest.cc b/chrome/browser/chromeos/policy/status_collector/interval_map_unittest.cc new file mode 100644 index 0000000..860405f --- /dev/null +++ b/chrome/browser/chromeos/policy/status_collector/interval_map_unittest.cc
@@ -0,0 +1,272 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> + +#include <string> +#include <vector> + +#include "base/rand_util.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/chromeos/policy/status_collector/interval_map.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +// Our tests only modify the interval map entries in [0..kTestSize). +// We need this to be big enough to hit tricky corner cases, but small +// enough that we get lots of entry duplication to clean up. +// Also, SimpleIntervalMap uses a vector of size kTestSize to emulate +// a intervalmap, so making this too big will the test down a lot. +const int kTestSize = 16; + +class SimpleIntervalMap { + public: + SimpleIntervalMap() : data_(kTestSize) {} + + void IncrementInterval(int32_t from, int32_t to, int32_t how_much) { + for (int32_t i = from; i < to; i++) { + data_[i] += how_much; + } + } + + void SetInterval(int32_t from, int32_t to, int32_t how_much) { + for (int32_t i = from; i < to; i++) { + data_[i] = how_much; + } + } + + int32_t operator[](int32_t index) const { return data_[index]; } + + private: + std::vector<int32_t> data_; +}; + +class IntervalMapTest : public testing::Test { + public: + IntervalMapTest() = default; + void IncrementInterval(int32_t from, int32_t to, int32_t how_much) { + truth_.IncrementInterval(from, to, how_much); + testee_.IncrementInterval(from, to, how_much); + std::string message = + base::StringPrintf("After [%d - %d) += %d", from, to, how_much); + Compare(message); + } + + void SetInterval(int32_t from, int32_t to, int32_t how_much) { + truth_.SetInterval(from, to, how_much); + testee_.SetInterval(from, to, how_much); + std::string message = + base::StringPrintf("After [%d - %d) += %d", from, to, how_much); + Compare(message); + } + + // Will exercise operator[] and IntervalMap::const_iterator. + void Compare(const std::string& message) { + bool had_fail = HasFailure(); + for (int i = 0; i < kTestSize; i++) { + EXPECT_EQ(truth_[i], testee_[i]) << " i = " << i << " " << message; + } + EXPECT_EQ(testee_[-1], 0) << message; + EXPECT_EQ(testee_[kTestSize], 0) << message; + int32_t prev_ = 0; + int32_t end_of_last_interval = 0; + int32_t num_intervals = 0; + for (const auto& r : testee_) { + num_intervals++; + EXPECT_LT(r.first.begin, r.first.end); + if (r.first.begin == std::numeric_limits<int32_t>::min()) { + EXPECT_EQ(0, r.second); + } else { + EXPECT_EQ(end_of_last_interval, r.first.begin); + EXPECT_GE(r.first.begin, 0) << message; + EXPECT_LE(r.first.begin, kTestSize) << message; + EXPECT_NE(r.second, prev_) << message; + } + end_of_last_interval = r.first.end; + prev_ = r.second; + } + EXPECT_EQ(prev_, 0) << message; + + if (HasFailure() && !had_fail) { + for (int i = 0; i < kTestSize; i++) { + LOG(ERROR) << i << ": Truth =" << truth_[i] + << " Testee = " << testee_[i]; + } + for (const auto& r : testee_) { + LOG(ERROR) << "Interval: " << r.first.begin << " - " << r.first.end + << " = " << r.second; + } + } + } + + void Clear() { + for (int j = 0; j < kTestSize; j++) { + IncrementInterval(j, j + 1, -truth_[j]); + } + } + + protected: + SimpleIntervalMap truth_; + policy::IntervalMap<int32_t, int32_t> testee_; +}; +} // namespace + +TEST_F(IntervalMapTest, SimpleTest) { + IncrementInterval(3, 7, 4); + EXPECT_EQ(0, testee_[0]); + EXPECT_EQ(0, testee_[2]); + EXPECT_EQ(4, testee_[3]); + EXPECT_EQ(4, testee_[5]); + EXPECT_EQ(4, testee_[6]); + EXPECT_EQ(0, testee_[7]); + IncrementInterval(3, 7, -4); + EXPECT_TRUE(testee_.empty()); +} + +TEST_F(IntervalMapTest, SimpleIncrementTest) { + IncrementInterval(3, 7, 1); + IncrementInterval(6, 10, 2); + EXPECT_EQ(0, testee_[2]); + EXPECT_EQ(1, testee_[3]); + EXPECT_EQ(1, testee_[5]); + EXPECT_EQ(3, testee_[6]); + EXPECT_EQ(2, testee_[7]); + EXPECT_EQ(2, testee_[9]); + EXPECT_EQ(0, testee_[10]); + SetInterval(3, 12, 0); + EXPECT_TRUE(testee_.empty()); +} + +TEST_F(IntervalMapTest, IncrementJoinIntervalsTest) { + IncrementInterval(3, 5, 1); + IncrementInterval(7, 8, 1); + IncrementInterval(9, 11, 1); + IncrementInterval(5, 7, 1); + IncrementInterval(8, 9, 1); + auto i = testee_.find(5); + EXPECT_EQ(3, i.interval_begin()); + EXPECT_EQ(11, i.interval_end()); + EXPECT_EQ(1, i.value()); +} + +TEST_F(IntervalMapTest, SetJoinIntervalsTest) { + SetInterval(3, 5, 1); + SetInterval(7, 8, 1); + SetInterval(9, 11, 1); + SetInterval(5, 9, 1); // overwrites one interval + auto i = testee_.find(5); + EXPECT_EQ(3, i.interval_begin()); + EXPECT_EQ(11, i.interval_end()); + EXPECT_EQ(1, i.value()); +} + +TEST_F(IntervalMapTest, FindTest) { + IncrementInterval(5, 6, 1); + IncrementInterval(1, 10, 2); + int32_t min_value = std::numeric_limits<int32_t>::min(); + int32_t max_value = std::numeric_limits<int32_t>::max(); + auto i = testee_.find(0); + EXPECT_EQ(min_value, i.interval_begin()); + EXPECT_EQ(1, i.interval_end()); + EXPECT_EQ(0, i.value()); + i = testee_.find(4); + EXPECT_EQ(1, i.interval_begin()); + EXPECT_EQ(5, i.interval_end()); + EXPECT_EQ(2, i.value()); + i = testee_.find(5); + EXPECT_EQ(5, i.interval_begin()); + EXPECT_EQ(6, i.interval_end()); + EXPECT_EQ(3, i.value()); + i = testee_.find(6); + EXPECT_EQ(6, i.interval_begin()); + EXPECT_EQ(10, i.interval_end()); + EXPECT_EQ(2, i.value()); + i = testee_.find(9); + EXPECT_EQ(6, i.interval_begin()); + EXPECT_EQ(10, i.interval_end()); + EXPECT_EQ(2, i.value()); + i = testee_.find(10); + EXPECT_EQ(10, i.interval_begin()); + EXPECT_EQ(max_value, i.interval_end()); + EXPECT_EQ(0, i.value()); +} + +TEST_F(IntervalMapTest, MinMaxInt) { + int32_t min_value = std::numeric_limits<int32_t>::min(); + int32_t max_value = std::numeric_limits<int32_t>::max(); + + // Change a single value at minint + testee_.IncrementInterval(min_value, min_value + 1, 7); + EXPECT_EQ(7, testee_[min_value]); + EXPECT_EQ(0, testee_[min_value + 1]); + auto i = testee_.find(0); + EXPECT_EQ(min_value + 1, i.interval_begin()); + EXPECT_EQ(max_value, i.interval_end()); + EXPECT_EQ(0, i.value()); + --i; + EXPECT_TRUE(i == testee_.find(min_value)); + EXPECT_EQ(min_value, i.interval_begin()); + EXPECT_EQ(min_value + 1, i.interval_end()); + EXPECT_EQ(7, i.value()); + testee_.clear(); + + // Change a single value at maxint + // Note that we don't actually have a way to represent a range + // that includes maxint as the end of the interval is non-inclusive. + testee_.IncrementInterval(max_value - 1, max_value, 7); + EXPECT_EQ(7, testee_[max_value - 1]); + EXPECT_EQ(0, testee_[max_value - 2]); + i = testee_.find(0); + EXPECT_EQ(min_value, i.interval_begin()); + EXPECT_EQ(max_value - 1, i.interval_end()); + EXPECT_EQ(0, i.value()); + ++i; + EXPECT_TRUE(i == testee_.find(max_value - 1)); + EXPECT_EQ(max_value - 1, i.interval_begin()); + EXPECT_EQ(max_value, i.interval_end()); + EXPECT_EQ(7, i.value()); + + testee_.clear(); + + // Change entire range (almost) + testee_.IncrementInterval(min_value, max_value, 17); + EXPECT_EQ(17, testee_[min_value]); + EXPECT_EQ(17, testee_[0]); + EXPECT_EQ(17, testee_[max_value - 1]); + i = testee_.find(0); + EXPECT_EQ(min_value, i.interval_begin()); + EXPECT_EQ(max_value, i.interval_end()); + EXPECT_EQ(17, i.value()); + EXPECT_TRUE(i == testee_.find(max_value - 1)); + EXPECT_TRUE(i == testee_.find(min_value)); +} + +TEST_F(IntervalMapTest, RandomIncrementTest) { + for (int j = 0; j < 200; j++) { + Clear(); + for (int i = 0; i < 200; i++) { + int32_t begin = base::RandInt(0, kTestSize - 1 - 1); + int32_t end = begin + 1 + base::RandInt(0, kTestSize - begin - 1 - 1); + IncrementInterval(begin, end, base::RandInt(0, 1) ? 1 : -1); + if (HasFailure()) { + return; + } + } + } +} + +TEST_F(IntervalMapTest, RandomSetTest) { + for (int j = 0; j < 200; j++) { + Clear(); + for (int i = 0; i < 200; i++) { + int32_t begin = base::RandInt(0, kTestSize - 1 - 1); + int32_t end = begin + 1 + base::RandInt(0, kTestSize - begin - 1 - 1); + SetInterval(begin, end, base::RandInt(0, 3)); + if (HasFailure()) { + return; + } + } + } +}
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn index 58a25ed9..feaf309 100644 --- a/chrome/browser/download/android/BUILD.gn +++ b/chrome/browser/download/android/BUILD.gn
@@ -8,6 +8,7 @@ sources = [ "java/src/org/chromium/chrome/browser/download/DirectoryOption.java", "java/src/org/chromium/chrome/browser/download/DownloadConstants.java", + "java/src/org/chromium/chrome/browser/download/DownloadDelegateImpl.java", "java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java", "java/src/org/chromium/chrome/browser/download/DownloadFileProvider.java", "java/src/org/chromium/chrome/browser/download/DownloadFilter.java", @@ -24,6 +25,7 @@ "//base:base_java", "//base:jni_java", "//chrome/browser/util:java", + "//components/download/internal/common:internal_java", "//components/download/public/common:public_java", "//components/offline_items_collection/core:core_java", "//content/public/android:content_java",
diff --git a/chrome/browser/download/android/DEPS b/chrome/browser/download/android/DEPS index 077462f..73d8bc3 100644 --- a/chrome/browser/download/android/DEPS +++ b/chrome/browser/download/android/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+media/video", "+content/public/android/java/src/org/chromium/content_public", + "+components/download/internal/common", ]
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDelegateImpl.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDelegateImpl.java new file mode 100644 index 0000000..9dfa1597 --- /dev/null +++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDelegateImpl.java
@@ -0,0 +1,31 @@ +// 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.download; + +import android.net.Uri; + +import org.chromium.components.download.DownloadDelegate; + +/** + * Utility class that implements DownloadDelegate. + */ +public class DownloadDelegateImpl extends DownloadDelegate { + public DownloadDelegateImpl() {} + + @Override + public String remapGenericMimeType(String mimeType, String url, String filename) { + return MimeUtils.remapGenericMimeType(mimeType, url, filename); + } + + @Override + public Uri parseOriginalUrl(String originalUrl) { + return UriUtils.parseOriginalUrl(originalUrl); + } + + @Override + public boolean isDownloadOnSDCard(String filePath) { + return DownloadDirectoryProvider.isDownloadOnSDCard(filePath); + } +}
diff --git a/chrome/browser/flags/BUILD.gn b/chrome/browser/flags/BUILD.gn index 2fbae9b..4b4ece6 100644 --- a/chrome/browser/flags/BUILD.gn +++ b/chrome/browser/flags/BUILD.gn
@@ -9,6 +9,7 @@ "android/java/src/org/chromium/chrome/browser/flags/BooleanCachedFieldTrialParameter.java", "android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameter.java", "android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java", + "android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java", "android/java/src/org/chromium/chrome/browser/flags/StringCachedFieldTrialParameter.java", ] deps = [
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java new file mode 100644 index 0000000..6fbaff9 --- /dev/null +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java
@@ -0,0 +1,31 @@ +// 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.chromium.chrome.browser.preferences.SharedPreferencesManager; + +/** + * An int-type {@link CachedFieldTrialParameter}. + */ +public class IntCachedFieldTrialParameter extends CachedFieldTrialParameter { + private int mDefaultValue; + + public IntCachedFieldTrialParameter( + String featureName, String variationName, int defaultValue) { + super(featureName, variationName, FieldTrialParameterType.INT, null); + mDefaultValue = defaultValue; + } + + public int getDefaultValue() { + return mDefaultValue; + } + + @Override + void cacheToDisk() { + int value = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( + getFeatureName(), getParameterName(), getDefaultValue()); + SharedPreferencesManager.getInstance().writeInt(getSharedPreferenceKey(), value); + } +}
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 45af542d..2e1162a 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -412,16 +412,17 @@ #if !defined(OS_ANDROID) registry->RegisterBooleanPref(prefs::kShowCastIconInToolbar, false); #endif // !defined(OS_ANDROID) + registry->RegisterTimePref(prefs::kProfileCreationTime, base::Time()); } ProfileImpl::ProfileImpl( const base::FilePath& path, Delegate* delegate, CreateMode create_mode, - base::Time creation_time, + base::Time path_creation_time, scoped_refptr<base::SequencedTaskRunner> io_task_runner) : path_(path), - creation_time_(creation_time), + path_creation_time_(path_creation_time), io_task_runner_(std::move(io_task_runner)), io_data_(this), last_session_exit_type_(EXIT_NORMAL), @@ -607,6 +608,15 @@ TRACE_EVENT0("browser", "ProfileImpl::DoFinalInit") PrefService* prefs = GetPrefs(); + + // Do not override the existing pref in case a profile directory is copied, or + // if the file system does not support creation time and the property (i.e. + // st_ctim in posix which is actually the last status change time when the + // inode was last updated) use to mimic it changes because of some other + // modification. + if (!prefs->HasPrefPath(prefs::kProfileCreationTime)) + prefs->SetTime(prefs::kProfileCreationTime, path_creation_time_); + pref_change_registrar_.Init(prefs); pref_change_registrar_.Add( prefs::kSupervisedUserId, @@ -831,7 +841,7 @@ } base::Time ProfileImpl::GetCreationTime() const { - return creation_time_; + return prefs_->GetTime(prefs::kProfileCreationTime); } scoped_refptr<base::SequencedTaskRunner> ProfileImpl::GetIOTaskRunner() { @@ -1411,7 +1421,7 @@ #endif // defined(OS_CHROMEOS) void ProfileImpl::SetCreationTimeForTesting(base::Time creation_time) { - creation_time_ = creation_time; + prefs_->SetTime(prefs::kProfileCreationTime, creation_time); } GURL ProfileImpl::GetHomePage() {
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index af04facc..326e2e9 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/optional.h" +#include "base/time/time.h" #include "base/timer/timer.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" @@ -181,7 +182,7 @@ ProfileImpl(const base::FilePath& path, Delegate* delegate, CreateMode create_mode, - base::Time creation_time, + base::Time path_creation_time, scoped_refptr<base::SequencedTaskRunner> io_task_runner); #if defined(OS_ANDROID) @@ -223,7 +224,7 @@ base::FilePath path_; - base::Time creation_time_; + base::Time path_creation_time_; // Task runner used for file access in the profile path. scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js index 1a3eecb8..cc564fb 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing.js
@@ -56,7 +56,6 @@ // A rich text field is one where selection gets placed on a DOM // descendant to a root text field. This is one of: // - content editables (detected via richly editable state) - // - the node is a textarea // // The only other editables we expect are all single line (including those // from ARC++). @@ -245,6 +244,14 @@ } const startIndex = this.start - lineStart; const endIndex = this.end - lineStart; + + // If the line is not the last line, and is empty, insert an explicit line + // break so that braille output is correctly cleared and has a position for + // a caret to be shown. + if (lineText == '' && lineIndex < this.lineBreaks_.length - 1) { + lineText = '\n'; + } + const spannable = new Spannable(lineText, new Output.NodeSpan(this.node_)); ChromeVox.braille.write( new NavBraille({text: spannable, startIndex, endIndex}));
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js index 9cb17c4..ee42628 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/editing_test.js
@@ -1361,3 +1361,23 @@ input.focus(); }); }); + +TEST_F('ChromeVoxEditingTest', 'TextAreaBrailleEmptyLine', function() { + const mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree('<textarea></textarea>', function(root) { + const textarea = root.find({role: RoleType.TEXT_FIELD}); + this.listenOnce(textarea, 'focus', function() { + this.listenOnce(textarea, 'valueChanged', function() { + mockFeedback.call(this.press(38 /* up arrow */)).expectBraille('\n'); + mockFeedback.call(this.press(38 /* up arrow */)).expectBraille('two'); + mockFeedback.call(this.press(38 /* up arrow */)).expectBraille('one'); + mockFeedback.call(this.press(38 /* up arrow */)).expectBraille('\n'); + mockFeedback.call(this.press(38 /* up arrow */)) + .expectBraille('test mled') + .replay(); + }); + }); + textarea.focus(); + textarea.setValue('test\n\none\ntwo\n\nthree'); + }); +});
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn index ebfd26b..1f96ff3 100644 --- a/chrome/browser/resources/settings/BUILD.gn +++ b/chrome/browser/resources/settings/BUILD.gn
@@ -220,10 +220,12 @@ "a11y_page:closure_compile_module", "about_page:closure_compile_module", "appearance_page:closure_compile_module", + "clear_browsing_data_dialog:closure_compile_module", "controls:closure_compile_module", "downloads_page:closure_compile_module", "languages_page:closure_compile_module", "on_startup_page:closure_compile_module", + "people_page:closure_compile_module", "prefs:closure_compile_module", "printing_page:closure_compile_module", "reset_page:closure_compile_module",
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn b/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn index cbe3fa9..c296d8d5 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
@@ -3,6 +3,9 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//tools/polymer/polymer.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") +import("../settings.gni") js_type_check("closure_compile") { deps = [ @@ -42,29 +45,33 @@ ] } -# TODO(crbug.com/1026426): Fix and enable. -#js_type_check("closure_compile_module") { -# is_polymer3 = true -# deps = [ -# ":clear_browsing_data_browser_proxy.m", -# ":clear_browsing_data_dialog.m", -# ":history_deletion_dialog.m", -# ":installed_app_checkbox.m", -# ] -#} +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ + ":clear_browsing_data_browser_proxy.m", + ":clear_browsing_data_dialog.m", + ":history_deletion_dialog.m", + ":installed_app_checkbox.m", + ] +} js_library("clear_browsing_data_browser_proxy.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.m.js" ] - deps = [ - # TODO: Fill those in. - ] + deps = [ "//ui/webui/resources/js:cr.m" ] extra_deps = [ ":modulize" ] } js_library("clear_browsing_data_dialog.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.m.js" ] deps = [ - # TODO: Fill those in. + ":clear_browsing_data_browser_proxy.m", + "..:route.m", + "..:router.m", + "../controls:settings_checkbox.m", + "../controls:settings_dropdown_menu.m", + "../people_page:sync_browser_proxy.m", + "//ui/webui/resources/js:load_time_data.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", ] extra_deps = [ ":clear_browsing_data_dialog_module" ] } @@ -72,7 +79,8 @@ js_library("history_deletion_dialog.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.m.js" ] deps = [ - # TODO: Fill those in. + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", ] extra_deps = [ ":history_deletion_dialog_module" ] } @@ -80,15 +88,14 @@ js_library("installed_app_checkbox.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.m.js" ] deps = [ - # TODO: Fill those in. + ":clear_browsing_data_browser_proxy.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] extra_deps = [ ":installed_app_checkbox_module" ] } -import("//tools/polymer/polymer.gni") - group("polymer3_elements") { - deps = [ + public_deps = [ ":clear_browsing_data_dialog_module", ":history_deletion_dialog_module", ":installed_app_checkbox_module", @@ -100,6 +107,15 @@ js_file = "clear_browsing_data_dialog.js" html_file = "clear_browsing_data_dialog.html" html_type = "dom-module" + auto_imports = settings_auto_imports + [ + "chrome/browser/resources/settings/route.html|routes", + "chrome/browser/resources/settings/router.html|Route, Router, RouteObserverBehavior", + "chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html|ClearBrowsingDataBrowserProxy, ClearBrowsingDataBrowserProxyImpl, InstalledApp", + "chrome/browser/resources/settings/controls/settings_dropdown_menu.html|DropdownMenuOptionList", + "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|StatusAction, SyncBrowserProxy, SyncBrowserProxyImpl, SyncStatus", + "ui/webui/resources/html/assert.html|assert", + ] + namespace_rewrites = settings_namespace_rewrites } polymer_modulizer("history_deletion_dialog") { @@ -112,10 +128,10 @@ js_file = "installed_app_checkbox.js" html_file = "installed_app_checkbox.html" html_type = "dom-module" + auto_imports = [ "chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html|InstalledApp" ] } -import("//ui/webui/resources/tools/js_modulizer.gni") - js_modulizer("modulize") { input_files = [ "clear_browsing_data_browser_proxy.js" ] + namespace_rewrites = settings_namespace_rewrites }
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js index 7043b50..ef587b0 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js
@@ -7,6 +7,10 @@ * to interact with the browser. */ +// clang-format off +// #import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +// clang-format on + /** * An InstalledApp represents a domain with data that the user might want * to protect from being deleted. @@ -21,11 +25,11 @@ * appName: string * }} */ -let InstalledApp; +/* #export */ let InstalledApp; cr.define('settings', function() { /** @interface */ - class ClearBrowsingDataBrowserProxy { + /* #export */ class ClearBrowsingDataBrowserProxy { /** * @param {!Array<string>} dataTypes * @param {number} timePeriod @@ -55,7 +59,7 @@ /** * @implements {settings.ClearBrowsingDataBrowserProxy} */ - class ClearBrowsingDataBrowserProxyImpl { + /* #export */ class ClearBrowsingDataBrowserProxyImpl { /** @override */ clearBrowsingData(dataTypes, timePeriod, installedApps) { return cr.sendWithPromise(
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html index 8d3a7ef..1fee615 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/cr_tabs/cr_tabs.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> +<link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> @@ -13,6 +14,7 @@ <link rel="import" href="installed_app_checkbox.html"> <link rel="import" href="../controls/settings_checkbox.html"> <link rel="import" href="../controls/settings_dropdown_menu.html"> +<link rel="import" href="../people_page/sync_browser_proxy.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../route.html"> <link rel="import" href="../router.html">
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.html index 83e0529..7cbb798 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.html +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.html
@@ -5,6 +5,7 @@ <link rel="import" href="../controls/settings_boolean_control_behavior.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="../site_favicon.html"> +<link rel="import" href="./clear_browsing_data_browser_proxy.html"> <dom-module id="installed-app-checkbox"> <template>
diff --git a/chrome/browser/resources/settings/people_page/BUILD.gn b/chrome/browser/resources/settings/people_page/BUILD.gn index 69c36a18..dcd3db1 100644 --- a/chrome/browser/resources/settings/people_page/BUILD.gn +++ b/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -3,6 +3,8 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") +import("../settings.gni") js_type_check("closure_compile") { deps = [ @@ -159,23 +161,23 @@ } # TODO(crbug.com/1026426): Fix and enable. -#js_type_check("closure_compile_module") { -# is_polymer3 = true -# deps = [ -# ":account_manager_browser_proxy.m", -# ":import_data_browser_proxy.m", -# ":import_data_dialog.m", -# ":manage_profile.m", -# ":manage_profile_browser_proxy.m", -# ":people_page.m", -# ":profile_info_browser_proxy.m", -# ":signout_dialog.m", -# ":sync_account_control.m", -# ":sync_browser_proxy.m", -# ":sync_controls.m", -# ":sync_page.m", -# ] -#} +js_type_check("closure_compile_module") { + is_polymer3 = true + deps = [ + # ":account_manager_browser_proxy.m", + # ":import_data_browser_proxy.m", + # ":import_data_dialog.m", + # ":manage_profile.m", + # ":manage_profile_browser_proxy.m", + # ":people_page.m", + # ":profile_info_browser_proxy.m", + # ":signout_dialog.m", + # ":sync_account_control.m", + ":sync_browser_proxy.m", + # ":sync_controls.m", + # ":sync_page.m", + ] +} js_library("account_manager_browser_proxy.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.m.js" ] @@ -251,9 +253,8 @@ js_library("sync_browser_proxy.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/sync_browser_proxy.m.js" ] - deps = [ - # TODO: Fill those in. - ] + deps = [ "//ui/webui/resources/js:cr.m" ] + externs_list = [ "$externs_path/metrics_private.js" ] extra_deps = [ ":modulize" ] } @@ -276,7 +277,7 @@ import("//tools/polymer/polymer.gni") group("polymer3_elements") { - deps = [ + public_deps = [ ":import_data_dialog_module", ":manage_profile_module", ":modulize", @@ -330,8 +331,6 @@ html_type = "dom-module" } -import("//ui/webui/resources/tools/js_modulizer.gni") - js_modulizer("modulize") { input_files = [ "account_manager_browser_proxy.js", @@ -340,4 +339,8 @@ "profile_info_browser_proxy.js", "sync_browser_proxy.js", ] + namespace_rewrites = settings_namespace_rewrites + [ + "settings.StoredAccount|StoredAccount", + "settings.SyncPrefs|SyncPrefs", + ] }
diff --git a/chrome/browser/resources/settings/people_page/sync_browser_proxy.js b/chrome/browser/resources/settings/people_page/sync_browser_proxy.js index 0e225285..336e8a2 100644 --- a/chrome/browser/resources/settings/people_page/sync_browser_proxy.js +++ b/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
@@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js'; +// clang-format on + cr.define('settings', function() { /** * @typedef {{fullName: (string|undefined), @@ -30,14 +34,14 @@ * syncSystemEnabled: (boolean|undefined)}} * @see chrome/browser/ui/webui/settings/people_handler.cc */ - let SyncStatus; + /* #export */ let SyncStatus; /** * Must be kept in sync with the return values of getSyncErrorAction in * chrome/browser/ui/webui/settings/people_handler.cc * @enum {string} */ - const StatusAction = { + /* #export */ const StatusAction = { NO_ACTION: 'noAction', // No action to take. REAUTHENTICATE: 'reauthenticate', // User needs to reauthenticate. SIGNOUT_AND_SIGNIN: @@ -88,7 +92,7 @@ let SyncPrefs; /** @enum {string} */ - const PageStatus = { + /* #export */ const PageStatus = { SPINNER: 'spinner', // Before the page has loaded. CONFIGURE: 'configure', // Preferences ready to be configured. DONE: 'done', // Sync subpage can be closed now. @@ -107,7 +111,7 @@ const PROMO_IMPRESSION_COUNT_KEY = 'signin-promo-count'; /** @interface */ - class SyncBrowserProxy { + /* #export */ class SyncBrowserProxy { // <if expr="not chromeos"> /** * Starts the signin process for the user. Does nothing if the user is @@ -232,7 +236,7 @@ /** * @implements {settings.SyncBrowserProxy} */ - class SyncBrowserProxyImpl { + /* #export */ class SyncBrowserProxyImpl { // <if expr="not chromeos"> /** @override */ startSignIn() {
diff --git a/chrome/browser/resources/settings/settings.gni b/chrome/browser/resources/settings/settings.gni index fda1b4b3..86279ac 100644 --- a/chrome/browser/resources/settings/settings.gni +++ b/chrome/browser/resources/settings/settings.gni
@@ -11,6 +11,7 @@ "settings.CaptionsBrowserProxy|CaptionsBrowserProxy", "settings.ChromeCleanupProxy|ChromeCleanupProxy", "settings.ChromeCleanupRemovalListItem|ChromeCleanupRemovalListItem", + "settings.ClearBrowsingDataBrowserProxy|ClearBrowsingDataBrowserProxy", "settings.DefaultBrowserBrowserProxy|DefaultBrowserBrowserProxy", "settings.DownloadsBrowserProxy|DownloadsBrowserProxy", "settings.EDIT_STARTUP_URL_EVENT|EDIT_STARTUP_URL_EVENT", @@ -24,6 +25,7 @@ "settings.LifetimeBrowserProxy|LifetimeBrowserProxy", "settings.MinimumRoutes|MinimumRoutes", "settings.OnStartupBrowserProxy|OnStartupBrowserProxy", + "settings.PageStatus|PageStatus", "settings.pageVisibility|pageVisibility", "Settings.PrefUtil.prefToString|prefToString", "Settings.PrefUtil.stringToPrefValue|stringToPrefValue", @@ -34,6 +36,9 @@ "settings.SearchEnginesBrowserProxy|SearchEnginesBrowserProxy", "settings.SearchRequest|SearchRequest", "settings.StartupUrlsPageBrowserProxy|StartupUrlsPageBrowserProxy", + "settings.StatusAction|StatusAction", + "settings.SyncBrowserProxy|SyncBrowserProxy", + "settings.SyncStatus|SyncStatus", "settings.SystemPageBrowserProxy|SystemPageBrowserProxy", "settings.RouteObserverBehavior|RouteObserverBehavior",
diff --git a/chrome/browser/resources/settings/settings.js b/chrome/browser/resources/settings/settings.js index 3331aad..f5b89157 100644 --- a/chrome/browser/resources/settings/settings.js +++ b/chrome/browser/resources/settings/settings.js
@@ -6,6 +6,7 @@ import './about_page/about_page.m.js'; import './appearance_page/appearance_page.m.js'; import './appearance_page/appearance_fonts_page.m.js'; +import './clear_browsing_data_dialog/clear_browsing_data_dialog.m.js'; import './controls/controlled_button.m.js'; import './controls/controlled_radio_button.m.js'; import './controls/extension_controlled_indicator.m.js'; @@ -57,6 +58,7 @@ export {AboutPageBrowserProxy, AboutPageBrowserProxyImpl, UpdateStatus} from './about_page/about_page_browser_proxy.m.js'; export {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_page/appearance_browser_proxy.m.js'; +export {ClearBrowsingDataBrowserProxyImpl} from './clear_browsing_data_dialog/clear_browsing_data_browser_proxy.m.js'; export {CrSettingsPrefs} from './prefs/prefs_types.m.js'; export {DownloadsBrowserProxyImpl} from './downloads_page/downloads_browser_proxy.m.js'; export {ExtensionControlBrowserProxyImpl} from './extension_control_browser_proxy.m.js'; @@ -68,6 +70,7 @@ export {OnStartupBrowserProxy, OnStartupBrowserProxyImpl} from './on_startup_page/on_startup_browser_proxy.m.js'; export {EDIT_STARTUP_URL_EVENT} from './on_startup_page/startup_url_entry.m.js'; export {StartupUrlsPageBrowserProxy, StartupUrlsPageBrowserProxyImpl} from './on_startup_page/startup_urls_page_browser_proxy.m.js'; +export {PageStatus, StatusAction, SyncBrowserProxyImpl} from './people_page/sync_browser_proxy.m.js'; export {pageVisibility} from './page_visibility.m.js'; export {prefToString, stringToPrefValue} from './prefs/pref_util.m.js'; export {routes} from './route.m.js';
diff --git a/chrome/browser/resources/settings/settings_resources_v3.grdp b/chrome/browser/resources/settings/settings_resources_v3.grdp index e9da18ff..5217aa16 100644 --- a/chrome/browser/resources/settings/settings_resources_v3.grdp +++ b/chrome/browser/resources/settings/settings_resources_v3.grdp
@@ -65,6 +65,23 @@ use_base_dir="false" type="BINDATA" /> </if> + <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_CLEAR_BROWSING_DATA_BROWSER_PROXY_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_CLEAR_BROWSING_DATA_DIALOG_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.m.js" + use_base_dir="false" + type="BINDATA" + preprocess="true" /> + <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_HISTORY_DELETION_DIALOG_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.m.js" + use_base_dir="false" + type="BINDATA" /> + <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_INSTALLED_APP_CHECKBOX_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.m.js" + use_base_dir="false" + type="BINDATA" /> <include name="IDR_SETTINGS_CONTROLS_CONTROLLED_BUTTON_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/controls/controlled_button.m.js" use_base_dir="false" @@ -361,6 +378,11 @@ file="${root_gen_dir}/chrome/browser/resources/settings/site_favicon.m.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_BROWSER_PROXY_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_browser_proxy.m.js" + use_base_dir="false" + type="BINDATA" + preprocess="true" /> <if expr="not chromeos"> <include name="IDR_SETTINGS_PRINTING_PAGE_PRINTING_BROWSER_PROXY_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/printing_page/printing_browser_proxy.m.js"
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn index 5637a76..3324ad38 100644 --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -99,6 +99,7 @@ ] deps += [ ":url_lookup_service_factory", + ":verdict_cache_manager_factory", "//chrome/browser/engagement:mojo_bindings", "//chrome/common/safe_browsing:proto", "//components/safe_browsing/content", @@ -279,6 +280,7 @@ ] deps = [ + ":verdict_cache_manager_factory", "//components/keyed_service/content", "//components/safe_browsing/core/realtime:url_lookup_service", "//components/signin/public/identity_manager", @@ -286,6 +288,22 @@ ] } +source_set("verdict_cache_manager_factory") { + sources = [ + "verdict_cache_manager_factory.cc", + "verdict_cache_manager_factory.h", + ] + + deps = [ + "//components/content_settings/core/browser", + "//components/history/core/browser", + "//components/keyed_service/content", + "//components/prefs", + "//components/safe_browsing/core:verdict_cache_manager", + "//content/public/browser", + ] +} + static_library("advanced_protection") { sources = [ "advanced_protection_status_manager.cc",
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc index 92a3cd2..c1a8c1b 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/ui_manager.h" +#include "chrome/browser/safe_browsing/verdict_cache_manager_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/user_event_service_factory.h" @@ -234,7 +235,7 @@ profile_(profile), navigation_observer_manager_(sb_service->navigation_observer_manager()), pref_change_registrar_(new PrefChangeRegistrar), - cache_manager_(sb_service->GetVerdictCacheManager(profile)) { + cache_manager_(VerdictCacheManagerFactory::GetForProfile(profile)) { pref_change_registrar_->Init(profile_->GetPrefs()); #if defined(SYNC_PASSWORD_REUSE_WARNING_ENABLED)
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc index eb79e37d..74bcbc4 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.cc
@@ -29,9 +29,7 @@ DeepScanningBrowserTestBase::DeepScanningBrowserTestBase() { // Enable every deep scanning features. scoped_feature_list_.InitWithFeatures( - {kContentComplianceEnabled, kMalwareScanEnabled, - kDeepScanningOfUploadsUI}, - {}); + {kContentComplianceEnabled, kMalwareScanEnabled}, {}); // Change the time values of the upload UI to smaller ones to make tests // showing it run faster.
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc index 8be3dbf..97db02c 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
@@ -50,10 +50,6 @@ namespace safe_browsing { -// TODO(rogerta): keeping this disabled by default until UX is finalized. -const base::Feature kDeepScanningOfUploadsUI{ - "SafeBrowsingDeepScanningOfUploadsUI", base::FEATURE_DISABLED_BY_DEFAULT}; - namespace { // Global pointer of factory function (RepeatingCallback) used to create @@ -205,6 +201,11 @@ state != BLOCK_UNSUPPORTED_FILETYPES_UPLOADS_AND_DOWNLOADS; } +bool* UIEnabledStorage() { + static bool enabled = true; + return &enabled; +} + } // namespace // A BinaryUploadService::Request implementation that gets the data to scan @@ -416,9 +417,8 @@ bool work_being_done = delegate->UploadData(); // Only show UI if work is being done in the background, the user must - // wait for a verdict, and the UI feature is enabled. - bool show_ui = work_being_done && wait_for_verdict && - base::FeatureList::IsEnabled(kDeepScanningOfUploadsUI); + // wait for a verdict. + bool show_ui = work_being_done && wait_for_verdict && (*UIEnabledStorage()); // If the UI is enabled, create the modal dialog. if (show_ui) { @@ -457,6 +457,11 @@ GetFactoryStorage()->Reset(); } +// static +void DeepScanningDialogDelegate::DisableUIForTesting() { + *UIEnabledStorage() = false; +} + DeepScanningDialogDelegate::DeepScanningDialogDelegate( content::WebContents* web_contents, Data data,
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h index 509d38f4..19e252c1 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h
@@ -31,8 +31,6 @@ class DeepScanningDialogViews; -extern const base::Feature kDeepScanningOfUploadsUI; - // A tab modal dialog delegate that informs the user of a background deep // scan happening in the given tab with an option to cancel the operation. // @@ -202,6 +200,9 @@ static void SetFactoryForTesting(Factory factory); static void ResetFactoryForTesting(); + // Showing the UI is not possible in unit tests, call this to disable it. + static void DisableUIForTesting(); + // Determines if a request result should be used to allow a data use or to // block it. static bool ResultShouldAllowDataUse(BinaryUploadService::Result result);
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc index 576b03b8..d77ceae 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc
@@ -59,6 +59,7 @@ BaseTest() : profile_manager_(TestingBrowserProcess::GetGlobal()) { EXPECT_TRUE(profile_manager_.SetUp()); profile_ = profile_manager_.CreateTestingProfile("test-user"); + DeepScanningDialogDelegate::DisableUIForTesting(); } void EnableFeatures(const std::vector<base::Feature>& features) {
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index c8585d5..7e2c981 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -45,7 +45,6 @@ #include "components/safe_browsing/core/ping_manager.h" #include "components/safe_browsing/core/realtime/policy_engine.h" #include "components/safe_browsing/core/triggers/trigger_manager.h" -#include "components/safe_browsing/core/verdict_cache_manager.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h" @@ -241,13 +240,6 @@ cmdline->HasSwitch(::switches::kDisableBackgroundNetworking)); } -VerdictCacheManager* SafeBrowsingService::GetVerdictCacheManager( - Profile* profile) const { - if (profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) - return services_delegate_->GetVerdictCacheManager(profile); - return nullptr; -} - BinaryUploadService* SafeBrowsingService::GetBinaryUploadService( Profile* profile) const { return services_delegate_->GetBinaryUploadService(profile); @@ -367,14 +359,12 @@ void SafeBrowsingService::OnProfileWillBeDestroyed(Profile* profile) { observed_profiles_.Remove(profile); - services_delegate_->RemoveVerdictCacheManager(profile); services_delegate_->RemovePasswordProtectionService(profile); services_delegate_->RemoveTelemetryService(profile); services_delegate_->RemoveBinaryUploadService(profile); } void SafeBrowsingService::CreateServicesForProfile(Profile* profile) { - services_delegate_->CreateVerdictCacheManager(profile); services_delegate_->CreatePasswordProtectionService(profile); services_delegate_->CreateTelemetryService(profile); services_delegate_->CreateBinaryUploadService(profile);
diff --git a/chrome/browser/safe_browsing/services_delegate.cc b/chrome/browser/safe_browsing/services_delegate.cc index 5dfc28f..1c5b8a3a 100644 --- a/chrome/browser/safe_browsing/services_delegate.cc +++ b/chrome/browser/safe_browsing/services_delegate.cc
@@ -18,7 +18,6 @@ #include "components/keyed_service/core/service_access_type.h" #include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/core/db/v4_local_database_manager.h" -#include "components/safe_browsing/core/verdict_cache_manager.h" #include "content/public/browser/browser_thread.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/preferences/public/mojom/tracked_preference_validation_delegate.mojom.h" @@ -62,37 +61,7 @@ : nullptr; } -void ServicesDelegate::CreateVerdictCacheManager(Profile* profile) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(profile); - auto it = cache_manager_map_.find(profile); - DCHECK(it == cache_manager_map_.end()); - auto cache_manager = std::make_unique<VerdictCacheManager>( - HistoryServiceFactory::GetForProfile(profile, - ServiceAccessType::EXPLICIT_ACCESS), - HostContentSettingsMapFactory::GetForProfile(profile)); - cache_manager_map_[profile] = std::move(cache_manager); -} - -void ServicesDelegate::RemoveVerdictCacheManager(Profile* profile) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(profile); - auto it = cache_manager_map_.find(profile); - if (it != cache_manager_map_.end()) - cache_manager_map_.erase(it); -} - -VerdictCacheManager* ServicesDelegate::GetVerdictCacheManager( - Profile* profile) const { - DCHECK(profile); - auto it = cache_manager_map_.find(profile); - return it != cache_manager_map_.end() ? it->second.get() : nullptr; -} - void ServicesDelegate::ShutdownServices() { - // Delete the VerdictCacheManager instances - cache_manager_map_.clear(); - // Delete the ChromePasswordProtectionService instances. password_protection_service_map_.clear(); }
diff --git a/chrome/browser/safe_browsing/services_delegate.h b/chrome/browser/safe_browsing/services_delegate.h index 7a4ab3e1..f42db2e 100644 --- a/chrome/browser/safe_browsing/services_delegate.h +++ b/chrome/browser/safe_browsing/services_delegate.h
@@ -41,7 +41,6 @@ class SafeBrowsingService; class SafeBrowsingDatabaseManager; struct V4ProtocolConfig; -class VerdictCacheManager; // Abstraction to help organize code for mobile vs full safe browsing modes. // This helper class should be owned by a SafeBrowsingService, and it handles @@ -130,10 +129,6 @@ virtual void CreateTelemetryService(Profile* profile) {} virtual void RemoveTelemetryService(Profile* profile) {} - virtual void CreateVerdictCacheManager(Profile* profile); - virtual void RemoveVerdictCacheManager(Profile* profile); - virtual VerdictCacheManager* GetVerdictCacheManager(Profile* profile) const; - virtual void CreateBinaryUploadService(Profile* profile) = 0; virtual void RemoveBinaryUploadService(Profile* profile) = 0; virtual BinaryUploadService* GetBinaryUploadService( @@ -154,10 +149,6 @@ base::flat_map<Profile*, std::unique_ptr<ChromePasswordProtectionService>> password_protection_service_map_; - // Tracks existing Profiles, and their corresponding VerdictCacheManager - // instances. Accessed on UI thread. - base::flat_map<Profile*, std::unique_ptr<VerdictCacheManager>> - cache_manager_map_; }; } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/url_lookup_service_factory.cc b/chrome/browser/safe_browsing/url_lookup_service_factory.cc index 8077b5a..5336c943 100644 --- a/chrome/browser/safe_browsing/url_lookup_service_factory.cc +++ b/chrome/browser/safe_browsing/url_lookup_service_factory.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/verdict_cache_manager_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" @@ -36,6 +37,7 @@ BrowserContextDependencyManager::GetInstance()) { DependsOn(IdentityManagerFactory::GetInstance()); DependsOn(ProfileSyncServiceFactory::GetInstance()); + DependsOn(VerdictCacheManagerFactory::GetInstance()); } KeyedService* RealTimeUrlLookupServiceFactory::BuildServiceInstanceFor( @@ -47,17 +49,10 @@ auto url_loader_factory = std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>( g_browser_process->safe_browsing_service()->GetURLLoaderFactory()); - // When |url_lookup_service| constructs, |cache_manager| is already - // constructed. Because |cache_manager| is constructed by |services_delegate| - // when the profile is created and |url_lookup_service| is constructed - // when the navigation starts. - VerdictCacheManager* cache_manager = - g_browser_process->safe_browsing_service()->GetVerdictCacheManager( - profile); - DCHECK(cache_manager); return new RealTimeUrlLookupService( network::SharedURLLoaderFactory::Create(std::move(url_loader_factory)), - cache_manager, IdentityManagerFactory::GetForProfile(profile), + VerdictCacheManagerFactory::GetForProfile(profile), + IdentityManagerFactory::GetForProfile(profile), ProfileSyncServiceFactory::GetForProfile(profile), profile->GetPrefs(), profile->IsOffTheRecord()); }
diff --git a/chrome/browser/safe_browsing/verdict_cache_manager_factory.cc b/chrome/browser/safe_browsing/verdict_cache_manager_factory.cc new file mode 100644 index 0000000..a6d6d2c --- /dev/null +++ b/chrome/browser/safe_browsing/verdict_cache_manager_factory.cc
@@ -0,0 +1,52 @@ +// 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/safe_browsing/verdict_cache_manager_factory.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/history/history_service_factory.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/safe_browsing/core/verdict_cache_manager.h" +#include "content/public/browser/browser_context.h" + +namespace safe_browsing { + +// static +VerdictCacheManager* VerdictCacheManagerFactory::GetForProfile( + Profile* profile) { + return static_cast<VerdictCacheManager*>( + GetInstance()->GetServiceForBrowserContext(profile, /* create= */ true)); +} + +// static +VerdictCacheManagerFactory* VerdictCacheManagerFactory::GetInstance() { + return base::Singleton<VerdictCacheManagerFactory>::get(); +} + +VerdictCacheManagerFactory::VerdictCacheManagerFactory() + : BrowserContextKeyedServiceFactory( + "VerdictCacheManager", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(HistoryServiceFactory::GetInstance()); + DependsOn(HostContentSettingsMapFactory::GetInstance()); +} + +KeyedService* VerdictCacheManagerFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + Profile* profile = Profile::FromBrowserContext(context); + return new VerdictCacheManager( + HistoryServiceFactory::GetForProfile(profile, + ServiceAccessType::EXPLICIT_ACCESS), + HostContentSettingsMapFactory::GetForProfile(profile)); +} + +content::BrowserContext* VerdictCacheManagerFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextOwnInstanceInIncognito(context); +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/verdict_cache_manager_factory.h b/chrome/browser/safe_browsing/verdict_cache_manager_factory.h new file mode 100644 index 0000000..f622e33 --- /dev/null +++ b/chrome/browser/safe_browsing/verdict_cache_manager_factory.h
@@ -0,0 +1,51 @@ +// 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_SAFE_BROWSING_VERDICT_CACHE_MANAGER_FACTORY_H_ +#define CHROME_BROWSER_SAFE_BROWSING_VERDICT_CACHE_MANAGER_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +class KeyedService; +class Profile; + +namespace content { +class BrowserContext; +} + +namespace safe_browsing { + +class VerdictCacheManager; + +// Singleton that owns VerdictCacheManager objects, one for each active +// Profile. It listens to profile destroy events and destroy its associated +// service. It returns a separate instance if the profile is in the Incognito +// mode. +class VerdictCacheManagerFactory : public BrowserContextKeyedServiceFactory { + public: + // Creates the service if it doesn't exist already for the given |profile|. + // If the service already exists, return its pointer. + static VerdictCacheManager* GetForProfile(Profile* profile); + + // Get the singleton instance. + static VerdictCacheManagerFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits<VerdictCacheManagerFactory>; + + VerdictCacheManagerFactory(); + ~VerdictCacheManagerFactory() override = default; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + + DISALLOW_COPY_AND_ASSIGN(VerdictCacheManagerFactory); +}; + +} // namespace safe_browsing +#endif // CHROME_BROWSER_SAFE_BROWSING_VERDICT_CACHE_MANAGER_FACTORY_H_
diff --git a/chrome/browser/safe_browsing/verdict_cache_manager_factory_unittest.cc b/chrome/browser/safe_browsing/verdict_cache_manager_factory_unittest.cc new file mode 100644 index 0000000..6b821a1f --- /dev/null +++ b/chrome/browser/safe_browsing/verdict_cache_manager_factory_unittest.cc
@@ -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. + +#include "chrome/browser/safe_browsing/verdict_cache_manager_factory.h" + +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace safe_browsing { + +// Check that VerdictCacheManagerFactory returns different object +// for off-the-record profile and regular profile. +TEST(VerdictCacheManagerFactoryTest, OffTheRecordUseDifferentService) { + content::BrowserTaskEnvironment task_environment; + + TestingProfile::Builder builder; + std::unique_ptr<TestingProfile> testing_profile = builder.Build(); + + // There should be a not null object for off-the-record profile. + EXPECT_NE(nullptr, VerdictCacheManagerFactory::GetForProfile( + testing_profile->GetOffTheRecordProfile())); + + EXPECT_NE(VerdictCacheManagerFactory::GetForProfile(testing_profile.get()), + VerdictCacheManagerFactory::GetForProfile( + testing_profile->GetOffTheRecordProfile())); +} + +} // namespace safe_browsing
diff --git a/chrome/browser/ui/ash/back_gesture_contextual_nudge_delegate.cc b/chrome/browser/ui/ash/back_gesture_contextual_nudge_delegate.cc index d7515f7e..0695ffc 100644 --- a/chrome/browser/ui/ash/back_gesture_contextual_nudge_delegate.cc +++ b/chrome/browser/ui/ash/back_gesture_contextual_nudge_delegate.cc
@@ -46,8 +46,14 @@ void BackGestureContextualNudgeDelegate::DidFinishNavigation( content::NavigationHandle* navigation_handle) { DCHECK(window_); - if (navigation_handle->HasCommitted()) + // Make sure for one valid navigation, we only fire one status change + // notification. + if (navigation_handle->HasCommitted() && + (navigation_handle->IsInMainFrame() || + navigation_handle->HasSubframeNavigationEntryCommitted()) && + (navigation_handle->GetURL() != navigation_handle->GetPreviousURL())) { controller_->NavigationEntryChanged(window_); + } } void BackGestureContextualNudgeDelegate::OnTabStripModelChanged(
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc index 7803de6..c8522bc 100644 --- a/chrome/browser/ui/startup/bad_flags_prompt.cc +++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -38,6 +38,7 @@ #include "media/media_buildflags.h" #include "services/network/public/cpp/network_switches.h" #include "services/service_manager/sandbox/switches.h" +#include "third_party/blink/public/common/features.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -141,6 +142,7 @@ // Dangerous feature flags in about:flags for which to display a warning that // "stability and security will suffer". static const base::Feature* kBadFeatureFlagsInAboutFlags[] = { + &blink::features::kRawClipboard, &features::kAllowSignedHTTPExchangeCertsWithoutExtension, &features::kWebBundlesFromNetwork, #if defined(OS_ANDROID)
diff --git a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc index 03add719..79a423c3 100644 --- a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc +++ b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc
@@ -80,6 +80,7 @@ &safe_browsing::FakeDeepScanningDialogDelegate::Create, run_loop_->QuitClosure(), callback, is_encrypted_callback, "dm_token")); + safe_browsing::DeepScanningDialogDelegate::DisableUIForTesting(); } // Common code for running the test cases.
diff --git a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc index 6fe13798..6bcc57d 100644 --- a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc +++ b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
@@ -110,7 +110,7 @@ IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestAccept) { ShowUi(std::string()); - EXPECT_TRUE(dialog_->Accept()); + dialog_->AcceptDialog(); EXPECT_EQ(blocked_state_, BlockState::UNKNOWN); EXPECT_TRUE(url_did_launch_); histogram_tester_.ExpectBucketCount( @@ -122,7 +122,7 @@ TestAcceptWithChecked) { ShowUi(std::string()); SetChecked(true); - EXPECT_TRUE(dialog_->Accept()); + dialog_->AcceptDialog(); EXPECT_EQ(blocked_scheme_, "telnet"); EXPECT_EQ(blocked_state_, BlockState::DONT_BLOCK); EXPECT_TRUE(url_did_launch_); @@ -138,7 +138,7 @@ ShowUi(std::string()); SetChecked(true); // |remember_| must be true for the segfault to occur. browser()->tab_strip_model()->CloseAllTabs(); - EXPECT_TRUE(dialog_->Accept()); + dialog_->AcceptDialog(); EXPECT_FALSE(url_did_launch_); histogram_tester_.ExpectBucketCount( ExternalProtocolHandler::kHandleStateMetric, @@ -147,7 +147,7 @@ IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestCancel) { ShowUi(std::string()); - EXPECT_TRUE(dialog_->Cancel()); + dialog_->CancelDialog(); EXPECT_EQ(blocked_state_, BlockState::UNKNOWN); EXPECT_FALSE(url_did_launch_); histogram_tester_.ExpectBucketCount( @@ -159,7 +159,7 @@ TestCancelWithChecked) { ShowUi(std::string()); SetChecked(true); - EXPECT_TRUE(dialog_->Cancel()); + dialog_->CancelDialog(); // Cancel() should not enforce the remember checkbox. EXPECT_EQ(blocked_state_, BlockState::UNKNOWN); EXPECT_FALSE(url_did_launch_);
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc index 5e2830d..a4e7cf8 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -779,23 +779,21 @@ void ProfileMenuViewBase::UpdateSyncInfoContainerBackground() { ui::NativeTheme::ColorId bg_color; - SkAlpha alpha = 16; switch (sync_background_state_) { case SyncInfoContainerBackgroundState::kNoError: sync_info_container_->SetBackground(nullptr); return; case SyncInfoContainerBackgroundState::kPaused: - bg_color = ui::NativeTheme::kColorId_ProminentButtonColor; + bg_color = ui::NativeTheme::kColorId_SyncInfoContainerPaused; break; case SyncInfoContainerBackgroundState::kError: - bg_color = ui::NativeTheme::kColorId_AlertSeverityHigh; + bg_color = ui::NativeTheme::kColorId_SyncInfoContainerError; break; case SyncInfoContainerBackgroundState::kNoPrimaryAccount: - bg_color = ui::NativeTheme::kColorId_HighlightedMenuItemBackgroundColor; - alpha = SK_AlphaOPAQUE; + bg_color = ui::NativeTheme::kColorId_SyncInfoContainerNoPrimaryAccount; } sync_info_container_->SetBackground(views::CreateRoundedRectBackground( - SkColorSetA(GetNativeTheme()->GetSystemColor(bg_color), alpha), + GetNativeTheme()->GetSystemColor(bg_color), views::LayoutProvider::Get()->GetCornerRadiusMetric( views::EMPHASIS_HIGH))); }
diff --git a/chrome/browser/ui/views/storage/storage_pressure_bubble_view.cc b/chrome/browser/ui/views/storage/storage_pressure_bubble_view.cc index bbaf274..6f39790 100644 --- a/chrome/browser/ui/views/storage/storage_pressure_bubble_view.cc +++ b/chrome/browser/ui/views/storage/storage_pressure_bubble_view.cc
@@ -12,14 +12,15 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/toolbar_button_provider.h" #include "chrome/grit/generated_resources.h" -#include "components/url_formatter/elide_url.h" +#include "components/url_formatter/url_formatter.h" #include "content/public/common/content_features.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views/layout/box_layout.h" namespace { -const char kAllSitesContentSettingsUrl[] = "chrome://settings/content/all"; +const char kAllSitesContentSettingsUrl[] = + "chrome://settings/content/all?sort=data-stored"; } // namespace @@ -90,9 +91,14 @@ provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL))); // Description text label. + auto origin_string = url_formatter::FormatUrl( + origin_.GetURL(), + url_formatter::kFormatUrlOmitDefaults | + url_formatter::kFormatUrlOmitHTTPS | + url_formatter::kFormatUrlOmitTrailingSlashOnBareHostname, + net::UnescapeRule::NONE, nullptr, nullptr, nullptr); auto text_label = std::make_unique<views::Label>(l10n_util::GetStringFUTF16( - IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_MESSAGE, - url_formatter::FormatOriginForSecurityDisplay(origin_))); + IDS_SETTINGS_STORAGE_PRESSURE_BUBBLE_VIEW_MESSAGE, origin_string)); text_label->SetMultiLine(true); text_label->SetLineHeight(20); text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc index b9257f19..ca2d541 100644 --- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -51,9 +51,11 @@ views::Widget* TabGroupEditorBubbleView::Show( const Browser* browser, const tab_groups::TabGroupId& group, - TabGroupHeader* anchor_view) { + TabGroupHeader* anchor_view, + bool stop_context_menu_propagation) { views::Widget* const widget = BubbleDialogDelegateView::CreateBubble( - new TabGroupEditorBubbleView(browser, group, anchor_view, base::nullopt)); + new TabGroupEditorBubbleView(browser, group, anchor_view, base::nullopt, + stop_context_menu_propagation)); widget->Show(); return widget; } @@ -63,8 +65,9 @@ const Browser* browser, const tab_groups::TabGroupId& group, gfx::Rect anchor_rect) { - views::Widget* const widget = BubbleDialogDelegateView::CreateBubble( - new TabGroupEditorBubbleView(browser, group, nullptr, anchor_rect)); + views::Widget* const widget = + BubbleDialogDelegateView::CreateBubble(new TabGroupEditorBubbleView( + browser, group, nullptr, anchor_rect, false)); widget->Show(); return widget; } @@ -87,7 +90,8 @@ const Browser* browser, const tab_groups::TabGroupId& group, TabGroupHeader* anchor_view, - base::Optional<gfx::Rect> anchor_rect) + base::Optional<gfx::Rect> anchor_rect, + bool stop_context_menu_propagation) : browser_(browser), group_(group), title_field_controller_(this), @@ -146,8 +150,8 @@ title_field_container->SetBorder(views::CreateEmptyBorder(gfx::Insets( 0, color_element_insets.left(), vertical_dialog_content_spacing, color_element_insets.right()))); - title_field_ = - title_field_container->AddChildView(std::make_unique<views::Textfield>()); + title_field_ = title_field_container->AddChildView( + std::make_unique<TitleField>(stop_context_menu_propagation)); title_field_->SetText(title); title_field_->SetAccessibleName(base::ASCIIToUTF16("Group title")); title_field_->SetPlaceholderText( @@ -310,6 +314,21 @@ return false; } +void TabGroupEditorBubbleView::TitleField::ShowContextMenu( + const gfx::Point& p, + ui::MenuSourceType source_type) { + // There is no easy way to stop the propagation of a ShowContextMenu event, + // which is sometimes used to open the bubble itself. So when the bubble is + // opened this way, we manually hide the textfield's context menu the first + // time. Otherwise, the textfield, which is automatically focused, would show + // an extra context menu when the bubble first opens. + if (stop_context_menu_propagation_) { + stop_context_menu_propagation_ = false; + return; + } + views::Textfield::ShowContextMenu(p, source_type); +} + TabGroupEditorBubbleView::ButtonListener::ButtonListener( const Browser* browser, tab_groups::TabGroupId group,
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h index d701fde4..54aaeec5 100644 --- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h +++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h
@@ -40,7 +40,8 @@ // Returns an *unowned* pointer to the bubble's widget. static views::Widget* Show(const Browser* browser, const tab_groups::TabGroupId& group, - TabGroupHeader* anchor_view); + TabGroupHeader* anchor_view, + bool stop_context_menu_propagation = false); // Shows the editor for |group| using a rect as an anchor. Should only be used // if the TabGroupHeader is not available as an anchor, e.g. in WebUI. Returns @@ -58,7 +59,8 @@ TabGroupEditorBubbleView(const Browser* browser, const tab_groups::TabGroupId& group, TabGroupHeader* anchor_view, - base::Optional<gfx::Rect> anchor_rect); + base::Optional<gfx::Rect> anchor_rect, + bool stop_context_menu_propagation); ~TabGroupEditorBubbleView() override; void UpdateGroup(); @@ -88,6 +90,26 @@ TitleFieldController title_field_controller_; + class TitleField : public views::Textfield { + public: + explicit TitleField(bool stop_context_menu_propagation) + : stop_context_menu_propagation_(stop_context_menu_propagation) {} + ~TitleField() override = default; + + // views::Textfield: + void ShowContextMenu(const gfx::Point& p, + ui::MenuSourceType source_type) override; + + private: + // Whether the context menu should be hidden the first time it shows. + // Needed because there is no easy way to stop the propagation of a + // ShowContextMenu event, which is sometimes used to open the bubble + // itself. + bool stop_context_menu_propagation_; + }; + + TitleField* title_field_; + class ButtonListener : public views::ButtonListener { public: explicit ButtonListener(const Browser* browser, @@ -105,8 +127,6 @@ ButtonListener button_listener_; - views::Textfield* title_field_; - std::vector<tab_groups::TabGroupColorId> color_ids_; std::vector<std::pair<SkColor, base::string16>> colors_; ColorPickerView* color_selector_;
diff --git a/chrome/browser/ui/views/tabs/tab_group_header.cc b/chrome/browser/ui/views/tabs/tab_group_header.cc index dd5fe02a..8ca9228 100644 --- a/chrome/browser/ui/views/tabs/tab_group_header.cc +++ b/chrome/browser/ui/views/tabs/tab_group_header.cc
@@ -78,6 +78,7 @@ DCHECK(tab_strip); set_group(group); + set_context_menu_controller(this); // The size and color of the chip are set in VisualsChanged(). title_chip_ = AddChildView(std::make_unique<views::View>()); @@ -227,6 +228,17 @@ return size_info; } +void TabGroupHeader::ShowContextMenuForViewImpl( + views::View* source, + const gfx::Point& point, + ui::MenuSourceType source_type) { + if (editor_bubble_tracker_.is_open()) + return; + + editor_bubble_tracker_.Opened(TabGroupEditorBubbleView::Show( + tab_strip_->controller()->GetBrowser(), group().value(), this, true)); +} + int TabGroupHeader::CalculateWidth() const { // We don't want tabs to visually overlap group headers, so we add that space // to the width to compensate. We don't want to actually remove the overlap
diff --git a/chrome/browser/ui/views/tabs/tab_group_header.h b/chrome/browser/ui/views/tabs/tab_group_header.h index 29fd2870..32e6ba77 100644 --- a/chrome/browser/ui/views/tabs/tab_group_header.h +++ b/chrome/browser/ui/views/tabs/tab_group_header.h
@@ -7,6 +7,7 @@ #include "chrome/browser/ui/views/tabs/tab_slot_view.h" #include "components/tab_groups/tab_group_id.h" +#include "ui/views/context_menu_controller.h" #include "ui/views/controls/focus_ring.h" #include "ui/views/widget/widget_observer.h" @@ -21,7 +22,7 @@ // View for tab group headers in the tab strip, which are markers of group // boundaries. There is one header for each group, which is included in the tab // strip flow and positioned left of the leftmost tab in the group. -class TabGroupHeader : public TabSlotView { +class TabGroupHeader : public TabSlotView, public views::ContextMenuController { public: TabGroupHeader(TabStrip* tab_strip, const tab_groups::TabGroupId& group); ~TabGroupHeader() override; @@ -39,6 +40,11 @@ TabSlotView::ViewType GetTabSlotViewType() const override; TabSizeInfo GetTabSizeInfo() const override; + // views::ContextMenuController: + void ShowContextMenuForViewImpl(views::View* source, + const gfx::Point& point, + ui::MenuSourceType source_type) override; + // Updates our visual state according to the tab_groups::TabGroupVisualData // for our group. void VisualsChanged();
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 8a8107b5..ab24fc2 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -66,6 +66,9 @@ // frequency it has been ignored. const char kImportantSitesDialogHistory[] = "important_sites_dialog"; +// This is the profile creation time. +const char kProfileCreationTime[] = "profile.creation_time"; + #if defined(OS_WIN) // This is a timestamp of the last time this profile was reset by a third party // tool. On Windows, a third party tool may set a registry value that will be
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 899fde4..2e0e9ac 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -31,6 +31,7 @@ extern const char kHomePageIsNewTabPage[]; extern const char kHomePage[]; extern const char kImportantSitesDialogHistory[]; +extern const char kProfileCreationTime[]; #if defined(OS_WIN) extern const char kLastProfileResetTimestamp[]; extern const char kChromeCleanerResetPending[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index d1ca426..d7bd45c8 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -5036,6 +5036,7 @@ "../browser/safe_browsing/local_two_phase_testserver.h", "../browser/safe_browsing/safe_browsing_navigation_observer_unittest.cc", "../browser/safe_browsing/signature_evaluator_mac_unittest.cc", + "../browser/safe_browsing/verdict_cache_manager_factory_unittest.cc", "../common/safe_browsing/binary_feature_extractor_mac_unittest.cc", "../common/safe_browsing/binary_feature_extractor_unittest.cc", "../common/safe_browsing/binary_feature_extractor_win_unittest.cc",
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 5710f7ed..4a90a3c4 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -212,6 +212,7 @@ "$root_gen_dir/chrome/test/data/webui/settings/appearance_page_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/appearance_fonts_page_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/checkbox_tests.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/clear_browsing_data_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/controlled_button_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/controlled_radio_button_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/default_browser_browsertest.m.js", @@ -246,6 +247,7 @@ "$root_gen_dir/chrome/test/data/webui/settings/test_lifetime_browser_proxy.m.js", "$root_gen_dir/chrome/test/data/webui/settings/test_reset_browser_proxy.m.js", "$root_gen_dir/chrome/test/data/webui/settings/test_search_engines_browser_proxy.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/test_sync_browser_proxy.m.js", "$root_gen_dir/chrome/test/data/webui/settings/test_util.m.js", "$root_gen_dir/chrome/test/data/webui/test_browser_proxy.m.js", "$root_gen_dir/chrome/test/data/webui/test_store.m.js",
diff --git a/chrome/test/data/webui/mocha_adapter.js b/chrome/test/data/webui/mocha_adapter.js index 504e8ca..cfca41c 100644 --- a/chrome/test/data/webui/mocha_adapter.js +++ b/chrome/test/data/webui/mocha_adapter.js
@@ -77,6 +77,14 @@ mocha.grep(new RegExp('^' + suiteName + ' ' + escapedTestName + '$')).run(); }; +/** + * Helper function provided to make running a single Mocha suite more robust. + * @param {string} suiteName + */ +window.runMochaSuite = function(suiteName) { + mocha.grep(new RegExp('^' + suiteName + ' ')).run(); +}; + // Configure mocha. mocha.setup({ // Use TDD interface instead of BDD.
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn index 12d5ce6..4a172eb9 100644 --- a/chrome/test/data/webui/settings/BUILD.gn +++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -12,6 +12,7 @@ "appearance_fonts_page_test.js", "appearance_page_test.js", "checkbox_tests.js", + "clear_browsing_data_test.js", "controlled_button_tests.js", "controlled_radio_button_tests.js", "default_browser_browsertest.js", @@ -47,6 +48,7 @@ "test_lifetime_browser_proxy.js", "test_reset_browser_proxy.js", "test_search_engines_browser_proxy.js", + "test_sync_browser_proxy.js", "test_util.js", ] if (is_win) {
diff --git a/chrome/test/data/webui/settings/clear_browsing_data_test.js b/chrome/test/data/webui/settings/clear_browsing_data_test.js new file mode 100644 index 0000000..f6001848c --- /dev/null +++ b/chrome/test/data/webui/settings/clear_browsing_data_test.js
@@ -0,0 +1,583 @@ +// 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. + +// clang-format off +// #import {ClearBrowsingDataBrowserProxyImpl, Router, routes, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; +// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +// #import {isChromeOS} from 'chrome://resources/js/cr.m.js'; +// #import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; +// #import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; +// #import {TestSyncBrowserProxy} from 'chrome://test/settings/test_sync_browser_proxy.m.js'; +// #import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; +// #import {isChildVisible, isVisible, whenAttributeIs} from 'chrome://test/test_util.m.js'; +// clang-format on + +cr.define('settings_clear_browsing_data_test', function() { + /** @implements {settings.ClearBrowsingDataBrowserProxy} */ + class TestClearBrowsingDataBrowserProxy extends TestBrowserProxy { + constructor() { + super(['initialize', 'clearBrowsingData', 'getInstalledApps']); + + /** + * The promise to return from |clearBrowsingData|. + * Allows testing code to test what happens after the call is made, and + * before the browser responds. + * @private {?Promise} + */ + this.clearBrowsingDataPromise_ = null; + + /** + * Response for |getInstalledApps|. + * @private {!Array<!InstalledApp>} + */ + this.installedApps_ = []; + } + + /** @param {!Promise} promise */ + setClearBrowsingDataPromise(promise) { + this.clearBrowsingDataPromise_ = promise; + } + + /** @override */ + clearBrowsingData(dataTypes, timePeriod, installedApps) { + this.methodCalled( + 'clearBrowsingData', [dataTypes, timePeriod, installedApps]); + cr.webUIListenerCallback('browsing-data-removing', true); + return this.clearBrowsingDataPromise_ !== null ? + this.clearBrowsingDataPromise_ : + Promise.resolve(); + } + + /** @param {!Array<!InstalledApp>} apps */ + setInstalledApps(apps) { + this.installedApps_ = apps; + } + + /** @override */ + getInstalledApps(timePeriod) { + this.methodCalled('getInstalledApps'); + return Promise.resolve(this.installedApps_); + } + + /** @override */ + initialize() { + this.methodCalled('initialize'); + return Promise.resolve(false); + } + } + + function getClearBrowsingDataPrefs() { + return { + browser: { + clear_data: { + browsing_history: { + key: 'browser.clear_data.browsing_history', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + browsing_history_basic: { + key: 'browser.clear_data.browsing_history_basic', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + cache: { + key: 'browser.clear_data.cache', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + cache_basic: { + key: 'browser.clear_data.cache_basic', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + cookies: { + key: 'browser.clear_data.cookies', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + cookies_basic: { + key: 'browser.clear_data.cookies_basic', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + download_history: { + key: 'browser.clear_data.download_history', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + hosted_apps_data: { + key: 'browser.clear_data.hosted_apps_data', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + form_data: { + key: 'browser.clear_data.form_data', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + passwords: { + key: 'browser.clear_data.passwords', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + site_settings: { + key: 'browser.clear_data.site_settings', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + time_period: { + key: 'browser.clear_data.time_period', + type: chrome.settingsPrivate.PrefType.NUMBER, + value: 0, + }, + time_period_basic: { + key: 'browser.clear_data.time_period_basic', + type: chrome.settingsPrivate.PrefType.NUMBER, + value: 0, + }, + }, + last_clear_browsing_data_tab: { + key: 'browser.last_clear_browsing_data_tab', + type: chrome.settingsPrivate.PrefType.NUMBER, + value: 0, + }, + } + }; + } + + suite('ClearBrowsingDataDesktop', function() { + /** @type {settings.TestClearBrowsingDataBrowserProxy} */ + let testBrowserProxy; + + /** @type {TestSyncBrowserProxy} */ + let testSyncBrowserProxy; + + /** @type {SettingsClearBrowsingDataDialogElement} */ + let element; + + setup(function() { + testBrowserProxy = new TestClearBrowsingDataBrowserProxy(); + settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy; + testSyncBrowserProxy = new TestSyncBrowserProxy(); + settings.SyncBrowserProxyImpl.instance_ = testSyncBrowserProxy; + PolymerTest.clearBody(); + element = document.createElement('settings-clear-browsing-data-dialog'); + element.set('prefs', getClearBrowsingDataPrefs()); + document.body.appendChild(element); + return testBrowserProxy.whenCalled('initialize').then(() => { + assertTrue(element.$$('#clearBrowsingDataDialog').open); + }); + }); + + teardown(function() { + element.remove(); + }); + + test('ClearBrowsingDataSyncAccountInfoDesktop', function() { + // Not syncing: the footer is hidden. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: false, + hasError: false, + }); + Polymer.dom.flush(); + assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + + // Syncing: the footer is shown, with the normal sync info. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: false, + }); + Polymer.dom.flush(); + assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + assertTrue(test_util.isChildVisible(element, '#sync-info')); + assertFalse(test_util.isChildVisible(element, '#sync-paused-info')); + assertFalse( + test_util.isChildVisible(element, '#sync-passphrase-error-info')); + assertFalse(test_util.isChildVisible(element, '#sync-other-error-info')); + + // Sync is paused. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: true, + statusAction: settings.StatusAction.REAUTHENTICATE, + }); + Polymer.dom.flush(); + assertFalse(test_util.isChildVisible(element, '#sync-info')); + assertTrue(test_util.isChildVisible(element, '#sync-paused-info')); + assertFalse( + test_util.isChildVisible(element, '#sync-passphrase-error-info')); + assertFalse(test_util.isChildVisible(element, '#sync-other-error-info')); + + // Sync passphrase error. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: true, + statusAction: settings.StatusAction.ENTER_PASSPHRASE, + }); + Polymer.dom.flush(); + assertFalse(test_util.isChildVisible(element, '#sync-info')); + assertFalse(test_util.isChildVisible(element, '#sync-paused-info')); + assertTrue( + test_util.isChildVisible(element, '#sync-passphrase-error-info')); + assertFalse(test_util.isChildVisible(element, '#sync-other-error-info')); + + // Other sync error. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: true, + statusAction: settings.StatusAction.NO_ACTION, + }); + Polymer.dom.flush(); + assertFalse(test_util.isChildVisible(element, '#sync-info')); + assertFalse(test_util.isChildVisible(element, '#sync-paused-info')); + assertFalse( + test_util.isChildVisible(element, '#sync-passphrase-error-info')); + assertTrue(test_util.isChildVisible(element, '#sync-other-error-info')); + }); + + test('ClearBrowsingDataPauseSyncDesktop', function() { + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: false, + }); + Polymer.dom.flush(); + assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + const syncInfo = element.$$('#sync-info'); + assertTrue(test_util.isVisible(syncInfo)); + const signoutLink = syncInfo.querySelector('a[href]'); + assertTrue(!!signoutLink); + assertEquals(0, testSyncBrowserProxy.getCallCount('pauseSync')); + signoutLink.click(); + assertEquals(1, testSyncBrowserProxy.getCallCount('pauseSync')); + }); + + test('ClearBrowsingDataStartSignInDesktop', function() { + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: true, + statusAction: settings.StatusAction.REAUTHENTICATE, + }); + Polymer.dom.flush(); + assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + const syncInfo = element.$$('#sync-paused-info'); + assertTrue(test_util.isVisible(syncInfo)); + const signinLink = syncInfo.querySelector('a[href]'); + assertTrue(!!signinLink); + assertEquals(0, testSyncBrowserProxy.getCallCount('startSignIn')); + signinLink.click(); + assertEquals(1, testSyncBrowserProxy.getCallCount('startSignIn')); + }); + + test('ClearBrowsingDataHandlePassphraseErrorDesktop', function() { + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: true, + statusAction: settings.StatusAction.ENTER_PASSPHRASE, + }); + Polymer.dom.flush(); + assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + const syncInfo = element.$$('#sync-passphrase-error-info'); + assertTrue(test_util.isVisible(syncInfo)); + const passphraseLink = syncInfo.querySelector('a[href]'); + assertTrue(!!passphraseLink); + passphraseLink.click(); + assertEquals( + settings.routes.SYNC, + settings.Router.getInstance().getCurrentRoute()); + }); + }); + + suite('ClearBrowsingDataAllPlatforms', function() { + /** @type {settings.TestClearBrowsingDataBrowserProxy} */ + let testBrowserProxy; + + /** @type {SettingsClearBrowsingDataDialogElement} */ + let element; + + setup(function() { + testBrowserProxy = new TestClearBrowsingDataBrowserProxy(); + settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy; + PolymerTest.clearBody(); + element = document.createElement('settings-clear-browsing-data-dialog'); + element.set('prefs', getClearBrowsingDataPrefs()); + document.body.appendChild(element); + return testBrowserProxy.whenCalled('initialize'); + }); + + teardown(function() { + element.remove(); + }); + + test('ClearBrowsingDataTap', function() { + assertTrue(element.$$('#clearBrowsingDataDialog').open); + assertFalse(element.$$('#installedAppsDialog').open); + + const cancelButton = element.$$('.cancel-button'); + assertTrue(!!cancelButton); + const actionButton = element.$$('.action-button'); + assertTrue(!!actionButton); + const spinner = element.$$('paper-spinner-lite'); + assertTrue(!!spinner); + + // Select a datatype for deletion to enable the clear button. + const cookieCheckbox = element.$$('#cookiesCheckboxBasic'); + assertTrue(!!cookieCheckbox); + cookieCheckbox.$.checkbox.click(); + + assertFalse(cancelButton.disabled); + assertFalse(actionButton.disabled); + assertFalse(spinner.active); + + const promiseResolver = new PromiseResolver(); + testBrowserProxy.setClearBrowsingDataPromise(promiseResolver.promise); + actionButton.click(); + + return testBrowserProxy.whenCalled('clearBrowsingData') + .then(function(args) { + const dataTypes = args[0]; + const timePeriod = args[1]; + const installedApps = args[2]; + assertEquals(1, dataTypes.length); + assertEquals('browser.clear_data.cookies_basic', dataTypes[0]); + assertTrue(element.$$('#clearBrowsingDataDialog').open); + assertTrue(cancelButton.disabled); + assertTrue(actionButton.disabled); + assertTrue(spinner.active); + assertTrue(installedApps.length == 0); + + // Simulate signal from browser indicating that clearing has + // completed. + cr.webUIListenerCallback('browsing-data-removing', false); + promiseResolver.resolve(); + // Yields to the message loop to allow the callback chain of the + // Promise that was just resolved to execute before the + // assertions. + }) + .then(function() { + assertFalse(element.$$('#clearBrowsingDataDialog').open); + assertFalse(cancelButton.disabled); + assertFalse(actionButton.disabled); + assertFalse(spinner.active); + assertFalse(!!element.$$('#notice')); + + // Check that the dialog didn't switch to installed apps. + assertFalse(element.$$('#installedAppsDialog').open); + }); + }); + + test('ClearBrowsingDataClearButton', function() { + assertTrue(element.$$('#clearBrowsingDataDialog').open); + + const actionButton = element.$$('.action-button'); + assertTrue(!!actionButton); + const cookieCheckboxBasic = element.$$('#cookiesCheckboxBasic'); + assertTrue(!!cookieCheckboxBasic); + // Initially the button is disabled because all checkboxes are off. + assertTrue(actionButton.disabled); + // The button gets enabled if any checkbox is selected. + cookieCheckboxBasic.$.checkbox.click(); + assertTrue(cookieCheckboxBasic.checked); + assertFalse(actionButton.disabled); + // Switching to advanced disables the button. + element.$$('cr-tabs').selected = 1; + assertTrue(actionButton.disabled); + // Switching back enables it again. + element.$$('cr-tabs').selected = 0; + assertFalse(actionButton.disabled); + }); + + test('showHistoryDeletionDialog', function() { + assertTrue(element.$$('#clearBrowsingDataDialog').open); + const actionButton = element.$$('.action-button'); + assertTrue(!!actionButton); + + // Select a datatype for deletion to enable the clear button. + const cookieCheckbox = element.$$('#cookiesCheckboxBasic'); + assertTrue(!!cookieCheckbox); + cookieCheckbox.$.checkbox.click(); + assertFalse(actionButton.disabled); + + const promiseResolver = new PromiseResolver(); + testBrowserProxy.setClearBrowsingDataPromise(promiseResolver.promise); + actionButton.click(); + + return testBrowserProxy.whenCalled('clearBrowsingData') + .then(function() { + // Passing showNotice = true should trigger the notice about other + // forms of browsing history to open, and the dialog to stay open. + promiseResolver.resolve(true /* showNotice */); + + // Yields to the message loop to allow the callback chain of the + // Promise that was just resolved to execute before the + // assertions. + }) + .then(function() { + Polymer.dom.flush(); + const notice = element.$$('#notice'); + assertTrue(!!notice); + const noticeActionButton = notice.$$('.action-button'); + assertTrue(!!noticeActionButton); + + assertTrue(element.$$('#clearBrowsingDataDialog').open); + assertTrue(notice.$$('#dialog').open); + + noticeActionButton.click(); + + return new Promise(function(resolve, reject) { + // Tapping the action button will close the notice. Move to the + // end of the message loop to allow the closing event to + // propagate to the parent dialog. The parent dialog should + // subsequently close as well. + setTimeout(function() { + const notice = element.$$('#notice'); + assertFalse(!!notice); + assertFalse(element.$$('#clearBrowsingDataDialog').open); + resolve(); + }, 0); + }); + }); + }); + + test('Counters', function() { + assertTrue(element.$$('#clearBrowsingDataDialog').open); + + const checkbox = element.$$('#cacheCheckboxBasic'); + assertEquals('browser.clear_data.cache_basic', checkbox.pref.key); + + // Simulate a browsing data counter result for history. This checkbox's + // sublabel should be updated. + cr.webUIListenerCallback( + 'update-counter-text', checkbox.pref.key, 'result'); + assertEquals('result', checkbox.subLabel); + }); + + test('history rows are hidden for supervised users', function() { + assertFalse(loadTimeData.getBoolean('isSupervised')); + assertFalse(element.$$('#browsingCheckbox').hidden); + assertFalse(element.$$('#browsingCheckboxBasic').hidden); + assertFalse(element.$$('#downloadCheckbox').hidden); + + element.remove(); + testBrowserProxy.reset(); + loadTimeData.overrideValues({isSupervised: true}); + + element = document.createElement('settings-clear-browsing-data-dialog'); + document.body.appendChild(element); + Polymer.dom.flush(); + + return testBrowserProxy.whenCalled('initialize').then(function() { + assertTrue(element.$$('#browsingCheckbox').hidden); + assertTrue(element.$$('#browsingCheckboxBasic').hidden); + assertTrue(element.$$('#downloadCheckbox').hidden); + }); + }); + + if (cr.isChromeOS) { + // On ChromeOS the footer is never shown. + test('ClearBrowsingDataSyncAccountInfo', function() { + assertTrue(element.$$('#clearBrowsingDataDialog').open); + + // Not syncing. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: false, + hasError: false, + }); + Polymer.dom.flush(); + assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + + // Syncing. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: false, + }); + Polymer.dom.flush(); + assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + + // Sync passphrase error. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: true, + statusAction: settings.StatusAction.ENTER_PASSPHRASE, + }); + Polymer.dom.flush(); + assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + + // Other sync error. + cr.webUIListenerCallback('sync-status-changed', { + signedIn: true, + hasError: true, + statusAction: settings.StatusAction.NO_ACTION, + }); + Polymer.dom.flush(); + assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); + }); + } + }); + + suite('InstalledApps', function() { + /** @type {settings.TestClearBrowsingDataBrowserProxy} */ + let testBrowserProxy; + + /** @type {SettingsClearBrowsingDataDialogElement} */ + let element; + + /** @type {Array<InstalledApp>} */ + const installedApps = [ + {registerableDomain: 'google.com', isChecked: true}, + {registerableDomain: 'yahoo.com', isChecked: true}, + ]; + + setup(() => { + loadTimeData.overrideValues({installedAppsInCbd: true}); + testBrowserProxy = new TestClearBrowsingDataBrowserProxy(); + testBrowserProxy.setInstalledApps(installedApps); + settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy; + PolymerTest.clearBody(); + element = document.createElement('settings-clear-browsing-data-dialog'); + element.set('prefs', getClearBrowsingDataPrefs()); + document.body.appendChild(element); + return testBrowserProxy.whenCalled('initialize'); + }); + + teardown(() => { + element.remove(); + }); + + test('getInstalledApps', async function() { + assertTrue(element.$.clearBrowsingDataDialog.open); + assertFalse(element.$.installedAppsDialog.open); + + // Select cookie checkbox. + element.$.cookiesCheckboxBasic.$.checkbox.click(); + assertTrue(element.$.cookiesCheckboxBasic.checked); + // Clear browsing data. + element.$.clearBrowsingDataConfirm.click(); + assertTrue(element.$.clearBrowsingDataDialog.open); + + await testBrowserProxy.whenCalled('getInstalledApps'); + await test_util.whenAttributeIs( + element.$.installedAppsDialog, 'open', ''); + const firstInstalledApp = element.$$('installed-app-checkbox'); + assertTrue(!!firstInstalledApp); + assertEquals( + 'google.com', firstInstalledApp.installed_app.registerableDomain); + assertTrue(firstInstalledApp.installed_app.isChecked); + // Choose to keep storage for google.com. + firstInstalledApp.$.checkbox.click(); + assertFalse(firstInstalledApp.installed_app.isChecked); + // Confirm deletion. + element.$.installedAppsConfirm.click(); + const [dataTypes, timePeriod, apps] = + await testBrowserProxy.whenCalled('clearBrowsingData'); + assertEquals(1, dataTypes.length); + assertEquals('browser.clear_data.cookies_basic', dataTypes[0]); + assertEquals(2, apps.length); + assertEquals('google.com', apps[0].registerableDomain); + assertFalse(apps[0].isChecked); + assertEquals('yahoo.com', apps[1].registerableDomain); + assertTrue(apps[1].isChecked); + }); + }); + // #cr_define_end +});
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 6c285d0..e783b42 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -933,11 +933,6 @@ ]), }; -TEST_F('CrSettingsPrivacyPageTest', 'ClearBrowsingDataTests', function() { - settings_privacy_page.registerClearBrowsingDataTests(); - mocha.run(); -}); - TEST_F('CrSettingsPrivacyPageTest', 'PrivacyPageTests', function() { settings_privacy_page.registerPrivacyPageTests(); mocha.run(); @@ -955,11 +950,6 @@ mocha.run(); }); -TEST_F('CrSettingsPrivacyPageTest', 'InstalledAppsTests', () => { - settings_privacy_page.registerInstalledAppsTests(); - mocha.run(); -}); - GEN('#if defined(OS_MACOSX) || defined(OS_WIN)'); // TODO(crbug.com/1043665): disabling due to failures on several builders. TEST_F( @@ -970,11 +960,46 @@ }); GEN('#endif'); +/** + * Test fixture for + * chrome/browser/resources/settings/clear_browsing_data_dialog/ + * clear_browsing_data_dialog.html. + * @constructor + * @extends {CrSettingsBrowserTest} + */ +function CrSettingsClearBrowsingDataTest() {} + +CrSettingsClearBrowsingDataTest.prototype = { + __proto__: CrSettingsBrowserTest.prototype, + + /** @override */ + browsePreload: 'chrome://settings/clear_browsing_data_dialog/' + + 'clear_browsing_data_dialog.html', + + /** @override */ + extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ + '//ui/webui/resources/js/promise_resolver.js', + '../test_util.js', + '../test_browser_proxy.js', + 'clear_browsing_data_test.js', + 'test_sync_browser_proxy.js', + ]), +}; + +TEST_F( + 'CrSettingsClearBrowsingDataTest', 'ClearBrowsingDataAllPlatforms', + function() { + runMochaSuite('ClearBrowsingDataAllPlatforms'); + }); + +TEST_F('CrSettingsClearBrowsingDataTest', 'InstalledApps', () => { + runMochaSuite('InstalledApps'); +}); + GEN('#if !defined(OS_CHROMEOS)'); TEST_F( - 'CrSettingsPrivacyPageTest', 'ClearBrowsingDataTestsDesktop', function() { - settings_privacy_page.registerClearBrowsingDataTestsDesktop(); - mocha.run(); + 'CrSettingsClearBrowsingDataTest', 'ClearBrowsingDataDesktop', function() { + runMochaSuite('ClearBrowsingDataDesktop'); }); GEN('#endif');
diff --git a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js index c7a9889..0a48f13 100644 --- a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
@@ -434,3 +434,29 @@ TEST_F('CrSettingsSearchV3Test', 'All', function() { mocha.run(); }); + +// eslint-disable-next-line no-var +var CrSettingsClearBrowsingDataV3Test = class extends CrSettingsV3BrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://settings/test_loader.html?module=settings/clear_browsing_data_test.m.js'; + } +}; + +TEST_F( + 'CrSettingsClearBrowsingDataV3Test', 'ClearBrowsingDataAllPlatforms', + function() { + runMochaSuite('ClearBrowsingDataAllPlatforms'); + }); + +TEST_F('CrSettingsClearBrowsingDataV3Test', 'InstalledApps', () => { + runMochaSuite('InstalledApps'); +}); + +GEN('#if !defined(OS_CHROMEOS)'); +TEST_F( + 'CrSettingsClearBrowsingDataV3Test', 'ClearBrowsingDataDesktop', + function() { + runMochaSuite('ClearBrowsingDataDesktop'); + }); +GEN('#endif');
diff --git a/chrome/test/data/webui/settings/privacy_page_test.js b/chrome/test/data/webui/settings/privacy_page_test.js index e01a1fd..5b46923 100644 --- a/chrome/test/data/webui/settings/privacy_page_test.js +++ b/chrome/test/data/webui/settings/privacy_page_test.js
@@ -4,138 +4,6 @@ cr.define('settings_privacy_page', function() { - /** @implements {settings.ClearBrowsingDataBrowserProxy} */ - class TestClearBrowsingDataBrowserProxy extends TestBrowserProxy { - constructor() { - super(['initialize', 'clearBrowsingData', 'getInstalledApps']); - - /** - * The promise to return from |clearBrowsingData|. - * Allows testing code to test what happens after the call is made, and - * before the browser responds. - * @private {?Promise} - */ - this.clearBrowsingDataPromise_ = null; - - /** - * Response for |getInstalledApps|. - * @private {!Array<!InstalledApp>} - */ - this.installedApps_ = []; - } - - /** @param {!Promise} promise */ - setClearBrowsingDataPromise(promise) { - this.clearBrowsingDataPromise_ = promise; - } - - /** @override */ - clearBrowsingData(dataTypes, timePeriod, installedApps) { - this.methodCalled( - 'clearBrowsingData', [dataTypes, timePeriod, installedApps]); - cr.webUIListenerCallback('browsing-data-removing', true); - return this.clearBrowsingDataPromise_ !== null ? - this.clearBrowsingDataPromise_ : - Promise.resolve(); - } - - /** @param {!Array<!InstalledApp>} apps */ - setInstalledApps(apps) { - this.installedApps_ = apps; - } - - /** @override */ - getInstalledApps(timePeriod) { - this.methodCalled('getInstalledApps'); - return Promise.resolve(this.installedApps_); - } - - /** @override */ - initialize() { - this.methodCalled('initialize'); - return Promise.resolve(false); - } - } - - function getClearBrowsingDataPrefs() { - return { - browser: { - clear_data: { - browsing_history: { - key: 'browser.clear_data.browsing_history', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - browsing_history_basic: { - key: 'browser.clear_data.browsing_history_basic', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - cache: { - key: 'browser.clear_data.cache', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - cache_basic: { - key: 'browser.clear_data.cache_basic', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - cookies: { - key: 'browser.clear_data.cookies', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - cookies_basic: { - key: 'browser.clear_data.cookies_basic', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - download_history: { - key: 'browser.clear_data.download_history', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - hosted_apps_data: { - key: 'browser.clear_data.hosted_apps_data', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - form_data: { - key: 'browser.clear_data.form_data', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - passwords: { - key: 'browser.clear_data.passwords', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - site_settings: { - key: 'browser.clear_data.site_settings', - type: chrome.settingsPrivate.PrefType.BOOLEAN, - value: false, - }, - time_period: { - key: 'browser.clear_data.time_period', - type: chrome.settingsPrivate.PrefType.NUMBER, - value: 0, - }, - time_period_basic: { - key: 'browser.clear_data.time_period_basic', - type: chrome.settingsPrivate.PrefType.NUMBER, - value: 0, - }, - }, - last_clear_browsing_data_tab: { - key: 'browser.last_clear_browsing_data_tab', - type: chrome.settingsPrivate.PrefType.NUMBER, - value: 0, - }, - } - }; - } - function registerUMALoggingTests() { suite('PrivacyPageUMACheck', function() { /** @type {settings.TestPrivacyPageBrowserProxy} */ @@ -336,383 +204,6 @@ }); } - function registerClearBrowsingDataTestsDesktop() { - assert(!cr.isChromeOS); - suite('ClearBrowsingDataDesktop', function() { - /** @type {settings.TestClearBrowsingDataBrowserProxy} */ - let testBrowserProxy; - - /** @type {TestSyncBrowserProxy} */ - let testSyncBrowserProxy; - - /** @type {SettingsClearBrowsingDataDialogElement} */ - let element; - - setup(function() { - testBrowserProxy = new TestClearBrowsingDataBrowserProxy(); - settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy; - testSyncBrowserProxy = new TestSyncBrowserProxy(); - settings.SyncBrowserProxyImpl.instance_ = testSyncBrowserProxy; - PolymerTest.clearBody(); - element = document.createElement('settings-clear-browsing-data-dialog'); - element.set('prefs', getClearBrowsingDataPrefs()); - document.body.appendChild(element); - return testBrowserProxy.whenCalled('initialize').then(() => { - assertTrue(element.$$('#clearBrowsingDataDialog').open); - }); - }); - - teardown(function() { - element.remove(); - }); - - test('ClearBrowsingDataSyncAccountInfoDesktop', function() { - // Not syncing: the footer is hidden. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: false, - hasError: false, - }); - Polymer.dom.flush(); - assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - - // Syncing: the footer is shown, with the normal sync info. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: false, - }); - Polymer.dom.flush(); - assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - assertTrue(test_util.isChildVisible(element, '#sync-info')); - assertFalse(test_util.isChildVisible(element, '#sync-paused-info')); - assertFalse( - test_util.isChildVisible(element, '#sync-passphrase-error-info')); - assertFalse( - test_util.isChildVisible(element, '#sync-other-error-info')); - - // Sync is paused. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: true, - statusAction: settings.StatusAction.REAUTHENTICATE, - }); - Polymer.dom.flush(); - assertFalse(test_util.isChildVisible(element, '#sync-info')); - assertTrue(test_util.isChildVisible(element, '#sync-paused-info')); - assertFalse( - test_util.isChildVisible(element, '#sync-passphrase-error-info')); - assertFalse( - test_util.isChildVisible(element, '#sync-other-error-info')); - - // Sync passphrase error. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: true, - statusAction: settings.StatusAction.ENTER_PASSPHRASE, - }); - Polymer.dom.flush(); - assertFalse(test_util.isChildVisible(element, '#sync-info')); - assertFalse(test_util.isChildVisible(element, '#sync-paused-info')); - assertTrue( - test_util.isChildVisible(element, '#sync-passphrase-error-info')); - assertFalse( - test_util.isChildVisible(element, '#sync-other-error-info')); - - // Other sync error. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: true, - statusAction: settings.StatusAction.NO_ACTION, - }); - Polymer.dom.flush(); - assertFalse(test_util.isChildVisible(element, '#sync-info')); - assertFalse(test_util.isChildVisible(element, '#sync-paused-info')); - assertFalse( - test_util.isChildVisible(element, '#sync-passphrase-error-info')); - assertTrue(test_util.isChildVisible(element, '#sync-other-error-info')); - }); - - test('ClearBrowsingDataPauseSyncDesktop', function() { - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: false, - }); - Polymer.dom.flush(); - assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - const syncInfo = element.$$('#sync-info'); - assertTrue(test_util.isVisible(syncInfo)); - const signoutLink = syncInfo.querySelector('a[href]'); - assertTrue(!!signoutLink); - assertEquals(0, testSyncBrowserProxy.getCallCount('pauseSync')); - signoutLink.click(); - assertEquals(1, testSyncBrowserProxy.getCallCount('pauseSync')); - }); - - test('ClearBrowsingDataStartSignInDesktop', function() { - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: true, - statusAction: settings.StatusAction.REAUTHENTICATE, - }); - Polymer.dom.flush(); - assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - const syncInfo = element.$$('#sync-paused-info'); - assertTrue(test_util.isVisible(syncInfo)); - const signinLink = syncInfo.querySelector('a[href]'); - assertTrue(!!signinLink); - assertEquals(0, testSyncBrowserProxy.getCallCount('startSignIn')); - signinLink.click(); - assertEquals(1, testSyncBrowserProxy.getCallCount('startSignIn')); - }); - - test('ClearBrowsingDataHandlePassphraseErrorDesktop', function() { - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: true, - statusAction: settings.StatusAction.ENTER_PASSPHRASE, - }); - Polymer.dom.flush(); - assertTrue(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - const syncInfo = element.$$('#sync-passphrase-error-info'); - assertTrue(test_util.isVisible(syncInfo)); - const passphraseLink = syncInfo.querySelector('a[href]'); - assertTrue(!!passphraseLink); - passphraseLink.click(); - assertEquals( - settings.routes.SYNC, - settings.Router.getInstance().getCurrentRoute()); - }); - }); - } - - function registerClearBrowsingDataTests() { - suite('ClearBrowsingData', function() { - /** @type {settings.TestClearBrowsingDataBrowserProxy} */ - let testBrowserProxy; - - /** @type {SettingsClearBrowsingDataDialogElement} */ - let element; - - setup(function() { - testBrowserProxy = new TestClearBrowsingDataBrowserProxy(); - settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy; - PolymerTest.clearBody(); - element = document.createElement('settings-clear-browsing-data-dialog'); - element.set('prefs', getClearBrowsingDataPrefs()); - document.body.appendChild(element); - return testBrowserProxy.whenCalled('initialize'); - }); - - teardown(function() { - element.remove(); - }); - - test('ClearBrowsingDataTap', function() { - assertTrue(element.$$('#clearBrowsingDataDialog').open); - assertFalse(element.$$('#installedAppsDialog').open); - - const cancelButton = element.$$('.cancel-button'); - assertTrue(!!cancelButton); - const actionButton = element.$$('.action-button'); - assertTrue(!!actionButton); - const spinner = element.$$('paper-spinner-lite'); - assertTrue(!!spinner); - - // Select a datatype for deletion to enable the clear button. - const cookieCheckbox = element.$$('#cookiesCheckboxBasic'); - assertTrue(!!cookieCheckbox); - cookieCheckbox.$.checkbox.click(); - - assertFalse(cancelButton.disabled); - assertFalse(actionButton.disabled); - assertFalse(spinner.active); - - const promiseResolver = new PromiseResolver(); - testBrowserProxy.setClearBrowsingDataPromise(promiseResolver.promise); - actionButton.click(); - - return testBrowserProxy.whenCalled('clearBrowsingData') - .then(function(args) { - const dataTypes = args[0]; - const timePeriod = args[1]; - const installedApps = args[2]; - assertEquals(1, dataTypes.length); - assertEquals('browser.clear_data.cookies_basic', dataTypes[0]); - assertTrue(element.$$('#clearBrowsingDataDialog').open); - assertTrue(cancelButton.disabled); - assertTrue(actionButton.disabled); - assertTrue(spinner.active); - assertTrue(installedApps.length == 0); - - // Simulate signal from browser indicating that clearing has - // completed. - cr.webUIListenerCallback('browsing-data-removing', false); - promiseResolver.resolve(); - // Yields to the message loop to allow the callback chain of the - // Promise that was just resolved to execute before the - // assertions. - }) - .then(function() { - assertFalse(element.$$('#clearBrowsingDataDialog').open); - assertFalse(cancelButton.disabled); - assertFalse(actionButton.disabled); - assertFalse(spinner.active); - assertFalse(!!element.$$('#notice')); - - // Check that the dialog didn't switch to installed apps. - assertFalse(element.$$('#installedAppsDialog').open); - }); - }); - - test('ClearBrowsingDataClearButton', function() { - assertTrue(element.$$('#clearBrowsingDataDialog').open); - - const actionButton = element.$$('.action-button'); - assertTrue(!!actionButton); - const cookieCheckboxBasic = element.$$('#cookiesCheckboxBasic'); - assertTrue(!!cookieCheckboxBasic); - // Initially the button is disabled because all checkboxes are off. - assertTrue(actionButton.disabled); - // The button gets enabled if any checkbox is selected. - cookieCheckboxBasic.$.checkbox.click(); - assertTrue(cookieCheckboxBasic.checked); - assertFalse(actionButton.disabled); - // Switching to advanced disables the button. - element.$$('cr-tabs').selected = 1; - assertTrue(actionButton.disabled); - // Switching back enables it again. - element.$$('cr-tabs').selected = 0; - assertFalse(actionButton.disabled); - }); - - test('showHistoryDeletionDialog', function() { - assertTrue(element.$$('#clearBrowsingDataDialog').open); - const actionButton = element.$$('.action-button'); - assertTrue(!!actionButton); - - // Select a datatype for deletion to enable the clear button. - const cookieCheckbox = element.$$('#cookiesCheckboxBasic'); - assertTrue(!!cookieCheckbox); - cookieCheckbox.$.checkbox.click(); - assertFalse(actionButton.disabled); - - const promiseResolver = new PromiseResolver(); - testBrowserProxy.setClearBrowsingDataPromise(promiseResolver.promise); - actionButton.click(); - - return testBrowserProxy.whenCalled('clearBrowsingData') - .then(function() { - // Passing showNotice = true should trigger the notice about other - // forms of browsing history to open, and the dialog to stay open. - promiseResolver.resolve(true /* showNotice */); - - // Yields to the message loop to allow the callback chain of the - // Promise that was just resolved to execute before the - // assertions. - }) - .then(function() { - Polymer.dom.flush(); - const notice = element.$$('#notice'); - assertTrue(!!notice); - const noticeActionButton = notice.$$('.action-button'); - assertTrue(!!noticeActionButton); - - assertTrue(element.$$('#clearBrowsingDataDialog').open); - assertTrue(notice.$$('#dialog').open); - - noticeActionButton.click(); - - return new Promise(function(resolve, reject) { - // Tapping the action button will close the notice. Move to the - // end of the message loop to allow the closing event to - // propagate to the parent dialog. The parent dialog should - // subsequently close as well. - setTimeout(function() { - const notice = element.$$('#notice'); - assertFalse(!!notice); - assertFalse(element.$$('#clearBrowsingDataDialog').open); - resolve(); - }, 0); - }); - }); - }); - - test('Counters', function() { - assertTrue(element.$$('#clearBrowsingDataDialog').open); - - const checkbox = element.$$('#cacheCheckboxBasic'); - assertEquals('browser.clear_data.cache_basic', checkbox.pref.key); - - // Simulate a browsing data counter result for history. This checkbox's - // sublabel should be updated. - cr.webUIListenerCallback( - 'update-counter-text', checkbox.pref.key, 'result'); - assertEquals('result', checkbox.subLabel); - }); - - test('history rows are hidden for supervised users', function() { - assertFalse(loadTimeData.getBoolean('isSupervised')); - assertFalse(element.$$('#browsingCheckbox').hidden); - assertFalse(element.$$('#browsingCheckboxBasic').hidden); - assertFalse(element.$$('#downloadCheckbox').hidden); - - element.remove(); - testBrowserProxy.reset(); - loadTimeData.overrideValues({isSupervised: true}); - - element = document.createElement('settings-clear-browsing-data-dialog'); - document.body.appendChild(element); - Polymer.dom.flush(); - - return testBrowserProxy.whenCalled('initialize').then(function() { - assertTrue(element.$$('#browsingCheckbox').hidden); - assertTrue(element.$$('#browsingCheckboxBasic').hidden); - assertTrue(element.$$('#downloadCheckbox').hidden); - }); - }); - - if (cr.isChromeOS) { - // On ChromeOS the footer is never shown. - test('ClearBrowsingDataSyncAccountInfo', function() { - assertTrue(element.$$('#clearBrowsingDataDialog').open); - - // Not syncing. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: false, - hasError: false, - }); - Polymer.dom.flush(); - assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - - // Syncing. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: false, - }); - Polymer.dom.flush(); - assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - - // Sync passphrase error. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: true, - statusAction: settings.StatusAction.ENTER_PASSPHRASE, - }); - Polymer.dom.flush(); - assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - - // Other sync error. - cr.webUIListenerCallback('sync-status-changed', { - signedIn: true, - hasError: true, - statusAction: settings.StatusAction.NO_ACTION, - }); - Polymer.dom.flush(); - assertFalse(!!element.$$('#clearBrowsingDataDialog [slot=footer]')); - }); - } - }); - } - function registerPrivacyPageSoundTests() { suite('PrivacyPageSound', function() { /** @type {settings.TestPrivacyPageBrowserProxy} */ @@ -831,78 +322,8 @@ }); } - function registerInstalledAppsTests() { - suite('InstalledApps', function() { - /** @type {settings.TestClearBrowsingDataBrowserProxy} */ - let testBrowserProxy; - - /** @type {SettingsClearBrowsingDataDialogElement} */ - let element; - - /** @type {Array<InstalledApp>} */ - const installedApps = [ - {registerableDomain: 'google.com', isChecked: true}, - {registerableDomain: 'yahoo.com', isChecked: true}, - ]; - - setup(() => { - loadTimeData.overrideValues({installedAppsInCbd: true}); - testBrowserProxy = new TestClearBrowsingDataBrowserProxy(); - testBrowserProxy.setInstalledApps(installedApps); - settings.ClearBrowsingDataBrowserProxyImpl.instance_ = testBrowserProxy; - PolymerTest.clearBody(); - element = document.createElement('settings-clear-browsing-data-dialog'); - element.set('prefs', getClearBrowsingDataPrefs()); - document.body.appendChild(element); - return testBrowserProxy.whenCalled('initialize'); - }); - - teardown(() => { - element.remove(); - }); - - test('getInstalledApps', async function() { - assertTrue(element.$.clearBrowsingDataDialog.open); - assertFalse(element.$.installedAppsDialog.open); - - // Select cookie checkbox. - element.$.cookiesCheckboxBasic.$.checkbox.click(); - assertTrue(element.$.cookiesCheckboxBasic.checked); - // Clear browsing data. - element.$.clearBrowsingDataConfirm.click(); - assertTrue(element.$.clearBrowsingDataDialog.open); - - await testBrowserProxy.whenCalled('getInstalledApps'); - await test_util.whenAttributeIs( - element.$.installedAppsDialog, 'open', ''); - const firstInstalledApp = element.$$('installed-app-checkbox'); - assertTrue(!!firstInstalledApp); - assertEquals( - 'google.com', firstInstalledApp.installed_app.registerableDomain); - assertTrue(firstInstalledApp.installed_app.isChecked); - // Choose to keep storage for google.com. - firstInstalledApp.$.checkbox.click(); - assertFalse(firstInstalledApp.installed_app.isChecked); - // Confirm deletion. - element.$.installedAppsConfirm.click(); - const [dataTypes, timePeriod, apps] = - await testBrowserProxy.whenCalled('clearBrowsingData'); - assertEquals(1, dataTypes.length); - assertEquals('browser.clear_data.cookies_basic', dataTypes[0]); - assertEquals(2, apps.length); - assertEquals('google.com', apps[0].registerableDomain); - assertFalse(apps[0].isChecked); - assertEquals('yahoo.com', apps[1].registerableDomain); - assertTrue(apps[1].isChecked); - }); - }); - } - return { registerNativeCertificateManagerTests, - registerClearBrowsingDataTestsDesktop, - registerClearBrowsingDataTests, - registerInstalledAppsTests, registerPrivacyPageTests, registerPrivacyPageSoundTests, registerUMALoggingTests,
diff --git a/chrome/test/data/webui/settings/test_sync_browser_proxy.js b/chrome/test/data/webui/settings/test_sync_browser_proxy.js index 1012764..05e4e898 100644 --- a/chrome/test/data/webui/settings/test_sync_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_sync_browser_proxy.js
@@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #import {PageStatus} from 'chrome://settings/settings.js'; +// #import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; +// #import {isChromeOS} from 'chrome://resources/js/cr.m.js'; + /** @implements {settings.SyncBrowserProxy} */ -class TestSyncBrowserProxy extends TestBrowserProxy { +/* #export */ class TestSyncBrowserProxy extends TestBrowserProxy { constructor() { const methodNames = [ 'didNavigateAwayFromSyncPage',
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn index 47a3e9d..853c2b0 100644 --- a/chrome/updater/BUILD.gn +++ b/chrome/updater/BUILD.gn
@@ -57,6 +57,7 @@ deps = [ ":version_header", "//base", + "//components/crash/core/common:crash_key_lib", "//components/prefs", "//components/update_client", "//courgette:bsdiff", @@ -70,11 +71,16 @@ source_set("lib") { sources = [ + "app/app.cc", + "app/app.h", + "app/app_uninstall.cc", + "app/app_uninstall.h", + "app/app_update_all.cc", + "app/app_update_all.h", "configurator.cc", "configurator.h", "installer.cc", "installer.h", - "update_apps.cc", "update_apps.h", "update_service_in_process.cc", "update_service_in_process.h", @@ -85,6 +91,10 @@ if (is_mac) { sources += [ "installer_mac.cc", + "server/mac/server.h", + "server/mac/server.mm", + "server/mac/service_delegate.h", + "server/mac/service_delegate.mm", "update_apps_mac.mm", ] } @@ -92,6 +102,10 @@ if (is_win) { sources += [ "installer_win.cc", + "server/win/server.cc", + "server/win/server.h", + "server/win/service_main.cc", + "server/win/service_main.h", "update_apps_win.cc", ] } @@ -100,7 +114,6 @@ ":base", ":version_header", "//base", - "//chrome/updater/server", "//components/crash/core/common:crash_key", "//components/crx_file:crx_file", "//components/prefs", @@ -110,7 +123,11 @@ ] if (is_win) { - deps += [ "//chrome/updater/win:lib" ] + deps += [ + "//chrome/updater/server/win:updater_idl_idl", + "//chrome/updater/win:constants", + "//chrome/updater/win:lib", + ] } if (is_mac) { @@ -119,8 +136,14 @@ "//chrome/updater/mac:network_fetcher_sources", "//chrome/updater/mac:update_service_client_sources", "//chrome/updater/mac:updater_setup_sources", + "//chrome/updater/server/mac:protocol", ] } + + if (is_win) { + configs -= [ "//build/config/win:winver" ] + configs += [ "//chrome/updater/server/win:winver" ] + } } process_version("version_header") {
diff --git a/chrome/updater/app/app.cc b/chrome/updater/app/app.cc new file mode 100644 index 0000000..a6f89011 --- /dev/null +++ b/chrome/updater/app/app.cc
@@ -0,0 +1,61 @@ +// 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/updater/app/app.h" + +#include <utility> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/message_loop/message_pump_type.h" +#include "base/run_loop.h" +#include "base/task/single_thread_task_executor.h" +#include "base/task/thread_pool/thread_pool_instance.h" +#include "base/threading/thread_restrictions.h" +#include "chrome/updater/crash_client.h" +#include "chrome/updater/crash_reporter.h" +#include "chrome/updater/updater_version.h" +#include "components/crash/core/common/crash_key.h" + +namespace updater { + +App::App() = default; +App::~App() = default; + +int App::Run() { + crash_reporter::InitializeCrashKeys(); + static crash_reporter::CrashKeyString<16> crash_key_process_type( + "process_type"); + crash_key_process_type.Set("updater"); + if (CrashClient::GetInstance()->InitializeCrashReporting()) + VLOG(1) << "Crash reporting initialized."; + else + VLOG(1) << "Crash reporting is not available."; + StartCrashReporter(UPDATER_VERSION_STRING); + + base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Updater"); + base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI); + Initialize(); + base::RunLoop runloop; + base::ScopedDisallowBlocking no_blocking_allowed_on_ui_thread; + int exit_code = 0; + quit_ = base::BindOnce( + [](base::OnceClosure quit, int* exit_code_out, int exit_code) { + *exit_code_out = exit_code; + std::move(quit).Run(); + }, + runloop.QuitWhenIdleClosure(), &exit_code); + FirstTaskRun(); + runloop.Run(); + base::ThreadPoolInstance::Get()->Shutdown(); + return exit_code; +} + +void App::Shutdown(int exit_code) { + std::move(quit_).Run(exit_code); +} + +void App::Initialize() {} + +} // namespace updater
diff --git a/chrome/updater/app/app.h b/chrome/updater/app/app.h new file mode 100644 index 0000000..dc78a9fc --- /dev/null +++ b/chrome/updater/app/app.h
@@ -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. + +#ifndef CHROME_UPDATER_APP_APP_H_ +#define CHROME_UPDATER_APP_APP_H_ + +#include "base/callback.h" +#include "base/memory/ref_counted.h" + +namespace updater { + +// An App is a main processing mode for the updater. +class App : public base::RefCountedThreadSafe<App> { + public: + // Starts the thread pool and task executor, then runs a runloop on the main + // sequence until Shutdown() is called. Returns the exit code for the + // program. + int Run(); + + protected: + friend class base::RefCountedThreadSafe<App>; + App(); + virtual ~App(); + + // Triggers program shutdown. Must be called on the main sequence. The program + // will exit with the specified code. + void Shutdown(int exitCode); + + private: + // Implementations of App can override this to perform work on the main + // sequence while blocking is still allowed. The default implementation does + // nothing. + virtual void Initialize(); + + // Concrete implementations of App can execute their first task in this + // method. It is called on the main sequence. Blocking is not allowed. It may + // call Shutdown. + virtual void FirstTaskRun() = 0; + + // A callback that quits the main sequence runloop. + base::OnceCallback<void(int)> quit_; +}; + +} // namespace updater + +#endif // CHROME_UPDATER_APP_APP_H_
diff --git a/chrome/updater/app/app_uninstall.cc b/chrome/updater/app/app_uninstall.cc new file mode 100644 index 0000000..42699ee1 --- /dev/null +++ b/chrome/updater/app/app_uninstall.cc
@@ -0,0 +1,40 @@ +// 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/updater/app/app_uninstall.h" + +#include "base/bind.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "build/build_config.h" +#include "chrome/updater/app/app.h" + +#if defined(OS_WIN) +#include "chrome/updater/win/setup/uninstall.h" +#endif + +#if defined(OS_MACOSX) +#include "chrome/updater/mac/setup/setup.h" +#endif + +namespace updater { + +// AppUninstall uninstalls the updater. +class AppUninstall : public App { + private: + ~AppUninstall() override = default; + void FirstTaskRun() override; +}; + +void AppUninstall::FirstTaskRun() { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, base::BindOnce(&Uninstall, false), + base::BindOnce(&AppUninstall::Shutdown, this)); +} + +scoped_refptr<App> MakeAppUninstall() { + return base::MakeRefCounted<AppUninstall>(); +} + +} // namespace updater
diff --git a/chrome/updater/app/app_uninstall.h b/chrome/updater/app/app_uninstall.h new file mode 100644 index 0000000..79b16c3 --- /dev/null +++ b/chrome/updater/app/app_uninstall.h
@@ -0,0 +1,18 @@ +// 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_UPDATER_APP_APP_UNINSTALL_H_ +#define CHROME_UPDATER_APP_APP_UNINSTALL_H_ + +#include "base/memory/ref_counted.h" + +namespace updater { + +class App; + +scoped_refptr<App> MakeAppUninstall(); + +} // namespace updater + +#endif // CHROME_UPDATER_APP_APP_UNINSTALL_H_
diff --git a/chrome/updater/app/app_update_all.cc b/chrome/updater/app/app_update_all.cc new file mode 100644 index 0000000..51c36bf --- /dev/null +++ b/chrome/updater/app/app_update_all.cc
@@ -0,0 +1,39 @@ +// 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/updater/app/app_update_all.h" + +#include <memory> +#include <utility> + +#include "base/bind.h" +#include "base/logging.h" +#include "chrome/updater/app/app.h" +#include "chrome/updater/configurator.h" +#include "chrome/updater/update_apps.h" +#include "chrome/updater/update_service.h" + +namespace updater { + +class AppUpdateAll : public App { + private: + ~AppUpdateAll() override = default; + void FirstTaskRun() override; +}; + +// AppUpdateAll triggers an update of all registered applications. +void AppUpdateAll::FirstTaskRun() { + CreateUpdateService()->UpdateAll(base::BindOnce( + [](base::OnceCallback<void(int)> quit, update_client::Error error) { + VLOG(0) << "UpdateAll complete: error = " << static_cast<int>(error); + std::move(quit).Run(static_cast<int>(error)); + }, + base::BindOnce(&AppUpdateAll::Shutdown, this))); +} + +scoped_refptr<App> MakeAppUpdateAll() { + return base::MakeRefCounted<AppUpdateAll>(); +} + +} // namespace updater
diff --git a/chrome/updater/app/app_update_all.h b/chrome/updater/app/app_update_all.h new file mode 100644 index 0000000..5af7effc --- /dev/null +++ b/chrome/updater/app/app_update_all.h
@@ -0,0 +1,18 @@ +// 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_UPDATER_APP_APP_UPDATE_ALL_H_ +#define CHROME_UPDATER_APP_APP_UPDATE_ALL_H_ + +#include "base/memory/ref_counted.h" + +namespace updater { + +class App; + +scoped_refptr<App> MakeAppUpdateAll(); + +} // namespace updater + +#endif // CHROME_UPDATER_APP_APP_UPDATE_ALL_H_
diff --git a/chrome/updater/mac/BUILD.gn b/chrome/updater/mac/BUILD.gn index af6dc66..e9b747f 100644 --- a/chrome/updater/mac/BUILD.gn +++ b/chrome/updater/mac/BUILD.gn
@@ -38,7 +38,7 @@ "//base", "//chrome/updater:base", "//chrome/updater:version_header", - "//chrome/updater/server", + "//chrome/updater/server/mac:protocol", "//components/update_client", ]
diff --git a/chrome/updater/server/BUILD.gn b/chrome/updater/server/BUILD.gn deleted file mode 100644 index bce2419a..0000000 --- a/chrome/updater/server/BUILD.gn +++ /dev/null
@@ -1,12 +0,0 @@ -# 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. - -group("server") { - if (is_mac) { - public_deps = [ "//chrome/updater/server/mac" ] - } - if (is_win) { - public_deps = [ "//chrome/updater/server/win" ] - } -}
diff --git a/chrome/updater/server/mac/BUILD.gn b/chrome/updater/server/mac/BUILD.gn index b85c0535..143d98a 100644 --- a/chrome/updater/server/mac/BUILD.gn +++ b/chrome/updater/server/mac/BUILD.gn
@@ -2,18 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("mac") { - sources = [ - "server.h", - "server.mm", - "service_delegate.h", - "service_delegate.mm", - "service_protocol.h", - ] +source_set("protocol") { + sources = [ "service_protocol.h" ] - deps = [ - "//base", - "//chrome/updater:base", - "//chrome/updater:version_header", - ] + deps = [ "//chrome/updater:base" ] }
diff --git a/chrome/updater/server/mac/server.h b/chrome/updater/server/mac/server.h index 18bac40d..29a2c2bf 100644 --- a/chrome/updater/server/mac/server.h +++ b/chrome/updater/server/mac/server.h
@@ -5,13 +5,14 @@ #ifndef CHROME_UPDATER_SERVER_MAC_SERVER_H_ #define CHROME_UPDATER_SERVER_MAC_SERVER_H_ -#include <memory> +#include "base/memory/ref_counted.h" namespace updater { -class UpdateService; +class App; -int RunServer(std::unique_ptr<UpdateService> update_service); -} +scoped_refptr<App> MakeAppServer(); + +} // namespace updater #endif // CHROME_UPDATER_SERVER_MAC_SERVER_H_
diff --git a/chrome/updater/server/mac/server.mm b/chrome/updater/server/mac/server.mm index 7a25969..4d51a4a 100644 --- a/chrome/updater/server/mac/server.mm +++ b/chrome/updater/server/mac/server.mm
@@ -8,29 +8,58 @@ #include <xpc/xpc.h> #include "base/mac/scoped_nsobject.h" +#include "base/memory/ref_counted.h" #include "base/strings/sys_string_conversions.h" -#import "chrome/updater/server/mac/service_delegate.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "chrome/updater/app/app.h" +#import "chrome/updater/configurator.h" +#include "chrome/updater/server/mac/service_delegate.h" #import "chrome/updater/update_service.h" +#include "chrome/updater/update_service_in_process.h" #include "chrome/updater/updater_version.h" namespace updater { -int RunServer(std::unique_ptr<UpdateService> update_service) { +class AppServer : public App { + public: + AppServer(); + + private: + ~AppServer() override; + void Initialize() override; + void FirstTaskRun() override; + + scoped_refptr<Configurator> config_; + base::scoped_nsobject<CRUUpdateCheckXPCServiceDelegate> delegate_; + base::scoped_nsobject<NSXPCListener> listener_; +}; + +AppServer::AppServer() = default; +AppServer::~AppServer() = default; + +void AppServer::Initialize() { + config_ = base::MakeRefCounted<Configurator>(); +} + +void AppServer::FirstTaskRun() { @autoreleasepool { std::string service_name = MAC_BUNDLE_IDENTIFIER_STRING; service_name.append(".UpdaterXPCService"); - base::scoped_nsobject<CRUUpdateCheckXPCServiceDelegate> delegate( - [[CRUUpdateCheckXPCServiceDelegate alloc] - initWithUpdateService:std::move(update_service)]); + delegate_.reset([[CRUUpdateCheckXPCServiceDelegate alloc] + initWithUpdateService:std::make_unique<UpdateServiceInProcess>( + config_)]); - NSXPCListener* listener = [[NSXPCListener alloc] - initWithMachServiceName:base::SysUTF8ToNSString(service_name)]; - listener.delegate = delegate.get(); + listener_.reset([[NSXPCListener alloc] + initWithMachServiceName:base::SysUTF8ToNSString(service_name)]); + listener_.get().delegate = delegate_.get(); - [listener resume]; - - return 0; + [listener_ resume]; } } +scoped_refptr<App> MakeAppServer() { + return base::MakeRefCounted<AppServer>(); +} + } // namespace updater
diff --git a/chrome/updater/server/win/BUILD.gn b/chrome/updater/server/win/BUILD.gn index c8db811..d96da1e 100644 --- a/chrome/updater/server/win/BUILD.gn +++ b/chrome/updater/server/win/BUILD.gn
@@ -4,25 +4,6 @@ import("//build/toolchain/win/midl.gni") -source_set("win") { - sources = [ - "server.cc", - "server.h", - "service_main.cc", - "service_main.h", - ] - - configs -= [ "//build/config/win:winver" ] - configs += [ ":winver" ] - - deps = [ - ":updater_idl_idl", - "//base", - "//chrome/updater:base", - "//chrome/updater/win:constants", - ] -} - midl("updater_idl_idl") { sources = [ "updater_idl.idl" ]
diff --git a/chrome/updater/server/win/server.cc b/chrome/updater/server/win/server.cc index 3234444..fa776db 100644 --- a/chrome/updater/server/win/server.cc +++ b/chrome/updater/server/win/server.cc
@@ -11,12 +11,62 @@ #include "chrome/updater/server/win/server.h" +#include <windows.h> +#include <wrl/implements.h> +#include <wrl/module.h> + #include "base/logging.h" +#include "base/stl_util.h" #include "base/win/scoped_com_initializer.h" +#include "chrome/updater/app/app.h" +#include "chrome/updater/configurator.h" #include "chrome/updater/update_service.h" +#include "chrome/updater/update_service_in_process.h" namespace updater { +// This class is responsible for the lifetime of the COM server, as well as +// class factory registration. +class ComServer : public App { + public: + ComServer(); + + private: + ~ComServer() override = default; + + void Initialize() override; + + void FirstTaskRun() override; + + // Registers and unregisters the out-of-process COM class factories. + HRESULT RegisterClassObject(); + void UnregisterClassObject(); + + // Waits until the last COM object is released. + void WaitForExitSignal(); + + // Called when the last object is released. + void SignalExit(); + + // Creates an out-of-process WRL Module. + void CreateWRLModule(); + + // Handles object unregistration then triggers program shutdown. + void Stop(); + + // Identifier of registered class objects used for unregistration. + DWORD cookies_[1] = {}; + + // While this object lives, COM can be used by all threads in the program. + base::win::ScopedCOMInitializer com_initializer_; + + // The UpdateService to use for handling COM requests. + std::unique_ptr<UpdateService> service_; + + // The updater's Configurator. + scoped_refptr<Configurator> config_; +}; + HRESULT UpdaterImpl::CheckForUpdate(const base::char16* app_id) { return E_NOTIMPL; } @@ -34,21 +84,7 @@ } ComServer::ComServer() - : exit_signal_(base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED) {} - -int ComServer::RunComServer() { - // Initialize COM for the current thread. - base::win::ScopedCOMInitializer com_initializer( - base::win::ScopedCOMInitializer::kMTA); - if (!com_initializer.Succeeded()) { - PLOG(ERROR) << "Failed to initialize COM"; - return -1; - } - - // Run the COM server. - return Run(); -} + : com_initializer_(base::win::ScopedCOMInitializer::kMTA) {} HRESULT ComServer::RegisterClassObject() { auto& module = Microsoft::WRL::Module<Microsoft::WRL::OutOfProc>::GetModule(); @@ -100,32 +136,35 @@ LOG(ERROR) << "UnregisterCOMObject failed; hr: " << hr; } -void ComServer::WaitForExitSignal() { - exit_signal_.Wait(); -} - -void ComServer::SignalExit() { - exit_signal_.Signal(); -} - void ComServer::CreateWRLModule() { - Microsoft::WRL::Module<Microsoft::WRL::OutOfProc>::Create( - this, &ComServer::SignalExit); + Microsoft::WRL::Module<Microsoft::WRL::OutOfProc>::Create(this, + &ComServer::Stop); } -HRESULT ComServer::Run() { +void ComServer::Stop() { + UnregisterClassObject(); + Shutdown(0); +} + +void ComServer::Initialize() { + config_ = base::MakeRefCounted<Configurator>(); +} + +void ComServer::FirstTaskRun() { + if (!com_initializer_.Succeeded()) { + PLOG(ERROR) << "Failed to initialize COM"; + Shutdown(-1); + return; + } + service_ = std::make_unique<UpdateServiceInProcess>(config_); CreateWRLModule(); HRESULT hr = RegisterClassObject(); - if (SUCCEEDED(hr)) { - WaitForExitSignal(); - UnregisterClassObject(); - } - - return hr; + if (FAILED(hr)) + Shutdown(hr); } -int RunServer(std::unique_ptr<UpdateService> update_service) { - return ComServer().RunComServer(); +scoped_refptr<App> MakeAppServer() { + return base::MakeRefCounted<ComServer>(); } } // namespace updater
diff --git a/chrome/updater/server/win/server.h b/chrome/updater/server/win/server.h index 85d4abb..08835b280 100644 --- a/chrome/updater/server/win/server.h +++ b/chrome/updater/server/win/server.h
@@ -5,20 +5,15 @@ #ifndef CHROME_UPDATER_SERVER_WIN_SERVER_H_ #define CHROME_UPDATER_SERVER_WIN_SERVER_H_ -#include <windows.h> - #include <wrl/implements.h> #include <wrl/module.h> -#include <memory> +#include "base/memory/ref_counted.h" #include "base/strings/string16.h" -#include "base/synchronization/waitable_event.h" #include "chrome/updater/server/win/updater_idl.h" namespace updater { -class UpdateService; - // This class implements the IUpdater interface and exposes it as a COM object. class UpdaterImpl : public Microsoft::WRL::RuntimeClass< @@ -41,45 +36,9 @@ ~UpdaterImpl() override = default; }; -// This class is responsible for the lifetime of the COM server, as well as -// class factory registration. -class ComServer { - public: - ComServer(); - ComServer(const ComServer&) = delete; - ComServer& operator=(const ComServer&) = delete; - ~ComServer() = default; +class App; - // Main entry point for the COM server. - int RunComServer(); - - private: - // Registers and unregisters the out-of-process COM class factories. - HRESULT RegisterClassObject(); - void UnregisterClassObject(); - - // Waits until the last COM object is released. - void WaitForExitSignal(); - - // Called when the last object is released. - void SignalExit(); - - // Creates an out-of-process WRL Module. - void CreateWRLModule(); - - // Handles object registration, message loop, and unregistration. Returns - // when all registered objects are released. - HRESULT Run(); - - // Identifier of registered class objects used for unregistration. - DWORD cookies_[1] = {}; - - // This event is signaled when the last COM instance is released. - base::WaitableEvent exit_signal_; -}; - -// Sets up and runs the server. -int RunServer(std::unique_ptr<UpdateService> update_service); +scoped_refptr<App> MakeAppServer(); } // namespace updater
diff --git a/chrome/updater/update_apps.cc b/chrome/updater/update_apps.cc deleted file mode 100644 index eecb58a..0000000 --- a/chrome/updater/update_apps.cc +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/updater/update_apps.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/run_loop.h" -#include "base/task/single_thread_task_executor.h" -#include "chrome/updater/update_service.h" - -namespace updater { - -int UpdateApps() { - base::SingleThreadTaskExecutor main_task_executor; - base::RunLoop runloop; - std::unique_ptr<UpdateService> service = CreateUpdateService(); - service->UpdateAll(base::BindOnce( - [](base::OnceClosure quit, update_client::Error error) { - VLOG(0) << "UpdateAll complete: error = " << static_cast<int>(error); - std::move(quit).Run(); - }, - runloop.QuitWhenIdleClosure())); - runloop.Run(); - return 0; -} - -} // namespace updater
diff --git a/chrome/updater/update_apps.h b/chrome/updater/update_apps.h index 6e1c76d..6a89f54 100644 --- a/chrome/updater/update_apps.h +++ b/chrome/updater/update_apps.h
@@ -13,9 +13,6 @@ // A factory method to create an UpdateService class instance. std::unique_ptr<UpdateService> CreateUpdateService(); -// Updates all registered applications. -int UpdateApps(); - } // namespace updater #endif // CHROME_UPDATER_UPDATE_APPS_H_
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index 738c7d5..51c20de2 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -8,28 +8,23 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" -#include "base/run_loop.h" -#include "base/task/thread_pool/thread_pool_instance.h" #include "build/build_config.h" +#include "chrome/updater/app/app.h" +#include "chrome/updater/app/app_uninstall.h" +#include "chrome/updater/app/app_update_all.h" #include "chrome/updater/configurator.h" #include "chrome/updater/constants.h" #include "chrome/updater/crash_client.h" #include "chrome/updater/crash_reporter.h" -#include "chrome/updater/update_apps.h" -#include "chrome/updater/update_service_in_process.h" -#include "chrome/updater/updater_version.h" #include "chrome/updater/util.h" -#include "components/crash/core/common/crash_key.h" #if defined(OS_WIN) #include "chrome/updater/server/win/server.h" #include "chrome/updater/server/win/service_main.h" #include "chrome/updater/win/install_app.h" -#include "chrome/updater/win/setup/uninstall.h" #endif #if defined(OS_MACOSX) -#include "chrome/updater/mac/setup/setup.h" #include "chrome/updater/server/mac/server.h" #endif @@ -47,14 +42,6 @@ namespace { -void ThreadPoolStart() { - base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Updater"); -} - -void ThreadPoolStop() { - base::ThreadPoolInstance::Get()->Shutdown(); -} - // The log file is created in DIR_LOCAL_APP_DATA or DIR_APP_DATA. void InitLogging(const base::CommandLine& command_line) { logging::LoggingSettings settings; @@ -71,80 +58,33 @@ VLOG(1) << "Log file " << settings.log_file_path; } -void InitializeUpdaterMain() { - crash_reporter::InitializeCrashKeys(); - - static crash_reporter::CrashKeyString<16> crash_key_process_type( - "process_type"); - crash_key_process_type.Set("updater"); - - if (CrashClient::GetInstance()->InitializeCrashReporting()) - VLOG(1) << "Crash reporting initialized."; - else - VLOG(1) << "Crash reporting is not available."; - - StartCrashReporter(UPDATER_VERSION_STRING); - - ThreadPoolStart(); -} - -void TerminateUpdaterMain() { - ThreadPoolStop(); -} - -void UpdaterUpdateApps() { - UpdateApps(); -} - -int UpdaterInstallApp() { -#if defined(OS_WIN) - // TODO(sorin): pick up the app id from the tag. https://crbug.com/1014298 - return InstallApp({kChromeAppId}); -#else - NOTREACHED(); - return -1; -#endif -} - -int UpdaterUninstall() { -#if defined(OS_WIN) || defined(OS_MACOSX) - return Uninstall(false); -#else - return -1; -#endif -} - } // namespace int HandleUpdaterCommands(const base::CommandLine* command_line) { DCHECK(!command_line->HasSwitch(kCrashHandlerSwitch)); -#if defined(OS_WIN) || defined(OS_MACOSX) - if (command_line->HasSwitch(kServerSwitch)) { - return RunServer(std::make_unique<UpdateServiceInProcess>( - base::MakeRefCounted<Configurator>())); - } -#endif - -#if defined(OS_WIN) - if (command_line->HasSwitch(kComServiceSwitch)) - return ServiceMain::RunComService(command_line); -#endif - if (command_line->HasSwitch(kCrashMeSwitch)) { int* ptr = nullptr; return *ptr; } + if (command_line->HasSwitch(kServerSwitch)) { + return MakeAppServer()->Run(); + } + +#if defined(OS_WIN) + if (command_line->HasSwitch(kComServiceSwitch)) + return ServiceMain::RunComService(command_line); + if (command_line->HasSwitch(kInstallSwitch)) - return UpdaterInstallApp(); + return InstallApp({kChromeAppId}); +#endif if (command_line->HasSwitch(kUninstallSwitch)) - return UpdaterUninstall(); + return MakeAppUninstall()->Run(); if (command_line->HasSwitch(kUpdateAppsSwitch)) { - UpdaterUpdateApps(); - return 0; + return MakeAppUpdateAll()->Run(); } VLOG(1) << "Unknown command line switch."; @@ -165,10 +105,7 @@ if (command_line->HasSwitch(kCrashHandlerSwitch)) return CrashReporterMain(); - InitializeUpdaterMain(); - const auto result = HandleUpdaterCommands(command_line); - TerminateUpdaterMain(); - return result; + return HandleUpdaterCommands(command_line); } } // namespace updater
diff --git a/chrome/updater/win/BUILD.gn b/chrome/updater/win/BUILD.gn index 158526e0..6fa984c 100644 --- a/chrome/updater/win/BUILD.gn +++ b/chrome/updater/win/BUILD.gn
@@ -189,7 +189,6 @@ "//base", "//base/test:test_support", "//chrome/updater:version_header", - "//chrome/updater/server/win", "//chrome/updater/win/test:test_executables", "//chrome/updater/win/test:test_strings", "//testing/gtest",
diff --git a/chrome/updater/win/test/BUILD.gn b/chrome/updater/win/test/BUILD.gn index f3b9809..1340a2907 100644 --- a/chrome/updater/win/test/BUILD.gn +++ b/chrome/updater/win/test/BUILD.gn
@@ -60,6 +60,6 @@ "//base", "//base/test:test_support", "//build/win:default_exe_manifest", - "//chrome/updater/server/win", + "//chrome/updater:lib", ] }
diff --git a/chromecast/crash/app_state_tracker.cc b/chromecast/crash/app_state_tracker.cc index e11956cf..f04b96d 100644 --- a/chromecast/crash/app_state_tracker.cc +++ b/chromecast/crash/app_state_tracker.cc
@@ -14,6 +14,7 @@ std::string previous_app; std::string current_app; std::string last_launched_app; + std::string stadia_session_id; }; CurrentAppState* GetAppState() { @@ -41,6 +42,11 @@ } // static +std::string AppStateTracker::GetStadiaSessionId() { + return GetAppState()->stadia_session_id; +} + +// static void AppStateTracker::SetLastLaunchedApp(const std::string& app_id) { GetAppState()->last_launched_app = app_id; @@ -59,4 +65,15 @@ crash_keys::previous_app.Set(app_state->previous_app); } +// static +void AppStateTracker::SetStadiaSessionId(const std::string& stadia_session_id) { + if (!stadia_session_id.empty()) { + GetAppState()->stadia_session_id = stadia_session_id; + crash_keys::stadia_session_id.Set(stadia_session_id); + } else { + GetAppState()->stadia_session_id.clear(); + crash_keys::stadia_session_id.Clear(); + } +} + } // namespace chromecast
diff --git a/chromecast/crash/app_state_tracker.h b/chromecast/crash/app_state_tracker.h index 3df8686c..513d42c 100644 --- a/chromecast/crash/app_state_tracker.h +++ b/chromecast/crash/app_state_tracker.h
@@ -17,6 +17,10 @@ // The current app becomes the previous app, |app_id| becomes the current app. static void SetCurrentApp(const std::string& app_id); + // Set the Stadia session ID, when a Stadia session starts running. + // Clear the Stadia session ID by passing in an empty string + static void SetStadiaSessionId(const std::string& stadia_session_id); + // Returns the id of the app that was last attempted to launch. static std::string GetLastLaunchedApp(); @@ -25,6 +29,9 @@ // Returns the id of the app which was previously active. static std::string GetPreviousApp(); + + // Returns the Stadia session ID, if a Stadia session is running. + static std::string GetStadiaSessionId(); }; } // namespace chromecast
diff --git a/chromecast/crash/cast_crash_keys.cc b/chromecast/crash/cast_crash_keys.cc index f2133d1..0237a5c 100644 --- a/chromecast/crash/cast_crash_keys.cc +++ b/chromecast/crash/cast_crash_keys.cc
@@ -11,5 +11,7 @@ crash_reporter::CrashKeyString<64> previous_app("previous_app"); +crash_reporter::CrashKeyString<64> stadia_session_id("stadia_session_id"); + } // namespace crash_keys } // namespace chromecast
diff --git a/chromecast/crash/cast_crash_keys.h b/chromecast/crash/cast_crash_keys.h index 83dfaf46..6f61531 100644 --- a/chromecast/crash/cast_crash_keys.h +++ b/chromecast/crash/cast_crash_keys.h
@@ -14,6 +14,8 @@ extern crash_reporter::CrashKeyString<64> previous_app; +extern crash_reporter::CrashKeyString<64> stadia_session_id; + } // namespace crash_keys } // namespace chromecast
diff --git a/chromecast/crash/linux/crash_util.cc b/chromecast/crash/linux/crash_util.cc index a2de8f6..66ed4901 100644 --- a/chromecast/crash/linux/crash_util.cc +++ b/chromecast/crash/linux/crash_util.cc
@@ -50,7 +50,8 @@ "", // suffix AppStateTracker::GetPreviousApp(), AppStateTracker::GetCurrentApp(), AppStateTracker::GetLastLaunchedApp(), CAST_BUILD_RELEASE, - CAST_BUILD_INCREMENTAL, "" /* reason */); + CAST_BUILD_INCREMENTAL, "", /* reason */ + AppStateTracker::GetStadiaSessionId()); DummyMinidumpGenerator minidump_generator(existing_minidump_path); base::FilePath filename = base::FilePath(existing_minidump_path).BaseName();
diff --git a/chromecast/crash/linux/dump_info.cc b/chromecast/crash/linux/dump_info.cc index f3516af..926c274 100644 --- a/chromecast/crash/linux/dump_info.cc +++ b/chromecast/crash/linux/dump_info.cc
@@ -32,6 +32,7 @@ const char kReleaseVersionKey[] = "release_version"; const char kBuildNumberKey[] = "build_number"; const char kReasonKey[] = "reason"; +const char kStadiaSessionIdKey[] = "stadia_session_id"; } // namespace @@ -75,6 +76,7 @@ entry->SetString(kReleaseVersionKey, params_.cast_release_version); entry->SetString(kBuildNumberKey, params_.cast_build_number); entry->SetString(kReasonKey, params_.reason); + entry->SetString(kStadiaSessionIdKey, params_.stadia_session_id); return result; } @@ -129,6 +131,8 @@ ++num_params; if (dict->GetString(kReasonKey, ¶ms_.reason)) ++num_params; + if (dict->GetString(kStadiaSessionIdKey, ¶ms_.stadia_session_id)) + ++num_params; // Disallow extraneous params if (dict->size() != num_params)
diff --git a/chromecast/crash/linux/minidump_params.cc b/chromecast/crash/linux/minidump_params.cc index ff81e2b..7f69427 100644 --- a/chromecast/crash/linux/minidump_params.cc +++ b/chromecast/crash/linux/minidump_params.cc
@@ -13,7 +13,8 @@ const std::string& p_last_app_name, const std::string& p_cast_release_version, const std::string& p_cast_build_number, - const std::string& p_reason) + const std::string& p_reason, + const std::string& p_stadia_session_id) : process_uptime(p_process_uptime), suffix(p_suffix), previous_app_name(p_previous_app_name), @@ -21,7 +22,8 @@ last_app_name(p_last_app_name), cast_release_version(p_cast_release_version), cast_build_number(p_cast_build_number), - reason(p_reason) {} + reason(p_reason), + stadia_session_id(p_stadia_session_id) {} MinidumpParams::MinidumpParams() : process_uptime(0) {}
diff --git a/chromecast/crash/linux/minidump_params.h b/chromecast/crash/linux/minidump_params.h index 9cf92d8..fb07cb4 100644 --- a/chromecast/crash/linux/minidump_params.h +++ b/chromecast/crash/linux/minidump_params.h
@@ -20,7 +20,8 @@ const std::string& p_last_app_name, const std::string& p_cast_release_version, const std::string& p_cast_build_number, - const std::string& p_reason); + const std::string& p_reason, + const std::string& p_stadia_session_id); MinidumpParams(const MinidumpParams& params); ~MinidumpParams(); @@ -35,6 +36,8 @@ std::string cast_build_number; // Reason for crash, if one is available. std::string reason; + // Stadia Session ID, if a Stadia session was running at the time of crash. + std::string stadia_session_id; }; } // namespace chromecast
diff --git a/chromecast/crash/linux/minidump_uploader.cc b/chromecast/crash/linux/minidump_uploader.cc index d63a128..4d0c114 100644 --- a/chromecast/crash/linux/minidump_uploader.cc +++ b/chromecast/crash/linux/minidump_uploader.cc
@@ -254,6 +254,9 @@ if (!dump.params().reason.empty()) { g.SetParameter("reason", dump.params().reason); } + if (!dump.params().stadia_session_id.empty()) { + g.SetParameter("stadia_session_id", dump.params().stadia_session_id); + } std::string response; if (!g.Upload(&response)) {
diff --git a/chromecast/crash/linux/minidump_uploader_unittest.cc b/chromecast/crash/linux/minidump_uploader_unittest.cc index 9e67ce50..74e9fd0 100644 --- a/chromecast/crash/linux/minidump_uploader_unittest.cc +++ b/chromecast/crash/linux/minidump_uploader_unittest.cc
@@ -97,7 +97,7 @@ // Must pass in non-empty MinidumpParams to circumvent the internal checks. std::unique_ptr<DumpInfo> dump(new DumpInfo( minidump_path.value(), logfile_path.value(), base::Time::Now(), - MinidumpParams(0, "_", "_", "_", "_", "_", "_", "_"))); + MinidumpParams(0, "_", "_", "_", "_", "_", "_", "_", "_"))); CHECK(AppendLockFile(lockfile_.value(), metadata_.value(), *dump)); base::File minidump(
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 6d40519f..e267e94 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -91,7 +91,11 @@ } if (is_printing_ppd_provider_v3) { - sources += [ "printing/ppd_provider_v3.cc" ] + sources += [ + "printing/ppd_provider_v3.cc", + "printing/printer_config_cache.cc", + "printing/printer_config_cache.h", + ] } else { sources += [ "printing/ppd_provider.cc" ] } @@ -194,7 +198,6 @@ "printing/epson_driver_matching_unittest.cc", "printing/ppd_cache_unittest.cc", "printing/ppd_line_reader_unittest.cc", - "printing/ppd_provider_unittest.cc", "printing/printer_configuration_unittest.cc", "printing/printer_translator_unittest.cc", "printing/usb_printer_id_unittest.cc", @@ -203,6 +206,12 @@ "test/run_all_unittests.cc", ] + if (is_printing_ppd_provider_v3) { + sources += [ "printing/printer_config_cache_unittest.cc" ] + } else { + sources += [ "printing/ppd_provider_unittest.cc" ] + } + data = [ "test/data/" ] }
diff --git a/chromeos/printing/ppd_provider_v3.cc b/chromeos/printing/ppd_provider_v3.cc index 2bddfa5..e8636f10 100644 --- a/chromeos/printing/ppd_provider_v3.cc +++ b/chromeos/printing/ppd_provider_v3.cc
@@ -91,8 +91,8 @@ const PpdProvider::Options& options) { // TODO(crbug.com/888189): use |loader_factory| and do away with // |ppd_cache|. - return base::MakeRefCounted<PpdProvider>(browser_locale, current_version, - options); + return base::MakeRefCounted<PpdProviderImpl>(browser_locale, current_version, + options); } } // namespace chromeos
diff --git a/chromeos/printing/printer_config_cache.cc b/chromeos/printing/printer_config_cache.cc new file mode 100644 index 0000000..06bb6a1 --- /dev/null +++ b/chromeos/printing/printer_config_cache.cc
@@ -0,0 +1,217 @@ +// 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 "chromeos/printing/printer_config_cache.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "base/location.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/strings/strcat.h" +#include "base/strings/string_piece.h" +#include "base/task/post_task.h" +#include "base/time/clock.h" +#include "base/time/time.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" +#include "url/gurl.h" + +namespace chromeos { + +namespace { + +// Defines the serving root in which all PPDs and PPD metadata reside. +const char kServingRoot[] = + "https://printerconfigurations.googleusercontent.com/" + "chromeos_printing/"; + +// Prepends the serving root to |name|, returning the result. +std::string PrependServingRoot(const std::string& name) { + return base::StrCat({base::StringPiece(kServingRoot), name}); +} + +// Accepts a relative |path| to a value in the Chrome OS Printing +// serving root) and returns a resource request to satisfy the same. +std::unique_ptr<network::ResourceRequest> FormRequest(const std::string& path) { + GURL full_url(PrependServingRoot(path)); + if (!full_url.is_valid()) { + return nullptr; + } + + auto request = std::make_unique<network::ResourceRequest>(); + request->url = full_url; + + request->load_flags = net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE; + request->credentials_mode = network::mojom::CredentialsMode::kOmit; + return request; +} + +} // namespace + +// In case of fetch failure, only the key is meaningful feedback. +// static +PrinterConfigCache::FetchResult PrinterConfigCache::FetchResult::Failure( + const std::string& key) { + return PrinterConfigCache::FetchResult{false, key, std::string(), + base::Time()}; +} + +// static +PrinterConfigCache::FetchResult PrinterConfigCache::FetchResult::Success( + const std::string& key, + const std::string& contents, + base::Time time_of_fetch) { + return PrinterConfigCache::FetchResult{true, key, contents, time_of_fetch}; +} + +class PrinterConfigCacheImpl : public PrinterConfigCache { + public: + explicit PrinterConfigCacheImpl( + const base::Clock* clock, + network::mojom::URLLoaderFactory* loader_factory) + : clock_(clock), loader_factory_(loader_factory), weak_factory_(this) {} + + ~PrinterConfigCacheImpl() override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + } + + void Fetch(const std::string& key, + base::TimeDelta expiration, + FetchCallback cb) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // Try to answer this fetch request locally. + const auto& finding = cache_.find(key); + if (finding != cache_.end()) { + const Entry& entry = finding->second; + if (entry.time_of_fetch + expiration > clock_->Now()) { + std::move(cb).Run( + FetchResult::Success(key, entry.contents, entry.time_of_fetch)); + return; + } + } + + // We couldn't answer this request locally. Issue a networked fetch + // and defer the answer to when we hear back. + auto context = std::make_unique<FetchContext>(key, std::move(cb)); + fetch_queue_.push(std::move(context)); + TryToStartNetworkedFetch(); + } + + void Drop(const std::string& key) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + cache_.erase(key); + } + + private: + // A FetchContext saves off the key and the FetchCallback that a + // caller passes to PrinterConfigCacheImpl::Fetch(). + struct FetchContext { + const std::string key; + PrinterConfigCache::FetchCallback cb; + + FetchContext(const std::string& arg_key, + PrinterConfigCache::FetchCallback arg_cb) + : key(arg_key), cb(std::move(arg_cb)) {} + ~FetchContext() = default; + }; + + // If a PrinterConfigCache maps keys to values, then Entry structs + // represent values. + struct Entry { + std::string contents; + base::Time time_of_fetch; + + Entry(const std::string& arg_contents, base::Time time) + : contents(arg_contents), time_of_fetch(time) {} + ~Entry() = default; + }; + + void TryToStartNetworkedFetch() { + // Either + // 1. a networked fetch is already in flight or + // 2. there are no more pending networked fetches to act upon. + // In either case, we can't do anything at the moment; back off + // and let a future call to Fetch() or FinishNetworkedFetch() + // return here to try again. + if (fetcher_ || fetch_queue_.empty()) { + return; + } + + std::unique_ptr<FetchContext> context = std::move(fetch_queue_.front()); + fetch_queue_.pop(); + auto request = FormRequest(context->key); + + // TODO(crbug.com/888189): add traffic annotation. + fetcher_ = network::SimpleURLLoader::Create(std::move(request), + MISSING_TRAFFIC_ANNOTATION); + fetcher_->DownloadToString( + loader_factory_, + base::BindOnce(&PrinterConfigCacheImpl::FinishNetworkedFetch, + weak_factory_.GetWeakPtr(), std::move(context)), + network::SimpleURLLoader::kMaxBoundedStringDownloadSize); + } + + // Called by |fetcher_| once DownloadToString() completes. + void FinishNetworkedFetch(std::unique_ptr<FetchContext> context, + std::unique_ptr<std::string> contents) { + // Wherever |fetcher_| works its sorcery, it had better have posted + // back onto _our_ sequence. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (fetcher_->NetError() == net::Error::OK) { + // We only want to update our local cache if the |fetcher_| + // succeeded; otherwise, prefer to either retain the stale entry + // (if extant) or retain no entry at all (if not). + const Entry newly_inserted = Entry(*contents, clock_->Now()); + cache_.insert_or_assign(context->key, newly_inserted); + std::move(context->cb) + .Run(FetchResult::Success(context->key, newly_inserted.contents, + newly_inserted.time_of_fetch)); + } else { + std::move(context->cb).Run(FetchResult::Failure(context->key)); + } + + fetcher_.reset(); + TryToStartNetworkedFetch(); + } + + // The heart of an PrinterConfigCache: the local cache itself. + base::flat_map<std::string, Entry> cache_; + + // Enqueues networked requests. + base::queue<std::unique_ptr<FetchContext>> fetch_queue_; + + // Dispenses Time objects to mark time of fetch on Entry instances. + const base::Clock* clock_; + + // Mutably borrowed from caller at construct-time. + network::mojom::URLLoaderFactory* loader_factory_; + + // Talks to the networked service to fetch resources. + // + // Because this class is sequenced, a non-nullptr value here (observed + // on-sequence) denotes an ongoing fetch. See the + // TryToStartNetworkedFetch() and FinishNetworkedFetch() methods. + std::unique_ptr<network::SimpleURLLoader> fetcher_; + + SEQUENCE_CHECKER(sequence_checker_); + + // Dispenses weak pointers to our |fetcher_|. This is necessary + // because |this| could be deleted while the loader is in flight + // off-sequence. + base::WeakPtrFactory<PrinterConfigCacheImpl> weak_factory_; +}; + +// static +std::unique_ptr<PrinterConfigCache> PrinterConfigCache::Create( + const base::Clock* clock, + network::mojom::URLLoaderFactory* loader_factory) { + return std::make_unique<PrinterConfigCacheImpl>(clock, loader_factory); +} + +} // namespace chromeos
diff --git a/chromeos/printing/printer_config_cache.h b/chromeos/printing/printer_config_cache.h new file mode 100644 index 0000000..6623759 --- /dev/null +++ b/chromeos/printing/printer_config_cache.h
@@ -0,0 +1,95 @@ +// 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. +// +// The PrinterConfigCache class accepts requests to fetch things from +// the Chrome OS Printing serving root. It only stores things in memory. +// +// In practice, the present class fetches either PPDs or PPD metadata. + +#ifndef CHROMEOS_PRINTING_PRINTER_CONFIG_CACHE_H_ +#define CHROMEOS_PRINTING_PRINTER_CONFIG_CACHE_H_ + +#include <memory> +#include <string> + +#include "base/containers/flat_map.h" +#include "base/containers/queue.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/sequence_checker.h" +#include "base/sequenced_task_runner.h" +#include "base/strings/string_piece.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "base/time/clock.h" +#include "base/time/time.h" +#include "chromeos/chromeos_export.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/simple_url_loader.h" + +namespace chromeos { + +// A PrinterConfigCache maps keys to values. By convention, keys are +// relative paths to files in the Chrome OS Printing serving root +// (hardcoded into this class). In practice, that means keys will either +// * start with "metadata_v3/" or +// * start with "ppds_for_metadata_v3/." +// +// This class must always be constructed on, used on, and destroyed from +// a sequenced context. +// +// TODO(crbug.com/888189): remove CHROMEOS_EXPORT and refactor all this +// into a dedicated gn component. +class CHROMEOS_EXPORT PrinterConfigCache { + public: + static std::unique_ptr<PrinterConfigCache> Create( + const base::Clock* clock, + network::mojom::URLLoaderFactory* loader_factory); + virtual ~PrinterConfigCache() = default; + + // Result of calling Fetch(). The |key| identifies how Fetch() was + // originally invoked. The |contents| and |time_of_fetch| are well- + // defined iff |succeeded| is true. + struct FetchResult { + static FetchResult Failure(const std::string& key); + + static FetchResult Success(const std::string& key, + const std::string& contents, + base::Time time_of_fetch); + + bool succeeded; + std::string key; + std::string contents; + base::Time time_of_fetch; + }; + + // Caller is responsible for providing sequencing of this type. + using FetchCallback = base::OnceCallback<void(const FetchResult&)>; + + // Queries the Chrome OS Printing serving root for |key|. Calls |cb| + // with the contents. If an entry newer than |expiration| is resident, + // calls |cb| immediately with those contents. Caller should not pass + // keys with leading slashes. + // + // Using TimeDelta implies the caller is asking for "some entry not + // older than |expiration|," e.g. "metadata_v3/index-00.json that + // was fetched within the last 30 minutes." + // + // Naturally, + // * passing the Max() TimeDelta means "perform this Fetch() with no + // limit on staleness" and + // * passing a zero TimeDelta should practically force a networked + // fetch (less esoteric timing quirks etc.). + virtual void Fetch(const std::string& key, + base::TimeDelta expiration, + FetchCallback cb) = 0; + + // Drops Entry corresponding to |key|. + virtual void Drop(const std::string& key) = 0; +}; + +} // namespace chromeos + +#endif // CHROMEOS_PRINTING_PRINTER_CONFIG_CACHE_H_
diff --git a/chromeos/printing/printer_config_cache_unittest.cc b/chromeos/printing/printer_config_cache_unittest.cc new file mode 100644 index 0000000..eabb44c --- /dev/null +++ b/chromeos/printing/printer_config_cache_unittest.cc
@@ -0,0 +1,420 @@ +// 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 "chromeos/printing/printer_config_cache.h" + +#include <vector> + +#include "base/bind.h" +#include "base/callback_forward.h" +#include "base/location.h" +#include "base/run_loop.h" +#include "base/test/simple_test_clock.h" +#include "base/test/task_environment.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/clock.h" +#include "base/time/time.h" +#include "net/http/http_status_code.h" +#include "services/network/test/test_url_loader_factory.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Maintainer's notes: +// +// 1. The use of base::Unretained throughout this suite is appropriate +// because the sequences of each test live as long as the test does. +// Real consumers probably can't do this. +// 2. The passage of time is controlled by a mock clock, so most Fetch() +// invocations not preceded by clock advancement never hit the +// "networked fetch" codepath. In such tests, the values of the +// TimeDelta argument are arbitrary and meaningless. + +namespace chromeos { +namespace { + +// Defines some resources (URLs and contents) used throughout this +// test suite. + +// Name of the "known-good" resource. +const char kKnownGoodResourceURL[] = + "https://printerconfigurations.googleusercontent.com/chromeos_printing/" + "known-good"; + +// Arbitrary content for the "known-good" resource. +const char kKnownGoodResourceContent[] = "yakisaba"; + +// Name of the "known-bad" resource. +const char kKnownBadResourceURL[] = + "https://printerconfigurations.googleusercontent.com/chromeos_printing/" + "known-bad"; + +// Defines an arbitrary time increment by which we advance the Clock. +constexpr base::TimeDelta kTestingIncrement = base::TimeDelta::FromSeconds(1LL); + +// Defines a time of fetch used to construct FetchResult instances that +// you'll use with the TimeInsensitiveFetchResultEquals matcher. +constexpr base::Time kUnusedTimeOfFetch; + +MATCHER_P(TimeInsensitiveFetchResultEquals, expected, "") { + return arg.succeeded == expected.succeeded && arg.key == expected.key && + arg.contents == expected.contents; +} + +MATCHER_P(FetchResultEquals, expected, "") { + return arg.succeeded == expected.succeeded && arg.key == expected.key && + arg.contents == expected.contents && + arg.time_of_fetch == expected.time_of_fetch; +} + +class PrinterConfigCacheTest : public ::testing::Test { + public: + PrinterConfigCacheTest() + : task_environment_(base::test::TaskEnvironment::MainThreadType::IO), + cache_(PrinterConfigCache::Create(&clock_, &loader_factory_)) {} + + // Sets up the default responses to dispense. + void SetUp() override { + // Dispenses the "known-good" resource with its content. + loader_factory_.AddResponse(kKnownGoodResourceURL, + kKnownGoodResourceContent); + + // Dispenses the "known-bad" resource with no content and an + // arbitrary HTTP error. + loader_factory_.AddResponse(kKnownBadResourceURL, "", + net::HTTP_NOT_ACCEPTABLE); + } + + // Method passed as a FetchCallback (partially bound) to + // cache_.Fetch(). Saves the |result| in the |fetched_results_|. + // Invokes the |quit_closure| to signal the enclosing RunLoop that + // this method has been called. + void CaptureFetchResult(base::RepeatingClosure quit_closure, + const PrinterConfigCache::FetchResult& result) { + fetched_results_.push_back(result); + + // The caller may elect to pass a default-constructed + // RepeatingClosure, indicating that they don't want anything run. + if (quit_closure) { + quit_closure.Run(); + } + } + + void AdvanceClock(base::TimeDelta amount = kTestingIncrement) { + clock_.Advance(amount); + } + + protected: + // Landing area used to collect Fetch()ed results. + std::vector<PrinterConfigCache::FetchResult> fetched_results_; + + // Loader factory for testing loaned to |cache_|. + network::TestURLLoaderFactory loader_factory_; + + // Environment for task schedulers. + base::test::TaskEnvironment task_environment_; + + // Controlled clock that dispenses times of Fetch(). + base::SimpleTestClock clock_; + + // Class under test. + std::unique_ptr<PrinterConfigCache> cache_; +}; + +// Tests that we can succeed in Fetch()ing anything at all. +TEST_F(PrinterConfigCacheTest, SucceedAtSingleFetch) { + base::RunLoop run_loop; + + // Fetches the "known-good" resource. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + &PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(0LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), run_loop.QuitClosure()))); + run_loop.Run(); + + ASSERT_EQ(fetched_results_.size(), 1ULL); + EXPECT_THAT( + fetched_results_.front(), + TimeInsensitiveFetchResultEquals(PrinterConfigCache::FetchResult::Success( + "known-good", "yakisaba", kUnusedTimeOfFetch))); +} + +// Tests that we fail to Fetch() the "known-bad" resource. +TEST_F(PrinterConfigCacheTest, FailAtSingleFetch) { + base::RunLoop run_loop; + + // Fetches the "known-bad" resource. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + &PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-bad", base::TimeDelta::FromSeconds(0LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), run_loop.QuitClosure()))); + run_loop.Run(); + + ASSERT_EQ(fetched_results_.size(), 1ULL); + EXPECT_THAT(fetched_results_.front(), + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Failure("known-bad"))); +} + +// Tests that we can force a networked Fetch() by demanding +// fresh content. +TEST_F(PrinterConfigCacheTest, RefreshSubsequentFetch) { + // Fetches the "known-good" resource with its stock contents. + base::RunLoop first_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(0LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + first_run_loop.QuitClosure()))); + first_run_loop.Run(); + + ASSERT_EQ(fetched_results_.size(), 1ULL); + + // To detect a networked fetch, we'll change the served content + // and check that the subsequent Fetch() recovers the new content. + loader_factory_.AddResponse(kKnownGoodResourceURL, "one Argentinian peso"); + + // We've mutated the content; now, this fetches the "known-good" + // resource with its new contents. + base::RunLoop second_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(0LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + second_run_loop.QuitClosure()))); + second_run_loop.Run(); + + ASSERT_EQ(fetched_results_.size(), 2ULL); + + EXPECT_THAT( + fetched_results_, + testing::ElementsAre( + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success("known-good", "yakisaba", + kUnusedTimeOfFetch)), + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success( + "known-good", "one Argentinian peso", kUnusedTimeOfFetch)))); +} + +// Tests that we can Fetch() locally cached contents by specifying a +// wide age limit. +TEST_F(PrinterConfigCacheTest, LocallyPerformSubsequentFetch) { + // Fetches the "known-good" resource with its stock contents. + base::RunLoop first_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(0LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + first_run_loop.QuitClosure()))); + first_run_loop.Run(); + + ASSERT_EQ(fetched_results_.size(), 1ULL); + + // As in the RefreshSubsequentFetch test, we'll change the served + // content to detect networked fetch requests made. + loader_factory_.AddResponse(kKnownGoodResourceURL, "apologize darn you"); + + // The "live" content in the serving root has changed; now, we perform + // some local fetches without hitting the network. These Fetch()es + // will return the stock content. + base::RunLoop second_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", + // Avoids hitting the network by using a long + // timeout. Bear in mind that this test controls + // the passage of time, so nonzero timeout is + // "long" here... + base::TimeDelta::FromSeconds(1LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + // Avoids quitting this RunLoop. + base::RepeatingClosure()))); + + // Performs a local Fetch() a few more times for no particular reason. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + &PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(3600LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), base::RepeatingClosure()))); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + &PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(86400LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), base::RepeatingClosure()))); + + // Performs a live Fetch(), returning the live (mutated) contents. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", + // Forces the networked fetch. + base::TimeDelta::FromSeconds(0LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + // Ends our RunLoop. + second_run_loop.QuitClosure()))); + second_run_loop.Run(); + + ASSERT_EQ(fetched_results_.size(), 5ULL); + EXPECT_THAT( + fetched_results_, + testing::ElementsAre( + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success("known-good", "yakisaba", + kUnusedTimeOfFetch)), + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success("known-good", "yakisaba", + kUnusedTimeOfFetch)), + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success("known-good", "yakisaba", + kUnusedTimeOfFetch)), + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success("known-good", "yakisaba", + kUnusedTimeOfFetch)), + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success( + "known-good", "apologize darn you", kUnusedTimeOfFetch)))); +} + +// Tests that Fetch() respects its |expiration| argument. This is a +// purely time-bound variation on the LocallyPerformSubsequentFetch +// test; the served content doesn't change between RunLoops. +TEST_F(PrinterConfigCacheTest, FetchExpirationIsRespected) { + // This Fetch() is given a useful |expiration|, but it won't matter + // here since there are no locally resident cache entries at this + // time; it'll have to be a networked fetch. + base::RunLoop first_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(32LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + first_run_loop.QuitClosure()))); + first_run_loop.Run(); + ASSERT_EQ(fetched_results_.size(), 1ULL); + const base::Time time_zero = clock_.Now(); + + // Advance clock to T+31. + AdvanceClock(base::TimeDelta::FromSeconds(31LL)); + + // This Fetch() is given the same useful |expiration|; it only matters + // in that the clock does not yet indicate that the locally resident + // cache entry has expired. + base::RunLoop second_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(32LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + second_run_loop.QuitClosure()))); + second_run_loop.Run(); + ASSERT_EQ(fetched_results_.size(), 2ULL); + // We don't capture the time right Now() because the above Fetch() + // should have replied with local contents, fetched at time_zero. + + // Advance clock to T+32. + AdvanceClock(base::TimeDelta::FromSeconds(1)); + + // This third Fetch() will be given the same |expiration| as ever. + // The two previous calls to AdvanceClock() will have moved the time + // beyond the staleness threshold, though, so this Fetch() will be + // networked. + base::RunLoop third_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", + // Entry fetched at T+0 is now stale at T+32. + base::TimeDelta::FromSeconds(32LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + third_run_loop.QuitClosure()))); + third_run_loop.Run(); + ASSERT_EQ(fetched_results_.size(), 3ULL); + const base::Time time_of_third_fetch = clock_.Now(); + + EXPECT_THAT(fetched_results_, + testing::ElementsAre( + FetchResultEquals(PrinterConfigCache::FetchResult::Success( + "known-good", "yakisaba", time_zero)), + FetchResultEquals(PrinterConfigCache::FetchResult::Success( + "known-good", "yakisaba", time_zero)), + FetchResultEquals(PrinterConfigCache::FetchResult::Success( + "known-good", "yakisaba", time_of_third_fetch)))); +} + +// Tests that we can Drop() locally cached contents. +TEST_F(PrinterConfigCacheTest, DropLocalContents) { + base::RunLoop first_run_loop; + + // Fetches the "known-good" resource with its stock contents. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(604800LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + first_run_loop.QuitClosure()))); + first_run_loop.Run(); + + // Drops that which we just fetched. This isn't immediately externally + // visible, but its effects will soon be made apparent. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&PrinterConfigCache::Drop, + base::Unretained(cache_.get()), "known-good")); + + // Mutates the contents served for the "known-good" resource. + loader_factory_.AddResponse(kKnownGoodResourceURL, "ultimate dogeza"); + + // Fetches the "known-good" resource anew with a wide timeout. + // This is where the side effect of the prior Drop() call manifests: + // the "known-good" resource is no longer cached, so not even a wide + // timeout will spare us a networked fetch. + base::RunLoop second_run_loop; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&PrinterConfigCache::Fetch, base::Unretained(cache_.get()), + "known-good", base::TimeDelta::FromSeconds(18748800LL), + base::BindOnce(&PrinterConfigCacheTest::CaptureFetchResult, + base::Unretained(this), + second_run_loop.QuitClosure()))); + second_run_loop.Run(); + + // We detect the networked fetch to by observing mutated + // contents. + ASSERT_EQ(fetched_results_.size(), 2ULL); + EXPECT_THAT( + fetched_results_, + testing::ElementsAre( + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success("known-good", "yakisaba", + kUnusedTimeOfFetch)), + TimeInsensitiveFetchResultEquals( + PrinterConfigCache::FetchResult::Success( + "known-good", "ultimate dogeza", kUnusedTimeOfFetch)))); +} + +} // namespace +} // namespace chromeos
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/animation/Interpolators.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/animation/Interpolators.java index 059785a..6ee034cd 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/animation/Interpolators.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/animation/Interpolators.java
@@ -4,13 +4,14 @@ package org.chromium.components.browser_ui.widget.animation; -import android.support.v4.view.animation.FastOutLinearInInterpolator; -import android.support.v4.view.animation.FastOutSlowInInterpolator; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; +import androidx.interpolator.view.animation.FastOutLinearInInterpolator; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; +import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; + /** Reference to one of each standard interpolator to avoid allocations. */ public class Interpolators { public static final AccelerateInterpolator ACCELERATE_INTERPOLATOR =
diff --git a/components/crash/core/common/crash_key.h b/components/crash/core/common/crash_key.h index 700ad3c..9d193ea 100644 --- a/components/crash/core/common/crash_key.h +++ b/components/crash/core/common/crash_key.h
@@ -19,6 +19,9 @@ // Annotation interface. Because not all platforms use Crashpad yet, a // source-compatible interface is provided on top of the older Breakpad // storage mechanism. +// +// See https://cs.chromium.org/chromium/src/docs/debugging_with_crash_keys.md +// for more information on using this. #if BUILDFLAG(USE_CRASHPAD_ANNOTATION) || BUILDFLAG(USE_COMBINED_ANNOTATIONS) #include "third_party/crashpad/crashpad/client/annotation.h" // nogncheck #endif
diff --git a/components/download/internal/common/BUILD.gn b/components/download/internal/common/BUILD.gn index 4f322c44..eba9ab1 100644 --- a/components/download/internal/common/BUILD.gn +++ b/components/download/internal/common/BUILD.gn
@@ -101,11 +101,15 @@ if (is_android) { android_library("internal_java") { - sources = [ "android/java/src/org/chromium/components/download/DownloadCollectionBridge.java" ] + sources = [ + "android/java/src/org/chromium/components/download/DownloadCollectionBridge.java", + "android/java/src/org/chromium/components/download/DownloadDelegate.java", + ] deps = [ "//base:base_java", "//base:jni_java", + "//third_party/android_provider:android_provider_java", ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] }
diff --git a/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java b/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java index 11bfaeb..a81973b 100644 --- a/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java +++ b/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
@@ -4,26 +4,59 @@ package org.chromium.components.download; +import android.annotation.TargetApi; import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.database.Cursor; import android.net.Uri; +import android.os.Build; +import android.os.FileUtils; import android.os.ParcelFileDescriptor; +import android.provider.BaseColumns; +import android.provider.MediaStore; +import android.provider.MediaStore.Downloads; +import android.provider.MediaStore.MediaColumns; +import android.text.TextUtils; +import android.text.format.DateUtils; +import androidx.annotation.NonNull; + +import org.chromium.base.BuildInfo; import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; +import org.chromium.third_party.android.provider.MediaStoreUtils; +import org.chromium.third_party.android.provider.MediaStoreUtils.PendingParams; +import org.chromium.third_party.android.provider.MediaStoreUtils.PendingSession; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Locale; /** * Helper class for publishing download files to the public download collection. */ @JNINamespace("download") public class DownloadCollectionBridge { - // Singleton instance that allows embedders to replace their implementation. - private static DownloadCollectionBridge sDownloadCollectionBridge; private static final String TAG = "DownloadCollection"; - // Guards access to sDownloadCollectionBridge. - private static final Object sLock = new Object(); + + // File name pattern to be used when media store has too many duplicates. This matches + // that of download_path_reservation_tracker.cc. + private static final String FILE_NAME_PATTERN = "yyyy-MM-dd'T'HHmmss.SSS"; + + private static final List<String> COMMON_DOUBLE_EXTENSIONS = + new ArrayList<String>(Arrays.asList("tar.gz", "tar.z", "tar.bz2", "tar.bz", "user.js")); + + private static DownloadDelegate sDownloadDelegate = new DownloadDelegate(); /** * Class representing the Uri and display name pair for downloads. @@ -49,127 +82,13 @@ } /** - * Return getDownloadCollectionBridge singleton. + * Sets the DownloadDelegate to be used for utility methods. + * TODO(qinmin): remove this method once we moved all the utility methods into + * components/. + * @param downloadDelegate The new delegate to be used. */ - public static DownloadCollectionBridge getDownloadCollectionBridge() { - synchronized (sLock) { - if (sDownloadCollectionBridge == null) { - sDownloadCollectionBridge = new DownloadCollectionBridge(); - } - } - return sDownloadCollectionBridge; - } - - /** - * Sets the singlton object to use later. - */ - public static void setDownloadCollectionBridge(DownloadCollectionBridge bridge) { - synchronized (sLock) { - sDownloadCollectionBridge = bridge; - } - } - - /** - * Returns whether a download needs to be published. - * @param filePath File path of the download. - * @return True if the download needs to be published, or false otherwise. - */ - public boolean needToPublishDownload(final String filePath) { - return false; - } - - /** - * Creates a pending session for download to be written into. - * @param fileName Name of the file. - * @param mimeType Mime type of the file. - * @param originalUrl Originating URL of the download. - * @param referrer Referrer of the download. - * @return Uri created for the pending session. - */ - protected Uri createPendingSession(final String fileName, final String mimeType, - final String originalUrl, final String referrer) { - return null; - } - - /** - * Copy file content from a source file to the pending Uri. - * @param sourcePath File content to be copied from. - * @param pendingUri Destination Uri to be copied to. - * @return true on success, or false otherwise. - */ - protected boolean copyFileToPendingUri(final String sourcePath, final String pendingUri) { - return false; - } - - /** - * Abandon the the intermediate Uri. - * @param pendingUri Intermediate Uri that is going to be deleted. - */ - protected void abandonPendingUri(final String pendingUri) {} - - /** - * Publish a completed download to public repository. - * @param pendingUri Pending uri to publish. - * @return Uri of the published file. - */ - protected Uri publishCompletedDownload(final String pendingUri) { - return null; - } - - /** - * Gets the content URI of the download that has the given file name. - * @param pendingUri name of the file. - * @return Uri of the download with the given display name. - */ - public Uri getDownloadUriForFileName(final String fileName) { - return null; - } - - /** - * Renames a download Uri with a display name. - * @param downloadUri Uri of the download. - * @param displayName New display name for the download. - * @return whether rename was successful. - */ - protected boolean rename(final String downloadUri, final String displayName) { - return false; - } - - /** - * @return Whether download display names needs to be retrieved. - */ - protected boolean needToGetDisplayNames() { - return false; - } - - /** - * Gets the display names for all downloads - * @return an array of download Uri and display name pair. - */ - protected DisplayNameInfo[] getDisplayNames() { - return null; - } - - /** - * @return whether download collection is supported. - */ - protected boolean isDownloadCollectionSupported() { - return false; - } - - /** - * Refreshes the expiration date so the unpublished download won't get abandoned. - * @param intermediateUri The intermediate Uri that is not yet published. - */ - protected void refreshExpirationDate(final String intermediateUri) {} - - /** - * Gets the display name for a download. - * @param downloadUri Uri of the download. - * @return the display name of the download. - */ - protected String getDisplayNameForUri(final String downloadUri) { - return null; + public static void setDownloadDelegate(DownloadDelegate downloadDelegate) { + sDownloadDelegate = downloadDelegate; } /** @@ -183,8 +102,20 @@ @CalledByNative public static String createIntermediateUriForPublish(final String fileName, final String mimeType, final String originalUrl, final String referrer) { - Uri uri = getDownloadCollectionBridge().createPendingSession( - fileName, mimeType, originalUrl, referrer); + Uri uri = createPendingSessionInternal(fileName, mimeType, originalUrl, referrer); + if (uri != null) return uri.toString(); + + // If there are too many duplicates on the same file name, createPendingSessionInternal() + // will return null. Generate a new file name with timestamp. + SimpleDateFormat sdf = new SimpleDateFormat(FILE_NAME_PATTERN, Locale.getDefault()); + // Remove the extension first. + String baseName = getBaseName(fileName); + String extension = fileName.substring(baseName.length()); + StringBuilder sb = new StringBuilder(baseName); + sb.append(" - "); + sb.append(sdf.format(new Date())); + sb.append(extension); + uri = createPendingSessionInternal(sb.toString(), mimeType, originalUrl, referrer); return uri == null ? null : uri.toString(); } @@ -194,8 +125,13 @@ * @return True if the download needs to be published, or false otherwise. */ @CalledByNative - private static boolean shouldPublishDownload(final String filePath) { - return getDownloadCollectionBridge().needToPublishDownload(filePath); + public static boolean shouldPublishDownload(final String filePath) { + if (isAtLeastQ()) { + if (filePath == null) return false; + // Only need to publish downloads that are on primary storage. + return !sDownloadDelegate.isDownloadOnSDCard(filePath); + } + return false; } /** @@ -205,9 +141,21 @@ * @return True on success, or false otherwise. */ @CalledByNative + @TargetApi(29) public static boolean copyFileToIntermediateUri( final String sourcePath, final String destinationUri) { - return getDownloadCollectionBridge().copyFileToPendingUri(sourcePath, destinationUri); + try { + PendingSession session = openPendingUri(destinationUri); + OutputStream out = session.openOutputStream(); + InputStream in = new FileInputStream(sourcePath); + FileUtils.copy(in, out); + in.close(); + out.close(); + return true; + } catch (Exception e) { + Log.e(TAG, "Unable to copy content to pending Uri.", e); + } + return false; } /** @@ -216,7 +164,8 @@ */ @CalledByNative public static void deleteIntermediateUri(final String uri) { - getDownloadCollectionBridge().abandonPendingUri(uri); + PendingSession session = openPendingUri(uri); + session.abandon(); } /** @@ -226,8 +175,34 @@ */ @CalledByNative public static String publishDownload(final String intermediateUri) { - Uri uri = getDownloadCollectionBridge().publishCompletedDownload(intermediateUri); - return uri == null ? null : uri.toString(); + // Android Q's MediaStore.Downloads has an issue that the custom mime type which is not + // supported by MimeTypeMap is overridden to "application/octet-stream" when publishing. + // To deal with this issue we set the mime type again after publishing. + // See crbug.com/1010829 for more details. + ContentResolver resolver = ContextUtils.getApplicationContext().getContentResolver(); + String mimeType = null; + Cursor cursor = null; + try { + cursor = resolver.query(Uri.parse(intermediateUri), + new String[] {MediaColumns.MIME_TYPE}, null, null, null); + if (cursor != null && cursor.getCount() != 0 && cursor.moveToNext()) { + mimeType = cursor.getString(cursor.getColumnIndex(MediaColumns.MIME_TYPE)); + } + } catch (Exception e) { + Log.e(TAG, "Unable to get mimeType.", e); + } finally { + if (cursor != null) cursor.close(); + } + + PendingSession session = openPendingUri(intermediateUri); + Uri publishedUri = session.publish(); + + if (!TextUtils.isEmpty(mimeType)) { + final ContentValues updateValues = new ContentValues(); + updateValues.put(MediaColumns.MIME_TYPE, mimeType); + resolver.update(publishedUri, updateValues, null, null); + } + return publishedUri.toString(); } /** @@ -241,7 +216,10 @@ ContentResolver resolver = ContextUtils.getApplicationContext().getContentResolver(); ParcelFileDescriptor pfd = resolver.openFileDescriptor(Uri.parse(intermediateUri), "rw"); - getDownloadCollectionBridge().refreshExpirationDate(intermediateUri); + ContentValues updateValues = new ContentValues(); + updateValues.put("date_expires", getNewExpirationTime()); + ContextUtils.getApplicationContext().getContentResolver().update( + Uri.parse(intermediateUri), updateValues, null, null); return pfd.detachFd(); } catch (Exception e) { Log.e(TAG, "Cannot open intermediate Uri.", e); @@ -250,12 +228,13 @@ } /** + * Check if a download with the same name already exists. + * @param fileName The name of the file to check. * @return whether a download with the file name exists. */ @CalledByNative private static boolean fileNameExists(final String fileName) { - Uri uri = getDownloadCollectionBridge().getDownloadUriForFileName(fileName); - return uri != null; + return getDownloadUriForFileName(fileName) != null; } /** @@ -266,7 +245,12 @@ */ @CalledByNative private static boolean renameDownloadUri(final String downloadUri, final String displayName) { - return getDownloadCollectionBridge().rename(downloadUri, displayName); + final ContentValues updateValues = new ContentValues(); + Uri uri = Uri.parse(downloadUri); + updateValues.put(MediaColumns.DISPLAY_NAME, displayName); + return ContextUtils.getApplicationContext().getContentResolver().update( + uri, updateValues, null, null) + == 1; } /** @@ -274,7 +258,7 @@ */ @CalledByNative private static boolean needToRetrieveDisplayNames() { - return getDownloadCollectionBridge().needToGetDisplayNames(); + return isAtLeastQ(); } /** @@ -282,15 +266,63 @@ * @return an array of download Uri and display name pair. */ @CalledByNative + @TargetApi(29) private static DisplayNameInfo[] getDisplayNamesForDownloads() { - return getDownloadCollectionBridge().getDisplayNames(); + ContentResolver resolver = ContextUtils.getApplicationContext().getContentResolver(); + Cursor cursor = null; + try { + Uri uri = Downloads.EXTERNAL_CONTENT_URI; + cursor = resolver.query(MediaStore.setIncludePending(uri), + new String[] {BaseColumns._ID, MediaColumns.DISPLAY_NAME}, null, null, null); + if (cursor == null || cursor.getCount() == 0) return null; + List<DisplayNameInfo> infos = new ArrayList<DisplayNameInfo>(); + while (cursor.moveToNext()) { + String displayName = + cursor.getString(cursor.getColumnIndex(MediaColumns.DISPLAY_NAME)); + Uri downloadUri = ContentUris.withAppendedId( + uri, cursor.getInt(cursor.getColumnIndex(BaseColumns._ID))); + infos.add(new DisplayNameInfo(downloadUri.toString(), displayName)); + } + return infos.toArray(new DisplayNameInfo[0]); + } catch (Exception e) { + Log.e(TAG, "Unable to get display names for downloads.", e); + } finally { + if (cursor != null) cursor.close(); + } + return null; } /** * @return whether download collection is supported. */ public static boolean supportsDownloadCollection() { - return getDownloadCollectionBridge().isDownloadCollectionSupported(); + return isAtLeastQ(); + } + + /** + * Gets the content URI of the download that has the given file name. + * @param pendingUri name of the file. + * @return Uri of the download with the given display name. + */ + @TargetApi(29) + public static Uri getDownloadUriForFileName(String fileName) { + Cursor cursor = null; + try { + Uri uri = Downloads.EXTERNAL_CONTENT_URI; + cursor = ContextUtils.getApplicationContext().getContentResolver().query( + MediaStore.setIncludePending(uri), new String[] {BaseColumns._ID}, + "_display_name LIKE ?1", new String[] {fileName}, null); + if (cursor == null) return null; + if (cursor.moveToNext()) { + return ContentUris.withAppendedId( + uri, cursor.getInt(cursor.getColumnIndex(BaseColumns._ID))); + } + } catch (Exception e) { + Log.e(TAG, "Unable to check file name existence.", e); + } finally { + if (cursor != null) cursor.close(); + } + return null; } /** @@ -300,6 +332,93 @@ return DownloadCollectionBridgeJni.get().getExpirationDurationInDays(); } + private static boolean isAtLeastQ() { + return BuildInfo.isAtLeastQ() || Build.VERSION.SDK_INT >= 29; + } + + /** + * Helper method to create a pending session for download to be written into. + * @param fileName Name of the file. + * @param mimeType Mime type of the file. + * @param originalUrl Originating URL of the download. + * @param referrer Referrer of the download. + * @return Uri created for the pending session, or null if failed. + */ + private static Uri createPendingSessionInternal(final String fileName, final String mimeType, + final String originalUrl, final String referrer) { + PendingParams pendingParams = + createPendingParams(fileName, mimeType, originalUrl, referrer); + pendingParams.setExpirationTime(getNewExpirationTime()); + try { + return MediaStoreUtils.createPending( + ContextUtils.getApplicationContext(), pendingParams); + } catch (Exception e) { + return null; + } + } + + /** + * Helper method to create PendingParams needed for PendingSession creation. + * @param fileName Name of the file. + * @param mimeType Mime type of the file. + * @param originalUrl Originating URL of the download. + * @param referrer Referrer of the download. + * @return PendingParams needed for creating the PendingSession. + */ + @TargetApi(29) + private static PendingParams createPendingParams(final String fileName, final String mimeType, + final String originalUrl, final String referrer) { + Uri downloadsUri = Downloads.EXTERNAL_CONTENT_URI; + String newMimeType = + sDownloadDelegate.remapGenericMimeType(mimeType, originalUrl, fileName); + PendingParams pendingParams = new PendingParams(downloadsUri, fileName, newMimeType); + Uri originalUri = sDownloadDelegate.parseOriginalUrl(originalUrl); + Uri referrerUri = TextUtils.isEmpty(referrer) ? null : Uri.parse(referrer); + pendingParams.setDownloadUri(originalUri); + pendingParams.setRefererUri(referrerUri); + return pendingParams; + } + + /** + * Gets the base name, without extension, from a file name. + * TODO(qinmin): move this into a common utility class. + * @param fileName Name of the file. + * @return Base name of the file. + */ + private static String getBaseName(final String fileName) { + for (String extension : COMMON_DOUBLE_EXTENSIONS) { + if (fileName.endsWith(extension)) { + String name = fileName.substring(0, fileName.length() - extension.length()); + // remove the "." at the end. + if (name.endsWith(".")) { + return name.substring(0, name.length() - 1); + } + } + } + int index = fileName.lastIndexOf('.'); + if (index == -1) { + return fileName; + } else { + return fileName.substring(0, index); + } + } + + private static @NonNull PendingSession openPendingUri(final String pendingUri) { + return MediaStoreUtils.openPending( + ContextUtils.getApplicationContext(), Uri.parse(pendingUri)); + } + + /** + * Helper method to generate a new expiration epoch time in seconds. + * @return Epoch time value in seconds for the download to expire. + */ + private static long getNewExpirationTime() { + return (System.currentTimeMillis() + + DownloadCollectionBridge.getExpirationDurationInDays() + * DateUtils.DAY_IN_MILLIS) + / 1000; + } + /** * Gets the display name for a download. * @param downloadUri Uri of the download. @@ -307,7 +426,21 @@ */ @CalledByNative private static String getDisplayName(final String downloadUri) { - return getDownloadCollectionBridge().getDisplayNameForUri(downloadUri); + ContentResolver resolver = ContextUtils.getApplicationContext().getContentResolver(); + Cursor cursor = null; + try { + cursor = resolver.query(Uri.parse(downloadUri), + new String[] {MediaColumns.DISPLAY_NAME}, null, null, null); + if (cursor == null || cursor.getCount() == 0) return null; + if (cursor.moveToNext()) { + return cursor.getString(cursor.getColumnIndex(MediaColumns.DISPLAY_NAME)); + } + } catch (Exception e) { + Log.e(TAG, "Unable to get display name for download.", e); + } finally { + if (cursor != null) cursor.close(); + } + return null; } @NativeMethods
diff --git a/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadDelegate.java b/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadDelegate.java new file mode 100644 index 0000000..00a38da --- /dev/null +++ b/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadDelegate.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.components.download; + +import android.net.Uri; + +/** + * Helper class for providering some helper method needed by DownloadCollectionBridge. + */ +public class DownloadDelegate { + public DownloadDelegate() {} + + /** + * If the given MIME type is null, or one of the "generic" types (text/plain + * or application/octet-stream) map it to a type that Android can deal with. + * If the given type is not generic, return it unchanged. + * + * @param mimeType MIME type provided by the server. + * @param url URL of the data being loaded. + * @param filename file name obtained from content disposition header + * @return The MIME type that should be used for this data. + */ + public String remapGenericMimeType(String mimeType, String url, String filename) { + return mimeType; + } + + /** + * Parses an originating URL string and returns a valid Uri that can be inserted into + * DownloadManager. The returned Uri has to be null or non-empty http(s) scheme. + * @param originalUrl String representation of the originating URL. + * @return A valid Uri that can be accepted by DownloadManager. + */ + public Uri parseOriginalUrl(String originalUrl) { + return Uri.parse(originalUrl); + } + + /** + * Returns whether the downloaded file path is on an external SD card. + * @param filePath The download file path. + * @return Whether download is on external sd card. + */ + public boolean isDownloadOnSDCard(String filePath) { + return false; + } +}
diff --git a/components/image_fetcher/core/image_data_fetcher.cc b/components/image_fetcher/core/image_data_fetcher.cc index 00e8951..01f4be8 100644 --- a/components/image_fetcher/core/image_data_fetcher.cc +++ b/components/image_fetcher/core/image_data_fetcher.cc
@@ -114,10 +114,7 @@ DVLOG(0) << "Failed to parse data url"; } - // Post a task to maintain our guarantee that the call won't be called - // synchronously. - base::PostTask(FROM_HERE, BindOnce(std::move(callback), std::move(data), - RequestMetadata())); + std::move(callback).Run(std::move(data), RequestMetadata()); return; }
diff --git a/components/image_fetcher/core/image_data_fetcher.h b/components/image_fetcher/core/image_data_fetcher.h index 7f91ef77..82781f0 100644 --- a/components/image_fetcher/core/image_data_fetcher.h +++ b/components/image_fetcher/core/image_data_fetcher.h
@@ -42,7 +42,7 @@ // Fetches the raw image bytes from the given |image_url| and calls the given // |callback|. The callback is run even if fetching the URL fails. In case - // of an error an empty string is passed to the callback. Won't return + // of an error an empty string is passed to the callback. May return // synchronously. void FetchImageData(const GURL& image_url, ImageDataFetcherCallback callback,
diff --git a/components/image_fetcher/core/image_data_fetcher_unittest.cc b/components/image_fetcher/core/image_data_fetcher_unittest.cc index b5806c50..6b65801 100644 --- a/components/image_fetcher/core/image_data_fetcher_unittest.cc +++ b/components/image_fetcher/core/image_data_fetcher_unittest.cc
@@ -60,7 +60,7 @@ void(const std::string&, const RequestMetadata&)); protected: - base::test::TaskEnvironment task_environment_; + base::test::SingleThreadTaskEnvironment task_environment_; base::HistogramTester histogram_tester_; network::TestURLLoaderFactory test_url_loader_factory_; @@ -115,17 +115,16 @@ "wn4GBgYGJAQoAHhgCAh6X4CYAAAAASUVORK5CYII="; std::string data_url = "data:image/png;base64," + data; + RequestMetadata expected_metadata; + std::string expected; + base::Base64Decode(data, &expected); + EXPECT_CALL(*this, OnImageDataFetched(expected, expected_metadata)); + image_data_fetcher_.FetchImageData( GURL(data_url), base::BindOnce(&ImageDataFetcherTest::OnImageDataFetched, base::Unretained(this)), ImageFetcherParams(TRAFFIC_ANNOTATION_FOR_TESTS, kTestUmaClientName)); - - RequestMetadata expected_metadata; - std::string expected; - base::Base64Decode(data, &expected); - EXPECT_CALL(*this, OnImageDataFetched(expected, expected_metadata)); - base::RunLoop().RunUntilIdle(); } TEST_F(ImageDataFetcherTest, FetchImageDataTrafficAnnotationOnly) {
diff --git a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc index 636d2f6..7e537bc1 100644 --- a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.cc
@@ -89,10 +89,6 @@ "InitiatingProcess"; const char kHistogramFirstMeaningfulPaint[] = "PageLoad.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"; -const char kHistogramLargestImagePaint[] = - "PageLoad.Experimental.PaintTiming.NavigationToLargestImagePaint"; -const char kHistogramLargestTextPaint[] = - "PageLoad.Experimental.PaintTiming.NavigationToLargestTextPaint"; const char kHistogramLargestContentfulPaint[] = "PageLoad.PaintTiming.NavigationToLargestContentfulPaint"; const char kHistogramLargestContentfulPaintContentType[] = @@ -719,26 +715,6 @@ } const page_load_metrics::ContentfulPaintTimingInfo& - main_frame_largest_image_paint = - largest_contentful_paint_handler_.MainFrameLargestImagePaint(); - if (main_frame_largest_image_paint.ContainsValidTime() && - WasStartedInForegroundOptionalEventInForeground( - main_frame_largest_image_paint.Time(), GetDelegate())) { - PAGE_LOAD_HISTOGRAM(internal::kHistogramLargestImagePaint, - main_frame_largest_image_paint.Time().value()); - } - - const page_load_metrics::ContentfulPaintTimingInfo& - main_frame_largest_text_paint = - largest_contentful_paint_handler_.MainFrameLargestTextPaint(); - if (main_frame_largest_text_paint.ContainsValidTime() && - WasStartedInForegroundOptionalEventInForeground( - main_frame_largest_text_paint.Time(), GetDelegate())) { - PAGE_LOAD_HISTOGRAM(internal::kHistogramLargestTextPaint, - main_frame_largest_text_paint.Time().value()); - } - - const page_load_metrics::ContentfulPaintTimingInfo& main_frame_largest_contentful_paint = largest_contentful_paint_handler_.MainFrameLargestContentfulPaint(); if (main_frame_largest_contentful_paint.ContainsValidTime() &&
diff --git a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h index 3af7079..7f53f40 100644 --- a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h +++ b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer.h
@@ -28,8 +28,6 @@ extern const char kHistogramLoad[]; extern const char kHistogramFirstContentfulPaint[]; extern const char kHistogramFirstMeaningfulPaint[]; -extern const char kHistogramLargestImagePaint[]; -extern const char kHistogramLargestTextPaint[]; extern const char kHistogramLargestContentfulPaint[]; extern const char kHistogramLargestContentfulPaintContentType[]; extern const char kHistogramLargestContentfulPaintMainFrame[];
diff --git a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc index 5f99ae32..b6b963e 100644 --- a/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc +++ b/components/page_load_metrics/browser/observers/core_page_load_metrics_observer_unittest.cc
@@ -626,26 +626,6 @@ internal::FIRST_MEANINGFUL_PAINT_RECORDED, 1); } -TEST_F(CorePageLoadMetricsObserverTest, LargestImagePaint) { - page_load_metrics::mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - timing.navigation_start = base::Time::FromDoubleT(1); - // Pick a value that lines up with a histogram bucket. - timing.paint_timing->largest_image_paint = - base::TimeDelta::FromMilliseconds(4780); - timing.paint_timing->largest_image_paint_size = 10u; - PopulateRequiredTimingFields(&timing); - - NavigateAndCommit(GURL(kDefaultTestUrl)); - tester()->SimulateTimingUpdate(timing); - // Navigate again to force histogram recording. - NavigateAndCommit(GURL(kDefaultTestUrl2)); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - internal::kHistogramLargestImagePaint), - testing::ElementsAre(base::Bucket(4780, 1))); -} - TEST_F(CorePageLoadMetricsObserverTest, LargestImageLoading) { page_load_metrics::mojom::PageLoadTiming timing; page_load_metrics::InitPageLoadTimingForTest(&timing); @@ -665,15 +645,9 @@ // Navigate again to force histogram recording. NavigateAndCommit(GURL(kDefaultTestUrl2)); - tester()->histogram_tester().ExpectTotalCount( - internal::kHistogramLargestImagePaint, 0); // The image was larger so LCP should NOT be reported. tester()->histogram_tester().ExpectTotalCount( internal::kHistogramLargestContentfulPaint, 0); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - internal::kHistogramLargestTextPaint), - testing::ElementsAre(base::Bucket(4780, 1))); } TEST_F(CorePageLoadMetricsObserverTest, LargestImageLoadingSmallerThanText) { @@ -695,12 +669,6 @@ // Navigate again to force histogram recording. NavigateAndCommit(GURL(kDefaultTestUrl2)); - tester()->histogram_tester().ExpectTotalCount( - internal::kHistogramLargestImagePaint, 0); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - internal::kHistogramLargestTextPaint), - testing::ElementsAre(base::Bucket(4780, 1))); EXPECT_THAT(tester()->histogram_tester().GetAllSamples( internal::kHistogramLargestContentfulPaint), testing::ElementsAre(base::Bucket(4780, 1))); @@ -1092,95 +1060,6 @@ 1))); } -TEST_F(CorePageLoadMetricsObserverTest, - LargestImagePaint_DiscardBackgroundResult) { - page_load_metrics::mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - PopulateRequiredTimingFields(&timing); - - NavigateAndCommit(GURL(kDefaultTestUrl)); - web_contents()->WasHidden(); - // This event happens after first background, so it will be discarded. - timing.paint_timing->largest_image_paint = base::Time::Now() - base::Time(); - tester()->SimulateTimingUpdate(timing); - // Navigate again to force histogram recording. - NavigateAndCommit(GURL(kDefaultTestUrl2)); - - tester()->histogram_tester().ExpectTotalCount( - internal::kHistogramLargestImagePaint, 0); -} - -TEST_F(CorePageLoadMetricsObserverTest, LargestImagePaint_ReportLastCandidate) { - page_load_metrics::mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - - NavigateAndCommit(GURL(kDefaultTestUrl)); - timing.navigation_start = base::Time::FromDoubleT(1); - - timing.paint_timing->largest_image_paint = - base::TimeDelta::FromMilliseconds(1000); - timing.paint_timing->largest_image_paint_size = 10u; - PopulateRequiredTimingFields(&timing); - tester()->SimulateTimingUpdate(timing); - - timing.paint_timing->largest_image_paint = - base::TimeDelta::FromMilliseconds(4780); - timing.paint_timing->largest_image_paint_size = 5u; - PopulateRequiredTimingFields(&timing); - tester()->SimulateTimingUpdate(timing); - // Navigate again to force histogram recording. - NavigateAndCommit(GURL(kDefaultTestUrl2)); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - internal::kHistogramLargestImagePaint), - testing::ElementsAre(base::Bucket(4780, 1))); -} - -TEST_F(CorePageLoadMetricsObserverTest, ReportLastNullCandidate) { - page_load_metrics::mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - - NavigateAndCommit(GURL(kDefaultTestUrl)); - timing.navigation_start = base::Time::FromDoubleT(1); - - timing.paint_timing->largest_image_paint = - base::TimeDelta::FromMilliseconds(1000); - timing.paint_timing->largest_image_paint_size = 10u; - - PopulateRequiredTimingFields(&timing); - tester()->SimulateTimingUpdate(timing); - - timing.paint_timing->largest_image_paint = base::Optional<base::TimeDelta>(); - timing.paint_timing->largest_image_paint_size = 0; - PopulateRequiredTimingFields(&timing); - tester()->SimulateTimingUpdate(timing); - // Navigate again to force histogram recording. - NavigateAndCommit(GURL(kDefaultTestUrl2)); - - tester()->histogram_tester().ExpectTotalCount( - internal::kHistogramLargestImagePaint, 0); -} - -TEST_F(CorePageLoadMetricsObserverTest, LargestTextPaint) { - page_load_metrics::mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - timing.navigation_start = base::Time::FromDoubleT(1); - // Pick a value that lines up with a histogram bucket. - timing.paint_timing->largest_text_paint = - base::TimeDelta::FromMilliseconds(4780); - timing.paint_timing->largest_text_paint_size = 10u; - PopulateRequiredTimingFields(&timing); - - NavigateAndCommit(GURL(kDefaultTestUrl)); - tester()->SimulateTimingUpdate(timing); - // Navigate again to force histogram recording. - NavigateAndCommit(GURL(kDefaultTestUrl2)); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - internal::kHistogramLargestTextPaint), - testing::ElementsAre(base::Bucket(4780, 1))); -} - TEST_F(CorePageLoadMetricsObserverTest, LargestContentfulPaint_NoTextOrImage) { page_load_metrics::mojom::PageLoadTiming timing; page_load_metrics::InitPageLoadTimingForTest(&timing);
diff --git a/components/page_load_metrics/browser/observers/largest_contentful_paint_handler.h b/components/page_load_metrics/browser/observers/largest_contentful_paint_handler.h index e2912b2..9a0831a0 100644 --- a/components/page_load_metrics/browser/observers/largest_contentful_paint_handler.h +++ b/components/page_load_metrics/browser/observers/largest_contentful_paint_handler.h
@@ -93,12 +93,6 @@ const ContentfulPaintTimingInfo& SubframesLargestContentfulPaint() { return subframe_contentful_paint_.MergeTextAndImageTiming(); } - const ContentfulPaintTimingInfo& MainFrameLargestImagePaint() { - return main_frame_contentful_paint_.Image(); - } - const ContentfulPaintTimingInfo& MainFrameLargestTextPaint() { - return main_frame_contentful_paint_.Text(); - } // We merge the candidates from main frame and subframe to get the largest // candidate across all frames.
diff --git a/components/safe_browsing/core/BUILD.gn b/components/safe_browsing/core/BUILD.gn index 86d0bb9..9ef255ed 100644 --- a/components/safe_browsing/core/BUILD.gn +++ b/components/safe_browsing/core/BUILD.gn
@@ -76,6 +76,7 @@ "//base", "//components/content_settings/core/browser", "//components/history/core/browser", + "//components/keyed_service/core:core", "//components/password_manager/core/browser:browser", "//components/safe_browsing/core/common:thread_utils", "//components/safe_browsing/core/db:v4_protocol_manager_util",
diff --git a/components/safe_browsing/core/verdict_cache_manager.cc b/components/safe_browsing/core/verdict_cache_manager.cc index 6ef30d1..64694b3 100644 --- a/components/safe_browsing/core/verdict_cache_manager.cc +++ b/components/safe_browsing/core/verdict_cache_manager.cc
@@ -366,12 +366,14 @@ history_service_observer_.Add(history_service); } -VerdictCacheManager::~VerdictCacheManager() { +void VerdictCacheManager::Shutdown() { CleanUpExpiredVerdicts(); history_service_observer_.RemoveAll(); weak_factory_.InvalidateWeakPtrs(); } +VerdictCacheManager::~VerdictCacheManager() {} + void VerdictCacheManager::CachePhishGuardVerdict( LoginReputationClientRequest::TriggerType trigger_type, ReusedPasswordAccountType password_type,
diff --git a/components/safe_browsing/core/verdict_cache_manager.h b/components/safe_browsing/core/verdict_cache_manager.h index 37464c0..915b6577 100644 --- a/components/safe_browsing/core/verdict_cache_manager.h +++ b/components/safe_browsing/core/verdict_cache_manager.h
@@ -14,6 +14,7 @@ #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" +#include "components/keyed_service/core/keyed_service.h" #include "components/safe_browsing/core/proto/csd.pb.h" #include "components/safe_browsing/core/proto/realtimeapi.pb.h" #include "url/gurl.h" @@ -26,7 +27,8 @@ LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordAccountType; // Structure: http://screen/YaNfDRYrcnk.png. -class VerdictCacheManager : public history::HistoryServiceObserver { +class VerdictCacheManager : public history::HistoryServiceObserver, + public KeyedService { public: explicit VerdictCacheManager( history::HistoryService* history_service, @@ -42,6 +44,10 @@ return weak_factory_.GetWeakPtr(); } + // KeyedService: + // Called before the actual deletion of the object. + void Shutdown() override; + // Stores |verdict| in |content_settings_| based on its |trigger_type|, |url|, // reused |password_type|, |verdict| and |receive_time|. void CachePhishGuardVerdict(
diff --git a/components/services/storage/public/mojom/service_worker_database.mojom b/components/services/storage/public/mojom/service_worker_database.mojom index 5191a12f..26ce471a 100644 --- a/components/services/storage/public/mojom/service_worker_database.mojom +++ b/components/services/storage/public/mojom/service_worker_database.mojom
@@ -55,8 +55,7 @@ // Not populated until the registration is stored into database. int64 resources_total_size_bytes = 0; - network.mojom.CrossOriginEmbedderPolicyValue cross_origin_embedder_policy = - network.mojom.CrossOriginEmbedderPolicyValue.kNone; + network.mojom.CrossOriginEmbedderPolicy cross_origin_embedder_policy; }; // Represents a service worker script data which is stored in database.
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index bf6a447..cd3ea3c4 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -15,14 +15,8 @@ namespace features { -// Use Skia's readback API instead of GLRendererCopier. -#if defined(OS_WIN) || defined(OS_LINUX) const base::Feature kUseSkiaForGLReadback{"UseSkiaForGLReadback", base::FEATURE_ENABLED_BY_DEFAULT}; -#else -const base::Feature kUseSkiaForGLReadback{"UseSkiaForGLReadback", - base::FEATURE_DISABLED_BY_DEFAULT}; -#endif // Use the SkiaRenderer. #if defined(OS_LINUX) && !(defined(OS_CHROMEOS) || BUILDFLAG(IS_CHROMECAST))
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.cc b/content/browser/devtools/service_worker_devtools_agent_host.cc index 1901d466..9f3b9a4 100644 --- a/content/browser/devtools/service_worker_devtools_agent_host.cc +++ b/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -205,15 +205,13 @@ return; } const url::Origin origin = url::Origin::Create(url_); - // TODO(https://crbug.com/1039613): Get the COEP value for the service worker + // TODO(https://crbug.com/1039613): Get the COEP for the service worker // and pass it to each factory bundle. auto script_bundle = EmbeddedWorkerInstance::CreateFactoryBundleOnUI( - rph, worker_route_id_, origin, - network::mojom::CrossOriginEmbedderPolicyValue::kNone, + rph, worker_route_id_, origin, network::CrossOriginEmbedderPolicy(), ContentBrowserClient::URLLoaderFactoryType::kServiceWorkerScript); auto subresource_bundle = EmbeddedWorkerInstance::CreateFactoryBundleOnUI( - rph, worker_route_id_, origin, - network::mojom::CrossOriginEmbedderPolicyValue::kNone, + rph, worker_route_id_, origin, network::CrossOriginEmbedderPolicy(), ContentBrowserClient::URLLoaderFactoryType::kServiceWorkerSubResource); if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 799ad94..fd77a87 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1895,10 +1895,6 @@ // process's channel. remote_associated_interfaces_.reset(); - // Ensure that the AssociatedRemote<blink::mojom::LocalFrame> works after a - // crash. - local_frame_.reset(); - // Any termination disablers in content loaded by the new process will // be sent again. has_before_unload_handler_ = false; @@ -6012,6 +6008,8 @@ frame_.reset(); frame_bindings_control_.reset(); frame_host_associated_receiver_.reset(); + local_frame_.reset(); + local_main_frame_.reset(); navigation_control_.reset(); frame_input_handler_.reset(); find_in_page_.reset(); @@ -6027,6 +6025,7 @@ sensor_provider_proxy_.reset(); local_frame_host_receiver_.reset(); + local_main_frame_host_receiver_.reset(); associated_registry_.reset(); }
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index fbeb817..6f6feb2 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1045,8 +1045,8 @@ void RenderFrameHostManager::OnEnforceInsecureRequestPolicy( blink::mojom::InsecureRequestPolicy policy) { for (const auto& pair : proxy_hosts_) { - pair.second->Send(new FrameMsg_EnforceInsecureRequestPolicy( - pair.second->GetRoutingID(), policy)); + pair.second->GetAssociatedRemoteFrame()->EnforceInsecureRequestPolicy( + policy); } }
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index 8f0e562..9d16815 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -88,21 +88,6 @@ EXPECT_EQ(expected_focus, focus_message->focused()); } -// Helper function for strict mixed content checking tests. -void CheckInsecureRequestPolicyIPC( - TestRenderFrameHost* rfh, - blink::mojom::InsecureRequestPolicy expected_param, - int expected_routing_id) { - const IPC::Message* message = - rfh->GetProcess()->sink().GetUniqueMessageMatching( - FrameMsg_EnforceInsecureRequestPolicy::ID); - ASSERT_TRUE(message); - EXPECT_EQ(expected_routing_id, message->routing_id()); - FrameMsg_EnforceInsecureRequestPolicy::Param params; - EXPECT_TRUE(FrameMsg_EnforceInsecureRequestPolicy::Read(message, ¶ms)); - EXPECT_EQ(expected_param, std::get<0>(params)); -} - class RenderFrameHostManagerTestWebUIControllerFactory : public WebUIControllerFactory { public: @@ -2914,6 +2899,53 @@ EXPECT_FALSE(GetPendingFrameHost(manager)); } +// This class intercepts RenderFrameProxyHost creations, and overrides their +// respective blink::mojom::RemoteFrame instances. +class InsecureRequestPolicyProxyObserver { + public: + InsecureRequestPolicyProxyObserver() { + RenderFrameProxyHost::SetCreatedCallbackForTesting( + base::BindRepeating(&InsecureRequestPolicyProxyObserver:: + RenderFrameProxyHostCreatedCallback, + base::Unretained(this))); + } + ~InsecureRequestPolicyProxyObserver() { + RenderFrameProxyHost::SetCreatedCallbackForTesting( + RenderFrameProxyHost::CreatedCallback()); + } + blink::mojom::InsecureRequestPolicy GetRequestPolicy( + RenderFrameProxyHost* proxy_host) { + return remote_frames_[proxy_host]->enforce_insecure_request_policy(); + } + + private: + // Stub out remote frame mojo binding. Intercepts calls to + // EnforceInsecureRequestPolicy and marks the message as received. + class RemoteFrame : public content::FakeRemoteFrame { + public: + explicit RemoteFrame(RenderFrameProxyHost* render_frame_proxy_host) { + Init(render_frame_proxy_host->GetRemoteAssociatedInterfacesTesting()); + } + + void EnforceInsecureRequestPolicy( + blink::mojom::InsecureRequestPolicy policy) override { + enforce_insecure_request_policy_ = policy; + } + blink::mojom::InsecureRequestPolicy enforce_insecure_request_policy() { + return enforce_insecure_request_policy_; + } + + private: + blink::mojom::InsecureRequestPolicy enforce_insecure_request_policy_; + }; + + void RenderFrameProxyHostCreatedCallback(RenderFrameProxyHost* proxy_host) { + remote_frames_[proxy_host] = std::make_unique<RemoteFrame>(proxy_host); + } + + std::map<RenderFrameProxyHost*, std::unique_ptr<RemoteFrame>> remote_frames_; +}; + // Tests that frame proxies receive updates when a frame's enforcement // of insecure request policy changes. TEST_P(RenderFrameHostManagerTestWithSiteIsolation, @@ -2921,6 +2953,7 @@ const GURL kUrl1("http://www.google.test"); const GURL kUrl2("http://www.google2.test"); const GURL kUrl3("http://www.google2.test/foo"); + InsecureRequestPolicyProxyObserver observer; contents()->NavigateAndCommit(kUrl1); @@ -2956,9 +2989,9 @@ RenderFrameProxyHost* proxy_to_child = root->render_manager()->GetRenderFrameProxyHost( child_host->GetSiteInstance()); - EXPECT_NO_FATAL_FAILURE(CheckInsecureRequestPolicyIPC( - child_host, blink::mojom::InsecureRequestPolicy::kBlockAllMixedContent, - proxy_to_child->GetRoutingID())); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(blink::mojom::InsecureRequestPolicy::kBlockAllMixedContent, + observer.GetRequestPolicy(proxy_to_child)); EXPECT_EQ(blink::mojom::InsecureRequestPolicy::kBlockAllMixedContent, root->current_replication_state().insecure_request_policy); @@ -2975,10 +3008,9 @@ blink::mojom::InsecureRequestPolicy::kBlockAllMixedContent); RenderFrameProxyHost* proxy_to_parent = child->GetRenderFrameProxyHost(main_test_rfh()->GetSiteInstance()); - EXPECT_NO_FATAL_FAILURE(CheckInsecureRequestPolicyIPC( - main_test_rfh(), - blink::mojom::InsecureRequestPolicy::kBlockAllMixedContent, - proxy_to_parent->GetRoutingID())); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(blink::mojom::InsecureRequestPolicy::kBlockAllMixedContent, + observer.GetRequestPolicy(proxy_to_parent)); EXPECT_EQ( blink::mojom::InsecureRequestPolicy::kBlockAllMixedContent, root->child_at(0)->current_replication_state().insecure_request_policy); @@ -2987,10 +3019,9 @@ // when the child navigates. main_test_rfh()->GetProcess()->sink().ClearMessages(); NavigationSimulator::NavigateAndCommitFromDocument(kUrl3, child_host); - EXPECT_NO_FATAL_FAILURE(CheckInsecureRequestPolicyIPC( - main_test_rfh(), - blink::mojom::InsecureRequestPolicy::kLeaveInsecureRequestsAlone, - proxy_to_parent->GetRoutingID())); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(blink::mojom::InsecureRequestPolicy::kLeaveInsecureRequestsAlone, + observer.GetRequestPolicy(proxy_to_parent)); EXPECT_EQ( blink::mojom::InsecureRequestPolicy::kLeaveInsecureRequestsAlone, root->child_at(0)->current_replication_state().insecure_request_policy);
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index 620bd68..0fa99dc 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc
@@ -369,7 +369,10 @@ int flags = plugin_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : ChildProcessHost::CHILD_NORMAL; #elif defined(OS_MACOSX) - int flags = ChildProcessHost::CHILD_PLUGIN; + // Flash needs to JIT, but other plugins do not. + int flags = permissions_.HasPermission(ppapi::PERMISSION_FLASH) + ? ChildProcessHost::CHILD_PLUGIN + : ChildProcessHost::CHILD_NORMAL; #else int flags = ChildProcessHost::CHILD_NORMAL; #endif
diff --git a/content/browser/renderer_host/OWNERS b/content/browser/renderer_host/OWNERS index e566b73..36f34e3 100644 --- a/content/browser/renderer_host/OWNERS +++ b/content/browser/renderer_host/OWNERS
@@ -24,6 +24,7 @@ # DelegatedFrame* per-file *delegated_frame*=fsamuel@chromium.org per-file *delegated_frame*=samans@chromium.org +per-file *delegated_frame*=jonross@chromium.org # WebSQL per-file web_database_*=jsbell@chromium.org
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index d66ff362..c1d5c75a 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -124,7 +124,7 @@ int embedded_worker_id, base::WeakPtr<ServiceWorkerProcessManager> process_manager, bool can_use_existing_process, - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy, + const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy, blink::mojom::EmbeddedWorkerStartParamsPtr params, mojo::PendingReceiver<blink::mojom::EmbeddedWorkerInstanceClient> receiver, ServiceWorkerContextCore* context, @@ -528,10 +528,10 @@ return skip_recording_startup_time_; } - void Start(blink::mojom::EmbeddedWorkerStartParamsPtr params, - network::mojom::CrossOriginEmbedderPolicyValue - cross_origin_embedder_policy, - StatusCallback sent_start_callback) { + void Start( + blink::mojom::EmbeddedWorkerStartParamsPtr params, + const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy, + StatusCallback sent_start_callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); DCHECK(instance_->context_); TRACE_EVENT_WITH_FLOW0( @@ -1037,7 +1037,7 @@ RenderProcessHost* rph, int routing_id, const url::Origin& origin, - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy, + const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy, ContentBrowserClient::URLLoaderFactoryType factory_type) { DCHECK_CURRENTLY_ON(BrowserThread::UI); auto factory_bundle = @@ -1067,9 +1067,7 @@ factory_params->client_security_state = network::mojom::ClientSecurityState::New(); - // TODO(https://crbug.com/1056122): Plumb other fields to support report only - // mode. - factory_params->client_security_state->cross_origin_embedder_policy.value = + factory_params->client_security_state->cross_origin_embedder_policy = std::move(cross_origin_embedder_policy); rph->CreateURLLoaderFactory(std::move(default_factory_receiver),
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h index 9801849..8576699 100644 --- a/content/browser/service_worker/embedded_worker_instance.h +++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -226,8 +226,7 @@ RenderProcessHost* rph, int routing_id, const url::Origin& origin, - network::mojom::CrossOriginEmbedderPolicyValue - cross_origin_embedder_policy, + const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy, ContentBrowserClient::URLLoaderFactoryType factory_type); private:
diff --git a/content/browser/service_worker/service_worker_database.cc b/content/browser/service_worker/service_worker_database.cc index 9a504aa..27358da 100644 --- a/content/browser/service_worker/service_worker_database.cc +++ b/content/browser/service_worker/service_worker_database.cc
@@ -1556,17 +1556,30 @@ static_cast<blink::mojom::ServiceWorkerUpdateViaCache>(value); } - if (data.has_cross_origin_embedder_policy()) { - switch (data.cross_origin_embedder_policy()) { - case ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST: - (*out)->cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kNone; - break; - case ServiceWorkerRegistrationData::REQUIRE_CORP: - (*out)->cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; - break; - } + if (data.has_cross_origin_embedder_policy_value()) { + (*out)->cross_origin_embedder_policy.value = + data.cross_origin_embedder_policy_value() == + ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST + ? network::mojom::CrossOriginEmbedderPolicyValue::kNone + : network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + } + + if (data.has_cross_origin_embedder_policy_reporting_endpoint()) { + (*out)->cross_origin_embedder_policy.reporting_endpoint = + data.cross_origin_embedder_policy_reporting_endpoint(); + } + + if (data.has_cross_origin_embedder_policy_report_only_value()) { + (*out)->cross_origin_embedder_policy.report_only_value = + data.cross_origin_embedder_policy_report_only_value() == + ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST + ? network::mojom::CrossOriginEmbedderPolicyValue::kNone + : network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + } + + if (data.has_cross_origin_embedder_policy_report_only_reporting_endpoint()) { + (*out)->cross_origin_embedder_policy.report_only_reporting_endpoint = + data.cross_origin_embedder_policy_report_only_reporting_endpoint(); } return Status::kOk; @@ -1626,11 +1639,26 @@ ServiceWorkerRegistrationData_ServiceWorkerUpdateViaCacheType>( registration.update_via_cache)); - data.set_cross_origin_embedder_policy( - registration.cross_origin_embedder_policy == + data.set_cross_origin_embedder_policy_value( + registration.cross_origin_embedder_policy.value == network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp ? ServiceWorkerRegistrationData::REQUIRE_CORP : ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST); + if (registration.cross_origin_embedder_policy.reporting_endpoint) { + data.set_cross_origin_embedder_policy_reporting_endpoint( + registration.cross_origin_embedder_policy.reporting_endpoint.value()); + } + data.set_cross_origin_embedder_policy_report_only_value( + registration.cross_origin_embedder_policy.report_only_value == + network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp + ? ServiceWorkerRegistrationData::REQUIRE_CORP + : ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST); + if (registration.cross_origin_embedder_policy + .report_only_reporting_endpoint) { + data.set_cross_origin_embedder_policy_report_only_reporting_endpoint( + registration.cross_origin_embedder_policy.report_only_reporting_endpoint + .value()); + } std::string value; bool success = data.SerializeToString(&value);
diff --git a/content/browser/service_worker/service_worker_database.proto b/content/browser/service_worker/service_worker_database.proto index 92bb9f0..5fadeea4 100644 --- a/content/browser/service_worker/service_worker_database.proto +++ b/content/browser/service_worker/service_worker_database.proto
@@ -77,8 +77,14 @@ // serialized by Time::ToDeltaSinceWindowsEpoch(). optional int64 script_response_time = 16; - optional CrossOriginEmbedderPolicyValue cross_origin_embedder_policy = 17 + optional CrossOriginEmbedderPolicyValue cross_origin_embedder_policy_value = + 17 [default = NONE_OR_NOT_EXIST]; + optional string cross_origin_embedder_policy_reporting_endpoint = 18; + optional CrossOriginEmbedderPolicyValue + cross_origin_embedder_policy_report_only_value = 19 [default = NONE_OR_NOT_EXIST]; + optional string cross_origin_embedder_policy_report_only_reporting_endpoint = + 20; } message ServiceWorkerResourceRecord {
diff --git a/content/browser/service_worker/service_worker_database_unittest.cc b/content/browser/service_worker/service_worker_database_unittest.cc index f8c02038..8406253 100644 --- a/content/browser/service_worker/service_worker_database_unittest.cc +++ b/content/browser/service_worker/service_worker_database_unittest.cc
@@ -95,6 +95,16 @@ } } +network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyNone() { + return network::CrossOriginEmbedderPolicy(); +} + +network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyRequireCorp() { + network::CrossOriginEmbedderPolicy out; + out.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + return out; +} + } // namespace TEST(ServiceWorkerDatabaseTest, OpenDatabase) { @@ -450,8 +460,7 @@ data1.version_id = 1000; data1.resources_total_size_bytes = 100; data1.script_response_time = base::Time::FromJsTime(0); - data1.cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kNone; + data1.cross_origin_embedder_policy = CrossOriginEmbedderPolicyNone(); std::vector<ResourceRecordPtr> resources1; resources1.push_back(CreateResource(1, data1.script, 100)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -474,8 +483,7 @@ data2.version_id = 2000; data2.resources_total_size_bytes = 200; data2.script_response_time = base::Time::FromJsTime(42); - data2.cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + data2.cross_origin_embedder_policy = CrossOriginEmbedderPolicyRequireCorp(); std::vector<ResourceRecordPtr> resources2; resources2.push_back(CreateResource(2, data2.script, 200)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -498,8 +506,7 @@ data3.version_id = 3000; data3.resources_total_size_bytes = 300; data3.script_response_time = base::Time::FromJsTime(420); - data3.cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kNone; + data3.cross_origin_embedder_policy = CrossOriginEmbedderPolicyNone(); std::vector<ResourceRecordPtr> resources3; resources3.push_back(CreateResource(3, data3.script, 300)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -513,8 +520,7 @@ data4.version_id = 4000; data4.resources_total_size_bytes = 400; data4.script_response_time = base::Time::FromJsTime(4200); - data4.cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + data4.cross_origin_embedder_policy = CrossOriginEmbedderPolicyRequireCorp(); std::vector<ResourceRecordPtr> resources4; resources4.push_back(CreateResource(4, data4.script, 400)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -559,8 +565,7 @@ data1.script = URL(origin1, "/script1.js"); data1.version_id = 1000; data1.resources_total_size_bytes = 100; - data1.cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kNone; + data1.cross_origin_embedder_policy = CrossOriginEmbedderPolicyNone(); std::vector<ResourceRecordPtr> resources1; resources1.push_back(CreateResource(1, data1.script, 100)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -574,8 +579,7 @@ data2.version_id = 2000; data2.resources_total_size_bytes = 200; data2.update_via_cache = blink::mojom::ServiceWorkerUpdateViaCache::kNone; - data2.cross_origin_embedder_policy = - network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + data2.cross_origin_embedder_policy = CrossOriginEmbedderPolicyRequireCorp(); std::vector<ResourceRecordPtr> resources2; resources2.push_back(CreateResource(2, data2.script, 200)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -2171,6 +2175,70 @@ EXPECT_EQ(expect, registration->used_features); } +// Check that every field of CrossOriginEmbedderPolicy can be properly +// serialized and deserialized. +TEST(ServiceWorkerDatabaseTest, CrossOriginEmbedderPolicyStoreRestore) { + auto store_and_restore = [](network::CrossOriginEmbedderPolicy policy) { + // Build the minimal RegistrationData with the given |policy|. + GURL origin("https://example.com"); + RegistrationData data; + data.registration_id = 123; + data.scope = URL(origin, "/foo"); + data.script = URL(origin, "/script.js"); + data.version_id = 456; + data.resources_total_size_bytes = 100; + data.cross_origin_embedder_policy = policy; + std::vector<ResourceRecordPtr> resources; + resources.push_back(CreateResource(1, data.script, 100)); + + // Store. + std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); + ServiceWorkerDatabase::DeletedVersion deleted_version; + ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, + database->WriteRegistration(data, resources, &deleted_version)); + + // Restore. + std::vector<storage::mojom::ServiceWorkerRegistrationDataPtr> registrations; + std::vector<std::vector<ResourceRecordPtr>> resources_list; + EXPECT_EQ(ServiceWorkerDatabase::Status::kOk, + database->GetRegistrationsForOrigin(origin, ®istrations, + &resources_list)); + + // The data must not have been altered. + VerifyRegistrationData(data, *registrations[0]); + }; + + { + network::CrossOriginEmbedderPolicy policy; + policy.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + store_and_restore(policy); + policy.value = network::mojom::CrossOriginEmbedderPolicyValue::kNone; + store_and_restore(policy); + } + + { + network::CrossOriginEmbedderPolicy policy; + policy.reporting_endpoint = "foo"; + store_and_restore(policy); + } + + { + network::CrossOriginEmbedderPolicy policy; + policy.report_only_value = + network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + store_and_restore(policy); + policy.report_only_value = + network::mojom::CrossOriginEmbedderPolicyValue::kNone; + store_and_restore(policy); + } + + { + network::CrossOriginEmbedderPolicy policy; + policy.report_only_reporting_endpoint = "bar"; + store_and_restore(policy); + } +} + TEST(ServiceWorkerDatabaseTest, NoCrossOriginEmbedderPolicyValue) { std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory()); @@ -2198,7 +2266,7 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->ParseRegistrationData(value, ®istration)); EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone, - registration->cross_origin_embedder_policy); + registration->cross_origin_embedder_policy.value); } } // namespace content
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc index 67bd23ca..ffc4832b 100644 --- a/content/browser/service_worker/service_worker_job_unittest.cc +++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -149,6 +149,16 @@ EmbeddedWorkerStatus expected_running_status_; }; +network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyNone() { + return network::CrossOriginEmbedderPolicy(); +} + +network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyRequireCorp() { + network::CrossOriginEmbedderPolicy out; + out.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + return out; +} + } // namespace class ServiceWorkerJobTest : public testing::Test { @@ -2055,7 +2065,7 @@ scoped_refptr<ServiceWorkerRegistration> registration = update_helper_->SetupInitialRegistration(kNewVersionOrigin); ASSERT_TRUE(registration.get()); - EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone, + EXPECT_EQ(CrossOriginEmbedderPolicyNone(), registration->active_version()->cross_origin_embedder_policy()); registration->AddListener(update_helper_); @@ -2098,7 +2108,7 @@ histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound", true, 1); ASSERT_NE(nullptr, registration->waiting_version()); - EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp, + EXPECT_EQ(CrossOriginEmbedderPolicyRequireCorp(), registration->waiting_version()->cross_origin_embedder_policy()); } @@ -2120,7 +2130,7 @@ histogram_tester.ExpectBucketCount("ServiceWorker.UpdateCheck.UpdateFound", true, 1); ASSERT_NE(nullptr, registration->waiting_version()); - EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone, + EXPECT_EQ(CrossOriginEmbedderPolicyNone(), registration->waiting_version()->cross_origin_embedder_policy()); } }
diff --git a/content/browser/service_worker/service_worker_new_script_loader.cc b/content/browser/service_worker/service_worker_new_script_loader.cc index b18d146e..4add383 100644 --- a/content/browser/service_worker/service_worker_new_script_loader.cc +++ b/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -205,7 +205,7 @@ } version_->set_cross_origin_embedder_policy( - response_head->cross_origin_embedder_policy.value); + response_head->cross_origin_embedder_policy); if (response_head->network_accessed) version_->embedded_worker()->OnNetworkAccessedForScriptLoad();
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker.cc b/content/browser/service_worker/service_worker_single_script_update_checker.cc index 3d1f4326..6633084 100644 --- a/content/browser/service_worker/service_worker_single_script_update_checker.cc +++ b/content/browser/service_worker/service_worker_single_script_update_checker.cc
@@ -278,8 +278,7 @@ network::URLLoaderCompletionStatus(net::ERR_INSECURE_RESPONSE)); return; } - cross_origin_embedder_policy_ = - response_head->cross_origin_embedder_policy.value; + cross_origin_embedder_policy_ = response_head->cross_origin_embedder_policy; } network_loader_state_ =
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker.h b/content/browser/service_worker/service_worker_single_script_update_checker.h index 728de85..bdac3408 100644 --- a/content/browser/service_worker/service_worker_single_script_update_checker.h +++ b/content/browser/service_worker/service_worker_single_script_update_checker.h
@@ -145,7 +145,7 @@ void OnComplete(const network::URLLoaderCompletionStatus& status) override; bool network_accessed() const { return network_accessed_; } - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy() + const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy() const { return cross_origin_embedder_policy_; } @@ -188,8 +188,7 @@ const blink::mojom::ServiceWorkerUpdateViaCache update_via_cache_; const base::TimeDelta time_since_last_check_; bool network_accessed_ = false; - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy_ = - network::mojom::CrossOriginEmbedderPolicyValue::kNone; + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy_; std::unique_ptr< ServiceWorkerUpdatedScriptLoader::ThrottlingURLLoaderCoreWrapper>
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc index 235eaf4c..457579e 100644 --- a/content/browser/service_worker/service_worker_storage_unittest.cc +++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -742,8 +742,10 @@ live_version->script_cache_map()->SetResources(resources); live_version->set_used_features( std::set<blink::mojom::WebFeature>(used_features)); - live_version->set_cross_origin_embedder_policy( - network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp); + network::CrossOriginEmbedderPolicy coep_require_corp; + coep_require_corp.value = + network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + live_version->set_cross_origin_embedder_policy(coep_require_corp); live_registration->SetWaitingVersion(live_version); live_registration->set_last_update_check(kYesterday); EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, @@ -761,7 +763,7 @@ found_registration->waiting_version()->used_features()); EXPECT_EQ( found_registration->waiting_version()->cross_origin_embedder_policy(), - network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp); + coep_require_corp); found_registration = nullptr; // But FindRegistrationForScope is always async.
diff --git a/content/browser/service_worker/service_worker_test_utils.cc b/content/browser/service_worker/service_worker_test_utils.cc index eba1a01..4057e943 100644 --- a/content/browser/service_worker/service_worker_test_utils.cc +++ b/content/browser/service_worker/service_worker_test_utils.cc
@@ -774,7 +774,7 @@ ServiceWorkerSingleScriptUpdateChecker::Result::kDifferent) ? script_url : GURL(), - network::mojom::CrossOriginEmbedderPolicyValue::kNone); + network::CrossOriginEmbedderPolicy()); } void ServiceWorkerUpdateCheckTestUtils::
diff --git a/content/browser/service_worker/service_worker_update_checker.h b/content/browser/service_worker/service_worker_update_checker.h index 21a2b5f..f356ca6d 100644 --- a/content/browser/service_worker/service_worker_update_checker.h +++ b/content/browser/service_worker/service_worker_update_checker.h
@@ -111,8 +111,7 @@ const GURL& updated_script_url() const { return updated_script_url_; } bool network_accessed() const { return network_accessed_; } - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy() - const { + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy() const { return cross_origin_embedder_policy_; } @@ -159,9 +158,8 @@ // True if any at least one of the scripts is fetched by network. bool network_accessed_ = false; - // The value of Cross-Origin-Embedder-Policy header for the updated main - // script. - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy_; + // The Cross-Origin-Embedder-Policy header for the updated main script. + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy_; // |context_| outlives |this| because it owns |this| through // ServiceWorkerJobCoordinator and ServiceWorkerRegisterJob.
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 07fe7974..5fe3884 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -2238,8 +2238,7 @@ std::map<GURL, ServiceWorkerUpdateChecker::ComparedScriptInfo> compared_script_info_map, const GURL& updated_script_url, - network::mojom::CrossOriginEmbedderPolicyValue - cross_origin_embedder_policy) { + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy) { compared_script_info_map_ = std::move(compared_script_info_map); updated_script_url_ = updated_script_url; cross_origin_embedder_policy_ = cross_origin_embedder_policy;
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index fc75325..0a37e0b 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h
@@ -44,7 +44,7 @@ #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/remote.h" -#include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h" +#include "services/network/public/cpp/cross_origin_embedder_policy.h" #include "third_party/blink/public/common/origin_trials/trial_token_validator.h" #include "third_party/blink/public/common/service_worker/service_worker_status_code.h" #include "third_party/blink/public/mojom/loader/fetch_client_settings_object.mojom.h" @@ -512,12 +512,10 @@ } void set_cross_origin_embedder_policy( - network::mojom::CrossOriginEmbedderPolicyValue - cross_origin_embedder_policy) { + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy) { cross_origin_embedder_policy_ = cross_origin_embedder_policy; } - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy() - const { + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy() const { return cross_origin_embedder_policy_; } @@ -554,8 +552,7 @@ std::map<GURL, ServiceWorkerUpdateChecker::ComparedScriptInfo> compared_script_info_map, const GURL& updated_script_url, - network::mojom::CrossOriginEmbedderPolicyValue - cross_origin_embedder_policy); + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy); const std::map<GURL, ServiceWorkerUpdateChecker::ComparedScriptInfo>& compared_script_info_map() const; ServiceWorkerUpdateChecker::ComparedScriptInfo TakeComparedScriptInfo( @@ -892,8 +889,7 @@ // Cross-Origin-Embedder-Policy for the service worker script. This persists // in the disk. kNone is set if this is a brand-new service worker whose main // script is not loaded yet. - network::mojom::CrossOriginEmbedderPolicyValue cross_origin_embedder_policy_ = - network::mojom::CrossOriginEmbedderPolicyValue::kNone; + network::CrossOriginEmbedderPolicy cross_origin_embedder_policy_; Status status_ = NEW; std::unique_ptr<EmbeddedWorkerInstance> embedded_worker_;
diff --git a/content/browser/service_worker/service_worker_version_browsertest.cc b/content/browser/service_worker/service_worker_version_browsertest.cc index 13ee9250..787149e 100644 --- a/content/browser/service_worker/service_worker_version_browsertest.cc +++ b/content/browser/service_worker/service_worker_version_browsertest.cc
@@ -281,6 +281,16 @@ return http_response; } +network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyNone() { + return network::CrossOriginEmbedderPolicy(); +} + +network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyRequireCorp() { + network::CrossOriginEmbedderPolicy out; + out.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp; + return out; +} + } // namespace class ConsoleListener : public EmbeddedWorkerInstance::Listener { @@ -1638,15 +1648,15 @@ RunOnCoreThread(base::BindOnce( &ServiceWorkerVersionBrowserTest::SetUpRegistrationOnCoreThread, base::Unretained(this), "/service_worker/generated")); - EXPECT_EQ(network::mojom::CrossOriginEmbedderPolicyValue::kNone, + EXPECT_EQ(CrossOriginEmbedderPolicyNone(), version_->cross_origin_embedder_policy()); // Once it's started, the worker script is read from the network and the COEP // value is set to the version. StartWorker(blink::ServiceWorkerStatusCode::kOk); EXPECT_EQ(IsCrossOriginIsolationEnabled() - ? network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp - : network::mojom::CrossOriginEmbedderPolicyValue::kNone, + ? CrossOriginEmbedderPolicyRequireCorp() + : CrossOriginEmbedderPolicyNone(), version_->cross_origin_embedder_policy()); }
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index e4196bc..7d0aa842 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -558,11 +558,6 @@ std::string /* name */, std::string /* unique_name */) -// Update a proxy's replicated enforcement of insecure request policy. -// Used when the frame's policy is changed in another process. -IPC_MESSAGE_ROUTED1(FrameMsg_EnforceInsecureRequestPolicy, - blink::mojom::InsecureRequestPolicy) - // Send to the RenderFrame to set text tracks state and style settings. // Sent for top-level frames. IPC_MESSAGE_ROUTED1(FrameMsg_SetTextTrackSettings,
diff --git a/content/public/test/fake_remote_frame.cc b/content/public/test/fake_remote_frame.cc index 3a27310..0e51675 100644 --- a/content/public/test/fake_remote_frame.cc +++ b/content/public/test/fake_remote_frame.cc
@@ -32,6 +32,9 @@ void FakeRemoteFrame::SetFrameOwnerProperties( blink::mojom::FrameOwnerPropertiesPtr properties) {} +void FakeRemoteFrame::EnforceInsecureRequestPolicy( + blink::mojom::InsecureRequestPolicy policy) {} + void FakeRemoteFrame::SetReplicatedOrigin( const url::Origin& origin, bool is_potentially_trustworthy_unique_origin) {}
diff --git a/content/public/test/fake_remote_frame.h b/content/public/test/fake_remote_frame.h index 72ed0dc..b2525b6d 100644 --- a/content/public/test/fake_remote_frame.h +++ b/content/public/test/fake_remote_frame.h
@@ -13,6 +13,7 @@ #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom.h" #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h" #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom.h" +#include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h" #include "ui/events/types/scroll_types.h" namespace base { @@ -45,6 +46,8 @@ void EnforceInsecureNavigationsSet(const std::vector<uint32_t>& set) override; void SetFrameOwnerProperties( blink::mojom::FrameOwnerPropertiesPtr properties) override; + void EnforceInsecureRequestPolicy( + blink::mojom::InsecureRequestPolicy policy) override; void SetReplicatedOrigin( const url::Origin& origin, bool is_potentially_trustworthy_unique_origin) override;
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc index 7db490c..4390820 100644 --- a/content/renderer/input/render_widget_input_handler.cc +++ b/content/renderer/input/render_widget_input_handler.cc
@@ -445,7 +445,7 @@ suppress_next_char_events_ = false; if (processed == WebInputEventResult::kNotHandled && widget_->GetWebWidget()) { - if (!widget_->GetWebWidget()->IsPepperWidget() && + if (delegate_->SupportsBufferedTouchEvents() && WebInputEvent::IsTouchEventType(input_event.GetType())) processed = HandleTouchEvent(coalesced_event); else
diff --git a/content/renderer/input/render_widget_input_handler_delegate.h b/content/renderer/input/render_widget_input_handler_delegate.h index 8d3e7d4..4491717c 100644 --- a/content/renderer/input/render_widget_input_handler_delegate.h +++ b/content/renderer/input/render_widget_input_handler_delegate.h
@@ -70,8 +70,11 @@ // won't be sent to WebKit or trigger DidHandleMouseEvent(). virtual bool WillHandleMouseEvent(const blink::WebMouseEvent& event) = 0; + // Whether buffered touch events should be supported or not. + virtual bool SupportsBufferedTouchEvents() = 0; + protected: - virtual ~RenderWidgetInputHandlerDelegate() {} + virtual ~RenderWidgetInputHandlerDelegate() = default; }; } // namespace content
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 60888e8..86914f7 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -374,8 +374,6 @@ IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg) IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener) IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateName, OnDidUpdateName) - IPC_MESSAGE_HANDLER(FrameMsg_EnforceInsecureRequestPolicy, - OnEnforceInsecureRequestPolicy) IPC_MESSAGE_HANDLER(FrameMsg_TransferUserActivationFrom, OnTransferUserActivationFrom) IPC_MESSAGE_HANDLER(UnfreezableFrameMsg_DeleteProxy, OnDeleteProxy) @@ -428,11 +426,6 @@ unique_name_ = unique_name; } -void RenderFrameProxy::OnEnforceInsecureRequestPolicy( - blink::mojom::InsecureRequestPolicy policy) { - web_frame_->SetReplicatedInsecureRequestPolicy(policy); -} - void RenderFrameProxy::OnTransferUserActivationFrom(int32_t source_routing_id) { RenderFrameProxy* source_proxy = RenderFrameProxy::FromRoutingID(source_routing_id);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 5e9155c..6476397 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1543,6 +1543,11 @@ return mouse_lock_dispatcher()->WillHandleMouseEvent(event); } +bool RenderWidget::SupportsBufferedTouchEvents() { + // Buffered touch events aren't supported for pepper. + return !pepper_fullscreen_; +} + void RenderWidget::ResizeWebWidget() { // In auto resize mode, blink controls sizes and RenderWidget should not be // passing values back in.
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index a5e2f92..7772dfa4 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -351,6 +351,7 @@ void ClearTextInputState() override; bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override; bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override; + bool SupportsBufferedTouchEvents() override; // RenderWidgetScreenMetricsEmulatorDelegate void SetScreenMetricsEmulationParameters(
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc index cbdb2df..47e8ce0e 100644 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -41,7 +41,6 @@ using blink::WebString; using blink::WebTextInputType; using blink::WebVector; -using blink::WebWidget; namespace content { @@ -126,142 +125,34 @@ widget_->Send(new WidgetHostMsg_UnlockMouse(widget_->routing_id())); } -// WebWidget that simply wraps the pepper plugin. -// TODO(piman): figure out IME and implement setComposition and friends if -// necessary. -class PepperWidget : public WebWidget { +} // anonymous namespace + +// We place the WebExternalWidgetClient interface on a separate class because +// RenderWidget implements blink::WebWidgetClient, which is not used for +// WebExternalWidgets, but may have similar method definitions as this +// interface. +class PepperExternalWidgetClient : public blink::WebExternalWidgetClient { public: - explicit PepperWidget(RenderWidgetFullscreenPepper* widget, - const blink::WebURL& local_main_frame_url) - : widget_(widget), local_main_frame_url_(local_main_frame_url) {} + explicit PepperExternalWidgetClient(RenderWidgetFullscreenPepper* widget) + : widget_(widget) {} + ~PepperExternalWidgetClient() override = default; - virtual ~PepperWidget() = default; - - // WebWidget API - void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override { - // These pointers are not stored as they aren't needed. + // blink::WebExternalWidgetClient overrides: + blink::WebInputEventResult HandleInputEvent( + const blink::WebCoalescedInputEvent& event) override { + return widget_->ProcessInputEvent(event); } - void Close() override { delete this; } - - WebSize Size() override { return size_; } - - bool IsPepperWidget() const override { return true; } - - void Resize(const WebSize& size) override { - if (!widget_->plugin() || size_ == size) - return; - - size_ = size; - WebRect plugin_rect(0, 0, size_.width, size_.height); - widget_->plugin()->ViewChanged(plugin_rect, plugin_rect, plugin_rect); + blink::WebInputEventResult DispatchBufferedTouchEvents() override { + return WebInputEventResult::kNotHandled; } - void ThemeChanged() override { NOTIMPLEMENTED(); } - - blink::WebHitTestResult HitTestResultAt(const gfx::Point&) override { - NOTIMPLEMENTED(); - return {}; - } - - WebInputEventResult HandleInputEvent( - const WebCoalescedInputEvent& coalesced_event) override { - if (!widget_->plugin()) - return WebInputEventResult::kNotHandled; - - const WebInputEvent& event = coalesced_event.Event(); - - // This cursor info is ignored, we always set the cursor directly from - // RenderWidgetFullscreenPepper::DidChangeCursor. - WebCursorInfo cursor; - - // Pepper plugins do not accept gesture events. So do not send the gesture - // events directly to the plugin. Instead, try to convert them to equivalent - // mouse events, and then send to the plugin. - if (WebInputEvent::IsGestureEventType(event.GetType())) { - bool result = false; - const WebGestureEvent* gesture_event = - static_cast<const WebGestureEvent*>(&event); - switch (event.GetType()) { - case WebInputEvent::kGestureTap: { - WebMouseEvent mouse(WebInputEvent::kMouseMove, - gesture_event->GetModifiers(), - gesture_event->TimeStamp()); - mouse.SetPositionInWidget(gesture_event->PositionInWidget()); - mouse.SetPositionInScreen(gesture_event->PositionInScreen()); - mouse.movement_x = 0; - mouse.movement_y = 0; - result |= widget_->plugin()->HandleInputEvent(mouse, &cursor); - - mouse.SetType(WebInputEvent::kMouseDown); - mouse.button = WebMouseEvent::Button::kLeft; - mouse.click_count = gesture_event->data.tap.tap_count; - result |= widget_->plugin()->HandleInputEvent(mouse, &cursor); - - mouse.SetType(WebInputEvent::kMouseUp); - result |= widget_->plugin()->HandleInputEvent(mouse, &cursor); - break; - } - - default: { - WebMouseEvent mouse = WebMouseEventFromGestureEvent(*gesture_event); - if (mouse.GetType() != WebInputEvent::kUndefined) - result |= widget_->plugin()->HandleInputEvent(mouse, &cursor); - break; - } - } - return result ? WebInputEventResult::kHandledApplication - : WebInputEventResult::kNotHandled; - } - - bool result = widget_->plugin()->HandleInputEvent(event, &cursor); - - // For normal web pages, WebViewImpl does input event translations and - // generates context menu events. Since we don't have a WebView, we need to - // do the necessary translation ourselves. - if (WebInputEvent::IsMouseEventType(event.GetType())) { - const WebMouseEvent& mouse_event = - reinterpret_cast<const WebMouseEvent&>(event); - bool send_context_menu_event = false; - // On Mac/Linux, we handle it on mouse down. - // On Windows, we handle it on mouse up. -#if defined(OS_WIN) - send_context_menu_event = - mouse_event.GetType() == WebInputEvent::kMouseUp && - mouse_event.button == WebMouseEvent::Button::kRight; -#elif defined(OS_MACOSX) - send_context_menu_event = - mouse_event.GetType() == WebInputEvent::kMouseDown && - (mouse_event.button == WebMouseEvent::Button::kRight || - (mouse_event.button == WebMouseEvent::Button::kLeft && - mouse_event.GetModifiers() & WebMouseEvent::kControlKey)); -#else - send_context_menu_event = - mouse_event.GetType() == WebInputEvent::kMouseDown && - mouse_event.button == WebMouseEvent::Button::kRight; -#endif - if (send_context_menu_event) { - WebMouseEvent context_menu_event(mouse_event); - context_menu_event.SetType(WebInputEvent::kContextMenu); - widget_->plugin()->HandleInputEvent(context_menu_event, &cursor); - } - } - return result ? WebInputEventResult::kHandledApplication - : WebInputEventResult::kNotHandled; - } - - blink::WebURL GetURLForDebugTrace() override { return local_main_frame_url_; } + void DidResize(const gfx::Size& size) override { widget_->DidResize(size); } private: RenderWidgetFullscreenPepper* widget_; - WebSize size_; - blink::WebURL local_main_frame_url_; - - DISALLOW_COPY_AND_ASSIGN(PepperWidget); }; -} // anonymous namespace - // static RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( int32_t routing_id, @@ -273,19 +164,22 @@ mojo::PendingReceiver<mojom::Widget> widget_receiver) { DCHECK_NE(MSG_ROUTING_NONE, routing_id); DCHECK(show_callback); - RenderWidgetFullscreenPepper* widget = new RenderWidgetFullscreenPepper( - routing_id, compositor_deps, plugin, std::move(widget_receiver)); - widget->InitForPepperFullscreen( - std::move(show_callback), new PepperWidget(widget, local_main_frame_url), - screen_info); - return widget; + RenderWidgetFullscreenPepper* render_widget = + new RenderWidgetFullscreenPepper(routing_id, compositor_deps, plugin, + std::move(widget_receiver), + local_main_frame_url); + render_widget->InitForPepperFullscreen(std::move(show_callback), + render_widget->blink_widget_.get(), + screen_info); + return render_widget; } RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper( int32_t routing_id, CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, - mojo::PendingReceiver<mojom::Widget> widget_receiver) + mojo::PendingReceiver<mojom::Widget> widget_receiver, + blink::WebURL main_frame_url) : RenderWidget(routing_id, compositor_deps, /*display_mode=*/blink::mojom::DisplayMode::kUndefined, @@ -294,11 +188,14 @@ std::move(widget_receiver)), plugin_(plugin), mouse_lock_dispatcher_( - std::make_unique<FullscreenMouseLockDispatcher>(this)) {} - -RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() { + std::make_unique<FullscreenMouseLockDispatcher>(this)), + widget_client_(std::make_unique<PepperExternalWidgetClient>(this)) { + blink_widget_ = + blink::WebExternalWidget::Create(widget_client_.get(), main_frame_url); } +RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() = default; + void RenderWidgetFullscreenPepper::Destroy() { // The plugin instance is going away reset any lock target that is set // on the dispatcher since this object can still live and receive IPC @@ -327,13 +224,13 @@ void RenderWidgetFullscreenPepper::SetLayer(scoped_refptr<cc::Layer> layer) { layer_ = layer.get(); if (!layer_) { - layer_tree_host()->SetRootLayer(nullptr); + blink_widget_->SetRootLayer(nullptr); return; } UpdateLayerBounds(); layer_->SetIsDrawable(true); layer_->SetHitTestable(true); - layer_tree_host()->SetNonBlinkManagedRootLayer(std::move(layer)); + blink_widget_->SetRootLayer(std::move(layer)); } bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) { @@ -388,4 +285,97 @@ layer_->SetBounds(layer_size); } +WebInputEventResult RenderWidgetFullscreenPepper::ProcessInputEvent( + const WebCoalescedInputEvent& coalesced_event) { + if (!plugin()) + return WebInputEventResult::kNotHandled; + + const WebInputEvent& event = coalesced_event.Event(); + + // This cursor info is ignored, we always set the cursor directly from + // RenderWidgetFullscreenPepper::DidChangeCursor. + blink::WebCursorInfo cursor; + + // Pepper plugins do not accept gesture events. So do not send the gesture + // events directly to the plugin. Instead, try to convert them to equivalent + // mouse events, and then send to the plugin. + if (blink::WebInputEvent::IsGestureEventType(event.GetType())) { + bool result = false; + const WebGestureEvent* gesture_event = + static_cast<const WebGestureEvent*>(&event); + switch (event.GetType()) { + case WebInputEvent::kGestureTap: { + WebMouseEvent mouse(WebInputEvent::kMouseMove, + gesture_event->GetModifiers(), + gesture_event->TimeStamp()); + mouse.SetPositionInWidget(gesture_event->PositionInWidget()); + mouse.SetPositionInScreen(gesture_event->PositionInScreen()); + mouse.movement_x = 0; + mouse.movement_y = 0; + result |= plugin()->HandleInputEvent(mouse, &cursor); + + mouse.SetType(WebInputEvent::kMouseDown); + mouse.button = WebMouseEvent::Button::kLeft; + mouse.click_count = gesture_event->data.tap.tap_count; + result |= plugin()->HandleInputEvent(mouse, &cursor); + + mouse.SetType(WebInputEvent::kMouseUp); + result |= plugin()->HandleInputEvent(mouse, &cursor); + break; + } + + default: { + WebMouseEvent mouse = WebMouseEventFromGestureEvent(*gesture_event); + if (mouse.GetType() != WebInputEvent::kUndefined) + result |= plugin()->HandleInputEvent(mouse, &cursor); + break; + } + } + return result ? WebInputEventResult::kHandledApplication + : WebInputEventResult::kNotHandled; + } + + bool result = plugin()->HandleInputEvent(event, &cursor); + + // For normal web pages, WebViewImpl does input event translations and + // generates context menu events. Since we don't have a WebView, we need to + // do the necessary translation ourselves. + if (WebInputEvent::IsMouseEventType(event.GetType())) { + const WebMouseEvent& mouse_event = + reinterpret_cast<const WebMouseEvent&>(event); + bool send_context_menu_event = false; + // On Mac/Linux, we handle it on mouse down. + // On Windows, we handle it on mouse up. +#if defined(OS_WIN) + send_context_menu_event = + mouse_event.GetType() == WebInputEvent::kMouseUp && + mouse_event.button == WebMouseEvent::Button::kRight; +#elif defined(OS_MACOSX) + send_context_menu_event = + mouse_event.GetType() == WebInputEvent::kMouseDown && + (mouse_event.button == WebMouseEvent::Button::kRight || + (mouse_event.button == WebMouseEvent::Button::kLeft && + mouse_event.GetModifiers() & WebMouseEvent::kControlKey)); +#else + send_context_menu_event = + mouse_event.GetType() == WebInputEvent::kMouseDown && + mouse_event.button == WebMouseEvent::Button::kRight; +#endif + if (send_context_menu_event) { + WebMouseEvent context_menu_event(mouse_event); + context_menu_event.SetType(WebInputEvent::kContextMenu); + plugin()->HandleInputEvent(context_menu_event, &cursor); + } + } + return result ? WebInputEventResult::kHandledApplication + : WebInputEventResult::kNotHandled; +} + +void RenderWidgetFullscreenPepper::DidResize(const gfx::Size& size) { + if (!plugin()) + return; + gfx::Rect plugin_rect(size); + plugin()->ViewChanged(plugin_rect, plugin_rect, plugin_rect); +} + } // namespace content
diff --git a/content/renderer/render_widget_fullscreen_pepper.h b/content/renderer/render_widget_fullscreen_pepper.h index 6bdea29..24350792 100644 --- a/content/renderer/render_widget_fullscreen_pepper.h +++ b/content/renderer/render_widget_fullscreen_pepper.h
@@ -14,7 +14,8 @@ #include "content/renderer/pepper/fullscreen_container.h" #include "content/renderer/render_widget.h" #include "mojo/public/cpp/bindings/pending_receiver.h" -#include "third_party/blink/public/web/web_widget.h" +#include "third_party/blink/public/web/web_external_widget.h" +#include "third_party/blink/public/web/web_external_widget_client.h" #include "url/gurl.h" namespace cc { @@ -24,6 +25,7 @@ namespace content { class CompositorDependencies; class PepperPluginInstanceImpl; +class PepperExternalWidgetClient; // A RenderWidget that hosts a fullscreen pepper plugin. This provides a // FullscreenContainer that the plugin instance can callback into to e.g. @@ -62,7 +64,8 @@ int32_t routing_id, CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, - mojo::PendingReceiver<mojom::Widget> widget_receiver); + mojo::PendingReceiver<mojom::Widget> widget_receiver, + blink::WebURL main_frame_url); ~RenderWidgetFullscreenPepper() override; // RenderWidget API. @@ -71,7 +74,12 @@ void AfterUpdateVisualProperties() override; private: + friend class PepperExternalWidgetClient; + void UpdateLayerBounds(); + void DidResize(const gfx::Size& size); + blink::WebInputEventResult ProcessInputEvent( + const blink::WebCoalescedInputEvent& event); // The plugin instance this widget wraps. PepperPluginInstanceImpl* plugin_; @@ -79,6 +87,8 @@ cc::Layer* layer_ = nullptr; std::unique_ptr<MouseLockDispatcher> mouse_lock_dispatcher_; + std::unique_ptr<PepperExternalWidgetClient> widget_client_; + std::unique_ptr<blink::WebExternalWidget> blink_widget_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetFullscreenPepper); };
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index 73dd792..6351e8e 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -41,7 +41,8 @@ #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/platform/web_coalesced_input_event.h" #include "third_party/blink/public/web/web_device_emulation_params.h" -#include "third_party/blink/public/web/web_widget.h" +#include "third_party/blink/public/web/web_external_widget.h" +#include "third_party/blink/public/web/web_external_widget_client.h" #include "ui/base/mojom/cursor_type.mojom-shared.h" #include "ui/events/base_event_utils.h" #include "ui/events/blink/web_input_event_traits.h" @@ -150,15 +151,12 @@ DISALLOW_COPY_AND_ASSIGN(MockHandledEventCallback); }; -class MockWebWidget : public blink::WebWidget { +class MockWebExternalWidgetClient : public blink::WebExternalWidgetClient { public: - // WebWidget implementation. - void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override {} - blink::WebURL GetURLForDebugTrace() override { return {}; } - blink::WebHitTestResult HitTestResultAt(const gfx::Point&) override { - return {}; - } + MockWebExternalWidgetClient() = default; + // WebExternalWidgetClient implementation. + MOCK_METHOD1(DidResize, void(const gfx::Size& size)); MOCK_METHOD0(DispatchBufferedTouchEvents, blink::WebInputEventResult()); MOCK_METHOD1( HandleInputEvent, @@ -177,8 +175,10 @@ /*is_hidden=*/false, /*never_composited=*/false, mojo::NullReceiver()), - always_overscroll_(false) { - Initialize(base::NullCallback(), &mock_webwidget_, screen_info); + external_web_widget_( + blink::WebExternalWidget::Create(&mock_web_external_widget_client_, + blink::WebURL())) { + Initialize(base::NullCallback(), external_web_widget_.get(), screen_info); mock_input_handler_host_ = std::make_unique<MockWidgetInputHandlerHost>(); @@ -203,12 +203,18 @@ IPC::TestSink* sink() { return &sink_; } - MockWebWidget* mock_webwidget() { return &mock_webwidget_; } + MockWebExternalWidgetClient* mock_web_external_widget_client() { + return &mock_web_external_widget_client_; + } MockWidgetInputHandlerHost* mock_input_handler_host() { return mock_input_handler_host_.get(); } + blink::WebExternalWidget* external_web_widget() { + return external_web_widget_.get(); + } + const viz::LocalSurfaceIdAllocation& local_surface_id_allocation_from_parent() const { return local_surface_id_allocation_from_parent_; @@ -240,8 +246,9 @@ private: IPC::TestSink sink_; - bool always_overscroll_; - MockWebWidget mock_webwidget_; + bool always_overscroll_ = false; + MockWebExternalWidgetClient mock_web_external_widget_client_; + std::unique_ptr<blink::WebExternalWidget> external_web_widget_; std::unique_ptr<MockWidgetInputHandlerHost> mock_input_handler_host_; static int next_routing_id_; @@ -298,7 +305,7 @@ widget()->DidChangeCursor(cursor_info); EXPECT_EQ(widget()->sink()->message_count(), 0U); - EXPECT_CALL(*widget()->mock_webwidget(), HandleInputEvent(_)) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), HandleInputEvent(_)) .WillOnce(::testing::Return(blink::WebInputEventResult::kNotHandled)); widget()->SendInputEvent(SyntheticWebMouseEventBuilder::Build( blink::WebInputEvent::Type::kMouseLeave), @@ -314,7 +321,7 @@ TEST_F(RenderWidgetUnittest, EventOverscroll) { widget()->set_always_overscroll(true); - EXPECT_CALL(*widget()->mock_webwidget(), HandleInputEvent(_)) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), HandleInputEvent(_)) .WillRepeatedly( ::testing::Return(blink::WebInputEventResult::kNotHandled)); @@ -345,12 +352,13 @@ touch.PressPoint(10, 10); touch.touch_start_or_first_touch_move = true; - EXPECT_CALL(*widget()->mock_webwidget(), HandleInputEvent(_)) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), HandleInputEvent(_)) .Times(5) .WillRepeatedly( ::testing::Return(blink::WebInputEventResult::kNotHandled)); - EXPECT_CALL(*widget()->mock_webwidget(), DispatchBufferedTouchEvents()) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), + DispatchBufferedTouchEvents()) .Times(5) .WillRepeatedly( ::testing::Return(blink::WebInputEventResult::kNotHandled)); @@ -387,9 +395,10 @@ EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING, 2); - EXPECT_CALL(*widget()->mock_webwidget(), HandleInputEvent(_)) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), HandleInputEvent(_)) .WillOnce(::testing::Return(blink::WebInputEventResult::kNotHandled)); - EXPECT_CALL(*widget()->mock_webwidget(), DispatchBufferedTouchEvents()) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), + DispatchBufferedTouchEvents()) .WillOnce( ::testing::Return(blink::WebInputEventResult::kHandledSuppressed)); touch.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking; @@ -397,9 +406,10 @@ histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM, PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED, 1); - EXPECT_CALL(*widget()->mock_webwidget(), HandleInputEvent(_)) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), HandleInputEvent(_)) .WillOnce(::testing::Return(blink::WebInputEventResult::kNotHandled)); - EXPECT_CALL(*widget()->mock_webwidget(), DispatchBufferedTouchEvents()) + EXPECT_CALL(*widget()->mock_web_external_widget_client(), + DispatchBufferedTouchEvents()) .WillOnce( ::testing::Return(blink::WebInputEventResult::kHandledApplication)); touch.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking;
diff --git a/content/shell/browser/web_test/web_test_devtools_bindings.cc b/content/shell/browser/web_test/web_test_devtools_bindings.cc index 09869458..7ca556d 100644 --- a/content/shell/browser/web_test/web_test_devtools_bindings.cc +++ b/content/shell/browser/web_test/web_test_devtools_bindings.cc
@@ -39,14 +39,9 @@ class WebTestDevToolsBindings::SecondaryObserver : public WebContentsObserver { public: - SecondaryObserver(WebTestDevToolsBindings* bindings, bool is_startup_test) + explicit SecondaryObserver(WebTestDevToolsBindings* bindings) : WebContentsObserver(bindings->inspected_contents()), - bindings_(bindings) { - if (is_startup_test) { - bindings_->NavigateDevToolsFrontend(); - bindings_ = nullptr; - } - } + bindings_(bindings) {} // WebContentsObserver implementation. void DocumentAvailableInMainFrame() override { @@ -108,12 +103,6 @@ } void WebTestDevToolsBindings::Attach() { - DCHECK(is_startup_test_); - ShellDevToolsBindings::Attach(); - web_contents()->GetMainFrame()->ExecuteJavaScriptForTests( - base::UTF8ToUTF16("TestRunner._startupTestSetupFinished();\n//# " - "sourceURL=layout_test_devtools_bindings.cc"), - base::NullCallback()); } WebTestDevToolsBindings::WebTestDevToolsBindings( @@ -122,12 +111,7 @@ const GURL& frontend_url) : ShellDevToolsBindings(devtools_contents, inspected_contents, nullptr), frontend_url_(frontend_url) { - is_startup_test_ = - frontend_url.query().find("/startup/") != std::string::npos; - secondary_observer_ = - std::make_unique<SecondaryObserver>(this, is_startup_test_); - if (is_startup_test_) - return; + secondary_observer_ = std::make_unique<SecondaryObserver>(this); NavigationController::LoadURLParams params(GetInspectedPageURL(frontend_url)); params.transition_type = ui::PageTransitionFromInt( ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); @@ -149,8 +133,6 @@ } void WebTestDevToolsBindings::DocumentAvailableInMainFrame() { - if (is_startup_test_) - return; ShellDevToolsBindings::Attach(); }
diff --git a/content/shell/browser/web_test/web_test_devtools_bindings.h b/content/shell/browser/web_test/web_test_devtools_bindings.h index 65c8fc0..1e64234 100644 --- a/content/shell/browser/web_test/web_test_devtools_bindings.h +++ b/content/shell/browser/web_test/web_test_devtools_bindings.h
@@ -35,7 +35,6 @@ void NavigateDevToolsFrontend(); - bool is_startup_test_ = false; GURL frontend_url_; std::unique_ptr<SecondaryObserver> secondary_observer_;
diff --git a/docs/asan.md b/docs/asan.md index 293e9f82..e3fc5c5 100644 --- a/docs/asan.md +++ b/docs/asan.md
@@ -120,7 +120,7 @@ ... lots more stuff ``` -Congrats, you have a working ASan build! 🙌 +Congrats, you have a working ASan build! 🙌 ## Run chrome under ASan @@ -210,14 +210,15 @@ To run stuff without Chromium testing script (ex. ContentShell.apk, or any third party apk or binary), device setup is needed: ```shell -tools/android/asan/third_party/asan_device_setup.sh --lib -third_party/llvm-build/Release+Asserts/lib/clang/*/lib/linux/libclang_rt.asan-arm-android.so +tools/android/asan/third_party/asan_device_setup.sh \ + --lib third_party/llvm-build/Release+Asserts/lib/clang/*/lib/linux/libclang_rt.asan-arm-android.so # wait a few seconds for the device to reload ``` It only needs to be run once per device. It is safe to run it multiple times. -When this is done, the device will run ASan apks as well as normal apks without -any further setup. +Examine the output to ensure that setup was successful (you may need to run +`adb disable-verity` and restart the device first). When this is done, the +device will run ASan apks as well as normal apks without any further setup. To run command-line tools (i.e. binaries), prefix them with `asanwrapper`: ```shell
diff --git a/docs/debugging_with_crash_keys.md b/docs/debugging_with_crash_keys.md index 400f948..b45c998 100644 --- a/docs/debugging_with_crash_keys.md +++ b/docs/debugging_with_crash_keys.md
@@ -32,6 +32,14 @@ switches, active extension IDs, GPU vendor information, experiment/variations information, etc. +## Redaction + +Beware that certain on certain platforms (e.g. Android Webview) we +[sanitize the stack in the dump](https://cs.chromium.org/chromium/src/third_party/crashpad/crashpad/snapshot/sanitized/memory_snapshot_sanitized.h) +and only crash keys on a +[whitelist](https://cs.chromium.org/chromium/src/android_webview/common/crash_reporter/crash_keys.cc) +will be captured. + ## Getting Started with a Single Key-Value Pair Imagine you are investigating a crash, and you want to know the value of some
diff --git a/fuchsia/engine/context_provider_impl.cc b/fuchsia/engine/context_provider_impl.cc index 381867a..373ece5 100644 --- a/fuchsia/engine/context_provider_impl.cc +++ b/fuchsia/engine/context_provider_impl.cc
@@ -462,9 +462,6 @@ .value_or(false); if (force_protected_video_buffers) { launch_command.AppendSwitch(switches::kForceProtectedVideoOutputBuffers); - // TODO(crbug.com/1019212): We observed flicker and buffer issues when - // using accelerated canvas with protected memory. - launch_command.AppendSwitch(switches::kDisableAccelerated2dCanvas); } }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h index 6b3fceb..1573e77 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h
@@ -384,22 +384,15 @@ GLsizei* length, T* params, GLGetFunction get_call) { - // Create a scratch buffer to hold the result of the query - std::vector<T> scratch_params(bufsize); - get_call(pname, bufsize, length, scratch_params.data()); + get_call(pname, bufsize, length, params); // Update the results of the query, if needed - error::Error error = - PatchGetNumericResults(pname, *length, scratch_params.data()); + const error::Error error = PatchGetNumericResults(pname, *length, params); if (error != error::kNoError) { *length = 0; return error; } - // Copy into the destination - DCHECK(*length <= bufsize); - std::copy(scratch_params.data(), scratch_params.data() + *length, params); - return error::kNoError; }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc index 0d3a45d..bc1be8b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
@@ -1680,11 +1680,8 @@ CheckErrorCallbackState(); - // Create a scratch buffer to hold the result of the query - std::vector<GLint> scratch_params(bufsize); api()->glGetFramebufferAttachmentParameterivRobustANGLEFn( - target, updated_attachment, pname, bufsize, length, - scratch_params.data()); + target, updated_attachment, pname, bufsize, length, params); if (CheckErrorCallbackState()) { DCHECK(*length == 0); @@ -1692,17 +1689,13 @@ } // Update the results of the query, if needed - error::Error error = PatchGetFramebufferAttachmentParameter( - target, updated_attachment, pname, *length, scratch_params.data()); + const error::Error error = PatchGetFramebufferAttachmentParameter( + target, updated_attachment, pname, *length, params); if (error != error::kNoError) { *length = 0; return error; } - // Copy into the destination - DCHECK(*length < bufsize); - std::copy(scratch_params.data(), scratch_params.data() + *length, params); - return error::kNoError; }
diff --git a/gpu/command_buffer/service/shared_image_video.cc b/gpu/command_buffer/service/shared_image_video.cc index 0240c02..2dbe03b 100644 --- a/gpu/command_buffer/service/shared_image_video.cc +++ b/gpu/command_buffer/service/shared_image_video.cc
@@ -497,14 +497,24 @@ } DCHECK(context_state->GrContextIsGL()); - auto* texture = stream_texture_sii_->GetTexture(); - DCHECK(texture); + auto* texture_base = stream_texture_sii_->GetTextureBase(); + DCHECK(texture_base); - // In GL mode, create the SharedImageRepresentationGLTextureVideo + // In GL mode, create the SharedImageRepresentationGLTexture*Video // representation to use with SharedImageRepresentationVideoSkiaGL. - auto gl_representation = - std::make_unique<SharedImageRepresentationGLTextureVideo>( - manager, this, tracker, texture); + std::unique_ptr<gpu::SharedImageRepresentationGLTextureBase> + gl_representation; + if (texture_base->GetType() == gpu::TextureBase::Type::kValidated) { + gl_representation = + std::make_unique<SharedImageRepresentationGLTextureVideo>( + manager, this, tracker, gles2::Texture::CheckedCast(texture_base)); + } else { + gl_representation = + std::make_unique<SharedImageRepresentationGLTexturePassthroughVideo>( + manager, this, tracker, + gles2::TexturePassthrough::CheckedCast(texture_base)); + } + return SharedImageRepresentationSkiaGL::Create(std::move(gl_representation), std::move(context_state), manager, this, tracker);
diff --git a/gpu/command_buffer/service/stream_texture_shared_image_interface.h b/gpu/command_buffer/service/stream_texture_shared_image_interface.h index 9c048f7..e1621e5 100644 --- a/gpu/command_buffer/service/stream_texture_shared_image_interface.h +++ b/gpu/command_buffer/service/stream_texture_shared_image_interface.h
@@ -10,10 +10,7 @@ namespace gpu { class TextureOwner; - -namespace gles2 { -class Texture; -} // namespace gles2 +class TextureBase; // This class is a specialized GLImage that lets SharedImageVideo draw video // frames. @@ -32,7 +29,7 @@ // texture. virtual void UpdateAndBindTexImage() = 0; virtual bool HasTextureOwner() const = 0; - virtual gles2::Texture* GetTexture() const = 0; + virtual TextureBase* GetTextureBase() const = 0; // Notify the texture of overlay decision, When overlay promotion is true, // this also sets the bounds of where the overlay is.
diff --git a/gpu/ipc/service/stream_texture_android.cc b/gpu/ipc/service/stream_texture_android.cc index ec06b7e..be5e99b 100644 --- a/gpu/ipc/service/stream_texture_android.cc +++ b/gpu/ipc/service/stream_texture_android.cc
@@ -159,9 +159,8 @@ return !!texture_owner_; } -gles2::Texture* StreamTexture::GetTexture() const { - DCHECK(texture_owner_); - return gles2::Texture::CheckedCast(texture_owner_->GetTextureBase()); +TextureBase* StreamTexture::GetTextureBase() const { + return texture_owner_->GetTextureBase(); } void StreamTexture::NotifyOverlayPromotion(bool promotion,
diff --git a/gpu/ipc/service/stream_texture_android.h b/gpu/ipc/service/stream_texture_android.h index 4f3f91f..9f364fb 100644 --- a/gpu/ipc/service/stream_texture_android.h +++ b/gpu/ipc/service/stream_texture_android.h
@@ -93,7 +93,7 @@ bool IsUsingGpuMemory() const override; void UpdateAndBindTexImage() override; bool HasTextureOwner() const override; - gles2::Texture* GetTexture() const override; + TextureBase* GetTextureBase() const override; void NotifyOverlayPromotion(bool promotion, const gfx::Rect& bounds) override; bool RenderToOverlay() override;
diff --git a/ios/build/bots/chromium.clang/ToTiOS.json b/ios/build/bots/chromium.clang/ToTiOS.json index 297eba49..3b3712a 100644 --- a/ios/build/bots/chromium.clang/ToTiOS.json +++ b/ios/build/bots/chromium.clang/ToTiOS.json
@@ -23,119 +23,119 @@ "app": "base_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "boringssl_crypto_tests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "boringssl_ssl_tests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "components_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "crypto_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "gfx_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "google_apis_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "ios_chrome_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "ios_net_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "ios_web_inttests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "ios_web_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "ios_web_view_inttests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "net_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "skia_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "sql_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "ui_base_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" }, { "app": "url_unittests", "device type": "iPhone 6s", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "os": "13.3" } ]
diff --git a/ios/build/bots/chromium.fyi/ios-simulator-cronet.json b/ios/build/bots/chromium.fyi/ios-simulator-cronet.json index 5351e1c..dd3680dc 100644 --- a/ios/build/bots/chromium.fyi/ios-simulator-cronet.json +++ b/ios/build/bots/chromium.fyi/ios-simulator-cronet.json
@@ -28,14 +28,14 @@ "device type": "iPhone X", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "cronet_test", "device type": "iPhone X", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" } ] }
diff --git a/ios/build/bots/chromium.fyi/ios-simulator.json b/ios/build/bots/chromium.fyi/ios-simulator.json index c50b525..7d26425 100644 --- a/ios/build/bots/chromium.fyi/ios-simulator.json +++ b/ios/build/bots/chromium.fyi/ios-simulator.json
@@ -19,7 +19,7 @@ "device type": "iPhone 6s", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_chrome_integration_egtests", @@ -31,7 +31,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_chrome_integration_egtests", @@ -43,7 +43,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_chrome_integration_egtests", @@ -52,7 +52,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_chrome_signin_egtests", @@ -64,7 +64,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_chrome_smoke_egtests", @@ -73,7 +73,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_chrome_web_egtests", @@ -82,7 +82,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_web_shell_egtests", @@ -91,7 +91,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_chrome_ui_egtests", @@ -100,7 +100,7 @@ "xcode parallelization": true, "xctest": true, "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" } ] }
diff --git a/ios/build/bots/chromium.fyi/ios-webkit-tot.json b/ios/build/bots/chromium.fyi/ios-webkit-tot.json index bbb0a813..7182e112 100644 --- a/ios/build/bots/chromium.fyi/ios-webkit-tot.json +++ b/ios/build/bots/chromium.fyi/ios-webkit-tot.json
@@ -20,7 +20,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ] @@ -31,7 +31,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ] @@ -42,7 +42,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ] @@ -53,7 +53,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ] @@ -64,7 +64,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ] @@ -75,7 +75,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ] @@ -86,7 +86,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ] @@ -97,7 +97,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "test args": [ "--run-with-custom-webkit" ]
diff --git a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json index a754ee1..7e7f3cf 100644 --- a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json +++ b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
@@ -25,7 +25,7 @@ "device type": "iPhone X", "os": "13.3", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -34,7 +34,7 @@ "device type": "iPhone 7", "os": "13.3", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -43,7 +43,7 @@ "device type": "iPad (6th generation)", "os": "13.3", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -52,7 +52,7 @@ "device type": "iPhone X", "os": "12.4", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -61,7 +61,7 @@ "device type": "iPad (6th generation)", "os": "12.4", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -70,7 +70,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "eg_cq_tests.json", @@ -78,7 +78,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -87,7 +87,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -96,7 +96,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -105,7 +105,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -114,7 +114,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", @@ -122,7 +122,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", @@ -130,7 +130,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_crash_xcuitests_module", @@ -140,7 +140,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "common_tests.json", @@ -148,7 +148,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "eg_cq_tests.json", @@ -156,7 +156,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -165,7 +165,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -174,7 +174,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -183,7 +183,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -192,7 +192,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", @@ -200,7 +200,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", @@ -208,7 +208,7 @@ "os": "12.4", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" } ] }
diff --git a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json index 5bd4eda4..9668aa6 100644 --- a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json +++ b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
@@ -22,7 +22,7 @@ "include": "screen_size_dependent_tests.json", "device type": "iPhone 6s Plus", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -30,7 +30,7 @@ "include": "screen_size_dependent_tests.json", "device type": "iPhone 6s", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -38,7 +38,7 @@ "include": "common_tests.json", "device type": "iPhone 6s", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -46,7 +46,7 @@ "include": "eg_tests.json", "device type": "iPhone 7", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30, "xcode parallelization": true @@ -55,7 +55,7 @@ "include": "eg_tests.json", "device type": "iPad Air 2", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30, "xcode parallelization": true @@ -64,7 +64,7 @@ "include": "eg_tests.json", "device type": "iPhone X", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30, "xcode parallelization": true @@ -73,7 +73,7 @@ "include": "eg_cq_tests.json", "device type": "iPhone X", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30, "xcode parallelization": true @@ -82,17 +82,27 @@ "include": "eg_cq_tests.json", "device type": "iPad Air 2", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30, "xcode parallelization": true }, { + "app": "ios_crash_xcuitests_module", + "host": "ios_crash_xcuitests", + "xcode parallelization": true, + "device type": "iPhone X", + "os": "13.3", + "xcode build version": "11c29", + "host os": "Mac-10.14.6", + "pool":"chromium.tests" + }, + { "xcode parallelization": true, "include": "eg2_tests.json", "device type": "iPhone X", "os": "12.4", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -100,7 +110,7 @@ "include": "eg2_tests.json", "device type": "iPad (6th generation)", "os": "12.4", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -108,14 +118,14 @@ "device type": "iPhone X", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "eg_cq_tests.json", "device type": "iPhone X", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -123,7 +133,7 @@ "device type": "iPad Pro (12.9-inch)", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -131,7 +141,7 @@ "device type": "iPhone X", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -139,7 +149,7 @@ "device type": "iPad Air (3rd generation)", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -147,21 +157,21 @@ "device type": "iPhone 6s Plus", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", "device type": "iPhone X", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", "device type": "iPad Air 2", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" } ] }
diff --git a/ios/build/bots/chromium.mac/ios-simulator-cronet.json b/ios/build/bots/chromium.mac/ios-simulator-cronet.json index 07f7014..3992d37 100644 --- a/ios/build/bots/chromium.mac/ios-simulator-cronet.json +++ b/ios/build/bots/chromium.mac/ios-simulator-cronet.json
@@ -26,7 +26,7 @@ "device type": "iPhone 6s", "os": "12.4", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "priority": 30 }, { @@ -34,7 +34,7 @@ "device type": "iPhone 6s", "os": "13.3", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "priority": 30 }, { @@ -42,7 +42,7 @@ "device type": "iPad Air 2", "os": "12.4", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "priority": 30 }, { @@ -50,7 +50,7 @@ "device type": "iPad Air 2", "os": "13.3", "host os": "Mac-10.14.6", - "pool": "chromium.tests", + "pool": "chromium.tests.template", "priority": 30 } ]
diff --git a/ios/build/bots/chromium.mac/ios-simulator-full-configs.json b/ios/build/bots/chromium.mac/ios-simulator-full-configs.json index b502acc..fbecdfc 100644 --- a/ios/build/bots/chromium.mac/ios-simulator-full-configs.json +++ b/ios/build/bots/chromium.mac/ios-simulator-full-configs.json
@@ -23,7 +23,7 @@ "device type": "iPad Air 2", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -31,7 +31,7 @@ "device type": "iPhone X", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -39,7 +39,7 @@ "device type": "iPad Air 2", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -47,7 +47,7 @@ "device type": "iPhone 7", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -55,7 +55,7 @@ "device type": "iPad Air 2", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -63,7 +63,7 @@ "device type": "iPhone X", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -71,7 +71,7 @@ "device type": "iPhone X", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -79,7 +79,7 @@ "device type": "iPad Air 2", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 } ]
diff --git a/ios/build/bots/chromium.mac/ios-simulator-noncq.json b/ios/build/bots/chromium.mac/ios-simulator-noncq.json index f9f04ec..4adb2fa7 100644 --- a/ios/build/bots/chromium.mac/ios-simulator-noncq.json +++ b/ios/build/bots/chromium.mac/ios-simulator-noncq.json
@@ -23,7 +23,7 @@ "include": "eg2_tests.json", "device type": "iPhone X", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -31,7 +31,7 @@ "include": "eg2_tests.json", "device type": "iPhone 7", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -39,7 +39,7 @@ "include": "eg2_tests.json", "device type": "iPad (6th generation)", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -47,14 +47,14 @@ "include": "eg2_tests.json", "device type": "iPad Air 2", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { "app": "crashpad_tests", "device type": "iPhone X", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -62,7 +62,7 @@ "include": "eg2_tests.json", "device type": "iPhone X", "os": "12.4", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -70,7 +70,7 @@ "include": "eg2_tests.json", "device type": "iPhone 7", "os": "12.4", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -78,7 +78,7 @@ "include": "eg2_tests.json", "device type": "iPad (6th generation)", "os": "12.4", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -86,14 +86,14 @@ "include": "eg2_tests.json", "device type": "iPad Air 2", "os": "12.4", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { "app": "crashpad_tests", "device type": "iPhone X", "os": "12.4", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" } ]
diff --git a/ios/build/bots/chromium.mac/ios-simulator.json b/ios/build/bots/chromium.mac/ios-simulator.json index 804bbd8..33c92ce 100644 --- a/ios/build/bots/chromium.mac/ios-simulator.json +++ b/ios/build/bots/chromium.mac/ios-simulator.json
@@ -24,7 +24,7 @@ "device type": "iPhone 6s", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -32,7 +32,7 @@ "device type": "iPhone 6s", "os": "12.4", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -40,7 +40,7 @@ "device type": "iPhone 6s Plus", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -48,7 +48,7 @@ "device type": "iPhone 6s", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -56,7 +56,7 @@ "device type": "iPhone SE", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -64,7 +64,7 @@ "device type": "iPhone 6s", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -72,7 +72,7 @@ "device type": "iPad Air 2", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 }, { @@ -80,7 +80,7 @@ "device type": "iPhone 6s", "os": "13.3", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "priority": 30 } ]
diff --git a/ios/build/bots/chromium.mac/ios13-beta-simulator.json b/ios/build/bots/chromium.mac/ios13-beta-simulator.json index fd40a9c..73ebf924 100644 --- a/ios/build/bots/chromium.mac/ios13-beta-simulator.json +++ b/ios/build/bots/chromium.mac/ios13-beta-simulator.json
@@ -25,7 +25,7 @@ "device type": "iPhone X", "os": "13.3", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -34,7 +34,7 @@ "device type": "iPhone 7", "os": "13.3", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -43,7 +43,7 @@ "device type": "iPad (6th generation)", "os": "13.3", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -52,7 +52,7 @@ "device type": "iPhone X", "os": "12.4", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -61,7 +61,7 @@ "device type": "iPad (6th generation)", "os": "12.4", "xcode build version": "11c29", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6" }, { @@ -70,7 +70,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "eg_cq_tests.json", @@ -78,7 +78,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -87,7 +87,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -96,7 +96,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -105,7 +105,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "xcode parallelization": true }, { @@ -114,7 +114,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", @@ -122,7 +122,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "include": "screen_size_dependent_tests.json", @@ -130,7 +130,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" }, { "app": "ios_crash_xcuitests_module", @@ -140,7 +140,7 @@ "os": "13.3", "xcode build version": "11c29", "host os": "Mac-10.14.6", - "pool":"chromium.tests" + "pool":"chromium.tests.template" } ] }
diff --git a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json index 8d90308e..1d0c962 100644 --- a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json +++ b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
@@ -25,7 +25,7 @@ "include": "screen_size_dependent_tests.json", "device type": "iPhone 6s Plus", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -33,7 +33,7 @@ "include": "screen_size_dependent_tests.json", "device type": "iPhone 6s", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -41,7 +41,7 @@ "include": "common_tests.json", "device type": "iPhone 6s", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -49,7 +49,7 @@ "include": "eg_tests.json", "device type": "iPhone 7", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -57,7 +57,7 @@ "include": "eg_tests.json", "device type": "iPad Air 2", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -65,7 +65,7 @@ "include": "eg_tests.json", "device type": "iPhone X", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -73,7 +73,7 @@ "include": "eg_cq_tests.json", "device type": "iPhone X", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }, @@ -81,7 +81,7 @@ "include": "eg_cq_tests.json", "device type": "iPad Air 2", "os": "13.3", - "pool":"chromium.tests", + "pool":"chromium.tests.template", "host os": "Mac-10.14.6", "priority": 30 }
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json index 9024d8ac..bf77e72 100644 --- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json +++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
@@ -24,21 +24,21 @@ "device type": "iPhone 6s Plus", "os": "12.4", "host os": "Mac-10.14.6", - "pool": "chromium.tests" + "pool": "chromium.tests.template" }, { "include": "webrtc_tests.json", "device type": "iPhone 6s", "os": "12.4", "host os": "Mac-10.14.6", - "pool": "chromium.tests" + "pool": "chromium.tests.template" }, { "include": "webrtc_tests.json", "device type": "iPad Air 2", "os": "12.4", "host os": "Mac-10.14.6", - "pool": "chromium.tests" + "pool": "chromium.tests.template" } ] }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index dd69d9f..385e7e2 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -505,16 +505,15 @@ [NSURLCache setSharedURLCache:[EmptyNSURLCache emptyNSURLCache]]; } -- (void)startUpBrowserForegroundInitialization { +// This initialization must happen before any windows are created. +// Returns YES iff there's a session restore available. +- (BOOL)startUpBeforeFirstWindowCreatedAndPrepareForRestorationPostCrash: + (BOOL)isPostCrashLaunch { // Give tests a chance to prepare for testing. tests_hook::SetUpTestsIfPresent(); GetApplicationContext()->OnAppEnterForeground(); - // TODO(crbug.com/546171): Audit all the following code to see if some of it - // should move into BrowserMainParts or BrowserProcess. - NSUserDefaults* standardDefaults = [NSUserDefaults standardUserDefaults]; - // Although this duplicates some metrics_service startup logic also in // IOSChromeMain(), this call does additional work, checking for wifi-only // and setting up the required support structures. @@ -545,9 +544,8 @@ // The CrashRestoreHelper must clean up the old browser state information // before the tabModels can be created. |self.restoreHelper| must be kept // alive until the BVC receives the browser state and tab model. - BOOL postCrashLaunch = [self mustShowRestoreInfobar]; BOOL needRestoration = NO; - if (postCrashLaunch) { + if (isPostCrashLaunch) { needRestoration = [CrashRestoreHelper moveAsideSessionInformationForBrowserState:chromeBrowserState]; } @@ -590,8 +588,36 @@ ->ClearAllCachedSuggestions(); } - // This is per-window code. + return needRestoration; +} +// This initialization must only happen once there's at least one Chrome window +// open. +- (void)startUpAfterFirstWindowCreated { + CustomizeUIAppearance(); + + [self scheduleStartupCleanupTasks]; + [MetricsMediator + logLaunchMetricsWithStartupInformation:self + interfaceProvider:self.interfaceProvider]; + if (self.isColdStart) { + [ContentSuggestionsSchedulerNotifications + notifyColdStart:self.mainBrowserState]; + [ContentSuggestionsSchedulerNotifications + notifyForeground:self.mainBrowserState]; + } + + ios::GetChromeBrowserProvider()->GetOverridesProvider()->InstallOverrides(); + + [self scheduleLowPriorityStartupTasks]; + + // Now that everything is properly set up, run the tests. + tests_hook::RunTestsIfPresent(); +} + +// Starts up a single chrome window and its UI. +- (void)startUpChromeUIPostCrash:(BOOL)isPostCrashLaunch + needRestoration:(BOOL)needsRestoration { DCHECK(!self.sceneController.browserViewWrangler); DCHECK(self.sceneController.appURLLoadingService); @@ -607,7 +633,7 @@ // Only create the restoration helper if the browser state was backed up // successfully. - if (needRestoration) { + if (needsRestoration) { self.restoreHelper = [[CrashRestoreHelper alloc] initWithBrowser:self.mainBrowser]; } @@ -625,10 +651,11 @@ // Before bringing up the UI, make sure the launch mode is correct, and // check for previous crashes. - BOOL startInIncognito = [standardDefaults boolForKey:kIncognitoCurrentKey]; + BOOL startInIncognito = + [[NSUserDefaults standardUserDefaults] boolForKey:kIncognitoCurrentKey]; BOOL switchFromIncognito = startInIncognito && ![self canLaunchInIncognito]; - if (postCrashLaunch || switchFromIncognito) { + if (isPostCrashLaunch || switchFromIncognito) { [self.sceneController clearIOSSpecificIncognitoData]; if (switchFromIncognito) [self.sceneController.browserViewWrangler @@ -650,28 +677,15 @@ [self.restoreHelper showRestorePrompt]; self.restoreHelper = nil; } +} - // End of per-window code. - - CustomizeUIAppearance(); - - [self scheduleStartupCleanupTasks]; - [MetricsMediator - logLaunchMetricsWithStartupInformation:self - interfaceProvider:self.interfaceProvider]; - if (self.isColdStart) { - [ContentSuggestionsSchedulerNotifications - notifyColdStart:self.mainBrowserState]; - [ContentSuggestionsSchedulerNotifications - notifyForeground:self.mainBrowserState]; - } - - ios::GetChromeBrowserProvider()->GetOverridesProvider()->InstallOverrides(); - - [self scheduleLowPriorityStartupTasks]; - - // Now that everything is properly set up, run the tests. - tests_hook::RunTestsIfPresent(); +- (void)startUpBrowserForegroundInitialization { + BOOL postCrashLaunch = [self mustShowRestoreInfobar]; + BOOL needRestore = + [self startUpBeforeFirstWindowCreatedAndPrepareForRestorationPostCrash: + postCrashLaunch]; + [self startUpChromeUIPostCrash:postCrashLaunch needRestoration:needRestore]; + [self startUpAfterFirstWindowCreated]; } - (void)initializeBrowserState:(ChromeBrowserState*)browserState {
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 47c2a13..e02d458 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
@@ -36,6 +36,9 @@ UnifiedConsentCoordinator* unifiedConsentCoordinator; // Coordinator that handles adding a user account. @property(nonatomic, strong) SigninCoordinator* addAccountSigninCoordinator; +// Coordinator that handles the advanced settings sign-in. +@property(nonatomic, strong) + SigninCoordinator* advancedSettingsSigninCoordinator; // View controller that handles the sign-in UI. @property(nonatomic, strong) UserSigninViewController* viewController; // Mediator that handles the sign-in authentication state. @@ -109,40 +112,51 @@ - (void)interruptWithAction:(SigninCoordinatorInterruptAction)action completion:(ProceduralBlock)completion { - [self.mediator cancelAndDismissAuthenticationFlow]; - - ProceduralBlock runCompletionCallback = ^{ - [self - runCompletionCallbackWithSigninResult:SigninCoordinatorResultInterrupted - identity:self.unifiedConsentCoordinator - .selectedIdentity]; - if (completion) { - completion(); - } - }; - switch (action) { - case SigninCoordinatorInterruptActionNoDismiss: { - runCompletionCallback(); - break; - } - case SigninCoordinatorInterruptActionDismissWithAnimation: { - [self.viewController dismissViewControllerAnimated:YES - completion:runCompletionCallback]; - break; - } - case SigninCoordinatorInterruptActionDismissWithoutAnimation: { - [self.viewController dismissViewControllerAnimated:NO - completion:runCompletionCallback]; - break; - } + __weak UserSigninCoordinator* weakSelf = self; + if (self.addAccountSigninCoordinator) { + // |self.addAccountSigninCoordinator| needs to be interupted before + // interrupting |self.viewController|. + // The add account view should not be dismissed since the + // |self.viewController| will take care of that according to |action|. + [self.addAccountSigninCoordinator + interruptWithAction:SigninCoordinatorInterruptActionNoDismiss + completion:^{ + // |self.addAccountSigninCoordinator.signinCompletion| + // is expected to be called before this block. + // Therefore |weakSelf.addAccountSigninCoordinator| is + // expected to be nil. + DCHECK(!weakSelf.addAccountSigninCoordinator); + [weakSelf interruptUserSigninUIWithAction:action + completion:completion]; + }]; + return; + } else if (self.advancedSettingsSigninCoordinator) { + // |self.viewController| has already been dismissed. The interruption should + // be sent to |self.advancedSettingsSigninCoordinator|. + DCHECK(!self.viewController); + DCHECK(!self.mediator); + [self.advancedSettingsSigninCoordinator + interruptWithAction:action + completion:^{ + // |self.advancedSettingsSigninCoordinator.signinCompletion| + // is expected to be called before this block. + // Therefore |weakSelf.advancedSettingsSigninCoordinator| is + // expected to be nil. + DCHECK(!weakSelf.advancedSettingsSigninCoordinator); + if (completion) { + completion(); + } + }]; + return; } + [self interruptUserSigninUIWithAction:action completion:completion]; } #pragma mark - UnifiedConsentCoordinatorDelegate - (void)unifiedConsentCoordinatorDidTapSettingsLink: (UnifiedConsentCoordinator*)coordinator { - // TODO(crbug.com/971989): Needs implementation. + [self startSigninFlow]; } - (void)unifiedConsentCoordinatorDidReachBottom: @@ -196,20 +210,7 @@ } - (void)userSigninViewControllerDidTapOnSignin { - DCHECK(self.unifiedConsentCoordinator.selectedIdentity); - // TODO(crbug.com/971989): Pass ShouldClearDataOption from main controller. - AuthenticationFlow* authenticationFlow = [[AuthenticationFlow alloc] - initWithBrowser:self.browser - identity:self.unifiedConsentCoordinator.selectedIdentity - shouldClearData:SHOULD_CLEAR_DATA_USER_CHOICE - postSignInAction:POST_SIGNIN_ACTION_NONE - presentingViewController:self.viewController]; - authenticationFlow.dispatcher = HandlerForProtocol( - self.browser->GetCommandDispatcher(), BrowsingDataCommands); - - [self.mediator - authenticateWithIdentity:self.unifiedConsentCoordinator.selectedIdentity - authenticationFlow:authenticationFlow]; + [self startSigninFlow]; } #pragma mark - UserSigninMediatorDelegate @@ -240,21 +241,16 @@ - (void)userSigninMediatorSigninFinishedWithResult: (SigninCoordinatorResult)signinResult { + BOOL settingsWasTapped = self.unifiedConsentCoordinator.settingsLinkWasTapped; + ChromeIdentity* identity = self.unifiedConsentCoordinator.selectedIdentity; [self recordSigninMetricsWithResult:signinResult]; - __weak UserSigninCoordinator* weakSelf = self; ProceduralBlock completion = ^void() { - [weakSelf - runCompletionCallbackWithSigninResult:signinResult - identity:weakSelf.unifiedConsentCoordinator - .selectedIdentity]; + [weakSelf viewControllerDismissedWithResult:signinResult + identity:identity + settingsLinkWasTapped:settingsWasTapped]; }; - [self.viewController dismissViewControllerAnimated:YES completion:completion]; - - self.unifiedConsentCoordinator.delegate = nil; - [self.unifiedConsentCoordinator stop]; - self.unifiedConsentCoordinator = nil; } - (void)userSigninMediatorNeedPrimaryButtonUpdate { @@ -263,6 +259,43 @@ #pragma mark - Private +// Called when |self.viewController| is dismissed. If |settingsWasTapped| is +// NO, the sign-in is finished and +// |runCompletionCallbackWithSigninResult:identity:| is called. +// Otherwise, the advanced settings sign-in is presented. +- (void)viewControllerDismissedWithResult:(SigninCoordinatorResult)signinResult + identity:(ChromeIdentity*)identity + settingsLinkWasTapped:(BOOL)settingsWasTapped { + DCHECK(!self.addAccountSigninCoordinator); + DCHECK(!self.advancedSettingsSigninCoordinator); + DCHECK(self.unifiedConsentCoordinator); + DCHECK(self.mediator); + DCHECK(self.viewController); + [self.unifiedConsentCoordinator stop]; + self.unifiedConsentCoordinator = nil; + self.mediator = nil; + self.viewController = nil; + if (!settingsWasTapped) { + [self runCompletionCallbackWithSigninResult:signinResult identity:identity]; + return; + } + self.advancedSettingsSigninCoordinator = [SigninCoordinator + advancedSettingsSigninCoordinatorWithBaseViewController: + self.baseViewController + browser:self.browser]; + __weak UserSigninCoordinator* weakSelf = self; + self.advancedSettingsSigninCoordinator.signinCompletion = ^( + SigninCoordinatorResult advancedSigninResult, + ChromeIdentity* advancedSigninIdentity) { + [weakSelf + advancedSettingsSigninCoordinatorFinishedWithResult:advancedSigninResult + identity: + advancedSigninIdentity]; + }; + [self.advancedSettingsSigninCoordinator start]; +} + +// Records the metrics when the sign-in is finished. - (void)recordSigninMetricsWithResult:(SigninCoordinatorResult)signinResult { switch (signinResult) { case SigninCoordinatorResultSuccess: { @@ -282,4 +315,76 @@ } } +// Interrupts the sign-in when |self.viewController| is presented, by dismissing +// it if needed (according to |action|). Then |completion| is called. +// This method should not be called if |self.addAccountSigninCoordinator| has +// not been stopped before. +- (void)interruptUserSigninUIWithAction:(SigninCoordinatorInterruptAction)action + completion:(ProceduralBlock)completion { + DCHECK(self.viewController); + DCHECK(self.mediator); + DCHECK(self.unifiedConsentCoordinator); + DCHECK(!self.addAccountSigninCoordinator); + DCHECK(!self.advancedSettingsSigninCoordinator); + [self.mediator cancelAndDismissAuthenticationFlow]; + __weak UserSigninCoordinator* weakSelf = self; + ProceduralBlock runCompletionCallback = ^{ + [weakSelf + runCompletionCallbackWithSigninResult:SigninCoordinatorResultInterrupted + identity:self.unifiedConsentCoordinator + .selectedIdentity]; + if (completion) { + completion(); + } + }; + switch (action) { + case SigninCoordinatorInterruptActionNoDismiss: { + runCompletionCallback(); + break; + } + case SigninCoordinatorInterruptActionDismissWithAnimation: { + [self.viewController dismissViewControllerAnimated:YES + completion:runCompletionCallback]; + break; + } + case SigninCoordinatorInterruptActionDismissWithoutAnimation: { + [self.viewController dismissViewControllerAnimated:NO + completion:runCompletionCallback]; + break; + } + } +} + +// Triggers the sign-in workflow. +- (void)startSigninFlow { + DCHECK(self.unifiedConsentCoordinator); + DCHECK(self.unifiedConsentCoordinator.selectedIdentity); + // TODO(crbug.com/971989): Pass ShouldClearDataOption from main controller. + AuthenticationFlow* authenticationFlow = [[AuthenticationFlow alloc] + initWithBrowser:self.browser + identity:self.unifiedConsentCoordinator.selectedIdentity + shouldClearData:SHOULD_CLEAR_DATA_USER_CHOICE + postSignInAction:POST_SIGNIN_ACTION_NONE + presentingViewController:self.viewController]; + authenticationFlow.dispatcher = HandlerForProtocol( + self.browser->GetCommandDispatcher(), BrowsingDataCommands); + + [self.mediator + authenticateWithIdentity:self.unifiedConsentCoordinator.selectedIdentity + authenticationFlow:authenticationFlow]; +} + +// Triggers |self.signinCompletion| by calling +// |runCompletionCallbackWithSigninResult:identity:| when +// |self.advancedSettingsSigninCoordinator| is done. +- (void)advancedSettingsSigninCoordinatorFinishedWithResult: + (SigninCoordinatorResult)signinResult + identity:(ChromeIdentity*) + identity { + DCHECK(self.advancedSettingsSigninCoordinator); + [self.advancedSettingsSigninCoordinator stop]; + self.advancedSettingsSigninCoordinator = nil; + [self runCompletionCallbackWithSigninResult:signinResult identity:identity]; +} + @end
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn b/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn index 501df904..c890f32 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/BUILD.gn
@@ -17,6 +17,10 @@ "toolbar_keyboard_accessory_view.mm", "toolbar_ui_bar_button_item.h", "toolbar_ui_bar_button_item.mm", + "voice_search_keyboard_accessory_button.h", + "voice_search_keyboard_accessory_button.mm", + "voice_search_keyboard_bar_button_item.h", + "voice_search_keyboard_bar_button_item.mm", ] deps = [ "resources:keyboard_accessory_qr_scanner", @@ -42,3 +46,20 @@ [ "//ios/chrome/browser/ui/omnibox:omnibox_internal" ] libs = [ "UIKit.framework" ] } + +source_set("unit_tests") { + testonly = true + sources = [ + "voice_search_keyboard_accessory_button_unittest.mm", + "voice_search_keyboard_bar_button_item_unittest.mm", + ] + + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + ":keyboard_assist", + "//ios/chrome/browser/voice", + "//ios/chrome/browser/voice:test_support", + "//testing/gtest", + ] +}
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.mm index b94b366..2bbc50fa 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.mm +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.mm
@@ -6,7 +6,9 @@ #include "base/logging.h" #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h" +#import "ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/browser/voice/voice_search_availability.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #include "ui/base/l10n/l10n_util.h" @@ -21,12 +23,11 @@ namespace { -UIButton* ButtonWithIcon(NSString* iconName) { +void SetUpButtonWithIcon(UIButton* button, NSString* iconName) { const CGFloat kButtonShadowOpacity = 0.35; const CGFloat kButtonShadowRadius = 1.0; const CGFloat kButtonShadowVerticalOffset = 1.0; - UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setTranslatesAutoresizingMaskIntoConstraints:NO]; UIImage* icon = [UIImage imageNamed:iconName]; [button setImage:icon forState:UIControlStateNormal]; @@ -34,15 +35,18 @@ button.layer.shadowOffset = CGSizeMake(0, kButtonShadowVerticalOffset); button.layer.shadowOpacity = kButtonShadowOpacity; button.layer.shadowRadius = kButtonShadowRadius; - return button; } } // namespace NSArray<UIButton*>* ToolbarAssistiveKeyboardLeadingButtons( id<ToolbarAssistiveKeyboardDelegate> delegate) { - UIButton* voiceSearchButton = - ButtonWithIcon(@"keyboard_accessory_voice_search"); + NSMutableArray<UIButton*>* buttons = [NSMutableArray<UIButton*> array]; + + UIButton* voiceSearchButton = [[VoiceSearchKeyboardAccessoryButton alloc] + initWithVoiceSearchAvailability:std::make_unique< + VoiceSearchAvailability>()]; + SetUpButtonWithIcon(voiceSearchButton, @"keyboard_accessory_voice_search"); NSString* accessibilityLabel = l10n_util::GetNSString(IDS_IOS_KEYBOARD_ACCESSORY_VIEW_VOICE_SEARCH); voiceSearchButton.accessibilityLabel = accessibilityLabel; @@ -51,15 +55,17 @@ addTarget:delegate action:@selector(keyboardAccessoryVoiceSearchTouchUpInside:) forControlEvents:UIControlEventTouchUpInside]; + [buttons addObject:voiceSearchButton]; - UIButton* cameraButton = ButtonWithIcon(@"keyboard_accessory_qr_scanner"); + UIButton* cameraButton = [UIButton buttonWithType:UIButtonTypeCustom]; + SetUpButtonWithIcon(cameraButton, @"keyboard_accessory_qr_scanner"); [cameraButton addTarget:delegate action:@selector(keyboardAccessoryCameraSearchTouchUp) forControlEvents:UIControlEventTouchUpInside]; SetA11yLabelAndUiAutomationName( cameraButton, IDS_IOS_KEYBOARD_ACCESSORY_VIEW_QR_CODE_SEARCH, @"QR code Search"); + [buttons addObject:cameraButton]; - NSArray<UIButton*>* buttons = @[ voiceSearchButton, cameraButton ]; return buttons; }
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.mm index c522f4f..c847682e 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.mm +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.mm
@@ -8,6 +8,7 @@ #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h" #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.h" #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_ui_bar_button_item.h" +#import "ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/voice/voice_search_availability.h" #include "ios/chrome/grit/ios_strings.h" @@ -18,25 +19,27 @@ #error "This file requires ARC support." #endif +#pragma mark - Util Functions + NSArray<UIBarButtonItemGroup*>* ToolbarAssistiveKeyboardLeadingBarButtonGroups( id<ToolbarAssistiveKeyboardDelegate> delegate) { NSMutableArray<UIBarButtonItem*>* items = [NSMutableArray array]; - VoiceSearchAvailability voice_search_availability; - if (voice_search_availability.IsVoiceSearchAvailable()) { - UIImage* voiceSearchIcon = - [[UIImage imageNamed:@"keyboard_accessory_voice_search"] - imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; - UIBarButtonItem* voiceSearchItem = [[UIBarButtonItem alloc] - initWithImage:voiceSearchIcon - style:UIBarButtonItemStylePlain - target:delegate - action:@selector(keyboardAccessoryVoiceSearchTouchUpInside:)]; - NSString* accessibilityLabel = - l10n_util::GetNSString(IDS_IOS_KEYBOARD_ACCESSORY_VIEW_VOICE_SEARCH); - voiceSearchItem.accessibilityLabel = accessibilityLabel; - voiceSearchItem.accessibilityIdentifier = kVoiceSearchInputAccessoryViewID; - [items addObject:voiceSearchItem]; - } + + UIImage* voiceSearchIcon = + [[UIImage imageNamed:@"keyboard_accessory_voice_search"] + imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + UIBarButtonItem* voiceSearchItem = [[VoiceSearchKeyboardBarButtonItem alloc] + initWithImage:voiceSearchIcon + style:UIBarButtonItemStylePlain + target:delegate + action:@selector + (keyboardAccessoryVoiceSearchTouchUpInside:) + voiceSearchAvailability:std::make_unique<VoiceSearchAvailability>()]; + NSString* accessibilityLabel = + l10n_util::GetNSString(IDS_IOS_KEYBOARD_ACCESSORY_VIEW_VOICE_SEARCH); + voiceSearchItem.accessibilityLabel = accessibilityLabel; + voiceSearchItem.accessibilityIdentifier = kVoiceSearchInputAccessoryViewID; + [items addObject:voiceSearchItem]; UIImage* cameraIcon = [[UIImage imageNamed:@"keyboard_accessory_qr_scanner"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; @@ -50,9 +53,10 @@ @"QR code Search"); [items addObject:cameraItem]; - UIBarButtonItemGroup* group = - [[UIBarButtonItemGroup alloc] initWithBarButtonItems:items - representativeItem:nil]; + UIBarButtonItemGroup* group = [[UIBarButtonItemGroup alloc] + initWithBarButtonItems:@[ voiceSearchItem, cameraItem ] + representativeItem:nil]; + return @[ group ]; }
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.h new file mode 100644 index 0000000..22f9f37 --- /dev/null +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.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_TOOLBAR_KEYBOARD_ASSIST_VOICE_SEARCH_KEYBOARD_ACCESSORY_BUTTON_H_ +#define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_VOICE_SEARCH_KEYBOARD_ACCESSORY_BUTTON_H_ + +#import <UIKit/UIKit.h> +#include <memory> + +class VoiceSearchAvailability; + +// A custom button that disables itself when voice search becomes unavailable. +@interface VoiceSearchKeyboardAccessoryButton : UIButton + +- (instancetype)initWithVoiceSearchAvailability: + (std::unique_ptr<VoiceSearchAvailability>)availability + NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_VOICE_SEARCH_KEYBOARD_ACCESSORY_BUTTON_H_
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.mm new file mode 100644 index 0000000..a243117 --- /dev/null +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.mm
@@ -0,0 +1,57 @@ +// 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/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.h" + +#include "base/logging.h" +#import "ios/chrome/browser/voice/voice_search_availability.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface VoiceSearchKeyboardAccessoryButton () < + VoiceSearchAvailabilityObserver> { + std::unique_ptr<VoiceSearchAvailability> _availability; +} +@end + +@implementation VoiceSearchKeyboardAccessoryButton + +- (instancetype)initWithVoiceSearchAvailability: + (std::unique_ptr<VoiceSearchAvailability>)availability { + if (self = [super initWithFrame:CGRectZero]) { + _availability = std::move(availability); + DCHECK(_availability); + _availability->AddObserver(self); + } + return self; +} + +- (void)dealloc { + _availability->RemoveObserver(self); +} + +#pragma mark - UIView + +- (void)willMoveToSuperview:(UIView*)newSuperview { + [self updateEnabledState]; +} + +#pragma mark - VoiceSearchAvailabilityObserver + +- (void)voiceSearchAvailability:(VoiceSearchAvailability*)availability + updatedAvailability:(BOOL)available { + [self updateEnabledState]; +} + +#pragma mark - Private + +// Updates the button's enabled state according to its voice search +// availability. +- (void)updateEnabledState { + self.enabled = _availability->IsVoiceSearchAvailable(); +} + +@end
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button_unittest.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button_unittest.mm new file mode 100644 index 0000000..e4c96fe --- /dev/null +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_accessory_button_unittest.mm
@@ -0,0 +1,44 @@ +// 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/toolbar/keyboard_assist/voice_search_keyboard_accessory_button.h" + +#import "ios/chrome/browser/voice/fake_voice_search_availability.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Test fixture for VoiceSearchKeyboardAccessoryButton. +class VoiceSearchKeyboardAccessoryButtonTest : public PlatformTest { + public: + VoiceSearchKeyboardAccessoryButtonTest() + : superview_([[UIView alloc] initWithFrame:CGRectZero]) { + std::unique_ptr<FakeVoiceSearchAvailability> availability = + std::make_unique<FakeVoiceSearchAvailability>(); + availability_ = availability.get(); + availability_->SetVoiceOverEnabled(false); + availability_->SetVoiceProviderEnabled(true); + button_ = [[VoiceSearchKeyboardAccessoryButton alloc] + initWithVoiceSearchAvailability:std::move(availability)]; + [superview_ addSubview:button_]; + } + + protected: + FakeVoiceSearchAvailability* availability_ = nullptr; + UIView* superview_ = nil; + VoiceSearchKeyboardAccessoryButton* button_ = nil; +}; + +// Tests that the button is disabled when VoiceOver is enabled. +TEST_F(VoiceSearchKeyboardAccessoryButtonTest, DisableForVoiceOver) { + ASSERT_TRUE(button_.enabled); + + availability_->SetVoiceOverEnabled(true); + EXPECT_FALSE(button_.enabled); + + availability_->SetVoiceOverEnabled(false); + EXPECT_TRUE(button_.enabled); +}
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.h new file mode 100644 index 0000000..5adb7f26 --- /dev/null +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.h
@@ -0,0 +1,31 @@ +// 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_TOOLBAR_KEYBOARD_ASSIST_VOICE_SEARCH_KEYBOARD_BAR_BUTTON_ITEM_H_ +#define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_VOICE_SEARCH_KEYBOARD_BAR_BUTTON_ITEM_H_ + +#import <UIKit/UIKit.h> +#include <memory> + +class VoiceSearchAvailability; + +// A custom bar button item that disables itself when voice search is +// unavailable. +@interface VoiceSearchKeyboardBarButtonItem : UIBarButtonItem + +// Initializer for an item that disables itself when |availability| returns +// false for IsVoiceSearchAvailable(). +- (instancetype)initWithImage:(UIImage*)image + style:(UIBarButtonItemStyle)style + target:(id)target + action:(SEL)action + voiceSearchAvailability: + (std::unique_ptr<VoiceSearchAvailability>)availability + NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_VOICE_SEARCH_KEYBOARD_BAR_BUTTON_ITEM_H_
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.mm new file mode 100644 index 0000000..e2a26c4 --- /dev/null +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.mm
@@ -0,0 +1,57 @@ +// 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/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.h" + +#import "ios/chrome/browser/voice/voice_search_availability.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface VoiceSearchKeyboardBarButtonItem () < + VoiceSearchAvailabilityObserver> { + std::unique_ptr<VoiceSearchAvailability> _availability; +} +@end + +@implementation VoiceSearchKeyboardBarButtonItem + +- (instancetype)initWithImage:(UIImage*)image + style:(UIBarButtonItemStyle)style + target:(id)target + action:(SEL)action + voiceSearchAvailability: + (std::unique_ptr<VoiceSearchAvailability>)availability { + if (self = [super init]) { + self.image = image; + self.style = style; + self.target = target; + self.action = action; + _availability = std::move(availability); + _availability->AddObserver(self); + [self updateEnabledState]; + } + return self; +} + +- (void)dealloc { + _availability->RemoveObserver(self); +} + +#pragma mark - VoiceSearchAvailabilityObserver + +- (void)voiceSearchAvailability:(VoiceSearchAvailability*)availability + updatedAvailability:(BOOL)available { + [self updateEnabledState]; +} + +#pragma mark - Private + +// Updates the item's enabled state according to its voice search availability. +- (void)updateEnabledState { + self.enabled = _availability->IsVoiceSearchAvailable(); +} + +@end
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item_unittest.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item_unittest.mm new file mode 100644 index 0000000..6955d25 --- /dev/null +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item_unittest.mm
@@ -0,0 +1,45 @@ +// 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/toolbar/keyboard_assist/voice_search_keyboard_bar_button_item.h" + +#import "ios/chrome/browser/voice/fake_voice_search_availability.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Test fixture for VoiceSearchKeyboardBarButtonItem. +class VoiceSearchKeyboardBarButtonItemTest : public PlatformTest { + public: + VoiceSearchKeyboardBarButtonItemTest() { + std::unique_ptr<FakeVoiceSearchAvailability> availability = + std::make_unique<FakeVoiceSearchAvailability>(); + availability_ = availability.get(); + availability_->SetVoiceOverEnabled(false); + availability_->SetVoiceProviderEnabled(true); + item_ = [[VoiceSearchKeyboardBarButtonItem alloc] + initWithImage:nil + style:UIBarButtonItemStylePlain + target:nil + action:nil + voiceSearchAvailability:std::move(availability)]; + } + + protected: + FakeVoiceSearchAvailability* availability_ = nullptr; + VoiceSearchKeyboardBarButtonItem* item_ = nil; +}; + +// Tests that the item is disabled when VoiceOver is enabled. +TEST_F(VoiceSearchKeyboardBarButtonItemTest, DisableForVoiceOver) { + ASSERT_TRUE(item_.enabled); + + availability_->SetVoiceOverEnabled(true); + EXPECT_FALSE(item_.enabled); + + availability_->SetVoiceOverEnabled(false); + EXPECT_TRUE(item_.enabled); +}
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 5f90cf0..8d573c2 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -295,6 +295,7 @@ "//ios/chrome/browser/ui/tabs:unit_tests", "//ios/chrome/browser/ui/toolbar:unit_tests", "//ios/chrome/browser/ui/toolbar/fullscreen:unit_tests", + "//ios/chrome/browser/ui/toolbar/keyboard_assist:unit_tests", "//ios/chrome/browser/ui/toolbar_container:unit_tests", "//ios/chrome/browser/ui/translate:unit_tests", "//ios/chrome/browser/ui/util:unit_tests",
diff --git a/media/audio/pulse/pulse_input.cc b/media/audio/pulse/pulse_input.cc index ed42cdb..3f0c9d7 100644 --- a/media/audio/pulse/pulse_input.cc +++ b/media/audio/pulse/pulse_input.cc
@@ -15,22 +15,6 @@ 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; @@ -62,7 +46,7 @@ DCHECK(mainloop); DCHECK(context); CHECK(params_.IsValid()); - SendLogMessage(log_callback_, "%s({device_id=%s}, {params=[%s]})", __func__, + SendLogMessage("%s({device_id=%s}, {params=[%s]})", __func__, device_name.c_str(), params.AsHumanReadableString().c_str()); } @@ -74,19 +58,17 @@ bool PulseAudioInputStream::Open() { DCHECK(thread_checker_.CalledOnValidThread()); - SendLogMessage(log_callback_, "%s()", __func__); + SendLogMessage("%s()", __func__); if (device_name_ == AudioDeviceDescription::kDefaultDeviceId && audio_manager_->DefaultSourceIsMonitor()) { - SendLogMessage(log_callback_, "%s => (ERROR: can't open monitor device)", - __func__); + SendLogMessage("%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__); + SendLogMessage("%s => (ERROR: failed to open PA stream)", __func__); return false; } @@ -99,7 +81,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(callback); DCHECK(handle_); - SendLogMessage(log_callback_, "%s()", __func__); + SendLogMessage("%s()", __func__); // AGC needs to be started out of the lock. StartAgc(); @@ -126,7 +108,7 @@ void PulseAudioInputStream::Stop() { DCHECK(thread_checker_.CalledOnValidThread()); - SendLogMessage(log_callback_, "%s()", __func__); + SendLogMessage("%s()", __func__); AutoPulseLock auto_lock(pa_mainloop_); if (!stream_started_) return; @@ -160,7 +142,7 @@ void PulseAudioInputStream::Close() { DCHECK(thread_checker_.CalledOnValidThread()); - SendLogMessage(log_callback_, "%s()", __func__); + SendLogMessage("%s()", __func__); { AutoPulseLock auto_lock(pa_mainloop_); if (handle_) { @@ -192,7 +174,7 @@ AutoPulseLock auto_lock(pa_mainloop_); if (!handle_) return; - SendLogMessage(log_callback_, "%s({volume=%.2f})", __func__, volume); + SendLogMessage("%s({volume=%.2f})", __func__, volume); size_t index = pa_stream_get_device_index(handle_); pa_operation* operation = nullptr; @@ -204,8 +186,7 @@ if (!WaitForOperationCompletion(pa_mainloop_, operation, pa_context_, handle_) || !channels_) { - SendLogMessage(log_callback_, - "%s => (WARNING: failed to read number of channels)", + SendLogMessage("%s => (WARNING: failed to read number of channels)", __func__); return; } @@ -252,6 +233,15 @@ // Not supported. Do nothing. } +void PulseAudioInputStream::SendLogMessage(const char* format, ...) { + if (log_callback_.is_null()) + return; + va_list args; + va_start(args, format); + log_callback_.Run("PAIS::" + base::StringPrintV(format, args)); + va_end(args); +} + // static, used by pa_stream_set_read_callback. void PulseAudioInputStream::ReadCallback(pa_stream* handle, size_t length,
diff --git a/media/audio/pulse/pulse_input.h b/media/audio/pulse/pulse_input.h index 6287ec8..2fe4b77 100644 --- a/media/audio/pulse/pulse_input.h +++ b/media/audio/pulse/pulse_input.h
@@ -45,6 +45,9 @@ void SetOutputDeviceForAec(const std::string& output_device_id) override; private: + // Helper method used for sending native logs to the registered client. + void SendLogMessage(const char* format, ...) PRINTF_FORMAT(2, 3); + // PulseAudio Callbacks. static void ReadCallback(pa_stream* handle, size_t length, void* user_data); static void StreamNotifyCallback(pa_stream* stream, void* user_data);
diff --git a/media/audio/pulse/pulse_output.cc b/media/audio/pulse/pulse_output.cc index 40a390c..cdcda5f 100644 --- a/media/audio/pulse/pulse_output.cc +++ b/media/audio/pulse/pulse_output.cc
@@ -18,22 +18,6 @@ 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("PAOS::" + base::StringPrintV(format, args)); - va_end(args); -} - -} // namespace - using pulse::AutoPulseLock; using pulse::WaitForOperationCompletion; @@ -78,10 +62,8 @@ source_callback_(nullptr), buffer_size_(params_.GetBytesPerBuffer(kSampleFormatF32)) { CHECK(params_.IsValid()); - SendLogMessage( - log_callback_, - "PulseAudioOutputStream({device_id=%s}, {params=[%s]} [this=%p])", - device_id.c_str(), params.AsHumanReadableString().c_str(), this); + SendLogMessage("%s({device_id=%s}, {params=[%s]})", __func__, + device_id.c_str(), params.AsHumanReadableString().c_str()); audio_bus_ = AudioBus::Create(params_); } @@ -95,13 +77,13 @@ bool PulseAudioOutputStream::Open() { DCHECK(thread_checker_.CalledOnValidThread()); - SendLogMessage(log_callback_, "Open([this=%p])", this); + SendLogMessage("%s()", __func__); bool result = pulse::CreateOutputStream( &pa_mainloop_, &pa_context_, &pa_stream_, params_, device_id_, AudioManager::GetGlobalAppName(), &StreamNotifyCallback, &StreamRequestCallback, this); if (!result) { - SendLogMessage(log_callback_, "Open => (ERROR: failed to open PA stream)"); + SendLogMessage("%s => (ERROR: failed to open PA stream)", __func__); } return result; } @@ -147,7 +129,7 @@ void PulseAudioOutputStream::Close() { DCHECK(thread_checker_.CalledOnValidThread()); - SendLogMessage(log_callback_, "Close([this=%p])", this); + SendLogMessage("%s()", __func__); Reset(); @@ -160,6 +142,16 @@ // sufficient to simply always flush upon Start(). void PulseAudioOutputStream::Flush() {} +void PulseAudioOutputStream::SendLogMessage(const char* format, ...) { + if (log_callback_.is_null()) + return; + va_list args; + va_start(args, format); + log_callback_.Run("PAOS::" + base::StringPrintV(format, args) + + base::StringPrintf(" [this=%p]", this)); + va_end(args); +} + void PulseAudioOutputStream::FulfillWriteRequest(size_t requested_bytes) { int bytes_remaining = requested_bytes; while (bytes_remaining > 0) { @@ -231,7 +223,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); CHECK(callback); CHECK(pa_stream_); - SendLogMessage(log_callback_, "Start([this=%p])", this); + SendLogMessage("%s()", __func__); AutoPulseLock auto_lock(pa_mainloop_); @@ -255,7 +247,7 @@ void PulseAudioOutputStream::Stop() { DCHECK(thread_checker_.CalledOnValidThread()); - SendLogMessage(log_callback_, "Stop([this=%p])", this); + SendLogMessage("%s()", __func__); // Cork (pause) the stream. Waiting for the main loop lock will ensure // outstanding callbacks have completed.
diff --git a/media/audio/pulse/pulse_output.h b/media/audio/pulse/pulse_output.h index 59ce6168..6a85b26 100644 --- a/media/audio/pulse/pulse_output.h +++ b/media/audio/pulse/pulse_output.h
@@ -57,6 +57,9 @@ void GetVolume(double* volume) override; private: + // Helper method used for sending native logs to the registered client. + void SendLogMessage(const char* format, ...) PRINTF_FORMAT(2, 3); + // Called by PulseAudio when |pa_stream_| change state. If an unexpected // failure state change happens and |source_callback_| is set // this method will forward the error via OnError().
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc index b8da03b9..5282739 100644 --- a/media/audio/win/audio_low_latency_output_win.cc +++ b/media/audio/win/audio_low_latency_output_win.cc
@@ -6,6 +6,7 @@ #include <Functiondiscoverykeys_devpkey.h> #include <audiopolicy.h> +#include <inttypes.h> #include <objbase.h> #include <climits> @@ -455,7 +456,9 @@ return; va_list args; va_start(args, format); - log_callback_.Run("WAOS::" + base::StringPrintV(format, args)); + log_callback_.Run("WAOS::" + base::StringPrintV(format, args) + + base::StringPrintf(" [this=0x%" PRIXPTR "]", + reinterpret_cast<uintptr_t>(this))); va_end(args); }
diff --git a/media/gpu/android/codec_image.cc b/media/gpu/android/codec_image.cc index d57cea86..187fb24 100644 --- a/media/gpu/android/codec_image.cc +++ b/media/gpu/android/codec_image.cc
@@ -234,9 +234,8 @@ return !!texture_owner(); } -gpu::gles2::Texture* CodecImage::GetTexture() const { - DCHECK(texture_owner()); - return gpu::gles2::Texture::CheckedCast(texture_owner()->GetTextureBase()); +gpu::TextureBase* CodecImage::GetTextureBase() const { + return texture_owner()->GetTextureBase(); } bool CodecImage::RenderToFrontBuffer() {
diff --git a/media/gpu/android/codec_image.h b/media/gpu/android/codec_image.h index fe4ed50c..6186182 100644 --- a/media/gpu/android/codec_image.h +++ b/media/gpu/android/codec_image.h
@@ -115,7 +115,7 @@ bool IsUsingGpuMemory() const override; void UpdateAndBindTexImage() override; bool HasTextureOwner() const override; - gpu::gles2::Texture* GetTexture() const override; + gpu::TextureBase* GetTextureBase() const override; void NotifyOverlayPromotion(bool promotion, const gfx::Rect& bounds) override; // Renders this image to the overlay. Returns true if the buffer is in the // overlay front buffer. Returns false if the buffer was invalidated.
diff --git a/net/base/features.cc b/net/base/features.cc index 196a509f..2e41e84 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -101,8 +101,7 @@ #endif const base::Feature kAppendFrameOriginToNetworkIsolationKey{ - "AppendFrameOriginToNetworkIsolationKey", - base::FEATURE_DISABLED_BY_DEFAULT}; + "AppendFrameOriginToNetworkIsolationKey", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kUseRegistrableDomainInNetworkIsolationKey{ "UseRegistrableDomainInNetworkIsolationKey",
diff --git a/net/base/network_change_notifier_win.cc b/net/base/network_change_notifier_win.cc index c453bda..099ead373 100644 --- a/net/base/network_change_notifier_win.cc +++ b/net/base/network_change_notifier_win.cc
@@ -273,8 +273,8 @@ // that interval. if (sequential_failures_ > 0) { RecomputeCurrentConnectionTypeOnBlockingSequence( - base::Bind(&NetworkChangeNotifierWin::NotifyObservers, - weak_factory_.GetWeakPtr())); + base::BindOnce(&NetworkChangeNotifierWin::NotifyObservers, + weak_factory_.GetWeakPtr())); } if (sequential_failures_ < 2000) {
diff --git a/net/base/network_isolation_key_unittest.cc b/net/base/network_isolation_key_unittest.cc index 842822e..a595bed 100644 --- a/net/base/network_isolation_key_unittest.cc +++ b/net/base/network_isolation_key_unittest.cc
@@ -152,33 +152,28 @@ const url::Origin kJunkOrigin = url::Origin::Create(GURL("data:text/html,junk")); - // Convert empty key to value and back, expecting the same value. - NetworkIsolationKey no_frame_origin_key; - base::Value no_frame_origin_value; - ASSERT_TRUE(no_frame_origin_key.ToValue(&no_frame_origin_value)); + for (bool use_frame_origins : {true, false}) { + SCOPED_TRACE(use_frame_origins); + base::test::ScopedFeatureList feature_list; + if (use_frame_origins) { + feature_list.InitAndEnableFeature( + features::kAppendFrameOriginToNetworkIsolationKey); + } else { + feature_list.InitAndDisableFeature( + features::kAppendFrameOriginToNetworkIsolationKey); + } - // Fill initial value with junk data, to make sure it's overwritten. - NetworkIsolationKey out_key(kJunkOrigin, kJunkOrigin); - EXPECT_TRUE(NetworkIsolationKey::FromValue(no_frame_origin_value, &out_key)); - EXPECT_EQ(no_frame_origin_key, out_key); + // Convert empty key to value and back, expecting the same value. + NetworkIsolationKey no_frame_origin_key; + base::Value no_frame_origin_value; + ASSERT_TRUE(no_frame_origin_key.ToValue(&no_frame_origin_value)); - // Perform same checks when frame origins are enabled. - - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kAppendFrameOriginToNetworkIsolationKey); - - NetworkIsolationKey frame_origin_key; - base::Value frame_origin_value; - ASSERT_TRUE(frame_origin_key.ToValue(&frame_origin_value)); - - // Fill initial value with junk data, to make sure it's overwritten. - out_key = NetworkIsolationKey(kJunkOrigin, kJunkOrigin); - EXPECT_TRUE(NetworkIsolationKey::FromValue(frame_origin_value, &out_key)); - EXPECT_EQ(frame_origin_key, out_key); - - // The Values should also be the same in both cases. - EXPECT_EQ(no_frame_origin_key, frame_origin_key); + // Fill initial value with junk data, to make sure it's overwritten. + NetworkIsolationKey out_key(kJunkOrigin, kJunkOrigin); + EXPECT_TRUE( + NetworkIsolationKey::FromValue(no_frame_origin_value, &out_key)); + EXPECT_EQ(no_frame_origin_key, out_key); + } } TEST(NetworkIsolationKeyTest, ValueRoundTripNoFrameOrigin) { @@ -236,12 +231,15 @@ const url::Origin kTransientOrigin = url::Origin::Create(GURL("data:text/html,transient")); - for (bool use_frame_origins : {false, true}) { + for (bool use_frame_origins : {true, false}) { SCOPED_TRACE(use_frame_origins); base::test::ScopedFeatureList feature_list; if (use_frame_origins) { feature_list.InitAndEnableFeature( features::kAppendFrameOriginToNetworkIsolationKey); + } else { + feature_list.InitAndDisableFeature( + features::kAppendFrameOriginToNetworkIsolationKey); } NetworkIsolationKey key1(kTransientOrigin, kTransientOrigin); @@ -273,12 +271,15 @@ base::Value(std::move(too_many_origins_list)), }; - for (bool use_frame_origins : {false, true}) { + for (bool use_frame_origins : {true, false}) { SCOPED_TRACE(use_frame_origins); base::test::ScopedFeatureList feature_list; if (use_frame_origins) { feature_list.InitAndEnableFeature( features::kAppendFrameOriginToNetworkIsolationKey); + } else { + feature_list.InitAndDisableFeature( + features::kAppendFrameOriginToNetworkIsolationKey); } for (const auto& test_case : kTestCases) { @@ -495,8 +496,11 @@ // host when using a non-standard scheme. TEST(NetworkIsolationKeyTest, UseRegistrableDomainWithNonStandardScheme) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kUseRegistrableDomainInNetworkIsolationKey); + feature_list.InitWithFeatures( + // enabled_features + {features::kUseRegistrableDomainInNetworkIsolationKey}, + // disabled_features + {features::kAppendFrameOriginToNetworkIsolationKey}); // Have to register the scheme, or url::Origin::Create() will return an opaque // origin. @@ -528,9 +532,10 @@ } TEST(NetworkIsolationKeyTest, CreateTransient) { - for (bool append_frame_origin : {false, true}) { + for (bool use_frame_origins : {true, false}) { + SCOPED_TRACE(use_frame_origins); base::test::ScopedFeatureList feature_list; - if (append_frame_origin) { + if (use_frame_origins) { feature_list.InitAndEnableFeature( features::kAppendFrameOriginToNetworkIsolationKey); } else {
diff --git a/net/disk_cache/simple/simple_test_util.h b/net/disk_cache/simple/simple_test_util.h index 79a6468..36af9285 100644 --- a/net/disk_cache/simple/simple_test_util.h +++ b/net/disk_cache/simple/simple_test_util.h
@@ -24,7 +24,7 @@ public: static const size_t size = Size; - ImmutableArray(const base::Callback<T (size_t index)>& initializer) { + ImmutableArray(const base::RepeatingCallback<T(size_t index)>& initializer) { for (size_t i = 0; i < size; ++i) data_[i] = initializer.Run(i); }
diff --git a/net/http/structured_headers_unittest.cc b/net/http/structured_headers_unittest.cc index e593865..afb77ab 100644 --- a/net/http/structured_headers_unittest.cc +++ b/net/http/structured_headers_unittest.cc
@@ -620,8 +620,50 @@ "a=3, b=2"}, {"numeric key dictionary", "a=1,1b=2,a=1", base::nullopt}, {"uppercase key dictionary", "a=1,B=2,a=1", base::nullopt}, - {"bad key dictionary", "a=1,b!=2,a=1", base::nullopt}}; - + {"bad key dictionary", "a=1,b!=2,a=1", base::nullopt}, + // Paramaterised dictionary tests + {"basic parameterised dict", + "abc=123;a=1;b=2, def=456, ghi=789;q=9;r=\"+w\"", + {Dictionary{ + {{"abc", {Integer(123), {Param("a", 1), Param("b", 2)}}}, + {"def", {Integer(456), {}}}, + {"ghi", {Integer(789), {Param("q", 9), Param("r", "+w")}}}}}}}, + {"single item parameterised dict", + "a=b; q=1.0", + {Dictionary{{{"a", {Token("b"), {DoubleParam("q", 1.0)}}}}}}, + "a=b;q=1.0"}, + {"list item parameterised dictionary", + "a=(1 2); q=1.0", + {Dictionary{{{"a", + {{{Integer(1L), {}}, {Integer(2L), {}}}, + {DoubleParam("q", 1.0)}}}}}}, + "a=(1 2);q=1.0"}, + {"missing parameter value parameterised dict", + "a=3;c;d=5", + {Dictionary{{{"a", {Integer(3), {Param("c"), Param("d", 5)}}}}}}}, + {"terminal missing parameter value parameterised dict", + "a=3;c=5;d", + {Dictionary{{{"a", {Integer(3), {Param("c", 5), Param("d")}}}}}}}, + {"no whitespace parameterised dict", + "a=b;c=1,d=e;f=2", + {Dictionary{{{"a", {Token("b"), {Param("c", 1)}}}, + {"d", {Token("e"), {Param("f", 2)}}}}}}, + "a=b;c=1, d=e;f=2"}, + {"whitespace before = parameterised dict", "a=b;q =0.5", base::nullopt}, + {"whitespace after = parameterised dict", "a=b;q= 0.5", base::nullopt}, + {"whitespace before ; parameterised dict", "a=b ;q=0.5", base::nullopt}, + {"whitespace after ; parameterised dict", + "a=b; q=0.5", + {Dictionary{{{"a", {Token("b"), {DoubleParam("q", 0.5)}}}}}}, + "a=b;q=0.5"}, + {"extra whitespace parameterised dict", + "a=b; c=1 , d=e; f=2; g=3", + {Dictionary{{{"a", {Token("b"), {Param("c", 1)}}}, + {"d", {Token("e"), {Param("f", 2), Param("g", 3)}}}}}}, + "a=b;c=1, d=e;f=2;g=3"}, + {"trailing comma parameterised list", "a=b; q=1.0,", base::nullopt}, + {"empty item parameterised list", "a=b; q=1.0,,c=d", base::nullopt}, +}; } // namespace TEST(StructuredHeaderTest, ParseBareItem) {
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc index 6a4a8b45..df2bd22 100644 --- a/net/nqe/network_quality_estimator.cc +++ b/net/nqe/network_quality_estimator.cc
@@ -196,16 +196,18 @@ // (i.e., base::ThreadTaskRunnerHandle::Get()). // Use WeakPtr() to avoid crashes where the socket watcher is destroyed // after |this| is destroyed. - base::Bind(&NetworkQualityEstimator::OnUpdatedTransportRTTAvailable, - weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating( + &NetworkQualityEstimator::OnUpdatedTransportRTTAvailable, + weak_ptr_factory_.GetWeakPtr()), // ShouldSocketWatcherNotifyRTT() below is called by only the socket // watchers that live on the same thread as the current thread // (i.e., base::ThreadTaskRunnerHandle::Get()). Also, network quality // estimator is destroyed after network contexts and URLRequestContexts. // It's safe to use base::Unretained() below since the socket watcher // (owned by sockets) would be destroyed before |this|. - base::Bind(&NetworkQualityEstimator::ShouldSocketWatcherNotifyRTT, - base::Unretained(this)), + base::BindRepeating( + &NetworkQualityEstimator::ShouldSocketWatcherNotifyRTT, + base::Unretained(this)), tick_clock_)); GatherEstimatesForNextConnectionType();
diff --git a/net/nqe/socket_watcher.h b/net/nqe/socket_watcher.h index a4bf0415..7fe97c9 100644 --- a/net/nqe/socket_watcher.h +++ b/net/nqe/socket_watcher.h
@@ -30,12 +30,13 @@ namespace { -typedef base::Callback<void(SocketPerformanceWatcherFactory::Protocol protocol, - const base::TimeDelta& rtt, - const base::Optional<nqe::internal::IPHash>& host)> +typedef base::RepeatingCallback<void( + SocketPerformanceWatcherFactory::Protocol protocol, + const base::TimeDelta& rtt, + const base::Optional<nqe::internal::IPHash>& host)> OnUpdatedRTTAvailableCallback; -typedef base::Callback<bool(base::TimeTicks)> ShouldNotifyRTTCallback; +typedef base::RepeatingCallback<bool(base::TimeTicks)> ShouldNotifyRTTCallback; } // namespace
diff --git a/net/nqe/socket_watcher_factory.h b/net/nqe/socket_watcher_factory.h index 6753f3a..769a7b12 100644 --- a/net/nqe/socket_watcher_factory.h +++ b/net/nqe/socket_watcher_factory.h
@@ -27,12 +27,13 @@ namespace { -typedef base::Callback<void(SocketPerformanceWatcherFactory::Protocol protocol, - const base::TimeDelta& rtt, - const base::Optional<nqe::internal::IPHash>& host)> +typedef base::RepeatingCallback<void( + SocketPerformanceWatcherFactory::Protocol protocol, + const base::TimeDelta& rtt, + const base::Optional<nqe::internal::IPHash>& host)> OnUpdatedRTTAvailableCallback; -typedef base::Callback<bool(base::TimeTicks)> ShouldNotifyRTTCallback; +typedef base::RepeatingCallback<bool(base::TimeTicks)> ShouldNotifyRTTCallback; } // namespace
diff --git a/net/nqe/socket_watcher_unittest.cc b/net/nqe/socket_watcher_unittest.cc index 8831ae1..b3d592f2 100644 --- a/net/nqe/socket_watcher_unittest.cc +++ b/net/nqe/socket_watcher_unittest.cc
@@ -114,8 +114,9 @@ SocketWatcher socket_watcher( SocketPerformanceWatcherFactory::PROTOCOL_TCP, address_list, base::TimeDelta::FromMilliseconds(2000), false, - base::ThreadTaskRunnerHandle::Get(), base::Bind(OnUpdatedRTTAvailable), - base::Bind(ShouldNotifyRTTCallback), &tick_clock); + base::ThreadTaskRunnerHandle::Get(), + base::BindRepeating(OnUpdatedRTTAvailable), + base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10)); @@ -158,8 +159,8 @@ SocketPerformanceWatcherFactory::PROTOCOL_QUIC, address_list, base::TimeDelta::FromMilliseconds(2000), false, base::ThreadTaskRunnerHandle::Get(), - base::Bind(OnUpdatedRTTAvailableStoreParams), - base::Bind(ShouldNotifyRTTCallback), &tick_clock); + base::BindRepeating(OnUpdatedRTTAvailableStoreParams), + base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10)); @@ -212,8 +213,9 @@ SocketWatcher socket_watcher( SocketPerformanceWatcherFactory::PROTOCOL_TCP, address_list, base::TimeDelta::FromMilliseconds(2000), false, - base::ThreadTaskRunnerHandle::Get(), base::Bind(OnUpdatedRTTAvailable), - base::Bind(ShouldNotifyRTTCallback), &tick_clock); + base::ThreadTaskRunnerHandle::Get(), + base::BindRepeating(OnUpdatedRTTAvailable), + base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock); EXPECT_EQ(test.expect_should_notify_rtt, socket_watcher.ShouldNotifyUpdatedRTT()); @@ -251,8 +253,8 @@ SocketPerformanceWatcherFactory::PROTOCOL_TCP, address_list, base::TimeDelta::FromMilliseconds(2000), false, base::ThreadTaskRunnerHandle::Get(), - base::Bind(OnUpdatedRTTAvailableStoreParams), - base::Bind(ShouldNotifyRTTCallback), &tick_clock); + base::BindRepeating(OnUpdatedRTTAvailableStoreParams), + base::BindRepeating(ShouldNotifyRTTCallback), &tick_clock); EXPECT_TRUE(socket_watcher.ShouldNotifyUpdatedRTT()); socket_watcher.OnUpdatedRTTAvailable(base::TimeDelta::FromSeconds(10)); base::RunLoop().RunUntilIdle();
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc index 4b67446..dbc2aa96 100644 --- a/net/socket/tcp_socket_win.cc +++ b/net/socket/tcp_socket_win.cc
@@ -489,9 +489,9 @@ DCHECK(!core_->read_iobuffer_.get()); // base::Unretained() is safe because RetryRead() won't be called when |this| // is gone. - int rv = - ReadIfReady(buf, buf_len, - base::Bind(&TCPSocketWin::RetryRead, base::Unretained(this))); + int rv = ReadIfReady( + buf, buf_len, + base::BindOnce(&TCPSocketWin::RetryRead, base::Unretained(this))); if (rv != ERR_IO_PENDING) return rv; read_callback_ = std::move(callback); @@ -932,7 +932,7 @@ // |this| is gone. rv = ReadIfReady( core_->read_iobuffer_.get(), core_->read_buffer_length_, - base::Bind(&TCPSocketWin::RetryRead, base::Unretained(this))); + base::BindOnce(&TCPSocketWin::RetryRead, base::Unretained(this))); if (rv == ERR_IO_PENDING) return; }
diff --git a/net/socket/transport_client_socket_pool_test_util.cc b/net/socket/transport_client_socket_pool_test_util.cc index ba52c32..1815967 100644 --- a/net/socket/transport_client_socket_pool_test_util.cc +++ b/net/socket/transport_client_socket_pool_test_util.cc
@@ -199,9 +199,9 @@ // Call this method to get a closure which will trigger the connect callback // when called. The closure can be called even after the socket is deleted; it // will safely do nothing. - base::Closure GetConnectCallback() { - return base::Bind(&MockTriggerableClientSocket::DoCallback, - weak_factory_.GetWeakPtr()); + base::OnceClosure GetConnectCallback() { + return base::BindOnce(&MockTriggerableClientSocket::DoCallback, + weak_factory_.GetWeakPtr()); } static std::unique_ptr<TransportClientSocket> MakeMockPendingClientSocket( @@ -432,7 +432,7 @@ // don't need to worry about atomicity because this code is // single-threaded. if (!run_loop_quit_closure_.is_null()) - run_loop_quit_closure_.Run(); + std::move(run_loop_quit_closure_).Run(); return std::move(rv); } default: @@ -476,7 +476,7 @@ client_socket_index_max_ = num_types; } -base::Closure +base::OnceClosure MockTransportClientSocketFactory::WaitForTriggerableSocketCreation() { while (triggerable_sockets_.empty()) { base::RunLoop run_loop; @@ -484,7 +484,7 @@ run_loop.Run(); run_loop_quit_closure_.Reset(); } - base::Closure trigger = triggerable_sockets_.front(); + base::OnceClosure trigger = std::move(triggerable_sockets_.front()); triggerable_sockets_.pop(); return trigger; }
diff --git a/net/socket/transport_client_socket_pool_test_util.h b/net/socket/transport_client_socket_pool_test_util.h index a10aea1..e545f7d 100644 --- a/net/socket/transport_client_socket_pool_test_util.h +++ b/net/socket/transport_client_socket_pool_test_util.h
@@ -122,7 +122,7 @@ // have been created yet, wait for one to be created before returning the // Closure. This method should be called the same number of times as // MOCK_TRIGGERABLE_CLIENT_SOCKETs are created in the test. - base::Closure WaitForTriggerableSocketCreation(); + base::OnceClosure WaitForTriggerableSocketCreation(); private: NetLog* net_log_; @@ -132,8 +132,8 @@ int client_socket_index_; int client_socket_index_max_; base::TimeDelta delay_; - base::queue<base::Closure> triggerable_sockets_; - base::Closure run_loop_quit_closure_; + base::queue<base::OnceClosure> triggerable_sockets_; + base::OnceClosure run_loop_quit_closure_; DISALLOW_COPY_AND_ASSIGN(MockTransportClientSocketFactory); };
diff --git a/net/socket/websocket_transport_client_socket_pool_unittest.cc b/net/socket/websocket_transport_client_socket_pool_unittest.cc index 24ed21d..14661598 100644 --- a/net/socket/websocket_transport_client_socket_pool_unittest.cc +++ b/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -58,9 +58,9 @@ // RunLoop doesn't support this natively but it is easy to emulate. void RunLoopForTimePeriod(base::TimeDelta period) { base::RunLoop run_loop; - base::Closure quit_closure(run_loop.QuitClosure()); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, quit_closure, - period); + base::OnceClosure quit_closure(run_loop.QuitClosure()); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, std::move(quit_closure), period); run_loop.Run(); } @@ -795,13 +795,13 @@ EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); ASSERT_FALSE(handle.socket()); - base::Closure ipv6_connect_trigger = + base::OnceClosure ipv6_connect_trigger = client_socket_factory_.WaitForTriggerableSocketCreation(); - base::Closure ipv4_connect_trigger = + base::OnceClosure ipv4_connect_trigger = client_socket_factory_.WaitForTriggerableSocketCreation(); - ipv4_connect_trigger.Run(); - ipv6_connect_trigger.Run(); + std::move(ipv4_connect_trigger).Run(); + std::move(ipv6_connect_trigger).Run(); EXPECT_THAT(callback.WaitForResult(), IsOk()); ASSERT_TRUE(handle.socket()); @@ -1096,10 +1096,10 @@ EXPECT_THAT(StartRequest(kDefaultPriority), IsError(ERR_IO_PENDING)); - base::Closure connect_trigger = + base::OnceClosure connect_trigger = client_socket_factory_.WaitForTriggerableSocketCreation(); - connect_trigger.Run(); // Calls InvokeUserCallbackLater() + std::move(connect_trigger).Run(); // Calls InvokeUserCallbackLater() request(0)->handle()->Reset(); // calls CancelRequest()
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 4f6c5ff..0f56bcd 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc
@@ -66,7 +66,7 @@ protected: // A function that takes a SpdyStream and the number of bytes which // will unstall the next frame completely. - typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32_t)> + typedef base::OnceCallback<void(const base::WeakPtr<SpdyStream>&, int32_t)> UnstallFunction; SpdyStreamTest() @@ -88,10 +88,9 @@ void TearDown() override { base::RunLoop().RunUntilIdle(); } void RunResumeAfterUnstallRequestResponseTest( - const UnstallFunction& unstall_function); + UnstallFunction unstall_function); - void RunResumeAfterUnstallBidirectionalTest( - const UnstallFunction& unstall_function); + void RunResumeAfterUnstallBidirectionalTest(UnstallFunction unstall_function); // Add{Read,Write}() populates lists that are eventually passed to a // SocketData class. |frame| must live for the whole test. @@ -1327,7 +1326,7 @@ // request/response (i.e., an HTTP-like) stream resumes after a stall // and unstall. void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest( - const UnstallFunction& unstall_function) { + UnstallFunction unstall_function) { spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); AddWrite(req); @@ -1372,7 +1371,7 @@ EXPECT_TRUE(stream->send_stalled_by_flow_control()); - unstall_function.Run(stream, kPostBodyLength); + std::move(unstall_function).Run(stream, kPostBodyLength); EXPECT_FALSE(stream->send_stalled_by_flow_control()); @@ -1386,18 +1385,18 @@ TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) { RunResumeAfterUnstallRequestResponseTest( - base::Bind(&IncreaseStreamSendWindowSize)); + base::BindOnce(&IncreaseStreamSendWindowSize)); } TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) { RunResumeAfterUnstallRequestResponseTest( - base::Bind(&AdjustStreamSendWindowSize)); + base::BindOnce(&AdjustStreamSendWindowSize)); } // Given an unstall function, runs a test to make sure that a bidirectional // (i.e., non-HTTP-like) stream resumes after a stall and unstall. void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest( - const UnstallFunction& unstall_function) { + UnstallFunction unstall_function) { spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); AddWrite(req); @@ -1451,7 +1450,7 @@ EXPECT_TRUE(stream->send_stalled_by_flow_control()); - unstall_function.Run(stream, kPostBodyLength); + std::move(unstall_function).Run(stream, kPostBodyLength); EXPECT_FALSE(stream->send_stalled_by_flow_control()); @@ -1466,12 +1465,12 @@ TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) { RunResumeAfterUnstallBidirectionalTest( - base::Bind(&IncreaseStreamSendWindowSize)); + base::BindOnce(&IncreaseStreamSendWindowSize)); } TEST_F(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) { RunResumeAfterUnstallBidirectionalTest( - base::Bind(&AdjustStreamSendWindowSize)); + base::BindOnce(&AdjustStreamSendWindowSize)); } // Test calculation of amount of bytes received from network.
diff --git a/net/test/embedded_test_server/android/embedded_test_server_android.cc b/net/test/embedded_test_server/android/embedded_test_server_android.cc index 9c2ce0b7..c29ee54 100644 --- a/net/test/embedded_test_server/android/embedded_test_server_android.cc +++ b/net/test/embedded_test_server/android/embedded_test_server_android.cc
@@ -120,7 +120,7 @@ const JavaParamRef<jobject>& jobj, jlong handler) { HandleRequestPtr handler_ptr = reinterpret_cast<HandleRequestPtr>(handler); - test_server_.RegisterRequestHandler(base::Bind(handler_ptr)); + test_server_.RegisterRequestHandler(base::BindRepeating(handler_ptr)); } void EmbeddedTestServerAndroid::ServeFilesFromDirectory(
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc index f847841..01e94cd 100644 --- a/net/test/embedded_test_server/embedded_test_server.cc +++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -495,7 +495,7 @@ void EmbeddedTestServer::ServeFilesFromDirectory( const base::FilePath& directory) { - RegisterDefaultHandler(base::Bind(&HandleFileRequest, directory)); + RegisterDefaultHandler(base::BindRepeating(&HandleFileRequest, directory)); } void EmbeddedTestServer::ServeFilesFromSourceDirectory( @@ -588,8 +588,9 @@ std::unique_ptr<HttpConnection> http_connection_ptr = std::make_unique<HttpConnection>( - std::move(socket), base::Bind(&EmbeddedTestServer::HandleRequest, - base::Unretained(this))); + std::move(socket), + base::BindRepeating(&EmbeddedTestServer::HandleRequest, + base::Unretained(this))); HttpConnection* http_connection = http_connection_ptr.get(); connections_[http_connection->socket_.get()] = std::move(http_connection_ptr);
diff --git a/net/test/embedded_test_server/embedded_test_server.h b/net/test/embedded_test_server/embedded_test_server.h index 0807e3a3..617b7b8 100644 --- a/net/test/embedded_test_server/embedded_test_server.h +++ b/net/test/embedded_test_server/embedded_test_server.h
@@ -53,7 +53,7 @@ // void SetUp() { // test_server_ = std::make_unique<EmbeddedTestServer>(); // test_server_->RegisterRequestHandler( -// base::Bind(&FooTest::HandleRequest, base::Unretained(this))); +// base::BindRepeating(&FooTest::HandleRequest, base::Unretained(this))); // ASSERT_TRUE((test_server_handle_ = test_server_.StartAndReturnHandle())); // } //
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index ecce8f01..d599f38 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc
@@ -1381,7 +1381,7 @@ std::unique_ptr<URLRequest> r(context.CreateRequest( url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS)); r->SetExtraRequestHeaders(extra_headers); - r->SetRequestHeadersCallback(base::Bind( + r->SetRequestHeadersCallback(base::BindRepeating( &HttpRawRequestHeaders::Assign, base::Unretained(&raw_req_headers))); r->Start(); @@ -1411,7 +1411,7 @@ std::unique_ptr<URLRequest> r(context.CreateRequest( url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->SetRequestHeadersCallback(base::Bind( + r->SetRequestHeadersCallback(base::BindRepeating( &HttpRawRequestHeaders::Assign, base::Unretained(&raw_req_headers))); r->Start(); @@ -1430,7 +1430,7 @@ std::unique_ptr<URLRequest> r(context.CreateRequest( url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->SetRequestHeadersCallback(base::Bind( + r->SetRequestHeadersCallback(base::BindRepeating( &HttpRawRequestHeaders::Assign, base::Unretained(&raw_req_headers))); r->Start();
diff --git a/net/url_request/url_request_quic_perftest.cc b/net/url_request/url_request_quic_perftest.cc index 8306d8cd..649f6b3 100644 --- a/net/url_request/url_request_quic_perftest.cc +++ b/net/url_request/url_request_quic_perftest.cc
@@ -240,7 +240,7 @@ base::trace_event::MemoryDumpLevelOfDetail::LIGHT}; auto on_memory_dump_done = - [](base::Closure quit_closure, const URLRequestContext* context, + [](base::OnceClosure quit_closure, const URLRequestContext* context, bool success, uint64_t dump_guid, std::unique_ptr<base::trace_event::ProcessMemoryDump> pmd) { ASSERT_TRUE(success); @@ -275,7 +275,7 @@ reinterpret_cast<uintptr_t>( context->http_transaction_factory()->GetSession())); ASSERT_EQ(0u, allocator_dumps.count(stream_factory_dump_name)); - quit_closure.Run(); + std::move(quit_closure).Run(); }; base::trace_event::MemoryDumpManager::GetInstance()->CreateProcessDump( args,
diff --git a/net/websockets/websocket_deflate_stream_test.cc b/net/websockets/websocket_deflate_stream_test.cc index 078a96cf..4f803427 100644 --- a/net/websockets/websocket_deflate_stream_test.cc +++ b/net/websockets/websocket_deflate_stream_test.cc
@@ -410,7 +410,7 @@ ReadFramesStub stub(ERR_IO_PENDING); std::vector<std::unique_ptr<WebSocketFrame>> frames; base::MockCallback<CompletionOnceCallback> mock_callback; - base::MockCallback<base::Closure> checkpoint; + base::MockCallback<base::OnceClosure> checkpoint; { InSequence s; @@ -441,7 +441,7 @@ ReadFramesStub stub(ERR_IO_PENDING); std::vector<std::unique_ptr<WebSocketFrame>> frames; base::MockCallback<CompletionOnceCallback> mock_callback; - base::MockCallback<base::Closure> checkpoint; + base::MockCallback<base::OnceClosure> checkpoint; { InSequence s; @@ -490,7 +490,7 @@ ReadFramesStub stub(ERR_IO_PENDING); base::MockCallback<CompletionOnceCallback> mock_callback; - base::MockCallback<base::Closure> checkpoint; + base::MockCallback<base::OnceClosure> checkpoint; std::vector<std::unique_ptr<WebSocketFrame>> frames; { InSequence s; @@ -528,7 +528,7 @@ data1); ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING); base::MockCallback<CompletionOnceCallback> mock_callback; - base::MockCallback<base::Closure> checkpoint; + base::MockCallback<base::OnceClosure> checkpoint; std::vector<std::unique_ptr<WebSocketFrame>> frames; { @@ -1068,7 +1068,7 @@ TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) { WriteFramesStub stub(predictor_, ERR_IO_PENDING); base::MockCallback<CompletionOnceCallback> mock_callback; - base::MockCallback<base::Closure> checkpoint; + base::MockCallback<base::OnceClosure> checkpoint; std::vector<std::unique_ptr<WebSocketFrame>> frames; { InSequence s;
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc index d9789a7..ff5a1c0 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc
@@ -405,6 +405,15 @@ return If(AnyOf(pid == 0, pid == target_pid), Allow()).Else(Error(EPERM)); } +ResultExpr RestrictPrlimitToGetrlimit(pid_t target_pid) { + const Arg<pid_t> pid(0); + const Arg<uintptr_t> new_limit(2); + // Only allow operations for the current process, and only with |new_limit| + // set to null. + return If(AllOf(new_limit == 0, AnyOf(pid == 0, pid == target_pid)), Allow()) + .Else(Error(EPERM)); +} + #if !defined(OS_NACL_NONSFI) ResultExpr RestrictPtrace() { const Arg<int> request(0);
diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h index 1544289..ba4289f 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h
@@ -104,6 +104,11 @@ // gracefully; see crbug.com/160157. SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimit(pid_t target_pid); +// Restrict |pid| to the calling process (or 0) for prlimit64(), and require the +// |new_limit_ argument to be null. This allows only getting limits on the +// current process. Otherwise fail gracefully. +SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimitToGetrlimit(pid_t target_pid); + // Restrict ptrace() to just read operations that are needed for crash // reporting. See https://crbug.com/933418 for details. SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPtrace();
diff --git a/services/network/public/cpp/cross_origin_embedder_policy.cc b/services/network/public/cpp/cross_origin_embedder_policy.cc index 87b1fe1..aa2c3ee7 100644 --- a/services/network/public/cpp/cross_origin_embedder_policy.cc +++ b/services/network/public/cpp/cross_origin_embedder_policy.cc
@@ -17,5 +17,12 @@ const CrossOriginEmbedderPolicy& src) = default; CrossOriginEmbedderPolicy& CrossOriginEmbedderPolicy::operator=( CrossOriginEmbedderPolicy&& src) = default; +bool CrossOriginEmbedderPolicy::operator==( + const CrossOriginEmbedderPolicy& other) const { + return value == other.value && + reporting_endpoint == other.reporting_endpoint && + report_only_value == other.report_only_value && + report_only_reporting_endpoint == other.report_only_reporting_endpoint; +} } // namespace network
diff --git a/services/network/public/cpp/cross_origin_embedder_policy.h b/services/network/public/cpp/cross_origin_embedder_policy.h index a94cb1ea..ea1e12c6 100644 --- a/services/network/public/cpp/cross_origin_embedder_policy.h +++ b/services/network/public/cpp/cross_origin_embedder_policy.h
@@ -22,6 +22,7 @@ CrossOriginEmbedderPolicy(CrossOriginEmbedderPolicy&&); CrossOriginEmbedderPolicy& operator=(const CrossOriginEmbedderPolicy&); CrossOriginEmbedderPolicy& operator=(CrossOriginEmbedderPolicy&&); + bool operator==(const CrossOriginEmbedderPolicy&) const; mojom::CrossOriginEmbedderPolicyValue value = mojom::CrossOriginEmbedderPolicyValue::kNone;
diff --git a/services/service_manager/sandbox/linux/bpf_utility_policy_linux.cc b/services/service_manager/sandbox/linux/bpf_utility_policy_linux.cc index c7f9009..192081e 100644 --- a/services/service_manager/sandbox/linux/bpf_utility_policy_linux.cc +++ b/services/service_manager/sandbox/linux/bpf_utility_policy_linux.cc
@@ -27,6 +27,9 @@ switch (sysno) { case __NR_ioctl: return sandbox::RestrictIoctl(); + case __NR_prlimit64: + // Restrict prlimit() to reference only the calling process. + return sandbox::RestrictPrlimitToGetrlimit(GetPolicyPid()); // Allow the system calls below. case __NR_fdatasync: case __NR_fsync:
diff --git a/testing/buildbot/chromium.swangle.json b/testing/buildbot/chromium.swangle.json index b85fe75..f6bdbf0 100644 --- a/testing/buildbot/chromium.swangle.json +++ b/testing/buildbot/chromium.swangle.json
@@ -48,7 +48,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -73,7 +73,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -98,7 +98,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -153,7 +153,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -225,7 +225,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -250,7 +250,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -275,7 +275,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -330,7 +330,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -402,7 +402,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -427,7 +427,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -452,7 +452,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -507,7 +507,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -579,7 +579,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -604,7 +604,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -629,7 +629,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -684,7 +684,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -756,7 +756,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -781,7 +781,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -806,7 +806,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -861,7 +861,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -933,7 +933,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -958,7 +958,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -983,7 +983,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -1038,7 +1038,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -1110,7 +1110,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -1135,7 +1135,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -1160,7 +1160,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -1215,7 +1215,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -1287,7 +1287,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -1312,7 +1312,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -1337,7 +1337,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -1392,7 +1392,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -1464,7 +1464,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -1489,7 +1489,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -1514,7 +1514,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -1569,7 +1569,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -1641,7 +1641,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -1666,7 +1666,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -1691,7 +1691,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -1746,7 +1746,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -1818,7 +1818,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -1843,7 +1843,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -1868,7 +1868,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -1923,7 +1923,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ], @@ -1995,7 +1995,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 20 + "shards": 3 }, "test": "angle_deqp_gles2_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles2_tests" @@ -2020,7 +2020,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 6 + "shards": 4 }, "test": "angle_deqp_gles31_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles31_tests" @@ -2045,7 +2045,7 @@ ], "hard_timeout": 900, "io_timeout": 900, - "shards": 29 + "shards": 9 }, "test": "angle_deqp_gles3_tests", "test_target": "//third_party/angle/src/tests:angle_deqp_gles3_tests" @@ -2100,7 +2100,7 @@ }, { "args": [ - "--gtest_filter=\\*Vulkan_SwiftShader", + "--gtest_filter=*Vulkan_SwiftShader", "--test-launcher-batch-limit=512", "--test-launcher-retry-limit=0" ],
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 6f8e6c5..65e9fcd 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3329,7 +3329,7 @@ '--test-launcher-retry-limit=0', ], 'swarming': { - 'shards': 20, + 'shards': 3, }, }, 'angle_deqp_gles31_tests': { @@ -3339,7 +3339,7 @@ '--test-launcher-retry-limit=0', ], 'swarming': { - 'shards': 6, + 'shards': 4, }, }, 'angle_deqp_gles3_tests': { @@ -3349,7 +3349,7 @@ '--test-launcher-retry-limit=0', ], 'swarming': { - 'shards': 29, + 'shards': 9, }, }, 'angle_deqp_khr_gles2_tests': { @@ -3368,7 +3368,7 @@ }, 'angle_end2end_tests': { 'args': [ - '--gtest_filter=\*Vulkan_SwiftShader', + '--gtest_filter=*Vulkan_SwiftShader', '--test-launcher-batch-limit=512', '--test-launcher-retry-limit=0', ],
diff --git a/third_party/android_provider/BUILD.gn b/third_party/android_provider/BUILD.gn new file mode 100644 index 0000000..34bedb42 --- /dev/null +++ b/third_party/android_provider/BUILD.gn
@@ -0,0 +1,14 @@ +# 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/android/rules.gni") + +assert(is_android) + +android_library("android_provider_java") { + sources = [ + "java/src/org/chromium/third_party/android/provider/MediaStoreUtils.java", + ] + deps = [ "//third_party/android_deps:androidx_annotation_annotation_java" ] +}
diff --git a/third_party/android_provider/LICENSE b/third_party/android_provider/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/third_party/android_provider/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
diff --git a/third_party/android_provider/OWNERS b/third_party/android_provider/OWNERS new file mode 100644 index 0000000..f41c891 --- /dev/null +++ b/third_party/android_provider/OWNERS
@@ -0,0 +1,6 @@ +qinmin@chromium.org +dtrainor@chromium.org + +# TEAM: chrome-downloads@chromium.org +# COMPONENT: UI>Browser>Downloads +
diff --git a/third_party/android_provider/README.chromium b/third_party/android_provider/README.chromium new file mode 100644 index 0000000..56cff5b --- /dev/null +++ b/third_party/android_provider/README.chromium
@@ -0,0 +1,17 @@ +Name: MediaStoreUtils Android sample. +URL: https://android.googlesource.com/platform/cts/+/master/tests/tests/provider/src/android/provider/cts/MediaStoreUtils.java +Version: 50f25a19f2a3de940d6ef7eac84b37d1c62f1b5f +License: Apache 2.0 +Security Critical: yes + +Description: +This contains a modified copy of MediaStoreUtils.java. Please don't modify this. + +MediaStoreUtils.java is based on a public Android sample that was +available as part of the Android cts libraries. It is +also available from: +https://android.googlesource.com/platform/cts/+/master/tests/tests/provider/src/android/provider/cts/MediaStoreUtils.java + +Local Modifications: +- Added logs +- Introduced some helper method.
diff --git a/third_party/android_provider/java/src/org/chromium/third_party/android/provider/MediaStoreUtils.java b/third_party/android_provider/java/src/org/chromium/third_party/android/provider/MediaStoreUtils.java new file mode 100644 index 0000000..c4664aa --- /dev/null +++ b/third_party/android_provider/java/src/org/chromium/third_party/android/provider/MediaStoreUtils.java
@@ -0,0 +1,228 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.chromium.third_party.android.provider; + +import android.content.ContentValues; +import android.content.Context; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.provider.MediaStore; +import android.provider.MediaStore.DownloadColumns; +import android.provider.MediaStore.MediaColumns; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.io.FileNotFoundException; +import java.io.OutputStream; +import java.util.Objects; + +/** + * Utility class to contribute download to the public download collection using + * MediaStore API from Q. + */ +public class MediaStoreUtils { + private static final String TAG = "MediaStoreUtils"; + + /** + * Creates a new pending media item using the given parameters. Pending items + * are expected to have a short lifetime, and owners should either + * {@link PendingSession#publish()} or {@link PendingSession#abandon()} a + * pending item within a few hours after first creating it. + * + * @param context Application context. + * @param params Parameters used to configure the item. + * @return token which can be passed to {@link #openPending(Context, Uri)} + * to work with this pending item. + */ + public static @NonNull Uri createPending( + @NonNull Context context, @NonNull PendingParams params) { + return context.getContentResolver().insert(params.mInsertUri, params.mInsertValues); + } + + /** + * Opens a pending media item to make progress on it. You can open a pending + * item multiple times before finally calling either + * {@link PendingSession#publish()} or {@link PendingSession#abandon()}. + * + * @param uri token which was previously returned from + * {@link #createPending(Context, PendingParams)}. + * @return pending session that was opened. + */ + public static @NonNull PendingSession openPending(@NonNull Context context, @NonNull Uri uri) { + return new PendingSession(context, uri); + } + + /** + * Parameters that describe a pending media item. + */ + public static class PendingParams { + final Uri mInsertUri; + final ContentValues mInsertValues; + + /** + * Creates parameters that describe a pending media item. + * + * @param insertUri the {@code content://} Uri where this pending item + * should be inserted when finally published. For example, to + * publish an image, use + * {@link MediaStore.Images.Media#getContentUri(String)}. + * @param displayName Display name of the item. + * @param mimeType MIME type of the item. + */ + public PendingParams( + @NonNull Uri insertUri, @NonNull String displayName, @NonNull String mimeType) { + mInsertUri = Objects.requireNonNull(insertUri); + final long now = System.currentTimeMillis() / 1000; + mInsertValues = new ContentValues(); + mInsertValues.put(MediaColumns.DISPLAY_NAME, Objects.requireNonNull(displayName)); + mInsertValues.put(MediaColumns.MIME_TYPE, Objects.requireNonNull(mimeType)); + mInsertValues.put(MediaColumns.DATE_ADDED, now); + mInsertValues.put(MediaColumns.DATE_MODIFIED, now); + try { + setPendingContentValues(this.mInsertValues, true); + } catch (Exception e) { + Log.e(TAG, "Unable to set pending content values.", e); + } + } + + /** + * Optionally sets the Uri from where the file has been downloaded. This is used + * for files being added to {@link Downloads} table. + * + * @see DownloadColumns#DOWNLOAD_URI + */ + public void setDownloadUri(@Nullable Uri downloadUri) { + if (downloadUri == null) { + mInsertValues.remove(DownloadColumns.DOWNLOAD_URI); + } else { + mInsertValues.put(DownloadColumns.DOWNLOAD_URI, downloadUri.toString()); + } + } + + /** + * Optionally set the Uri indicating HTTP referer of the file. This is used for + * files being added to {@link Downloads} table. + * + * @see DownloadColumns#REFERER_URI + */ + public void setRefererUri(@Nullable Uri refererUri) { + if (refererUri == null) { + mInsertValues.remove(DownloadColumns.REFERER_URI); + } else { + mInsertValues.put(DownloadColumns.REFERER_URI, refererUri.toString()); + } + } + + /** + * Sets the expiration time of the download. + * + * @time Epoch time in seconds. + */ + public void setExpirationTime(long time) { + mInsertValues.put("date_expires", time); + } + } + + /** + * Session actively working on a pending media item. Pending items are + * expected to have a short lifetime, and owners should either + * {@link PendingSession#publish()} or {@link PendingSession#abandon()} a + * pending item within a few hours after first creating it. + */ + public static class PendingSession implements AutoCloseable { + private final Context mContext; + private final Uri mUri; + + /** + * Create a new pending session item to be published. + * @param context Contexxt of the application. + * @param uri Token which was previously returned from + * {@link #createPending(Context, PendingParams)}. + */ + PendingSession(Context context, Uri uri) { + mContext = Objects.requireNonNull(context); + mUri = Objects.requireNonNull(uri); + } + + /** + * Open the underlying file representing this media item. When a media + * item is successfully completed, you should + * {@link ParcelFileDescriptor#close()} and then {@link #publish()} it. + * + * @return ParcelFileDescriptor to be written into. + */ + public @NonNull ParcelFileDescriptor open() throws FileNotFoundException { + return mContext.getContentResolver().openFileDescriptor(mUri, "rw"); + } + + /** + * Open the underlying file representing this media item. When a media + * item is successfully completed, you should + * {@link OutputStream#close()} and then {@link #publish()} it. + * + * @return OutputStream to be written into. + */ + public @NonNull OutputStream openOutputStream() throws FileNotFoundException { + return mContext.getContentResolver().openOutputStream(mUri); + } + + /** + * When this media item is successfully completed, call this method to + * publish and make the final item visible to the user. + * + * @return the final {@code content://} Uri representing the newly + * published media. + */ + public @NonNull Uri publish() { + try { + final ContentValues values = new ContentValues(); + setPendingContentValues(values, false); + values.putNull("date_expires"); + mContext.getContentResolver().update(mUri, values, null, null); + } catch (Exception e) { + Log.e(TAG, "Unable to publish pending session.", e); + } + return mUri; + } + + /** + * When this media item has failed to be completed, call this method to + * destroy the pending item record and any data related to it. + */ + public void abandon() { + mContext.getContentResolver().delete(mUri, null, null); + } + + @Override + public void close() { + // No resources to close, but at least we can inform people that no + // progress is being actively made. + } + } + + /** + * Helper method to set the ContentValues to pending or non-pending. + * @param values ContentValues to be set. + * @param isPending Whether the item is pending. + */ + private static void setPendingContentValues(ContentValues values, boolean isPending) + throws Exception { + values.put(MediaColumns.IS_PENDING, isPending ? 1 : 0); + } +}
diff --git a/third_party/android_swipe_refresh/README.chromium b/third_party/android_swipe_refresh/README.chromium index aa10d32..057fd8e8 100644 --- a/third_party/android_swipe_refresh/README.chromium +++ b/third_party/android_swipe_refresh/README.chromium
@@ -6,8 +6,9 @@ Description: This is a modified copy of the swipe refresh layout widget (and its two -dependencies) from Android's app compat library (v4). The widget provides a -pull-to-refresh styled layout for touch-activated refresh of view contents. +dependencies) from Android's app compat library (v4). This has been +migrated to use AndroidX libraries. The widget provides a pull-to-refresh +styled layout for touch-activated refresh of view contents. Local Modifications:
diff --git a/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/MaterialProgressDrawable.java b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/MaterialProgressDrawable.java index 5913842..265c29c 100644 --- a/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/MaterialProgressDrawable.java +++ b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/MaterialProgressDrawable.java
@@ -16,11 +16,6 @@ package org.chromium.third_party.android.swiperefresh; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.Interpolator; -import android.view.animation.Animation; -import android.view.animation.LinearInterpolator; -import android.view.animation.Transformation; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; @@ -32,11 +27,17 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; -import android.graphics.drawable.Drawable; import android.graphics.drawable.Animatable; -import android.support.v4.view.animation.FastOutSlowInInterpolator; +import android.graphics.drawable.Drawable; import android.util.DisplayMetrics; import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; +import android.view.animation.Transformation; + +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;
diff --git a/third_party/blink/perf_tests/css/OWNERS b/third_party/blink/perf_tests/css/OWNERS new file mode 100644 index 0000000..dbb9dfd2 --- /dev/null +++ b/third_party/blink/perf_tests/css/OWNERS
@@ -0,0 +1,2 @@ +file://third_party/blink/renderer/core/css/OWNERS +
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index f98b53b..cb3b27e 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -321,6 +321,8 @@ "web/web_embedded_worker_start_data.h", "web/web_external_popup_menu.h", "web/web_external_popup_menu_client.h", + "web/web_external_widget.h", + "web/web_external_widget_client.h", "web/web_form_control_element.h", "web/web_form_element.h", "web/web_frame.h",
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 2511123..fb2f7d2 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -2845,22 +2845,6 @@ # Media features to emulate. optional array of MediaFeature features - # Emulates the given vision deficiency. - experimental command setEmulatedVisionDeficiency - parameters - # Vision deficiency to emulate. - enum type - none - achromatomaly - achromatopsia - blurredVision - deuteranomaly - deuteranopia - protanomaly - protanopia - tritanomaly - tritanopia - # Overrides the Geolocation Position or Error. Omitting any of the parameters emulates position # unavailable. command setGeolocationOverride
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index 5542faa..0572f18 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -508,6 +508,11 @@ // navigation. This matches the in-process frame behavior. SetFrameOwnerProperties(FrameOwnerProperties properties); + // Updates the remote frame's replicated enforcement of insecure request + // policy. Used when the frame's policy is changed in another renderer + // process. Argument |policy| is a bitfield for InsecureRequestPolicy. + EnforceInsecureRequestPolicy(blink.mojom.InsecureRequestPolicy policy); + // Update the replicated origin. Used when the frame is navigated to a // new origin. SetReplicatedOrigin(url.mojom.Origin origin,
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h index 6efde7b..3438308 100644 --- a/third_party/blink/public/platform/task_type.h +++ b/third_party/blink/public/platform/task_type.h
@@ -249,13 +249,14 @@ kMainThreadTaskQueueControl = 43, kMainThreadTaskQueueCleanup = 52, kMainThreadTaskQueueMemoryPurge = 62, + kMainThreadTaskQueueNonWaking = 69, kCompositorThreadTaskQueueDefault = 45, kCompositorThreadTaskQueueInput = 49, kWorkerThreadTaskQueueDefault = 46, kWorkerThreadTaskQueueV8 = 47, kWorkerThreadTaskQueueCompositor = 48, - kCount = 69, + kCount = 70, }; } // namespace blink
diff --git a/third_party/blink/public/web/web_external_widget.h b/third_party/blink/public/web/web_external_widget.h new file mode 100644 index 0000000..8dd77c7 --- /dev/null +++ b/third_party/blink/public/web/web_external_widget.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 THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_EXTERNAL_WIDGET_H_ +#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_EXTERNAL_WIDGET_H_ + +#include "cc/layers/layer.h" +#include "third_party/blink/public/web/web_external_widget_client.h" +#include "third_party/blink/public/web/web_widget.h" + +namespace blink { + +// This is a type of Widget which is partially implemented outside of blink, +// such as fullscreen pepper widgets. This interface provides methods for the +// external implementation to access common Widget behaviour implemented inside +// blink, in addition to the WebWidget methods. The blink Widget uses +// WebExternalWidgetClient to communicate back to the external implementation. +class WebExternalWidget : public WebWidget { + public: + // Create a new concrete instance of this class. + // |client| should be non-null. + // |debug_url| provides the return value for WebWidget::GetURLForDebugTrace. + BLINK_EXPORT static std::unique_ptr<WebExternalWidget> Create( + WebExternalWidgetClient* client, + const WebURL& debug_url); + + virtual ~WebExternalWidget() = default; + + // Provides an externally-created Layer to display as the widget's content, or + // a null pointer to remove any existing Layer which will cause the widget to + // display nothing. + virtual void SetRootLayer(scoped_refptr<cc::Layer>) = 0; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_EXTERNAL_WIDGET_H_
diff --git a/third_party/blink/public/web/web_external_widget_client.h b/third_party/blink/public/web/web_external_widget_client.h new file mode 100644 index 0000000..4fa83804 --- /dev/null +++ b/third_party/blink/public/web/web_external_widget_client.h
@@ -0,0 +1,39 @@ +// 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 THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_EXTERNAL_WIDGET_CLIENT_H_ +#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_EXTERNAL_WIDGET_CLIENT_H_ + +#include "third_party/blink/public/platform/web_input_event_result.h" +#include "ui/gfx/geometry/size.h" + +namespace blink { +class WebCoalescedInputEvent; + +// The interface from blink to Widgets with implementations outside of blink. +class WebExternalWidgetClient { + public: + virtual ~WebExternalWidgetClient() = default; + + // Called when the associated WebExternalWidget receives input and + // needs the implementation to handle it. + virtual WebInputEventResult HandleInputEvent( + const WebCoalescedInputEvent&) = 0; + + // Called when the associated WebExternalWidget wishes to dispatch + // any pending buffered touch events. The implementation may choose to buffer + // individual pointer events (received via HandleInputEvent) and dispatch + // a single touch event indicating the changes since the last touch event. + // This method is typically invoked once per frame whereas HandleInputEvent + // may be invoked many times per frame (i.e. multiple fingers on the touch + // surface). + virtual WebInputEventResult DispatchBufferedTouchEvents() = 0; + + // Called when the associated WebExternalWidget has adjusted its size. + virtual void DidResize(const gfx::Size& size) = 0; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_EXTERNAL_WIDGET_CLIENT_H_
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h index 03123834..eb89afd 100644 --- a/third_party/blink/public/web/web_widget.h +++ b/third_party/blink/public/web/web_widget.h
@@ -206,9 +206,6 @@ return false; } - // Returns true if the WebWidget created is of type PepperWidget. - virtual bool IsPepperWidget() const { return false; } - // Calling WebWidgetClient::requestPointerLock() will result in one // return call to didAcquirePointerLock() or didNotAcquirePointerLock(). virtual void DidAcquirePointerLock() {}
diff --git a/third_party/blink/renderer/build/scripts/core/css/OWNERS b/third_party/blink/renderer/build/scripts/core/css/OWNERS index 89abcdb..dbb9dfd2 100644 --- a/third_party/blink/renderer/build/scripts/core/css/OWNERS +++ b/third_party/blink/renderer/build/scripts/core/css/OWNERS
@@ -1,7 +1,2 @@ file://third_party/blink/renderer/core/css/OWNERS -andruud@chromium.org -futhark@chromium.org - -# TEAM: layout-dev@chromium.org -# COMPONENT: Blink>CSS
diff --git a/third_party/blink/renderer/build/scripts/core/style/OWNERS b/third_party/blink/renderer/build/scripts/core/style/OWNERS index 44d94a9..59049c3 100644 --- a/third_party/blink/renderer/build/scripts/core/style/OWNERS +++ b/third_party/blink/renderer/build/scripts/core/style/OWNERS
@@ -1,7 +1,2 @@ file://third_party/blink/renderer/core/style/OWNERS -andruud@chromium.org -futhark@chromium.org - -# TEAM: layout-dev@chromium.org -# COMPONENT: Blink>CSS
diff --git a/third_party/blink/renderer/controller/memory_usage_monitor.cc b/third_party/blink/renderer/controller/memory_usage_monitor.cc index ee61472..7ed800c7 100644 --- a/third_party/blink/renderer/controller/memory_usage_monitor.cc +++ b/third_party/blink/renderer/controller/memory_usage_monitor.cc
@@ -7,6 +7,7 @@ #include "base/test/test_mock_time_task_runner.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" namespace blink { @@ -16,7 +17,8 @@ } MemoryUsageMonitor::MemoryUsageMonitor() { - timer_.SetTaskRunner(Thread::MainThread()->GetTaskRunner()); + timer_.SetTaskRunner( + Thread::MainThread()->Scheduler()->NonWakingTaskRunner()); } MemoryUsageMonitor::MemoryUsageMonitor(
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index 8759ba0..36bd76ad 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -53,6 +53,7 @@ "+cc/paint/paint_flags.h", "+cc/paint/paint_worklet_input.h", "+cc/trees/browser_controls_params.h", + "+cc/trees/layer_tree_host.h", "+cc/trees/paint_holding_commit_trigger.h", "+cc/trees/layer_tree_host.h", "+components/performance_manager/public/mojom/coordination_unit.mojom-blink.h",
diff --git a/third_party/blink/renderer/core/css/BUILD.gn b/third_party/blink/renderer/core/css/BUILD.gn index b70a955..8f8b6f4 100644 --- a/third_party/blink/renderer/core/css/BUILD.gn +++ b/third_party/blink/renderer/core/css/BUILD.gn
@@ -584,8 +584,6 @@ "style_traversal_root.h", "tree_scope_style_sheet_collection.cc", "tree_scope_style_sheet_collection.h", - "vision_deficiency.cc", - "vision_deficiency.h", "zoom_adjusted_pixel_value.h", ] }
diff --git a/third_party/blink/renderer/core/css/OWNERS b/third_party/blink/renderer/core/css/OWNERS index d1eb1c3..a007a39 100644 --- a/third_party/blink/renderer/core/css/OWNERS +++ b/third_party/blink/renderer/core/css/OWNERS
@@ -2,6 +2,7 @@ andruud@chromium.org ericwilligers@chromium.org futhark@chromium.org +xiaochengh@chromium.org # TEAM: layout-dev@chromium.org # COMPONENT: Blink>CSS
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 1605896..7293a782 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -737,8 +737,6 @@ viewport_style->SetOverflowX(EOverflow::kAuto); viewport_style->SetOverflowY(EOverflow::kAuto); - document.GetStyleEngine().ApplyVisionDeficiencyStyle(viewport_style); - return viewport_style; }
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index 5ab331c8..97d2bfa 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -36,7 +36,6 @@ #include "third_party/blink/renderer/core/css/css_font_selector.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" #include "third_party/blink/renderer/core/css/css_style_sheet.h" -#include "third_party/blink/renderer/core/css/css_uri_value.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/document_style_environment_variables.h" #include "third_party/blink/renderer/core/css/document_style_sheet_collector.h" @@ -79,9 +78,7 @@ #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/style/computed_style.h" -#include "third_party/blink/renderer/core/style/filter_operations.h" #include "third_party/blink/renderer/core/style/style_initial_data.h" -#include "third_party/blink/renderer/core/svg/svg_resource.h" #include "third_party/blink/renderer/core/svg/svg_style_element.h" #include "third_party/blink/renderer/platform/fonts/font_cache.h" #include "third_party/blink/renderer/platform/fonts/font_selector.h" @@ -1629,42 +1626,6 @@ kInvalidateCurrentScope, has_rebuilt_font_cache); } -void StyleEngine::LoadVisionDeficiencyFilter() { - VisionDeficiency old_vision_deficiency = vision_deficiency_; - vision_deficiency_ = GetDocument().GetPage()->GetVisionDeficiency(); - if (vision_deficiency_ == old_vision_deficiency) - return; - - if (vision_deficiency_ == VisionDeficiency::kNoVisionDeficiency) { - vision_deficiency_filter_ = nullptr; - } else { - AtomicString url = CreateVisionDeficiencyFilterUrl(vision_deficiency_); - cssvalue::CSSURIValue css_uri_value(url); - SVGResource* svg_resource = css_uri_value.EnsureResourceReference(); - // Note: The fact that we're using data: URLs here is an - // implementation detail. Emulating vision deficiencies should still - // work even if the Document's Content-Security-Policy disallows - // data: URLs. - svg_resource->LoadWithoutCSP(GetDocument()); - vision_deficiency_filter_ = - MakeGarbageCollected<ReferenceFilterOperation>(url, svg_resource); - } -} - -void StyleEngine::VisionDeficiencyChanged() { - MarkViewportStyleDirty(); -} - -void StyleEngine::ApplyVisionDeficiencyStyle( - scoped_refptr<ComputedStyle> layout_view_style) { - LoadVisionDeficiencyFilter(); - if (vision_deficiency_filter_) { - FilterOperations ops; - ops.Operations().push_back(vision_deficiency_filter_); - layout_view_style->SetFilter(ops); - } -} - const MediaQueryEvaluator& StyleEngine::EnsureMediaQueryEvaluator() { if (!media_query_evaluator_) { if (GetDocument().GetFrame()) { @@ -2174,7 +2135,6 @@ visitor->Trace(active_tree_scopes_); visitor->Trace(tree_boundary_crossing_scopes_); visitor->Trace(resolver_); - visitor->Trace(vision_deficiency_filter_); visitor->Trace(viewport_resolver_); visitor->Trace(media_query_evaluator_); visitor->Trace(global_rule_set_);
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index 05a79dfd..e750feac 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -51,7 +51,6 @@ #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/tree_ordered_list.h" #include "third_party/blink/renderer/core/html/track/text_track.h" -#include "third_party/blink/renderer/core/style/filter_operations.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/fonts/font_selector_client.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -81,7 +80,7 @@ // The StyleEngine class manages style-related state for the document. There is // a 1-1 relationship of Document to StyleEngine. The document calls the -// StyleEngine when the document is updated in a way that impacts styles. +// StyleEngine when the the document is updated in a way that impacts styles. class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>, public FontSelectorClient, public NameClient { @@ -325,10 +324,6 @@ void ApplyUserRuleSetChanges(const ActiveStyleSheetVector& old_style_sheets, const ActiveStyleSheetVector& new_style_sheets); - void VisionDeficiencyChanged(); - void ApplyVisionDeficiencyStyle( - scoped_refptr<ComputedStyle> layout_view_style); - void CollectMatchingUserRules(ElementRuleCollector&) const; void CustomPropertyRegistered(); @@ -391,8 +386,6 @@ // FontSelectorClient implementation. void FontsNeedUpdate(FontSelector*) override; - void LoadVisionDeficiencyFilter(); - private: bool NeedsActiveStyleSheetUpdate() const { return all_tree_scopes_dirty_ || tree_scopes_removed_ || @@ -545,9 +538,6 @@ bool viewport_style_dirty_ = false; bool fonts_need_update_ = false; - VisionDeficiency vision_deficiency_ = VisionDeficiency::kNoVisionDeficiency; - Member<ReferenceFilterOperation> vision_deficiency_filter_; - Member<StyleResolver> resolver_; Member<ViewportStyleResolver> viewport_resolver_; Member<MediaQueryEvaluator> media_query_evaluator_;
diff --git a/third_party/blink/renderer/core/css/vision_deficiency.cc b/third_party/blink/renderer/core/css/vision_deficiency.cc deleted file mode 100644 index 66e9d39..0000000 --- a/third_party/blink/renderer/core/css/vision_deficiency.cc +++ /dev/null
@@ -1,100 +0,0 @@ -// 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 "third_party/blink/renderer/core/css/vision_deficiency.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" - -namespace blink { - -AtomicString CreateFilterDataUrl(AtomicString piece) { - // clang-format off - AtomicString url = - "data:image/svg+xml," - "<svg xmlns=\"http://www.w3.org/2000/svg\">" - "<filter id=\"f\">" + - piece + - "</filter>" - "</svg>" - "#f"; - // clang-format on - return url; -} - -AtomicString CreateVisionDeficiencyFilterUrl( - VisionDeficiency vision_deficiency) { - switch (vision_deficiency) { - case VisionDeficiency::kAchromatomaly: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.618 0.320 0.062 0.000 0.000 " - "0.163 0.775 0.062 0.000 0.000 " - "0.163 0.320 0.516 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kAchromatopsia: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.299 0.587 0.114 0.000 0.000 " - "0.299 0.587 0.114 0.000 0.000 " - "0.299 0.587 0.114 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kBlurredVision: - return CreateFilterDataUrl( - "<feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"2\"/>"); - case VisionDeficiency::kDeuteranomaly: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.800 0.200 0.000 0.000 0.000 " - "0.258 0.742 0.000 0.000 0.000 " - "0.000 0.142 0.858 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kDeuteranopia: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.625 0.375 0.000 0.000 0.000 " - "0.700 0.300 0.000 0.000 0.000 " - "0.000 0.300 0.700 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kProtanomaly: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.817 0.183 0.000 0.000 0.000 " - "0.333 0.667 0.000 0.000 0.000 " - "0.000 0.125 0.875 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kProtanopia: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.567 0.433 0.000 0.000 0.000 " - "0.558 0.442 0.000 0.000 0.000 " - "0.000 0.242 0.758 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kTritanomaly: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.967 0.033 0.000 0.000 0.000 " - "0.000 0.733 0.267 0.000 0.000 " - "0.000 0.183 0.817 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kTritanopia: - return CreateFilterDataUrl( - "<feColorMatrix values=\"" - "0.950 0.050 0.000 0.000 0.000 " - "0.000 0.433 0.567 0.000 0.000 " - "0.000 0.475 0.525 0.000 0.000 " - "0.000 0.000 0.000 1.000 0.000 " - "\"/>"); - case VisionDeficiency::kNoVisionDeficiency: - NOTREACHED(); - return ""; - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/css/vision_deficiency.h b/third_party/blink/renderer/core/css/vision_deficiency.h deleted file mode 100644 index b91d422..0000000 --- a/third_party/blink/renderer/core/css/vision_deficiency.h +++ /dev/null
@@ -1,30 +0,0 @@ -// 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 THIRD_PARTY_BLINK_RENDERER_CORE_CSS_VISION_DEFICIENCY_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_VISION_DEFICIENCY_H_ - -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" - -namespace blink { - -enum class VisionDeficiency { - kNoVisionDeficiency, - kAchromatomaly, - kAchromatopsia, - kBlurredVision, - kDeuteranomaly, - kDeuteranopia, - kProtanomaly, - kProtanopia, - kTritanomaly, - kTritanopia, -}; - -AtomicString CreateVisionDeficiencyFilterUrl( - VisionDeficiency vision_deficiency); - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_VISION_DEFICIENCY_H_
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index fa3b053..87cfca1a 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -8606,10 +8606,6 @@ MediaQueryAffectingValueChanged(); } -void Document::VisionDeficiencyChanged() { - GetStyleEngine().VisionDeficiencyChanged(); -} - void Document::UpdateForcedColors() { auto* web_theme_engine = RuntimeEnabledFeatures::ForcedColorsEnabled() && Platform::Current()
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index e2ca926..de5330e 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -44,7 +44,6 @@ #include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h" #include "third_party/blink/renderer/core/accessibility/axid.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css/vision_deficiency.h" #include "third_party/blink/renderer/core/dom/container_node.h" #include "third_party/blink/renderer/core/dom/create_element_flags.h" #include "third_party/blink/renderer/core/dom/document_encoding_data.h" @@ -1699,9 +1698,6 @@ void ColorSchemeChanged(); - // A new vision deficiency is being emulated through DevTools. - void VisionDeficiencyChanged(); - void ClearIsolatedWorldCSPForTesting(int32_t world_id); // A META element with name=color-scheme was added, removed, or modified.
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 5bbe367..99e7f8f 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4805,6 +4805,16 @@ return nullptr; } +void Element::HideNonce() { + const AtomicString& nonce_value = FastGetAttribute(html_names::kNonceAttr); + if (nonce_value.IsEmpty()) + return; + if (!InActiveDocument()) + return; + if (GetDocument().GetContentSecurityPolicy()->HasHeaderDeliveredPolicy()) + setAttribute(html_names::kNonceAttr, g_empty_atom); +} + ElementIntersectionObserverData* Element::IntersectionObserverData() const { if (HasRareData()) return GetElementRareData()->IntersectionObserverData();
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index a2ff655..580d51a 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -1013,6 +1013,17 @@ virtual void ParserDidSetAttributes() {} + // The "nonce" attribute is hidden when: + // 1) The Content-Security-Policy is delivered from the HTTP headers. + // 2) The Element is part of the active document. + // See https://github.com/whatwg/html/pull/2373 + // + // This applies to the element of the HTML and SVG namespaces. + // + // This function clears the "nonce" attribute whenever conditions (1) and (2) + // are met. + void HideNonce(); + private: void ScrollLayoutBoxBy(const ScrollToOptions*); void ScrollLayoutBoxTo(const ScrollToOptions*);
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index 20fd026..625c561 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -140,8 +140,8 @@ event_dispatched_ = true; #endif if (GetEvent().GetEventPath().IsEmpty()) { - // eventPath() can be empty if event path is shrinked by relataedTarget - // retargeting. + // eventPath() can be empty if relatedTarget retargeting has shrunk the + // path. return DispatchEventResult::kNotCanceled; } std::unique_ptr<EventTiming> eventTiming;
diff --git a/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/third_party/blink/renderer/core/dom/idle_deadline_test.cc index 8116102..71dc4d7 100644 --- a/third_party/blink/renderer/core/dom/idle_deadline_test.cc +++ b/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -42,6 +42,9 @@ scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override { return nullptr; } + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override { + return nullptr; + } scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() override { return nullptr;
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc index fb61aec..911c7e2c 100644 --- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc +++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
@@ -33,6 +33,9 @@ scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override { return nullptr; } + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override { + return nullptr; + } scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() override { return nullptr;
diff --git a/third_party/blink/renderer/core/exported/BUILD.gn b/third_party/blink/renderer/core/exported/BUILD.gn index f807bf8..8c2a7601 100644 --- a/third_party/blink/renderer/core/exported/BUILD.gn +++ b/third_party/blink/renderer/core/exported/BUILD.gn
@@ -24,6 +24,8 @@ "web_dom_message_event.cc", "web_element.cc", "web_element_collection.cc", + "web_external_widget_impl.cc", + "web_external_widget_impl.h", "web_form_control_element.cc", "web_form_element.cc", "web_form_element_observer_impl.cc",
diff --git a/third_party/blink/renderer/core/exported/web_external_widget_impl.cc b/third_party/blink/renderer/core/exported/web_external_widget_impl.cc new file mode 100644 index 0000000..80ee313 --- /dev/null +++ b/third_party/blink/renderer/core/exported/web_external_widget_impl.cc
@@ -0,0 +1,64 @@ +// 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 "third_party/blink/renderer/core/exported/web_external_widget_impl.h" + +#include "cc/trees/layer_tree_host.h" + +namespace blink { + +std::unique_ptr<WebExternalWidget> WebExternalWidget::Create( + WebExternalWidgetClient* client, + const blink::WebURL& debug_url) { + return std::make_unique<WebExternalWidgetImpl>(client, debug_url); +} + +WebExternalWidgetImpl::WebExternalWidgetImpl(WebExternalWidgetClient* client, + const WebURL& debug_url) + : client_(client), debug_url_(debug_url) { + DCHECK(client_); +} + +WebExternalWidgetImpl::~WebExternalWidgetImpl() = default; + +void WebExternalWidgetImpl::SetCompositorHosts( + cc::LayerTreeHost* layer_tree_host, + cc::AnimationHost* animation_host) { + widget_base_.SetCompositorHosts(layer_tree_host, animation_host); +} + +WebHitTestResult WebExternalWidgetImpl::HitTestResultAt(const gfx::Point&) { + NOTIMPLEMENTED(); + return {}; +} + +WebURL WebExternalWidgetImpl::GetURLForDebugTrace() { + return debug_url_; +} + +WebSize WebExternalWidgetImpl::Size() { + return size_; +} + +void WebExternalWidgetImpl::Resize(const WebSize& size) { + if (size_ == size) + return; + size_ = size; + client_->DidResize(gfx::Size(size)); +} + +WebInputEventResult WebExternalWidgetImpl::HandleInputEvent( + const WebCoalescedInputEvent& coalesced_event) { + return client_->HandleInputEvent(coalesced_event); +} + +WebInputEventResult WebExternalWidgetImpl::DispatchBufferedTouchEvents() { + return client_->DispatchBufferedTouchEvents(); +} + +void WebExternalWidgetImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) { + widget_base_.LayerTreeHost()->SetNonBlinkManagedRootLayer(layer); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_external_widget_impl.h b/third_party/blink/renderer/core/exported/web_external_widget_impl.h new file mode 100644 index 0000000..60ad34f --- /dev/null +++ b/third_party/blink/renderer/core/exported/web_external_widget_impl.h
@@ -0,0 +1,43 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_EXTERNAL_WIDGET_IMPL_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_EXTERNAL_WIDGET_IMPL_H_ + +#include "third_party/blink/public/web/web_external_widget.h" + +#include "third_party/blink/public/platform/web_url.h" +#include "third_party/blink/renderer/platform/widget/widget_base.h" + +namespace blink { + +class WebExternalWidgetImpl : public WebExternalWidget { + public: + WebExternalWidgetImpl(WebExternalWidgetClient* client, + const WebURL& debug_url); + ~WebExternalWidgetImpl() override; + + // WebWidget overrides: + void SetCompositorHosts(cc::LayerTreeHost*, cc::AnimationHost*) override; + WebHitTestResult HitTestResultAt(const gfx::Point&) override; + WebURL GetURLForDebugTrace() override; + WebSize Size() override; + void Resize(const WebSize& size) override; + WebInputEventResult HandleInputEvent( + const WebCoalescedInputEvent& coalesced_event) override; + WebInputEventResult DispatchBufferedTouchEvents() override; + + // WebExternalWidget overrides: + void SetRootLayer(scoped_refptr<cc::Layer>) override; + + private: + WebExternalWidgetClient* const client_; + const WebURL debug_url_; + WebSize size_; + WidgetBase widget_base_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WEB_EXTERNAL_WIDGET_IMPL_H_
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc index 534c694..5cbb3af 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.cc
@@ -139,6 +139,14 @@ uma_percentage_name.ToString().Utf8().c_str(), 0, 10000000, 50)); } } + + // Make space in the current sample. + current_sample_.sub_metrics_durations.Grow(static_cast<wtf_size_t>(kCount)); + current_sample_.sub_metric_percentages.Grow(static_cast<wtf_size_t>(kCount)); +} + +LocalFrameUkmAggregator::~LocalFrameUkmAggregator() { + ReportUpdateTimeEvent(); } LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer @@ -205,10 +213,10 @@ if (!calls_to_next_forced_style_layout_uma_) { auto& record = absolute_metric_records_[kForcedStyleAndLayout]; record.uma_counter->CountMicroseconds(duration); - if (is_before_fcp_) - record.pre_fcp_uma_counter->CountMicroseconds(duration); - else + if (fcp_state_ == kHavePassedFCP) record.post_fcp_uma_counter->CountMicroseconds(duration); + else + record.pre_fcp_uma_counter->CountMicroseconds(duration); calls_to_next_forced_style_layout_uma_ = base::RandInt(0, mean_calls_between_forced_style_layout_uma_ * 2); } else { @@ -219,69 +227,27 @@ void LocalFrameUkmAggregator::DidReachFirstContentfulPaint( bool are_painting_main_frame) { - DCHECK(is_before_fcp_); - - is_before_fcp_ = false; + DCHECK(fcp_state_ != kHavePassedFCP); if (!are_painting_main_frame) { DCHECK(AllMetricsAreZero()); return; } -#define CASE_FOR_ID(name) \ - case k##name: \ - builder.Set##name(absolute_record.pre_fcp_aggregate.InMicroseconds()); \ - break - - ukm::builders::Blink_PageLoad builder(source_id_); - builder.SetMainFrame(primary_metric_.pre_fcp_aggregate.InMicroseconds()); - primary_metric_.uma_aggregate_counter->CountMicroseconds( - primary_metric_.pre_fcp_aggregate); - for (unsigned i = 0; i < (unsigned)kCount; ++i) { - auto& absolute_record = absolute_metric_records_[i]; - if (absolute_record.uma_aggregate_counter) { - absolute_record.uma_aggregate_counter->CountMicroseconds( - absolute_record.pre_fcp_aggregate); - } - - switch (static_cast<MetricId>(i)) { - CASE_FOR_ID(Compositing); - CASE_FOR_ID(CompositingCommit); - CASE_FOR_ID(ImplCompositorCommit); - CASE_FOR_ID(IntersectionObservation); - CASE_FOR_ID(Paint); - CASE_FOR_ID(PrePaint); - CASE_FOR_ID(Style); - CASE_FOR_ID(Layout); - CASE_FOR_ID(ForcedStyleAndLayout); - CASE_FOR_ID(HitTestDocumentUpdate); - CASE_FOR_ID(ScrollingCoordinator); - CASE_FOR_ID(HandleInputEvents); - CASE_FOR_ID(Animate); - CASE_FOR_ID(UpdateLayers); - CASE_FOR_ID(ProxyCommit); - CASE_FOR_ID(WaitForCommit); - case kCount: - case kMainFrame: - NOTREACHED(); - break; - } - } - builder.Record(recorder_); - -#undef CASE_FOR_ID + fcp_state_ = kThisFrameReachedFCP; } void LocalFrameUkmAggregator::RecordSample(size_t metric_index, base::TimeTicks start, base::TimeTicks end) { base::TimeDelta duration = end - start; + bool is_pre_fcp = (fcp_state_ != kHavePassedFCP); // Accumulate for UKM and record the UMA DCHECK_LT(metric_index, absolute_metric_records_.size()); auto& record = absolute_metric_records_[metric_index]; record.interval_duration += duration; - if (is_before_fcp_) + if (is_pre_fcp) record.pre_fcp_aggregate += duration; // Record the UMA // ForcedStyleAndLayout happen so frequently on some pages that we overflow @@ -292,7 +258,7 @@ RecordForcedStyleLayoutUMA(duration); } else { record.uma_counter->CountMicroseconds(duration); - if (is_before_fcp_) { + if (is_pre_fcp) { record.pre_fcp_uma_counter->CountMicroseconds(duration); } else { record.post_fcp_uma_counter->CountMicroseconds(duration); @@ -347,17 +313,19 @@ in_main_frame_update_ = false; base::TimeDelta duration = end - start; + bool report_as_pre_fcp = (fcp_state_ != kHavePassedFCP); + bool report_fcp_metrics = (fcp_state_ == kThisFrameReachedFCP); // Record UMA primary_metric_.uma_counter->CountMicroseconds(duration); - if (is_before_fcp_) + if (report_as_pre_fcp) primary_metric_.pre_fcp_uma_counter->CountMicroseconds(duration); else primary_metric_.post_fcp_uma_counter->CountMicroseconds(duration); // Record primary time information primary_metric_.interval_duration = duration; - if (is_before_fcp_) + if (report_as_pre_fcp) primary_metric_.pre_fcp_aggregate += duration; // Compute all the dependent metrics, after finding which bucket we're in @@ -378,43 +346,76 @@ // Record here to avoid resetting the ratios before this data point is // recorded. - UpdateEventTimeAndRecordEventIfNeeded(trackers); + UpdateEventTimeAndUpdateSampleIfNeeded(trackers); + + // Report the FCP metrics, if necessary, after updating the sample so that + // the sample has been recorded for the frame that produced FCP. + if (report_fcp_metrics) { + ReportPreFCPEvent(); + ReportUpdateTimeEvent(); + // Update the state to prevent future reporting. + fcp_state_ = kHavePassedFCP; + } // Reset for the next frame. ResetAllMetrics(); } -void LocalFrameUkmAggregator::UpdateEventTimeAndRecordEventIfNeeded( +void LocalFrameUkmAggregator::UpdateEventTimeAndUpdateSampleIfNeeded( cc::ActiveFrameSequenceTrackers trackers) { - // TODO(schenney) Adjust the mean sample interval so that we do not - // get our events throttled by the UKM system. For M-73 only 1 in 212 - // events are being sent. - if (!frames_to_next_event_) { - RecordEvent(trackers); - frames_to_next_event_ += SampleFramesToNextEvent(); + // Update the frame count first, because it must include this frame + frames_since_last_report_++; + + // Regardless of test requests, always capture the first frame. + if (frames_since_last_report_ == 1) { + UpdateSample(trackers); + return; } - DCHECK_GT(frames_to_next_event_, 0u); - --frames_to_next_event_; + + // Exit if in testing and we do not want to update this frame + if (next_frame_sample_control_for_test_ == kMustNotChooseNextFrame) + return; + + // Update the sample with probability 1/frames_since_last_report_, or if + // testing demand is. + if ((next_frame_sample_control_for_test_ == kMustChooseNextFrame) || + base::RandDouble() < 1 / static_cast<double>(frames_since_last_report_)) { + UpdateSample(trackers); + } } -void LocalFrameUkmAggregator::RecordEvent( +void LocalFrameUkmAggregator::UpdateSample( cc::ActiveFrameSequenceTrackers trackers) { -#define CASE_FOR_ID(name) \ - case k##name: \ - builder.Set##name(absolute_record.interval_duration.InMicroseconds()) \ - .Set##name##Percentage(percentage); \ + current_sample_.primary_metric_duration = primary_metric_.interval_duration; + float primary_metric_in_microseconds = + primary_metric_.interval_duration.InMicrosecondsF(); + for (unsigned i = 0; i < static_cast<unsigned>(kCount); ++i) { + current_sample_.sub_metrics_durations[i] = + absolute_metric_records_[i].interval_duration; + current_sample_.sub_metric_percentages[i] = static_cast<unsigned>(floor( + main_frame_percentage_records_[i].interval_duration.InMicrosecondsF() * + 100.0 / primary_metric_in_microseconds)); + } + current_sample_.trackers = trackers; +} + +void LocalFrameUkmAggregator::ReportPreFCPEvent() { +#define CASE_FOR_ID(name) \ + case k##name: \ + builder.Set##name(absolute_record.pre_fcp_aggregate.InMicroseconds()); \ break - ukm::builders::Blink_UpdateTime builder(source_id_); - builder.SetMainFrame(primary_metric_.interval_duration.InMicroseconds()); - builder.SetMainFrameIsBeforeFCP(is_before_fcp_); - builder.SetMainFrameReasons(trackers); + ukm::builders::Blink_PageLoad builder(source_id_); + builder.SetMainFrame(primary_metric_.pre_fcp_aggregate.InMicroseconds()); + primary_metric_.uma_aggregate_counter->CountMicroseconds( + primary_metric_.pre_fcp_aggregate); for (unsigned i = 0; i < static_cast<unsigned>(kCount); ++i) { auto& absolute_record = absolute_metric_records_[i]; - auto& percentage_record = main_frame_percentage_records_[i]; - unsigned percentage = static_cast<unsigned>( - floor(percentage_record.interval_duration.InMicrosecondsF() * 100.0 / - primary_metric_.interval_duration.InMicrosecondsF())); + if (absolute_record.uma_aggregate_counter) { + absolute_record.uma_aggregate_counter->CountMicroseconds( + absolute_record.pre_fcp_aggregate); + } + switch (static_cast<MetricId>(i)) { CASE_FOR_ID(Compositing); CASE_FOR_ID(CompositingCommit); @@ -442,6 +443,55 @@ #undef CASE_FOR_ID } +void LocalFrameUkmAggregator::ReportUpdateTimeEvent() { + // Don't report if we haven't generated any samples. + if (!frames_since_last_report_) + return; + +#define CASE_FOR_ID(name, index) \ + case k##name: \ + builder \ + .Set##name( \ + current_sample_.sub_metrics_durations[index].InMicroseconds()) \ + .Set##name##Percentage(current_sample_.sub_metric_percentages[index]); \ + break + + ukm::builders::Blink_UpdateTime builder(source_id_); + builder.SetMainFrame( + current_sample_.primary_metric_duration.InMicroseconds()); + builder.SetMainFrameIsBeforeFCP(fcp_state_ != kHavePassedFCP); + builder.SetMainFrameReasons(current_sample_.trackers); + for (unsigned i = 0; i < static_cast<unsigned>(kCount); ++i) { + switch (static_cast<MetricId>(i)) { + CASE_FOR_ID(Compositing, i); + CASE_FOR_ID(CompositingCommit, i); + CASE_FOR_ID(ImplCompositorCommit, i); + CASE_FOR_ID(IntersectionObservation, i); + CASE_FOR_ID(Paint, i); + CASE_FOR_ID(PrePaint, i); + CASE_FOR_ID(Style, i); + CASE_FOR_ID(Layout, i); + CASE_FOR_ID(ForcedStyleAndLayout, i); + CASE_FOR_ID(HitTestDocumentUpdate, i); + CASE_FOR_ID(ScrollingCoordinator, i); + CASE_FOR_ID(HandleInputEvents, i); + CASE_FOR_ID(Animate, i); + CASE_FOR_ID(UpdateLayers, i); + CASE_FOR_ID(ProxyCommit, i); + CASE_FOR_ID(WaitForCommit, i); + case kCount: + case kMainFrame: + NOTREACHED(); + break; + } + } + builder.Record(recorder_); +#undef CASE_FOR_ID + + // Reset the frames since last report to ensure correct sampling. + frames_since_last_report_ = 0; +} + void LocalFrameUkmAggregator::ResetAllMetrics() { primary_metric_.reset(); for (auto& record : absolute_metric_records_) @@ -450,38 +500,6 @@ record.reset(); } -unsigned LocalFrameUkmAggregator::SampleFramesToNextEvent() { - // Return the test interval if set - if (frames_to_next_event_for_test_) - return frames_to_next_event_for_test_; - - // Sample from an exponential distribution to give a poisson distribution - // of samples per time unit, then weigh it with an exponential multiplier to - // give a few samples in rapid succession (for frames early in the page's - // life) then exponentially fewer as the page lives longer. - // RandDouble() returns [0,1), but we need (0,1]. If RandDouble() is - // uniformly random, so is 1-RandDouble(), so use it to adjust the range. - // When RandDouble returns 0.0, as it could, we will get a float_sample of - // 0, causing underflow in UpdateEventTimeAndRecordIfNeeded. So rejection - // sample until we get a positive count. - double float_sample = 0; - do { - float_sample = -(sample_rate_multiplier_ * - std::exp(samples_so_far_ * sample_decay_rate_) * - std::log(1.0 - base::RandDouble())); - } while (float_sample == 0); - // float_sample is positive, so we don't need to worry about underflow. - // After around 30 samples we will end up with a super high - // sample. That's OK because it just means we'll stop reporting metrics - // for that session, but we do need to be careful about overflow and NaN. - samples_so_far_++; - unsigned unsigned_sample = - std::isnan(float_sample) - ? UINT_MAX - : base::saturated_cast<unsigned>(std::ceil(float_sample)); - return unsigned_sample; -} - bool LocalFrameUkmAggregator::AllMetricsAreZero() { if (primary_metric_.interval_duration.InMicroseconds()) return false; @@ -493,4 +511,12 @@ return true; } +void LocalFrameUkmAggregator::ChooseNextFrameForTest() { + next_frame_sample_control_for_test_ = kMustChooseNextFrame; +} + +void LocalFrameUkmAggregator::DoNotChooseNextFrameForTest() { + next_frame_sample_control_for_test_ = kMustNotChooseNextFrame; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h index b25aa46..ef31447 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h
@@ -35,7 +35,7 @@ // - recorder: UkmRecorder which will handle the events // // The aggregator manages all of the UKM and UMA names for LocalFrameView. -// It constructs and takes ownership the UMA counters when constructed +// It constructs and takes ownership of the UMA counters when constructed // itself. We do this to localize all UMA and UKM metrics in one place, so // that adding a metric is localized to the cc file of this class, protected // from errors that might arise when adding names in multiple places. @@ -53,12 +53,11 @@ // primary time and computes metrics that depend on it. UMA metrics are updated // at this time. // -// A UKM event is generated according to a sampling strategy. A record is always -// generated on the first lifecycle update, and then additional samples are -// taken at random frames simulating a poisson process with mean number of -// frames between events of mean_frames_between_samples_. The first primary -// metric recording after the frame count has passed will produce an event with -// all the data for that frame (i.e. the period since the last BeginMainFrame). +// A UKM event is generated according to a sampling strategy, with the goal +// being to choose one frame to report before First Contentful Paint and +// one frame to report during the subsequent document lifetime. We maintain +// a copy of the current sample, and randomly choose to update it on each frame +// such that any given frame is equally likely to be the final sample. // // Sample usage (see also SCOPED_UMA_AND_UKM_TIMER): // std::unique_ptr<UkmHierarchicalTimeAggregator> aggregator( @@ -224,7 +223,7 @@ }; LocalFrameUkmAggregator(int64_t source_id, ukm::UkmRecorder*); - ~LocalFrameUkmAggregator() = default; + ~LocalFrameUkmAggregator(); // Create a scoped timer with the index of the metric. Note the index must // correspond to the matching index in metric_names. @@ -259,8 +258,9 @@ void BeginMainFrame(); // Inform the aggregator that we have reached First Contentful Paint. - // The UKM event reports this and UMA for aggregated contributions to - // FCP are reported if are_painting_main_frame is true. + // The UKM event for the pre-FCP period will be recorded and UMA for + // aggregated contributions to FCP are reported if are_painting_main_frame + // is true. void DidReachFirstContentfulPaint(bool are_painting_main_frame); bool InMainFrameUpdate() { return in_main_frame_update_; } @@ -296,22 +296,36 @@ void reset() { interval_duration = base::TimeDelta(); } }; - void UpdateEventTimeAndRecordEventIfNeeded( + struct SampleToRecord { + base::TimeDelta primary_metric_duration; + Vector<base::TimeDelta> sub_metrics_durations; + Vector<unsigned> sub_metric_percentages; + cc::ActiveFrameSequenceTrackers trackers; + }; + + void UpdateEventTimeAndUpdateSampleIfNeeded( cc::ActiveFrameSequenceTrackers trackers); - void RecordEvent(cc::ActiveFrameSequenceTrackers trackers); + void UpdateSample(cc::ActiveFrameSequenceTrackers trackers); void ResetAllMetrics(); - unsigned SampleFramesToNextEvent(); + + // Reports the current sample to the UKM system. Called on the first main + // frame update after First Contentful Paint and at destruction. Also resets + // the frame count. + void ReportUpdateTimeEvent(); + + // Reports the Blink.PageLoad to the UKM system. Called on the first main + // frame after First Contentful Paint. + void ReportPreFCPEvent(); // Implements throttling of the ForcedStyleAndLayoutUMA metric. void RecordForcedStyleLayoutUMA(base::TimeDelta& duration); - // To test event sampling. This and all future intervals will be the given - // frame count, until this is called again. - void FramesToNextEventForTest(unsigned num_frames) { - frames_to_next_event_for_test_ = num_frames; - } + // To test event sampling. Controls whether we update the current sample + // on the next frame, or do not. Values persist until explicitly changed. + void ChooseNextFrameForTest(); + void DoNotChooseNextFrameForTest(); - // Used to check that we only for the MainFrame of a document. + // Used to check that we record only for the MainFrame of a document. bool AllMetricsAreZero(); // The caller is the owner of the |clock|. The |clock| must outlive the @@ -329,32 +343,36 @@ Vector<AbsoluteMetricRecord> absolute_metric_records_; Vector<MainFramePercentageRecord> main_frame_percentage_records_; - // Sampling control. We use a Poisson process with an exponential decay - // multiplier. The goal is to get many randomly distributed samples early - // during page load and initial interaction, then samples at an exponentially - // decreasing rate to effectively cap the number of samples. The particular - // parameters chosen here give roughly 5-10 samples in the first 100 frames, - // decaying to several hours between samples by the 40th sample. The - // multiplier value and sample_decay_rate_ should be tuned to achieve a total - // sample count that avoids throttling by the UKM system. - double sample_decay_rate_ = 1; - double sample_rate_multiplier_ = 2; - unsigned samples_so_far_ = 0; - unsigned frames_to_next_event_ = 0; + // The current sample to report. When RecordEvent() is called we + // check for uniform_random[0,1) < 1 / n where n is the number of frames + // we have seen (including this one). If true, we replace the sample with + // the current frame data. The result is a uniformly randomly chosen frame + // in the period between the frame counter being reset and the recording + // to the UKM system of the current sample. + // This process is designed to get maximum utility while only sending 2 + // events per page load, which in turn maximizes client counts. + SampleToRecord current_sample_; + unsigned frames_since_last_report_ = 0; // Control for the ForcedStyleAndUpdate UMA metric sampling unsigned mean_calls_between_forced_style_layout_uma_ = 100; unsigned calls_to_next_forced_style_layout_uma_ = 0; - // Test data, used for SampleFramesToNextEvent if present - unsigned frames_to_next_event_for_test_ = 0; - // Set by BeginMainFrame() and cleared in RecordMEndOfFrameMetrics. // Main frame metrics are only recorded if this is true. bool in_main_frame_update_ = false; - // Record whether or not it is before the First Contentful Paint. - bool is_before_fcp_ = true; + // A bitfield maintaining state for first contentful paint. + enum FCPState { kBeforeFCPSignal, kThisFrameReachedFCP, kHavePassedFCP }; + FCPState fcp_state_ = kBeforeFCPSignal; + + // A bitfield used to control updating the sample for tests. + enum SampleControlForTest { + kNoPreference, + kMustChooseNextFrame, + kMustNotChooseNextFrame + }; + SampleControlForTest next_frame_sample_control_for_test_ = kNoPreference; DISALLOW_COPY_AND_ASSIGN(LocalFrameUkmAggregator); };
diff --git a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc index 325558e7..dbf50505 100644 --- a/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc +++ b/third_party/blink/renderer/core/frame/local_frame_ukm_aggregator_test.cc
@@ -49,14 +49,9 @@ "Percentage"; } - void FramesToNextEventForTest(unsigned delta) { - aggregator().FramesToNextEventForTest(delta); - } - - unsigned FramesToNextEvent() { return aggregator().frames_to_next_event_; } - unsigned SamplesSoFar() { return aggregator().samples_so_far_; } - unsigned SampleFramesToNextEvent() { - return aggregator().SampleFramesToNextEvent(); + void ChooseNextFrameForTest() { aggregator().ChooseNextFrameForTest(); } + void DoNotChooseNextFrameForTest() { + aggregator().DoNotChooseNextFrameForTest(); } base::TimeTicks Now() { return test_task_runner_->NowTicks(); } @@ -64,43 +59,42 @@ protected: scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_; - void VerifyUpdateEntries(unsigned expected_num_entries, - unsigned expected_primary_metric, - unsigned expected_sub_metric, - unsigned expected_percentage, - unsigned expected_reasons, - bool expected_before_fcp) { + void VerifyUpdateEntry(unsigned index, + unsigned expected_primary_metric, + unsigned expected_sub_metric, + unsigned expected_percentage, + unsigned expected_reasons, + bool expected_before_fcp) { auto entries = recorder().GetEntriesByName("Blink.UpdateTime"); - EXPECT_EQ(entries.size(), expected_num_entries); + EXPECT_GT(entries.size(), index); - for (auto* entry : entries) { + auto* entry = entries[index]; + EXPECT_TRUE( + ukm::TestUkmRecorder::EntryHasMetric(entry, GetPrimaryMetricName())); + const int64_t* primary_metric_value = + ukm::TestUkmRecorder::GetEntryMetric(entry, GetPrimaryMetricName()); + EXPECT_NEAR(*primary_metric_value / 1e3, expected_primary_metric, 0.001); + for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { EXPECT_TRUE( - ukm::TestUkmRecorder::EntryHasMetric(entry, GetPrimaryMetricName())); - const int64_t* primary_metric_value = - ukm::TestUkmRecorder::GetEntryMetric(entry, GetPrimaryMetricName()); - EXPECT_NEAR(*primary_metric_value / 1e3, expected_primary_metric, 0.001); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - EXPECT_TRUE( - ukm::TestUkmRecorder::EntryHasMetric(entry, GetMetricName(i))); - const int64_t* metric_value = - ukm::TestUkmRecorder::GetEntryMetric(entry, GetMetricName(i)); - EXPECT_NEAR(*metric_value / 1e3, expected_sub_metric, 0.001); + ukm::TestUkmRecorder::EntryHasMetric(entry, GetMetricName(i))); + const int64_t* metric_value = + ukm::TestUkmRecorder::GetEntryMetric(entry, GetMetricName(i)); + EXPECT_NEAR(*metric_value / 1e3, expected_sub_metric, 0.001); - EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric( - entry, GetPercentageMetricName(i))); - const int64_t* metric_percentage = ukm::TestUkmRecorder::GetEntryMetric( - entry, GetPercentageMetricName(i)); - EXPECT_NEAR(*metric_percentage, expected_percentage, 0.001); - } - EXPECT_TRUE( - ukm::TestUkmRecorder::EntryHasMetric(entry, "MainFrameIsBeforeFCP")); - EXPECT_EQ(expected_before_fcp, *ukm::TestUkmRecorder::GetEntryMetric( - entry, "MainFrameIsBeforeFCP")); - EXPECT_TRUE( - ukm::TestUkmRecorder::EntryHasMetric(entry, "MainFrameReasons")); - EXPECT_EQ(expected_reasons, *ukm::TestUkmRecorder::GetEntryMetric( - entry, "MainFrameReasons")); + EXPECT_TRUE(ukm::TestUkmRecorder::EntryHasMetric( + entry, GetPercentageMetricName(i))); + const int64_t* metric_percentage = ukm::TestUkmRecorder::GetEntryMetric( + entry, GetPercentageMetricName(i)); + EXPECT_NEAR(*metric_percentage, expected_percentage, 0.001); } + EXPECT_TRUE( + ukm::TestUkmRecorder::EntryHasMetric(entry, "MainFrameIsBeforeFCP")); + EXPECT_EQ(expected_before_fcp, *ukm::TestUkmRecorder::GetEntryMetric( + entry, "MainFrameIsBeforeFCP")); + EXPECT_TRUE( + ukm::TestUkmRecorder::EntryHasMetric(entry, "MainFrameReasons")); + EXPECT_EQ(expected_reasons, + *ukm::TestUkmRecorder::GetEntryMetric(entry, "MainFrameReasons")); } void VerifyAggregatedEntries(unsigned expected_num_entries, @@ -125,6 +119,27 @@ } } + void SimulateFrame(base::TimeTicks start_time, + unsigned millisecond_per_step, + cc::ActiveFrameSequenceTrackers trackers, + bool mark_fcp = false) { + aggregator().BeginMainFrame(); + for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { + auto timer = aggregator().GetScopedTimer(i); + if (mark_fcp && i == static_cast<int>(LocalFrameUkmAggregator::kPaint)) + aggregator().DidReachFirstContentfulPaint(true); + test_task_runner_->FastForwardBy( + base::TimeDelta::FromMilliseconds(millisecond_per_step)); + } + aggregator().RecordEndOfFrameMetrics(start_time, Now(), trackers); + } + + bool SampleMatchesIteration(int64_t iteration_count) { + return aggregator() + .current_sample_.sub_metrics_durations[0] + .InMilliseconds() == iteration_count; + } + private: scoped_refptr<LocalFrameUkmAggregator> aggregator_; ukm::TestUkmRecorder recorder_; @@ -146,6 +161,8 @@ } TEST_F(LocalFrameUkmAggregatorTest, FirstFrameIsRecorded) { + // Verifies that we always get a sample when we report at least one frame. + // Although the tests use a mock clock, the UKM aggregator checks if the // system has a high resolution clock before recording results. As a result, // the tests will fail if the system does not have a high resolution clock. @@ -155,17 +172,14 @@ // The initial interval is always zero, so we should see one set of metrics // for the initial frame, regardless of the initial interval. base::TimeTicks start_time = Now(); - FramesToNextEventForTest(1); unsigned millisecond_for_step = 1; - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = - aggregator().GetScopedTimer(i % LocalFrameUkmAggregator::kCount); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_for_step)); - } - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 0); + SimulateFrame(start_time, millisecond_for_step, 12); + // Metrics are not reported until destruction. + EXPECT_EQ(recorder().entries_count(), 0u); + + // Reset the aggregator. Should record one pre-FCP metric. + ResetAggregator(); EXPECT_EQ(recorder().entries_count(), 1u); float expected_primary_metric = @@ -174,119 +188,60 @@ float expected_percentage = floor(100.0 / static_cast<float>(LocalFrameUkmAggregator::kCount)); - VerifyUpdateEntries(1u, expected_primary_metric, expected_sub_metric, - expected_percentage, 0, true); - - // Reset the aggregator. Should not record any more. - ResetAggregator(); - - VerifyUpdateEntries(1u, expected_primary_metric, expected_sub_metric, - expected_percentage, 0, true); + VerifyUpdateEntry(0u, expected_primary_metric, expected_sub_metric, + expected_percentage, 12, true); } -TEST_F(LocalFrameUkmAggregatorTest, EventsRecordedAtIntervals) { +TEST_F(LocalFrameUkmAggregatorTest, PreAndPostFCPAreRecorded) { + // Confirm that we get at least one frame pre-FCP and one post-FCP. + // Although the tests use a mock clock, the UKM aggregator checks if the // system has a high resolution clock before recording results. As a result, // the tests will fail if the system does not have a high resolution clock. if (!base::TimeTicks::IsHighResolution()) return; - // The records should be recorded in the first frame after every interval, - // and no sooner. - - // If we claim we are past FCP, the event should indicate that. - aggregator().DidReachFirstContentfulPaint(true); - - // Set the first sample interval to 2. - FramesToNextEventForTest(2); - unsigned millisecond_per_step = 50 / (LocalFrameUkmAggregator::kCount + 1); - unsigned millisecond_per_frame = - millisecond_per_step * (LocalFrameUkmAggregator::kCount + 1); - + // The initial interval is always zero, so we should see one set of metrics + // for the initial frame, regardless of the initial interval. base::TimeTicks start_time = Now(); - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = aggregator().GetScopedTimer(i); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - } - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 4); + unsigned millisecond_per_step = 50 / (LocalFrameUkmAggregator::kCount + 1); + SimulateFrame(start_time, millisecond_per_step, 4, true); + + // We marked FCP when we simulated, so we should report something. There + // should be 2 entries because the aggregated pre-FCP metric also reported. + EXPECT_EQ(recorder().entries_count(), 2u); + + float expected_primary_metric = + millisecond_per_step * LocalFrameUkmAggregator::kCount; + float expected_sub_metric = millisecond_per_step; + float expected_percentage = + floor(100.0 / static_cast<float>(LocalFrameUkmAggregator::kCount)); + + VerifyUpdateEntry(0u, expected_primary_metric, expected_sub_metric, + expected_percentage, 4, true); + + // Take another step. Should reset the frame count and report the first post- + // fcp frame. A failure here iundicates that we did not reset the frame, + // or that we are incorrectly tracking pre/post fcp. + unsigned millisecond_per_frame = + millisecond_per_step * LocalFrameUkmAggregator::kCount; + + start_time = Now(); + SimulateFrame(start_time, millisecond_per_step, 4); + + // Need to destruct to report + ResetAggregator(); // We should have a sample after the very first step, regardless of the // interval. The FirstFrameIsRecorded test above also tests this. There - // should be 2 entries because the aggregated pre-fcp event has also + // should be 3 entries because the aggregated pre-fcp event has also // been recorded. - float expected_percentage = floor(millisecond_per_step * 100.0 / - static_cast<float>(millisecond_per_frame)); - VerifyUpdateEntries(1u, millisecond_per_frame, millisecond_per_step, - expected_percentage, 4, false); + EXPECT_EQ(recorder().entries_count(), 3u); - // Another step does not get us past the sample interval. - start_time = Now(); - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = aggregator().GetScopedTimer(i); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - } - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 8); - - VerifyUpdateEntries(1u, millisecond_per_frame, millisecond_per_step, - expected_percentage, 4, false); - - // Another step should tick us past the sample interval. - // Note that the sample is a single frame, so even if we've taken - // multiple steps we should see just one frame's time. - start_time = Now(); - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = aggregator().GetScopedTimer(i); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - } - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 4); - - VerifyUpdateEntries(2u, millisecond_per_frame, millisecond_per_step, - expected_percentage, 4, false); - - // Step one more frame so we don't sample again. - start_time = Now(); - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = aggregator().GetScopedTimer(i); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - } - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 32); - - // Should be no more samples. - VerifyUpdateEntries(2u, millisecond_per_frame, millisecond_per_step, - expected_percentage, 4, false); - - // And one more step to generate one more sample - start_time = Now(); - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = aggregator().GetScopedTimer(i); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - } - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 4); - - // We should have 3 more events, once for the prior interval and 2 for the - // new interval. - VerifyUpdateEntries(3u, millisecond_per_frame, millisecond_per_step, - expected_percentage, 4, false); + expected_percentage = floor(millisecond_per_step * 100.0 / + static_cast<float>(millisecond_per_frame)); + VerifyUpdateEntry(1u, millisecond_per_frame, millisecond_per_step, + expected_percentage, 4, false); } TEST_F(LocalFrameUkmAggregatorTest, AggregatedPreFCPEventRecorded) { @@ -296,49 +251,30 @@ if (!base::TimeTicks::IsHighResolution()) return; - // Set the first sample interval to 5. We shouldn't need to record an + // Be sure to not choose the next frame. We shouldn't need to record an // UpdateTime metric in order to record an aggregated metric. - FramesToNextEventForTest(5); + DoNotChooseNextFrameForTest(); unsigned millisecond_per_step = 50 / (LocalFrameUkmAggregator::kCount + 1); unsigned millisecond_per_frame = - millisecond_per_step * (LocalFrameUkmAggregator::kCount + 1); + millisecond_per_step * (LocalFrameUkmAggregator::kCount); base::TimeTicks start_time = Now(); - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = aggregator().GetScopedTimer(i); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - } - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 0); + SimulateFrame(start_time, millisecond_per_step, 3); // We should not have an aggregated metric yet because we have not reached - // FCP. - VerifyAggregatedEntries(0u, millisecond_per_frame, millisecond_per_step); + // FCP. We shouldn't have any other kind of metric either. + EXPECT_EQ(recorder().entries_count(), 0u); - // Another step does not get us past the sample interval. + // Another step marking FCP this time. + ChooseNextFrameForTest(); start_time = Now(); - aggregator().BeginMainFrame(); - for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { - auto timer = aggregator().GetScopedTimer(i); - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - } - test_task_runner_->FastForwardBy( - base::TimeDelta::FromMilliseconds(millisecond_per_step)); - aggregator().RecordEndOfFrameMetrics(start_time, Now(), 0); + SimulateFrame(start_time, millisecond_per_step, 3, true); - // Still no aggregated record because we have not reached FCP. - VerifyAggregatedEntries(0u, millisecond_per_frame, millisecond_per_step); - - // If we claim we are past FCP, the event should indicate that. - aggregator().DidReachFirstContentfulPaint(true); - - // Now we should have an aggregated metric. + // Now we should have an aggregated metric, plus the pre-FCP update metric + EXPECT_EQ(recorder().entries_count(), 2u); VerifyAggregatedEntries(1u, 2 * millisecond_per_frame, 2 * millisecond_per_step); + ResetAggregator(); } TEST_F(LocalFrameUkmAggregatorTest, LatencyDataIsPopulated) { @@ -348,9 +284,8 @@ if (!base::TimeTicks::IsHighResolution()) return; - // The initial interval is always zero, so we should see one set of metrics - // for the initial frame, regardless of the initial interval. - FramesToNextEventForTest(1); + // We always record the first frame. Din't use the SimulateFrame method + // because we need to populate before the end of the frame. unsigned millisecond_for_step = 1; aggregator().BeginMainFrame(); for (int i = 0; i < LocalFrameUkmAggregator::kCount; ++i) { @@ -360,7 +295,6 @@ base::TimeDelta::FromMilliseconds(millisecond_for_step)); } - // Need to populate before the end of the frame. std::unique_ptr<cc::BeginMainFrameMetrics> metrics_data = aggregator().GetBeginMainFrameMetrics(); EXPECT_EQ(metrics_data->handle_input_events.InMillisecondsF(), @@ -378,22 +312,28 @@ millisecond_for_step); // Do not check the value in metrics_data.update_layers because it // is not set by the aggregator. + ResetAggregator(); } -TEST_F(LocalFrameUkmAggregatorTest, SampleFramesGoesToMaxUnsigned) { - // This will time out if the exponential decay in sample rate does not - // happen. It should not take too many iterations to reach maximum time - // between samples. - unsigned initial_sample_count = SamplesSoFar(); - unsigned last_sample_count = initial_sample_count; - unsigned frames_to_next_event = FramesToNextEvent(); - while (frames_to_next_event < UINT_MAX) { - frames_to_next_event = SampleFramesToNextEvent(); - EXPECT_GT(frames_to_next_event, 0u); - EXPECT_EQ(last_sample_count + 1, SamplesSoFar()); - last_sample_count++; +TEST_F(LocalFrameUkmAggregatorTest, SampleDoesChange) { + // To write a test that the sample eventually changes we need to let it very + // occasionally time out or fail. We'll go up to 100,000 tries for an update, + // so this should not hit on average once every 100,000 test runs. One flake + // in 100,000 seems acceptable. + + // Generate the first frame. We will look for a change from this frame. + unsigned millisecond_for_step = 1; + SimulateFrame(base::TimeTicks(), millisecond_for_step, 0); + + unsigned iteration_count = 2; + bool new_sample = false; + while (iteration_count < 100000u && !new_sample) { + millisecond_for_step = iteration_count; + SimulateFrame(base::TimeTicks(), millisecond_for_step, 0); + new_sample = SampleMatchesIteration(static_cast<int64_t>(iteration_count)); + ++iteration_count; } - EXPECT_NE(initial_sample_count, last_sample_count); + EXPECT_LT(iteration_count, 100000u); } } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index b9fdeeb..12ffa76 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -381,6 +381,11 @@ Frame::ApplyFrameOwnerProperties(std::move(properties)); } +void RemoteFrame::EnforceInsecureRequestPolicy( + mojom::blink::InsecureRequestPolicy policy) { + SetInsecureRequestPolicy(policy); +} + void RemoteFrame::SetReplicatedOrigin( const scoped_refptr<const SecurityOrigin>& origin, bool is_potentially_trustworthy_unique_origin) {
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h index 814a6fb..baddf4d 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.h +++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -103,6 +103,8 @@ void EnforceInsecureNavigationsSet(const WTF::Vector<uint32_t>& set) override; void SetFrameOwnerProperties( mojom::blink::FrameOwnerPropertiesPtr properties) override; + void EnforceInsecureRequestPolicy( + mojom::blink::InsecureRequestPolicy policy) override; void SetReplicatedOrigin( const scoped_refptr<const SecurityOrigin>& origin, bool is_potentially_trustworthy_unique_origin) override;
diff --git a/third_party/blink/renderer/core/frame/settings_delegate.h b/third_party/blink/renderer/core/frame/settings_delegate.h index 8919c3d5..1b0bdcf 100644 --- a/third_party/blink/renderer/core/frame/settings_delegate.h +++ b/third_party/blink/renderer/core/frame/settings_delegate.h
@@ -72,7 +72,6 @@ kColorSchemeChange, kSpatialNavigationChange, kUniversalAccessChange, - kVisionDeficiencyChange, }; virtual void SettingsChanged(ChangeType) = 0;
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 7c0e72d..eb953393 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1213,11 +1213,8 @@ // Process the superclass first to ensure that `InActiveDocument()` is // updated. Element::InsertedInto(insertion_point); + HideNonce(); - if (GetDocument().GetContentSecurityPolicy()->HasHeaderDeliveredPolicy() && - InActiveDocument() && FastHasAttribute(html_names::kNonceAttr)) { - setAttribute(html_names::kNonceAttr, g_empty_atom); - } if (IsFormAssociatedCustomElement()) EnsureElementInternals().InsertedInto(insertion_point);
diff --git a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc index 70efd14..3d94b51 100644 --- a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc
@@ -6,7 +6,6 @@ #include "third_party/blink/public/common/input/web_touch_event.h" #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/renderer/core/css/vision_deficiency.h" #include "third_party/blink/renderer/core/exported/web_view_impl.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" @@ -40,8 +39,6 @@ max_touch_points_(&agent_state_, /*default_value=*/1), emulated_media_(&agent_state_, /*default_value=*/WTF::String()), emulated_media_features_(&agent_state_, /*default_value=*/WTF::String()), - emulated_vision_deficiency_(&agent_state_, - /*default_value=*/WTF::String()), navigator_platform_override_(&agent_state_, /*default_value=*/WTF::String()), user_agent_override_(&agent_state_, /*default_value=*/WTF::String()), @@ -104,8 +101,6 @@ .build()); } setEmulatedMedia(emulated_media_.Get(), std::move(features)); - if (!emulated_vision_deficiency_.Get().IsNull()) - setEmulatedVisionDeficiency(emulated_vision_deficiency_.Get()); auto rgba = ParseRGBA(default_background_color_override_rgba_.Get()); if (rgba) setDefaultBackgroundColorOverride(std::move(rgba)); @@ -171,8 +166,6 @@ // (e.g. if we allowed two different front-ends with the same // settings to attach to the same page). TODO: support this use case. setEmulatedMedia(String(), {}); - if (!emulated_vision_deficiency_.Get().IsNull()) - setEmulatedVisionDeficiency(String("none")); setCPUThrottlingRate(1); setFocusEmulationEnabled(false); setDefaultBackgroundColorOverride(Maybe<protocol::DOM::RGBA>()); @@ -279,43 +272,6 @@ return response; } -Response InspectorEmulationAgent::setEmulatedVisionDeficiency( - const String& type) { - Response response = AssertPage(); - if (!response.isSuccess()) - return response; - - VisionDeficiency vision_deficiency; - namespace TypeEnum = - protocol::Emulation::SetEmulatedVisionDeficiency::TypeEnum; - if (type == TypeEnum::None) - vision_deficiency = VisionDeficiency::kNoVisionDeficiency; - else if (type == TypeEnum::Achromatomaly) - vision_deficiency = VisionDeficiency::kAchromatomaly; - else if (type == TypeEnum::Achromatopsia) - vision_deficiency = VisionDeficiency::kAchromatopsia; - else if (type == TypeEnum::BlurredVision) - vision_deficiency = VisionDeficiency::kBlurredVision; - else if (type == TypeEnum::Deuteranomaly) - vision_deficiency = VisionDeficiency::kDeuteranomaly; - else if (type == TypeEnum::Deuteranopia) - vision_deficiency = VisionDeficiency::kDeuteranopia; - else if (type == TypeEnum::Protanomaly) - vision_deficiency = VisionDeficiency::kProtanomaly; - else if (type == TypeEnum::Protanopia) - vision_deficiency = VisionDeficiency::kProtanopia; - else if (type == TypeEnum::Tritanomaly) - vision_deficiency = VisionDeficiency::kTritanomaly; - else if (type == TypeEnum::Tritanopia) - vision_deficiency = VisionDeficiency::kTritanopia; - else - return Response::InvalidParams("Unknown vision deficiency type"); - - emulated_vision_deficiency_.Set(type); - GetWebViewImpl()->GetPage()->SetVisionDeficiency(vision_deficiency); - return response; -} - Response InspectorEmulationAgent::setCPUThrottlingRate(double rate) { Response response = AssertPage(); if (!response.isSuccess())
diff --git a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h index 4c77396..4543033e 100644 --- a/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h
@@ -48,7 +48,6 @@ protocol::Maybe<String> media, protocol::Maybe<protocol::Array<protocol::Emulation::MediaFeature>> features) override; - protocol::Response setEmulatedVisionDeficiency(const String&) override; protocol::Response setCPUThrottlingRate(double) override; protocol::Response setFocusEmulationEnabled(bool) override; protocol::Response setVirtualTimePolicy( @@ -128,7 +127,6 @@ InspectorAgentState::Integer max_touch_points_; InspectorAgentState::String emulated_media_; InspectorAgentState::StringMap emulated_media_features_; - InspectorAgentState::String emulated_vision_deficiency_; InspectorAgentState::String navigator_platform_override_; InspectorAgentState::String user_agent_override_; InspectorAgentState::String accept_language_override_;
diff --git a/third_party/blink/renderer/core/inspector/inspector_protocol_config.json b/third_party/blink/renderer/core/inspector/inspector_protocol_config.json index b6ba2f3..bafa314 100644 --- a/third_party/blink/renderer/core/inspector/inspector_protocol_config.json +++ b/third_party/blink/renderer/core/inspector/inspector_protocol_config.json
@@ -84,7 +84,7 @@ { "domain": "Emulation", "include": ["forceViewport", "resetViewport", "resetPageScaleFactor", "setPageScaleFactor", "setScriptExecutionDisabled", "setTouchEmulationEnabled", - "setEmulatedMedia", "setEmulatedVisionDeficiency", "setCPUThrottlingRate", "setVirtualTimePolicy", "setTimezoneOverride", "setNavigatorOverrides", "setDefaultBackgroundColorOverride", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", + "setEmulatedMedia", "setCPUThrottlingRate", "setVirtualTimePolicy", "setTimezoneOverride", "setNavigatorOverrides", "setDefaultBackgroundColorOverride", "setDeviceMetricsOverride", "clearDeviceMetricsOverride", "setUserAgentOverride", "setScrollbarsHidden", "setDocumentCookieDisabled", "setFocusEmulationEnabled", "setLocaleOverride"], "include_events": ["virtualTimeBudgetExpired", "virtualTimeAdvanced", "virtualTimePaused"] },
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 8ff83ef..70905ed7 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -30,7 +30,6 @@ #include "third_party/blink/renderer/core/css/media_feature_overrides.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/css/style_engine.h" -#include "third_party/blink/renderer/core/css/vision_deficiency.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/visited_link_state.h" #include "third_party/blink/renderer/core/editing/drag_caret.h" @@ -800,11 +799,6 @@ } break; } - case SettingsDelegate::kVisionDeficiencyChange: { - if (auto* main_local_frame = DynamicTo<LocalFrame>(MainFrame())) - main_local_frame->GetDocument()->VisionDeficiencyChanged(); - break; - } } } @@ -1075,13 +1069,6 @@ SettingsChanged(SettingsDelegate::kColorSchemeChange); } -void Page::SetVisionDeficiency(VisionDeficiency new_vision_deficiency) { - if (new_vision_deficiency != vision_deficiency_) { - vision_deficiency_ = new_vision_deficiency; - SettingsChanged(SettingsDelegate::kVisionDeficiencyChange); - } -} - Page::PageClients::PageClients() : chrome_client(nullptr) {} template class CORE_TEMPLATE_EXPORT Supplement<Page>;
diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h index ee101e42..7f5b14a 100644 --- a/third_party/blink/renderer/core/page/page.h +++ b/third_party/blink/renderer/core/page/page.h
@@ -31,7 +31,6 @@ #include "third_party/blink/public/platform/web_text_autosizer_page_info.h" #include "third_party/blink/public/web/web_window_features.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/css/vision_deficiency.h" #include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/frame/hosts_using_features.h" #include "third_party/blink/renderer/core/frame/settings_delegate.h" @@ -343,9 +342,6 @@ } void ClearMediaFeatureOverrides(); - void SetVisionDeficiency(VisionDeficiency new_vision_deficiency); - VisionDeficiency GetVisionDeficiency() const { return vision_deficiency_; } - WebScopedVirtualTimePauser& HistoryNavigationVirtualTimePauser() { return history_navigation_virtual_time_pauser_; } @@ -458,12 +454,9 @@ std::unique_ptr<PageScheduler> page_scheduler_; - // Overrides for various media features, set from DevTools. + // Overrides for various media features set from the devtools. std::unique_ptr<MediaFeatureOverrides> media_feature_overrides_; - // Emulated vision deficiency, set from DevTools. - VisionDeficiency vision_deficiency_ = VisionDeficiency::kNoVisionDeficiency; - int32_t autoplay_flags_; // Accessed by frames to determine whether to expose the PortalHost object.
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc index b4403c1..8d66f2a56 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_test.cc
@@ -1441,7 +1441,10 @@ // After an initial compositing update, we should have one scrolling update // recorded as PreFCP. + GetWebView()->MainFrameWidget()->RecordStartOfFrameMetrics(); ForceFullCompositingUpdate(); + GetWebView()->MainFrameWidget()->RecordEndOfFrameMetrics(base::TimeTicks(), + 0); histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 1); histogram_tester.ExpectTotalCount( "Blink.ScrollingCoordinator.UpdateTime.PreFCP", 1); @@ -1451,7 +1454,10 @@ "Blink.ScrollingCoordinator.UpdateTime.AggregatedPreFCP", 0); // An update with no scrolling changes should not cause a scrolling update. + GetWebView()->MainFrameWidget()->RecordStartOfFrameMetrics(); ForceFullCompositingUpdate(); + GetWebView()->MainFrameWidget()->RecordEndOfFrameMetrics(base::TimeTicks(), + 0); histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 1); histogram_tester.ExpectTotalCount( "Blink.ScrollingCoordinator.UpdateTime.PreFCP", 1); @@ -1463,27 +1469,34 @@ // A change to background color does not need to cause a scrolling update but, // because hit test display items paint, we also cause a scrolling coordinator // update when the background paints. Also render some text to get past FCP. + // Note that this frame is still considered pre-FCP. auto* background = GetFrame()->GetDocument()->getElementById("bg"); background->removeAttribute(html_names::kStyleAttr); background->SetInnerHTMLFromString("Some Text"); + GetWebView()->MainFrameWidget()->RecordStartOfFrameMetrics(); ForceFullCompositingUpdate(); + GetWebView()->MainFrameWidget()->RecordEndOfFrameMetrics(base::TimeTicks(), + 0); histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 2); histogram_tester.ExpectTotalCount( - "Blink.ScrollingCoordinator.UpdateTime.PreFCP", 1); + "Blink.ScrollingCoordinator.UpdateTime.PreFCP", 2); histogram_tester.ExpectTotalCount( - "Blink.ScrollingCoordinator.UpdateTime.PostFCP", 1); + "Blink.ScrollingCoordinator.UpdateTime.PostFCP", 0); histogram_tester.ExpectTotalCount( "Blink.ScrollingCoordinator.UpdateTime.AggregatedPreFCP", 1); // Removing a scrollable area should cause a scrolling update. auto* scroller = GetFrame()->GetDocument()->getElementById("scroller"); scroller->removeAttribute(html_names::kStyleAttr); + GetWebView()->MainFrameWidget()->RecordStartOfFrameMetrics(); ForceFullCompositingUpdate(); + GetWebView()->MainFrameWidget()->RecordEndOfFrameMetrics(base::TimeTicks(), + 0); histogram_tester.ExpectTotalCount("Blink.ScrollingCoordinator.UpdateTime", 3); histogram_tester.ExpectTotalCount( - "Blink.ScrollingCoordinator.UpdateTime.PreFCP", 1); + "Blink.ScrollingCoordinator.UpdateTime.PreFCP", 2); histogram_tester.ExpectTotalCount( - "Blink.ScrollingCoordinator.UpdateTime.PostFCP", 2); + "Blink.ScrollingCoordinator.UpdateTime.PostFCP", 1); histogram_tester.ExpectTotalCount( "Blink.ScrollingCoordinator.UpdateTime.AggregatedPreFCP", 1); }
diff --git a/third_party/blink/renderer/core/style/OWNERS b/third_party/blink/renderer/core/style/OWNERS index d1eb1c3..a007a39 100644 --- a/third_party/blink/renderer/core/style/OWNERS +++ b/third_party/blink/renderer/core/style/OWNERS
@@ -2,6 +2,7 @@ andruud@chromium.org ericwilligers@chromium.org futhark@chromium.org +xiaochengh@chromium.org # TEAM: layout-dev@chromium.org # COMPONENT: Blink>CSS
diff --git a/third_party/blink/renderer/core/svg/svg_element.cc b/third_party/blink/renderer/core/svg/svg_element.cc index c2b425c..1bf5161 100644 --- a/third_party/blink/renderer/core/svg/svg_element.cc +++ b/third_party/blink/renderer/core/svg/svg_element.cc
@@ -296,16 +296,8 @@ Node::InsertionNotificationRequest SVGElement::InsertedInto( ContainerNode& root_parent) { Element::InsertedInto(root_parent); + HideNonce(); UpdateRelativeLengthsInformation(); - - const AtomicString& nonce_value = FastGetAttribute(html_names::kNonceAttr); - if (!nonce_value.IsEmpty()) { - setNonce(nonce_value); - if (InActiveDocument() && - GetDocument().GetContentSecurityPolicy()->HasHeaderDeliveredPolicy()) { - setAttribute(html_names::kNonceAttr, g_empty_atom); - } - } return kInsertionDone; }
diff --git a/third_party/blink/renderer/core/svg/svg_resource.cc b/third_party/blink/renderer/core/svg/svg_resource.cc index 9cf40b6..213d359 100644 --- a/third_party/blink/renderer/core/svg/svg_resource.cc +++ b/third_party/blink/renderer/core/svg/svg_resource.cc
@@ -139,22 +139,7 @@ options.initiator_info.name = fetch_initiator_type_names::kCSS; FetchParameters params(ResourceRequest(url_), options); params.MutableResourceRequest().SetMode( - network::mojom::blink::RequestMode::kSameOrigin); - resource_document_ = - DocumentResource::FetchSVGDocument(params, document.Fetcher(), this); - target_ = ResolveTarget(); -} - -void ExternalSVGResource::LoadWithoutCSP(const Document& document) { - if (resource_document_) - return; - ResourceLoaderOptions options; - options.initiator_info.name = fetch_initiator_type_names::kCSS; - FetchParameters params(ResourceRequest(url_), options); - params.SetContentSecurityCheck( - network::mojom::blink::CSPDisposition::DO_NOT_CHECK); - params.MutableResourceRequest().SetMode( - network::mojom::blink::RequestMode::kSameOrigin); + network::mojom::RequestMode::kSameOrigin); resource_document_ = DocumentResource::FetchSVGDocument(params, document.Fetcher(), this); target_ = ResolveTarget();
diff --git a/third_party/blink/renderer/core/svg/svg_resource.h b/third_party/blink/renderer/core/svg/svg_resource.h index aab5fd2..2272dda 100644 --- a/third_party/blink/renderer/core/svg/svg_resource.h +++ b/third_party/blink/renderer/core/svg/svg_resource.h
@@ -64,7 +64,6 @@ virtual ~SVGResource(); virtual void Load(const Document&) {} - virtual void LoadWithoutCSP(const Document&) {} Element* Target() const { return target_; } LayoutSVGResourceContainer* ResourceContainer() const; @@ -118,7 +117,6 @@ explicit ExternalSVGResource(const KURL&); void Load(const Document&) override; - void LoadWithoutCSP(const Document&) override; void Trace(Visitor*) override;
diff --git a/third_party/blink/renderer/platform/graphics/OWNERS b/third_party/blink/renderer/platform/graphics/OWNERS index 73a6535..0bb32866 100644 --- a/third_party/blink/renderer/platform/graphics/OWNERS +++ b/third_party/blink/renderer/platform/graphics/OWNERS
@@ -13,6 +13,7 @@ # For surface ID propagation and synchronization samans@chromium.org +jonross@chromium.org # lowLatency canvas mcasas@chromium.org
diff --git a/third_party/blink/renderer/platform/scheduler/BUILD.gn b/third_party/blink/renderer/platform/scheduler/BUILD.gn index a3ff491..3caa75a 100644 --- a/third_party/blink/renderer/platform/scheduler/BUILD.gn +++ b/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -89,6 +89,8 @@ "main_thread/main_thread_task_queue.h", "main_thread/memory_purge_manager.cc", "main_thread/memory_purge_manager.h", + "main_thread/non_waking_time_domain.cc", + "main_thread/non_waking_time_domain.h", "main_thread/page_scheduler_impl.cc", "main_thread/page_scheduler_impl.h", "main_thread/page_visibility_state.cc",
diff --git a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc index e685d5dd..c456a69 100644 --- a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc +++ b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -175,6 +175,10 @@ return base::ThreadTaskRunnerHandle::Get(); } + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override { + return base::ThreadTaskRunnerHandle::Get(); + } + std::unique_ptr<PageScheduler> CreatePageScheduler( PageScheduler::Delegate*) override { return std::make_unique<DummyPageScheduler>();
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc index 920153dc..97dbeaa 100644 --- a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.cc
@@ -61,6 +61,11 @@ return base::ThreadTaskRunnerHandle::Get(); } +scoped_refptr<base::SingleThreadTaskRunner> +SimpleThreadScheduler::NonWakingTaskRunner() { + return base::ThreadTaskRunnerHandle::Get(); +} + std::unique_ptr<PageScheduler> SimpleThreadScheduler::CreatePageScheduler( PageScheduler::Delegate* delegate) { return nullptr;
diff --git a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h index 35c83b2..1111310 100644 --- a/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/common/simple_thread_scheduler.h
@@ -55,6 +55,7 @@ scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override; + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() override;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index 222c1ee..edd6883 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -436,6 +436,7 @@ case TaskType::kWorkerThreadTaskQueueDefault: case TaskType::kWorkerThreadTaskQueueV8: case TaskType::kWorkerThreadTaskQueueCompositor: + case TaskType::kMainThreadTaskQueueNonWaking: // The web scheduling API task types are used by WebSchedulingTaskQueues. // The associated TaskRunner should be obtained by creating a // WebSchedulingTaskQueue with CreateWebSchedulingTaskQueue().
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index 5ebcf94..e3a5cd6b 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -216,6 +216,7 @@ TaskQueue::QueuePriority::kBestEffortPriority))), memory_purge_manager_(memory_purge_task_queue_->CreateTaskRunner( TaskType::kMainThreadTaskQueueMemoryPurge)), + non_waking_time_domain_(tick_clock()), delayed_update_policy_runner_( base::BindRepeating(&MainThreadSchedulerImpl::UpdatePolicy, base::Unretained(this)), @@ -237,12 +238,18 @@ task_runners_.emplace(compositor_task_queue_, compositor_task_queue_->CreateQueueEnabledVoter()); + RegisterTimeDomain(&non_waking_time_domain_); + v8_task_queue_ = NewTaskQueue(MainThreadTaskQueue::QueueCreationParams( MainThreadTaskQueue::QueueType::kV8)); ipc_task_queue_ = NewTaskQueue(MainThreadTaskQueue::QueueCreationParams( MainThreadTaskQueue::QueueType::kIPC)); cleanup_task_queue_ = NewTaskQueue(MainThreadTaskQueue::QueueCreationParams( MainThreadTaskQueue::QueueType::kCleanup)); + non_waking_task_queue_ = + NewTaskQueue(MainThreadTaskQueue::QueueCreationParams( + MainThreadTaskQueue::QueueType::kNonWaking) + .SetTimeDomain(&non_waking_time_domain_)); v8_task_runner_ = v8_task_queue_->CreateTaskRunner(TaskType::kMainThreadTaskQueueV8); @@ -254,6 +261,8 @@ ipc_task_queue_->CreateTaskRunner(TaskType::kMainThreadTaskQueueIPC); cleanup_task_runner_ = cleanup_task_queue_->CreateTaskRunner( TaskType::kMainThreadTaskQueueCleanup); + non_waking_task_runner_ = non_waking_task_queue_->CreateTaskRunner( + TaskType::kMainThreadTaskQueueNonWaking); // TaskQueueThrottler requires some task runners, then initialize // TaskQueueThrottler after task queues/runners are initialized. @@ -305,6 +314,8 @@ pair.first->ShutdownTaskQueue(); } + UnregisterTimeDomain(&non_waking_time_domain_); + if (virtual_time_domain_) UnregisterTimeDomain(virtual_time_domain_.get()); @@ -2324,6 +2335,11 @@ return compositor_task_runner_; } +scoped_refptr<base::SingleThreadTaskRunner> +MainThreadSchedulerImpl::NonWakingTaskRunner() { + return non_waking_task_runner_; +} + std::unique_ptr<PageScheduler> MainThreadSchedulerImpl::CreatePageScheduler( PageScheduler::Delegate* delegate) { return std::make_unique<PageSchedulerImpl>(delegate, this);
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h index f275b2bd..5efc92d 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -37,6 +37,7 @@ #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h" +#include "third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/pending_user_input.h" #include "third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h" @@ -163,6 +164,7 @@ // Note: this is also shared by the ThreadScheduler interface. scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> CleanupTaskRunner() override; + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner() override; std::unique_ptr<WebRenderWidgetSchedulingState> @@ -808,17 +810,20 @@ scoped_refptr<MainThreadTaskQueue> ipc_task_queue_; scoped_refptr<MainThreadTaskQueue> cleanup_task_queue_; scoped_refptr<MainThreadTaskQueue> memory_purge_task_queue_; + scoped_refptr<MainThreadTaskQueue> non_waking_task_queue_; scoped_refptr<base::SingleThreadTaskRunner> v8_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> cleanup_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> non_waking_task_runner_; MemoryPurgeManager memory_purge_manager_; // Note |virtual_time_domain_| is lazily created. std::unique_ptr<AutoAdvancingVirtualTimeDomain> virtual_time_domain_; + NonWakingTimeDomain non_waking_time_domain_; base::RepeatingClosure update_policy_closure_; DeadlineTaskRunner delayed_update_policy_runner_;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc index 474b338..5e7e3d8 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -3538,6 +3538,52 @@ EXPECT_FALSE(scheduler_->IsBeginMainFrameScheduled()); } +TEST_F(MainThreadSchedulerImplTest, NonWakingTaskQueue) { + std::vector<std::pair<std::string, base::TimeTicks>> log; + base::TimeTicks start = scheduler_->GetTickClock()->NowTicks(); + + scheduler_->DefaultTaskQueue()->task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + [](std::vector<std::pair<std::string, base::TimeTicks>>* log, + const base::TickClock* clock) { + log->emplace_back("regular (immediate)", clock->NowTicks()); + }, + &log, scheduler_->GetTickClock())); + scheduler_->NonWakingTaskRunner()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + [](std::vector<std::pair<std::string, base::TimeTicks>>* log, + const base::TickClock* clock) { + log->emplace_back("non-waking", clock->NowTicks()); + }, + &log, scheduler_->GetTickClock()), + base::TimeDelta::FromSeconds(3)); + scheduler_->DefaultTaskQueue()->task_runner()->PostDelayedTask( + FROM_HERE, + base::BindOnce( + [](std::vector<std::pair<std::string, base::TimeTicks>>* log, + const base::TickClock* clock) { + log->emplace_back("regular (delayed)", clock->NowTicks()); + }, + &log, scheduler_->GetTickClock()), + base::TimeDelta::FromSeconds(5)); + + test_task_runner_->FastForwardUntilNoTasksRemain(); + + // Check that the non-waking task runner didn't generate an unnecessary + // wake-up. + // Note: the exact order of these tasks is not fixed and depends on the time + // domain iteration order. + EXPECT_THAT( + log, + testing::UnorderedElementsAre( + std::make_pair("regular (immediate)", start), + std::make_pair("non-waking", start + base::TimeDelta::FromSeconds(5)), + std::make_pair("regular (delayed)", + start + base::TimeDelta::FromSeconds(5)))); +} + class VeryHighPriorityForCompositingAlwaysExperimentTest : public MainThreadSchedulerImplTest { public:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc index d008643..0d54d31 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
@@ -63,6 +63,8 @@ return "other_tq"; case MainThreadTaskQueue::QueueType::kWebScheduling: return "web_scheduling_tq"; + case MainThreadTaskQueue::QueueType::kNonWaking: + return "non_waking_tq"; case MainThreadTaskQueue::QueueType::kCount: NOTREACHED(); return nullptr; @@ -95,6 +97,7 @@ case MainThreadTaskQueue::QueueType::kInput: case MainThreadTaskQueue::QueueType::kDetached: case MainThreadTaskQueue::QueueType::kCleanup: + case MainThreadTaskQueue::QueueType::kNonWaking: case MainThreadTaskQueue::QueueType::kOther: return false; case MainThreadTaskQueue::QueueType::kCount: @@ -114,6 +117,7 @@ case QueueType::kTest: case QueueType::kV8: case QueueType::kIPC: + case QueueType::kNonWaking: case QueueType::kCleanup: return QueueClass::kNone; case QueueType::kFrameLoading:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h index c1ea93cd..4329479 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
@@ -76,10 +76,11 @@ // 22 : kWebSchedulingBestEffort, obsolete. kWebScheduling = 24, + kNonWaking = 25, // Used to group multiple types when calculating Expected Queueing Time. kOther = 23, - kCount = 25 + kCount = 26 }; // Returns name of the given queue type. Returned string has application
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.cc b/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.cc new file mode 100644 index 0000000..13d6f4a9 --- /dev/null +++ b/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.cc
@@ -0,0 +1,45 @@ +// 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 "third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h" + +namespace blink { +namespace scheduler { + +NonWakingTimeDomain::NonWakingTimeDomain(const base::TickClock* tick_clock) + : tick_clock_(tick_clock) {} + +NonWakingTimeDomain::~NonWakingTimeDomain() = default; + +base::sequence_manager::LazyNow NonWakingTimeDomain::CreateLazyNow() const { + return base::sequence_manager::LazyNow(tick_clock_); +} + +base::TimeTicks NonWakingTimeDomain::Now() const { + return tick_clock_->NowTicks(); +} + +base::Optional<base::TimeDelta> NonWakingTimeDomain::DelayTillNextTask( + base::sequence_manager::LazyNow* lazy_now) { + // NonWakingTimeDomain should never generate wakeups on its own. + return base::nullopt; +} + +bool NonWakingTimeDomain::MaybeFastForwardToNextTask( + bool quit_when_idle_requested) { + return false; +} + +const char* NonWakingTimeDomain::GetName() const { + return "non_waking_time_domain"; +} + +void NonWakingTimeDomain::SetNextDelayedDoWork( + base::sequence_manager::LazyNow* lazy_now, + base::TimeTicks run_time) { + // Do not request a wake-up, unlike a regular TimeDomain. +} + +} // namespace scheduler +} // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h b/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.h new file mode 100644 index 0000000..9641ed9 --- /dev/null +++ b/third_party/blink/renderer/platform/scheduler/main_thread/non_waking_time_domain.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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_NON_WAKING_TIME_DOMAIN_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_NON_WAKING_TIME_DOMAIN_H_ + +#include "base/task/sequence_manager/time_domain.h" +#include "base/time/tick_clock.h" + +namespace blink { +namespace scheduler { + +// A time domain which never generates wake-ups on its own. Useful for tasks +// which should run only when the system is non-idle. +class NonWakingTimeDomain : public base::sequence_manager::TimeDomain { + public: + explicit NonWakingTimeDomain(const base::TickClock* tick_clock); + ~NonWakingTimeDomain() override; + + // TimeDomain: + base::sequence_manager::LazyNow CreateLazyNow() const override; + base::TimeTicks Now() const override; + base::Optional<base::TimeDelta> DelayTillNextTask( + base::sequence_manager::LazyNow* lazy_now) override; + bool MaybeFastForwardToNextTask(bool quit_when_idle_requested) override; + const char* GetName() const override; + void SetNextDelayedDoWork(base::sequence_manager::LazyNow* lazy_now, + base::TimeTicks run_time) override; + + private: + const base::TickClock* tick_clock_; +}; + +} // namespace scheduler +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_NON_WAKING_TIME_DOMAIN_H_
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc index 46cbd2b..52ffc2cb 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/task_type_names.cc
@@ -107,6 +107,8 @@ return "MainThreadTaskQueueCleanup"; case TaskType::kMainThreadTaskQueueMemoryPurge: return "MainThreadTaskQueueMemoryPurge"; + case TaskType::kMainThreadTaskQueueNonWaking: + return "MainThreadTaskQueueNonWaking"; case TaskType::kInternalIntersectionObserver: return "InternalIntersectionObserver"; case TaskType::kCompositorThreadTaskQueueDefault:
diff --git a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h index 0f1eddf..20e3e743 100644 --- a/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
@@ -89,6 +89,11 @@ // Returns a task runner for kV8 tasks. Can be called from any thread. virtual scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() = 0; + // Returns a task runner which does not generate system wakeups on its own. + // This means that if a delayed task is posted to it, it will run when + // the delay expires AND another task runs. + virtual scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() = 0; + // Returns a task runner for compositor tasks. This is intended only to be // used by specific animation and rendering related tasks (e.g. animated GIFS) // and should not generally be used.
diff --git a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc index 9580c0b..0bc371a 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
@@ -93,6 +93,12 @@ return nullptr; } +scoped_refptr<base::SingleThreadTaskRunner> +CompositorThreadScheduler::NonWakingTaskRunner() { + NOTREACHED(); + return nullptr; +} + bool CompositorThreadScheduler::CanExceedIdleDeadlineIfRequired() const { return false; }
diff --git a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h index 8dc3759..3c808170 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
@@ -43,6 +43,7 @@ scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override; + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override; bool ShouldYieldForHighPriorityWork() override; bool CanExceedIdleDeadlineIfRequired() const override; void AddTaskObserver(base::TaskObserver* task_observer) override;
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc index b9a44ecc..5de97638 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -197,6 +197,7 @@ case TaskType::kMainThreadTaskQueueControl: case TaskType::kMainThreadTaskQueueCleanup: case TaskType::kMainThreadTaskQueueMemoryPurge: + case TaskType::kMainThreadTaskQueueNonWaking: case TaskType::kCompositorThreadTaskQueueDefault: case TaskType::kCompositorThreadTaskQueueInput: case TaskType::kWorkerThreadTaskQueueDefault:
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc index 6a202f8..4434805 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
@@ -155,6 +155,12 @@ return nullptr; } +scoped_refptr<base::SingleThreadTaskRunner> +WorkerThreadScheduler::NonWakingTaskRunner() { + NOTREACHED() << "Not implemented"; + return nullptr; +} + bool WorkerThreadScheduler::CanExceedIdleDeadlineIfRequired() const { DCHECK(initialized_); return idle_helper_.CanExceedIdleDeadlineIfRequired();
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h index fb26754..130a125 100644 --- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h +++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
@@ -50,6 +50,7 @@ scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override; + scoped_refptr<base::SingleThreadTaskRunner> NonWakingTaskRunner() override; bool ShouldYieldForHighPriorityWork() override; bool CanExceedIdleDeadlineIfRequired() const override; void AddTaskObserver(base::TaskObserver* task_observer) override;
diff --git a/third_party/blink/renderer/platform/wtf/vector.h b/third_party/blink/renderer/platform/wtf/vector.h index 7f3573e..f43d3c30 100644 --- a/third_party/blink/renderer/platform/wtf/vector.h +++ b/third_party/blink/renderer/platform/wtf/vector.h
@@ -2017,7 +2017,6 @@ Allocator::template Trace<T, VectorTraits<T>>( visitor, *const_cast<T*>(buffer_entry)); } - CheckUnusedSlots(Buffer() + size(), Buffer() + capacity()); } } }
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py index 51056c1..2a95be7 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/fuchsia.py
@@ -125,7 +125,8 @@ self._process.kill() class _TargetHost(object): - def __init__(self, build_path, ports_to_forward, target_device): + def __init__(self, build_path, ports_to_forward, target_device, + results_directory): try: self._target = None target_args = { @@ -146,12 +147,12 @@ }) self._target = aemu_target.AemuTarget(**target_args) self._target.Start() - self._setup_target(build_path, ports_to_forward) + self._setup_target(build_path, ports_to_forward, results_directory) except: self.cleanup() raise - def _setup_target(self, build_path, ports_to_forward): + def _setup_target(self, build_path, ports_to_forward, results_directory): # Tell SSH to forward all server ports from the Fuchsia device to # the host. forwarding_flags = [ @@ -165,6 +166,12 @@ ssh_args=forwarding_flags, stderr=subprocess.PIPE) + listener_log_path = os.path.join(results_directory, 'system.log') + listener_log = open(listener_log_path,'w') + self._listener = self._target.RunCommandPiped(['log_listener'], + stderr=listener_log, + stdout=listener_log) + package_path = os.path.join(build_path, CONTENT_SHELL_PACKAGE_PATH) self._target.InstallPackage([package_path]) @@ -228,7 +235,8 @@ super(FuchsiaPort, self).setup_test_run() try: self._target_host = _TargetHost( - self._build_path(), self.SERVER_PORTS, self._target_device) + self._build_path(), self.SERVER_PORTS, self._target_device, + self.results_directory()) if self.get_option('zircon_logging'): self._zircon_logger = SubprocessOutputLogger(
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index e35a693..7bc696b 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5209,22 +5209,6 @@ # Utility for manual testing, not intended to be run as part of layout tests. crbug.com/785955 http/tests/credentialmanager/tools/virtual-authenticator-environment-manual.html [ Skip ] -# These Web Authentication API would require either real hardware, or -# virtual simulation thereof (work in progress, see: https://crbug.com/785955). -# Sheriff 2018-08-16 -crbug.com/826936 external/wpt/webauthn/createcredential-badargs-authnrselection.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/createcredential-badargs-rp.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/createcredential-badargs-user.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/createcredential-excludecredentials.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/createcredential-passing.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/createcredential-badargs-challenge.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/createcredential-pubkeycredparams.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/getcredential-badargs-rpid.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/getcredential-badargs-userverification.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/getcredential-extensions.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/getcredential-passing.https.html [ Pass Timeout Failure ] -crbug.com/826936 external/wpt/webauthn/getcredential-timeout.https.html [ Pass Timeout Failure ] - # Sheriff 2018-04-11 crbug.com/831796 fast/events/autoscroll-in-textfield.html [ Failure Pass ] crbug.com/831673 http/tests/devtools/reveal-objects.js [ Pass Timeout ] @@ -6764,3 +6748,6 @@ # Sheriff 2020-03-04 crbug.com/1058244 [ Mac ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scrollbar-rtl-manipulation.html [ Pass Failure ] + +# Ecosystem-Infra Sheriff 2020-03-04 +crbug.com/1058403 external/wpt/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/nonces.html b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/nonces.html index b023d060..7ee10a7 100644 --- a/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/nonces.html +++ b/third_party/blink/web_tests/external/wpt/content-security-policy/nonce-hiding/nonces.html
@@ -3,30 +3,62 @@ <script src="/resources/testharnessreport.js"></script> <div id=log></div> <script> -[["meh", ""], - ["div", ""], - ["script", ""], - ["meh", "http://www.w3.org/2000/svg"], - ["svg", "http://www.w3.org/2000/svg"], - ["script", "http://www.w3.org/2000/svg"]].forEach(([localName, namespace]) => { - test(t => { - const element = namespace === "" ? document.createElement(localName) : document.createElementNS(namespace, localName); - t.add_cleanup(() => element.remove()); - assert_equals(element.nonce, "", "Initial IDL attribute value"); - element.setAttribute("nonce", "x"); - assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set"); - assert_equals(element.getAttribute("nonce"), "x", "Content attribute is modified after content attribute set"); - document.body.appendChild(element); - assert_equals(element.nonce, "x", "IDL attribute is unchanged after element insertion"); - assert_equals(element.getAttribute("nonce"), "", "Content attribute is changed after element insertion"); - }, `Basic nonce tests for ${localName} in ${namespace === "" ? "HTML" : "SVG"} namespace`); + const namespace_url= { + "HTML": "http://www.w3.org/1999/xhtml", + "SVG": "http://www.w3.org/2000/svg", + } + const test_cases = [ + ["meh" , "HTML"], + ["div" , "HTML"], + ["script" , "HTML"], + ["meh" , "SVG"], + ["svg" , "SVG"], + ["script" , "SVG"], + ]; - test(t => { - const element = namespace === "" ? document.createElement(localName) : document.createElementNS(namespace, localName); - element.setAttribute("nonce", "x"); - assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set"); - element.removeAttribute("nonce"); - assert_equals(element.nonce, "", "IDL attribute is empty after content attribute removal"); - }, `Ensure that removal of content attribute does not affect IDL attribute for ${localName} in ${namespace === "" ? "HTML" : "SVG"} namespace`); -}); + test_cases.forEach(([localName, namespace]) => { + test(t => { + const element = document.createElementNS(namespace_url[namespace], localName); + t.add_cleanup(() => element.remove()); + assert_equals(element.nonce, "", "Initial IDL attribute value"); + assert_equals(element.getAttribute("nonce"), null, "Initial content attribute"); + + element.setAttribute("nonce", "x"); + assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set"); + assert_equals(element.getAttribute("nonce"), "x", "Content attribute is modified after content attribute set"); + + document.body.appendChild(element); + assert_equals(element.nonce, "x", "IDL attribute is unchanged after element insertion"); + assert_equals(element.getAttribute("nonce"), "", "Content attribute is changed after element insertion"); + }, `Basic nonce tests for ${localName} in ${namespace} namespace`); + + test(t => { + const element = document.createElementNS(namespace_url[namespace], localName); + t.add_cleanup(() => element.remove()); + element.setAttribute("nonce", "x"); + assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set"); + + element.removeAttribute("nonce"); + assert_equals(element.nonce, "", "IDL attribute is empty after content attribute removal"); + }, `Ensure that removal of content attribute does not affect IDL attribute for ${localName} in ${namespace} namespace`); + + test(t => { + const element = document.createElementNS(namespace_url[namespace], localName); + t.add_cleanup(() => element.remove()); + assert_equals(element.nonce, ""); + assert_equals(element.getAttribute("nonce"), null); + + element.setAttribute("nonce", ""); + assert_equals(element.nonce, ""); + assert_equals(element.getAttribute("nonce"), ""); + + document.body.appendChild(element); + assert_equals(element.nonce, ""); + assert_equals(element.getAttribute("nonce"), ""); + + element.removeAttribute("nonce"); + assert_equals(element.nonce, ""); + assert_equals(element.getAttribute("nonce"), null); + }, `Test empty nonces for ${localName} in ${namespace} namespace`); + }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https-expected.txt deleted file mode 100644 index c10a465..0000000 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -This is a testharness.js-based test. -PASS Set up the test environment -FAIL Bad AuthenticatorSelectionCriteria: authenticatorSelection is empty array assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad AuthenticatorSelectionCriteria: authenticatorSelection is null assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection is empty string -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection is string -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection attachment is empty string -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection attachment is empty object -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection attachment is null -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection attachment platform -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection residentKey true -FAIL Bad AuthenticatorSelectionCriteria: authenticatorSelection residentKey is string promise_rejects_js: Expected bad parameters to fail function "function() { throw e }" threw object "NotAllowedError: The operation either timed out or was not allowed. See: https://w3c.github.io/webauthn/#sec-assertion-privacy." ("NotAllowedError") expected instance of function "function TypeError() { [native code] }" ("TypeError") -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection userVerification empty string -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection userVerification empty object -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection userVerification bad value -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection userVerification null -PASS Bad AuthenticatorSelectionCriteria: authenticatorSelection userVerification required -PASS Clean up the test environment -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html index 5da0745..9497a001 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html +++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-authnrselection.https.html
@@ -46,8 +46,6 @@ authnrSelBadUvNull.userVerification = null; // authenticatorSelection bad values - new CreateCredentialsTest("options.publicKey.authenticatorSelection", []).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is empty array", TypeError); - new CreateCredentialsTest("options.publicKey.authenticatorSelection", null).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is null", TypeError); new CreateCredentialsTest("options.publicKey.authenticatorSelection", "").runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is empty string", TypeError); new CreateCredentialsTest("options.publicKey.authenticatorSelection", "none").runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is string", TypeError); @@ -65,10 +63,6 @@ new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelRkTrue) .modify("options.publicKey.timeout", 300) .runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection residentKey true", "NotAllowedError"); - new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelRkBadString) - .modify("options.publicKey.timeout", 300) - .runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection residentKey is string", TypeError); - // TODO: not sure if rk is "boolean" or "truthy"; add test cases if it should only accept boolean values // authenticatorSelection bad userVerification values new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelBadUvEmptyStr).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection userVerification empty string", TypeError);
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-rp.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-rp.https-expected.txt deleted file mode 100644 index c28fc6f..0000000 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-rp.https-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -This is a testharness.js-based test. -PASS Set up the test environment -PASS Bad rp: rp missing -PASS Bad rp: rp null -PASS Bad rp: rp is string -PASS Bad rp: rp is empty object -FAIL Bad rp: id is object promise_rejects_js: Expected bad parameters to fail function "function() { throw e }" threw object "SecurityError: The relying party ID is not a registrable domain suffix of, nor equal to the current domain." ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") -PASS Bad rp: id is null -PASS Bad rp: id is empty String -PASS Bad rp: id is invalid domain (has space) -PASS Bad rp: id is invalid domain (starts with dash) -PASS Bad rp: id is invalid domain (starts with number) -PASS rp missing name -FAIL Bad rp: name is object assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad rp: name is null assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad rp: name is empty String assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad rp: icon is object promise_rejects_js: Expected bad parameters to fail function "function() { throw e }" threw object "SecurityError: 'rp.icon' should be a secure URL" ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") -FAIL Bad rp: icon is null promise_rejects_js: Expected bad parameters to fail function "function() { throw e }" threw object "SecurityError: 'rp.icon' should be a secure URL" ("SecurityError") expected instance of function "function TypeError() { [native code] }" ("TypeError") -FAIL Bad rp: icon is empty String assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -PASS Bad rp: icon is insecure -PASS Clean up the test environment -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-rp.https.html b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-rp.https.html index cbd86b8..8886cc1 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-rp.https.html +++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-badargs-rp.https.html
@@ -21,7 +21,6 @@ new CreateCredentialsTest("options.publicKey.rp", {}).runTest("Bad rp: rp is empty object", TypeError); // // rp.id - new CreateCredentialsTest("options.publicKey.rp.id", {}).runTest("Bad rp: id is object", TypeError); new CreateCredentialsTest("options.publicKey.rp.id", null).runTest("Bad rp: id is null", "SecurityError"); new CreateCredentialsTest("options.publicKey.rp.id", "").runTest("Bad rp: id is empty String", "SecurityError"); new CreateCredentialsTest("options.publicKey.rp.id", "invalid domain.com").runTest("Bad rp: id is invalid domain (has space)", "SecurityError"); @@ -30,17 +29,10 @@ // // rp.name new CreateCredentialsTest({path: "options.publicKey.rp.name", value: undefined}).runTest("rp missing name", TypeError); - new CreateCredentialsTest("options.publicKey.rp.name", {}).runTest("Bad rp: name is object", TypeError); - new CreateCredentialsTest("options.publicKey.rp.name", null).runTest("Bad rp: name is null", TypeError); - new CreateCredentialsTest("options.publicKey.rp.name", "").runTest("Bad rp: name is empty String", TypeError); - // // rp.icon - new CreateCredentialsTest("options.publicKey.rp.icon", {}).runTest("Bad rp: icon is object", TypeError); - new CreateCredentialsTest("options.publicKey.rp.icon", null).runTest("Bad rp: icon is null", TypeError); - new CreateCredentialsTest("options.publicKey.rp.icon", "").runTest("Bad rp: icon is empty String", TypeError); + // rp.icon new CreateCredentialsTest("options.publicKey.rp.icon", "http://fidoalliance.co.nz/testimages/catimage.png") .runTest("Bad rp: icon is insecure", "SecurityError"); - // // TODO: unicode tests for icon URL (see also: USVString) }); /* JSHINT */
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-excludecredentials.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-excludecredentials.https-expected.txt index b7f4ce9..aefa11e9 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-excludecredentials.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-excludecredentials.https-expected.txt
@@ -1,5 +1,4 @@ This is a testharness.js-based test. -PASS Set up the test environment PASS Bad excludeCredentials: string PASS Bad excludeCredentials: empty object PASS excludeCredentials missing
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https-expected.txt deleted file mode 100644 index 957f89c..0000000 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -This is a testharness.js-based test. -PASS Bad extensions: extensions is string -FAIL Bad extensions: extensions is null assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad extensions: extensions is empty Array assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad extensions: extensions is empty ArrayBuffer assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad extensions: malformatted JSON assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad extensions: JavaScript object assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -FAIL Bad extensions: extension ID too long assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code -PASS extensions is a nonsensical JSON string -PASS empty appid in create request -PASS null appid in create request -PASS appid in create request -PASS Clean up the test environment -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html index 036200dbb..46cab30 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html +++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-extensions.https.html
@@ -21,15 +21,6 @@ // bad extension values new CreateCredentialsTest("options.publicKey.extensions", "hi mom").runTest("Bad extensions: extensions is string", TypeError); - new CreateCredentialsTest("options.publicKey.extensions", null).runTest("Bad extensions: extensions is null", TypeError); - new CreateCredentialsTest("options.publicKey.extensions", []).runTest("Bad extensions: extensions is empty Array", TypeError); - new CreateCredentialsTest("options.publicKey.extensions", new ArrayBuffer(0)).runTest("Bad extensions: extensions is empty ArrayBuffer", TypeError); - var badJson = '{"foo": true, "bar: "yup"}'; // missing quote after "bar" - new CreateCredentialsTest("options.publicKey.extensions", {foo: badJson}).runTest("Bad extensions: malformatted JSON", TypeError); - new CreateCredentialsTest("options.publicKey.extensions", {foo: dummyExtension}).runTest("Bad extensions: JavaScript object", TypeError); - var badExtId = {}; - badExtId[createRandomString(65)] = dummyExtension; - new CreateCredentialsTest("options.publicKey.extensions", {badExtId: dummyExtension}).runTest("Bad extensions: extension ID too long", TypeError); // phony extensions // TODO: not sure if this should pass or fail
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https-expected.txt index 4de4f55..ea74f1e 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-passing.https-expected.txt
@@ -1,5 +1,4 @@ This is a testharness.js-based test. -PASS Set up the test environment PASS passing credentials.create() with default arguments FAIL passing credentials.create() with rpId (host and port) promise_test: Unhandled rejection with value: object "SecurityError: The relying party ID is not a registrable domain suffix of, nor equal to the current domain." PASS passing credentials.create() with rpId (hostname)
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-pubkeycredparams.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-pubkeycredparams.https-expected.txt index f4b9e50..878f2ddf 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/createcredential-pubkeycredparams.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webauthn/createcredential-pubkeycredparams.https-expected.txt
@@ -1,5 +1,4 @@ This is a testharness.js-based test. -PASS Set up the test environment PASS Bad pubKeyCredParams: pubKeyCredParams is undefined PASS Bad pubKeyCredParams: pubKeyCredParams is string PASS Bad pubKeyCredParams: pubKeyCredParams is null
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https-expected.txt index 7f8bf6c..402ef6fc 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-extensions.https-expected.txt
@@ -1,5 +1,4 @@ This is a testharness.js-based test. -PASS Set up the test environment PASS Bad extensions: extensions is string FAIL Bad extensions: extensions is null assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code FAIL Bad extensions: extensions is empty Array assert_unreached: Should have rejected: Expected bad parameters to fail Reached unreachable code
diff --git a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-passing.https-expected.txt b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-passing.https-expected.txt index ddbee33..cbb45aa 100644 --- a/third_party/blink/web_tests/external/wpt/webauthn/getcredential-passing.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webauthn/getcredential-passing.https-expected.txt
@@ -1,5 +1,4 @@ This is a testharness.js-based test. -PASS Set up the test environment PASS passing credentials.get() with default args PASS passing credentials.create() with no timeout PASS rpId undefined
diff --git a/third_party/blink/web_tests/inspector-protocol/emulation/set-vision-deficiency-expected.txt b/third_party/blink/web_tests/inspector-protocol/emulation/set-vision-deficiency-expected.txt deleted file mode 100644 index 1699891..0000000 --- a/third_party/blink/web_tests/inspector-protocol/emulation/set-vision-deficiency-expected.txt +++ /dev/null
@@ -1,42 +0,0 @@ -Tests that vision deficiencies can be emulated. -<p>Emulating none: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg=="> -<p>Emulating achromatomaly: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAGFJREFUWIXt10ENwCAUBFFAATbQxBErtVNdyAARs016mCdgM/m3X8capwTtdybnSouufcBAykDKQMpAykDKQMpAykDKQKr2/kR/krTfX9BAykDKQMpAykDKQMpAykDKQOoCayUFlTeCp/sAAAAASUVORK5CYII="> -<p>Emulating achromatopsia: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFpJREFUWIXt10ENADEMxMD2eARR2IfQFYS3Uh8eACsrv+zu/lfQzCTn1hddu8BAykDKQMpAykDKQMpAykDKQGpXVfQnSXv+ggZSBlIGUgZSBlIGUgZSBlIGUgcPVwX7L3bHewAAAABJRU5ErkJggg=="> -<p>Emulating blurredVision: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAehJREFUWIXtl81u4jAURo8TN7RpASXqohKLvsG89DzXLJFm1ZZCyb89i5tAWtAQYlfqIp90FWEl1yfX186H4tdvy3wN8Qvc7CGoQVnA8n8psAqMhiqGfQrbFWye4X0FWSrjRst9qAv5zkuzWEPyBx7+QrQDXbZwAwBRUEdQPsDuSYbKOeQJFAtQZhTUZ8C7F4FbrGG2EUBlhgHaQACLhQzlCURbCAtZicOLjqueAN7spXK3G5i9jQCcyfz5TlokLI9tMp6rBxjUkjQsBU4X1wEC1GUPrOn18KUcQwCV4WwM6kF6z1hvVfsMeJA9E5d07hk/lesUeMv0TZoAXTUBumoCdFXvHFRf4pKuvX+cNDbgJIDBn7qT8AusMRqaSKKO2rmvdDPd80aDDb1CaqpY/Fy+FKZRdmspOaq4B9pV0xUwS8VsAkRLN8OapWJYmxmYEB/9qXlfCUue+LH8WQplfKyiozSbZ3nr7bb1dM0AuB6kCWVZy7nAfTxCdS9jHjaNVDBLxKh2Nl0NBOwmN1qcdRVDed/7s+ReQcXtqyWor1ja0xSHpe5OBKPbHnTfKIqwsIddqxgJ2F39n4cK1bREri5YHa+2/9s5q/UM6FdfvsU/Tz/ezUyArpoAXTUBumoCdNUE6KoJ0FX/AAow6PKlz4YvAAAAAElFTkSuQmCC"> -<p>Emulating none: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg=="> -<p>Emulating deuteranomaly: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAGFJREFUWIXt1zENwDAQBMG3IaQ0uWAzHGNwHxoOiL1IKXYAnFbffRv3dSromSs5Vz269gEDKQMpAykDKQMpAykDKQMpA6lWtaM/SdrvL2ggZSBlIGUgZSBlIGUgZSBlIPUCZwcGA/y3590AAAAASUVORK5CYII="> -<p>Emulating deuteranopia: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF9JREFUWIXt17ENwCAQBMGHYohdqKuhEsduBorYQyLYKeC0+uzbM8aqoO9/k3PVo2sHGEgZSBlIGUgZSBlIGUgZSBlItaoZ/UnSrr+ggZSBlIGUgZSBlIGUgZSBlIHUBmSnBbHzufJtAAAAAElFTkSuQmCC"> -<p>Emulating none: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg=="> -<p>Emulating protanomaly: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAGFJREFUWIXt1zENwDAQBMG3EaQzsqA0GENwHRQOiL1IKXYAnFbffRv3dSromSs5Vz269gEDKQMpAykDKQMpAykDKQMpA6lWtaM/SdrvL2ggZSBlIGUgZSBlIGUgZSBlIPUC9+8GC+XyxMUAAAAASUVORK5CYII="> -<p>Emulating protanopia: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF9JREFUWIXt10ENwCAQBdEFI5VBahcnnEhVURHzm/QwT8DPZG/bxn2dCnr2TM5Vj659wEDKQMpAykDKQMpAykDKQMpAqlWt6E+S9vsLGkgZSBlIGUgZSBlIGUgZSBlIvZuvBc8DKP+1AAAAAElFTkSuQmCC"> -<p>Emulating tritanomaly: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFxJREFUWIXt18EJACEQBEEVczA78zQhoxA0iJ6De3QFMDT729rnuCXo7JWcKy269gEDKQMpAykDKQMpAykDKQMpA6me/iHSfn9BAykDKQMpAykDKQMpAykDKQOpB4zjBwAkamC5AAAAAElFTkSuQmCC"> -<p>Emulating tritanopia: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF5JREFUWIXt17ENwCAQBEGwEC0RuQBaoP8qnJgi9pAIdgo4rT772sf7l6BvzeRceaJrBxhIGUgZSBlIGUgZSBlIGUgZSLX0D5F2/QUNpAykDKQMpAykDKQMpAykDKQ2h2YFBXR3unwAAAAASUVORK5CYII="> -<p>Emulating tritanopia: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF5JREFUWIXt17ENwCAQBEGwEC0RuQBaoP8qnJgi9pAIdgo4rT772sf7l6BvzeRceaJrBxhIGUgZSBlIGUgZSBlIGUgZSLX0D5F2/QUNpAykDKQMpAykDKQMpAykDKQ2h2YFBXR3unwAAAAASUVORK5CYII="> -<p>Emulating some-invalid-deficiency: -{ - "code": -32602, - "message": "Unknown vision deficiency type" -} -<p>Emulating : -{ - "code": -32602, - "message": "Unknown vision deficiency type" -} -<p>Navigating… -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF5JREFUWIXt17ENwCAQBEGwEC0RuQBaoP8qnJgi9pAIdgo4rT772sf7l6BvzeRceaJrBxhIGUgZSBlIGUgZSBlIGUgZSLX0D5F2/QUNpAykDKQMpAykDKQMpAykDKQ2h2YFBXR3unwAAAAASUVORK5CYII="> -<p>Emulating achromatopsia: -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFpJREFUWIXt10ENADEMxMD2eARR2IfQFYS3Uh8eACsrv+zu/lfQzCTn1hddu8BAykDKQMpAykDKQMpAykDKQGpXVfQnSXv+ggZSBlIGUgZSBlIGUgZSBlIGUgcPVwX7L3bHewAAAABJRU5ErkJggg=="> -
diff --git a/third_party/blink/web_tests/inspector-protocol/emulation/set-vision-deficiency.js b/third_party/blink/web_tests/inspector-protocol/emulation/set-vision-deficiency.js deleted file mode 100644 index 6adc8ca2..0000000 --- a/third_party/blink/web_tests/inspector-protocol/emulation/set-vision-deficiency.js +++ /dev/null
@@ -1,59 +0,0 @@ -(async function(testRunner) { - const {page, session, dp} = await testRunner.startBlank( - 'Tests that vision deficiencies can be emulated.'); - // Note: the output log for this test can be viewed as HTML to - // simplify review. - - await session.navigate('../resources/vision-deficiency.html'); - - async function logScreenshotData() { - const response = await dp.Page.captureScreenshot({ - clip: { - x: 0, - y: 0, - width: 40, - height: 40, - scale: 1, - }, - }); - const imageData = response.result.data; - testRunner.log(`<img src="data:image/png;base64,${imageData}">`); - } - - async function setEmulatedVisionDeficiency(id) { - testRunner.log(`<p>Emulating ${id}: `); - const response = await dp.Emulation.setEmulatedVisionDeficiency({ - type: id, - }); - if (response.error) { - testRunner.log(JSON.stringify(response.error, null, 2)); - return; - } - await logScreenshotData(); - } - - await setEmulatedVisionDeficiency('none'); - await setEmulatedVisionDeficiency('achromatomaly'); - await setEmulatedVisionDeficiency('achromatopsia'); - await setEmulatedVisionDeficiency('blurredVision'); - await setEmulatedVisionDeficiency('none'); - await setEmulatedVisionDeficiency('deuteranomaly'); - await setEmulatedVisionDeficiency('deuteranopia'); - await setEmulatedVisionDeficiency('none'); - await setEmulatedVisionDeficiency('protanomaly'); - await setEmulatedVisionDeficiency('protanopia'); - await setEmulatedVisionDeficiency('tritanomaly'); - await setEmulatedVisionDeficiency('tritanopia'); - // Test setting the already-active vision deficiency. - await setEmulatedVisionDeficiency('tritanopia'); - // Test setting unknown vision deficiencies. - await setEmulatedVisionDeficiency('some-invalid-deficiency'); - await setEmulatedVisionDeficiency(''); - - testRunner.log(`<p>Navigating…`); - await session.navigate('../resources/vision-deficiency.html'); - await logScreenshotData(); - await setEmulatedVisionDeficiency('achromatopsia'); - - testRunner.completeTest(); -});
diff --git a/third_party/blink/web_tests/inspector-protocol/resources/vision-deficiency.css b/third_party/blink/web_tests/inspector-protocol/resources/vision-deficiency.css deleted file mode 100644 index 17733910..0000000 --- a/third_party/blink/web_tests/inspector-protocol/resources/vision-deficiency.css +++ /dev/null
@@ -1,12 +0,0 @@ -html { - background: blue; -} -html, body { - margin: 0; - padding: 0; -} -div { - width: 20px; - height: 20px; - background: green; -}
diff --git a/third_party/blink/web_tests/inspector-protocol/resources/vision-deficiency.html b/third_party/blink/web_tests/inspector-protocol/resources/vision-deficiency.html deleted file mode 100644 index 3273a67..0000000 --- a/third_party/blink/web_tests/inspector-protocol/resources/vision-deficiency.html +++ /dev/null
@@ -1,8 +0,0 @@ -<!DOCTYPE html> -<!-- -Note: These tests should pass even when the document's CSP disallows - data: URLs. ---> -<meta http-equiv="Content-Security-Policy" content="default-src 'self'"> -<link rel="stylesheet" href="vision-deficiency.css"> -<div></div>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index f53f57b0..71c81e1 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -55804,6 +55804,8 @@ <int value="20" label="Cleanup"/> <int value="21" label="WebSchedulingUserInteraction"/> <int value="22" label="WebSchedulingBestEffort"/> + <int value="24" label="WebScheduling"/> + <int value="25" label="NonWaking"/> </enum> <enum name="RendererSchedulerTaskType"> @@ -55867,6 +55869,7 @@ <int value="57" label="ApplicationLifeCycle"/> <int value="58" label="BackgroundFetch"/> <int value="59" label="Permission"/> + <int value="60" label="ServiceWorkerClientMessage"/> <int value="61" label="InternalContentCapture"/> <int value="62" label="MainThreadTaskQueueMemoryPurge"/> <int value="63" label="InternalNavigation"/> @@ -55874,6 +55877,8 @@ <int value="65" label="InternalContinueScriptLoading"/> <int value="66" label="kWebLocks"/> <int value="67" label="ExperimentalWebScheduling"/> + <int value="68" label="InternalFrameLifecycleControl"/> + <int value="69" label="MainThreadTaskQueueNonWaking"/> </enum> <enum name="RendererSchedulerTaskUseCase">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 9eeefde4..90efef65 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -16195,7 +16195,7 @@ <summary>Records whenever a Blimp tab toggles visibility.</summary> </histogram> -<histogram base="true" name="Blink.Animate.UpdateTime" units="microseconds" +<histogram name="Blink.Animate.UpdateTime" units="microseconds" expires_after="2020-07-06"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> @@ -17042,7 +17042,7 @@ </summary> </histogram> -<histogram base="true" name="Blink.Compositing.UpdateTime" units="microseconds" +<histogram name="Blink.Compositing.UpdateTime" units="microseconds" expires_after="2021-03-01"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> @@ -17059,8 +17059,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.CompositingCommit.UpdateTime" - units="microseconds" expires_after="2021-03-01"> +<histogram name="Blink.CompositingCommit.UpdateTime" units="microseconds" + expires_after="2021-03-01"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> <owner>schenney@chromium.org</owner> @@ -17518,8 +17518,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.ForcedStyleAndLayout.UpdateTime" - units="microseconds" expires_after="2020-07-06"> +<histogram name="Blink.ForcedStyleAndLayout.UpdateTime" units="microseconds" + expires_after="2020-07-06"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> <owner>schenney@chromium.org</owner> @@ -17547,8 +17547,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.HandleInputEvents.UpdateTime" - units="microseconds" expires_after="2020-07-26"> +<histogram name="Blink.HandleInputEvents.UpdateTime" units="microseconds" + expires_after="2020-07-26"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> <owner>schenney@chromium.org</owner> @@ -17561,8 +17561,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.HitTestDocumentUpdate.UpdateTime" - units="microseconds" expires_after="2020-07-26"> +<histogram name="Blink.HitTestDocumentUpdate.UpdateTime" units="microseconds" + expires_after="2020-07-26"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> <owner>schenney@chromium.org</owner> @@ -17649,8 +17649,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.ImplCompositorCommit.UpdateTime" - units="microseconds" expires_after="2021-03-01"> +<histogram name="Blink.ImplCompositorCommit.UpdateTime" units="microseconds" + expires_after="2021-03-01"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> <owner>schenney@chromium.org</owner> @@ -17665,8 +17665,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.IntersectionObservation.UpdateTime" - units="microseconds" expires_after="2020-07-06"> +<histogram name="Blink.IntersectionObservation.UpdateTime" units="microseconds" + expires_after="2020-07-06"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> <owner>schenney@chromium.org</owner> @@ -17689,7 +17689,7 @@ </summary> </histogram> -<histogram base="true" name="Blink.Layout.UpdateTime" units="microseconds" +<histogram name="Blink.Layout.UpdateTime" units="microseconds" expires_after="2020-08-24"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> @@ -17957,7 +17957,7 @@ </summary> </histogram> -<histogram base="true" name="Blink.MainFrame.WaitForCommitRatio" units="%" +<histogram name="Blink.MainFrame.WaitForCommitRatio" units="%" expires_after="2020-07-06"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> @@ -18159,7 +18159,7 @@ </summary> </histogram> -<histogram base="true" name="Blink.Paint.UpdateTime" units="microseconds" +<histogram name="Blink.Paint.UpdateTime" units="microseconds" expires_after="2020-08-10"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> @@ -18177,8 +18177,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.PaintInvalidation.UpdateTime" - units="microseconds" expires_after="2018-02-22"> +<histogram name="Blink.PaintInvalidation.UpdateTime" units="microseconds" + expires_after="2018-02-22"> <obsolete> SlimmingPaintInvalidation is enabled by default, so this histogram is no longer being logged. Was removed in 02-2018. @@ -18190,7 +18190,7 @@ </summary> </histogram> -<histogram base="true" name="Blink.PrePaint.UpdateTime" units="microseconds" +<histogram name="Blink.PrePaint.UpdateTime" units="microseconds" expires_after="2020-08-17"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> @@ -18210,7 +18210,7 @@ </summary> </histogram> -<histogram base="true" name="Blink.ProxyCommit.UpdateTime" units="microseconds" +<histogram name="Blink.ProxyCommit.UpdateTime" units="microseconds" expires_after="2020-07-06"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> @@ -18520,8 +18520,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.ScrollingCoordinator.UpdateTime" - units="microseconds" expires_after="2020-07-06"> +<histogram name="Blink.ScrollingCoordinator.UpdateTime" units="microseconds" + expires_after="2020-07-06"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" --> @@ -18706,7 +18706,7 @@ </summary> </histogram> -<histogram base="true" name="Blink.Style.UpdateTime" units="microseconds" +<histogram name="Blink.Style.UpdateTime" units="microseconds" expires_after="2020-07-06"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> @@ -18724,8 +18724,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.StyleAndLayout.UpdateTime" - units="microseconds" expires_after="2020-08-10"> +<histogram name="Blink.StyleAndLayout.UpdateTime" units="microseconds" + expires_after="2020-08-10"> <obsolete> Replaced with separate Style and Layout metrics and removed in M81. </obsolete> @@ -19262,8 +19262,8 @@ </summary> </histogram> -<histogram base="true" name="Blink.WaitForCommit.UpdateTime" - units="microseconds" expires_after="2021-03-01"> +<histogram name="Blink.WaitForCommit.UpdateTime" units="microseconds" + expires_after="2021-03-01"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimeAggregatedSuffixes" --> <owner>schenney@chromium.org</owner> @@ -23756,7 +23756,7 @@ </histogram> <histogram name="ChromeOS.SAML.APILogin" enum="ChromeOSSamlApiUsed" - expires_after="2020-04-02"> + expires_after="2020-10-02"> <owner>mslus@chromium.org</owner> <owner>emaxx@chromium.org</owner> <summary> @@ -79691,7 +79691,7 @@ </histogram> <histogram name="MobileDownload.Location.DirectoryType" - enum="DownloadLocationDirectoryType" expires_after="2020-03-01"> + enum="DownloadLocationDirectoryType" expires_after="2021-03-01"> <owner>xingliu@chromium.org</owner> <owner>dtrainor@chromium.org</owner> <owner>qinmin@chromium.org</owner> @@ -110501,6 +110501,10 @@ <histogram name="PageLoad.Experimental.PaintTiming.NavigationToLargestImagePaint" units="ms" expires_after="2020-04-23"> + <obsolete> + Removed Mar 2020 in favor of + PageLoad.PaintTiming.NavigationToLargestContentfulPaint. + </obsolete> <owner>maxlg@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> <summary> @@ -110514,6 +110518,10 @@ <histogram name="PageLoad.Experimental.PaintTiming.NavigationToLargestTextPaint" units="ms" expires_after="2020-07-26"> + <obsolete> + Removed Mar 2020 in favor of + PageLoad.PaintTiming.NavigationToLargestContentfulPaint. + </obsolete> <owner>maxlg@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> <summary> @@ -185051,6 +185059,8 @@ <suffix name="GenerateRequest" label="GenerateRequest promises only."/> <suffix name="LoadSession" label="LoadSession promises only."/> <suffix name="RemoveSession" label="RemoveSession promises only."/> + <suffix name="SetServerCertificate" + label="SetServerCertificate promises only."/> <suffix name="UpdateSession" label="UpdateSession promises only."/> <affected-histogram name="Media.EME.ClearKey"/> <affected-histogram name="Media.EME.Unknown"/>
diff --git a/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java b/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java index e461f6c..9940872 100644 --- a/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java +++ b/ui/android/java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java
@@ -4,11 +4,12 @@ package org.chromium.ui.interpolators; -import android.support.v4.view.animation.FastOutLinearInInterpolator; -import android.support.v4.view.animation.FastOutSlowInInterpolator; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.view.animation.Interpolator; +import androidx.interpolator.view.animation.FastOutLinearInInterpolator; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; +import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; + /** * A pre-baked bezier-curved interpolator for quantum-paper transitions. * TODO(dtrainor): Move to the API Compatibility version iff that supports the curves we need and
diff --git a/ui/color/BUILD.gn b/ui/color/BUILD.gn index 8413ed17..9c4976de 100644 --- a/ui/color/BUILD.gn +++ b/ui/color/BUILD.gn
@@ -17,96 +17,83 @@ sources = [ "color_id.h", "color_id_macros.inc", + "color_mixer.h", "color_provider.h", + "color_set.h", ] - public_deps = [ ":color_buildflags" ] - - if (use_color_pipeline) { - sources += [ - "color_mixer.h", - "color_set.h", - ] - - public_deps += [ - "//base:base", - "//skia:skia", - ] - } else { - public_deps += [ - "//ui/base:base", - "//ui/native_theme:native_theme", - ] - } + public_deps = [ + ":color_buildflags", + "//base:base", + "//skia:skia", + ] } -if (use_color_pipeline) { - jumbo_component("color") { - sources = [ - "color_mixer.cc", - "color_provider.cc", - "color_recipe.cc", - "color_recipe.h", - "color_set.cc", - "color_transform.cc", - "color_transform.h", - ] +jumbo_component("color") { + sources = [ + "color_mixer.cc", + "color_provider.cc", + "color_recipe.cc", + "color_recipe.h", + "color_set.cc", + "color_transform.cc", + "color_transform.h", + ] - defines = [ "IS_COLOR_IMPL" ] + defines = [ "IS_COLOR_IMPL" ] - public_deps = [ - ":color_headers", - "//base:base", - "//skia:skia", - "//ui/gfx:color_utils", - ] - } + public_deps = [ + ":color_headers", + "//base:base", + "//skia:skia", + "//ui/gfx:color_utils", + ] +} - test("color_unittests") { - testonly = true +test("color_unittests") { + testonly = true - sources = [ - "color_mixer_unittest.cc", - "color_provider_unittest.cc", - "color_recipe_unittest.cc", - "color_test_ids.h", - "color_transform_unittest.cc", - "run_all_unittests.cc", - ] + sources = [ + "color_mixer_unittest.cc", + "color_provider_unittest.cc", + "color_recipe_unittest.cc", + "color_test_ids.h", + "color_transform_unittest.cc", + "run_all_unittests.cc", + ] - deps = [ - ":color", - "//base/test:test_support", - "//testing/gtest", - ] - } + deps = [ + ":color", + "//base/test:test_support", + "//testing/gtest", + ] +} - jumbo_component("mixers") { - sources = [ - "color_mixers.h", - "core_default_color_mixer.cc", - "ui_color_mixer.cc", - ] +jumbo_component("mixers") { + sources = [ + "color_mixers.h", + "core_default_color_mixer.cc", + "ui_color_mixer.cc", + ] - defines = [ "IS_COLOR_IMPL" ] + defines = [ "IS_COLOR_IMPL" ] - deps = [ - ":color", - ":color_headers", - "//skia", - "//ui/gfx:color_utils", - ] + deps = [ + ":color", + ":color_headers", + "//skia", + "//ui/gfx:color_utils", + ] - public_deps = [ "//base" ] + public_deps = [ "//base" ] - if (is_chromeos) { - sources += [ "cros/native_color_mixer.cc" ] - } else if (is_linux) { - sources += [ "linux/native_color_mixer.cc" ] - } else if (is_mac) { - sources += [ "mac/native_color_mixer.cc" ] - } else if (is_win) { - sources += [ "win/native_color_mixer.cc" ] - } + if (is_chromeos) { + sources += [ "cros/native_color_mixer.cc" ] + } else if (is_linux) { + sources += [ "linux/native_color_mixer.cc" ] + } else if (is_mac) { + sources += [ "mac/native_color_mixer.cc" ] + } else if (is_win) { + sources += [ "win/native_color_mixer.cc" ] } }
diff --git a/ui/color/DEPS b/ui/color/DEPS index c5a8c5f9..41134f5 100644 --- a/ui/color/DEPS +++ b/ui/color/DEPS
@@ -1,6 +1,4 @@ include_rules = [ "+third_party/skia/include", - "+ui/base/theme_provider.h", # used by color_provider.h when !USE_COLOR_PIPELINE. "+ui/gfx", - "+ui/native_theme/native_theme.h", # used by color_id.h when !USE_COLOR_PIPELINE. ]
diff --git a/ui/color/color_id.h b/ui/color/color_id.h index e5b2d49d..ccf3d6c 100644 --- a/ui/color/color_id.h +++ b/ui/color/color_id.h
@@ -9,14 +9,6 @@ #include "build/buildflag.h" #include "ui/color/color_buildflags.h" -#if !BUILDFLAG(USE_COLOR_PIPELINE) -#include "ui/native_theme/native_theme.h" // nogncheck - -#if defined(OS_WIN) -#include <windows.h> -#endif -#endif - // clang-format off #define CROSS_PLATFORM_COLOR_IDS \ /* Core color concepts */ \ @@ -206,8 +198,6 @@ #include "ui/color/color_id_macros.inc" -#if BUILDFLAG(USE_COLOR_PIPELINE) - // ColorSetId contains identifiers for all distinct color sets known to the core // UI layer. As with ColorId, embedders can extend this enum with additional // values that are understood by the ColorProvider implementation. Embedders @@ -237,8 +227,6 @@ // Verifies that |id| is a color set ID, not a color ID. #define DCHECK_COLOR_SET_ID_VALID(id) DCHECK_GE(id, kUiColorSetsStart) -#endif // BUILDFLAG(USE_COLOR_PIPELINE) - } // namespace ui #endif // UI_COLOR_COLOR_ID_H_
diff --git a/ui/color/color_id_macros.inc b/ui/color/color_id_macros.inc index 66e4a492..112e49b 100644 --- a/ui/color/color_id_macros.inc +++ b/ui/color/color_id_macros.inc
@@ -20,21 +20,11 @@ #define D2(enum_name, enum_value) enum_name = enum_value #endif // defined(STRINGIZE_COLOR_IDS) // Select which token in the declaration is the assigned value. -#if BUILDFLAG(USE_COLOR_PIPELINE) // Use first and optional third token, ignore optional second. #define E1(enum_name) D1(enum_name) #define E2(enum_name, old_enum_name) D1(enum_name) #define E3(enum_name, old_enum_name, enum_value) D2(enum_name, enum_value) #define E_CPONLY(...) E(__VA_ARGS__) -#else -// Use first and mandatory second token, ignore optional third. -#define E1(enum_name) \ - static_assert(false, "New-style color compiled for !USE_COLOR_PIPELINE") -#define E2(enum_name, old_enum_name) D2(enum_name, old_enum_name) -#define E3(enum_name, old_enum_name, enum_value) D2(enum_name, old_enum_name) -// Ignore any new color id defined only for color pipeline enabled. -#define E_CPONLY(...) -#endif // BUILDFLAG(USE_COLOR_PIPELINE) #define GET_E(_1, _2, _3, macro_name, ...) macro_name #define E(...) GET_E(__VA_ARGS__, E3, E2, E1)(__VA_ARGS__), #else
diff --git a/ui/color/color_provider.h b/ui/color/color_provider.h index 1c60ea9..0a7f428fc 100644 --- a/ui/color/color_provider.h +++ b/ui/color/color_provider.h
@@ -8,21 +8,14 @@ #include <forward_list> #include <map> -#include "ui/color/color_buildflags.h" - -#if BUILDFLAG(USE_COLOR_PIPELINE) #include "base/component_export.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/color/color_buildflags.h" #include "ui/color/color_id.h" #include "ui/color/color_mixer.h" -#else -#include "ui/base/theme_provider.h" // nogncheck -#endif namespace ui { -#if BUILDFLAG(USE_COLOR_PIPELINE) - // A ColorProvider holds the complete pipeline of ColorMixers that compute // result colors for UI elements. ColorProvider is meant to be a long-lived // object whose internal list of mixers does not change after initial @@ -57,12 +50,6 @@ mutable std::map<ColorId, SkColor> cache_; }; -#else - -using ColorProvider = ThemeProvider; - -#endif // !BUILDFLAG(USE_COLOR_PIPELINE) - } // namespace ui #endif // UI_COLOR_COLOR_PROVIDER_H_
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc index 901ac87..baa857e 100644 --- a/ui/native_theme/common_theme.cc +++ b/ui/native_theme/common_theme.cc
@@ -479,6 +479,19 @@ case NativeTheme::kColorId_DefaultIconColor: return gfx::kGoogleGrey700; + // Sync info container + case NativeTheme::kColorId_SyncInfoContainerPaused: + return SkColorSetA(base_theme->GetSystemColor( + NativeTheme::kColorId_ProminentButtonColor), + 16); + case NativeTheme::kColorId_SyncInfoContainerError: + return SkColorSetA( + base_theme->GetSystemColor(NativeTheme::kColorId_AlertSeverityHigh), + 16); + case NativeTheme::kColorId_SyncInfoContainerNoPrimaryAccount: + return base_theme->GetSystemColor( + NativeTheme::kColorId_BubbleFooterBackground); + case NativeTheme::kColorId_NumColors: break; }
diff --git a/ui/native_theme/native_theme_color_id.h b/ui/native_theme/native_theme_color_id.h index 72f1ea6..85a7da0 100644 --- a/ui/native_theme/native_theme_color_id.h +++ b/ui/native_theme/native_theme_color_id.h
@@ -75,6 +75,10 @@ OP(kColorId_SliderTroughMinimal), \ /* Separator */ \ OP(kColorId_SeparatorColor), \ + /* Sync info container */ \ + OP(kColorId_SyncInfoContainerPaused), \ + OP(kColorId_SyncInfoContainerError), \ + OP(kColorId_SyncInfoContainerNoPrimaryAccount), \ /* TabbedPane */ \ OP(kColorId_TabTitleColorActive), \ OP(kColorId_TabTitleColorInactive), \ @@ -122,6 +126,7 @@ OP(kColorId_AlertSeverityHigh), \ /* Colors for icons in secondary UI (content settings, help button, etc). */ \ OP(kColorId_DefaultIconColor) + // clang-format on #endif // UI_NATIVE_THEME_NATIVE_THEME_COLOR_ID_H_
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc index 3c74784..9799a58 100644 --- a/ui/views/widget/root_view.cc +++ b/ui/views/widget/root_view.cc
@@ -427,13 +427,15 @@ // Reset mouse_pressed_handler_ to indicate that no processing is occurring. mouse_pressed_handler_ = nullptr; + + const bool last_click_was_handled = (last_click_handler_ != nullptr); last_click_handler_ = nullptr; // In the event that a double-click is not handled after traversing the // entire hierarchy (even as a single-click when sent to a different view), // it must be marked as handled to avoid anything happening from default // processing if it the first click-part was handled by us. - return event.flags() & ui::EF_IS_DOUBLE_CLICK; + return last_click_was_handled && (event.flags() & ui::EF_IS_DOUBLE_CLICK); } bool RootView::OnMouseDragged(const ui::MouseEvent& event) {
diff --git a/ui/views/widget/root_view_unittest.cc b/ui/views/widget/root_view_unittest.cc index 48e2372..2a0b24db 100644 --- a/ui/views/widget/root_view_unittest.cc +++ b/ui/views/widget/root_view_unittest.cc
@@ -860,5 +860,57 @@ EXPECT_EQ(1, v3->GetEventCount(ui::ET_MOUSE_PRESSED)); } +// If RootView::OnMousePressed() receives a double-click event that isn't +// handled by any views, it should still report it as handled if the first click +// was handled. However, it should *not* if the first click was unhandled. +// Regression test for https://crbug.com/1055674. +TEST_F(RootViewTest, DoubleClickHandledIffFirstClickHandled) { + Widget widget; + Widget::InitParams init_params = + CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + init_params.bounds = {100, 100, 100, 100}; + widget.Init(std::move(init_params)); + widget.Show(); + internal::RootView* root_view = + static_cast<internal::RootView*>(widget.GetRootView()); + root_view->SetContentsView(new View()); + + View* const contents_view = root_view->GetContentsView(); + EventCountView* const v1 = + contents_view->AddChildView(std::make_unique<EventCountView>()); + + contents_view->SetBoundsRect(gfx::Rect(0, 0, 10, 10)); + v1->SetBoundsRect(gfx::Rect(0, 0, 10, 10)); + + ui::MouseEvent pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), + gfx::Point(5, 5), ui::EventTimeForNow(), 0, 0); + ui::MouseEvent released_event(ui::ET_MOUSE_RELEASED, gfx::Point(5, 5), + gfx::Point(5, 5), ui::EventTimeForNow(), 0, 0); + + // First click handled, second click unhandled. + v1->set_handle_mode(EventCountView::CONSUME_EVENTS); + pressed_event.SetClickCount(1); + released_event.SetClickCount(1); + EXPECT_TRUE(root_view->OnMousePressed(pressed_event)); + root_view->OnMouseReleased(released_event); + v1->set_handle_mode(EventCountView::PROPAGATE_EVENTS); + pressed_event.SetClickCount(2); + released_event.SetClickCount(2); + EXPECT_TRUE(root_view->OnMousePressed(pressed_event)); + root_view->OnMouseReleased(released_event); + + // Both clicks unhandled. + v1->set_handle_mode(EventCountView::PROPAGATE_EVENTS); + pressed_event.SetClickCount(1); + released_event.SetClickCount(1); + EXPECT_FALSE(root_view->OnMousePressed(pressed_event)); + root_view->OnMouseReleased(released_event); + pressed_event.SetClickCount(2); + released_event.SetClickCount(2); + EXPECT_FALSE(root_view->OnMousePressed(pressed_event)); + root_view->OnMouseReleased(released_event); +} + } // namespace test } // namespace views
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index c5cd9d597..a9869561 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -616,6 +616,9 @@ for (WidgetObserver& observer : observers_) observer.OnWidgetClosing(this); + if (widget_delegate_) + widget_delegate_->WindowWillClose(); + native_widget_->Close(); }
diff --git a/ui/views/widget/widget_delegate.h b/ui/views/widget/widget_delegate.h index fd8ea2e..a3ec229 100644 --- a/ui/views/widget/widget_delegate.h +++ b/ui/views/widget/widget_delegate.h
@@ -132,13 +132,22 @@ // Default is true. virtual bool ShouldRestoreWindowSize() const; - // Called when the window closes. The delegate MUST NOT delete itself during - // this call, since it can be called afterwards. See DeleteDelegate(). + // Hooks for the end of the Widget/Window lifecycle. As of this writing, these + // callbacks happen like so: + // 1. Client code calls Widget::CloseWithReason() + // 2. WidgetDelegate::WindowWillClose() is called + // 3. NativeWidget teardown (maybe async) starts OR the operating system + // abruptly closes the backing native window + // 4. WidgetDelegate::WindowClosing() is called + // 5. NativeWidget teardown completes, Widget teardown starts + // 6. WidgetDelegate::DeleteDelegate() is called + // 7. Widget teardown finishes, Widget is deleted + // At step 3, the "maybe async" is controlled by whether the close is done via + // Close() or CloseNow(). + // Important note: for OS-initiated window closes, steps 1 and 2 don't happen + // - i.e, WindowWillClose() is never invoked. + virtual void WindowWillClose() {} virtual void WindowClosing() {} - - // Called when the window is destroyed. No events must be sent or received - // after this point. The delegate can use this opportunity to delete itself at - // this time if necessary. virtual void DeleteDelegate() {} // Called when the user begins/ends to change the bounds of the window.
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc index 58ce3ab..0f34750 100644 --- a/ui/views/window/dialog_client_view.cc +++ b/ui/views/window/dialog_client_view.cc
@@ -86,41 +86,12 @@ dialog->RemoveObserver(this); } -void DialogClientView::AcceptWindow() { - // Only notify the delegate once. See |delegate_allowed_close_|'s comment. - if (!delegate_allowed_close_ && GetDialogDelegate()->Accept()) { - delegate_allowed_close_ = true; - GetWidget()->CloseWithReason( - views::Widget::ClosedReason::kAcceptButtonClicked); - } -} - -void DialogClientView::CancelWindow() { - // Only notify the delegate once. See |delegate_allowed_close_|'s comment. - if (!delegate_allowed_close_ && GetDialogDelegate()->Cancel()) { - delegate_allowed_close_ = true; - GetWidget()->CloseWithReason( - views::Widget::ClosedReason::kCancelButtonClicked); - } -} - void DialogClientView::SetButtonRowInsets(const gfx::Insets& insets) { button_row_insets_ = insets; if (GetWidget()) UpdateDialogButtons(); } -/////////////////////////////////////////////////////////////////////////////// -// DialogClientView, ClientView overrides: - -bool DialogClientView::CanClose() { - // If the dialog is closing but no Accept or Cancel action has been performed - // before, it's a Close action. - if (!delegate_allowed_close_) - delegate_allowed_close_ = GetDialogDelegate()->Close(); - return delegate_allowed_close_; -} - //////////////////////////////////////////////////////////////////////////////// // DialogClientView, View overrides: @@ -235,9 +206,9 @@ return; if (sender == ok_button_) - AcceptWindow(); + GetDialogDelegate()->AcceptDialog(); else if (sender == cancel_button_) - CancelWindow(); + GetDialogDelegate()->CancelDialog(); else NOTREACHED(); }
diff --git a/ui/views/window/dialog_client_view.h b/ui/views/window/dialog_client_view.h index d7bc090..faf6b5e 100644 --- a/ui/views/window/dialog_client_view.h +++ b/ui/views/window/dialog_client_view.h
@@ -43,10 +43,6 @@ DialogClientView(Widget* widget, View* contents_view); ~DialogClientView() override; - // Accept or Cancel the dialog. - void AcceptWindow(); - void CancelWindow(); - // Accessors in case the user wishes to adjust these buttons. LabelButton* ok_button() const { return ok_button_; } LabelButton* cancel_button() const { return cancel_button_; } @@ -54,9 +50,6 @@ void SetButtonRowInsets(const gfx::Insets& insets); - // ClientView implementation: - bool CanClose() override; - // View implementation: gfx::Size CalculatePreferredSize() const override; gfx::Size GetMinimumSize() const override; @@ -136,12 +129,6 @@ // Container view for the button row. ButtonRowContainer* button_row_container_ = nullptr; - // True if we've notified the delegate the window is closing and the delegate - // allowed the close. In some situations it's possible to get two closes (see - // http://crbug.com/71940). This is used to avoid notifying the delegate - // twice, which can have bad consequences. - bool delegate_allowed_close_ = false; - // Used to prevent unnecessary or potentially harmful changes during // SetupLayout(). Everything will be manually updated afterwards. bool adding_or_removing_views_ = false;
diff --git a/ui/views/window/dialog_delegate.cc b/ui/views/window/dialog_delegate.cc index bc9c10c..caf94e2 100644 --- a/ui/views/window/dialog_delegate.cc +++ b/ui/views/window/dialog_delegate.cc
@@ -137,52 +137,22 @@ } bool DialogDelegate::Cancel() { + DCHECK(!already_started_close_); if (cancel_callback_) RunCloseCallback(std::move(cancel_callback_)); return true; } bool DialogDelegate::Accept() { + DCHECK(!already_started_close_); if (accept_callback_) RunCloseCallback(std::move(accept_callback_)); return true; } -bool DialogDelegate::Close() { - // Test for callback_delivered_ here, because it indicates that: - // 1) A new-style callback used to be present in one of these slots - // 2) It has already been invoked and therefore the slot is now empty - if (callback_delivered_ || close_callback_ || cancel_callback_ || - accept_callback_) { - if (close_callback_) - RunCloseCallback(std::move(close_callback_)); - return true; - } else { - return DefaultClose(); - } -} - -bool DialogDelegate::DefaultClose() { - DCHECK(!close_callback_); - DCHECK(!cancel_callback_); - DCHECK(!accept_callback_); - int buttons = GetDialogButtons(); - if ((buttons & ui::DIALOG_BUTTON_CANCEL) || - (buttons == ui::DIALOG_BUTTON_NONE)) { - return Cancel(); - } - return Accept(); -} - void DialogDelegate::RunCloseCallback(base::OnceClosure callback) { - // TODO(ellyjones): It would be better if this instead was: - // DCHECK(!callback_delivered_); - // i.e., it was enforced by Views that client code does not cause the - // DialogDelegate to be closed from within a closure handler. Unfortunately a - // lot of client code does not behave that way right now. - if (callback_delivered_) - return; - callback_delivered_ = true; + DCHECK(!already_started_close_); + already_started_close_ = true; std::move(callback).Run(); } @@ -223,6 +193,36 @@ return WidgetDelegate::CreateNonClientFrameView(widget); } +void DialogDelegate::WindowWillClose() { + if (already_started_close_) + return; + + bool new_callback_present = + close_callback_ || cancel_callback_ || accept_callback_; + + if (close_callback_) + RunCloseCallback(std::move(close_callback_)); + + if (new_callback_present) + return; + + // Old-style close behavior: if the only button was Ok, call Accept(); + // otherwise call Cancel(). Note that in this case the window is already going + // to close, so the return values of Accept()/Cancel(), which normally say + // whether the window should close, are ignored. + int buttons = GetDialogButtons(); + if (buttons == ui::DIALOG_BUTTON_OK) + Accept(); + else + Cancel(); + + // This is set here instead of before the invocations of Accept()/Cancel() so + // that those methods can DCHECK that !already_started_close_. Otherwise, + // client code could (eg) call Accept() from inside the cancel callback, which + // could lead to multiple callbacks being delivered from this class. + already_started_close_ = true; +} + // static NonClientFrameView* DialogDelegate::CreateDialogFrameView(Widget* widget) { LayoutProvider* provider = LayoutProvider::Get(); @@ -325,12 +325,9 @@ return std::move(extra_view_); } -void DialogDelegate::CancelDialog() { - GetDialogClientView()->CancelWindow(); -} - -void DialogDelegate::AcceptDialog() { - GetDialogClientView()->AcceptWindow(); +bool DialogDelegate::Close() { + WindowWillClose(); + return true; } void DialogDelegate::ResetViewShownTimeStampForTesting() { @@ -341,6 +338,24 @@ GetDialogClientView()->SetButtonRowInsets(insets); } +void DialogDelegate::AcceptDialog() { + if (already_started_close_ || !Accept()) + return; + + already_started_close_ = true; + GetWidget()->CloseWithReason( + views::Widget::ClosedReason::kAcceptButtonClicked); +} + +void DialogDelegate::CancelDialog() { + if (already_started_close_ || !Cancel()) + return; + + already_started_close_ = true; + GetWidget()->CloseWithReason( + views::Widget::ClosedReason::kCancelButtonClicked); +} + DialogDelegate::~DialogDelegate() { UMA_HISTOGRAM_LONG_TIMES("Dialog.DialogDelegate.Duration", base::TimeTicks::Now() - creation_time_);
diff --git a/ui/views/window/dialog_delegate.h b/ui/views/window/dialog_delegate.h index 2f5c4ff..c4e3da8 100644 --- a/ui/views/window/dialog_delegate.h +++ b/ui/views/window/dialog_delegate.h
@@ -129,6 +129,7 @@ DialogDelegate* AsDialogDelegate() override; ClientView* CreateClientView(Widget* widget) override; NonClientFrameView* CreateNonClientFrameView(Widget* widget) override; + void WindowWillClose() override; static NonClientFrameView* CreateDialogFrameView(Widget* widget); @@ -225,16 +226,19 @@ // lazy layout system in View::InvalidateLayout std::unique_ptr<View> DisownExtraView(); - // Externally or accept the dialog. These methods: + // Accept or cancel the dialog, as though the user had pressed the + // Accept/Cancel buttons. These methods: // 1) Invoke the DialogDelegate's Cancel or Accept methods // 2) Depending on their return value, close the dialog's widget. // Neither of these methods can be called before the dialog has been // initialized. - void CancelDialog(); void AcceptDialog(); + void CancelDialog(); - // Deprecated, for compatibility with a few remaining unit tests. - // TODO(https://crbug.com/1011446): Delete this method. + // This method invokes the behavior that *would* happen if this dialog's + // containing widget were closed. It is present only as a compatibility shim + // for unit tests; do not add new calls to it. + // TODO(https://crbug.com/1011446): Delete this. bool Close(); // Reset the dialog's shown timestamp, for tests that are subject to the @@ -269,10 +273,6 @@ const DialogClientView* GetDialogClientView() const; DialogClientView* GetDialogClientView(); - // Implements the default close behavior, as described in the comment on - // Close() above. - bool DefaultClose(); - // Runs a close callback, ensuring that at most one close callback is ever // run. void RunCloseCallback(base::OnceClosure callback); @@ -303,8 +303,9 @@ base::OnceClosure cancel_callback_; base::OnceClosure close_callback_; - // Whether any of the three callbacks just above has been delivered yet. - bool callback_delivered_ = false; + // Whether any of the three callbacks just above has been delivered yet, *or* + // one of the Accept/Cancel methods have been called and returned true. + bool already_started_close_ = false; DISALLOW_COPY_AND_ASSIGN(DialogDelegate); };
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc index 82f4fd8..ace06841 100644 --- a/ui/views/window/dialog_delegate_unittest.cc +++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -17,6 +17,7 @@ #include "ui/views/controls/textfield/textfield.h" #include "ui/views/style/platform_style.h" #include "ui/views/test/views_test_base.h" +#include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_delegate.h" @@ -466,4 +467,41 @@ EXPECT_FALSE(closed); } +class TestDialogDelegateView : public DialogDelegateView { + public: + TestDialogDelegateView(bool* accepted, bool* cancelled) + : accepted_(accepted), cancelled_(cancelled) {} + ~TestDialogDelegateView() override = default; + + private: + bool Accept() override { + *(accepted_) = true; + return true; + } + bool Cancel() override { + *(cancelled_) = true; + return true; + } + + bool* accepted_; + bool* cancelled_; +}; + +TEST_F(DialogDelegateCloseTest, OldClosePathDoesNotDoubleClose) { + bool accepted = false; + bool cancelled = false; + + auto* dialog = new TestDialogDelegateView(&accepted, &cancelled); + Widget* widget = + DialogDelegate::CreateDialogWidget(dialog, GetContext(), nullptr); + widget->Show(); + + views::test::WidgetDestroyedWaiter destroyed_waiter(widget); + dialog->AcceptDialog(); + destroyed_waiter.Wait(); + + EXPECT_TRUE(accepted); + EXPECT_FALSE(cancelled); +} + } // namespace views