diff --git a/DEPS b/DEPS index be4246c..f851cd7 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': '3aee4845b5039149a506fb85e7442be1924f69c8', + 'skia_revision': 'e9bc857b39c22878fd2f46284d83f22fe45540d9', # 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': '5269c3133de0093c180c57cc51dac04406293e24', + 'v8_revision': '056e6aee712040d9139e159d6f409edf82fc2925', # 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,7 +187,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '1b2dd6f92a6ba4ac4738ae796692e4844bfd28c7', + 'angle_revision': '50a47bd992294216b0fe08db02bdd78746b56d8e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # 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': 'ca9a03f92fbd213b17466a9393ae3490b3eb1806', + 'devtools_frontend_revision': '3fffd0d4592e1896c05f2d9dca6e2f4f5f9507d3', # 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. @@ -302,7 +302,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '81431f5034b4ce3a0cdc339709bd8ca8856fe427', + 'dawn_revision': '29d712f9de99c646bbebd97cbe55ad5d81486612', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -933,7 +933,7 @@ Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'fa1c3c4e673cf12ffa22b8fbe4a7c79314571f1b', 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'bfe4c5957fc51148a0aab6e04bb22020667c1092', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '344bd0889ac98c5369df2bf359d0369e3d235b62', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1228,7 +1228,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd1dae2a33653ee6648f179eeb28244840fb3f248', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e7603d3ab87813963019bd764a4e0dd1b580fe00', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1448,7 +1448,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '84ee597cdeae08bb26e578fc66a35bcf35f633f4', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'd19513f3ffbb939fd56b5377b678bb31d3154e14', + Var('webrtc_git') + '/src.git' + '@' + '7bd282acce658a1a640964e90dc2c54e8f3b1530', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1523,7 +1523,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@04f3ecdadc728b53cb94d8f282eefd3748311912', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8df96b104065304c1bb7bb58a1394c59063be2c1', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 727b21f..93b9fb2 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -24,7 +24,7 @@ "$target_gen_dir/system_webview_pak_whitelist.txt" } -if (public_android_sdk) { +if (define_upstream_webview_targets) { template("standalone_system_webview_apk_tmpl") { system_webview_apk_or_module_tmpl(target_name) { forward_variables_from(invoker, "*")
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index d56d610..9cf1ddb 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -1007,8 +1007,7 @@ // In fullscreen mode FullScreenView owns the AwViewMethodsImpl and AwContents // a NullAwViewMethods. - FullScreenView fullScreenView = new FullScreenView(mContext, mAwViewMethods, this, - mContainerView.getWidth(), mContainerView.getHeight()); + FullScreenView fullScreenView = new FullScreenView(mContext, mAwViewMethods, this); fullScreenView.setFocusable(true); fullScreenView.setFocusableInTouchMode(true); boolean wasInitialContainerViewFocused = mContainerView.isFocused(); @@ -1122,8 +1121,15 @@ } else if (!containerViewAttached && mIsAttachedToWindow) { awViewMethodsImpl.onDetachedFromWindow(); } - awViewMethodsImpl.onSizeChanged( - mContainerView.getWidth(), mContainerView.getHeight(), 0, 0); + // Skip passing size of FullScreenView down. FullScreenView is newly created and detached + // so has initial size 0x0 before layout. Avoid this temporary resize to 0x0 which can + // cause flickers and sometimes layout problems in the web page. + if ((mContainerView instanceof FullScreenView)) { + assert !containerViewAttached; + } else { + awViewMethodsImpl.onSizeChanged( + mContainerView.getWidth(), mContainerView.getHeight(), 0, 0); + } awViewMethodsImpl.onWindowFocusChanged(mContainerView.hasWindowFocus()); awViewMethodsImpl.onFocusChanged(mContainerView.hasFocus(), 0, null); mContainerView.requestLayout();
diff --git a/android_webview/java/src/org/chromium/android_webview/FullScreenView.java b/android_webview/java/src/org/chromium/android_webview/FullScreenView.java index 372b916..da09864 100644 --- a/android_webview/java/src/org/chromium/android_webview/FullScreenView.java +++ b/android_webview/java/src/org/chromium/android_webview/FullScreenView.java
@@ -29,11 +29,8 @@ private final AwContents mAwContents; private InternalAccessAdapter mInternalAccessAdapter; - public FullScreenView(Context context, AwViewMethods awViewMethods, AwContents awContents, - int initialWidth, int initialHeight) { + public FullScreenView(Context context, AwViewMethods awViewMethods, AwContents awContents) { super(context); - setRight(initialWidth); - setBottom(initialHeight); setAwViewMethods(awViewMethods); mAwContents = awContents; mInternalAccessAdapter = new InternalAccessAdapter(); @@ -139,10 +136,7 @@ @Override public void onSizeChanged(final int w, final int h, final int ow, final int oh) { super.onSizeChanged(w, h, ow, oh); - // Null check for setting initial size before mAwViewMethods is set. - if (mAwViewMethods != null) { - mAwViewMethods.onSizeChanged(w, h, ow, oh); - } + mAwViewMethods.onSizeChanged(w, h, ow, oh); } @Override
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni index 8a13d74..30cab84 100644 --- a/android_webview/system_webview_apk_tmpl.gni +++ b/android_webview/system_webview_apk_tmpl.gni
@@ -46,6 +46,11 @@ "//android_webview:pak_file_assets", ] + # If the R SDK isn't public yet, include the downstream code to support R. + if (!public_android_sdk && android_sdk_release == "r") { + deps += [ "//clank/android_webview/next:r_sdk_java" ] + } + if (_exclude_weblayer_java) { deps += [ "//android_webview:android_webview_no_weblayer_java" ] } else {
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index f44427c..8051351 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -20,7 +20,7 @@ ] } -if (public_android_sdk) { +if (define_upstream_webview_targets) { python_library("webview_cts_tests") { pydeps_file = "//android_webview/tools/run_cts.pydeps" deps = [ "//android_webview:system_webview_apk" ]
diff --git a/android_webview/variables.gni b/android_webview/variables.gni index aaa4d94..3b6ec80 100644 --- a/android_webview/variables.gni +++ b/android_webview/variables.gni
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/config/android/channel.gni") +import("//build/config/android/config.gni") import("//weblayer/variables.gni") declare_args() { @@ -21,6 +22,12 @@ trichrome_webview_32_android_manifest = "$root_gen_dir/android_webview/trichrome_webview_32_apk/AndroidManifest.xml" +# TODO(crbug/760187): We're in the process of migrating to always defining the +# WebView targets upstream. Remove this once it's always true. +if (!defined(define_upstream_webview_targets)) { + define_upstream_webview_targets = public_android_sdk +} + upstream_only_webview_deps = [ "//android_webview:platform_service_bridge_upstream_implementation_java", "//android_webview/nonembedded:icon_resources",
diff --git a/base/task/thread_pool/job_task_source.cc b/base/task/thread_pool/job_task_source.cc index a731b10..77039dc 100644 --- a/base/task/thread_pool/job_task_source.cc +++ b/base/task/thread_pool/job_task_source.cc
@@ -336,11 +336,7 @@ bool JobTaskSource::WaitForConcurrencyIncreaseUpdate(size_t recorded_version) { AutoLock auto_lock(version_lock_); - // This timeout is meant to catch a JobDelegate which forgets to decrease the - // max-concurrency it returns despite workers returning (hence entering an - // infinite loop of workers being spawned with no work to do). 30 seconds - // catches this error early enough without causing false positives. - constexpr TimeDelta timeout = TimeDelta::FromSeconds(30); + constexpr TimeDelta timeout = TimeDelta::FromSeconds(1); const base::TimeTicks start_time = subtle::TimeTicksNowIgnoringOverride(); do { DCHECK_LE(recorded_version, increase_version_);
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index ef9064f9..2dcb168 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -447,6 +447,8 @@ <ignore regexp="chrome/android/java/res/values/styles.xml"/> <!--TODO(crbug.com/1044658): This suppression was added blindly, and needs investigated.--> <ignore regexp="chrome/android/java/res/layout/tab_switcher_action_menu_layout.xml"/> + <!--TODO(crbug.com/1052375): Remove this suppression once ConnectionInfoPopAndroid moves to components.--> + <ignore regexp="components/page_info/android/java/res/drawable-hdpi/pageinfo_*"/> </issue> <issue id="UseCompoundDrawables"> <!-- Upscaling 24dp to 48dp doesn't work as expected with a TextView compound drawable. -->
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 8e7aa7e..bf0d3da2 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200329.2.1 \ No newline at end of file +0.20200330.1.1 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 8e7aa7e..bf0d3da2 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200329.2.1 \ No newline at end of file +0.20200330.1.1 \ No newline at end of file
diff --git a/buildtools/linux64/clang-format.sha1 b/buildtools/linux64/clang-format.sha1 index e2b3199a..62b2d60 100644 --- a/buildtools/linux64/clang-format.sha1 +++ b/buildtools/linux64/clang-format.sha1
@@ -1 +1 @@ -942fc8b1789144b8071d3fc03ff0fcbe1cf81ac8 \ No newline at end of file +1baf0089e895c989a311b6a38ed94d0e8be4c0a7 \ No newline at end of file
diff --git a/buildtools/mac/clang-format.sha1 b/buildtools/mac/clang-format.sha1 index d32c626..5ef063b 100644 --- a/buildtools/mac/clang-format.sha1 +++ b/buildtools/mac/clang-format.sha1
@@ -1 +1 @@ -025ca7c75f37ef4a40f3a67d81ddd11d7d0cdb9b \ No newline at end of file +62bde1baa7196ad9df969fc1f06b66360b1a927b \ No newline at end of file
diff --git a/buildtools/win/clang-format.exe.sha1 b/buildtools/win/clang-format.exe.sha1 index d31c76f..03c98aa 100644 --- a/buildtools/win/clang-format.exe.sha1 +++ b/buildtools/win/clang-format.exe.sha1
@@ -1 +1 @@ -b5f5d8d5f8a8fcd2edb5b6cae37c0dc3e129c945 \ No newline at end of file +d4afd4eba27022f5f6d518133aebde57281677c9 \ No newline at end of file
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 49138134..23eb5fc 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1526,10 +1526,6 @@ sources = [ "browser/ui/android/page_info/page_info_controller_android.h" ] } - java_cpp_enum("page_info_action_javagen") { - sources = [ "browser/ui/page_info/page_info.h" ] - } - java_cpp_enum("partner_bookmarks_javagen") { sources = [ "browser/android/bookmarks/partner_bookmarks_reader.h" ] }
diff --git a/chrome/VERSION b/chrome/VERSION index 3b52afb..ad5f7eb5 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=83 MINOR=0 -BUILD=4099 +BUILD=4100 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 7f66b0c..a9a800e 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -460,7 +460,6 @@ "//chrome:download_enum_javagen", "//chrome:instant_apps_reasons_enum_javagen", "//chrome:offline_pages_enum_javagen", - "//chrome:page_info_action_javagen", "//chrome:page_info_connection_type_javagen", "//chrome:partner_bookmarks_javagen", "//chrome:payments_journey_logger_enum_javagen", @@ -482,6 +481,7 @@ "//components/ntp_snippets:ntp_snippets_java_enums_srcjar", "//components/ntp_tiles:ntp_tiles_enums_java", "//components/offline_pages/core:offline_page_model_enums_java", + "//components/page_info:page_info_action_javagen", "//components/password_manager/core/browser:password_manager_java_enums_srcjar", "//components/payments/content/android:method_strings_generated_srcjar", "//components/search_engines:search_engine_type_java", @@ -681,7 +681,8 @@ package_path = "org/chromium/chrome/browser/resources" inputs = [ "../browser/android/resource_id.h", - "//components/permissions/android/resource_id.h", + "//components/resources/android/page_info_resource_id.h", + "//components/resources/android/permissions_resource_id.h", ] } @@ -1917,7 +1918,9 @@ include_64_bit_webview = true } } +} +if (define_upstream_webview_targets) { trichrome_library_apk_tmpl("trichrome_library_apk") { apk_name = "TrichromeLibrary" android_manifest = trichrome_library_android_manifest
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index daaeb93b..0bebf1434 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -137,9 +137,6 @@ "java/res/drawable-hdpi/offline_pin.png", "java/res/drawable-hdpi/open_in_new_tab.png", "java/res/drawable-hdpi/overlay_side_shadow.9.png", - "java/res/drawable-hdpi/pageinfo_bad.png", - "java/res/drawable-hdpi/pageinfo_good.png", - "java/res/drawable-hdpi/pageinfo_warning.png", "java/res/drawable-hdpi/permission_background_sync.png", "java/res/drawable-hdpi/permission_javascript.png", "java/res/drawable-hdpi/permission_mic.png", @@ -332,9 +329,6 @@ "java/res/drawable-mdpi/offline_pin.png", "java/res/drawable-mdpi/open_in_new_tab.png", "java/res/drawable-mdpi/overlay_side_shadow.9.png", - "java/res/drawable-mdpi/pageinfo_bad.png", - "java/res/drawable-mdpi/pageinfo_good.png", - "java/res/drawable-mdpi/pageinfo_warning.png", "java/res/drawable-mdpi/permission_background_sync.png", "java/res/drawable-mdpi/permission_javascript.png", "java/res/drawable-mdpi/permission_mic.png", @@ -520,9 +514,6 @@ "java/res/drawable-xhdpi/offline_pin.png", "java/res/drawable-xhdpi/open_in_new_tab.png", "java/res/drawable-xhdpi/overlay_side_shadow.9.png", - "java/res/drawable-xhdpi/pageinfo_bad.png", - "java/res/drawable-xhdpi/pageinfo_good.png", - "java/res/drawable-xhdpi/pageinfo_warning.png", "java/res/drawable-xhdpi/permission_background_sync.png", "java/res/drawable-xhdpi/permission_javascript.png", "java/res/drawable-xhdpi/permission_mic.png", @@ -678,9 +669,6 @@ "java/res/drawable-xxhdpi/offline_pin.png", "java/res/drawable-xxhdpi/open_in_new_tab.png", "java/res/drawable-xxhdpi/overlay_side_shadow.9.png", - "java/res/drawable-xxhdpi/pageinfo_bad.png", - "java/res/drawable-xxhdpi/pageinfo_good.png", - "java/res/drawable-xxhdpi/pageinfo_warning.png", "java/res/drawable-xxhdpi/permission_background_sync.png", "java/res/drawable-xxhdpi/permission_javascript.png", "java/res/drawable-xxhdpi/permission_mic.png", @@ -832,9 +820,6 @@ "java/res/drawable-xxxhdpi/offline_pin.png", "java/res/drawable-xxxhdpi/open_in_new_tab.png", "java/res/drawable-xxxhdpi/overlay_side_shadow.9.png", - "java/res/drawable-xxxhdpi/pageinfo_bad.png", - "java/res/drawable-xxxhdpi/pageinfo_good.png", - "java/res/drawable-xxxhdpi/pageinfo_warning.png", "java/res/drawable-xxxhdpi/permission_background_sync.png", "java/res/drawable-xxxhdpi/permission_javascript.png", "java/res/drawable-xxxhdpi/permission_mic.png",
diff --git a/chrome/android/java/ResourceId.template b/chrome/android/java/ResourceId.template index 9abb1f1..6717cab 100644 --- a/chrome/android/java/ResourceId.template +++ b/chrome/android/java/ResourceId.template
@@ -12,7 +12,8 @@ #define LINK_RESOURCE_ID(c_id,java_id) java_id, #define DECLARE_RESOURCE_ID(c_id,java_id) java_id, #include "chrome/browser/android/resource_id.h" -#include "components/permissions/android/resource_id.h" +#include "components/resources/android/permissions_resource_id.h" +#include "components/resources/android/page_info_resource_id.h" }; return resourceList; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java index b8ad965..fe6932a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/childaccounts/ChildAccountService.java
@@ -14,6 +14,7 @@ import org.chromium.base.task.PostTask; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChildAccountStatus; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.ui.base.WindowAndroid; @@ -76,7 +77,7 @@ return; } - Account account = AccountManagerFacade.createAccountFromName(accountName); + Account account = AccountUtils.createAccountFromName(accountName); AccountManagerFacadeProvider.getInstance().updateCredentials(account, activity, result -> ChildAccountServiceJni.get().onReauthenticationResult(nativeCallback, result));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index 6fca974..c99e916 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -331,7 +331,7 @@ @Override protected boolean requiresFirstRunToBeCompleted(Intent intent) { // Custom Tabs can be used to open Chrome help pages before the ToS has been accepted. - if (IntentHandler.notSecureIsIntentChromeOrFirstParty(intent) + if (CustomTabIntentDataProvider.isTrustedCustomTab(intent, mSession) && IntentUtils.safeGetIntExtra(intent, CustomTabIntentDataProvider.EXTRA_UI_TYPE, CustomTabIntentDataProvider.CustomTabsUiType.DEFAULT) == CustomTabIntentDataProvider.CustomTabsUiType.INFO_PAGE) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index 71b7670c..1b6df1d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -219,6 +219,20 @@ } /** + * Evaluates whether the passed Intent and/or CustomTabsSessionToken are + * from a trusted source. Trusted in this case means from the app itself or + * via a first-party application. + * + * @param intent The Intent used to start the custom tabs activity, or null. + * @param session The connected session for the custom tabs activity, or null. + * @return True if the intent or session are trusted. + */ + public static boolean isTrustedCustomTab(Intent intent, CustomTabsSessionToken session) { + return IntentHandler.wasIntentSenderChrome(intent) + || CustomTabsConnection.getInstance().isSessionFirstParty(session); + } + + /** * Constructs a {@link CustomTabIntentDataProvider}. * * The colorScheme parameter specifies which color scheme the Custom Tab should use. @@ -233,7 +247,7 @@ mIntent = intent; mSession = CustomTabsSessionToken.getSessionTokenFromIntent(intent); - mIsTrustedIntent = IntentHandler.notSecureIsIntentChromeOrFirstParty(intent); + mIsTrustedIntent = isTrustedCustomTab(intent, mSession); mAnimationBundle = IntentUtils.safeGetBundleExtra( intent, CustomTabsIntent.EXTRA_EXIT_ANIMATION_BUNDLE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java index 48b3982..f5d4eef6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -57,6 +57,7 @@ import org.chromium.chrome.browser.browserservices.SessionDataHolder; import org.chromium.chrome.browser.browserservices.SessionHandler; import org.chromium.chrome.browser.device.DeviceClassManager; +import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.init.ChainedTasks; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; @@ -1065,6 +1066,13 @@ return mClientManager.getClientPackageNameForSession(session); } + /** @return Whether the client of the {@code session} is a first-party application. */ + public boolean isSessionFirstParty(CustomTabsSessionToken session) { + String packageName = getClientPackageNameForSession(session); + if (packageName == null) return false; + return ExternalAuthUtils.getInstance().isGoogleSigned(packageName); + } + @VisibleForTesting void setIgnoreUrlFragmentsForSession(CustomTabsSessionToken session, boolean value) { mClientManager.setIgnoreFragmentsForSession(session, value); @@ -1093,15 +1101,6 @@ } /** - * Extracts the creator package name from the intent. - * @param intent The intent to get the package name from. - * @return the package name which can be null. - */ - String extractCreatorPackage(Intent intent) { - return null; - } - - /** * Shows a toast about any possible sign in issues encountered during custom tab startup. * @param session The session that corresponding custom tab is assigned. * @param intent The intent that launched the custom tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java index f807a51..0e4695d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.compositor.CompositorViewHolder; import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory; +import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.customtabs.CustomTabNavigationEventObserver; import org.chromium.chrome.browser.customtabs.CustomTabObserver; import org.chromium.chrome.browser.customtabs.CustomTabTabPersistencePolicy; @@ -440,7 +441,7 @@ /** Sets the initial background color for the Tab, shown before the page content is ready. */ private void prepareTabBackground(final Tab tab) { - if (!IntentHandler.notSecureIsIntentChromeOrFirstParty(mIntent)) return; + if (!CustomTabIntentDataProvider.isTrustedCustomTab(mIntent, mSession)) return; int backgroundColor = mIntentDataProvider.getInitialBackgroundColor(); if (backgroundColor == Color.TRANSPARENT) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java index 545cfb5..52b94346 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
@@ -87,7 +87,10 @@ SettingsLauncher.getInstance().launchSettingsPage( getContext(), DataReductionPreferenceFragment.class, fragmentArgs); - Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile()); + // TODO (https://crbug.com/1048632): Use the current profile (i.e., regular profile or + // incognito profile) instead of always using regular profile. It works correctly now, but + // it is not safe. + Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile()); tracker.notifyEvent(EventConstants.DATA_SAVER_DETAIL_OPENED); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java index f163ce68..563eb425 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -639,8 +639,11 @@ */ public static void getLoadUrlParamsForOpeningOfflineVersion(final String url, long offlineId, final @LaunchLocation int location, Callback<LoadUrlParams> callback) { + // TODO(https://crbug.com/1041781): Use the current profile (i.e., regular profile or + // incognito profile) instead of always using regular profile. It is wrong and need to be + // fixed. OfflinePageBridge offlinePageBridge = - getInstance().getOfflinePageBridge(Profile.getLastUsedProfile()); + getInstance().getOfflinePageBridge(Profile.getLastUsedRegularProfile()); if (offlinePageBridge == null) { callback.onResult(null); return; @@ -659,8 +662,11 @@ */ public static void getLoadUrlParamsForOpeningMhtmlFileOrContent( final String intentUrl, Callback<LoadUrlParams> callback) { + // TODO(https://crbug.com/1041781): Use the current profile (i.e., regular profile or + // incognito profile) instead of always using regular profile. It is wrong and need to be + // fixed. OfflinePageBridge offlinePageBridge = - getInstance().getOfflinePageBridge(Profile.getLastUsedProfile()); + getInstance().getOfflinePageBridge(Profile.getLastUsedRegularProfile()); if (offlinePageBridge == null) { callback.onResult(new LoadUrlParams(intentUrl)); return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java index ea59021..1f92592 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -20,9 +20,9 @@ import org.chromium.base.task.AsyncTask; import org.chromium.chrome.browser.signin.SigninManager.SignInCallback; import org.chromium.chrome.browser.sync.ProfileSyncService; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountTrackerService; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.components.signin.metrics.SignoutReason; @@ -200,7 +200,7 @@ private void performResignin(String newName) { // This is the correct account now. - final Account account = AccountManagerFacade.createAccountFromName(newName); + final Account account = AccountUtils.createAccountFromName(newName); mSigninManager.signIn(SigninAccessPoint.ACCOUNT_RENAMED, account, new SignInCallback() { @Override @@ -264,7 +264,7 @@ // We have found a rename event of the current account. // We need to check if that account is further renamed. newName = name; - if (!accountExists(AccountManagerFacade.createAccountFromName(newName))) { + if (!accountExists(AccountUtils.createAccountFromName(newName))) { newIndex = 0; // Start from the beginning of the new account. continue outerLoop; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java index bd789475..2f14873f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -22,8 +22,8 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.task.PostTask; import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountTrackerService; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.identitymanager.ClearAccountsAction; @@ -369,8 +369,7 @@ public void signIn(@SigninAccessPoint int accessPoint, CoreAccountInfo accountInfo, @Nullable SignInCallback callback) { assert accountInfo != null; - signIn(accessPoint, AccountManagerFacade.createAccountFromName(accountInfo.getEmail()), - callback); + signIn(accessPoint, AccountUtils.createAccountFromName(accountInfo.getEmail()), callback); } /** @@ -697,7 +696,7 @@ // Cache the signed-in account name. This must be done after the native call, otherwise // sync tries to start without being signed in the native code and crashes. mAndroidSyncSettings.updateAccount( - AccountManagerFacade.createAccountFromName(accountInfo.getEmail())); + AccountUtils.createAccountFromName(accountInfo.getEmail())); mAndroidSyncSettings.enableChromeSync(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 3bc3033..0904088e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -958,7 +958,7 @@ // Mark the intent as trusted so it can show more than one action button. IntentHandler.addTrustedIntentExtras(intent); - Assert.assertTrue(IntentHandler.notSecureIsIntentChromeOrFirstParty(intent)); + Assert.assertTrue(IntentHandler.wasIntentSenderChrome(intent)); ArrayList<Bundle> toolbarItems = new ArrayList<>(2); final PendingIntent pi1 = PendingIntent.getBroadcast( @@ -1033,7 +1033,7 @@ Intent intent = createMinimalCustomTabIntent(); // By default, the intent should not be trusted. - Assert.assertFalse(IntentHandler.notSecureIsIntentChromeOrFirstParty(intent)); + Assert.assertFalse(IntentHandler.wasIntentSenderChrome(intent)); ArrayList<Bundle> toolbarItems = new ArrayList<>(2); final PendingIntent pi = PendingIntent.getBroadcast(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunUtilsTest.java index 24df8be..a7bb111 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunUtilsTest.java
@@ -18,8 +18,8 @@ import org.chromium.base.test.util.AdvancedMockContext; import org.chromium.base.test.util.Feature; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; @@ -33,7 +33,7 @@ private Account mTestAccount; public FirstRunUtilsTest() { - mTestAccount = AccountManagerFacade.createAccountFromName("Dummy"); + mTestAccount = AccountUtils.createAccountFromName("Dummy"); } @Before @@ -77,7 +77,7 @@ public void testHasGoogleAccountCorrectlyDetected() { // Set up an account manager mock that returns Google account types // when queried. - setUpAccountManager(AccountManagerFacade.GOOGLE_ACCOUNT_TYPE); + setUpAccountManager(AccountUtils.GOOGLE_ACCOUNT_TYPE); addTestAccount(); ContextUtils.initApplicationContextForTests(mAccountTestingContext);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java index c5509c2..adb9ac5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordViewingTypeTest.java
@@ -26,7 +26,7 @@ import org.chromium.chrome.browser.settings.SettingsActivity; import org.chromium.chrome.browser.settings.SettingsLauncher; import org.chromium.chrome.browser.sync.ProfileSyncService; -import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.AccountManagerTestRule; import org.chromium.components.sync.AndroidSyncSettings; @@ -72,7 +72,7 @@ } private void setupTestAccount() { - mAccount = AccountManagerFacade.createAccountFromName("account@example.com"); + mAccount = AccountUtils.createAccountFromName("account@example.com"); AccountHolder.Builder accountHolder = AccountHolder.builder(mAccount).alwaysAccept(true); mAccountManagerTestRule.addAccount(accountHolder.build()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceTest.java index ec4deb5..303f5ce 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceTest.java
@@ -41,6 +41,11 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class DecoderServiceTest { + // By default, the test will wait for 3 seconds to create the decoder process, which (at least + // in the emulators) brushes up against the actual time it takes to create the process, so these + // tests are frequently flaky when run locally. + private static final int DECODER_STARTUP_TIMEOUT_IN_MS = 7500; + @Rule public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = new ChromeActivityTestRule<>(ChromeActivity.class); @@ -99,7 +104,7 @@ public boolean isSatisfied() { return mBound; } - }); + }, DECODER_STARTUP_TIMEOUT_IN_MS, CriteriaHelper.DEFAULT_POLLING_INTERVAL); } private void decode(String filePath, FileDescriptor fd, int width,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java index 9c1151b..badba0f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java
@@ -34,7 +34,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.browser.Features; -import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ProfileDataSource; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.AccountManagerTestRule; @@ -135,7 +135,7 @@ } private void addAccount(String accountName, String fullName) { - Account account = AccountManagerFacade.createAccountFromName(accountName); + Account account = AccountUtils.createAccountFromName(accountName); AccountHolder.Builder accountHolder = AccountHolder.builder(account).alwaysAccept(true); ProfileDataSource.ProfileData profileData = new ProfileDataSource.ProfileData(accountName, null, fullName, null);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java index 47ebf05..444b6a5a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java
@@ -15,8 +15,8 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.RetryOnFailure; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.base.CoreAccountId; import org.chromium.components.signin.base.CoreAccountInfo; @@ -46,11 +46,11 @@ private static final String TEST_ACCOUNT1 = "foo@gmail.com"; private static final String TEST_ACCOUNT2 = "bar@gmail.com"; private static final AccountHolder TEST_ACCOUNT_HOLDER_1 = - AccountHolder.builder(AccountManagerFacade.createAccountFromName(TEST_ACCOUNT1)) + AccountHolder.builder(AccountUtils.createAccountFromName(TEST_ACCOUNT1)) .alwaysAccept(true) .build(); private static final AccountHolder TEST_ACCOUNT_HOLDER_2 = - AccountHolder.builder(AccountManagerFacade.createAccountFromName(TEST_ACCOUNT2)) + AccountHolder.builder(AccountUtils.createAccountFromName(TEST_ACCOUNT2)) .alwaysAccept(true) .build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java index 620d022..f77a67a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java
@@ -17,8 +17,8 @@ import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.signin.MockChangeEventChecker; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.AccountManagerTestRule; @@ -110,7 +110,7 @@ mEventChecker.insertRenameEvent("B", "C"); mEventChecker.insertRenameEvent("C", "D"); mEventChecker.insertRenameEvent("D", "A"); // Looped. - Account account = AccountManagerFacade.createAccountFromName("D"); + Account account = AccountUtils.createAccountFromName("D"); AccountHolder accountHolder = AccountHolder.builder(account).build(); mAccountManagerTestRule.addAccount(accountHolder); SigninHelper.updateAccountRenameData(mEventChecker);
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 11f55b0..2b15c8a 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -4384,6 +4384,9 @@ <message name="IDS_PLUGIN_VM_INSTALLER_NOT_ALLOWED_TITLE" desc="Title of the Plugin VM installer if Plugin VM is disallowed."> Plugin VM needs permission to run </message> + <message name="IDS_PLUGIN_VM_INSTALLER_LOW_DISK_SPACE_MESSAGE" desc="Text of the Plugin VM installer that warns them of low disk space."> + Your device is low on storage space. At least <ph name="RECOMMENDED_SPACE">$1<ex>32GB</ex></ph> of free space is recommended to use Plugin VM. To free up space, delete files from device storage. + </message> <message name="IDS_PLUGIN_VM_INSTALLER_START_DOWNLOADING_MESSAGE" desc="Text of the Plugin VM installer that informs the user that setup may take a while."> This may take awhile </message> @@ -4423,6 +4426,9 @@ <message name="IDS_PLUGIN_VM_INSTALLER_TIME_LEFT_MESSAGE" desc="Text of the Plugin VM installer that shows estimated time left before current installation stage ends."> <ph name="TIME_LEFT">$1<ex>30 mins</ex></ph> left </message> + <message name="IDS_PLUGIN_VM_INSTALLER_CONTINUE_BUTTON" desc="Label for the button in the Plugin VM installer to continue installation."> + Continue + </message> <message name="IDS_PLUGIN_VM_INSTALLER_LAUNCH_BUTTON" desc="Label for the button in the Plugin VM installer to launch Plugin VM after successful installation."> Launch </message> @@ -4468,8 +4474,8 @@ <message name="IDS_PLUGIN_VM_DLC_NEED_REBOOT_FAILED_MESSAGE" desc="Error message shown if Plugin VM installation fails because a pending update requires the device to be restarted."> Please restart your device to use Plugin VM. </message> - <message name="IDS_PLUGIN_VM_DLC_NEED_SPACE_FAILED_MESSAGE" desc="Error message shown if Plugin VM installation fails because there is not enough free space on the device."> - Your device is low on storage space. Please free up space to use Plugin VM. + <message name="IDS_PLUGIN_VM_INSUFFICIENT_DISK_SPACE_MESSAGE" desc="Error message shown if Plugin VM installation fails because there is not enough free space on the device."> + Your device is low on storage space. At least <ph name="MINIMUM_SPACE">$1<ex>16GB</ex></ph> of free space is required to use Plugin VM, and over <ph name="RECOMMENDED_SPACE">$2<ex>32GB</ex></ph> of free space is recommended. To free up space, delete files from device storage. </message> <!-- Strings for Account Manager error screen -->
diff --git a/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_DLC_NEED_SPACE_FAILED_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_DLC_NEED_SPACE_FAILED_MESSAGE.png.sha1 deleted file mode 100644 index 0bc8db9..0000000 --- a/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_DLC_NEED_SPACE_FAILED_MESSAGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -ab2aaafa34246f7a3c88c095348306050c987c4e \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSTALLER_LOW_DISK_SPACE_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSTALLER_LOW_DISK_SPACE_MESSAGE.png.sha1 new file mode 100644 index 0000000..3841f82 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSTALLER_LOW_DISK_SPACE_MESSAGE.png.sha1
@@ -0,0 +1 @@ +9be927ad30f67d387e96ef4eb99a0e9aa518670c \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSUFFICIENT_DISK_SPACE_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSUFFICIENT_DISK_SPACE_MESSAGE.png.sha1 new file mode 100644 index 0000000..f32be7ec --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_PLUGIN_VM_INSUFFICIENT_DISK_SPACE_MESSAGE.png.sha1
@@ -0,0 +1 @@ +4088af357e5509c43f1b0bbaa0cb1ca29b9243e3 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 13f8ca4..739cf3a 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -2525,9 +2525,6 @@ <message name="IDS_LIST_BULLET" desc="Unicode bullet for list items in permission bubbles."> • <ph name="LIST_ITEM_TEXT">$1<ex>You might need permission to continue ...</ex></ph> </message> - <message name="IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL" desc="Header for multiple automatic downloads page on Content Settings dialog"> - Automatic Downloads - </message> <message name="IDS_BLOCKED_DOWNLOAD_NO_ACTION" desc="Radio button to keep blocking automatic downloads"> Continue blocking automatic downloads of multiple files </message>
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index 2069ad4..fbba6e2d 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -15,22 +15,18 @@ "account_child.icon", "account_child_circle.icon", "add.icon", - "ads.icon", "apps.icon", "autofill/webauthn_dialog_header.icon", "autofill/webauthn_dialog_header_dark.icon", - "blocked_badge.icon", "blocked_redirect.icon", "browser_tools.icon", "browser_tools_error.icon", "browser_tools_update.icon", "caret_down.icon", "caret_up.icon", - "certificate.icon", "click_to_call_illustration.icon", "click_to_call_illustration_dark.icon", "close_all.icon", - "code.icon", # Alternative squarer content_paste icon optimised for display at 18x18dip. # Currently only used in the Page Info bubble. @@ -47,7 +43,6 @@ "default_touch_favicon_mask.icon", "eol.icon", "extension_crashed.icon", - "file_download.icon", "file_download_shelf.icon", "fingerprint.icon", "forward_arrow_touch.icon", @@ -62,7 +57,6 @@ "input.icon", "key.icon", "laptop.icon", - "launch.icon", "media_toolbar_button.icon", "media_toolbar_button_touch.icon", "mixed_content.icon", @@ -73,13 +67,10 @@ "navigate_stop_touch.icon", "nfc.icon", "overflow_chevron.icon", - "page_info_content_paste.icon", "paintbrush.icon", - "photo.icon", "photo_camera.icon", "picture_in_picture_control_background.icon", "picture_in_picture_alt.icon", - "protected_content.icon", "qrcode_generator.icon", "reader_mode.icon", "reader_mode_disabled.icon", @@ -88,12 +79,10 @@ "remove_box.icon", "resize_handle.icon", "sad_tab.icon", - "save_original_file.icon", "security.icon", "send_tab_to_self.icon", "eye_crossed.icon", "eye.icon", - "sensors.icon", "signin_button_drop_down_arrow.icon", "sign_out.icon", "smartphone.icon", @@ -101,7 +90,6 @@ "speaker_group.icon", "supervisor_account.icon", "supervisor_account_circle.icon", - "sync.icon", "sync_circle.icon", "sync_error_circle.icon", "sync_paused.icon", @@ -128,7 +116,6 @@ "user_account_avatar.icon", "user_menu_guest.icon", "user_menu_right_arrow.icon", - "volume_up.icon", "warning_badge.icon", "web.icon", "webauthn/webauthn_ble.icon",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 9768ca7..1940ec8 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -170,7 +170,7 @@ "+components/optimization_guide", "+components/os_crypt", "+components/ownership", - "+components/page_info/android", + "+components/page_info", "+components/page_load_metrics/browser", "+components/page_load_metrics/common", "+components/paint_preview/features",
diff --git a/chrome/browser/android/DEPS b/chrome/browser/android/DEPS index 617640f..0ebd7fa 100644 --- a/chrome/browser/android/DEPS +++ b/chrome/browser/android/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "-components/devtools_bridge", + "+components/resources/android", "+cc/layers/layer.h", "+chrome/android/test_support_jni_headers", "+chrome_jni_registration/chrome_jni_registration.h",
diff --git a/chrome/browser/android/android_theme_resources.h b/chrome/browser/android/android_theme_resources.h index 7459b98..865482fc 100644 --- a/chrome/browser/android/android_theme_resources.h +++ b/chrome/browser/android/android_theme_resources.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_ANDROID_ANDROID_THEME_RESOURCES_H_ #define CHROME_BROWSER_ANDROID_ANDROID_THEME_RESOURCES_H_ -#include "components/permissions/android/theme_resources.h" +#include "components/resources/android/theme_resources.h" // LINK_RESOURCE_ID will use an ID defined by grit, so no-op. #define LINK_RESOURCE_ID(c_id, java_id)
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h index 0937162..01eb4a6 100644 --- a/chrome/browser/android/resource_id.h +++ b/chrome/browser/android/resource_id.h
@@ -51,24 +51,6 @@ LINK_RESOURCE_ID(IDR_AUTOFILL_GOOGLE_PAY_WITH_DIVIDER, R.drawable.google_pay_with_divider) -// PageInfoUI images, used in ConnectionInfoPopup -// Good: -DECLARE_RESOURCE_ID(IDR_PAGEINFO_GOOD, R.drawable.pageinfo_good) -// Warnings: -DECLARE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MINOR, R.drawable.pageinfo_warning) -// Bad: -DECLARE_RESOURCE_ID(IDR_PAGEINFO_BAD, R.drawable.pageinfo_bad) -// Should never occur, use warning just in case: -// Enterprise managed: ChromeOS only. -DECLARE_RESOURCE_ID(IDR_PAGEINFO_ENTERPRISE_MANAGED, - R.drawable.pageinfo_warning) -// Info: Only shown on chrome:// urls, which don't show the connection info -// popup. -DECLARE_RESOURCE_ID(IDR_PAGEINFO_INFO, R.drawable.pageinfo_warning) -// Major warning: Used on insecure pages, which don't show the connection info -// popup. -DECLARE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MAJOR, R.drawable.pageinfo_warning) - // Autofill popup and keyboard accessory images. // We use Android's |VectorDrawableCompat| for the following images that are // displayed using |DropdownAdapter|.
diff --git a/chrome/browser/android/resource_mapper.cc b/chrome/browser/android/resource_mapper.cc index a89476d..af7af86 100644 --- a/chrome/browser/android/resource_mapper.cc +++ b/chrome/browser/android/resource_mapper.cc
@@ -53,7 +53,8 @@ #define DECLARE_RESOURCE_ID(c_id, java_id) \ g_id_map.Get()[c_id] = resource_id_list[next_id++]; #include "chrome/browser/android/resource_id.h" -#include "components/permissions/android/resource_id.h" +#include "components/resources/android/page_info_resource_id.h" +#include "components/resources/android/permissions_resource_id.h" #undef LINK_RESOURCE_ID #undef DECLARE_RESOURCE_ID // Make sure ID list sizes match up.
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn index 233c9cb90..fc8abdb0 100644 --- a/chrome/browser/android/vr/BUILD.gn +++ b/chrome/browser/android/vr/BUILD.gn
@@ -119,6 +119,7 @@ "//components/content_settings/core/browser", "//components/language/core/browser", "//components/omnibox/browser", + "//components/page_info", "//components/permissions", "//components/rappor", "//components/search_engines:search_engines",
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h index 882f30f..ad734a7 100644 --- a/chrome/browser/android/vr/vr_shell.h +++ b/chrome/browser/android/vr/vr_shell.h
@@ -16,7 +16,6 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string16.h" #include "base/timer/timer.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" #include "chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h" #include "chrome/browser/vr/assets_load_status.h" #include "chrome/browser/vr/exit_vr_prompt_choice.h" @@ -26,6 +25,7 @@ #include "chrome/browser/vr/ui_browser_interface.h" #include "chrome/browser/vr/ui_initial_state.h" #include "chrome/browser/vr/ui_unsupported_mode.h" +#include "components/page_info/page_info_ui.h" #include "content/public/browser/web_contents_observer.h" #include "device/vr/public/mojom/vr_service.mojom.h" #include "device/vr/vr_device.h"
diff --git a/chrome/browser/browser_switcher/bho/bho.cc b/chrome/browser/browser_switcher/bho/bho.cc index 7aec413..6fd3b8a 100644 --- a/chrome/browser/browser_switcher/bho/bho.cc +++ b/chrome/browser/browser_switcher/bho/bho.cc
@@ -38,7 +38,7 @@ CBrowserSwitcherBHO::~CBrowserSwitcherBHO() = default; // Implementation of IObjectWithSiteImpl::SetSite. -STDMETHODIMP CBrowserSwitcherBHO::SetSite(IUnknown* site) { +STDMETHODIMP CBrowserSwitcherBHO::SetSite(IUnknown* site) noexcept { if (site != NULL) { HRESULT hr = site->QueryInterface(IID_PPV_ARGS(&web_browser_)); if (SUCCEEDED(hr)) {
diff --git a/chrome/browser/browser_switcher/bho/browser_switcher_core.cc b/chrome/browser/browser_switcher/bho/browser_switcher_core.cc index e2ffb29..aad2117e 100644 --- a/chrome/browser/browser_switcher/bho/browser_switcher_core.cc +++ b/chrome/browser/browser_switcher/bho/browser_switcher_core.cc
@@ -499,7 +499,7 @@ // In almost every case should this be enough for the sanitization because // any ASCII char will expand to at most 3 chars - %[0-9A-F][0-9A-F]. DWORD length = static_cast<DWORD>(url.length() * 3 + 1); - std::auto_ptr<wchar_t> buffer(new wchar_t[length]); + std::unique_ptr<wchar_t[]> buffer(new wchar_t[length]); if (!::InternetCanonicalizeUrl(url.c_str(), buffer.get(), &length, 0)) { DWORD error = ::GetLastError(); if (error == ERROR_INSUFFICIENT_BUFFER) { @@ -540,7 +540,7 @@ // any ASCII char will expand to at most 3 chars - %[0-9A-F][0-9A-F]. std::wstring::const_iterator it = url.begin(); std::wstring untranslated_chars(L".:/\\_-@~();"); - std::auto_ptr<wchar_t> sanitized_url(new wchar_t[url.length() * 3 + 1]); + std::unique_ptr<wchar_t[]> sanitized_url(new wchar_t[url.length() * 3 + 1]); wchar_t* output = sanitized_url.get(); while (it != url.end()) { @@ -613,7 +613,7 @@ << std::endl; return std::wstring(); } - std::auto_ptr<wchar_t> browser_path(new wchar_t[length]); + std::unique_ptr<wchar_t[]> browser_path(new wchar_t[length]); if (ERROR_SUCCESS != ::RegQueryValueEx(key, name, NULL, NULL, reinterpret_cast<LPBYTE>(browser_path.get()), @@ -632,7 +632,7 @@ expanded_size = ::ExpandEnvironmentStrings(str.c_str(), NULL, expanded_size); if (expanded_size != 0) { // The expected buffer length as defined in MSDN is chars + null + 1. - std::auto_ptr<wchar_t> expanded_path(new wchar_t[expanded_size + 2]); + std::unique_ptr<wchar_t[]> expanded_path(new wchar_t[expanded_size + 2]); expanded_size = ::ExpandEnvironmentStrings(str.c_str(), expanded_path.get(), expanded_size); if (expanded_size != 0)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 27d55fdf..d2dde69 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -914,6 +914,8 @@ "crostini/crostini_remover.h", "crostini/crostini_reporting_util.cc", "crostini/crostini_reporting_util.h", + "crostini/crostini_shelf_utils.cc", + "crostini/crostini_shelf_utils.h", "crostini/crostini_simple_types.h", "crostini/crostini_terminal.cc", "crostini/crostini_terminal.h", @@ -2817,6 +2819,7 @@ "crostini/crostini_port_forwarder_unittest.cc", "crostini/crostini_registry_service_unittest.cc", "crostini/crostini_reporting_util_unittest.cc", + "crostini/crostini_shelf_utils_unittest.cc", "crostini/crostini_unsupported_action_notifier_unittest.cc", "crostini/crostini_util_unittest.cc", "crostini/crosvm_metrics_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc index 192ac33..1127656a 100644 --- a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
@@ -16,6 +16,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/memory/weak_ptr.h" +#include "base/strings/pattern.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/speech_monitor.h" #include "chrome/browser/profiles/profile.h" @@ -73,7 +74,7 @@ ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); } - SpeechMonitor sm_; + SpeechMonitor speech_monitor_; std::unique_ptr<ui::test::EventGenerator> generator_; gfx::Rect GetWebContentsBounds() const { @@ -139,8 +140,8 @@ return browser()->tab_strip_model()->GetActiveWebContents(); } - void ExecuteJavaScriptAsync(const std::string& script) { - content::ExecuteScriptAsync(GetWebContents(), script); + void ExecuteJavaScriptInForeground(const std::string& script) { + CHECK(content::ExecuteScript(GetWebContents(), script)); } private: @@ -175,8 +176,8 @@ generator_->ReleaseLeftButton(); generator_->ReleaseKey(ui::VKEY_LWIN, 0 /* flags */); - sm_.ExpectSpeechPattern("Status tray*"); - sm_.Replay(); + EXPECT_TRUE( + base::MatchPattern(speech_monitor_.GetNextUtterance(), "Status tray*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, ActivatesWithTapOnSelectToSpeakTray) { @@ -198,8 +199,8 @@ bounds.y() + bounds.height()); generator_->ReleaseLeftButton(); - sm_.ExpectSpeechPattern("This is some text*"); - sm_.Replay(); + EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(), + "This is some text*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SelectToSpeakTrayNotSpoken) { @@ -217,9 +218,8 @@ // The next should be the first thing spoken -- the tray was not spoken. ActivateSelectToSpeakInWindowBounds( "data:text/html;charset=utf-8,<p>This is some text</p>"); - - sm_.ExpectSpeechPattern("This is some text*"); - sm_.Replay(); + EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(), + "This is some text*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossInlineUrl) { @@ -230,8 +230,9 @@ // Should combine nodes in a paragraph into one utterance. // Includes some wildcards between words because there may be extra // spaces. Spaces are not pronounced, so extra spaces do not impact output. - sm_.ExpectSpeechPattern("This is some text*with a node*in the middle*"); - sm_.Replay(); + EXPECT_TRUE( + base::MatchPattern(speech_monitor_.GetNextUtterance(), + "This is some text*with a node*in the middle*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossMultipleLines) { @@ -244,8 +245,9 @@ // spaces, for example at line wraps. Extra wildcards included to // reduce flakyness in case wrapping is not consistent. // Spaces are not pronounced, so extra spaces do not impact output. - sm_.ExpectSpeechPattern("This is some*text*with*a*node*in*the*middle*"); - sm_.Replay(); + EXPECT_TRUE( + base::MatchPattern(speech_monitor_.GetNextUtterance(), + "This is some*text*with*a*node*in*the*middle*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, SmoothlyReadsAcrossFormattedText) { @@ -257,8 +259,9 @@ // Should combine nodes in a paragraph into one utterance. // Includes some wildcards between words because there may be extra // spaces. Spaces are not pronounced, so extra spaces do not impact output. - sm_.ExpectSpeechPattern("This is some text*with a node*in the middle*"); - sm_.Replay(); + EXPECT_TRUE( + base::MatchPattern(speech_monitor_.GetNextUtterance(), + "This is some text*with a node*in the middle*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, @@ -266,9 +269,8 @@ // Bold or formatted text ActivateSelectToSpeakInWindowBounds( "data:text/html;charset=utf-8,<canvas>This is some text</canvas>"); - - sm_.ExpectSpeechPattern("This is some text*"); - sm_.Replay(); + EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(), + "This is some text*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, BreaksAtParagraphBounds) { @@ -277,9 +279,10 @@ "<p>Second paragraph</p></div>"); // Should keep each paragraph as its own utterance. - sm_.ExpectSpeechPattern("First paragraph*"); - sm_.ExpectSpeechPattern("Second paragraph*"); - sm_.Replay(); + EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(), + "First paragraph*")); + EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(), + "Second paragraph*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, LanguageBoundsIgnoredByDefault) { @@ -290,8 +293,9 @@ "<span lang='en-US'>The first paragraph</span>" "<span lang='fr-FR'>la deuxième paragraphe</span></div>"); - sm_.ExpectSpeechPattern("The first paragraph* la deuxième paragraphe*"); - sm_.Replay(); + EXPECT_TRUE( + base::MatchPattern(speech_monitor_.GetNextUtterance(), + "The first paragraph* la deuxième paragraphe*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTestWithLanguageDetection, @@ -301,9 +305,15 @@ "<span lang='en-US'>The first paragraph</span>" "<span lang='fr-FR'>la deuxième paragraphe</span></div>"); - sm_.ExpectSpeechPatternWithLocale("The first paragraph*", "en-US"); - sm_.ExpectSpeechPatternWithLocale("la deuxième paragraphe*", "fr-FR"); - sm_.Replay(); + SpeechMonitorUtterance result1 = + speech_monitor_.GetNextUtteranceWithLanguage(); + EXPECT_TRUE(base::MatchPattern(result1.text, "The first paragraph*")); + EXPECT_EQ("en-US", result1.lang); + + SpeechMonitorUtterance result2 = + speech_monitor_.GetNextUtteranceWithLanguage(); + EXPECT_TRUE(base::MatchPattern(result2.text, "la deuxième paragraphe*")); + EXPECT_EQ("fr-FR", result2.lang); } // Flaky test. https://crbug.com/950049 @@ -389,16 +399,15 @@ "<p>Second paragraph is longer than 300 pixels and will wrap when " "resized</p></div>"); - sm_.ExpectSpeechPattern("First paragraph*"); + EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(), + "First paragraph*")); // Resize before second is spoken. If resizing caused errors finding the // inlineTextBoxes in the node, speech would be stopped early. - sm_.Call([this]() { - ExecuteJavaScriptAsync( - "document.getElementById('resize').style.width='100px'"); - }); - sm_.ExpectSpeechPattern("*when*resized*"); - sm_.Replay(); + ExecuteJavaScriptInForeground( + "document.getElementById('resize').style.width='100px'"); + EXPECT_TRUE( + base::MatchPattern(speech_monitor_.GetNextUtterance(), "*when*resized*")); } IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, WorksWithStickyKeys) { @@ -420,12 +429,11 @@ bounds.y() + bounds.height()); generator_->ReleaseLeftButton(); - sm_.ExpectSpeechPattern("This is some text*"); + EXPECT_TRUE(base::MatchPattern(speech_monitor_.GetNextUtterance(), + "This is some text*")); // Reset state. - sm_.Call([]() { AccessibilityManager::Get()->EnableStickyKeys(false); }); - - sm_.Replay(); + AccessibilityManager::Get()->EnableStickyKeys(false); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.cc b/chrome/browser/chromeos/accessibility/speech_monitor.cc index 6516aa3..0d84ff4 100644 --- a/chrome/browser/chromeos/accessibility/speech_monitor.cc +++ b/chrome/browser/chromeos/accessibility/speech_monitor.cc
@@ -12,9 +12,12 @@ namespace chromeos { namespace { +const char kChromeVoxEnabledMessage[] = "ChromeVox spoken feedback is ready"; +const char kChromeVoxAlertMessage[] = "Alert"; +const char kChromeVoxUpdate1[] = "chrome vox Updated Press chrome vox o,"; +const char kChromeVoxUpdate2[] = "n to learn more about chrome vox Next."; constexpr int kPrintExpectationDelayMs = 3000; - } // namespace SpeechMonitor::SpeechMonitor() { @@ -28,6 +31,52 @@ CHECK(replay_called_) << "Expectation was made, but Replay() not called."; } +std::string SpeechMonitor::GetNextUtterance() { + return GetNextUtteranceWithLanguage().text; +} + +SpeechMonitorUtterance SpeechMonitor::GetNextUtteranceWithLanguage() { + if (utterance_queue_.empty()) { + loop_runner_ = new content::MessageLoopRunner(); + loop_runner_->Run(); + loop_runner_.reset(); + } + SpeechMonitorUtterance result = utterance_queue_.front(); + utterance_queue_.pop_front(); + return result; +} + +bool SpeechMonitor::SkipChromeVoxEnabledMessage() { + return SkipChromeVoxMessage(kChromeVoxEnabledMessage); +} + +bool SpeechMonitor::DidStop() { + return did_stop_; +} + +void SpeechMonitor::BlockUntilStop() { + if (!did_stop_) { + loop_runner_ = new content::MessageLoopRunner(); + loop_runner_->Run(); + loop_runner_.reset(); + } +} + +bool SpeechMonitor::SkipChromeVoxMessage(const std::string& message) { + while (true) { + if (utterance_queue_.empty()) { + loop_runner_ = new content::MessageLoopRunner(); + loop_runner_->Run(); + loop_runner_.reset(); + } + SpeechMonitorUtterance result = utterance_queue_.front(); + utterance_queue_.pop_front(); + if (result.text == message) + return true; + } + return false; +} + bool SpeechMonitor::PlatformImplAvailable() { return true; } @@ -46,6 +95,7 @@ } bool SpeechMonitor::StopSpeaking() { + did_stop_ = true; return true; } @@ -64,8 +114,21 @@ void SpeechMonitor::WillSpeakUtteranceWithVoice( content::TtsUtterance* utterance, const content::VoiceData& voice_data) { + // Blacklist some phrases. + // Filter out empty utterances which can be used to trigger a start event from + // tts as an earcon sync. + if (utterance->GetText() == "" || + utterance->GetText() == kChromeVoxAlertMessage || + utterance->GetText() == kChromeVoxUpdate1 || + utterance->GetText() == kChromeVoxUpdate2) + return; + + VLOG(0) << "Speaking " << utterance->GetText(); utterance_queue_.emplace_back(utterance->GetText(), utterance->GetLang()); delay_for_last_utterance_ms_ = CalculateUtteranceDelayMS(); + if (loop_runner_.get()) + loop_runner_->Quit(); + MaybeContinueReplay(); } @@ -120,19 +183,11 @@ void SpeechMonitor::ExpectSpeechPattern(const std::string& pattern, const base::Location& location) { - ExpectSpeechPatternWithLocale(pattern, "", location); -} - -void SpeechMonitor::ExpectSpeechPatternWithLocale( - const std::string& pattern, - const std::string& locale, - const base::Location& location) { CHECK(!replay_loop_runner_.get()); - replay_queue_.push_back({[this, pattern, locale]() { + replay_queue_.push_back({[this, pattern]() { for (auto it = utterance_queue_.begin(); it != utterance_queue_.end(); it++) { - if (base::MatchPattern(it->text, pattern) && - (locale.empty() || it->lang == locale)) { + if (base::MatchPattern(it->text, pattern)) { // Erase all utterances that came before the // match as well as the match itself. utterance_queue_.erase(
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.h b/chrome/browser/chromeos/accessibility/speech_monitor.h index 368de795..eb319a6 100644 --- a/chrome/browser/chromeos/accessibility/speech_monitor.h +++ b/chrome/browser/chromeos/accessibility/speech_monitor.h
@@ -25,13 +25,35 @@ }; // For testing purpose installs itself as the platform speech synthesis engine, -// allowing it to intercept all speech calls. Provides an api to make -// asynchronous function calls and expectations about resulting speech. +// allowing it to intercept all speech calls, and then provides a method to +// block until the next utterance is spoken. class SpeechMonitor : public content::TtsPlatform { public: SpeechMonitor(); virtual ~SpeechMonitor(); + // Blocing api. + // Use the following apis to write a synchronous test e.g. + // DoSomething(); + // EXPECT_EQ("foo", speech_monitor_.GetNextUtterance()); + + // Blocks until the next utterance is spoken, and returns its text. + std::string GetNextUtterance(); + // Blocks until the next utterance is spoken, and returns its text. + SpeechMonitorUtterance GetNextUtteranceWithLanguage(); + + // Wait for next utterance and return true if next utterance is ChromeVox + // enabled message. + bool SkipChromeVoxEnabledMessage(); + bool SkipChromeVoxMessage(const std::string& message); + + // Returns true if StopSpeaking() was called on TtsController. + bool DidStop(); + + // Blocks until StopSpeaking() is called on TtsController. + void BlockUntilStop(); + + // Non-blocking api. // Use these apis if you want to write an async test e.g. // sm_.ExpectSpeech("foo"); // sm_.Call([this]() { DoSomething(); }) @@ -45,10 +67,6 @@ const base::Location& location = FROM_HERE); void ExpectSpeechPattern(const std::string& pattern, const base::Location& location = FROM_HERE); - void ExpectSpeechPatternWithLocale( - const std::string& pattern, - const std::string& locale, - const base::Location& location = FROM_HERE); void ExpectNextSpeechIsNot(const std::string& text, const base::Location& location = FROM_HERE); void ExpectNextSpeechIsNotPattern(const std::string& pattern, @@ -93,17 +111,17 @@ void MaybeContinueReplay(); void MaybePrintExpectations(); + scoped_refptr<content::MessageLoopRunner> loop_runner_; // Our list of utterances and specified language. base::circular_deque<SpeechMonitorUtterance> utterance_queue_; - + bool did_stop_ = false; std::string error_; + // Delayed utterances. // Calculates the milliseconds elapsed since the last call to Speak(). double CalculateUtteranceDelayMS(); - // Stores the milliseconds elapsed since the last call to Speak(). double delay_for_last_utterance_ms_; - // Stores the last time Speak() was called. std::chrono::steady_clock::time_point time_of_last_utterance_;
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_app_list_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_app_list_browsertest.cc index 37f144a..055e0effa 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_app_list_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_app_list_browsertest.cc
@@ -8,12 +8,15 @@ #include "ash/app_list/test/test_search_result.h" #include "ash/app_list/views/app_list_view.h" #include "ash/shell.h" +#include "base/strings/pattern.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/app_list/app_list_client_impl.h" #include "chrome/common/chrome_switches.h" #include "chrome/grit/generated_resources.h" #include "chromeos/constants/chromeos_switches.h" +#include "components/account_id/account_id.h" #include "components/user_manager/user_names.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" @@ -101,8 +104,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, LauncherStateTransition) { EnableChromeVox(); - sm_.Call( - [this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); }); + EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); + sm_.ExpectSpeechPattern("Launcher"); sm_.ExpectSpeech("Button"); sm_.ExpectSpeech("Shelf"); @@ -135,8 +138,8 @@ DisabledFullscreenExpandButton) { EnableChromeVox(); - sm_.Call( - [this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); }); + EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); + sm_.ExpectSpeech("Shelf"); // Press space on the launcher button in shelf, this opens peeking launcher. @@ -172,8 +175,8 @@ EnableChromeVox(); - sm_.Call( - [this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); }); + EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); + sm_.ExpectSpeech("Press Search plus Space to activate"); // Press space on the launcher button in shelf, this opens peeking // launcher. @@ -209,8 +212,8 @@ EnableChromeVox(); - sm_.Call( - [this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); }); + EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); + sm_.ExpectSpeech("Press Search plus Space to activate"); // Press space on the launcher button in shelf, this opens peeking // launcher. @@ -254,12 +257,10 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListTest, NavigateAppLauncher) { EnableChromeVox(); - sm_.Call([this]() { - // Add one app to the applist. - PopulateApps(1); + // Add one app to the applist. + PopulateApps(1); - EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); - }); + EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); // Wait for it to say "Launcher", "Button", "Shelf", "Tool bar". sm_.ExpectSpeechPattern("Launcher");
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc index 00ae998c..201bab8 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -17,25 +17,38 @@ #include "ash/system/status_area_widget.h" #include "ash/system/unified/unified_system_tray.h" #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/macros.h" +#include "base/strings/pattern.h" +#include "base/strings/string_util.h" #include "base/task/post_task.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/login/login_manager_test.h" +#include "chrome/browser/chromeos/login/test/js_checker.h" +#include "chrome/browser/chromeos/login/ui/login_display_host.h" +#include "chrome/browser/chromeos/login/ui/webui_login_view.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/test/base/interactive_test_utils.h" +#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/ui_test_utils.h" #include "chromeos/constants/chromeos_switches.h" +#include "components/account_id/account_id.h" #include "components/user_manager/user_names.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/tts_controller.h" +#include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "extensions/browser/extension_host.h" @@ -148,23 +161,36 @@ void LoggedInSpokenFeedbackTest::EnableChromeVox() { // Test setup. - // Enable ChromeVox, wait for something to be spoken, and disable earcons. + // Enable ChromeVox, skip welcome message/notification, and disable earcons. ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); AccessibilityManager::Get()->EnableSpokenFeedback(true); - sm_.ExpectSpeechPattern("*"); - sm_.Call([this]() { DisableEarcons(); }); + EXPECT_TRUE(sm_.SkipChromeVoxEnabledMessage()); + DisableEarcons(); +} + +void LoggedInSpokenFeedbackTest::PressRepeatedlyUntilUtterance( + ui::KeyboardCode key, + const std::string& expected_utterance) { + // This helper function is needed when you want to poll for something + // that happens asynchronously. Keep pressing |key|, until + // the speech feedback that follows is |expected_utterance|. + // Note that this doesn't work if pressing that key doesn't speak anything + // at all before the asynchronous event occurred. + while (true) { + SendKeyPress(key); + const std::string& utterance = sm_.GetNextUtterance(); + if (utterance == expected_utterance) + break; + } } IN_PROC_BROWSER_TEST_F(LoggedInSpokenFeedbackTest, AddBookmark) { EnableChromeVox(); - - sm_.Call( - [this]() { chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR); }); + chrome::ExecuteCommand(browser(), IDC_SHOW_BOOKMARK_BAR); // Create a bookmark with title "foo". - sm_.Call( - [this]() { chrome::ExecuteCommand(browser(), IDC_BOOKMARK_THIS_TAB); }); + chrome::ExecuteCommand(browser(), IDC_BOOKMARK_THIS_TAB); sm_.ExpectSpeech("Bookmark name"); sm_.ExpectSpeech("about:blank"); @@ -215,9 +241,7 @@ IN_PROC_BROWSER_TEST_F(LoggedInSpokenFeedbackTest, NavigateNotificationCenter) { EnableChromeVox(); - sm_.Call([this]() { - EXPECT_TRUE(PerformAcceleratorAction(ash::TOGGLE_MESSAGE_CENTER_BUBBLE)); - }); + EXPECT_TRUE(PerformAcceleratorAction(ash::TOGGLE_MESSAGE_CENTER_BUBBLE)); sm_.ExpectSpeech( "Quick Settings, Press search plus left to access the notification " "center., window"); @@ -264,25 +288,21 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, EnableSpokenFeedback) { EnableChromeVox(); - sm_.Replay(); } IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, FocusToolbar) { EnableChromeVox(); - sm_.Call([this]() { chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR); }); - sm_.ExpectSpeech("Reload"); - sm_.ExpectSpeech("Button"); - - sm_.Replay(); + chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR); + while (sm_.GetNextUtterance() != "Reload") { + } + EXPECT_EQ("Button", sm_.GetNextUtterance()); } IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, TypeInOmnibox) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL( - browser(), GURL("data:text/html;charset=utf-8,<p>unused</p>")); - }); + ui_test_utils::NavigateToURL( + browser(), GURL("data:text/html;charset=utf-8,<p>unused</p>")); sm_.Call([this]() { SendKeyPressWithControl(ui::VKEY_L); }); sm_.ExpectSpeech("Address and search bar"); @@ -314,18 +334,22 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, FocusShelf) { EnableChromeVox(); - sm_.Call( - [this]() { EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); }); - sm_.ExpectSpeechPattern("Launcher"); - sm_.ExpectSpeech("Button"); - sm_.ExpectSpeech("Shelf"); - sm_.ExpectSpeech("Tool bar"); - sm_.ExpectSpeech(", window"); - sm_.ExpectSpeech("Press Search plus Space to activate"); + EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); + while (true) { + std::string utterance = sm_.GetNextUtterance(); + if (base::MatchPattern(utterance, "Launcher")) + break; + } + EXPECT_EQ("Button", sm_.GetNextUtterance()); - sm_.Call([this]() { SendKeyPress(ui::VKEY_TAB); }); - sm_.ExpectSpeechPattern("Button"); - sm_.Replay(); + EXPECT_EQ("Shelf", sm_.GetNextUtterance()); + EXPECT_EQ("Tool bar", sm_.GetNextUtterance()); + EXPECT_EQ(", window", sm_.GetNextUtterance()); + EXPECT_EQ("Press Search plus Space to activate", sm_.GetNextUtterance()); + + SendKeyPress(ui::VKEY_TAB); + EXPECT_TRUE(base::MatchPattern(sm_.GetNextUtterance(), "*")); + EXPECT_TRUE(base::MatchPattern(sm_.GetNextUtterance(), "Button")); } // Verifies that pressing right arrow button with search button should move @@ -338,11 +362,9 @@ // when an extension is enabled, the ShelfItems which are not recorded as // pinned apps in user preference will be removed. EnableChromeVox(); - sm_.Call([controller, title]() { - controller->CreateAppShortcutLauncherItem( - ash::ShelfID("FakeApp"), controller->shelf_model()->item_count(), - base::ASCIIToUTF16(title)); - }); + controller->CreateAppShortcutLauncherItem( + ash::ShelfID("FakeApp"), controller->shelf_model()->item_count(), + base::ASCIIToUTF16(title)); // Focus on the shelf. sm_.Call([this]() { PerformAcceleratorAction(ash::FOCUS_SHELF); }); @@ -374,35 +396,31 @@ // pinned apps in user preference will be removed. EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL(browser(), - GURL("data:text/html;charset=utf-8,<button " - "autofocus>Click me</button>")); - }); + ui_test_utils::NavigateToURL( + browser(), + GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>")); sm_.ExpectSpeech("Click me"); - sm_.Call([this]() { - // Add three Shelf buttons. Wait for the change on ShelfModel to reach ash. - ChromeLauncherController* controller = ChromeLauncherController::instance(); - const int base_index = controller->shelf_model()->item_count(); - const std::string title("MockApp"); - const std::string id("FakeApp"); - const int insert_app_num = 3; - for (int i = 0; i < insert_app_num; i++) { - std::string app_title = title + base::NumberToString(i); - std::string app_id = id + base::NumberToString(i); - controller->CreateAppShortcutLauncherItem( - ash::ShelfID(app_id), base_index + i, base::ASCIIToUTF16(app_title)); - } + // Add three Shelf buttons. Wait for the change on ShelfModel to reach ash. + ChromeLauncherController* controller = ChromeLauncherController::instance(); + const int base_index = controller->shelf_model()->item_count(); + const std::string title("MockApp"); + const std::string id("FakeApp"); + const int insert_app_num = 3; + for (int i = 0; i < insert_app_num; i++) { + std::string app_title = title + base::NumberToString(i); + std::string app_id = id + base::NumberToString(i); + controller->CreateAppShortcutLauncherItem( + ash::ShelfID(app_id), base_index + i, base::ASCIIToUTF16(app_title)); + } - // Enable the function of speaking text under mouse. - ash::EventRewriterController::Get()->SetSendMouseEventsToDelegate(true); + // Enable the function of speaking text under mouse. + ash::EventRewriterController::Get()->SetSendMouseEventsToDelegate(true); - // Focus on the Shelf because voice text for focusing on Shelf is fixed. - // Wait until voice announcements are finished. - EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); - }); + // Focus on the Shelf because voice text for focusing on Shelf is fixed. Wait + // until voice announcements are finished. + EXPECT_TRUE(PerformAcceleratorAction(ash::FOCUS_SHELF)); sm_.ExpectSpeechPattern("Launcher"); // Hover mouse on the Shelf button. Verifies that text under mouse is spoken. @@ -428,13 +446,15 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, OpenStatusTray) { EnableChromeVox(); - sm_.Call([this]() { - EXPECT_TRUE(PerformAcceleratorAction(ash::TOGGLE_SYSTEM_TRAY_BUBBLE)); - }); - sm_.ExpectSpeech( - "Quick Settings, Press search plus left to access the notification " - "center., window"); - sm_.Replay(); + EXPECT_TRUE(PerformAcceleratorAction(ash::TOGGLE_SYSTEM_TRAY_BUBBLE)); + while (true) { + std::string utterance = sm_.GetNextUtterance(); + // TODO: this seems like a regression. + if (base::MatchPattern(utterance, + "Quick Settings, Press search plus left to access " + "the notification center., window")) + break; + } } // Fails on ASAN. See http://crbug.com/776308 . (Note MAYBE_ doesn't work well @@ -491,11 +511,9 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, OverviewMode) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL(browser(), - GURL("data:text/html;charset=utf-8,<button " - "autofocus>Click me</button>")); - }); + ui_test_utils::NavigateToURL( + browser(), + GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>")); sm_.ExpectSpeech("Click me"); @@ -515,16 +533,14 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxFindInPage) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL(browser(), - GURL("data:text/html;charset=utf-8,<button " - "autofocus>Click me</button>")); - }); + ui_test_utils::NavigateToURL( + browser(), + GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>")); sm_.ExpectSpeech("Click me"); // Press Search+/ to enter ChromeVox's "find in page". - sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_OEM_2); }); + SendKeyPressWithSearch(ui::VKEY_OEM_2); sm_.ExpectSpeech("Find in page"); sm_.Replay(); } @@ -532,12 +548,11 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxNavigateAndSelect) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL(browser(), - GURL("data:text/html;charset=utf-8," - "<h1>Title</h1>" - "<button autofocus>Click me</button>")); - }); + ui_test_utils::NavigateToURL(browser(), + GURL("data:text/html;charset=utf-8," + "<h1>Title</h1>" + "<button autofocus>Click me</button>")); + sm_.ExpectSpeech("Click me"); // Press Search+Left to navigate to the previous item. @@ -560,11 +575,10 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxStickyMode) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL(browser(), - GURL("data:text/html;charset=utf-8,<button " - "autofocus>Click me</button>")); - }); + ui_test_utils::NavigateToURL( + browser(), + GURL("data:text/html;charset=utf-8,<button autofocus>Click me</button>")); + sm_.ExpectSpeech("Click me"); // Press the sticky-key sequence: Search Search. @@ -583,7 +597,7 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, TouchExploreStatusTray) { EnableChromeVox(); - sm_.Call([this]() { SimulateTouchScreenInChromeVox(); }); + SimulateTouchScreenInChromeVox(); // Send an accessibility hover event on the system tray, which is // what we get when you tap it on a touch screen when ChromeVox is on. @@ -603,42 +617,108 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxNextTabRecovery) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL( - browser(), GURL("data:text/html;charset=utf-8," - "<button id='b1' autofocus>11</button>" - "<button>22</button>" - "<button>33</button>" - "<h1>Middle</h1>" - "<button>44</button>" - "<button>55</button>" - "<div id=console aria-live=polite></div>" - "<script>" - "var b1 = document.getElementById('b1');" - "b1.addEventListener('blur', function() {" - " document.getElementById('console').innerText = " - "'button lost focus';" - "});" - "</script>")); - }); - sm_.ExpectSpeech("Button"); + ui_test_utils::NavigateToURL( + browser(), GURL("data:text/html;charset=utf-8," + "<button id='b1' autofocus>11</button>" + "<button>22</button>" + "<button>33</button>" + "<h1>Middle</h1>" + "<button>44</button>" + "<button>55</button>" + "<div id=console aria-live=polite></div>" + "<script>" + "var b1 = document.getElementById('b1');" + "b1.addEventListener('blur', function() {" + " document.getElementById('console').innerText = " + "'button lost focus';" + "});" + "</script>")); + while ("Button" != sm_.GetNextUtterance()) { + } // Press Search+H to go to the next heading - sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_H); }); + SendKeyPressWithSearch(ui::VKEY_H); sm_.ExpectSpeech("Middle"); - // To ensure that the setSequentialFocusNavigationStartingPoint has // executed before pressing Tab, the page has an event handler waiting // for the 'blur' event on the button, and when it loses focus it // triggers a live region announcement that we wait for, here. sm_.ExpectSpeech("button lost focus"); - // Now we know that focus has left the button, so the sequential focus // navigation starting point must be on the heading. Press Tab and // ensure that we land on the first link past the heading. sm_.Call([this]() { SendKeyPress(ui::VKEY_TAB); }); sm_.ExpectSpeech("44"); + sm_.Replay(); +} + +// +// Spoken feedback tests that run only in guest mode. +// + +class GuestSpokenFeedbackTest : public LoggedInSpokenFeedbackTest { + protected: + GuestSpokenFeedbackTest() {} + ~GuestSpokenFeedbackTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(chromeos::switches::kGuestSession); + command_line->AppendSwitch(::switches::kIncognito); + command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); + command_line->AppendSwitchASCII( + switches::kLoginUser, user_manager::GuestAccountId().GetUserEmail()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(GuestSpokenFeedbackTest); +}; + +IN_PROC_BROWSER_TEST_F(GuestSpokenFeedbackTest, FocusToolbar) { + EnableChromeVox(); + chrome::ExecuteCommand(browser(), IDC_FOCUS_TOOLBAR); + sm_.ExpectSpeech("Reload"); + sm_.ExpectSpeech("Button"); + sm_.Replay(); +} + +// +// Spoken feedback tests of the out-of-box experience. +// + +class OobeSpokenFeedbackTest : public LoginManagerTest { + protected: + OobeSpokenFeedbackTest() + : LoginManagerTest(false, true /* should_initialize_webui */) {} + ~OobeSpokenFeedbackTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + LoginManagerTest::SetUpCommandLine(command_line); + // Many bots don't have keyboard/mice which triggers the HID detection + // dialog in the OOBE. Avoid confusing the tests with that. + command_line->AppendSwitch(chromeos::switches::kDisableHIDDetectionOnOOBE); + } + + SpeechMonitor sm_; + + private: + DISALLOW_COPY_AND_ASSIGN(OobeSpokenFeedbackTest); +}; + +IN_PROC_BROWSER_TEST_F(OobeSpokenFeedbackTest, SpokenFeedbackInOobe) { + ui_controls::EnableUIControls(); + ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); + AccessibilityManager::Get()->EnableSpokenFeedback(true); + + // The Let's go button gets initial focus. + sm_.ExpectSpeech("Let's go"); + + sm_.Call([]() { + ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( + nullptr, ui::VKEY_TAB, false, false, false, false)); + }); + sm_.ExpectSpeech("Shut down"); + sm_.ExpectSpeech("Button"); sm_.Replay(); } @@ -646,10 +726,9 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, MoveByCharacterPhoneticSpeechAndHints) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL( - browser(), GURL("data:text/html,<button autofocus>Click me</button>")); - }); + ui_test_utils::NavigateToURL( + browser(), GURL("data:text/html,<button autofocus>Click me</button>")); + sm_.ExpectSpeech("Web Content"); sm_.ExpectSpeech("Click me"); sm_.ExpectSpeech("Button"); sm_.ExpectSpeech("Press Search plus Space to activate"); @@ -709,10 +788,8 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ResetTtsSettings) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL( - browser(), GURL("data:text/html,<button autofocus>Click me</button>")); - }); + ui_test_utils::NavigateToURL( + browser(), GURL("data:text/html,<button autofocus>Click me</button>")); sm_.ExpectSpeech("Click me"); @@ -741,11 +818,9 @@ IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, SmartStickyMode) { EnableChromeVox(); - sm_.Call([this]() { - ui_test_utils::NavigateToURL(browser(), - GURL("data:text/html,<p>start</p><input " - "autofocus type='text'><p>end</p>")); - }); + ui_test_utils::NavigateToURL(browser(), + GURL("data:text/html,<p>start</p><input " + "autofocus type='text'><p>end</p>")); // The input is autofocused. sm_.ExpectSpeech("Edit text"); @@ -795,45 +870,4 @@ sm_.Replay(); } -// -// Spoken feedback tests of the out-of-box experience. -// - -class OobeSpokenFeedbackTest : public LoginManagerTest { - protected: - OobeSpokenFeedbackTest() - : LoginManagerTest(false, true /* should_initialize_webui */) {} - ~OobeSpokenFeedbackTest() override {} - - void SetUpCommandLine(base::CommandLine* command_line) override { - LoginManagerTest::SetUpCommandLine(command_line); - // Many bots don't have keyboard/mice which triggers the HID detection - // dialog in the OOBE. Avoid confusing the tests with that. - command_line->AppendSwitch(chromeos::switches::kDisableHIDDetectionOnOOBE); - } - - SpeechMonitor sm_; - - private: - DISALLOW_COPY_AND_ASSIGN(OobeSpokenFeedbackTest); -}; - -IN_PROC_BROWSER_TEST_F(OobeSpokenFeedbackTest, SpokenFeedbackInOobe) { - ui_controls::EnableUIControls(); - ASSERT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); - AccessibilityManager::Get()->EnableSpokenFeedback(true); - - // The Let's go button gets initial focus. - sm_.ExpectSpeech("Let's go"); - - sm_.Call([]() { - ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( - nullptr, ui::VKEY_TAB, false, false, false, false)); - }); - sm_.ExpectSpeech("Shut down"); - sm_.ExpectSpeech("Button"); - - sm_.Replay(); -} - } // namespace chromeos
diff --git a/chrome/browser/chromeos/crostini/crostini_registry_service.cc b/chrome/browser/chromeos/crostini/crostini_registry_service.cc index 22d39a1..0a634180 100644 --- a/chrome/browser/chromeos/crostini/crostini_registry_service.cc +++ b/chrome/browser/chromeos/crostini/crostini_registry_service.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/files/file_util.h" #include "base/metrics/histogram_macros.h" -#include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/task/post_task.h" @@ -21,7 +20,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/crostini/crostini_features.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" -#include "chrome/browser/chromeos/crostini/crostini_pref_names.h" #include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_syncable_service.h" @@ -40,31 +38,14 @@ namespace { -// Prefix of the ApplicationId set on exo windows for X apps. -constexpr char kCrostiniWindowAppIdPrefix[] = "org.chromium.termina."; -// This comes after kCrostiniWindowAppIdPrefix -constexpr char kWMClassPrefix[] = "wmclass."; +// This prefix is used when generating the crostini app list id. +constexpr char kCrostiniAppIdPrefix[] = "crostini:"; constexpr char kCrostiniIconFolder[] = "crostini.icons"; constexpr char kCrostiniAppsInstalledHistogram[] = "Crostini.AppsInstalledAtLogin"; -const std::string* GetAppNameForWMClass(base::StringPiece wmclass) { - // A hard-coded mapping from WMClass to app names. - // This is used to deal with the Linux apps that don't specify the correct - // WMClass in their desktop files so that their aura windows can be identified - // with their respective app IDs. - static const base::NoDestructor<std::map<std::string, std::string>> - kWMClassToNname({{"Octave-gui", "GNU Octave"}, - {"MuseScore2", "MuseScore 2"}, - {"XnViewMP", "XnView Multi Platform"}}); - const auto it = kWMClassToNname->find(wmclass.as_string()); - if (it == kWMClassToNname->end()) - return nullptr; - return &it->second; -} - std::string GenerateAppId(const std::string& desktop_file_id, const std::string& vm_name, const std::string& container_name) { @@ -171,76 +152,6 @@ base::TimeDelta::FromMicroseconds(time)); } -bool MatchingString(const std::string& search_string, - const std::string& value_string, - bool ignore_space) { - std::string search = search_string; - std::string value = value_string; - if (ignore_space) { - base::RemoveChars(search, " ", &search); - base::RemoveChars(value, " ", &value); - } - return base::EqualsCaseInsensitiveASCII(search, value); -} - -enum class FindAppIdResult { NoMatch, UniqueMatch, NonUniqueMatch }; -// Looks for an app where prefs_key is set to search_value. Returns the apps id -// if there was only one app matching, otherwise returns an empty string. -FindAppIdResult FindAppId(const base::DictionaryValue* prefs, - base::StringPiece prefs_key, - base::StringPiece search_value, - std::string* result, - bool require_startup_notify = false, - bool need_display = false, - bool ignore_space = false) { - result->clear(); - for (const auto& item : prefs->DictItems()) { - if (item.first == GetTerminalId()) - continue; - - if (require_startup_notify && - !item.second - .FindKeyOfType(guest_os::prefs::kAppStartupNotifyKey, - base::Value::Type::BOOLEAN) - ->GetBool()) - continue; - - if (need_display) { - const base::Value* no_display = item.second.FindKeyOfType( - guest_os::prefs::kAppNoDisplayKey, base::Value::Type::BOOLEAN); - if (no_display && no_display->GetBool()) - continue; - } - - const base::Value* value = item.second.FindKey(prefs_key); - if (!value) - continue; - if (value->type() == base::Value::Type::STRING) { - if (!MatchingString(search_value.as_string(), value->GetString(), - ignore_space)) { - continue; - } - } else if (value->type() == base::Value::Type::DICTIONARY) { - // Look at the unlocalized name to see if that matches. - value = value->FindKeyOfType("", base::Value::Type::STRING); - if (!value || !MatchingString(search_value.as_string(), - value->GetString(), ignore_space)) { - continue; - } - } else { - continue; - } - - if (!result->empty()) - return FindAppIdResult::NonUniqueMatch; - *result = item.first; - } - - if (!result->empty()) - return FindAppIdResult::UniqueMatch; - return FindAppIdResult::NoMatch; -} - bool EqualsExcludingTimestamps(const base::Value& left, const base::Value& right) { auto left_items = left.DictItems(); @@ -566,107 +477,6 @@ return weak_ptr_factory_.GetWeakPtr(); } -// The code follows these steps to identify apps and returns the first match: -// 1) If the Startup Id is set, look for a matching desktop file id. -// 2) Ignore windows if the App Id is not set. -// 3) If the App Id is not prefixed by org.chromium.termina., it's an app with -// native Wayland support. Look for a matching desktop file id. -// 4) If the App Id is prefixed by org.chromium.termina.wmclass.: -// 4.1) Look for an app where StartupWMClass is matches the suffix. -// 4.2) Look for an app where the desktop file id matches the suffix. -// 4.3) Look for an app where the unlocalized name matches the suffix. This -// handles the xterm & uxterm examples. -// 5) If we couldn't find a match, prefix the app id with 'crostini:' so we can -// easily identify shelf entries as Crostini apps. -std::string CrostiniRegistryService::GetCrostiniShelfAppId( - const std::string* window_app_id, - const std::string* window_startup_id) { - const base::DictionaryValue* apps = - prefs_->GetDictionary(guest_os::prefs::kGuestOsRegistry); - std::string app_id; - - if (window_startup_id) { - // TODO(timloh): We should use a value that is unique so we can handle - // an app installed in multiple containers. - if (FindAppId(apps, guest_os::prefs::kAppDesktopFileIdKey, - *window_startup_id, &app_id, - true) == FindAppIdResult::UniqueMatch) - return app_id; - LOG(ERROR) << "Startup ID was set to '" << *window_startup_id - << "' but not matched"; - // Try a lookup with the window app id. - } - - if (!window_app_id) - return std::string(); - - // Wayland apps won't be prefixed with org.chromium.termina. - if (!base::StartsWith(*window_app_id, kCrostiniWindowAppIdPrefix, - base::CompareCase::SENSITIVE)) { - if (FindAppId(apps, guest_os::prefs::kAppDesktopFileIdKey, *window_app_id, - &app_id) == FindAppIdResult::UniqueMatch) { - return app_id; - } - return kCrostiniAppIdPrefix + *window_app_id; - } - - base::StringPiece suffix( - window_app_id->begin() + strlen(kCrostiniWindowAppIdPrefix), - window_app_id->end()); - - // If we don't have an id to match to a desktop file, use the window app id. - if (!base::StartsWith(suffix, kWMClassPrefix, base::CompareCase::SENSITIVE)) - return kCrostiniAppIdPrefix + *window_app_id; - - // If an app had StartupWMClass set to the given WM class, use that, - // otherwise look for a desktop file id matching the WM class. - base::StringPiece key = suffix.substr(strlen(kWMClassPrefix)); - FindAppIdResult result = FindAppId( - apps, guest_os::prefs::kAppStartupWMClassKey, key, &app_id, - false /* require_startup_notification */, true /* need_display */); - if (result == FindAppIdResult::UniqueMatch) - return app_id; - if (result == FindAppIdResult::NonUniqueMatch) - return kCrostiniAppIdPrefix + *window_app_id; - - if (FindAppId(apps, guest_os::prefs::kAppDesktopFileIdKey, key, &app_id) == - FindAppIdResult::UniqueMatch) { - return app_id; - } - - if (FindAppId(apps, guest_os::prefs::kAppNameKey, key, &app_id, - false /* require_startup_notification */, - true /* need_display */, - true /* ignore_space */) == FindAppIdResult::UniqueMatch) { - return app_id; - } - - const std::string* app_name = GetAppNameForWMClass(key); - if (app_name && - FindAppId(apps, guest_os::prefs::kAppNameKey, *app_name, &app_id, - false /* require_startup_notification */, - true /* need_display */) == FindAppIdResult::UniqueMatch) { - return app_id; - } - - return kCrostiniAppIdPrefix + *window_app_id; -} - -bool CrostiniRegistryService::IsCrostiniShelfAppId( - const std::string& shelf_app_id) { - if (base::StartsWith(shelf_app_id, kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { - return true; - } - if (shelf_app_id == GetTerminalId()) - return true; - // TODO(timloh): We need to handle desktop files that have been removed. - // For example, running windows with a no-longer-valid app id will try to - // use the ExtensionContextMenuModel. - return prefs_->GetDictionary(guest_os::prefs::kGuestOsRegistry) - ->FindKey(shelf_app_id) != nullptr; -} - std::map<std::string, CrostiniRegistryService::Registration> CrostiniRegistryService::GetRegisteredApps() const { const base::DictionaryValue* apps =
diff --git a/chrome/browser/chromeos/crostini/crostini_registry_service.h b/chrome/browser/chromeos/crostini/crostini_registry_service.h index cbc7e77..b245bdc 100644 --- a/chrome/browser/chromeos/crostini/crostini_registry_service.h +++ b/chrome/browser/chromeos/crostini/crostini_registry_service.h
@@ -35,10 +35,6 @@ namespace crostini { -// This prefix is used when generating the crostini app list id, and used as a -// prefix when generating shelf ids for windows we couldn't match to an app. -constexpr char kCrostiniAppIdPrefix[] = "crostini:"; - // The CrostiniRegistryService stores information about Desktop Entries (apps) // in Crostini. We store this in prefs so that it is readily available even when // the VM isn't running. The registrations here correspond to .desktop files, @@ -137,21 +133,6 @@ base::WeakPtr<CrostiniRegistryService> GetWeakPtr(); - // Returns a shelf app id for an exo window startup id or app id. - // - // First try to return a desktop file id matching the |window_startup_id|. - // - // If the app id is empty, returns empty string. If we can uniquely identify - // a registry entry, returns the crostini app id for that. Otherwise, returns - // the string pointed to by |window_app_id|, prefixed by "crostini:". - // - // As the window app id is derived from fields set by the app itself, it is - // possible for an app to masquerade as a different app. - std::string GetCrostiniShelfAppId(const std::string* window_app_id, - const std::string* window_startup_id); - // Returns whether the app_id is a Crostini app id. - bool IsCrostiniShelfAppId(const std::string& shelf_app_id); - // Return all installed apps. This always includes the Terminal app. std::map<std::string, CrostiniRegistryService::Registration> GetRegisteredApps() const;
diff --git a/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc b/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc index bac1368..95564be5 100644 --- a/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc
@@ -53,10 +53,6 @@ const std::vector<std::string>&)); }; - std::string WindowIdForWMClass(const std::string& wm_class) { - return "org.chromium.termina.wmclass." + wm_class; - } - CrostiniRegistryService* service() { return service_.get(); } Profile* profile() { return &profile_; } @@ -332,115 +328,6 @@ app_id_1, app_id_2, GetTerminalId())); } -TEST_F(CrostiniRegistryServiceTest, GetCrostiniAppIdNoStartupID) { - ApplicationList app_list = - CrostiniTestHelper::BasicAppList("app", "vm", "container"); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("cool.app"); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("super"); - service()->UpdateApplicationList(app_list); - - service()->UpdateApplicationList( - CrostiniTestHelper::BasicAppList("super", "vm 2", "container")); - - EXPECT_THAT(service()->GetRegisteredApps(), testing::SizeIs(5)); - - EXPECT_TRUE(service()->GetCrostiniShelfAppId(nullptr, nullptr).empty()); - - std::string window_app_id = WindowIdForWMClass("App"); - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - CrostiniTestHelper::GenerateAppId("app", "vm", "container")); - - window_app_id = WindowIdForWMClass("cool.app"); - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - CrostiniTestHelper::GenerateAppId("cool.app", "vm", "container")); - - window_app_id = WindowIdForWMClass("super"); - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - "crostini:" + WindowIdForWMClass("super")); - - window_app_id = "org.chromium.termina.wmclientleader.1234"; - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - "crostini:org.chromium.termina.wmclientleader.1234"); - - window_app_id = "org.chromium.termina.xid.654321"; - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - "crostini:org.chromium.termina.xid.654321"); - - window_app_id = "cool.app"; - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - CrostiniTestHelper::GenerateAppId("cool.app", "vm", "container")); - - window_app_id = "fancy.app"; - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - "crostini:fancy.app"); -} - -TEST_F(CrostiniRegistryServiceTest, GetCrostiniAppIdStartupWMClass) { - ApplicationList app_list = - CrostiniTestHelper::BasicAppList("app", "vm", "container"); - app_list.mutable_apps(0)->set_startup_wm_class("app_start"); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("app2"); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("app3"); - app_list.mutable_apps(1)->set_startup_wm_class("app2"); - app_list.mutable_apps(2)->set_startup_wm_class("app2"); - service()->UpdateApplicationList(app_list); - - EXPECT_THAT(service()->GetRegisteredApps(), testing::SizeIs(4)); - - std::string window_app_id = WindowIdForWMClass("app_start"); - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - CrostiniTestHelper::GenerateAppId("app", "vm", "container")); - - window_app_id = WindowIdForWMClass("app2"); - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - "crostini:" + WindowIdForWMClass("app2")); -} - -TEST_F(CrostiniRegistryServiceTest, GetCrostiniAppIdStartupNotify) { - ApplicationList app_list = - CrostiniTestHelper::BasicAppList("app", "vm", "container"); - app_list.mutable_apps(0)->set_startup_notify(true); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("app2"); - service()->UpdateApplicationList(app_list); - - std::string window_app_id = "whatever"; - std::string startup_id = "app"; - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, &startup_id), - CrostiniTestHelper::GenerateAppId("app", "vm", "container")); - - startup_id = "app2"; - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, &startup_id), - "crostini:whatever"); - - startup_id = "app"; - EXPECT_EQ(service()->GetCrostiniShelfAppId(nullptr, &startup_id), - CrostiniTestHelper::GenerateAppId("app", "vm", "container")); -} - -TEST_F(CrostiniRegistryServiceTest, GetCrostiniAppIdName) { - ApplicationList app_list = - CrostiniTestHelper::BasicAppList("app", "vm", "container"); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("app2", "name2"); - service()->UpdateApplicationList(app_list); - - std::string window_app_id = WindowIdForWMClass("name2"); - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - CrostiniTestHelper::GenerateAppId("app2", "vm", "container")); -} - -TEST_F(CrostiniRegistryServiceTest, GetCrostiniAppIdNameSkipNoDisplay) { - ApplicationList app_list = - CrostiniTestHelper::BasicAppList("app", "vm", "container"); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("app2", "name2"); - *app_list.add_apps() = CrostiniTestHelper::BasicApp("another_app2", "name2", - true /* no_display */); - service()->UpdateApplicationList(app_list); - - std::string window_app_id = WindowIdForWMClass("name2"); - EXPECT_EQ(service()->GetCrostiniShelfAppId(&window_app_id, nullptr), - CrostiniTestHelper::GenerateAppId("app2", "vm", "container")); -} - TEST_F(CrostiniRegistryServiceTest, IsScaledReturnFalseWhenNotSet) { std::string app_id = CrostiniTestHelper::GenerateAppId("app", "vm", "container");
diff --git a/chrome/browser/chromeos/crostini/crostini_shelf_utils.cc b/chrome/browser/chromeos/crostini/crostini_shelf_utils.cc new file mode 100644 index 0000000..c3a56d7 --- /dev/null +++ b/chrome/browser/chromeos/crostini/crostini_shelf_utils.cc
@@ -0,0 +1,220 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" + +#include "base/no_destructor.h" +#include "base/strings/string_util.h" +#include "chrome/browser/chromeos/crostini/crostini_registry_service.h" +#include "chrome/browser/chromeos/crostini/crostini_util.h" +#include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h" +#include "chrome/browser/profiles/profile.h" +#include "components/prefs/pref_service.h" + +namespace crostini { + +namespace { + +// This prefix is used as a prefix when generating shelf ids for windows we +// couldn't match to an app. +constexpr char kCrostiniShelfIdPrefix[] = "crostini:"; +// Prefix of the ApplicationId set on exo windows for X apps. +constexpr char kCrostiniWindowAppIdPrefix[] = "org.chromium.termina."; +// This comes after kCrostiniWindowAppIdPrefix +constexpr char kWMClassPrefix[] = "wmclass."; + +const std::string* GetAppNameForWMClass(base::StringPiece wmclass) { + // A hard-coded mapping from WMClass to app names. + // This is used to deal with the Linux apps that don't specify the correct + // WMClass in their desktop files so that their aura windows can be identified + // with their respective app IDs. + static const base::NoDestructor<std::map<std::string, std::string>> + kWMClassToNname({{"Octave-gui", "GNU Octave"}, + {"MuseScore2", "MuseScore 2"}, + {"XnViewMP", "XnView Multi Platform"}}); + const auto it = kWMClassToNname->find(wmclass.as_string()); + if (it == kWMClassToNname->end()) + return nullptr; + return &it->second; +} + +bool MatchingString(const std::string& search_string, + const std::string& value_string, + bool ignore_space) { + std::string search = search_string; + std::string value = value_string; + if (ignore_space) { + base::RemoveChars(search, " ", &search); + base::RemoveChars(value, " ", &value); + } + return base::EqualsCaseInsensitiveASCII(search, value); +} + +enum class FindAppIdResult { NoMatch, UniqueMatch, NonUniqueMatch }; +// Looks for an app where prefs_key is set to search_value. Returns the apps id +// if there was only one app matching, otherwise returns an empty string. +FindAppIdResult FindAppId(const base::DictionaryValue* prefs, + base::StringPiece prefs_key, + base::StringPiece search_value, + std::string* result, + bool require_startup_notify = false, + bool need_display = false, + bool ignore_space = false) { + result->clear(); + for (const auto& item : prefs->DictItems()) { + if (item.first == GetTerminalId()) + continue; + + if (require_startup_notify && + !item.second + .FindKeyOfType(guest_os::prefs::kAppStartupNotifyKey, + base::Value::Type::BOOLEAN) + ->GetBool()) + continue; + + if (need_display) { + const base::Value* no_display = item.second.FindKeyOfType( + guest_os::prefs::kAppNoDisplayKey, base::Value::Type::BOOLEAN); + if (no_display && no_display->GetBool()) + continue; + } + + const base::Value* value = item.second.FindKey(prefs_key); + if (!value) + continue; + if (value->type() == base::Value::Type::STRING) { + if (!MatchingString(search_value.as_string(), value->GetString(), + ignore_space)) { + continue; + } + } else if (value->type() == base::Value::Type::DICTIONARY) { + // Look at the unlocalized name to see if that matches. + value = value->FindKeyOfType("", base::Value::Type::STRING); + if (!value || !MatchingString(search_value.as_string(), + value->GetString(), ignore_space)) { + continue; + } + } else { + continue; + } + + if (!result->empty()) + return FindAppIdResult::NonUniqueMatch; + *result = item.first; + } + + if (!result->empty()) + return FindAppIdResult::UniqueMatch; + return FindAppIdResult::NoMatch; +} + +} // namespace + +// The code follows these steps to identify apps and returns the first match: +// 1) If the Startup Id is set, look for a matching desktop file id. +// 2) Ignore windows if the App Id is not set. +// 3) If the App Id is not prefixed by org.chromium.termina., it's an app with +// native Wayland support. Look for a matching desktop file id. +// 4) If the App Id is prefixed by org.chromium.termina.wmclass.: +// 4.1) Look for an app where StartupWMClass is matches the suffix. +// 4.2) Look for an app where the desktop file id matches the suffix. +// 4.3) Look for an app where the unlocalized name matches the suffix. This +// handles the xterm & uxterm examples. +// 5) If we couldn't find a match, prefix the app id with 'crostini:' so we can +// easily identify shelf entries as Crostini apps. +std::string GetCrostiniShelfAppId(const Profile* profile, + const std::string* window_app_id, + const std::string* window_startup_id) { + const base::DictionaryValue* apps = + profile->GetPrefs()->GetDictionary(guest_os::prefs::kGuestOsRegistry); + std::string app_id; + + if (window_startup_id) { + // TODO(timloh): We should use a value that is unique so we can handle + // an app installed in multiple containers. + if (FindAppId(apps, guest_os::prefs::kAppDesktopFileIdKey, + *window_startup_id, &app_id, + true) == FindAppIdResult::UniqueMatch) + return app_id; + LOG(ERROR) << "Startup ID was set to '" << *window_startup_id + << "' but not matched"; + // Try a lookup with the window app id. + } + + if (!window_app_id) + return std::string(); + + // Wayland apps won't be prefixed with org.chromium.termina. + if (!base::StartsWith(*window_app_id, kCrostiniWindowAppIdPrefix, + base::CompareCase::SENSITIVE)) { + if (FindAppId(apps, guest_os::prefs::kAppDesktopFileIdKey, *window_app_id, + &app_id) == FindAppIdResult::UniqueMatch) { + return app_id; + } + return kCrostiniShelfIdPrefix + *window_app_id; + } + + base::StringPiece suffix( + window_app_id->begin() + strlen(kCrostiniWindowAppIdPrefix), + window_app_id->end()); + + // If we don't have an id to match to a desktop file, use the window app id. + if (!base::StartsWith(suffix, kWMClassPrefix, base::CompareCase::SENSITIVE)) + return kCrostiniShelfIdPrefix + *window_app_id; + + // If an app had StartupWMClass set to the given WM class, use that, + // otherwise look for a desktop file id matching the WM class. + base::StringPiece key = suffix.substr(strlen(kWMClassPrefix)); + FindAppIdResult result = FindAppId( + apps, guest_os::prefs::kAppStartupWMClassKey, key, &app_id, + false /* require_startup_notification */, true /* need_display */); + if (result == FindAppIdResult::UniqueMatch) + return app_id; + if (result == FindAppIdResult::NonUniqueMatch) + return kCrostiniShelfIdPrefix + *window_app_id; + + if (FindAppId(apps, guest_os::prefs::kAppDesktopFileIdKey, key, &app_id) == + FindAppIdResult::UniqueMatch) { + return app_id; + } + + if (FindAppId(apps, guest_os::prefs::kAppNameKey, key, &app_id, + false /* require_startup_notification */, + true /* need_display */, + true /* ignore_space */) == FindAppIdResult::UniqueMatch) { + return app_id; + } + + const std::string* app_name = GetAppNameForWMClass(key); + if (app_name && + FindAppId(apps, guest_os::prefs::kAppNameKey, *app_name, &app_id, + false /* require_startup_notification */, + true /* need_display */) == FindAppIdResult::UniqueMatch) { + return app_id; + } + + return kCrostiniShelfIdPrefix + *window_app_id; +} + +bool IsUnmatchedCrostiniShelfAppId(base::StringPiece shelf_app_id) { + return base::StartsWith(shelf_app_id, kCrostiniShelfIdPrefix, + base::CompareCase::SENSITIVE); +} + +bool IsCrostiniShelfAppId(const Profile* profile, + base::StringPiece shelf_app_id) { + if (IsUnmatchedCrostiniShelfAppId(shelf_app_id)) { + return true; + } + if (shelf_app_id == GetTerminalId()) + return true; + // TODO(timloh): We need to handle desktop files that have been removed. + // For example, running windows with a no-longer-valid app id will try to + // use the ExtensionContextMenuModel. + return profile->GetPrefs() + ->GetDictionary(guest_os::prefs::kGuestOsRegistry) + ->FindKey(shelf_app_id) != nullptr; +} + +} // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_shelf_utils.h b/chrome/browser/chromeos/crostini/crostini_shelf_utils.h new file mode 100644 index 0000000..40a3bcd --- /dev/null +++ b/chrome/browser/chromeos/crostini/crostini_shelf_utils.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 CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_SHELF_UTILS_H_ +#define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_SHELF_UTILS_H_ + +#include <string> +#include "base/strings/string_piece_forward.h" + +class Profile; + +namespace crostini { + +// Returns a shelf app id for an exo window startup id or app id. +// +// First try to return a desktop file id matching the |window_startup_id|. +// +// If the app id is empty, returns empty string. If we can uniquely identify +// a registry entry, returns the crostini app id for that. Otherwise, returns +// the string pointed to by |window_app_id|, prefixed by "crostini:". +// +// As the window app id is derived from fields set by the app itself, it is +// possible for an app to masquerade as a different app. +std::string GetCrostiniShelfAppId(const Profile* profile, + const std::string* window_app_id, + const std::string* window_startup_id); + +// Returns whether the app_id is an unmatched Crostini app id. +bool IsUnmatchedCrostiniShelfAppId(base::StringPiece shelf_app_id); + +// Returns whether the app_id is a Crostini app id. +bool IsCrostiniShelfAppId(const Profile* profile, + base::StringPiece shelf_app_id); + +} // namespace crostini + +#endif // CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_SHELF_UTILS_H_
diff --git a/chrome/browser/chromeos/crostini/crostini_shelf_utils_unittest.cc b/chrome/browser/chromeos/crostini/crostini_shelf_utils_unittest.cc new file mode 100644 index 0000000..5977299 --- /dev/null +++ b/chrome/browser/chromeos/crostini/crostini_shelf_utils_unittest.cc
@@ -0,0 +1,232 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" +#include <iterator> +#include <memory> + +#include "base/optional.h" +#include "base/values.h" +#include "chrome/browser/chromeos/crostini/crostini_registry_service.h" +#include "chrome/browser/chromeos/crostini/crostini_test_helper.h" +#include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h" +#include "chrome/test/base/testing_profile.h" +#include "components/prefs/pref_service.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace crostini { + +namespace { + +struct App { + std::string desktop_file_id; + std::string vm_name = "vm"; + std::string container_name = "container"; + std::string app_name = ""; + base::Optional<std::string> startup_wm_class; + base::Optional<bool> startup_notify; + base::Optional<bool> no_display; +}; + +struct WindowIds { + base::Optional<std::string> app_id; + base::Optional<std::string> startup_id; +}; + +std::string GenAppId(const App& app) { + return CrostiniTestHelper::GenerateAppId(app.desktop_file_id, app.vm_name, + app.container_name); +} + +} // namespace + +class CrostiniShelfUtilsTest : public testing::Test { + public: + std::string GetShelfAppId(WindowIds window_ids) const { + return GetCrostiniShelfAppId( + &testing_profile_, base::OptionalOrNullptr(window_ids.app_id), + base::OptionalOrNullptr(window_ids.startup_id)); + } + + void SetGuestOsRegistry(std::vector<App> apps) { + using AppLists = std::map<std::pair<std::string, std::string>, + vm_tools::apps::ApplicationList>; + AppLists app_lists; + for (App& in_app : apps) { + AppLists::key_type key(std::move(in_app.vm_name), + std::move(in_app.container_name)); + AppLists::iterator app_list_it = app_lists.find(key); + if (app_list_it == app_lists.cend()) { + vm_tools::apps::ApplicationList app_list; + app_list.set_vm_name(key.first); + app_list.set_container_name(key.second); + app_list_it = app_lists.emplace_hint(app_list_it, std::move(key), + std::move(app_list)); + } + vm_tools::apps::App& out_app = *app_list_it->second.add_apps(); + out_app.set_desktop_file_id(std::move(in_app.desktop_file_id)); + out_app.mutable_name()->add_values()->set_value( + std::move(in_app.app_name)); + if (in_app.startup_wm_class) + out_app.set_startup_wm_class(std::move(*in_app.startup_wm_class)); + if (in_app.startup_notify) + out_app.set_startup_notify(*in_app.startup_notify); + if (in_app.no_display) + out_app.set_no_display(*in_app.no_display); + } + CrostiniRegistryService service(&testing_profile_); + for (AppLists::value_type& value : app_lists) { + service.UpdateApplicationList(std::move(value.second)); + } + } + + private: + content::BrowserTaskEnvironment task_environment_; + TestingProfile testing_profile_; +}; + +TEST_F(CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdReturnsEmptyIdWhenCalledWithoutAnyParametersSet) { + SetGuestOsRegistry({}); + + EXPECT_EQ(GetShelfAppId(WindowIds()), ""); +} + +TEST_F(CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdFindsAppWithEitherWindowIdOrAppId) { + SetGuestOsRegistry({ + {.desktop_file_id = "cool.app"}, + }); + + // App is found using wm app_id. + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.cool.app"}), + GenAppId({.desktop_file_id = "cool.app"})); + + // App is found using app_id. + EXPECT_EQ(GetShelfAppId({.app_id = "cool.app"}), + GenAppId({.desktop_file_id = "cool.app"})); +} + +TEST_F(CrostiniShelfUtilsTest, GetCrostiniShelfAppIdIgnoresWindowAppIdsCase) { + SetGuestOsRegistry({ + {.desktop_file_id = "app"}, + }); + + // App is found using capitalized App. + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.App"}), + GenAppId({.desktop_file_id = "app"})); +} + +TEST_F( + CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdCantFindAppWhenMultipleAppsInDifferentVmsShareDesktopFileIds) { + SetGuestOsRegistry({ + {.desktop_file_id = "super"}, + {.desktop_file_id = "super", .vm_name = "vm 2"}, + }); + + // Neither app is found, as they can't be disambiguated. + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.super"}), + "crostini:org.chromium.termina.wmclass.super"); +} + +TEST_F(CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdDoesntFindAppWhenGivenUnregisteredAppIds) { + SetGuestOsRegistry({}); + + EXPECT_EQ( + GetShelfAppId({.app_id = "org.chromium.termina.wmclientleader.1234"}), + "crostini:org.chromium.termina.wmclientleader.1234"); + + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.xid.654321"}), + "crostini:org.chromium.termina.xid.654321"); + + EXPECT_EQ(GetShelfAppId({.app_id = "fancy.app"}), "crostini:fancy.app"); +} + +TEST_F(CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdCanFindAppUsingItsStartupWmClass) { + SetGuestOsRegistry({ + {.desktop_file_id = "app", .startup_wm_class = "app_start"}, + }); + + // App is found using it's startup_wm_class. + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.app_start"}), + GenAppId({.desktop_file_id = "app"})); +} + +TEST_F( + CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdCantFindAppIfMultipleAppsStartupWmClassesAreTheSame) { + SetGuestOsRegistry({ + {.desktop_file_id = "app2", .startup_wm_class = "app2"}, + {.desktop_file_id = "app3", .startup_wm_class = "app2"}, + }); + + // Neither app is found, as they can't be disambiguated. + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.app2"}), + "crostini:org.chromium.termina.wmclass.app2"); +} + +TEST_F(CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdCanFindAppUsingStartupIdIfStartupNotifyIsTrue) { + SetGuestOsRegistry({ + {.desktop_file_id = "app", .startup_notify = true}, + {.desktop_file_id = "app2", .startup_notify = false}, + }); + + // App's startup_notify is true, so it can be found using startup_id. + EXPECT_EQ(GetShelfAppId({.startup_id = "app"}), + GenAppId({.desktop_file_id = "app"})); + + // App's startup_notify is true, so it can be found using startup_id, even if + // app_id is set. + EXPECT_EQ(GetShelfAppId({.app_id = "unknown_app_id", .startup_id = "app"}), + GenAppId({.desktop_file_id = "app"})); + + // App's startup_notify is false, so startup_id is ignored and no app was + // found. + EXPECT_EQ(GetShelfAppId({.app_id = "unknown_app_id", .startup_id = "app2"}), + "crostini:unknown_app_id"); +} + +TEST_F(CrostiniShelfUtilsTest, GetCrostiniShelfAppIdCanFindAppsByName) { + SetGuestOsRegistry({ + {.desktop_file_id = "app", .app_name = "name"}, + }); + + // App found by app_name: "name". + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.name"}), + GenAppId({.desktop_file_id = "app"})); +} + +TEST_F(CrostiniShelfUtilsTest, + GetCrostiniShelfAppIdDoesntFindAppsByNameIfTheyHaveNoDisplaySet) { + // One no_display app. + SetGuestOsRegistry({ + {.desktop_file_id = "another_app", + .app_name = "name", + .no_display = true}, + }); + + // No app is found. + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.name"}), + "crostini:org.chromium.termina.wmclass.name"); + + // Two apps with the same name, where one is no_display. + SetGuestOsRegistry({ + {.desktop_file_id = "app", .app_name = "name"}, + {.desktop_file_id = "another_app", + .app_name = "name", + .no_display = true}, + }); + + // The app without no_display set is found. + EXPECT_EQ(GetShelfAppId({.app_id = "org.chromium.termina.wmclass.name"}), + GenAppId({.desktop_file_id = "app"})); +} + +} // namespace crostini
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc index 0bbc42b..2aa689d 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
@@ -19,7 +19,6 @@ #include "build/build_config.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.h" -#include "chrome/browser/chromeos/login/login_manager_test.h" #include "chrome/browser/chromeos/login/mock_network_state_helper.h" #include "chrome/browser/chromeos/login/oobe_screen.h" #include "chrome/browser/chromeos/login/screens/demo_setup_screen.h" @@ -27,6 +26,7 @@ #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/test/enrollment_helper_mixin.h" #include "chrome/browser/chromeos/login/test/js_checker.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" #include "chrome/browser/chromeos/login/test/test_condition_waiter.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" @@ -139,22 +139,13 @@ } // namespace // Basic tests for demo mode setup flow. -class DemoSetupTest : public LoginManagerTest { +class DemoSetupTestBase : public OobeBaseTest { public: - DemoSetupTest() - : LoginManagerTest(false, true /* should_initialize_webui */) {} - ~DemoSetupTest() override = default; - - // LoginTestManager: - void SetUpCommandLine(base::CommandLine* command_line) override { - LoginManagerTest::SetUpCommandLine(command_line); - command_line->AppendSwitchASCII(switches::kArcAvailability, - "officially-supported"); - ASSERT_TRUE(arc::IsArcAvailable()); - } + DemoSetupTestBase() = default; + ~DemoSetupTestBase() override = default; void SetUpOnMainThread() override { - LoginManagerTest::SetUpOnMainThread(); + OobeBaseTest::SetUpOnMainThread(); DisableConfirmationDialogAnimations(); branded_build_override_ = WizardController::ForceBrandedBuildForTesting(); DisconnectAllNetworks(); @@ -466,10 +457,25 @@ policy::MockCloudPolicyStore mock_policy_store_; std::unique_ptr<base::AutoReset<bool>> branded_build_override_; - DISALLOW_COPY_AND_ASSIGN(DemoSetupTest); + DISALLOW_COPY_AND_ASSIGN(DemoSetupTestBase); }; -IN_PROC_BROWSER_TEST_F(DemoSetupTest, ShowConfirmationDialogAndProceed) { +class DemoSetupArcSupportedTest : public DemoSetupTestBase { + public: + DemoSetupArcSupportedTest() = default; + ~DemoSetupArcSupportedTest() override = default; + + // DemoSetupTestBase: + void SetUpCommandLine(base::CommandLine* command_line) override { + DemoSetupTestBase::SetUpCommandLine(command_line); + command_line->AppendSwitchASCII(switches::kArcAvailability, + "officially-supported"); + ASSERT_TRUE(arc::IsArcAvailable()); + } +}; + +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + ShowConfirmationDialogAndProceed) { EXPECT_FALSE(IsConfirmationDialogShown()); InvokeDemoModeWithAccelerator(); @@ -481,14 +487,8 @@ EXPECT_TRUE(IsScreenShown(DemoPreferencesScreenView::kScreenId)); } -#if defined(OS_CHROMEOS) -// Flaky on ChromeOS. crbug.com/895120 -#define MAYBE_ShowConfirmationDialogAndCancel \ - DISABLED_ShowConfirmationDialogAndCancel -#else -#define MAYBE_ShowConfirmationDialogAndCancel ShowConfirmationDialogAndCancel -#endif -IN_PROC_BROWSER_TEST_F(DemoSetupTest, MAYBE_ShowConfirmationDialogAndCancel) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + ShowConfirmationDialogAndCancel) { EXPECT_FALSE(IsConfirmationDialogShown()); InvokeDemoModeWithAccelerator(); @@ -500,7 +500,7 @@ EXPECT_FALSE(IsScreenShown(DemoPreferencesScreenView::kScreenId)); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, InvokeWithTaps) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, InvokeWithTaps) { // Use fake time to avoid flakiness. SetFakeTimeForMultiTapDetector(base::Time::UnixEpoch()); EXPECT_FALSE(IsConfirmationDialogShown()); @@ -509,7 +509,8 @@ EXPECT_TRUE(IsConfirmationDialogShown()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, DoNotInvokeWithNonConsecutiveTaps) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + DoNotInvokeWithNonConsecutiveTaps) { // Use fake time to avoid flakiness. const base::Time kFakeTime = base::Time::UnixEpoch(); SetFakeTimeForMultiTapDetector(kFakeTime); @@ -527,7 +528,7 @@ EXPECT_FALSE(IsConfirmationDialogShown()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowSuccess) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, OnlineSetupFlowSuccess) { // Simulate successful online setup. enrollment_helper_.ExpectEnrollmentMode( policy::EnrollmentConfig::MODE_ATTESTATION); @@ -584,7 +585,7 @@ EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, OnlineSetupFlowSuccessWithCountryCustomization) { // Simulate successful online setup. enrollment_helper_.ExpectEnrollmentMode( @@ -674,7 +675,7 @@ EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowErrorDefault) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, OnlineSetupFlowErrorDefault) { // Simulate online setup failure. enrollment_helper_.ExpectEnrollmentMode( policy::EnrollmentConfig::MODE_ATTESTATION); @@ -738,7 +739,8 @@ EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowErrorPowerwashRequired) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + OnlineSetupFlowErrorPowerwashRequired) { // Simulate online setup failure that requires powerwash. enrollment_helper_.ExpectEnrollmentMode( policy::EnrollmentConfig::MODE_ATTESTATION); @@ -801,7 +803,8 @@ EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OnlineSetupFlowCrosComponentFailure) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + OnlineSetupFlowCrosComponentFailure) { // Simulate failure to load demo resources CrOS component. // There is no enrollment attempt, as process fails earlier. enrollment_helper_.ExpectNoEnrollment(); @@ -858,7 +861,7 @@ EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OfflineDemoModeUnavailable) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, OfflineDemoModeUnavailable) { SimulateNetworkDisconnected(); InvokeDemoModeWithAccelerator(); @@ -881,7 +884,7 @@ EXPECT_FALSE(IsCustomNetworkListElementShown("offlineDemoSetupListItemName")); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OfflineSetupFlowSuccess) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, OfflineSetupFlowSuccess) { // Simulate offline setup success. enrollment_helper_.ExpectOfflineEnrollmentSuccess(); SimulateNetworkDisconnected(); @@ -938,7 +941,8 @@ EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OfflineSetupFlowErrorDefault) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + OfflineSetupFlowErrorDefault) { // Simulate offline setup failure. enrollment_helper_.ExpectOfflineEnrollmentError( policy::EnrollmentStatus::ForStatus( @@ -1003,7 +1007,8 @@ EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, OfflineSetupFlowErrorPowerwashRequired) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + OfflineSetupFlowErrorPowerwashRequired) { // Simulate offline setup failure. enrollment_helper_.ExpectOfflineEnrollmentError( policy::EnrollmentStatus::ForLockError( @@ -1067,7 +1072,7 @@ EXPECT_FALSE(StartupUtils::IsDeviceRegistered()); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, NextDisabledOnNetworkScreen) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, NextDisabledOnNetworkScreen) { SimulateNetworkDisconnected(); SkipToScreen(NetworkScreenView::kScreenId); EXPECT_FALSE(IsScreenDialogElementEnabled(NetworkScreenView::kScreenId, @@ -1081,7 +1086,7 @@ EXPECT_TRUE(IsScreenShown(NetworkScreenView::kScreenId)); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, ClickNetworkOnNetworkScreen) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, ClickNetworkOnNetworkScreen) { SkipToScreen(NetworkScreenView::kScreenId); EXPECT_FALSE(IsScreenDialogElementEnabled(NetworkScreenView::kScreenId, DemoSetupDialog::kNetwork, @@ -1094,7 +1099,8 @@ EXPECT_TRUE(IsScreenShown(EulaView::kScreenId)); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, ClickConnectedNetworkOnNetworkScreen) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + ClickConnectedNetworkOnNetworkScreen) { SimulateNetworkConnected(); SkipToScreen(NetworkScreenView::kScreenId); EXPECT_TRUE(IsScreenDialogElementEnabled(NetworkScreenView::kScreenId, @@ -1107,7 +1113,7 @@ EXPECT_TRUE(IsScreenShown(EulaView::kScreenId)); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, BackOnNetworkScreen) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, BackOnNetworkScreen) { SimulateNetworkConnected(); SkipToScreen(NetworkScreenView::kScreenId); @@ -1118,7 +1124,7 @@ EXPECT_TRUE(IsScreenShown(DemoPreferencesScreenView::kScreenId)); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, BackOnArcTermsScreen) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, BackOnArcTermsScreen) { // User cannot go to ARC ToS screen without accepting eula - simulate that. StartupUtils::MarkEulaAccepted(); @@ -1130,7 +1136,7 @@ OobeScreenWaiter(NetworkScreenView::kScreenId).Wait(); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, BackOnErrorScreen) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, BackOnErrorScreen) { SkipToErrorDialog(); ClickScreenDialogButton(DemoSetupScreenView::kScreenId, @@ -1140,7 +1146,7 @@ OobeScreenWaiter(WelcomeView::kScreenId).Wait(); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, RetryOnErrorScreen) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, RetryOnErrorScreen) { SkipToErrorDialog(); // We need to create another mock after showing error dialog. @@ -1157,7 +1163,8 @@ OobeScreenWaiter(GaiaView::kScreenId).Wait(); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, ShowOfflineSetupOptionOnNetworkList) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + ShowOfflineSetupOptionOnNetworkList) { auto* const wizard_controller = WizardController::default_controller(); wizard_controller->SimulateDemoModeSetupForTesting(); SimulateOfflineEnvironment(); @@ -1166,19 +1173,20 @@ EXPECT_TRUE(IsCustomNetworkListElementShown("offlineDemoSetupListItemName")); } -IN_PROC_BROWSER_TEST_F(DemoSetupTest, NoOfflineSetupOptionOnNetworkList) { +IN_PROC_BROWSER_TEST_F(DemoSetupArcSupportedTest, + NoOfflineSetupOptionOnNetworkList) { SkipToScreen(NetworkScreenView::kScreenId); EXPECT_FALSE(IsCustomNetworkListElementShown("offlineDemoSetupListItemName")); } -class DemoSetupArcUnsupportedTest : public DemoSetupTest { +class DemoSetupArcUnsupportedTest : public DemoSetupTestBase { public: DemoSetupArcUnsupportedTest() = default; ~DemoSetupArcUnsupportedTest() override = default; - // DemoSetupTest: + // DemoSetupTestBase: void SetUpCommandLine(base::CommandLine* command_line) override { - LoginManagerTest::SetUpCommandLine(command_line); + DemoSetupTestBase::SetUpCommandLine(command_line); command_line->AppendSwitchASCII(switches::kArcAvailability, "none"); ASSERT_FALSE(arc::IsArcAvailable()); } @@ -1204,7 +1212,7 @@ } // Demo setup tests related to Force Re-Enrollment. -class DemoSetupFRETest : public DemoSetupTest { +class DemoSetupFRETest : public DemoSetupArcSupportedTest { protected: DemoSetupFRETest() { statistics_provider_.SetMachineStatistic(system::kSerialNumberKeyForTest, @@ -1212,10 +1220,8 @@ } ~DemoSetupFRETest() override = default; - void SetUpOnMainThread() override { DemoSetupTest::SetUpOnMainThread(); } - void SetUpCommandLine(base::CommandLine* command_line) override { - DemoSetupTest::SetUpCommandLine(command_line); + DemoSetupArcSupportedTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII( switches::kEnterpriseEnableForcedReEnrollment,
diff --git a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc index 5abc8017..c0822a5 100644 --- a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc +++ b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
@@ -13,9 +13,9 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/login/login_manager_test.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/test/js_checker.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/chromeos/login/ui/webui_login_view.h" @@ -150,21 +150,18 @@ int num_remove_protection_; }; -class EnableDebuggingTest : public LoginManagerTest { +class EnableDebuggingTestBase : public OobeBaseTest { public: - EnableDebuggingTest() - : LoginManagerTest(false, true /* should_initialize_webui */) {} - ~EnableDebuggingTest() override {} + EnableDebuggingTestBase() = default; + ~EnableDebuggingTestBase() override = default; + // OobeBaseTest: void SetUpCommandLine(base::CommandLine* command_line) override { - LoginManagerTest::SetUpCommandLine(command_line); - command_line->AppendSwitch(chromeos::switches::kSystemDevMode); + OobeBaseTest::SetUpCommandLine(command_line); // Disable HID detection because it takes precedence and could block // enable-debugging UI. command_line->AppendSwitch(chromeos::switches::kDisableHIDDetectionOnOOBE); } - - // LoginManagerTest overrides: void SetUpInProcessBrowserTestFixture() override { std::unique_ptr<DBusThreadManagerSetter> dbus_setter = chromeos::DBusThreadManager::GetSetterForTesting(); @@ -172,20 +169,7 @@ dbus_setter->SetDebugDaemonClient( std::unique_ptr<DebugDaemonClient>(debug_daemon_client_)); - LoginManagerTest::SetUpInProcessBrowserTestFixture(); - } - - void WaitUntilJSIsReady() { - LoginDisplayHost* host = LoginDisplayHost::default_host(); - if (!host) - return; - chromeos::OobeUI* oobe_ui = host->GetOobeUI(); - if (!oobe_ui) - return; - base::RunLoop run_loop; - const bool oobe_ui_ready = oobe_ui->IsJSReady(run_loop.QuitClosure()); - if (!oobe_ui_ready) - run_loop.Run(); + OobeBaseTest::SetUpInProcessBrowserTestFixture(); } void InvokeEnableDebuggingScreen() { @@ -224,7 +208,7 @@ void ShowRemoveProtectionScreen() { debug_daemon_client_->SetDebuggingFeaturesStatus( DebugDaemonClient::DEV_FEATURE_NONE); - WaitUntilJSIsReady(); + OobeBaseTest::WaitForOobeUI(); test::OobeJS().ExpectHidden("debugging"); InvokeEnableDebuggingScreen(); test::OobeJS().ExpectVisible("debugging"); @@ -245,7 +229,7 @@ void ShowSetupScreen() { debug_daemon_client_->SetDebuggingFeaturesStatus( debugd::DevFeatureFlag::DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED); - WaitUntilJSIsReady(); + OobeBaseTest::WaitForOobeUI(); test::OobeJS().ExpectHidden("debugging"); InvokeEnableDebuggingScreen(); test::OobeJS().ExpectVisible("debugging"); @@ -266,11 +250,23 @@ TestDebugDaemonClient* debug_daemon_client_ = nullptr; private: - DISALLOW_COPY_AND_ASSIGN(EnableDebuggingTest); + DISALLOW_COPY_AND_ASSIGN(EnableDebuggingTestBase); +}; + +class EnableDebuggingDevTest : public EnableDebuggingTestBase { + public: + EnableDebuggingDevTest() = default; + ~EnableDebuggingDevTest() override = default; + + // EnableDebuggingTestBase: + void SetUpCommandLine(base::CommandLine* command_line) override { + EnableDebuggingTestBase::SetUpCommandLine(command_line); + command_line->AppendSwitch(chromeos::switches::kSystemDevMode); + } }; // Show remove protection screen, click on [Cancel] button. -IN_PROC_BROWSER_TEST_F(EnableDebuggingTest, ShowAndCancelRemoveProtection) { +IN_PROC_BROWSER_TEST_F(EnableDebuggingDevTest, ShowAndCancelRemoveProtection) { ShowRemoveProtectionScreen(); CloseEnableDebuggingScreen(); test::OobeJS().ExpectHidden("debugging"); @@ -282,7 +278,7 @@ // Show remove protection, click on [Remove protection] button and wait for // reboot. -IN_PROC_BROWSER_TEST_F(EnableDebuggingTest, ShowAndRemoveProtection) { +IN_PROC_BROWSER_TEST_F(EnableDebuggingDevTest, ShowAndRemoveProtection) { ShowRemoveProtectionScreen(); debug_daemon_client_->ResetWait(); ClickRemoveProtectionButton(); @@ -297,7 +293,7 @@ } // Show setup screen. Click on [Enable] button. Wait until done screen is shown. -IN_PROC_BROWSER_TEST_F(EnableDebuggingTest, ShowSetup) { +IN_PROC_BROWSER_TEST_F(EnableDebuggingDevTest, ShowSetup) { ShowSetupScreen(); debug_daemon_client_->ResetWait(); ClickEnableButton(); @@ -309,7 +305,7 @@ // Show setup screen. Type in matching passwords. // Click on [Enable] button. Wait until done screen is shown. -IN_PROC_BROWSER_TEST_F(EnableDebuggingTest, SetupMatchingPasswords) { +IN_PROC_BROWSER_TEST_F(EnableDebuggingDevTest, SetupMatchingPasswords) { ShowSetupScreen(); debug_daemon_client_->ResetWait(); test::OobeJS().TypeIntoPath("test0000", {"enable-debugging-password"}); @@ -325,7 +321,7 @@ // Show setup screen. Type in different passwords. // Click on [Enable] button. Assert done screen is not shown. // Then confirm that typing in matching passwords enables debugging features. -IN_PROC_BROWSER_TEST_F(EnableDebuggingTest, SetupNotMatchingPasswords) { +IN_PROC_BROWSER_TEST_F(EnableDebuggingDevTest, SetupNotMatchingPasswords) { ShowSetupScreen(); debug_daemon_client_->ResetWait(); test::OobeJS().TypeIntoPath("test0000", {"enable-debugging-password"}); @@ -349,11 +345,11 @@ // Test images come with some features enabled but still has rootfs protection. // Invoking debug screen should show remove protection screen. -IN_PROC_BROWSER_TEST_F(EnableDebuggingTest, ShowOnTestImages) { +IN_PROC_BROWSER_TEST_F(EnableDebuggingDevTest, ShowOnTestImages) { debug_daemon_client_->SetDebuggingFeaturesStatus( debugd::DevFeatureFlag::DEV_FEATURE_SSH_SERVER_CONFIGURED | debugd::DevFeatureFlag::DEV_FEATURE_SYSTEM_ROOT_PASSWORD_SET); - WaitUntilJSIsReady(); + OobeBaseTest::WaitForOobeUI(); test::OobeJS().ExpectHidden("debugging"); InvokeEnableDebuggingScreen(); test::OobeJS().ExpectVisible("debugging"); @@ -366,12 +362,12 @@ EXPECT_EQ(debug_daemon_client_->num_remove_protection(), 0); } -IN_PROC_BROWSER_TEST_F(EnableDebuggingTest, WaitForDebugDaemon) { +IN_PROC_BROWSER_TEST_F(EnableDebuggingDevTest, WaitForDebugDaemon) { // Stat with service not ready. debug_daemon_client_->SetServiceIsAvailable(false); debug_daemon_client_->SetDebuggingFeaturesStatus( DebugDaemonClient::DEV_FEATURE_NONE); - WaitUntilJSIsReady(); + OobeBaseTest::WaitForOobeUI(); // Invoking UI and it should land on wait-view. test::OobeJS().ExpectHidden("debugging"); @@ -386,22 +382,16 @@ VerifyRemoveProtectionScreen(); } -class EnableDebuggingNonDevTest : public EnableDebuggingTest { +class EnableDebuggingNonDevTest : public EnableDebuggingTestBase { public: - EnableDebuggingNonDevTest() {} + EnableDebuggingNonDevTest() = default; - void SetUpCommandLine(base::CommandLine* command_line) override { - // Skip EnableDebuggingTest::SetUpCommandLine(). - LoginManagerTest::SetUpCommandLine(command_line); - } - - // LoginManagerTest overrides: void SetUpInProcessBrowserTestFixture() override { std::unique_ptr<DBusThreadManagerSetter> dbus_setter = chromeos::DBusThreadManager::GetSetterForTesting(); dbus_setter->SetDebugDaemonClient( std::unique_ptr<DebugDaemonClient>(new FakeDebugDaemonClient)); - LoginManagerTest::SetUpInProcessBrowserTestFixture(); + EnableDebuggingTestBase::SetUpInProcessBrowserTestFixture(); } }; @@ -419,11 +409,11 @@ test::OobeJS().ExpectHasNoClass("wait-view", {"debugging"}); } -class EnableDebuggingRequestedTest : public EnableDebuggingTest { +class EnableDebuggingRequestedTest : public EnableDebuggingDevTest { public: EnableDebuggingRequestedTest() {} - // EnableDebuggingTest overrides: + // EnableDebuggingDevTest overrides: bool SetUpUserDataDirectory() override { base::DictionaryValue local_state_dict; local_state_dict.SetBoolean(prefs::kDebuggingFeaturesRequested, true); @@ -435,10 +425,10 @@ CHECK( JSONFileValueSerializer(local_state_path).Serialize(local_state_dict)); - return EnableDebuggingTest::SetUpUserDataDirectory(); + return EnableDebuggingDevTest::SetUpUserDataDirectory(); } void SetUpInProcessBrowserTestFixture() override { - EnableDebuggingTest::SetUpInProcessBrowserTestFixture(); + EnableDebuggingDevTest::SetUpInProcessBrowserTestFixture(); debug_daemon_client_->SetDebuggingFeaturesStatus( debugd::DevFeatureFlag::DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED);
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc index 526fa7e..c7945741 100644 --- a/chrome/browser/chromeos/login/reset_browsertest.cc +++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -54,40 +54,42 @@ constexpr char kTpmUpdate[] = "tpmFirmwareUpdate"; constexpr char kTpmUpdateCheckbox[] = "tpmFirmwareUpdateCheckbox"; +constexpr char kCancelDialogButton[] = "resetCancel"; +constexpr char kTriggerPowerwashButton[] = "powerwash"; +constexpr char kConfirmPowerwashButton[] = "confirmPowerwash"; +constexpr char kCancelPowerwashButton[] = "cancelButton"; +constexpr char kRestartButton[] = "restart"; + void InvokeRollbackOption() { test::ExecuteOobeJS("cr.ui.Oobe.handleAccelerator('reset');"); } -void RequestCloseResetScreen() { - test::ExecuteOobeJS( - "chrome.send('login.ResetScreen.userActed', ['cancel-reset']);"); +void ClickCancelButton() { + test::OobeJS().TapOnPath({kResetScreen, kCancelDialogButton}); } -void CloseResetScreen() { - RequestCloseResetScreen(); +void CloseResetScreenAndWait() { + test::OobeJS().TapOnPath({kResetScreen, kCancelDialogButton}); OobeScreenExitWaiter(ResetView::kScreenId).Wait(); - EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); + test::OobeJS() + .CreateVisibilityWaiter(false /* visible */, {kResetScreen}) + ->Wait(); } void ClickResetButton() { - test::ExecuteOobeJS( - "chrome.send('login.ResetScreen.userActed', ['powerwash-pressed']);"); + test::OobeJS().TapOnPath({kResetScreen, kConfirmPowerwashButton}); } void ClickRestartButton() { - test::ExecuteOobeJS( - "chrome.send('login.ResetScreen.userActed', ['restart-pressed']);"); + test::OobeJS().TapOnPath({kResetScreen, kRestartButton}); } void ClickToConfirmButton() { - test::ExecuteOobeJS( - "chrome.send('login.ResetScreen.userActed', ['show-confirmation']);"); + test::OobeJS().TapOnPath({kResetScreen, kTriggerPowerwashButton}); } void ClickDismissConfirmationButton() { - test::ExecuteOobeJS( - "chrome.send('login.ResetScreen.userActed', " - "['reset-confirm-dismissed']);"); + test::OobeJS().TapOnPath({kResetScreen, kCancelPowerwashButton}); } void WaitForConfirmationDialogToOpen() { @@ -171,6 +173,9 @@ chromeos::LoginDisplayHost::default_host()->ShowResetScreen(); EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted()); OobeScreenWaiter(ResetView::kScreenId).Wait(); + test::OobeJS() + .CreateVisibilityWaiter(true /* visible */, {kResetScreen}) + ->Wait(); EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); ExpectConfirmationDialogClosed(); } @@ -199,7 +204,7 @@ // Simulates reset screen request from OOBE UI. void InvokeResetScreen() { - test::ExecuteOobeJS("cr.ui.Oobe.handleAccelerator('reset');"); + InvokeRollbackOption(); OobeScreenWaiter(ResetView::kScreenId).Wait(); EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); ExpectConfirmationDialogClosed(); @@ -295,7 +300,8 @@ IN_PROC_BROWSER_TEST_F(ResetTest, ShowAndCancel) { EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); InvokeResetScreen(); - CloseResetScreen(); + CloseResetScreenAndWait(); + EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); } IN_PROC_BROWSER_TEST_F(ResetTest, RestartBeforePowerwash) { @@ -330,9 +336,8 @@ EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); InvokeResetScreen(); - RequestCloseResetScreen(); + ClickCancelButton(); OobeScreenWaiter(WelcomeView::kScreenId).Wait(); - test::OobeJS().ExpectHidden(kResetScreen); EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls()); @@ -361,7 +366,8 @@ // Rollback unavailable. Show and cancel. update_engine_client_->set_can_rollback_check_result(false); InvokeResetScreen(); - CloseResetScreen(); + CloseResetScreenAndWait(); + EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); // Go to confirmation phase, cancel from there in 2 steps. prefs->SetBoolean(prefs::kFactoryResetRequested, true); @@ -375,7 +381,8 @@ test::OobeJS().ExpectVisible(kResetScreen); EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); - CloseResetScreen(); + CloseResetScreenAndWait(); + EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); // Rollback available. Show and cancel from confirmation screen. update_engine_client_->set_can_rollback_check_result(true); @@ -390,7 +397,8 @@ WaitForConfirmationDialogToClose(); test::OobeJS().ExpectVisible(kResetScreen); - CloseResetScreen(); + CloseResetScreenAndWait(); + EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); } IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTest, PRE_ShowAfterBootIfRequested) { @@ -405,7 +413,8 @@ test::OobeJS().CreateVisibilityWaiter(true, {kResetScreen})->Wait(); EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); - CloseResetScreen(); + CloseResetScreenAndWait(); + EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); } IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTest, PRE_RollbackUnavailable) { @@ -425,7 +434,7 @@ EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls()); EXPECT_EQ(1, FakeSessionManagerClient::Get()->start_device_wipe_call_count()); EXPECT_EQ(0, update_engine_client_->rollback_call_count()); - CloseResetScreen(); + CloseResetScreenAndWait(); // Next invocation leads to rollback view. PrefService* prefs = g_browser_process->local_state(); @@ -436,7 +445,7 @@ EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls()); EXPECT_EQ(2, FakeSessionManagerClient::Get()->start_device_wipe_call_count()); EXPECT_EQ(0, update_engine_client_->rollback_call_count()); - CloseResetScreen(); + CloseResetScreenAndWait(); } IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTestWithRollback, @@ -466,7 +475,7 @@ EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls()); EXPECT_EQ(1, FakeSessionManagerClient::Get()->start_device_wipe_call_count()); EXPECT_EQ(0, update_engine_client_->rollback_call_count()); - CloseResetScreen(); + CloseResetScreenAndWait(); // Next invocation leads to simple reset, not rollback view. prefs->SetBoolean(prefs::kFactoryResetRequested, true); @@ -475,14 +484,15 @@ EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); ClickDismissConfirmationButton(); EXPECT_FALSE(ash::LoginScreenTestApi::IsGuestButtonShown()); - CloseResetScreen(); + CloseResetScreenAndWait(); + EXPECT_TRUE(ash::LoginScreenTestApi::IsGuestButtonShown()); InvokeResetScreen(); ClickToConfirmButton(); ClickResetButton(); EXPECT_EQ(0, FakePowerManagerClient::Get()->num_request_restart_calls()); EXPECT_EQ(2, FakeSessionManagerClient::Get()->start_device_wipe_call_count()); EXPECT_EQ(0, update_engine_client_->rollback_call_count()); - CloseResetScreen(); + CloseResetScreenAndWait(); prefs->SetBoolean(prefs::kFactoryResetRequested, true); InvokeResetScreen(); @@ -557,7 +567,7 @@ .CreateHasClassWaiter(true, "rollback-proposal-view", {kResetScreen}) ->Wait(); - CloseResetScreen(); + CloseResetScreenAndWait(); InvokeResetScreen(); InvokeRollbackOption();
diff --git a/chrome/browser/chromeos/login/screens/packaged_license_screen.h b/chrome/browser/chromeos/login/screens/packaged_license_screen.h index 750900a..2465714 100644 --- a/chrome/browser/chromeos/login/screens/packaged_license_screen.h +++ b/chrome/browser/chromeos/login/screens/packaged_license_screen.h
@@ -32,6 +32,10 @@ PackagedLicenseScreen& operator=(const PackagedLicenseScreen&) = delete; ~PackagedLicenseScreen() override; + void set_exit_callback_for_testing(const ScreenExitCallback& exit_callback) { + exit_callback_ = exit_callback; + } + protected: // BaseScreen void ShowImpl() override;
diff --git a/chrome/browser/chromeos/login/screens/packaged_license_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/packaged_license_screen_browsertest.cc new file mode 100644 index 0000000..e4a07aa --- /dev/null +++ b/chrome/browser/chromeos/login/screens/packaged_license_screen_browsertest.cc
@@ -0,0 +1,87 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/screens/packaged_license_screen.h" + +#include "base/bind.h" +#include "base/run_loop.h" +#include "chrome/browser/chromeos/login/screen_manager.h" +#include "chrome/browser/chromeos/login/test/js_checker.h" +#include "chrome/browser/chromeos/login/test/oobe_base_test.h" +#include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "chrome/browser/chromeos/policy/enrollment_config.h" +#include "chrome/browser/ui/webui/chromeos/login/packaged_license_screen_handler.h" + +namespace chromeos { + +class PackagedLicenseScreenTest : public OobeBaseTest { + public: + PackagedLicenseScreenTest() {} + ~PackagedLicenseScreenTest() override = default; + + void SetUpOnMainThread() override { + PackagedLicenseScreen* screen = static_cast<PackagedLicenseScreen*>( + WizardController::default_controller()->screen_manager()->GetScreen( + PackagedLicenseView::kScreenId)); + screen->set_exit_callback_for_testing(base::BindRepeating( + &PackagedLicenseScreenTest::HandleScreenExit, base::Unretained(this))); + policy::EnrollmentConfig config; + config.is_license_packaged_with_device = true; + WizardController::default_controller() + ->set_prescribed_enrollment_config_for_testing(config); + + OobeBaseTest::SetUpOnMainThread(); + } + + void ShowPackagedLicenseScreen() { + WizardController::default_controller()->AdvanceToScreen( + PackagedLicenseView::kScreenId); + OobeScreenWaiter(PackagedLicenseView::kScreenId).Wait(); + } + + void WaitForScreenExit() { + if (screen_exited_) + return; + base::RunLoop run_loop; + screen_exit_callback_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + void CheckResult(PackagedLicenseScreen::Result result) { + EXPECT_EQ(result_, result); + } + + private: + void HandleScreenExit(PackagedLicenseScreen::Result result) { + screen_exited_ = true; + result_ = result; + if (screen_exit_callback_) + std::move(screen_exit_callback_).Run(); + } + + bool screen_exited_ = false; + PackagedLicenseScreen::Result result_; + base::RepeatingClosure screen_exit_callback_; +}; + +IN_PROC_BROWSER_TEST_F(PackagedLicenseScreenTest, DontEnroll) { + ShowPackagedLicenseScreen(); + + test::OobeJS().TapOnPath({"packaged-license", "dont-enroll-button"}); + + WaitForScreenExit(); + CheckResult(PackagedLicenseScreen::Result::DONT_ENROLL); +} + +IN_PROC_BROWSER_TEST_F(PackagedLicenseScreenTest, Enroll) { + ShowPackagedLicenseScreen(); + + test::OobeJS().TapOnPath({"packaged-license", "enroll-button"}); + + WaitForScreenExit(); + CheckResult(PackagedLicenseScreen::Result::ENROLL); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h index 114a522d..1be5a63 100644 --- a/chrome/browser/chromeos/login/wizard_controller.h +++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -142,6 +142,11 @@ !prescribed_enrollment_config_.should_enroll(); } + void set_prescribed_enrollment_config_for_testing( + policy::EnrollmentConfig config) { + prescribed_enrollment_config_ = config; + } + // Returns true if a given screen exists. bool HasScreen(OobeScreenId screen);
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc index 18ac7e1..83dfd53 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.cc
@@ -13,6 +13,7 @@ #include "base/files/scoped_file.h" #include "base/guid.h" #include "base/strings/string_util.h" +#include "base/system/sys_info.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_drive_image_download_service.h" @@ -35,6 +36,13 @@ namespace { +// Size to use for calculating progress when the actual size isn't available. +constexpr int64_t kDownloadSizeFallbackEstimate = 15LL * 1024 * 1024 * 1024; + +constexpr char kFailureReasonHistogram[] = "PluginVm.SetupFailureReason"; + +constexpr char kHomeDirectory[] = "/home"; + chromeos::ConciergeClient* GetConciergeClient() { return chromeos::DBusThreadManager::Get()->GetConciergeClient(); } @@ -75,7 +83,7 @@ << " another PluginVm image is currently being processed " << "in state " << GetStateName(state_) << ", " << GetInstallingStateName(installing_state_); - OnDownloadFailed(FailureReason::OPERATION_IN_PROGRESS); + InstallFailed(FailureReason::OPERATION_IN_PROGRESS); return; } // Defensive check preventing any download attempts when PluginVm is @@ -84,11 +92,31 @@ if (!IsPluginVmAllowedForProfile(profile_)) { LOG(ERROR) << "Download of PluginVm image cannot be started because " << "the user is not allowed to run PluginVm"; - OnDownloadFailed(FailureReason::NOT_ALLOWED); + InstallFailed(FailureReason::NOT_ALLOWED); return; } state_ = State::kInstalling; + installing_state_ = InstallingState::kCheckingDiskSpace; + progress_ = 0; + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace, + base::FilePath(kHomeDirectory)), + base::BindOnce(&PluginVmInstaller::OnAvailableDiskSpace, + weak_ptr_factory_.GetWeakPtr())); +} + +void PluginVmInstaller::Continue() { + if (state_ != State::kInstalling || + installing_state_ != InstallingState::kPausedLowDiskSpace) { + LOG(ERROR) << "Tried to continue installation in unexpected state " + << GetStateName(state_) << ", " + << GetInstallingStateName(installing_state_); + return; + } + StartDlcDownload(); } @@ -100,6 +128,10 @@ } state_ = State::kCancelling; switch (installing_state_) { + case InstallingState::kPausedLowDiskSpace: + CancelFinished(); + return; + case InstallingState::kCheckingDiskSpace: case InstallingState::kCheckingForExistingVm: case InstallingState::kDownloadingDlc: // These can't be cancelled, so we wait for completion. For DLC, we also @@ -116,6 +148,40 @@ } } +void PluginVmInstaller::OnAvailableDiskSpace(int64_t bytes) { + if (state_ == State::kCancelling) { + CancelFinished(); + return; + } + + if (free_disk_space_for_testing_ != -1) + bytes = free_disk_space_for_testing_; + + // We allow the installer to fail for users who already set up a VM via vmc + // and have low disk space as it's simpler to check for existing VMs after + // installing DLC and this case should be very rare. + + if (bytes < kMinimumFreeDiskSpace) { + InstallFailed(FailureReason::INSUFFICIENT_DISK_SPACE); + return; + } + + if (bytes < kRecommendedFreeDiskSpace) { + // If there's no observer, we would get stuck in the paused state. + if (!observer_) { + InstallFinished(); + return; + } + observer_->OnCheckedDiskSpace(/*low_disk_space=*/true); + installing_state_ = InstallingState::kPausedLowDiskSpace; + return; + } + + if (observer_) + observer_->OnCheckedDiskSpace(/*low_disk_space=*/false); + StartDlcDownload(); +} + void PluginVmInstaller::OnUpdateVmState(bool default_vm_exists) { if (state_ == State::kCancelling) { CancelFinished(); @@ -139,19 +205,17 @@ void PluginVmInstaller::OnUpdateVmStateFailed() { // Either the dispatcher failed to start or ListVms didn't work. // PluginVmManager logs the details. - OnDownloadFailed(FailureReason::DISPATCHER_NOT_AVAILABLE); + InstallFailed(FailureReason::DISPATCHER_NOT_AVAILABLE); } void PluginVmInstaller::StartDlcDownload() { installing_state_ = InstallingState::kDownloadingDlc; if (!GetPluginVmImageDownloadUrl().is_valid()) { - OnDownloadFailed(FailureReason::INVALID_IMAGE_URL); + InstallFailed(FailureReason::INVALID_IMAGE_URL); return; } - dlc_download_start_tick_ = base::TimeTicks::Now(); - chromeos::DlcserviceClient::Get()->Install( GetPluginVmDlcModuleList(), base::BindOnce(&PluginVmInstaller::OnDlcDownloadCompleted, @@ -163,11 +227,12 @@ void PluginVmInstaller::StartDownload() { DCHECK_EQ(installing_state_, InstallingState::kDownloadingDlc); installing_state_ = InstallingState::kDownloadingImage; + UpdateProgress(/*state_progress=*/0); GURL url = GetPluginVmImageDownloadUrl(); // This may have changed since running StartDlcDownload. if (!url.is_valid()) { - OnDownloadFailed(FailureReason::INVALID_IMAGE_URL); + InstallFailed(FailureReason::INVALID_IMAGE_URL); return; } @@ -203,9 +268,7 @@ if (state_ == State::kCancelling) return; - if (observer_) - observer_->OnDlcDownloadProgressUpdated( - progress, base::TimeTicks::Now() - dlc_download_start_tick_); + UpdateProgress(progress); } void PluginVmInstaller::OnDlcDownloadCompleted( @@ -258,22 +321,23 @@ } RecordPluginVmDlcUseResultHistogram(result); - if (observer_) - observer_->OnDownloadFailed(reason); - InstallFinished(); + InstallFailed(reason); } void PluginVmInstaller::OnDownloadStarted() { - download_start_tick_ = base::TimeTicks::Now(); } void PluginVmInstaller::OnDownloadProgressUpdated(uint64_t bytes_downloaded, int64_t content_length) { - if (observer_) { - observer_->OnDownloadProgressUpdated( - bytes_downloaded, content_length, - base::TimeTicks::Now() - download_start_tick_); - } + DCHECK_EQ(installing_state_, InstallingState::kDownloadingImage); + if (observer_) + observer_->OnDownloadProgressUpdated(bytes_downloaded, content_length); + + if (content_length <= 0) + content_length = kDownloadSizeFallbackEstimate; + + UpdateProgress( + std::min(1., static_cast<double>(bytes_downloaded) / content_length)); } void PluginVmInstaller::OnDownloadCompleted( @@ -318,14 +382,13 @@ using_drive_download_service_ = false; } - if (observer_) - observer_->OnDownloadFailed(reason); - InstallFinished(); + InstallFailed(reason); } void PluginVmInstaller::StartImport() { DCHECK_EQ(installing_state_, InstallingState::kDownloadingImage); installing_state_ = InstallingState::kImporting; + UpdateProgress(/*state_progress=*/0); base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, @@ -335,6 +398,49 @@ weak_ptr_factory_.GetWeakPtr())); } +void PluginVmInstaller::UpdateProgress(double state_progress) { + DCHECK_EQ(state_, State::kInstalling); + if (state_progress < 0 || state_progress > 1) { + LOG(ERROR) << "Unexpected progress value " << state_progress + << " in installing state " + << GetInstallingStateName(installing_state_); + return; + } + + double start_range = 0; + double end_range = 0; + switch (installing_state_) { + case InstallingState::kDownloadingDlc: + start_range = 0; + end_range = 0.01; + break; + case InstallingState::kDownloadingImage: + start_range = 0.01; + end_range = 0.45; + break; + case InstallingState::kImporting: + start_range = 0.45; + end_range = 1; + break; + default: + // Other states take a negligible amount of time so we don't send progress + // updates. + NOTREACHED(); + } + + double new_progress = + start_range + (end_range - start_range) * state_progress; + if (new_progress < progress_) { + LOG(ERROR) << "Progress went backwards from " << progress_ << " to " + << progress_; + return; + } + + progress_ = new_progress; + if (observer_) + observer_->OnProgressUpdated(new_progress); +} + void PluginVmInstaller::DetectImageType() { creating_new_vm_ = IsIsoImage(downloaded_image_); } @@ -455,7 +561,6 @@ } VLOG(1) << "Disk image creation/import is now in progress"; - import_start_tick_ = base::TimeTicks::Now(); current_import_command_uuid_ = response.command_uuid(); // Image in progress. Waiting for progress signals... // TODO(https://crbug.com/966398): think about adding a timeout here, @@ -479,10 +584,7 @@ RequestFinalStatus(); return; case vm_tools::concierge::DiskImageStatus::DISK_STATUS_IN_PROGRESS: - if (observer_) { - observer_->OnImportProgressUpdated( - percent_completed, base::TimeTicks::Now() - import_start_tick_); - } + UpdateProgress(percent_completed / 100.); return; default: LOG(ERROR) << "Disk image status signal has status: " << status @@ -534,11 +636,7 @@ LOG(ERROR) << "New VM creation failed"; else LOG(ERROR) << "Image import failed"; - if (observer_) { - observer_->OnImportFailed(*failure_reason); - } - - InstallFinished(); + InstallFailed(*failure_reason); return; } @@ -649,6 +747,10 @@ switch (state) { case InstallingState::kInactive: return "kInactive"; + case InstallingState::kCheckingDiskSpace: + return "kCheckingDiskSpace"; + case InstallingState::kPausedLowDiskSpace: + return "kPausedLowDiskSpace"; case InstallingState::kCheckingForExistingVm: return "kCheckingForExistingVm"; case InstallingState::kDownloadingDlc: @@ -752,6 +854,14 @@ observer_->OnCancelFinished(); } +void PluginVmInstaller::InstallFailed(FailureReason reason) { + state_ = State::kIdle; + installing_state_ = InstallingState::kInactive; + base::UmaHistogramEnumeration(kFailureReasonHistogram, reason); + if (observer_) + observer_->OnError(reason); +} + void PluginVmInstaller::InstallFinished() { state_ = State::kIdle; installing_state_ = InstallingState::kInactive;
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h index fc4e18d4..50f5373 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer.h
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/time/time.h" #include "chromeos/dbus/concierge/concierge_service.pb.h" #include "chromeos/dbus/concierge_client.h" #include "chromeos/dbus/dlcservice/dlcservice_client.h" @@ -39,8 +38,8 @@ class PluginVmInstaller : public KeyedService, public chromeos::ConciergeClient::DiskImageObserver { public: - // FailureReasons values can be shown to the user. Do not reorder or renumber - // these values without careful consideration. + // FailureReasons values are logged to UMA and shown to users. Do not change + // or re-use enum values. enum class FailureReason { // LOGIC_ERROR = 0, SIGNAL_NOT_CONNECTED = 1, @@ -65,38 +64,50 @@ DLC_BUSY = 20, DLC_NEED_REBOOT = 21, DLC_NEED_SPACE = 22, + INSUFFICIENT_DISK_SPACE = 23, + + kMaxValue = INSUFFICIENT_DISK_SPACE, }; enum class InstallingState { kInactive, + kCheckingDiskSpace, + kPausedLowDiskSpace, kDownloadingDlc, kCheckingForExistingVm, kDownloadingImage, kImporting, }; + static constexpr int64_t kMinimumFreeDiskSpace = 16LL * 1024 * 1024 * 1024; + static constexpr int64_t kRecommendedFreeDiskSpace = + 32LL * 1024 * 1024 * 1024; + // Observer class for the PluginVm image related events. + // TODO(timloh): Merge OnFooFailed functions as the failure reason is enough + // to distinguish where we failed. class Observer { public: virtual ~Observer() = default; - virtual void OnDlcDownloadProgressUpdated(double progress, - base::TimeDelta elapsed_time) = 0; + virtual void OnProgressUpdated(double fraction_complete) = 0; + + // If |low_disk_space| is true, the device doesn't have the recommended + // amount of free disk space and the install will pause until Continue() or + // Cancel() is called. + virtual void OnCheckedDiskSpace(bool low_disk_space) = 0; + virtual void OnDlcDownloadCompleted() = 0; // If |has_vm| is true, the install is done. virtual void OnExistingVmCheckCompleted(bool has_vm) = 0; virtual void OnDownloadProgressUpdated(uint64_t bytes_downloaded, - int64_t content_length, - base::TimeDelta elapsed_time) = 0; + int64_t content_length) = 0; virtual void OnDownloadCompleted() = 0; - virtual void OnDownloadFailed(FailureReason reason) = 0; - virtual void OnImportProgressUpdated(int percent_completed, - base::TimeDelta elapsed_time) = 0; virtual void OnCreated() = 0; virtual void OnImported() = 0; - virtual void OnImportFailed(FailureReason reason) = 0; + virtual void OnError(FailureReason reason) = 0; virtual void OnCancelFinished() = 0; }; @@ -108,6 +119,8 @@ // Start the installation. Progress updates will be sent to the observer. void Start(); + // Continue the installation if it was paused due to low disk space. + void Continue(); // Cancel the installation. void Cancel(); @@ -137,6 +150,9 @@ // Public for testing purposes. bool VerifyDownload(const std::string& downloaded_archive_hash); + void SetFreeDiskSpaceForTesting(int64_t bytes) { + free_disk_space_for_testing_ = bytes; + } void SetDownloadServiceForTesting( download::DownloadService* download_service); void SetDownloadedImageForTesting(const base::FilePath& downloaded_image); @@ -146,13 +162,16 @@ std::string GetCurrentDownloadGuidForTesting(); private: + void OnAvailableDiskSpace(int64_t bytes); + void StartDlcDownload(); void OnUpdateVmState(bool default_vm_exists); void OnUpdateVmStateFailed(); - void StartDlcDownload(); void StartDownload(); void DetectImageType(); void StartImport(); + void UpdateProgress(double state_progress); + // Cancels the download of PluginVm image finishing the image processing. // Downloaded PluginVm image archive is being deleted. void CancelDownload(); @@ -161,6 +180,7 @@ // Reset state and call observers. void CancelFinished(); + void InstallFailed(FailureReason reason); // Reset state, callers also need to call the appropriate observer functions. void InstallFinished(); @@ -182,12 +202,13 @@ // -1 when is not yet determined. int64_t downloaded_image_size_ = -1; bool creating_new_vm_ = false; - base::TimeTicks dlc_download_start_tick_; - base::TimeTicks download_start_tick_; - base::TimeTicks import_start_tick_; + double progress_ = 0; std::unique_ptr<PluginVmDriveImageDownloadService> drive_download_service_; bool using_drive_download_service_ = false; + // -1 indicates not set + int64_t free_disk_space_for_testing_ = -1; + ~PluginVmInstaller() override; // Get string representation of state for logging purposes.
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc index 2e2297b..5d58b98e 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_installer_unittest.cc
@@ -49,11 +49,16 @@ using ::base::test::RunClosure; using ::testing::_; +using ::testing::AnyNumber; using ::testing::AtLeast; +using ::testing::DoubleEq; using ::testing::Invoke; using ::testing::InvokeWithoutArgs; +using ::testing::Mock; using ::testing::StrictMock; +using FailureReason = PluginVmInstaller::FailureReason; + const char kProfileName[] = "p1"; const char kUrl[] = "http://example.com"; const char kDriveUrl[] = "https://drive.google.com/open?id=fakedriveid"; @@ -71,29 +76,22 @@ // File size set in test_download_service. const int kDownloadedPluginVmImageSizeInMb = 123456789u / (1024 * 1024); +constexpr char kFailureReasonHistogram[] = "PluginVm.SetupFailureReason"; + } // namespace class MockObserver : public PluginVmInstaller::Observer { public: + MOCK_METHOD1(OnProgressUpdated, void(double)); + MOCK_METHOD1(OnCheckedDiskSpace, void(bool)); MOCK_METHOD1(OnExistingVmCheckCompleted, void(bool)); - MOCK_METHOD2(OnDlcDownloadProgressUpdated, - void(double progress, base::TimeDelta elapsed_time)); MOCK_METHOD0(OnDlcDownloadCompleted, void()); - MOCK_METHOD1(OnDlcDownloadFailed, - void(plugin_vm::PluginVmInstaller::FailureReason)); - MOCK_METHOD3(OnDownloadProgressUpdated, - void(uint64_t bytes_downloaded, - int64_t content_length, - base::TimeDelta elapsed_time)); + MOCK_METHOD2(OnDownloadProgressUpdated, + void(uint64_t bytes_downloaded, int64_t content_length)); MOCK_METHOD0(OnDownloadCompleted, void()); - MOCK_METHOD1(OnDownloadFailed, - void(plugin_vm::PluginVmInstaller::FailureReason)); - MOCK_METHOD2(OnImportProgressUpdated, - void(int percent_completed, base::TimeDelta elapsed_time)); MOCK_METHOD0(OnCreated, void()); MOCK_METHOD0(OnImported, void()); - MOCK_METHOD1(OnImportFailed, - void(plugin_vm::PluginVmInstaller::FailureReason)); + MOCK_METHOD1(OnError, void(FailureReason)); MOCK_METHOD0(OnCancelFinished, void()); }; @@ -170,7 +168,9 @@ installer_ = PluginVmInstallerFactory::GetForProfile(profile_.get()); observer_ = std::make_unique<StrictMock<MockObserver>>(); installer_->SetObserver(observer_.get()); + installer_->SetFreeDiskSpaceForTesting(std::numeric_limits<int64_t>::max()); + SetDefaultExpectations(); // These actions are required to make the RunUntil* functions work, so tests // probably shouldn't override them. ON_CALL(*observer_, OnExistingVmCheckCompleted(false)) @@ -213,6 +213,11 @@ return zip_file_path; } + void VerifyExpectations() { + Mock::VerifyAndClearExpectations(observer_.get()); + SetDefaultExpectations(); + } + // Helper functions for starting and progressing the installer. void RunUntilDownloading() { @@ -280,6 +285,11 @@ std::move(download_completed_closure_).Run(); } + void SetDefaultExpectations() { + // Suppress progress updates. + EXPECT_CALL(*observer_, OnProgressUpdated(_)).Times(AnyNumber()); + } + base::ScopedTempDir profiles_dir_; DISALLOW_COPY_AND_ASSIGN(PluginVmInstallerTestBase); @@ -384,6 +394,64 @@ DISALLOW_COPY_AND_ASSIGN(PluginVmInstallerDriveTest); }; +TEST_F(PluginVmInstallerDownloadServiceTest, ProgressUpdates) { + SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); + + // Override default expectation so unexpected calls will fail the test. + EXPECT_CALL(*observer_, OnProgressUpdated(_)).Times(0); + + EXPECT_CALL(*observer_, OnProgressUpdated(DoubleEq(0.01))); + EXPECT_CALL(*observer_, OnProgressUpdated(DoubleEq(0.45))); + EXPECT_CALL(*observer_, OnProgressUpdated(DoubleEq(0.725))); + + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); + EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); + EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); + EXPECT_CALL(*observer_, OnDownloadCompleted()); + EXPECT_CALL(*observer_, OnImported()); + StartAndRunToCompletion(); +} + +TEST_F(PluginVmInstallerDownloadServiceTest, InsufficientDisk) { + installer_->SetFreeDiskSpaceForTesting( + PluginVmInstaller::kMinimumFreeDiskSpace - 1); + EXPECT_CALL(*observer_, OnError(FailureReason::INSUFFICIENT_DISK_SPACE)); + StartAndRunToCompletion(); + histogram_tester_->ExpectUniqueSample( + kFailureReasonHistogram, FailureReason::INSUFFICIENT_DISK_SPACE, 1); +} + +TEST_F(PluginVmInstallerDownloadServiceTest, LowDiskCancel) { + SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); + installer_->SetFreeDiskSpaceForTesting( + PluginVmInstaller::kMinimumFreeDiskSpace); + + EXPECT_CALL(*observer_, OnCheckedDiskSpace(/*low_disk_space=*/true)); + StartAndRunToCompletion(); + VerifyExpectations(); + + EXPECT_CALL(*observer_, OnCancelFinished()); + installer_->Cancel(); + task_environment_.RunUntilIdle(); +} + +TEST_F(PluginVmInstallerDownloadServiceTest, LowDiskContinue) { + SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); + installer_->SetFreeDiskSpaceForTesting( + PluginVmInstaller::kRecommendedFreeDiskSpace - 1); + + EXPECT_CALL(*observer_, OnCheckedDiskSpace(/*low_disk_space=*/true)); + StartAndRunToCompletion(); + VerifyExpectations(); + + EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); + EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); + EXPECT_CALL(*observer_, OnDownloadCompleted()); + EXPECT_CALL(*observer_, OnImported()); + installer_->Continue(); + task_environment_.RunUntilIdle(); +} + TEST_F(PluginVmInstallerDownloadServiceTest, VmExists) { vm_tools::plugin_dispatcher::ListVmResponse list_vms_response; list_vms_response.add_vm_info()->set_state( @@ -392,6 +460,7 @@ chromeos::DBusThreadManager::Get()->GetVmPluginDispatcherClient()) ->set_list_vms_response(list_vms_response); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(true)); StartAndRunToCompletion(); @@ -399,6 +468,7 @@ TEST_F(PluginVmInstallerDownloadServiceTest, CancelOnVmExistsCheck) { base::RunLoop run_loop; + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted) .WillOnce(RunClosure(run_loop.QuitClosure())); EXPECT_CALL(*observer_, OnCancelFinished()); @@ -412,10 +482,10 @@ TEST_F(PluginVmInstallerDownloadServiceTest, DownloadPluginVmImageParamsTest) { SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); EXPECT_CALL(*observer_, OnDownloadCompleted()); - EXPECT_CALL(*observer_, OnImportProgressUpdated(50.0, _)); EXPECT_CALL(*observer_, OnImported()); StartAndRunUntilDownloading(); @@ -435,10 +505,10 @@ TEST_F(PluginVmInstallerDownloadServiceTest, OnlyOneImageIsProcessedTest) { SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); EXPECT_CALL(*observer_, OnDownloadCompleted()); - EXPECT_CALL(*observer_, OnImportProgressUpdated(50.0, _)); EXPECT_CALL(*observer_, OnImported()); StartAndRunUntilDownloading(); @@ -461,10 +531,10 @@ CanProceedWithANewImageWhenSucceededTest) { SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)).Times(2); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()).Times(2); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)).Times(2); EXPECT_CALL(*observer_, OnDownloadCompleted()).Times(2); - EXPECT_CALL(*observer_, OnImportProgressUpdated(50.0, _)).Times(2); EXPECT_CALL(*observer_, OnImported()).Times(2); StartAndRunToCompletion(); @@ -483,13 +553,11 @@ CanProceedWithANewImageWhenFailedTest) { SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); - EXPECT_CALL(*observer_, - OnDownloadFailed( - PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_ABORTED)); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)).Times(2); + EXPECT_CALL(*observer_, OnError(FailureReason::DOWNLOAD_FAILED_ABORTED)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()).Times(2); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)).Times(2); EXPECT_CALL(*observer_, OnDownloadCompleted()); - EXPECT_CALL(*observer_, OnImportProgressUpdated(50.0, _)); EXPECT_CALL(*observer_, OnImported()); StartAndRunUntilDownloading(); @@ -506,6 +574,7 @@ } TEST_F(PluginVmInstallerDownloadServiceTest, CancelledDownloadTest) { + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); EXPECT_CALL(*observer_, OnCancelFinished()); @@ -517,17 +586,17 @@ installer_->OnDownloadCancelled(); histogram_tester_->ExpectTotalCount(kPluginVmImageDownloadedSizeHistogram, 0); + histogram_tester_->ExpectTotalCount(kFailureReasonHistogram, 0); } TEST_F(PluginVmInstallerDownloadServiceTest, ImportNonExistingImageTest) { SetupConciergeForSuccessfulDiskImageImport(fake_concierge_client_); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); EXPECT_CALL(*observer_, OnDownloadCompleted()); - EXPECT_CALL( - *observer_, - OnImportFailed(PluginVmInstaller::FailureReason::COULD_NOT_OPEN_IMAGE)); + EXPECT_CALL(*observer_, OnError(FailureReason::COULD_NOT_OPEN_IMAGE)); fake_downloaded_plugin_vm_image_archive_ = base::FilePath(); StartAndRunToCompletion(); @@ -541,6 +610,7 @@ SetupConciergeForCancelDiskImageOperation(fake_concierge_client_, true /* success */); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); EXPECT_CALL(*observer_, OnDownloadCompleted()); @@ -553,12 +623,13 @@ TEST_F(PluginVmInstallerDownloadServiceTest, EmptyPluginVmImageUrlTest) { SetPluginVmImagePref("", kHash); - EXPECT_CALL( - *observer_, - OnDownloadFailed(PluginVmInstaller::FailureReason::INVALID_IMAGE_URL)); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); + EXPECT_CALL(*observer_, OnError(FailureReason::INVALID_IMAGE_URL)); StartAndRunToCompletion(); histogram_tester_->ExpectTotalCount(kPluginVmImageDownloadedSizeHistogram, 0); + histogram_tester_->ExpectUniqueSample(kFailureReasonHistogram, + FailureReason::INVALID_IMAGE_URL, 1); } TEST_F(PluginVmInstallerDownloadServiceTest, VerifyDownloadTest) { @@ -571,8 +642,7 @@ TEST_F(PluginVmInstallerDownloadServiceTest, CannotStartIfPluginVmIsDisabled) { profile_->ScopedCrosSettingsTestHelper()->SetBoolean( chromeos::kPluginVmAllowed, false); - EXPECT_CALL(*observer_, - OnDownloadFailed(PluginVmInstaller::FailureReason::NOT_ALLOWED)); + EXPECT_CALL(*observer_, OnError(FailureReason::NOT_ALLOWED)); installer_->Start(); task_environment_.RunUntilIdle(); } @@ -580,11 +650,10 @@ TEST_F(PluginVmInstallerDriveTest, InvalidDriveUrlTest) { SetPluginVmImagePref(kDriveUrl2, kHash); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); - EXPECT_CALL( - *observer_, - OnDownloadFailed(PluginVmInstaller::FailureReason::INVALID_IMAGE_URL)); + EXPECT_CALL(*observer_, OnError(FailureReason::INVALID_IMAGE_URL)); StartAndRunToCompletion(); } @@ -592,22 +661,21 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_drive_service_->set_offline(true); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); - EXPECT_CALL(*observer_, - OnDownloadFailed( - PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_NETWORK)); + EXPECT_CALL(*observer_, OnError(FailureReason::DOWNLOAD_FAILED_NETWORK)); StartAndRunToCompletion(); } TEST_F(PluginVmInstallerDriveTest, WrongHashDriveTest) { SetPluginVmImagePref(kDriveUrl, kHash2); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); - EXPECT_CALL(*observer_, OnDownloadProgressUpdated(_, _, _)).Times(2); - EXPECT_CALL(*observer_, OnDownloadFailed( - PluginVmInstaller::FailureReason::HASH_MISMATCH)); + EXPECT_CALL(*observer_, OnDownloadProgressUpdated(_, _)).Times(2); + EXPECT_CALL(*observer_, OnError(FailureReason::HASH_MISMATCH)); StartAndRunToCompletion(); } @@ -616,13 +684,12 @@ SetPluginVmImagePref(kDriveUrl, kHash); SimpleFakeDriveService* fake_drive_service = SetUpSimpleFakeDriveService(); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); - EXPECT_CALL(*observer_, OnDownloadProgressUpdated(5, 100, _)); - EXPECT_CALL(*observer_, OnDownloadProgressUpdated(10, 100, _)); - EXPECT_CALL(*observer_, - OnDownloadFailed( - PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_NETWORK)); + EXPECT_CALL(*observer_, OnDownloadProgressUpdated(5, 100)); + EXPECT_CALL(*observer_, OnDownloadProgressUpdated(10, 100)); + EXPECT_CALL(*observer_, OnError(FailureReason::DOWNLOAD_FAILED_NETWORK)); StartAndRunToCompletion(); @@ -640,9 +707,10 @@ SetPluginVmImagePref(kDriveUrl, kHash); SimpleFakeDriveService* fake_drive_service = SetUpSimpleFakeDriveService(); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); - EXPECT_CALL(*observer_, OnDownloadProgressUpdated(5, 100, _)); + EXPECT_CALL(*observer_, OnDownloadProgressUpdated(5, 100)); EXPECT_CALL(*observer_, OnCancelFinished()); StartAndRunToCompletion(); @@ -659,13 +727,13 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_dlcservice_client_->SetInstallError(dlcservice::kErrorNone); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); EXPECT_CALL(*observer_, OnDlcDownloadCompleted()); EXPECT_CALL(*observer_, OnExistingVmCheckCompleted(false)); EXPECT_CALL(*observer_, OnDownloadCompleted()); - EXPECT_CALL(*observer_, - OnDownloadProgressUpdated(_, std::strlen(kContent), _)) + EXPECT_CALL(*observer_, OnDownloadProgressUpdated(_, std::strlen(kContent))) .Times(AtLeast(1)); - EXPECT_CALL(*observer_, OnImportFailed(_)); + EXPECT_CALL(*observer_, OnError(_)); StartAndRunToCompletion(); histogram_tester_->ExpectUniqueSample(kPluginVmDlcUseResultHistogram, @@ -676,7 +744,8 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_dlcservice_client_->SetInstallError(dlcservice::kErrorInternal); - EXPECT_CALL(*observer_, OnDownloadFailed(_)).Times(1); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); + EXPECT_CALL(*observer_, OnError(FailureReason::DLC_INTERNAL)); StartAndRunToCompletion(); histogram_tester_->ExpectUniqueSample(kPluginVmDlcUseResultHistogram, @@ -688,7 +757,8 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_dlcservice_client_->SetInstallError(dlcservice::kErrorBusy); - EXPECT_CALL(*observer_, OnDownloadFailed(_)).Times(1); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); + EXPECT_CALL(*observer_, OnError(FailureReason::DLC_BUSY)); StartAndRunToCompletion(); histogram_tester_->ExpectUniqueSample(kPluginVmDlcUseResultHistogram, @@ -699,7 +769,8 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_dlcservice_client_->SetInstallError(dlcservice::kErrorNeedReboot); - EXPECT_CALL(*observer_, OnDownloadFailed(_)).Times(1); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); + EXPECT_CALL(*observer_, OnError(FailureReason::DLC_NEED_REBOOT)); StartAndRunToCompletion(); histogram_tester_->ExpectUniqueSample( @@ -711,7 +782,8 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_dlcservice_client_->SetInstallError(dlcservice::kErrorAllocation); - EXPECT_CALL(*observer_, OnDownloadFailed(_)).Times(1); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); + EXPECT_CALL(*observer_, OnError(FailureReason::DLC_NEED_SPACE)); StartAndRunToCompletion(); histogram_tester_->ExpectUniqueSample( @@ -723,7 +795,8 @@ SetPluginVmImagePref(kDriveUrl, kHash); fake_dlcservice_client_->SetInstallError(dlcservice::kErrorInvalidDlc); - EXPECT_CALL(*observer_, OnDownloadFailed(_)).Times(1); + EXPECT_CALL(*observer_, OnCheckedDiskSpace(false)); + EXPECT_CALL(*observer_, OnError(FailureReason::DLC_UNSUPPORTED)); StartAndRunToCompletion(); histogram_tester_->ExpectUniqueSample(kPluginVmDlcUseResultHistogram,
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_metrics_util.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_metrics_util.h index b76fca6..62e2591d 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_metrics_util.h +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_metrics_util.h
@@ -34,22 +34,22 @@ // numeric values should never be reused. enum class PluginVmSetupResult { kSuccess = 0, - - kPluginVmIsNotAllowed = 1, - - kErrorDownloadingPluginVmImage = 2, - kErrorImportingPluginVmImage = 3, - + // kPluginVmIsNotAllowed = 1, + // kErrorDownloadingPluginVmImage = 2, + // kErrorImportingPluginVmImage = 3, kUserCancelledDownloadingPluginVmImage = 4, kUserCancelledImportingPluginVmImage = 5, - - kErrorDownloadingPluginVmDlc = 6, + // kErrorDownloadingPluginVmDlc = 6, kUserCancelledDownloadingPluginVmDlc = 7, - kVmAlreadyExists = 8, kUserCancelledCheckingForExistingVm = 9, + // kErrorInsufficientDiskSpace = 10, + kUserCancelledLowDiskSpace = 11, + kUserCancelledCheckingDiskSpace = 12, + // Failure reasons are broken down in PluginVm.SetupFailureReason. + kError = 13, - kMaxValue = kUserCancelledCheckingForExistingVm, + kMaxValue = kError, }; enum class PluginVmDlcUseResult {
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc index 23289be..e3b6f2b 100644 --- a/chrome/browser/chromeos/smb_client/smb_service.cc +++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -180,6 +180,12 @@ } } +void SmbService::Shutdown() { + // Unmount and destroy all smbfs instances explicitly before destruction, + // since SmbFsShare accesses KeyedServices on destruction. + smbfs_shares_.clear(); +} + // static void SmbService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) {
diff --git a/chrome/browser/chromeos/smb_client/smb_service.h b/chrome/browser/chromeos/smb_client/smb_service.h index 1bc2d6d..95c4fa6 100644 --- a/chrome/browser/chromeos/smb_client/smb_service.h +++ b/chrome/browser/chromeos/smb_client/smb_service.h
@@ -62,6 +62,9 @@ SmbService(Profile* profile, std::unique_ptr<base::TickClock> tick_clock); ~SmbService() override; + // KeyedService override. + void Shutdown() override; + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); // Starts the process of mounting an SMB file system.
diff --git a/chrome/browser/chromeos/smb_client/smb_service_factory.cc b/chrome/browser/chromeos/smb_client/smb_service_factory.cc index 6b63c97..008093e 100644 --- a/chrome/browser/chromeos/smb_client/smb_service_factory.cc +++ b/chrome/browser/chromeos/smb_client/smb_service_factory.cc
@@ -8,6 +8,7 @@ #include "base/time/default_tick_clock.h" #include "chrome/browser/chromeos/authpolicy/authpolicy_credentials_manager.h" +#include "chrome/browser/chromeos/file_manager/volume_manager_factory.h" #include "chrome/browser/chromeos/file_system_provider/service_factory.h" #include "chrome/browser/chromeos/kerberos/kerberos_credentials_manager_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -54,6 +55,7 @@ DependsOn(file_system_provider::ServiceFactory::GetInstance()); DependsOn(AuthPolicyCredentialsManagerFactory::GetInstance()); DependsOn(KerberosCredentialsManagerFactory::GetInstance()); + DependsOn(file_manager::VolumeManagerFactory::GetInstance()); } SmbServiceFactory::~SmbServiceFactory() {}
diff --git a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc index 35b65cf..0a651d9 100644 --- a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc +++ b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
@@ -601,7 +601,8 @@ ASSERT_FLOAT_EQ(kScale, fontSize / oldFontSize); } -IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, UISetsPrefs) { +IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest, + DISABLED_UISetsPrefs) { content::WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chrome/browser/download/download_permission_request.cc b/chrome/browser/download/download_permission_request.cc index c49c0b4..d90f115 100644 --- a/chrome/browser/download/download_permission_request.cc +++ b/chrome/browser/download/download_permission_request.cc
@@ -12,7 +12,7 @@ #include "components/url_formatter/elide_url.h" #include "url/origin.h" #else -#include "chrome/app/vector_icons/vector_icons.h" +#include "components/vector_icons/vector_icons.h" #endif DownloadPermissionRequest::DownloadPermissionRequest( @@ -27,7 +27,7 @@ #if defined(OS_ANDROID) return IDR_ANDROID_INFOBAR_MULTIPLE_DOWNLOADS; #else - return kFileDownloadIcon; + return vector_icons::kFileDownloadIcon; #endif }
diff --git a/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chrome/browser/extensions/api/debugger/debugger_apitest.cc index bdd45750..ea248c27 100644 --- a/chrome/browser/extensions/api/debugger/debugger_apitest.cc +++ b/chrome/browser/extensions/api/debugger/debugger_apitest.cc
@@ -338,6 +338,19 @@ ASSERT_TRUE(RunExtensionTest("debugger")) << message_; } +// Tests that an extension is not allowed to inspect a worker through the +// inspectWorker debugger command. +// Regression test for https://crbug.com/1059577. +IN_PROC_BROWSER_TEST_F(DebuggerExtensionApiTest, + DebuggerNotAllowedToInvokeInspectWorker) { + GURL url(embedded_test_server()->GetURL( + "/extensions/api_test/debugger_inspect_worker/inspected_page.html")); + + EXPECT_TRUE( + RunExtensionTestWithArg("debugger_inspect_worker", url.spec().c_str())) + << message_; +} + class SitePerProcessDebuggerExtensionApiTest : public DebuggerExtensionApiTest { public: void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chrome/browser/extensions/api/permissions/permissions_apitest.cc index 3bffa0d..8931e0c 100644 --- a/chrome/browser/extensions/api/permissions/permissions_apitest.cc +++ b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
@@ -69,6 +69,12 @@ << message_; } +// TODO(crbug/1065399): Flaky on ChromeOS and Linux non-dbg builds. +#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(NDEBUG) +#define MAYBE_FaviconPermission DISABLED_FaviconPermission +#else +#define MAYBE_FaviconPermission MAYBE_FaviconPermission +#endif IN_PROC_BROWSER_TEST_F(PermissionsApiTest, FaviconPermission) { base::HistogramTester tester; ASSERT_TRUE(RunExtensionTest("permissions/favicon")) << message_;
diff --git a/chrome/browser/notifications/notification_platform_bridge_mac.mm b/chrome/browser/notifications/notification_platform_bridge_mac.mm index ebd61c7..acf1849a 100644 --- a/chrome/browser/notifications/notification_platform_bridge_mac.mm +++ b/chrome/browser/notifications/notification_platform_bridge_mac.mm
@@ -114,7 +114,10 @@ base::string16 CreateNotificationTitle( const message_center::Notification& notification) { base::string16 title; - if (notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS) { + // Show progress percentage if available. We don't support indeterminate + // states on macOS native notifications. + if (notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS && + notification.progress() >= 0 && notification.progress() <= 100) { title += base::FormatPercent(notification.progress()); title += base::UTF8ToUTF16(" - "); }
diff --git a/chrome/browser/resources/chromeos/login/oobe_reset.html b/chrome/browser/resources/chromeos/login/oobe_reset.html index 39d24fb..7706065 100644 --- a/chrome/browser/resources/chromeos/login/oobe_reset.html +++ b/chrome/browser/resources/chromeos/login/oobe_reset.html
@@ -81,15 +81,15 @@ <div class="flex"></div> <!-- Cancel button, only disabled when reverting --> <oobe-text-button border on-tap="onCancelTap_" text-key="cancelButton" - disabled="[[inRevertState_]]"></oobe-text-button> + id="resetCancel" disabled="[[inRevertState_]]"></oobe-text-button> <!-- Restart button --> <oobe-text-button inverse on-tap="onRestartTap_" class="focus-on-show" - text-key="resetButtonRestart" + id="restart" text-key="resetButtonRestart" hidden="[[!inRestartRequiredState_]]"> </oobe-text-button> <!-- Powerwash button (depends on powerwash mode) --> <oobe-text-button inverse on-tap="onPowerwashTap_" class="focus-on-show" - hidden="[[!inPowerwashState_]]" + id="powerwash" hidden="[[!inPowerwashState_]]" text-key="[[powerwashButtonTextKey_]]" disabled="[[powerwashButtonDisabled_]]"> </oobe-text-button> @@ -104,6 +104,7 @@ <oobe-text-button id="cancelButton" border on-tap="onDialogCancelTap_" text-key="cancel"></oobe-text-button> <oobe-text-button inverse on-tap="onDialogContinueTap_" + id="confirmPowerwash" text-key="confirmResetButton"></oobe-text-button> </div> </oobe-help-dialog>
diff --git a/chrome/browser/resources/media/media_data_table.js b/chrome/browser/resources/media/media_data_table.js index 758ace61..8efaad5 100644 --- a/chrome/browser/resources/media/media_data_table.js +++ b/chrome/browser/resources/media/media_data_table.js
@@ -80,7 +80,7 @@ key = k; }); - this.delegate_.insertDataField(td, data, key, dataRow); + this.delegate_.insertDataField(td, data, key); tr.appendChild(td); }); }); @@ -103,10 +103,8 @@ * @param {Element} td * @param {?Object} data * @param {string} key - * @param {Object} dataRow This is the row itself in case we need extra - * data to render the field. */ - insertDataField(td, data, key, dataRow) {} + insertDataField(td, data, key) {} /** * Compares two objects based on |sortKey|.
diff --git a/chrome/browser/resources/media/media_feeds.html b/chrome/browser/resources/media/media_feeds.html index 1083adcf..3f848c5 100644 --- a/chrome/browser/resources/media/media_feeds.html +++ b/chrome/browser/resources/media/media_feeds.html
@@ -124,8 +124,6 @@ </th> <th data-key="logos"> Logos - <th data-key="actions"> - Actions </th> </tr> </thead> @@ -133,71 +131,22 @@ </tbody> </table> - <div id="feed-content" style="display:none;"> - <hr> - <h2>Feed Contents: <span id="current-feed"></span></h2> - <table id="feed-items-table"> - <thead> - <tr> - <th sort-key="type" class="sort-column" sort-reverse> - Type - </th> - <th sort-key="name"> - Name - </th> - <th sort-key="author"> - Author - </th> - <th sort-key="datePublished"> - Date Published - </th> - <th sort-key="isFamilyFriendly"> - Family Friendly - </th> - <th sort-key="actionStatus"> - Action Status - </th> - <th sort-key="action.url"> - Action URL - </th> - <th sort-key="action.startTime"> - Action Start Time (secs) - </th> - <th sort-key="interactionCounters"> - Interaction Counters - </th> - <th sort-key="contentRatings"> - Content Ratings - </th> - <th sort-key="genre"> - Genre - </th> - <th sort-key="live"> - Live Details - </th> - <th sort-key="tvEpisode"> - TV Episode - </th> - <th sort-key="playNextCandidate"> - Play Next Candidate - </th> - <th sort-key="identifiers"> - Identifiers - </th> - <th sort-key="shownCount"> - Shown Count - </th> - <th sort-key="clicked"> - Clicked - </th> - <th sort-key="images"> - Images - </th> - </tr> - </thead> - <tbody> - </tbody> - </table> - </div> + <template id="datarow"> + <tr> + <td class="id-cell"></td> + <td class="url-cell"></td> + <td></td> + <td class="last-discovery-time-cell"></td> + <td></td> + <td></td> + <td></td> + <td></td> + <td></td> + <td></td> + <td></td> + <td></td> + <td></td> + </tr> + </template> </body> </html>
diff --git a/chrome/browser/resources/media/media_feeds.js b/chrome/browser/resources/media/media_feeds.js index cb517fb..13830a4 100644 --- a/chrome/browser/resources/media/media_feeds.js +++ b/chrome/browser/resources/media/media_feeds.js
@@ -11,16 +11,10 @@ return mediaFeedsPageIsPopulatedResolver.promise; } -const mediaFeedItemsPageIsPopulatedResolver = new PromiseResolver(); -function whenFeedTableIsPopulatedForTest() { - return mediaFeedItemsPageIsPopulatedResolver.promise; -} - (function() { let delegate = null; let feedsTable = null; -let feedItemsTable = null; let store = null; /** @implements {cr.ui.MediaDataTableDelegate} */ @@ -31,28 +25,8 @@ * @param {Element} td * @param {?Object} data * @param {string} key - * @param {Object} dataRow */ - insertDataField(td, data, key, dataRow) { - if (key == 'actions') { - const a = document.createElement('a'); - a.href = '#feed-content'; - a.textContent = 'Show Contents'; - td.appendChild(a); - - a.addEventListener('click', () => { - store.getItemsForMediaFeed(dataRow.id).then(response => { - feedItemsTable.setData(response.items); - - // Show the feed items section. - $('current-feed').textContent = dataRow.url.url; - $('feed-content').style.display = 'block'; - - mediaFeedItemsPageIsPopulatedResolver.resolve(); - }); - }); - } - + insertDataField(td, data, key) { if (data === undefined || data === null) { return; } @@ -62,11 +36,11 @@ td.textContent = data.url; } else if ( key === 'lastDiscoveryTime' || key === 'lastFetchTime' || - key === 'cacheExpiryTime' || key === 'datePublished') { + key === 'cacheExpiryTime') { // Format a mojo time. td.textContent = convertMojoTimeToJS(/** @type {mojoBase.mojom.Time} */ (data)) - .toLocaleString(); + .toString(); } else if (key === 'userStatus') { // Format a FeedUserStatus. if (data == mediaFeeds.mojom.FeedUserStatus.kAuto) { @@ -100,7 +74,7 @@ td.textContent = contentTypes.length === 0 ? 'None' : contentTypes.join(','); - } else if (key === 'logos' || key === 'images') { + } else if (key === 'logos') { // Format an array of mojo media images. data.forEach((image) => { const a = document.createElement('a'); @@ -110,129 +84,6 @@ td.appendChild(a); td.appendChild(document.createElement('br')); }); - } else if (key == 'type') { - // Format a MediaFeedItemType. - switch (parseInt(data, 10)) { - case mediaFeeds.mojom.MediaFeedItemType.kVideo: - td.textContent = 'Video'; - break; - case mediaFeeds.mojom.MediaFeedItemType.kTVSeries: - td.textContent = 'TV Series'; - break; - case mediaFeeds.mojom.MediaFeedItemType.kMovie: - td.textContent = 'Movie'; - break; - } - } else if (key == 'isFamilyFriendly' || key == 'clicked') { - // Format a boolean. - td.textContent = data ? 'Yes' : 'No'; - } else if (key == 'actionStatus') { - // Format a MediaFeedItemActionStatus. - switch (parseInt(data, 10)) { - case mediaFeeds.mojom.MediaFeedItemActionStatus.kUnknown: - td.textContent = 'Unknown'; - break; - case mediaFeeds.mojom.MediaFeedItemActionStatus.kActive: - td.textContent = 'Active'; - break; - case mediaFeeds.mojom.MediaFeedItemActionStatus.kPotential: - td.textContent = 'Potential'; - break; - case mediaFeeds.mojom.MediaFeedItemActionStatus.kCompleted: - td.textContent = 'Completed'; - break; - } - } else if (key == 'startTime') { - // Format a start time. - td.textContent = - timeDeltaToSeconds(/** @type {mojoBase.mojom.TimeDelta} */ (data)); - } else if (key == 'interactionCounters') { - // Format interaction counters. - const counters = []; - - Object.keys(data).forEach((key) => { - let keyString = ''; - - switch (parseInt(key, 10)) { - case mediaFeeds.mojom.InteractionCounterType.kWatch: - keyString = 'Watch'; - break; - case mediaFeeds.mojom.InteractionCounterType.kLike: - keyString = 'Like'; - break; - case mediaFeeds.mojom.InteractionCounterType.kDislike: - keyString = 'Dislike'; - break; - } - - counters.push(keyString + '=' + data[key]); - }); - - td.textContent = counters.join(' '); - } else if (key == 'contentRatings') { - // Format content ratings. - const ratings = []; - - data.forEach((rating) => { - ratings.push(rating.agency + ' ' + rating.value); - }); - - td.textContent = ratings.join(', '); - } else if (key == 'author') { - // Format a mojom author. - const a = document.createElement('a'); - a.href = data.url; - a.textContent = data.name; - a.target = '_blank'; - td.appendChild(a); - } else if (key == 'name' || key == 'genre') { - // Format a mojo string16. - td.textContent = - decodeString16(/** @type {mojoBase.mojom.String16} */ (data)); - } else if (key == 'live') { - // Format LiveDetails. - td.textContent = 'Live'; - - if (data.startTime) { - td.textContent += ' ' + - 'StartTime=' + - convertMojoTimeToJS( - /** @type {mojoBase.mojom.Time} */ (data.startTime)) - .toLocaleString(); - } - - if (data.endTime) { - td.textContent += ' ' + - 'EndTime=' + - convertMojoTimeToJS( - /** @type {mojoBase.mojom.Time} */ (data.endTime)) - .toLocaleString(); - } - } else if (key == 'tvEpisode') { - // Format a TV Episode. - td.textContent = data.name + ' EpisodeNumber=' + data.episodeNumber + - ' SeasonNumber=' + data.seasonNumber + ' ' + - formatIdentifiers(/** @type {Array<mediaFeeds.mojom.Identifier>} */ ( - data.identifiers)); - } else if (key == 'playNextCandidate') { - // Format a Play Next Candidate. - td.textContent = data.name + ' EpisodeNumber=' + data.episodeNumber + - ' SeasonNumber=' + data.seasonNumber + ' ' + - formatIdentifiers( - /** @type {Array<mediaFeeds.mojom.Identifier>} */ ( - data.identifiers)) + - ' ActionURL=' + data.action.url.url; - - if (data.action.startTime) { - td.textContent += - ' ActionStartTimeSecs=' + timeDeltaToSeconds(data.action.startTime); - } - - td.textContent += ' DurationSecs=' + timeDeltaToSeconds(data.duration); - } else if (key == 'identifiers') { - // Format identifiers. - td.textContent = formatIdentifiers( - /** @type {Array<mediaFeeds.mojom.Identifier>} */ (data)); } else { td.textContent = data; } @@ -271,57 +122,6 @@ } /** - * Convert a time delta to seconds. - * @param {mojoBase.mojom.TimeDelta} timeDelta - * @returns {number} - */ -function timeDeltaToSeconds(timeDelta) { - return timeDelta.microseconds / 1000 / 1000; -} - -/** - * Formats an array of identifiers for display. - * @param {Array<mediaFeeds.mojom.Identifier>} mojoIdentifiers - * @returns {string} - */ -function formatIdentifiers(mojoIdentifiers) { - const identifiers = []; - - mojoIdentifiers.forEach((identifier) => { - let keyString = ''; - - switch (identifier.type) { - case mediaFeeds.mojom.Identifier_Type.kTMSRootId: - keyString = 'TMSRootId'; - break; - case mediaFeeds.mojom.Identifier_Type.kTMSId: - keyString = 'TMSId'; - break; - case mediaFeeds.mojom.Identifier_Type.kPartnerId: - keyString = 'PartnerId'; - break; - } - - identifiers.push(keyString + '=' + identifier.value); - }); - - return identifiers.join(' '); -} - -/** - * Parses utf16 coded string. - * @param {?mojoBase.mojom.String16} arr - * @return {string} - */ -function decodeString16(arr) { - if (arr == null) { - return ''; - } - - return arr.data.map(ch => String.fromCodePoint(ch)).join(''); -} - -/** * Converts a mojo time to a JS time. * @param {mojoBase.mojom.Time} mojoTime * @return {Date} @@ -360,7 +160,6 @@ delegate = new MediaFeedsTableDelegate(); feedsTable = new cr.ui.MediaDataTable($('feeds-table'), delegate); - feedItemsTable = new cr.ui.MediaDataTable($('feed-items-table'), delegate); updateFeedsTable();
diff --git a/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chrome/browser/resources/settings/autofill_page/BUILD.gn index 9a5034e1..96b464b6 100644 --- a/chrome/browser/resources/settings/autofill_page/BUILD.gn +++ b/chrome/browser/resources/settings/autofill_page/BUILD.gn
@@ -100,6 +100,7 @@ ":password_manager_proxy", "..:plural_string_proxy", "../prefs:prefs_behavior", + "//ui/webui/resources/js:assert", "//ui/webui/resources/js:i18n_behavior", ] } @@ -296,6 +297,7 @@ "..:plural_string_proxy.m", "../prefs:prefs_behavior.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:i18n_behavior.m", ] extra_deps = [ ":password_check_module" ] @@ -318,6 +320,7 @@ ":password_manager_proxy.m", "..:open_window_proxy.m", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:i18n_behavior", ] extra_deps = [ ":password_check_list_item_module" ]
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.html b/chrome/browser/resources/settings/autofill_page/password_check.html index 97c649f..d7f0496 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check.html +++ b/chrome/browser/resources/settings/autofill_page/password_check.html
@@ -136,7 +136,10 @@ </div> </div> <cr-action-menu id="moreActionsMenu" role-description="$i18n{menu}"> - <!-- TODO(crbug.com/1047726) Add show / hide functionality --> + <button id="menuShowPassword" class="dropdown-item" + on-click="onMenuShowPasswordClick_"> + [[showHideMenuTitle_]] + </button> <button id="menuEditPassword" class="dropdown-item" on-click="onMenuEditPasswordClick_"> $i18n{editCompromisedPassword}
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.js b/chrome/browser/resources/settings/autofill_page/password_check.js index 057e14c0..83767f8 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check.js +++ b/chrome/browser/resources/settings/autofill_page/password_check.js
@@ -103,6 +103,12 @@ type: Boolean, computed: 'computeShowNoCompromisedPasswordsLabel(syncStatus_, prefs.*, status_, leakedPasswords)', + }, + + /** @private */ + showHideMenuTitle_: { + type: String, + computed: 'computeShowHideMenuTitle(activePassword_)', } }, @@ -130,6 +136,12 @@ */ activeDialogAnchor_: null, + /** + * The password_check_list_item that the user is interacting with now. + * @private {?EventTarget} + */ + activeListItem_: null, + /** @override */ attached() { // Set the manager. These can be overridden by tests. @@ -239,7 +251,17 @@ const target = event.detail.moreActionsButton; this.$.moreActionsMenu.showAt(target); this.activeDialogAnchor_ = target; - this.activePassword_ = event.target.item; + this.activeListItem_ = event.target; + this.activePassword_ = this.activeListItem_.item; + }, + + /** @private */ + onMenuShowPasswordClick_() { + this.activePassword_.password ? this.activeListItem_.hidePassword() : + this.activeListItem_.showPassword(); + this.$.moreActionsMenu.close(); + this.activePassword_ = null; + this.activeDialogAnchor_ = null; }, /** @private */ @@ -281,6 +303,12 @@ this.activeDialogAnchor_ = null; }, + computeShowHideMenuTitle() { + return this.i18n( + this.activeListItem_.isPasswordVisible_ ? 'hideCompromisedPassword' : + 'showCompromisedPassword'); + }, + /** * Returns the icon (warning, info or error) indicating the check status. * @return {string} @@ -560,6 +588,7 @@ if (map.has(item.id)) { // Replace old version with new resultList.push(map.get(item.id)); + resultList[resultList.length - 1].password = item.password; map.delete(item.id); } }); @@ -573,7 +602,8 @@ } return rhs.compromiseTime - lhs.compromiseTime; }); - this.leakedPasswords = resultList.concat(addedResults); + addedResults.forEach(item => resultList.push(item)); + this.leakedPasswords = resultList; }, /**
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_list_item.html b/chrome/browser/resources/settings/autofill_page/password_check_list_item.html index 35e0b6f..5ecf82d9 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check_list_item.html +++ b/chrome/browser/resources/settings/autofill_page/password_check_list_item.html
@@ -3,6 +3,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="../open_window_proxy.html"> <link rel="import" href="../settings_shared_css.html"> @@ -84,8 +85,11 @@ <span class="no-min-width text-elide secondary"> [[item.username]] </span> - <input class="no-min-width secondary" id="leakedPassword" - type="password" value="[[password_]]" readonly disabled> + <input class="no-min-width secondary text-elide" id="leakedPassword" + focus-row-control focus-type="passwordField" readonly + type="[[getInputType_(isPasswordVisible_)]]" + value="[[password_]]" on-click="onReadonlyInputTap_" + disabled$="[[!isPasswordVisible_]]"> </div> <div class="secondary" id="leakType"> [[getCompromiseType_(item)]]
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_list_item.js b/chrome/browser/resources/settings/autofill_page/password_check_list_item.js index 1a744ec25..dc83263 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check_list_item.js +++ b/chrome/browser/resources/settings/autofill_page/password_check_list_item.js
@@ -11,16 +11,34 @@ is: 'password-check-list-item', properties: { - password_: { - type: String, - value: ' '.repeat(10), - }, - /** * The password that is being displayed. * @type {!PasswordManagerProxy.CompromisedCredential} */ item: Object, + + /** @private */ + isPasswordVisible_: { + type: Boolean, + computed: 'computePasswordVisibility_(item.password)', + }, + + /** @private */ + password_: { + type: String, + computed: 'computePassword_(item.password)', + }, + }, + + /** + * @private {?PasswordManagerProxy} + */ + passwordManager_: null, + + /** @override */ + attached() { + // Set the manager. These can be overridden by tests. + this.passwordManager_ = PasswordManagerImpl.getInstance(); }, /** @@ -59,4 +77,63 @@ onMoreClick_(event) { this.fire('more-actions-click', {moreActionsButton: event.target}); }, + + /** + * @return {string} + * @private + */ + getInputType_() { + return this.isPasswordVisible_ ? 'text' : 'password'; + }, + + /** + * @return {boolean} + * @private + */ + computePasswordVisibility_() { + return !!this.item.password; + }, + + /** + * @return {string} + * @private + */ + computePassword_() { + const NUM_PLACEHOLDERS = 10; + return this.item.password || ' '.repeat(NUM_PLACEHOLDERS); + }, + + /** + * @public + */ + hidePassword() { + this.set('item.password', null); + }, + + /** + * @public + */ + showPassword() { + this.passwordManager_.recordPasswordCheckInteraction( + PasswordManagerProxy.PasswordCheckInteraction.SHOW_PASSWORD); + this.passwordManager_ + .getPlaintextCompromisedPassword( + assert(this.item), chrome.passwordsPrivate.PlaintextReason.VIEW) + .then( + compromisedCredential => { + this.set('item', compromisedCredential); + }, + error => { + this.hidePassword(); + }); + }, + + /** + * @private + */ + onReadonlyInputTap_() { + if (this.isPasswordVisible_) { + this.$$('#leakedPassword').select(); + } + }, });
diff --git a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js index 6fdd2058..b749952 100644 --- a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js +++ b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js
@@ -292,8 +292,9 @@ CHANGE_PASSWORD: 3, EDIT_PASSWORD: 4, REMOVE_PASSWORD: 5, + SHOW_PASSWORD: 6, // Must be last. - COUNT: 6, + COUNT: 7, }; /**
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn index 8fed398..930b195 100644 --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -23,6 +23,7 @@ "//components/browser_sync", "//components/keyed_service/content", "//components/language/core/browser", + "//components/page_info", "//components/password_manager/core/browser", "//components/password_manager/core/browser:hash_password_manager", "//components/pref_registry",
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc index beab5887..ad9f53b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" #include "components/sessions/content/session_tab_helper.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h"
diff --git a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc index d7eb9d9..605003ef 100644 --- a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc +++ b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler.cc
@@ -17,6 +17,7 @@ #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/trace_event/trace_event.h" +#include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service_factory.h" @@ -332,12 +333,25 @@ // This might happen if we don't know the total size of the image but we // still want to show how many bytes have been transferred. notification.set_progress(-1); +#if defined(OS_MACOSX) + // On macOS we only have the title and message available. The progress is + // prepended to the title and the message should be the context. + notification.set_message(context); +#else notification.set_progress_status(context); +#endif // defined(OS_MACOSX) } else { notification.set_progress(image_content_progress_ * 100 / image_content_length_); - notification.set_progress_status( - GetProgressString(image_content_progress_, image_content_length_)); + base::string16 progress = + GetProgressString(image_content_progress_, image_content_length_); +#if defined(OS_MACOSX) + // On macOS we only have the title and message available. The progress is + // prepended to the title and the message should be the progress. + notification.set_message(progress); +#else + notification.set_progress_status(progress); +#endif // defined(OS_MACOSX) } NotificationDisplayServiceFactory::GetForProfile(profile_)->Display( @@ -502,6 +516,13 @@ base::Unretained(this), old_sequence_number, base::TimeTicks::Now(), /*is_image=*/true)); +#if defined(OS_MACOSX) + // On macOS we can't replace a persistent notification with a non-persistent + // one because they are posted from different sources (app vs xpc). To avoid + // having both notifications on screen, remove the progress one first. + CancelProgressNotification(); +#endif // defined(OS_MACOSX) + std::string notification_id = image_notification_id_; if (notification_id.empty()) { notification_id = base::GenerateGUID(); @@ -523,13 +544,23 @@ const std::string& notification_id) { TRACE_EVENT0("sharing", "RemoteCopyMessageHandler::ShowNotification"); + gfx::Image icon; + message_center::RichNotificationData rich_notification_data; + bool use_image_notification = base::FeatureList::IsEnabled(kRemoteCopyImageNotification) && !image.drawsNothing(); - message_center::RichNotificationData rich_notification_data; - if (use_image_notification) + if (use_image_notification) { +#if defined(OS_MACOSX) + // On macOS notifications do not support large images so use the icon + // instead. + icon = gfx::Image::CreateFrom1xBitmap(image); +#else rich_notification_data.image = gfx::Image::CreateFrom1xBitmap(image); +#endif // defined(OS_MACOSX) + } + rich_notification_data.vector_small_image = &kSendTabToSelfIcon; message_center::NotificationType type = @@ -543,7 +574,7 @@ l10n_util::GetStringFUTF16( IDS_SHARING_REMOTE_COPY_NOTIFICATION_DESCRIPTION, paste_accelerator.GetShortcutText()), - /*icon=*/gfx::Image(), + icon, /*display_source=*/base::string16(), /*origin_url=*/GURL(), message_center::NotifierId(), rich_notification_data,
diff --git a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc index 329ac4fb..c3ec61b 100644 --- a/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc +++ b/chrome/browser/sharing/shared_clipboard/remote_copy_message_handler_unittest.cc
@@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "build/build_config.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/sharing/mock_sharing_service.h" #include "chrome/browser/sharing/proto/remote_copy_message.pb.h" @@ -222,9 +223,17 @@ IDS_SHARING_REMOTE_COPY_NOTIFICATION_TITLE_IMAGE_CONTENT, base::ASCIIToUTF16(kDeviceNameInMessage)), notification.title()); + +#if defined(OS_MACOSX) + // On macOS the progress status is shown in the message. + base::string16 progress_status = notification.message(); +#else + base::string16 progress_status = notification.progress_status(); +#endif // defined(OS_MACOSX) + EXPECT_EQ(l10n_util::GetStringUTF16( IDS_SHARING_REMOTE_COPY_NOTIFICATION_PREPARING_DOWNLOAD), - notification.progress_status()); + progress_status); EXPECT_EQ(-1, notification.progress()); // Calling GetDefaultStoragePartition creates tasks that need to run before @@ -260,7 +269,13 @@ // Expect an image notification showing the image. auto notification = GetImageNotification(); + +#if defined(OS_MACOSX) + // On macOS we show the image as the icon instead. + EXPECT_FALSE(notification.icon().IsEmpty()); +#else EXPECT_FALSE(notification.image().IsEmpty()); +#endif // defined(OS_MACOSX) // Calling GetDefaultStoragePartition creates tasks that need to run before // the ScopedFeatureList is destroyed. See crbug.com/1060869 @@ -338,7 +353,13 @@ // Expect an image notification showing the image. auto notification = GetImageNotification(); + +#if defined(OS_MACOSX) + // On macOS we show the image as the icon instead. + EXPECT_FALSE(notification.icon().IsEmpty()); +#else EXPECT_FALSE(notification.image().IsEmpty()); +#endif // defined(OS_MACOSX) // Calling GetDefaultStoragePartition creates tasks that need to run before // the ScopedFeatureList is destroyed. See crbug.com/1060869
diff --git a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc index 74122d0..bbdf253 100644 --- a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc +++ b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/browser/ui/webui/signin/login_ui_test_utils.h" +#include "chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h" #include "chrome/test/base/ui_test_utils.h" #include "components/signin/core/browser/account_reconcilor.h" #include "components/signin/public/identity_manager/account_info.h" @@ -462,7 +463,7 @@ // profile is created. Checks that Sync to account 2 is enabled in the new // profile. Checks that account 2 was removed from the original profile. IN_PROC_BROWSER_TEST_F(LiveSignInTest, - MANUAL_SyncSecondAccountCreateNewProfile) { + MANUAL_SyncSecondAccount_CreateNewProfile) { // Enable and disable sync for the first account. TestAccount test_account_1; CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1)); @@ -531,5 +532,105 @@ EXPECT_FALSE(identity_manager()->HasPrimaryAccount()); } +// This test can pass. Marked as manual because it TIMED_OUT on Win7. +// See crbug.com/1025335. +// Enables and disables sync to account 1. Enables sync to account 2 and clicks +// on "This was me" in the email confirmation dialog. Checks that Sync to +// account 2 is enabled in the current profile. +IN_PROC_BROWSER_TEST_F(LiveSignInTest, + MANUAL_SyncSecondAccount_InExistingProfile) { + // Enable and disable sync for the first account. + TestAccount test_account_1; + CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1)); + TurnOnSync(test_account_1, 0); + TurnOffSync(); + + // Start enable sync for the second account. + TestAccount test_account_2; + CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_2", test_account_2)); + SignInFromSettings(test_account_2, 0); + + // Check there is only one profile. + ProfileManager* profile_manager = g_browser_process->profile_manager(); + EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U); + EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); + + // Click "This was me" on the email confirmation dialog, confirm sync and wait + // for a primary account to be set. + SignInTestObserver observer(identity_manager(), account_reconcilor()); + EXPECT_TRUE(login_ui_test_utils::CompleteSigninEmailConfirmationDialog( + browser(), base::TimeDelta::FromSeconds(3), + SigninEmailConfirmationDialog::START_SYNC)); + EXPECT_TRUE(login_ui_test_utils::ConfirmSyncConfirmationDialog( + browser(), base::TimeDelta::FromSeconds(5))); + observer.WaitForAccountChanges(1, PrimarySyncAccountWait::kWaitForAdded); + + // Check no profile was created. + EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U); + EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); + + // Check accounts in cookies. + const AccountsInCookieJarInfo& accounts_in_cookie_jar = + identity_manager()->GetAccountsInCookieJar(); + EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh); + ASSERT_EQ(1u, accounts_in_cookie_jar.signed_in_accounts.size()); + const gaia::ListedAccount& account = + accounts_in_cookie_jar.signed_in_accounts[0]; + EXPECT_TRUE(gaia::AreEmailsSame(test_account_2.user, account.email)); + + // Check the primary account is set and syncing. + const CoreAccountInfo& primary_account = + identity_manager()->GetPrimaryAccountInfo(); + EXPECT_FALSE(primary_account.IsEmpty()); + EXPECT_TRUE(gaia::AreEmailsSame(test_account_2.user, primary_account.email)); + EXPECT_TRUE(identity_manager()->HasAccountWithRefreshToken( + primary_account.account_id)); + EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled()); +} + +// This test can pass. Marked as manual because it TIMED_OUT on Win7. +// See crbug.com/1025335. +// Enables and disables sync to account 1. Enables sync to account 2 and clicks +// on "Cancel" in the email confirmation dialog. Checks that the signin flow is +// canceled and no accounts are added to Chrome. +IN_PROC_BROWSER_TEST_F(LiveSignInTest, + MANUAL_SyncSecondAccount_CancelOnEmailConfirmation) { + // Enable and disable sync for the first account. + TestAccount test_account_1; + CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_1", test_account_1)); + TurnOnSync(test_account_1, 0); + TurnOffSync(); + + // Start enable sync for the second account. + TestAccount test_account_2; + CHECK(GetTestAccountsUtil()->GetAccount("TEST_ACCOUNT_2", test_account_2)); + SignInFromSettings(test_account_2, 0); + + // Check there is only one profile. + ProfileManager* profile_manager = g_browser_process->profile_manager(); + EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U); + EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); + + // Click "Cancel" on the email confirmation dialog and wait for an account to + // removed from Chrome. + SignInTestObserver observer(identity_manager(), account_reconcilor()); + EXPECT_TRUE(login_ui_test_utils::CompleteSigninEmailConfirmationDialog( + browser(), base::TimeDelta::FromSeconds(3), + SigninEmailConfirmationDialog::CLOSE)); + observer.WaitForAccountChanges(0, PrimarySyncAccountWait::kWaitForCleared); + + // Check no profile was created. + EXPECT_EQ(profile_manager->GetNumberOfProfiles(), 1U); + EXPECT_EQ(chrome::GetTotalBrowserCount(), 1U); + + // Check Chrome has no accounts. + const AccountsInCookieJarInfo& accounts_in_cookie_jar = + identity_manager()->GetAccountsInCookieJar(); + EXPECT_TRUE(accounts_in_cookie_jar.accounts_are_fresh); + EXPECT_TRUE(accounts_in_cookie_jar.signed_in_accounts.empty()); + EXPECT_TRUE(identity_manager()->GetAccountsWithRefreshTokens().empty()); + EXPECT_FALSE(identity_manager()->HasPrimaryAccount()); +} + } // namespace test } // namespace signin
diff --git a/chrome/browser/sync/test/integration/password_manager_sync_test.cc b/chrome/browser/sync/test/integration/password_manager_sync_test.cc index 59514cf..c53d1da 100644 --- a/chrome/browser/sync/test/integration/password_manager_sync_test.cc +++ b/chrome/browser/sync/test/integration/password_manager_sync_test.cc
@@ -33,12 +33,19 @@ using testing::ElementsAre; using testing::IsEmpty; +using testing::UnorderedElementsAre; MATCHER_P2(MatchesLogin, username, password, "") { return arg->username_value == base::UTF8ToUTF16(username) && arg->password_value == base::UTF8ToUTF16(password); } +MATCHER_P3(MatchesLoginAndRealm, username, password, signon_realm, "") { + return arg->username_value == base::UTF8ToUTF16(username) && + arg->password_value == base::UTF8ToUTF16(password) && + arg->signon_realm == signon_realm; +} + // Note: This helper applies to ChromeOS too, but is currently unused there. So // define it out to prevent a compile error due to the unused function. #if !defined(OS_CHROMEOS) @@ -96,29 +103,60 @@ ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::PASSWORDS)); } + GURL GetWWWOrigin() { + return embedded_test_server()->GetURL("www.example.com", "/"); + } + GURL GetPSLOrigin() { + return embedded_test_server()->GetURL("psl.example.com", "/"); + } + + // Returns a credential for the origin returned by GetWWWOrigin(). autofill::PasswordForm CreateTestPasswordForm(const std::string& username, const std::string& password) { - GURL origin = embedded_test_server()->GetURL("/"); autofill::PasswordForm form; - form.signon_realm = origin.spec(); - form.origin = origin; + form.signon_realm = GetWWWOrigin().spec(); + form.origin = GetWWWOrigin(); form.username_value = base::UTF8ToUTF16(username); form.password_value = base::UTF8ToUTF16(password); form.date_created = base::Time::Now(); return form; } - void AddPasswordToFakeServer(const std::string& username, - const std::string& password) { - passwords_helper::InjectKeystoreEncryptedServerPassword( - CreateTestPasswordForm(username, password), GetFakeServer()); + // Returns a credential for the origin returned by GetPSLOrigin(). + autofill::PasswordForm CreateTestPSLPasswordForm( + const std::string& username, + const std::string& password) { + autofill::PasswordForm form = CreateTestPasswordForm(username, password); + form.signon_realm = GetPSLOrigin().spec(); + form.origin = GetPSLOrigin(); + return form; } - void AddLocalPassword(const std::string& username, - const std::string& password) { + // Adds a credential to the Sync fake server for the origin returned by + // GetWWWOrigin(). + void AddCredentialToFakeServer(const std::string& username, + const std::string& password) { + AddCredentialToFakeServer(CreateTestPasswordForm(username, password)); + } + + // Adds a credential to the Sync fake server. + void AddCredentialToFakeServer(const autofill::PasswordForm& form) { + passwords_helper::InjectKeystoreEncryptedServerPassword(form, + GetFakeServer()); + } + + // Adds a credential to the local store for the origin returned by + // GetWWWOrigin(). + void AddLocalCredential(const std::string& username, + const std::string& password) { + AddLocalCredential(CreateTestPasswordForm(username, password)); + } + + // Adds a credential to the local store. + void AddLocalCredential(const autofill::PasswordForm& form) { scoped_refptr<password_manager::PasswordStore> password_store = passwords_helper::GetPasswordStore(0); - password_store->AddLogin(CreateTestPasswordForm(username, password)); + password_store->AddLogin(form); // Do a roundtrip to the DB thread, to make sure the new password is stored // before doing anything else that might depend on it. GetAllLoginsFromProfilePasswordStore(); @@ -151,7 +189,7 @@ ASSERT_EQ(web_contents, GetBrowser(0)->tab_strip_model()->GetActiveWebContents()); NavigationObserver observer(web_contents); - GURL url = embedded_test_server()->GetURL(path); + GURL url = embedded_test_server()->GetURL("www.example.com", path); ui_test_utils::NavigateToURL(GetBrowser(0), url); observer.Wait(); // After navigation, the password manager retrieves any matching credentials @@ -243,7 +281,7 @@ IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, UpdateInProfileStore) { ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; - AddLocalPassword("user", "localpass"); + AddLocalCredential("user", "localpass"); SetupSyncTransportWithPasswordAccountStorage(); @@ -269,7 +307,7 @@ IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, UpdateInAccountStore) { ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; - AddPasswordToFakeServer("user", "accountpass"); + AddCredentialToFakeServer("user", "accountpass"); SetupSyncTransportWithPasswordAccountStorage(); @@ -296,8 +334,8 @@ UpdateMatchingCredentialInBothStores) { ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; - AddPasswordToFakeServer("user", "pass"); - AddLocalPassword("user", "pass"); + AddCredentialToFakeServer("user", "pass"); + AddLocalCredential("user", "pass"); SetupSyncTransportWithPasswordAccountStorage(); @@ -324,8 +362,8 @@ UpdateMismatchingCredentialInBothStores) { ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; - AddPasswordToFakeServer("user", "accountpass"); - AddLocalPassword("user", "localpass"); + AddCredentialToFakeServer("user", "accountpass"); + AddLocalCredential("user", "localpass"); SetupSyncTransportWithPasswordAccountStorage(); @@ -357,8 +395,8 @@ // Add credentials for the same username, but with different passwords, to the // two stores. - AddPasswordToFakeServer("user", "accountpass"); - AddLocalPassword("user", "localpass"); + AddCredentialToFakeServer("user", "accountpass"); + AddLocalCredential("user", "localpass"); SetupSyncTransportWithPasswordAccountStorage(); @@ -395,8 +433,8 @@ // Add credentials for the same username, but with different passwords, to the // two stores. - AddPasswordToFakeServer("user", "accountpass"); - AddLocalPassword("user", "localpass"); + AddCredentialToFakeServer("user", "accountpass"); + AddLocalCredential("user", "localpass"); SetupSyncTransportWithPasswordAccountStorage(); @@ -422,6 +460,66 @@ EXPECT_THAT(GetAllLoginsFromProfilePasswordStore(), ElementsAre(MatchesLogin("user", "accountpass"))); } + +IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, + AutoUpdatePSLMatchInAccountStoreOnSuccessfulUse) { + ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + + // Add the same credential to both stores, but the account one is a PSL match + // (i.e. it's stored for psl.example.com instead of www.example.com). + AddCredentialToFakeServer(CreateTestPSLPasswordForm("user", "pass")); + AddLocalCredential(CreateTestPasswordForm("user", "pass")); + + SetupSyncTransportWithPasswordAccountStorage(); + + content::WebContents* web_contents = nullptr; + GetNewTab(GetBrowser(0), &web_contents); + + // Go to a form (on www.) and submit it with the saved credentials. + NavigateToFile(web_contents, "/password/simple_password.html"); + FillAndSubmitPasswordForm(web_contents, "user", "pass"); + + // Now the PSL-matched credential should have been automatically saved for + // www. as well (in the account store). + EXPECT_THAT(GetAllLoginsFromAccountPasswordStore(), + UnorderedElementsAre( + MatchesLoginAndRealm("user", "pass", GetWWWOrigin()), + MatchesLoginAndRealm("user", "pass", GetPSLOrigin()))); + // In the profile store, there was already a credential for www. so nothing + // should have changed. + ASSERT_THAT(GetAllLoginsFromProfilePasswordStore(), + ElementsAre(MatchesLogin("user", "pass"))); +} + +IN_PROC_BROWSER_TEST_F(PasswordManagerSyncTest, + AutoUpdatePSLMatchInProfileStoreOnSuccessfulUse) { + ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + + // Add the same credential to both stores, but the local one is a PSL match + // (i.e. it's stored for psl.example.com instead of www.example.com). + AddCredentialToFakeServer(CreateTestPasswordForm("user", "pass")); + AddLocalCredential(CreateTestPSLPasswordForm("user", "pass")); + + SetupSyncTransportWithPasswordAccountStorage(); + + content::WebContents* web_contents = nullptr; + GetNewTab(GetBrowser(0), &web_contents); + + // Go to a form (on www.) and submit it with the saved credentials. + NavigateToFile(web_contents, "/password/simple_password.html"); + FillAndSubmitPasswordForm(web_contents, "user", "pass"); + + // Now the PSL-matched credential should have been automatically saved for + // www. as well (in the profile store). + EXPECT_THAT(GetAllLoginsFromProfilePasswordStore(), + UnorderedElementsAre( + MatchesLoginAndRealm("user", "pass", GetWWWOrigin()), + MatchesLoginAndRealm("user", "pass", GetPSLOrigin()))); + // In the account store, there was already a credential for www. so nothing + // should have changed. + ASSERT_THAT(GetAllLoginsFromAccountPasswordStore(), + ElementsAre(MatchesLogin("user", "pass"))); +} #endif // !defined(OS_CHROMEOS) } // namespace
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index 335edb6..d4185be 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -93,7 +93,7 @@ // change default theme assets, if you need themes to recreate their generated // images (which are cached), or if you changed how missing values are // generated. -const int kThemePackVersion = 74; +const int kThemePackVersion = 75; // IDs that are in the DataPack won't clash with the positive integer // uint16_t. kHeaderID should always have the maximum value because we want the @@ -149,6 +149,8 @@ {PRS::kNtpAttribution, IDR_THEME_NTP_ATTRIBUTION, "theme_ntp_attribution"}, {PRS::kWindowControlBackground, IDR_THEME_WINDOW_CONTROL_BACKGROUND, "theme_window_control_background"}, + + // NOTE! If you make any changes here, please update kThemePackVersion. }; BrowserThemePack::PersistentID GetPersistentIDByName(const std::string& key) { @@ -207,6 +209,8 @@ {"frame_incognito", TP::TINT_FRAME_INCOGNITO}, {"frame_incognito_inactive", TP::TINT_FRAME_INCOGNITO_INACTIVE}, {"background_tab", TP::TINT_BACKGROUND_TAB}, + + // NOTE! If you make any changes here, please update kThemePackVersion. }; const size_t kTintTableLength = base::size(kTintTable); @@ -241,6 +245,8 @@ {"ntp_header", TP::COLOR_NTP_HEADER}, {"ntp_link", TP::COLOR_NTP_LINK}, {"ntp_text", TP::COLOR_NTP_TEXT}, + + // NOTE! If you make any changes here, please update kThemePackVersion. }; constexpr size_t kOverwritableColorTableLength = base::size(kOverwritableColorTable); @@ -258,7 +264,10 @@ TP::COLOR_TOOLBAR_BUTTON_ICON_PRESSED, TP::COLOR_TAB_BACKGROUND_ACTIVE_FRAME_ACTIVE, TP::COLOR_TAB_BACKGROUND_ACTIVE_FRAME_INACTIVE, - TP::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_INACTIVE}; + TP::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_INACTIVE + + // NOTE! If you make any changes here, please update kThemePackVersion. +}; constexpr size_t kNonOverwritableColorTableLength = base::size(kNonOverwritableColorTable); @@ -272,6 +281,8 @@ {"ntp_background_alignment", TP::NTP_BACKGROUND_ALIGNMENT}, {"ntp_background_repeat", TP::NTP_BACKGROUND_TILING}, {"ntp_logo_alternate", TP::NTP_LOGO_ALTERNATE}, + + // NOTE! If you make any changes here, please update kThemePackVersion. }; const size_t kDisplayPropertiesSize = base::size(kDisplayProperties); @@ -677,6 +688,8 @@ DCHECK(extension->is_theme()); DCHECK(!pack->is_valid()); + // NOTE! If you make any changes here, please update kThemePackVersion. + pack->InitEmptyPack(); pack->set_extension_id(extension->id()); pack->SetHeaderId(extension); @@ -794,6 +807,8 @@ // differently. pack->InitSourceImages(); + // NOTE! If you make any changes here, please update kThemePackVersion. + pack->SetColor(TP::COLOR_FRAME_ACTIVE, colors.frame_color); pack->SetColor(TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_ACTIVE, colors.frame_color);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e522eafb..4568bb5 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -128,12 +128,6 @@ "page_info/chrome_page_info_delegate.h", "page_info/chrome_page_info_ui_delegate.cc", "page_info/chrome_page_info_ui_delegate.h", - "page_info/page_info.cc", - "page_info/page_info.h", - "page_info/page_info_delegate.h", - "page_info/page_info_ui.cc", - "page_info/page_info_ui.h", - "page_info/page_info_ui_delegate.h", "passwords/account_avatar_fetcher.cc", "passwords/account_avatar_fetcher.h", "passwords/manage_passwords_state.cc", @@ -834,6 +828,7 @@ "//components/javascript_dialogs/android:jni_headers", "//components/navigation_interception", "//components/optimization_guide/proto:optimization_guide_proto", + "//components/page_info", "//components/page_info/android:android", "//components/subresource_filter/core/browser", "//crypto:platform", @@ -3480,6 +3475,7 @@ "//chrome/common/qr_code_generator", "//components/constrained_window", "//components/media_message_center", + "//components/page_info", "//components/payments/content", "//components/payments/core", "//components/tab_count_metrics",
diff --git a/chrome/browser/ui/android/page_info/connection_info_popup_android.cc b/chrome/browser/ui/android/page_info/connection_info_popup_android.cc index bad3143..dd904fd8 100644 --- a/chrome/browser/ui/android/page_info/connection_info_popup_android.cc +++ b/chrome/browser/ui/android/page_info/connection_info_popup_android.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ui/page_info/chrome_page_info_delegate.h" -#include "chrome/browser/ui/page_info/page_info.h" +#include "components/page_info/page_info.h" #include "components/security_state/core/security_state.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ui/android/page_info/connection_info_popup_android.h b/chrome/browser/ui/android/page_info/connection_info_popup_android.h index 3cee4ed..6a2c206 100644 --- a/chrome/browser/ui/android/page_info/connection_info_popup_android.h +++ b/chrome/browser/ui/android/page_info/connection_info_popup_android.h
@@ -11,7 +11,7 @@ #include "base/android/scoped_java_ref.h" #include "base/macros.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" namespace content { class WebContents;
diff --git a/chrome/browser/ui/android/page_info/page_info_controller_android.cc b/chrome/browser/ui/android/page_info/page_info_controller_android.cc index 3db7efd..6fabd3bb 100644 --- a/chrome/browser/ui/android/page_info/page_info_controller_android.cc +++ b/chrome/browser/ui/android/page_info/page_info_controller_android.cc
@@ -13,12 +13,12 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ui/page_info/chrome_page_info_delegate.h" -#include "chrome/browser/ui/page_info/page_info.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" #include "chrome/common/chrome_features.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/page_info/page_info.h" +#include "components/page_info/page_info_ui.h" #include "components/security_state/core/security_state.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/ui/android/page_info/page_info_controller_android.h b/chrome/browser/ui/android/page_info/page_info_controller_android.h index 294aa00c..b57d821d 100644 --- a/chrome/browser/ui/android/page_info/page_info_controller_android.h +++ b/chrome/browser/ui/android/page_info/page_info_controller_android.h
@@ -12,7 +12,7 @@ #include "base/android/scoped_java_ref.h" #include "base/macros.h" #include "base/optional.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" namespace content { class WebContents;
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc index 34c5e23..fb920f87 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc +++ b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
@@ -6,7 +6,7 @@ #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" -#include "chrome/browser/chromeos/crostini/crostini_registry_service.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/ash/launcher/arc_app_shelf_id.h" @@ -61,8 +61,7 @@ // with the prefix "crostini:". if (proxy && (proxy->AppRegistryCache().GetAppType(app_id) != apps::mojom::AppType::kUnknown || - base::StartsWith(app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE))) { + crostini::IsUnmatchedCrostiniShelfAppId(app_id))) { return true; } @@ -135,8 +134,7 @@ // When Crostini generates shelf id as the app_id, which couldn't match to an // app, the default penguin icon should be loaded. - if (base::StartsWith(app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { + if (crostini::IsUnmatchedCrostiniShelfAppId(app_id)) { apps::mojom::IconKeyPtr icon_key = apps::mojom::IconKey::New(); proxy->LoadIconFromIconKey( apps::mojom::AppType::kCrostini, std::string(), std::move(icon_key),
diff --git a/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc b/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc index f6179e5..c1738e2 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc +++ b/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc
@@ -173,9 +173,8 @@ command_id < ash::USE_LAUNCH_TYPE_COMMAND_END) { auto* provider = web_app::WebAppProvider::Get(profile()); DCHECK(provider); - if (command_id == ash::USE_LAUNCH_TYPE_TABBED_WINDOW) { - return provider->registrar().IsInExperimentalTabbedWindowMode( - app_id()); + if (provider->registrar().IsInExperimentalTabbedWindowMode(app_id())) { + return command_id == ash::USE_LAUNCH_TYPE_TABBED_WINDOW; } web_app::DisplayMode effective_display_mode =
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc index 9a04fc7..6a84ce4 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/chromeos/crostini/crostini_force_close_watcher.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -96,18 +97,20 @@ const AccountId& primary_account_id = user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId(); - crostini::CrostiniRegistryService* registry_service = - crostini::CrostiniRegistryServiceFactory::GetForProfile( - chromeos::ProfileHelper::Get()->GetProfileByAccountId( - primary_account_id)); + Profile* primary_account_profile = + chromeos::ProfileHelper::Get()->GetProfileByAccountId(primary_account_id); // Windows without an application id set will get filtered out here. - const std::string& crostini_shelf_app_id = - registry_service->GetCrostiniShelfAppId( - exo::GetShellApplicationId(window), exo::GetShellStartupId(window)); + const std::string& crostini_shelf_app_id = crostini::GetCrostiniShelfAppId( + primary_account_profile, exo::GetShellApplicationId(window), + exo::GetShellStartupId(window)); if (crostini_shelf_app_id.empty()) return; + crostini::CrostiniRegistryService* registry_service = + crostini::CrostiniRegistryServiceFactory::GetForProfile( + primary_account_profile); + // At this point, all remaining windows are Crostini windows. Firstly, we add // support for forcibly closing it. We use the registration to retrieve the // app's name, but this may be null in the case of apps with no associated @@ -130,8 +133,7 @@ // respective apps take at most another few seconds to start. // Work is ongoing to make this occur as infrequently as possible. // See https://crbug.com/854911. - if (base::StartsWith(shelf_app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { + if (crostini::IsUnmatchedCrostiniShelfAppId(shelf_app_id)) { ChromeLauncherController::instance() ->GetShelfSpinnerController() ->CloseCrostiniSpinners(); @@ -249,14 +251,12 @@ // Currently Crostini can only be used from the primary profile. In the // future, this may be replaced by some way of matching the container that // runs this app with the user that owns it. - const AccountId& primary_account_id = - user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId(); - crostini::CrostiniRegistryService* registry_service = - crostini::CrostiniRegistryServiceFactory::GetForProfile( - chromeos::ProfileHelper::Get()->GetProfileByAccountId( - primary_account_id)); - std::string shelf_app_id = registry_service->GetCrostiniShelfAppId( - exo::GetShellApplicationId(window), exo::GetShellStartupId(window)); + const Profile* primary_account_profile = + chromeos::ProfileHelper::Get()->GetProfileByAccountId( + user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId()); + std::string shelf_app_id = crostini::GetCrostiniShelfAppId( + primary_account_profile, exo::GetShellApplicationId(window), + exo::GetShellStartupId(window)); return shelf_app_id; }
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc index 178011a9..3493297 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/crostini/crostini_features.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" @@ -300,8 +301,7 @@ std::string app_id = update.AppId(); if (proxy_->AppRegistryCache().GetAppType(app_id) == apps::mojom::AppType::kCrostini || - base::StartsWith(app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { + crostini::IsUnmatchedCrostiniShelfAppId(app_id)) { window->SetProperty(aura::client::kAppType, static_cast<int>(ash::AppType::CROSTINI_APP)); }
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc index 34b7f254..87fd4eee 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_shelf_context_menu.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/crostini/crostini_terminal.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager.h" @@ -86,8 +87,7 @@ apps::AppServiceProxyFactory::GetForProfile(controller->profile()); DCHECK(proxy); - if (base::StartsWith(item->id.app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { + if (crostini::IsUnmatchedCrostiniShelfAppId(item->id.app_id)) { // For Crostini app_id with the prefix "crostini:", set app_type as Unknown // to skip the ArcAppShelfId valid. App type can't be set as Crostini, // because the pin item should not be added for it. @@ -207,12 +207,13 @@ case apps::mojom::AppType::kWeb: { auto* provider = web_app::WebAppProvider::Get(controller()->profile()); DCHECK(provider); - if (command_id == ash::LAUNCH_TYPE_TABBED_WINDOW) { - return provider->registrar().IsInExperimentalTabbedWindowMode( - item().id.app_id); - } - if (command_id >= ash::LAUNCH_TYPE_PINNED_TAB && - command_id <= ash::LAUNCH_TYPE_WINDOW) { + if ((command_id >= ash::LAUNCH_TYPE_PINNED_TAB && + command_id <= ash::LAUNCH_TYPE_WINDOW) || + command_id == ash::LAUNCH_TYPE_TABBED_WINDOW) { + if (provider->registrar().IsInExperimentalTabbedWindowMode( + item().id.app_id)) { + return command_id == ash::LAUNCH_TYPE_TABBED_WINDOW; + } web_app::DisplayMode effective_display_mode = provider->registrar().GetAppEffectiveDisplayMode(item().id.app_id); return effective_display_mode != web_app::DisplayMode::kUndefined && @@ -305,8 +306,7 @@ // When Crostini generates shelf id with the prefix "crostini:", AppService // can't generate the menu items, because the app_id doesn't match, so add the // menu items at UI side, based on the app running status. - if (base::StartsWith(item().id.app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { + if (crostini::IsUnmatchedCrostiniShelfAppId(item().id.app_id)) { BuildCrostiniAppMenu(menu_model.get()); }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc index 932f9e3..850d10b7 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -2333,46 +2333,48 @@ chromeos::SpeechMonitor speech_monitor; // Enable ChromeVox. + { ASSERT_FALSE( chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(true); + EXPECT_TRUE(speech_monitor.SkipChromeVoxEnabledMessage()); + + // Disable earcons (https://crbug.com/396507). + const std::string script("ChromeVox.earcons.playEarcon = function() {};"); + extensions::ExtensionHost* host = + extensions::ProcessManager::Get(browser()->profile()) + ->GetBackgroundHostForExtension( + extension_misc::kChromeVoxExtensionId); + ASSERT_TRUE(content::ExecuteScript(host->host_contents(), script)); + } ash::RootWindowController* controller = ash::Shell::GetRootWindowControllerWithDisplayId( display::Screen::GetScreen()->GetPrimaryDisplay().id()); + + // Gesture tap at the home button. views::View* home_button = ash::ShelfTestApi().GetHomeButton(); ui::test::EventGenerator event_generator(controller->GetRootWindow()); - auto* generator_ptr = &event_generator; + event_generator.GestureTapAt(home_button->GetBoundsInScreen().CenterPoint()); - // Wait for ChromeVox to start reading anything. - speech_monitor.ExpectSpeechPattern("*"); - speech_monitor.Call([generator_ptr, home_button]() { - // Gesture tap at the home button. - generator_ptr->GestureTapAt(home_button->GetBoundsInScreen().CenterPoint()); - }); - speech_monitor.ExpectSpeech("Launcher"); - speech_monitor.ExpectSpeech("Button"); - speech_monitor.ExpectSpeech("Shelf"); - speech_monitor.ExpectSpeech("Tool bar"); - speech_monitor.ExpectSpeech(", window"); + ASSERT_EQ("Launcher", speech_monitor.GetNextUtterance()); + ASSERT_EQ("Button", speech_monitor.GetNextUtterance()); + ASSERT_EQ("Shelf", speech_monitor.GetNextUtterance()); + ASSERT_EQ("Tool bar", speech_monitor.GetNextUtterance()); + ASSERT_EQ(", window", speech_monitor.GetNextUtterance()); - speech_monitor.Call([controller]() { - // Hotseat is expected to be extended if spoken feedback is enabled. - ASSERT_EQ(ash::HotseatState::kExtended, - controller->shelf()->shelf_layout_manager()->hotseat_state()); - }); + // Hotseat is expected to be extended if spoken feedback is enabled. + ASSERT_EQ(ash::HotseatState::kExtended, + controller->shelf()->shelf_layout_manager()->hotseat_state()); - speech_monitor.Call([generator_ptr]() { - // Press the search + right. Expects that the browser icon receives the - // accessibility focus and the hotseat remains in kExtended state. - generator_ptr->PressKey(ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN); - }); + // Press the search + right. Expects that the browser icon receives the + // accessibility focus and the hotseat remains in kExtended state. + event_generator.PressKey(ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN); const int browser_index = ash::ShelfModel::Get()->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT); - speech_monitor.ExpectSpeech( - base::UTF16ToASCII(ash::ShelfModel::Get()->items()[browser_index].title)); - speech_monitor.Replay(); - + EXPECT_EQ( + base::UTF16ToASCII(ash::ShelfModel::Get()->items()[browser_index].title), + speech_monitor.GetNextUtterance()); EXPECT_EQ(ash::HotseatState::kExtended, controller->shelf()->shelf_layout_manager()->hotseat_state());
diff --git a/chrome/browser/ui/ash/launcher/crostini_app_window_shelf_controller.cc b/chrome/browser/ui/ash/launcher/crostini_app_window_shelf_controller.cc index 01653ce5..1392d08c 100644 --- a/chrome/browser/ui/ash/launcher/crostini_app_window_shelf_controller.cc +++ b/chrome/browser/ui/ash/launcher/crostini_app_window_shelf_controller.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/chromeos/crostini/crostini_force_close_watcher.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -208,16 +209,20 @@ const AccountId& primary_account_id = user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId(); - crostini::CrostiniRegistryService* registry_service = - crostini::CrostiniRegistryServiceFactory::GetForProfile( - chromeos::ProfileHelper::Get()->GetProfileByAccountId( - primary_account_id)); - const std::string& shelf_app_id = registry_service->GetCrostiniShelfAppId( - exo::GetShellApplicationId(window), exo::GetShellStartupId(window)); + Profile* primary_account_profile = + chromeos::ProfileHelper::Get()->GetProfileByAccountId(primary_account_id); + + const std::string& shelf_app_id = crostini::GetCrostiniShelfAppId( + primary_account_profile, exo::GetShellApplicationId(window), + exo::GetShellStartupId(window)); // Windows without an application id set will get filtered out here. if (shelf_app_id.empty()) return; + crostini::CrostiniRegistryService* registry_service = + crostini::CrostiniRegistryServiceFactory::GetForProfile( + primary_account_profile); + // At this point, all remaining windows are Crostini windows. Firstly, we add // support for forcibly closing it. We use the registration to retrieve the // app's name, but this may be null in the case of apps with no associated @@ -240,8 +245,7 @@ // respective apps take at most another few seconds to start. // Work is ongoing to make this occur as infrequently as possible. // See https://crbug.com/854911. - if (base::StartsWith(shelf_app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { + if (crostini::IsUnmatchedCrostiniShelfAppId(shelf_app_id)) { owner()->GetShelfSpinnerController()->CloseCrostiniSpinners(); }
diff --git a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc index 04dd788..846ab98 100644 --- a/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc +++ b/chrome/browser/ui/ash/launcher/launcher_controller_helper.cc
@@ -14,8 +14,7 @@ #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/session/arc_session_manager.h" #include "chrome/browser/chromeos/crostini/crostini_features.h" -#include "chrome/browser/chromeos/crostini/crostini_registry_service.h" -#include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/extensions/extension_service.h" @@ -228,8 +227,7 @@ bool LauncherControllerHelper::IsValidIDFromAppService( const std::string& app_id) const { - if (base::StartsWith(app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE)) { + if (crostini::IsUnmatchedCrostiniShelfAppId(app_id)) { return true; }
diff --git a/chrome/browser/ui/ash/launcher/shelf_context_menu.cc b/chrome/browser/ui/ash/launcher/shelf_context_menu.cc index 1fee29a..c6ed3bb 100644 --- a/chrome/browser/ui/ash/launcher/shelf_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/shelf_context_menu.cc
@@ -13,8 +13,7 @@ #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" -#include "chrome/browser/chromeos/crostini/crostini_registry_service.h" -#include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" @@ -71,12 +70,10 @@ // AppServiceShelfContextMenu supports context menus for apps registered in // AppService, Arc shortcuts and Crostini apps with the prefix "crostini:". - if (proxy && - (proxy->AppRegistryCache().GetAppType(item->id.app_id) != - apps::mojom::AppType::kUnknown || - base::StartsWith(item->id.app_id, crostini::kCrostiniAppIdPrefix, - base::CompareCase::SENSITIVE) || - arc::IsArcItem(controller->profile(), item->id.app_id))) { + if (proxy && (proxy->AppRegistryCache().GetAppType(item->id.app_id) != + apps::mojom::AppType::kUnknown || + crostini::IsUnmatchedCrostiniShelfAppId(item->id.app_id) || + arc::IsArcItem(controller->profile(), item->id.app_id))) { return std::make_unique<AppServiceShelfContextMenu>(controller, item, display_id); } @@ -91,11 +88,7 @@ return std::make_unique<ArcShelfContextMenu>(controller, item, display_id); // Use CrostiniShelfContextMenu for crostini apps and Terminal System App. - crostini::CrostiniRegistryService* crostini_registry_service = - crostini::CrostiniRegistryServiceFactory::GetForProfile( - controller->profile()); - if ((crostini_registry_service && - crostini_registry_service->IsCrostiniShelfAppId(item->id.app_id)) || + if (crostini::IsCrostiniShelfAppId(controller->profile(), item->id.app_id) || item->id.app_id == crostini::kCrostiniTerminalSystemAppId) { return std::make_unique<CrostiniShelfContextMenu>(controller, item, display_id);
diff --git a/chrome/browser/ui/ash/launcher/shelf_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/shelf_context_menu_unittest.cc index b696967..81ea1a1 100644 --- a/chrome/browser/ui/ash/launcher/shelf_context_menu_unittest.cc +++ b/chrome/browser/ui/ash/launcher/shelf_context_menu_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/crostini/crostini_test_helper.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" @@ -634,9 +635,8 @@ const std::string fake_window_app_id = "foo"; const std::string fake_window_startup_id = "bar"; - const std::string app_id = - crostini::CrostiniRegistryServiceFactory::GetForProfile(profile()) - ->GetCrostiniShelfAppId(&fake_window_app_id, &fake_window_startup_id); + const std::string app_id = crostini::GetCrostiniShelfAppId( + profile(), &fake_window_app_id, &fake_window_startup_id); controller()->PinAppWithID(app_id); const ash::ShelfItem* item = controller()->GetItem(ash::ShelfID(app_id)); ASSERT_TRUE(item);
diff --git a/chrome/browser/ui/ash/launcher/shelf_spinner_controller.cc b/chrome/browser/ui/ash/launcher/shelf_spinner_controller.cc index 290e1556..c5fab7ea 100644 --- a/chrome/browser/ui/ash/launcher/shelf_spinner_controller.cc +++ b/chrome/browser/ui/ash/launcher/shelf_spinner_controller.cc
@@ -9,9 +9,9 @@ #include "ash/public/cpp/shelf_model.h" #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/chromeos/crostini/crostini_registry_service.h" -#include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/launcher/shelf_spinner_item_controller.h" #include "components/user_manager/user_manager.h" @@ -232,12 +232,11 @@ void ShelfSpinnerController::CloseCrostiniSpinners() { std::vector<std::string> app_ids_to_close; - crostini::CrostiniRegistryService* registry_service = - crostini::CrostiniRegistryServiceFactory::GetForProfile( - chromeos::ProfileHelper::Get()->GetProfileByAccountId( - current_account_id_)); + const Profile* profile = + chromeos::ProfileHelper::Get()->GetProfileByAccountId( + current_account_id_); for (const auto& app_id_controller_pair : app_controller_map_) { - if (registry_service->IsCrostiniShelfAppId(app_id_controller_pair.first)) + if (crostini::IsCrostiniShelfAppId(profile, app_id_controller_pair.first)) app_ids_to_close.push_back(app_id_controller_pair.first); } for (const auto& app_id : app_ids_to_close)
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model.cc b/chrome/browser/ui/content_settings/content_setting_image_model.cc index de103df3..acd86aa 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model.cc
@@ -224,9 +224,10 @@ const ContentSettingsImageDetails kImageDetails[] = { {ContentSettingsType::COOKIES, vector_icons::kCookieIcon, IDS_BLOCKED_COOKIES_MESSAGE, 0, IDS_ACCESSED_COOKIES_MESSAGE}, - {ContentSettingsType::IMAGES, kPhotoIcon, IDS_BLOCKED_IMAGES_MESSAGE, 0, 0}, - {ContentSettingsType::JAVASCRIPT, kCodeIcon, IDS_BLOCKED_JAVASCRIPT_MESSAGE, - 0, 0}, + {ContentSettingsType::IMAGES, vector_icons::kPhotoIcon, + IDS_BLOCKED_IMAGES_MESSAGE, 0, 0}, + {ContentSettingsType::JAVASCRIPT, vector_icons::kCodeIcon, + IDS_BLOCKED_JAVASCRIPT_MESSAGE, 0, 0}, {ContentSettingsType::PLUGINS, vector_icons::kExtensionIcon, IDS_BLOCKED_PLUGINS_MESSAGE, IDS_BLOCKED_PLUGIN_EXPLANATORY_TEXT, 0}, {ContentSettingsType::MIXEDSCRIPT, kMixedContentIcon, @@ -234,8 +235,8 @@ {ContentSettingsType::PPAPI_BROKER, vector_icons::kExtensionIcon, IDS_BLOCKED_PPAPI_BROKER_MESSAGE, 0, IDS_ALLOWED_PPAPI_BROKER_MESSAGE}, {ContentSettingsType::SOUND, kTabAudioIcon, IDS_BLOCKED_SOUND_TITLE, 0, 0}, - {ContentSettingsType::ADS, kAdsIcon, IDS_BLOCKED_ADS_PROMPT_TOOLTIP, - IDS_BLOCKED_ADS_PROMPT_TITLE, 0}, + {ContentSettingsType::ADS, vector_icons::kAdsIcon, + IDS_BLOCKED_ADS_PROMPT_TOOLTIP, IDS_BLOCKED_ADS_PROMPT_TITLE, 0}, }; const ContentSettingsImageDetails* GetImageDetails(ContentSettingsType type) { @@ -456,7 +457,7 @@ if (type == ContentSettingsType::PPAPI_BROKER) badge_id = &kWarningBadgeIcon; else if (content_settings->IsContentBlocked(type)) - badge_id = &kBlockedBadgeIcon; + badge_id = &vector_icons::kBlockedBadgeIcon; const gfx::VectorIcon* icon = &image_details->icon; // Touch mode uses a different tab audio icon. @@ -494,7 +495,8 @@ usages_state.GetDetailedInfo(nullptr, &state_flags); bool allowed = !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED); - set_icon(kMyLocationIcon, allowed ? gfx::kNoneIcon : kBlockedBadgeIcon); + set_icon(kMyLocationIcon, + allowed ? gfx::kNoneIcon : vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(allowed ? IDS_GEOLOCATION_ALLOWED_TOOLTIP : IDS_GEOLOCATION_BLOCKED_TOOLTIP)); @@ -546,7 +548,7 @@ bool allowed = !!(state_flags & ContentSettingsUsagesState::TABSTATE_HAS_ANY_ALLOWED); set_icon(vector_icons::kMidiIcon, - allowed ? gfx::kNoneIcon : kBlockedBadgeIcon); + allowed ? gfx::kNoneIcon : vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(allowed ? IDS_MIDI_SYSEX_ALLOWED_TOOLTIP : IDS_MIDI_SYSEX_BLOCKED_TOOLTIP)); @@ -571,12 +573,13 @@ switch (download_request_limiter->GetDownloadUiStatus(web_contents)) { case DownloadRequestLimiter::DOWNLOAD_UI_ALLOWED: - set_icon(kFileDownloadIcon, gfx::kNoneIcon); + set_icon(vector_icons::kFileDownloadIcon, gfx::kNoneIcon); set_explanatory_string_id(0); set_tooltip(l10n_util::GetStringUTF16(IDS_ALLOWED_DOWNLOAD_TITLE)); return true; case DownloadRequestLimiter::DOWNLOAD_UI_BLOCKED: - set_icon(kFileDownloadIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kFileDownloadIcon, + vector_icons::kBlockedBadgeIcon); set_explanatory_string_id(IDS_BLOCKED_DOWNLOADS_EXPLANATION); set_tooltip(l10n_util::GetStringUTF16(IDS_BLOCKED_DOWNLOAD_TITLE)); return true; @@ -607,7 +610,7 @@ return false; set_icon(vector_icons::kContentPasteIcon, - allowed ? gfx::kNoneIcon : kBlockedBadgeIcon); + allowed ? gfx::kNoneIcon : vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16( allowed ? IDS_ALLOWED_CLIPBOARD_MESSAGE : IDS_BLOCKED_CLIPBOARD_MESSAGE)); return true; @@ -645,11 +648,11 @@ if (IsCamAccessed() && IsMicAccessed()) { if (IsCameraBlockedOnSiteLevel() || IsMicBlockedOnSiteLevel()) { - set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kVideocamIcon, vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_BLOCKED)); } else if (DidCameraAccessFailBecauseOfSystemLevelBlock() || DidMicAccessFailBecauseOfSystemLevelBlock()) { - set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kVideocamIcon, vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_BLOCKED)); if (content_settings->camera_was_just_granted_on_site_level() || content_settings->mic_was_just_granted_on_site_level()) { @@ -669,10 +672,10 @@ if (IsCamAccessed()) { if (IsCameraBlockedOnSiteLevel()) { - set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kVideocamIcon, vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED)); } else if (DidCameraAccessFailBecauseOfSystemLevelBlock()) { - set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kVideocamIcon, vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED)); if (content_settings->camera_was_just_granted_on_site_level()) { set_should_auto_open_bubble(true); @@ -688,10 +691,10 @@ if (IsMicAccessed()) { if (IsMicBlockedOnSiteLevel()) { - set_icon(vector_icons::kMicIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kMicIcon, vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_BLOCKED)); } else if (DidMicAccessFailBecauseOfSystemLevelBlock()) { - set_icon(vector_icons::kMicIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kMicIcon, vector_icons::kBlockedBadgeIcon); set_tooltip(l10n_util::GetStringUTF16(IDS_MICROPHONE_BLOCKED)); if (content_settings->mic_was_just_granted_on_site_level()) { set_should_auto_open_bubble(true); @@ -711,7 +714,7 @@ int id = IDS_CAMERA_BLOCKED; if (IsMicBlockedOnSiteLevel() || IsCameraBlockedOnSiteLevel()) { - set_icon(vector_icons::kVideocamIcon, kBlockedBadgeIcon); + set_icon(vector_icons::kVideocamIcon, vector_icons::kBlockedBadgeIcon); if (IsMicAccessed()) id = IsCamAccessed() ? IDS_MICROPHONE_CAMERA_BLOCKED : IDS_MICROPHONE_BLOCKED; @@ -790,7 +793,7 @@ if (!FramebustBlockTabHelper::FromWebContents(web_contents)->HasBlockedUrls()) return false; - set_icon(kBlockedRedirectIcon, kBlockedBadgeIcon); + set_icon(kBlockedRedirectIcon, vector_icons::kBlockedBadgeIcon); set_explanatory_string_id(IDS_REDIRECT_BLOCKED_TITLE); set_tooltip(l10n_util::GetStringUTF16(IDS_REDIRECT_BLOCKED_TOOLTIP)); return true; @@ -832,7 +835,8 @@ return false; } - set_icon(kSensorsIcon, !blocked ? gfx::kNoneIcon : kBlockedBadgeIcon); + set_icon(vector_icons::kSensorsIcon, + !blocked ? gfx::kNoneIcon : vector_icons::kBlockedBadgeIcon); if (base::FeatureList::IsEnabled(features::kGenericSensorExtraClasses)) { set_tooltip(l10n_util::GetStringUTF16( !blocked ? IDS_SENSORS_ALLOWED_TOOLTIP : IDS_SENSORS_BLOCKED_TOOLTIP)); @@ -856,7 +860,7 @@ TabSpecificContentSettings::FromWebContents(web_contents); if (!content_settings || !content_settings->IsContentBlocked(content_type())) return false; - set_icon(kWebIcon, kBlockedBadgeIcon); + set_icon(kWebIcon, vector_icons::kBlockedBadgeIcon); set_explanatory_string_id(IDS_BLOCKED_POPUPS_EXPLANATORY_TEXT); set_tooltip(l10n_util::GetStringUTF16(IDS_BLOCKED_POPUPS_TOOLTIP)); return true;
diff --git a/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm b/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm index b55023c..eddbd217 100644 --- a/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm +++ b/chrome/browser/ui/content_settings/content_setting_media_image_model_unittest.mm
@@ -9,7 +9,6 @@ #include "base/mac/mac_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" -#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/content_settings/tab_specific_content_settings.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h" @@ -22,6 +21,7 @@ #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "components/prefs/pref_service.h" +#include "components/vector_icons/vector_icons.h" #include "content/public/test/web_contents_tester.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" @@ -103,10 +103,10 @@ l10n_util::GetStringUTF16(IDS_CAMERA_ACCESSED), 0, &gfx::kNoneIcon); auth_wrapper.SetMockMediaPermissionStatus(kDenied); content_setting_image_model->Update(web_contents()); - ExpectImageModelState(*content_setting_image_model, true /*is_visible*/, - true /*has_icon*/, - l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED), - IDS_CAMERA_TURNED_OFF, &kBlockedBadgeIcon); + ExpectImageModelState( + *content_setting_image_model, true /*is_visible*/, true /*has_icon*/, + l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED), IDS_CAMERA_TURNED_OFF, + &vector_icons::kBlockedBadgeIcon); auth_wrapper.SetMockMediaPermissionStatus(kNotDetermined); content_setting_image_model->Update(web_contents()); EXPECT_FALSE(content_setting_image_model->is_visible()); @@ -127,7 +127,7 @@ ExpectImageModelState(*content_setting_image_model, true /*is_visible*/, true /*has_icon*/, l10n_util::GetStringUTF16(IDS_MICROPHONE_BLOCKED), - IDS_MIC_TURNED_OFF, &kBlockedBadgeIcon); + IDS_MIC_TURNED_OFF, &vector_icons::kBlockedBadgeIcon); auth_wrapper.SetMockMediaPermissionStatus(kNotDetermined); content_setting_image_model->Update(web_contents()); EXPECT_FALSE(content_setting_image_model->is_visible()); @@ -153,7 +153,7 @@ ExpectImageModelState( *content_setting_image_model, true /*is_visible*/, true /*has_icon*/, l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_BLOCKED), - IDS_CAMERA_TURNED_OFF, &kBlockedBadgeIcon); + IDS_CAMERA_TURNED_OFF, &vector_icons::kBlockedBadgeIcon); auth_wrapper.SetMockMediaPermissionStatus(kNotDetermined); auth_wrapper.SetMockMediaPermissionStatus(kNotDetermined); content_setting_image_model->Update(web_contents()); @@ -176,9 +176,10 @@ GetDefaultAudioDevice(), GetDefaultVideoDevice(), std::string(), std::string()); content_setting_image_model->Update(web_contents()); - ExpectImageModelState( - *content_setting_image_model, true /*is_visible*/, true /*has_icon*/, - l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED), 0, &kBlockedBadgeIcon); + ExpectImageModelState(*content_setting_image_model, true /*is_visible*/, + true /*has_icon*/, + l10n_util::GetStringUTF16(IDS_CAMERA_BLOCKED), 0, + &vector_icons::kBlockedBadgeIcon); } // Microphone blocked per site. @@ -193,7 +194,7 @@ ExpectImageModelState(*content_setting_image_model, true /*is_visible*/, true /*has_icon*/, l10n_util::GetStringUTF16(IDS_MICROPHONE_BLOCKED), - 0, &kBlockedBadgeIcon); + 0, &vector_icons::kBlockedBadgeIcon); } // Microphone & camera blocked per site @@ -210,7 +211,7 @@ ExpectImageModelState( *content_setting_image_model, true /*is_visible*/, true /*has_icon*/, l10n_util::GetStringUTF16(IDS_MICROPHONE_CAMERA_BLOCKED), 0, - &kBlockedBadgeIcon); + &vector_icons::kBlockedBadgeIcon); } } }
diff --git a/chrome/browser/ui/page_info/chrome_page_info_delegate.h b/chrome/browser/ui/page_info/chrome_page_info_delegate.h index dad2560..9f38fd7 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_delegate.h +++ b/chrome/browser/ui/page_info/chrome_page_info_delegate.h
@@ -7,7 +7,7 @@ #include "build/build_config.h" #include "chrome/browser/content_settings/local_shared_objects_container.h" -#include "chrome/browser/ui/page_info/page_info_delegate.h" +#include "components/page_info/page_info_delegate.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" #include "url/gurl.h"
diff --git a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h index 05317cc..674ef665 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h +++ b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h
@@ -6,7 +6,7 @@ #define CHROME_BROWSER_UI_PAGE_INFO_CHROME_PAGE_INFO_UI_DELEGATE_H_ #include "build/build_config.h" -#include "chrome/browser/ui/page_info/page_info_ui_delegate.h" +#include "components/page_info/page_info_ui_delegate.h" class Profile;
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc index bce9a87..034d799 100644 --- a/chrome/browser/ui/page_info/page_info_unittest.cc +++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/page_info/page_info.h" +#include "components/page_info/page_info.h" #include <memory> #include <set> @@ -23,7 +23,6 @@ #include "chrome/browser/ssl/tls_deprecation_test_utils.h" #include "chrome/browser/ui/page_info/chrome_page_info_delegate.h" #include "chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/common/chrome_features.h" @@ -33,6 +32,7 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/infobars/core/infobar.h" +#include "components/page_info/page_info_ui.h" #include "components/safe_browsing/buildflags.h" #include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h" #include "components/security_state/core/features.h"
diff --git a/chrome/browser/ui/page_info/permission_menu_model.h b/chrome/browser/ui/page_info/permission_menu_model.h index 1a406a8..6fb08ae1 100644 --- a/chrome/browser/ui/page_info/permission_menu_model.h +++ b/chrome/browser/ui/page_info/permission_menu_model.h
@@ -6,9 +6,9 @@ #define CHROME_BROWSER_UI_PAGE_INFO_PERMISSION_MENU_MODEL_H_ #include "base/macros.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/page_info/page_info_ui.h" #include "ui/base/models/simple_menu_model.h" #include "url/gurl.h"
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc b/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc index a63d959..1e296d5 100644 --- a/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc +++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc
@@ -15,6 +15,7 @@ #include "chrome/grit/generated_resources.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/strings/grit/components_strings.h" +#include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/paint_vector_icon.h" @@ -135,7 +136,7 @@ ManageMigrationUiController* controller = GetController(); if (controller && controller->GetFlowStep() == LocalCardMigrationFlowStep::MIGRATION_FAILED) { - return kBlockedBadgeIcon; + return vector_icons::kBlockedBadgeIcon; } return gfx::kNoneIcon; }
diff --git a/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc b/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc index 92ad7cd..b9ed9cc 100644 --- a/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc +++ b/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc
@@ -14,6 +14,7 @@ #include "chrome/grit/generated_resources.h" #include "components/autofill/core/common/autofill_payments_features.h" #include "components/strings/grit/components_strings.h" +#include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/paint_vector_icon.h" @@ -81,7 +82,7 @@ const gfx::VectorIcon& SavePaymentIconView::GetVectorIconBadge() const { SavePaymentIconController* controller = GetController(); if (controller && controller->ShouldShowSaveFailureBadge()) - return kBlockedBadgeIcon; + return vector_icons::kBlockedBadgeIcon; return gfx::kNoneIcon; }
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc index c817c73..f807bbf 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.cc +++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -241,7 +241,8 @@ *item_icon, CONTEXT_BODY_TEXT_SMALL, views::style::STYLE_PRIMARY); item_icon->SetImage(CreateVectorIconWithBadge( *item.image, GetLayoutConstant(LOCATION_BAR_ICON_SIZE), icon_color, - item.has_blocked_badge ? kBlockedBadgeIcon : gfx::kNoneIcon)); + item.has_blocked_badge ? vector_icons::kBlockedBadgeIcon + : gfx::kNoneIcon)); } std::unique_ptr<views::View> item_contents;
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc b/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc index ea10050..18e89b56 100644 --- a/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc +++ b/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc
@@ -111,7 +111,7 @@ } const gfx::VectorIcon& NativeFileSystemAccessIconView::GetVectorIcon() const { - return has_write_access_ ? kSaveOriginalFileIcon + return has_write_access_ ? vector_icons::kSaveOriginalFileIcon : vector_icons::kInsertDriveFileOutlineIcon; }
diff --git a/chrome/browser/ui/views/page_info/chosen_object_view.cc b/chrome/browser/ui/views/page_info/chosen_object_view.cc index 7c5d43c..07f5478c 100644 --- a/chrome/browser/ui/views/page_info/chosen_object_view.cc +++ b/chrome/browser/ui/views/page_info/chosen_object_view.cc
@@ -7,11 +7,11 @@ #include <memory> #include <utility> -#include "chrome/browser/ui/page_info/page_info_delegate.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/page_info/chosen_object_view_observer.h" #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h" +#include "components/page_info/page_info_delegate.h" #include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/chrome/browser/ui/views/page_info/chosen_object_view.h b/chrome/browser/ui/views/page_info/chosen_object_view.h index 7e50cf2..92bbe43 100644 --- a/chrome/browser/ui/views/page_info/chosen_object_view.h +++ b/chrome/browser/ui/views/page_info/chosen_object_view.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/strings/string16.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" #include "ui/views/controls/button/button.h" #include "ui/views/view.h"
diff --git a/chrome/browser/ui/views/page_info/chosen_object_view_observer.h b/chrome/browser/ui/views/page_info/chosen_object_view_observer.h index 636415c4..b3db127 100644 --- a/chrome/browser/ui/views/page_info/chosen_object_view_observer.h +++ b/chrome/browser/ui/views/page_info/chosen_object_view_observer.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_VIEWS_PAGE_INFO_CHOSEN_OBJECT_VIEW_OBSERVER_H_ #define CHROME_BROWSER_UI_VIEWS_PAGE_INFO_CHOSEN_OBJECT_VIEW_OBSERVER_H_ -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" class ChosenObjectViewObserver { public:
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index 0e095ba2..68f826e 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -27,7 +27,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/page_info/chrome_page_info_delegate.h" -#include "chrome/browser/ui/page_info/page_info.h" #include "chrome/browser/ui/page_info/page_info_dialog.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/view_ids.h" @@ -49,6 +48,7 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "components/dom_distiller/core/url_constants.h" #include "components/dom_distiller/core/url_utils.h" +#include "components/page_info/page_info.h" #include "components/safe_browsing/buildflags.h" #include "components/strings/grit/components_chromium_strings.h" #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h index 466f205..d1bfbf3 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -14,7 +14,6 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/reputation/safety_tip_ui.h" #include "chrome/browser/ui/page_info/page_info_dialog.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" #include "chrome/browser/ui/views/bubble_anchor_util_views.h" #include "chrome/browser/ui/views/hover_button.h" #include "chrome/browser/ui/views/page_info/chosen_object_view_observer.h" @@ -22,6 +21,7 @@ #include "chrome/browser/ui/views/page_info/page_info_hover_button.h" #include "chrome/browser/ui/views/page_info/permission_selector_row.h" #include "chrome/browser/ui/views/page_info/permission_selector_row_observer.h" +#include "components/page_info/page_info_ui.h" #include "components/safe_browsing/buildflags.h" #include "components/security_state/core/security_state.h" #include "ui/gfx/native_widget_types.h"
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_base.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_base.cc index ef61d91c..f0d7e3d 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_base.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_base.cc
@@ -6,7 +6,7 @@ #include "base/strings/string16.h" #include "chrome/browser/ui/page_info/page_info_dialog.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "ui/base/buildflags.h"
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_base.h b/chrome/browser/ui/views/page_info/page_info_bubble_view_base.h index 6529dd4..49e1e50 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_base.h +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_base.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_VIEWS_PAGE_INFO_PAGE_INFO_BUBBLE_VIEW_BASE_H_ #define CHROME_BROWSER_UI_VIEWS_PAGE_INFO_PAGE_INFO_BUBBLE_VIEW_BASE_H_ -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" #include "content/public/browser/web_contents_observer.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h"
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc index f54d281..c463423 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/page_info/page_info.h" #include "chrome/browser/ui/page_info/page_info_dialog.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/test/test_browser_dialog.h" @@ -28,6 +27,7 @@ #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/page_info/page_info.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/safe_browsing/content/password_protection/metrics_util.h" #include "components/safe_browsing/core/features.h"
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.cc b/chrome/browser/ui/views/page_info/permission_selector_row.cc index b36361b1..89a12de7 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row.cc +++ b/chrome/browser/ui/views/page_info/permission_selector_row.cc
@@ -9,12 +9,12 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" #include "chrome/browser/ui/page_info/permission_menu_model.h" #include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h" +#include "components/page_info/page_info_ui.h" #include "components/strings/grit/components_strings.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.h b/chrome/browser/ui/views/page_info/permission_selector_row.h index 14d22086..bd6850c1 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row.h +++ b/chrome/browser/ui/views/page_info/permission_selector_row.h
@@ -10,11 +10,11 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/observer_list.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" #include "chrome/browser/ui/page_info/permission_menu_model.h" #include "chrome/browser/ui/views/page_info/permission_selector_row_observer.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/page_info/page_info_ui.h" class Profile;
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row_observer.h b/chrome/browser/ui/views/page_info/permission_selector_row_observer.h index 37685bba..5b579b3 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row_observer.h +++ b/chrome/browser/ui/views/page_info/permission_selector_row_observer.h
@@ -5,7 +5,7 @@ #ifndef CHROME_BROWSER_UI_VIEWS_PAGE_INFO_PERMISSION_SELECTOR_ROW_OBSERVER_H_ #define CHROME_BROWSER_UI_VIEWS_PAGE_INFO_PERMISSION_SELECTOR_ROW_OBSERVER_H_ -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" class PermissionSelectorRowObserver { public:
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc index 862700d8..0582182 100644 --- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc +++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
@@ -19,7 +19,6 @@ #include "content/public/browser/browser_thread.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/l10n/time_format.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/text/bytes_formatting.h" #include "ui/chromeos/devicetype_utils.h" @@ -39,16 +38,6 @@ constexpr int kWindowWidth = 768; constexpr int kWindowHeight = 636; -base::Optional<double> GetFractionComplete(double units_processed, - double total_units) { - if (total_units <= 0) - return base::nullopt; - double fraction_complete = units_processed / total_units; - if (fraction_complete < 0.0 || fraction_complete > 1.0) - return base::nullopt; - return base::make_optional(fraction_complete); -} - } // namespace void plugin_vm::ShowPluginVmInstallerView(Profile* profile) { @@ -120,11 +109,9 @@ upper_container_view->AddChildView(big_message_label_); views::View* message_container_view = new views::View(); - views::BoxLayout* message_container_layout = - message_container_view->SetLayoutManager( - std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical, - gfx::Insets(kMessageHeight - kMessageFontSize, 0, 0, 0))); + message_container_view->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical, + gfx::Insets(kMessageHeight - kMessageFontSize, 0, 0, 0))); upper_container_view->AddChildView(message_container_view); message_label_ = new views::Label(GetMessage(), {kMessageFont}); @@ -132,13 +119,6 @@ message_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); message_container_view->AddChildView(message_label_); - time_left_message_label_ = new views::Label(base::string16(), {kMessageFont}); - time_left_message_label_->SetEnabledColor(gfx::kGoogleGrey700); - time_left_message_label_->SetMultiLine(false); - time_left_message_label_->SetHorizontalAlignment(gfx::ALIGN_RIGHT); - message_container_view->AddChildView(time_left_message_label_); - message_container_layout->SetFlexForView(time_left_message_label_, 1); - progress_bar_ = new views::ProgressBar(kProgressBarHeight); progress_bar_->SetProperty( views::kMarginsKey, @@ -184,6 +164,12 @@ plugin_vm::PluginVmManager::GetForProfile(profile_)->LaunchPluginVm(); return true; } + if (state_ == State::LOW_DISK_SPACE) { + state_ = State::DOWNLOADING_DLC; + OnStateUpdated(); + plugin_vm_installer_->Continue(); + return false; + } DCHECK_EQ(state_, State::ERROR); // Retry button has been clicked to retry setting of PluginVm environment // after error occurred. @@ -194,6 +180,14 @@ bool PluginVmInstallerView::Cancel() { switch (state_) { case State::STARTING: + case State::CHECKING_DISK_SPACE: + plugin_vm::RecordPluginVmSetupResultHistogram( + plugin_vm::PluginVmSetupResult::kUserCancelledCheckingDiskSpace); + break; + case State::LOW_DISK_SPACE: + plugin_vm::RecordPluginVmSetupResultHistogram( + plugin_vm::PluginVmSetupResult::kUserCancelledLowDiskSpace); + break; case State::DOWNLOADING_DLC: plugin_vm::RecordPluginVmSetupResultHistogram( plugin_vm::PluginVmSetupResult::kUserCancelledDownloadingPluginVmDlc); @@ -226,13 +220,19 @@ return gfx::Size(kWindowWidth, kWindowHeight); } -void PluginVmInstallerView::OnDlcDownloadProgressUpdated( - double progress, - base::TimeDelta elapsed_time) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, State::DOWNLOADING_DLC); +void PluginVmInstallerView::OnProgressUpdated(double fraction_complete) { + progress_bar_->SetValue(fraction_complete); +} - UpdateOperationProgress(progress * 100, 100.0, elapsed_time); +void PluginVmInstallerView::OnCheckedDiskSpace(bool low_disk_space) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_EQ(state_, State::CHECKING_DISK_SPACE); + + if (low_disk_space) + state_ = State::LOW_DISK_SPACE; + else + state_ = State::DOWNLOADING_DLC; + OnStateUpdated(); } void PluginVmInstallerView::OnDlcDownloadCompleted() { @@ -270,10 +270,8 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } -void PluginVmInstallerView::OnDownloadProgressUpdated( - uint64_t bytes_downloaded, - int64_t content_length, - base::TimeDelta elapsed_time) { +void PluginVmInstallerView::OnDownloadProgressUpdated(uint64_t bytes_downloaded, + int64_t content_length) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, State::DOWNLOADING); @@ -281,7 +279,6 @@ GetDownloadProgressMessage(bytes_downloaded, content_length)); download_progress_message_label_->NotifyAccessibilityEvent( ax::mojom::Event::kTextChanged, true); - UpdateOperationProgress(bytes_downloaded, content_length, elapsed_time); } void PluginVmInstallerView::OnDownloadCompleted() { @@ -292,44 +289,6 @@ OnStateUpdated(); } -void PluginVmInstallerView::OnDownloadFailed( - plugin_vm::PluginVmInstaller::FailureReason reason) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - state_ = State::ERROR; - reason_ = reason; - OnStateUpdated(); - - if (reason == plugin_vm::PluginVmInstaller::FailureReason::NOT_ALLOWED) { - plugin_vm::RecordPluginVmSetupResultHistogram( - plugin_vm::PluginVmSetupResult::kPluginVmIsNotAllowed); - } else { - plugin_vm::RecordPluginVmSetupResultHistogram( - plugin_vm::PluginVmSetupResult::kErrorDownloadingPluginVmImage); - } -} - -void PluginVmInstallerView::OnImportProgressUpdated( - int percent_completed, - base::TimeDelta elapsed_time) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK_EQ(state_, State::IMPORTING); - - UpdateOperationProgress(percent_completed, 100.0, elapsed_time); -} - -void PluginVmInstallerView::OnImportFailed( - plugin_vm::PluginVmInstaller::FailureReason reason) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - state_ = State::ERROR; - reason_ = reason; - OnStateUpdated(); - - plugin_vm::RecordPluginVmSetupResultHistogram( - plugin_vm::PluginVmSetupResult::kErrorImportingPluginVmImage); -} - void PluginVmInstallerView::OnImported() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, State::IMPORTING); @@ -356,9 +315,23 @@ setup_start_tick_); } +void PluginVmInstallerView::OnError( + plugin_vm::PluginVmInstaller::FailureReason reason) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + state_ = State::ERROR; + reason_ = reason; + OnStateUpdated(); + + plugin_vm::RecordPluginVmSetupResultHistogram( + plugin_vm::PluginVmSetupResult::kError); +} + base::string16 PluginVmInstallerView::GetBigMessage() const { switch (state_) { case State::STARTING: + case State::CHECKING_DISK_SPACE: + case State::LOW_DISK_SPACE: case State::DOWNLOADING_DLC: case State::CHECKING_VMS: case State::DOWNLOADING: @@ -382,7 +355,15 @@ base::string16 PluginVmInstallerView::GetMessage() const { switch (state_) { + case State::LOW_DISK_SPACE: + return l10n_util::GetStringFUTF16( + IDS_PLUGIN_VM_INSTALLER_LOW_DISK_SPACE_MESSAGE, + ui::FormatBytesWithUnits( + plugin_vm::PluginVmInstaller::kRecommendedFreeDiskSpace, + ui::DATA_UNITS_GIBIBYTE, + /*show_units=*/true)); case State::STARTING: + case State::CHECKING_DISK_SPACE: case State::DOWNLOADING_DLC: case State::CHECKING_VMS: return l10n_util::GetStringUTF16( @@ -449,9 +430,18 @@ case Reason::DLC_NEED_REBOOT: return l10n_util::GetStringUTF16( IDS_PLUGIN_VM_DLC_NEED_REBOOT_FAILED_MESSAGE); + case Reason::INSUFFICIENT_DISK_SPACE: case Reason::DLC_NEED_SPACE: - return l10n_util::GetStringUTF16( - IDS_PLUGIN_VM_DLC_NEED_SPACE_FAILED_MESSAGE); + return l10n_util::GetStringFUTF16( + IDS_PLUGIN_VM_INSUFFICIENT_DISK_SPACE_MESSAGE, + ui::FormatBytesWithUnits( + plugin_vm::PluginVmInstaller::kMinimumFreeDiskSpace, + ui::DATA_UNITS_GIBIBYTE, + /*show_units=*/true), + ui::FormatBytesWithUnits( + plugin_vm::PluginVmInstaller::kRecommendedFreeDiskSpace, + ui::DATA_UNITS_GIBIBYTE, + /*show_units=*/true)); } } } @@ -469,11 +459,14 @@ int PluginVmInstallerView::GetCurrentDialogButtons() const { switch (state_) { case State::STARTING: + case State::CHECKING_DISK_SPACE: case State::DOWNLOADING_DLC: case State::CHECKING_VMS: case State::DOWNLOADING: case State::IMPORTING: return ui::DIALOG_BUTTON_CANCEL; + case State::LOW_DISK_SPACE: + return ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK; case State::IMPORTED: case State::CREATED: return ui::DIALOG_BUTTON_OK; @@ -492,6 +485,7 @@ ui::DialogButton button) const { switch (state_) { case State::STARTING: + case State::CHECKING_DISK_SPACE: case State::DOWNLOADING_DLC: case State::CHECKING_VMS: case State::DOWNLOADING: @@ -504,6 +498,11 @@ DCHECK_EQ(button, ui::DIALOG_BUTTON_OK); return l10n_util::GetStringUTF16(IDS_PLUGIN_VM_INSTALLER_LAUNCH_BUTTON); } + case State::LOW_DISK_SPACE: + return l10n_util::GetStringUTF16( + button == ui::DIALOG_BUTTON_OK + ? IDS_PLUGIN_VM_INSTALLER_CONTINUE_BUTTON + : IDS_APP_CANCEL); case State::ERROR: { DCHECK(reason_); switch (*reason_) { @@ -546,15 +545,10 @@ } const bool progress_bar_visible = - state_ == State::STARTING || state_ == State::DOWNLOADING_DLC || - state_ == State::CHECKING_VMS || state_ == State::DOWNLOADING || - state_ == State::IMPORTING; + state_ == State::STARTING || state_ == State::CHECKING_DISK_SPACE || + state_ == State::DOWNLOADING_DLC || state_ == State::CHECKING_VMS || + state_ == State::DOWNLOADING || state_ == State::IMPORTING; progress_bar_->SetVisible(progress_bar_visible); - // Values outside the range [0,1] display an infinite loading animation. - progress_bar_->SetValue(-1); - - // This will be shown once we receive download/import progress messages. - time_left_message_label_->SetVisible(false); const bool download_progress_message_label_visible = state_ == State::DOWNLOADING; @@ -576,11 +570,8 @@ int64_t content_length) const { DCHECK_EQ(state_, State::DOWNLOADING); - base::Optional<double> fraction_complete = - GetFractionComplete(bytes_downloaded, content_length); - // If download size isn't known |fraction_complete| should be empty. - if (fraction_complete.has_value()) { + if (content_length > 0) { return l10n_util::GetStringFUTF16( IDS_PLUGIN_VM_INSTALLER_DOWNLOAD_PROGRESS_MESSAGE, ui::FormatBytesWithUnits(bytes_downloaded, ui::DATA_UNITS_GIBIBYTE, @@ -595,37 +586,6 @@ } } -void PluginVmInstallerView::UpdateOperationProgress( - double units_processed, - double total_units, - base::TimeDelta elapsed_time) const { - DCHECK(state_ == State::DOWNLOADING_DLC || state_ == State::CHECKING_VMS || - state_ == State::DOWNLOADING || state_ == State::IMPORTING); - - base::Optional<double> maybe_fraction_complete = - GetFractionComplete(units_processed, total_units); - - if (!maybe_fraction_complete || units_processed == 0 || - elapsed_time.is_zero()) { - progress_bar_->SetValue(-1); - time_left_message_label_->SetVisible(false); - return; - } - - const double fraction_complete = *maybe_fraction_complete; - const double fraction_remaining = 1 - fraction_complete; - - progress_bar_->SetValue(fraction_complete); - time_left_message_label_->SetVisible(true); - base::TimeDelta remaining = - fraction_remaining / fraction_complete * elapsed_time; - time_left_message_label_->SetText( - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_REMAINING, - ui::TimeFormat::LENGTH_SHORT, remaining)); - time_left_message_label_->NotifyAccessibilityEvent( - ax::mojom::Event::kTextChanged, true); -} - void PluginVmInstallerView::SetBigMessageLabel() { big_message_label_->SetText(GetBigMessage()); big_message_label_->SetVisible(true); @@ -657,7 +617,8 @@ // retry button is clicked). setup_start_tick_ = base::TimeTicks::Now(); - state_ = State::DOWNLOADING_DLC; + state_ = State::CHECKING_DISK_SPACE; + progress_bar_->SetValue(0); OnStateUpdated(); plugin_vm_installer_->SetObserver(this);
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h index 0c4a148..70355d2 100644 --- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h +++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h
@@ -33,23 +33,16 @@ gfx::Size CalculatePreferredSize() const override; // plugin_vm::PluginVmImageDownload::Observer implementation. - void OnDlcDownloadProgressUpdated(double progress, - base::TimeDelta elapsed_time) override; + void OnProgressUpdated(double fraction_complete) override; + void OnCheckedDiskSpace(bool low_disk_space) override; void OnDlcDownloadCompleted() override; void OnExistingVmCheckCompleted(bool has_vm) override; void OnDownloadProgressUpdated(uint64_t bytes_downloaded, - int64_t content_length, - base::TimeDelta elapsed_time) override; + int64_t content_length) override; void OnDownloadCompleted() override; - void OnDownloadFailed( - plugin_vm::PluginVmInstaller::FailureReason reason) override; - void OnImportProgressUpdated(int percent_completed, - base::TimeDelta elapsed_time) override; void OnCreated() override; void OnImported() override; - void OnImportFailed( - plugin_vm::PluginVmInstaller::FailureReason reason) override; - + void OnError(plugin_vm::PluginVmInstaller::FailureReason reason) override; void OnCancelFinished() override; // Public for testing purposes. @@ -60,8 +53,11 @@ base::OnceCallback<void(bool success)> callback); private: + // TODO(crbug.com/1063748): Re-use PluginVmInstaller::InstallingState. enum class State { - STARTING, // View was just created, installation hasn't yet started + STARTING, // View was just created, installation hasn't yet started + CHECKING_DISK_SPACE, // Checking there is available free disk space. + LOW_DISK_SPACE, // Prompt user to continue or abort due to low disk space. DOWNLOADING_DLC, // PluginVm DLC downloading and installing in progress. CHECKING_VMS, // Checking for existing VMs. DOWNLOADING, // Image download (ISO or VM) is in progress. @@ -82,10 +78,6 @@ base::string16 GetDownloadProgressMessage(uint64_t downlaoded_bytes, int64_t content_length) const; - // Updates the progress bar and shows a time left message if available. - void UpdateOperationProgress(double units_processed, - double total_units, - base::TimeDelta elapsed_time) const; void SetBigMessageLabel(); void SetMessageLabel(); void SetBigImage(); @@ -98,7 +90,6 @@ views::Label* message_label_ = nullptr; views::ProgressBar* progress_bar_ = nullptr; views::Label* download_progress_message_label_ = nullptr; - views::Label* time_left_message_label_ = nullptr; views::ImageView* big_image_ = nullptr; base::TimeTicks setup_start_tick_;
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc index a01603c..e6d785a 100644 --- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc +++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view_browsertest.cc
@@ -227,7 +227,7 @@ histogram_tester_->ExpectUniqueSample( plugin_vm::kPluginVmSetupResultHistogram, - plugin_vm::PluginVmSetupResult::kErrorDownloadingPluginVmImage, 1); + plugin_vm::PluginVmSetupResult::kError, 1); } IN_PROC_BROWSER_TEST_F(PluginVmInstallerViewBrowserTestWithFeatureEnabled, @@ -245,7 +245,7 @@ histogram_tester_->ExpectUniqueSample( plugin_vm::kPluginVmSetupResultHistogram, - plugin_vm::PluginVmSetupResult::kErrorImportingPluginVmImage, 1); + plugin_vm::PluginVmSetupResult::kError, 1); } IN_PROC_BROWSER_TEST_F(PluginVmInstallerViewBrowserTestWithFeatureEnabled, @@ -273,9 +273,9 @@ CheckSetupIsFinishedSuccessfully(); - histogram_tester_->ExpectBucketCount( - plugin_vm::kPluginVmSetupResultHistogram, - plugin_vm::PluginVmSetupResult::kErrorDownloadingPluginVmImage, 1); + histogram_tester_->ExpectBucketCount(plugin_vm::kPluginVmSetupResultHistogram, + plugin_vm::PluginVmSetupResult::kError, + 1); histogram_tester_->ExpectBucketCount(plugin_vm::kPluginVmSetupResultHistogram, plugin_vm::PluginVmSetupResult::kSuccess, 1); @@ -294,5 +294,5 @@ histogram_tester_->ExpectUniqueSample( plugin_vm::kPluginVmSetupResultHistogram, - plugin_vm::PluginVmSetupResult::kPluginVmIsNotAllowed, 1); + plugin_vm::PluginVmSetupResult::kError, 1); }
diff --git a/chrome/browser/ui/views/sharing/sharing_icon_view.cc b/chrome/browser/ui/views/sharing/sharing_icon_view.cc index 5b6579e9..4c5e71e 100644 --- a/chrome/browser/ui/views/sharing/sharing_icon_view.cc +++ b/chrome/browser/ui/views/sharing/sharing_icon_view.cc
@@ -144,7 +144,7 @@ } const gfx::VectorIcon& SharingIconView::GetVectorIconBadge() const { - return should_show_error_ ? kBlockedBadgeIcon : gfx::kNoneIcon; + return should_show_error_ ? vector_icons::kBlockedBadgeIcon : gfx::kNoneIcon; } void SharingIconView::OnExecuting(
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler.cc b/chrome/browser/ui/webui/settings/safety_check_handler.cc index 1024243..1373c1f4 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler.cc +++ b/chrome/browser/ui/webui/settings/safety_check_handler.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/settings/safety_check_handler.h" #include "base/bind.h" +#include "base/i18n/number_formatting.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "base/strings/string16.h" @@ -255,18 +256,20 @@ } void SafetyCheckHandler::OnPasswordsCheckResult(PasswordsStatus status, - int num_compromised) { + Compromised compromised, + Done done, + Total total) { base::DictionaryValue event; event.SetIntKey(kNewState, static_cast<int>(status)); if (status == PasswordsStatus::kCompromisedExist) { - event.SetIntKey(kPasswordsCompromised, num_compromised); + event.SetIntKey(kPasswordsCompromised, compromised.value()); event.SetStringKey( kButtonString, l10n_util::GetPluralStringFUTF16( - IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_BUTTON, num_compromised)); + IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_BUTTON, compromised.value())); } event.SetStringKey(kDisplayString, - GetStringForPasswords(status, num_compromised)); + GetStringForPasswords(status, compromised, done, total)); FireWebUIListener(kPasswordsEvent, event); } @@ -341,17 +344,27 @@ } } -base::string16 SafetyCheckHandler::GetStringForPasswords(PasswordsStatus status, - int num_compromised) { +base::string16 SafetyCheckHandler::GetStringForPasswords( + PasswordsStatus status, + Compromised compromised, + Done done, + Total total) { switch (status) { - case PasswordsStatus::kChecking: - return l10n_util::GetStringUTF16(IDS_SETTINGS_SAFETY_CHECK_RUNNING); + case PasswordsStatus::kChecking: { + // Unable to get progress for some reason. + if (total.value() == 0) { + return l10n_util::GetStringUTF16(IDS_SETTINGS_SAFETY_CHECK_RUNNING); + } + return l10n_util::GetStringFUTF16( + IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_PROGRESS, + base::FormatNumber(done.value()), base::FormatNumber(total.value())); + } case PasswordsStatus::kSafe: return l10n_util::GetStringUTF16( IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_SAFE); case PasswordsStatus::kCompromisedExist: return l10n_util::GetPluralStringFUTF16( - IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_COMPROMISED, num_compromised); + IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_COMPROMISED, compromised.value()); case PasswordsStatus::kOffline: return l10n_util::GetStringUTF16( IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_OFFLINE); @@ -471,7 +484,7 @@ passwords) { OnPasswordsCheckResult(passwords.empty() ? PasswordsStatus::kNoPasswords : PasswordsStatus::kSafe, - 0); + Compromised(0), Done(0), Total(0)); } void SafetyCheckHandler::OnStateChanged( @@ -488,27 +501,32 @@ base::Unretained(this))); } else { OnPasswordsCheckResult(PasswordsStatus::kCompromisedExist, - num_compromised); + Compromised(num_compromised), Done(0), Total(0)); } break; } case BulkLeakCheckService::State::kRunning: - OnPasswordsCheckResult(PasswordsStatus::kChecking, 0); + OnPasswordsCheckResult(PasswordsStatus::kChecking, Compromised(0), + Done(0), Total(0)); // Non-terminal state, so nothing else needs to be done. return; case BulkLeakCheckService::State::kSignedOut: - OnPasswordsCheckResult(PasswordsStatus::kSignedOut, 0); + OnPasswordsCheckResult(PasswordsStatus::kSignedOut, Compromised(0), + Done(0), Total(0)); break; case BulkLeakCheckService::State::kNetworkError: - OnPasswordsCheckResult(PasswordsStatus::kOffline, 0); + OnPasswordsCheckResult(PasswordsStatus::kOffline, Compromised(0), Done(0), + Total(0)); break; case BulkLeakCheckService::State::kQuotaLimit: - OnPasswordsCheckResult(PasswordsStatus::kQuotaLimit, 0); + OnPasswordsCheckResult(PasswordsStatus::kQuotaLimit, Compromised(0), + Done(0), Total(0)); break; case BulkLeakCheckService::State::kTokenRequestFailure: case BulkLeakCheckService::State::kHashingFailure: case BulkLeakCheckService::State::kServiceError: - OnPasswordsCheckResult(PasswordsStatus::kError, 0); + OnPasswordsCheckResult(PasswordsStatus::kError, Compromised(0), Done(0), + Total(0)); break; } @@ -520,8 +538,17 @@ void SafetyCheckHandler::OnCredentialDone( const password_manager::LeakCheckCredential& credential, password_manager::IsLeaked is_leaked) { - // Do nothing because we only want to know the total number of compromised - // credentials at the end of the bulk leak check. + extensions::api::passwords_private::PasswordCheckStatus status = + passwords_delegate_->GetPasswordCheckStatus(); + // Send progress updates only if the check is still running. + if (status.state == + extensions::api::passwords_private::PASSWORD_CHECK_STATE_RUNNING && + status.already_processed && status.remaining_in_queue) { + Done done = Done(*(status.already_processed)); + Total total = Total(*(status.remaining_in_queue) + done.value()); + OnPasswordsCheckResult(PasswordsStatus::kChecking, Compromised(0), done, + total); + } } void SafetyCheckHandler::OnJavascriptAllowed() {}
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler.h b/chrome/browser/ui/webui/settings/safety_check_handler.h index 23b4a092..045bda6 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler.h +++ b/chrome/browser/ui/webui/settings/safety_check_handler.h
@@ -99,6 +99,9 @@ private: // These ensure integers are passed in the correct possitions in the extension // check methods. + using Compromised = util::StrongAlias<class CompromisedTag, int>; + using Done = util::StrongAlias<class DoneTag, int>; + using Total = util::StrongAlias<class TotalTag, int>; using Blocklisted = util::StrongAlias<class BlocklistedTag, int>; using ReenabledUser = util::StrongAlias<class ReenabledUserTag, int>; using ReenabledAdmin = util::StrongAlias<class ReenabledAdminTag, int>; @@ -135,7 +138,10 @@ int64_t update_size, const base::string16& message); void OnSafeBrowsingCheckResult(SafeBrowsingStatus status); - void OnPasswordsCheckResult(PasswordsStatus status, int num_compromised); + void OnPasswordsCheckResult(PasswordsStatus status, + Compromised compromised, + Done done, + Total total); void OnExtensionsCheckResult(ExtensionsStatus status, Blocklisted blocklisted, ReenabledUser reenabled_user, @@ -146,7 +152,9 @@ base::string16 GetStringForUpdates(UpdateStatus status); base::string16 GetStringForSafeBrowsing(SafeBrowsingStatus status); base::string16 GetStringForPasswords(PasswordsStatus status, - int num_compromised); + Compromised compromised, + Done done, + Total total); base::string16 GetStringForExtensions(ExtensionsStatus status, Blocklisted blocklisted, ReenabledUser reenabled_user,
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc index b47be1c..d1e12bf 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/optional.h" +#include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -23,6 +24,7 @@ #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/crx_file/id_util.h" #include "components/password_manager/core/browser/bulk_leak_check_service.h" +#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -98,6 +100,11 @@ state_ = state; } + void SetProgress(int done, int total) { + done_ = done; + total_ = total; + } + std::vector<extensions::api::passwords_private::CompromisedCredential> GetCompromisedCredentials() override { std::vector<extensions::api::passwords_private::CompromisedCredential> @@ -112,12 +119,18 @@ GetPasswordCheckStatus() override { extensions::api::passwords_private::PasswordCheckStatus status; status.state = state_; + if (total_ != 0) { + status.already_processed = std::make_unique<int>(done_); + status.remaining_in_queue = std::make_unique<int>(total_ - done_); + } return status; } private: password_manager::BulkLeakCheckService* leak_service_ = nullptr; int compromised_password_count_ = 0; + int done_ = 0; + int total_ = 0; extensions::api::passwords_private::PasswordCheckState state_ = extensions::api::passwords_private::PASSWORD_CHECK_STATE_IDLE; }; @@ -223,8 +236,11 @@ SafetyCheckHandlerTest::GetSafetyCheckStatusChangedWithDataIfExists( const std::string& component, int new_state) { - for (const auto& it : test_web_ui_.call_data()) { - const content::TestWebUI::CallData& data = *it; + // Return the latest update if multiple, so iterate from the end. + const std::vector<std::unique_ptr<content::TestWebUI::CallData>>& call_data = + test_web_ui_.call_data(); + for (int i = call_data.size() - 1; i >= 0; --i) { + const content::TestWebUI::CallData& data = *(call_data[i]); if (data.function_name() != "cr.webUIListenerCallback") { continue; } @@ -683,6 +699,52 @@ VerifyDisplayString(event, "No saved passwords"); } +TEST_F(SafetyCheckHandlerTest, CheckPasswords_Progress) { + auto credential = password_manager::LeakCheckCredential( + base::UTF8ToUTF16("test"), base::UTF8ToUTF16("test")); + auto is_leaked = password_manager::IsLeaked(false); + safety_check_->PerformSafetyCheck(); + test_passwords_delegate_.SetPasswordCheckState( + extensions::api::passwords_private::PASSWORD_CHECK_STATE_RUNNING); + test_passwords_delegate_.SetProgress(1, 3); + static_cast<password_manager::BulkLeakCheckService::Observer*>( + safety_check_.get()) + ->OnCredentialDone(credential, is_leaked); + const base::DictionaryValue* event = + GetSafetyCheckStatusChangedWithDataIfExists( + kPasswords, + static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)); + EXPECT_TRUE(event); + VerifyDisplayString(event, base::UTF8ToUTF16("1/3 passwords checked…")); + + test_passwords_delegate_.SetProgress(2, 3); + static_cast<password_manager::BulkLeakCheckService::Observer*>( + safety_check_.get()) + ->OnCredentialDone(credential, is_leaked); + const base::DictionaryValue* event2 = + GetSafetyCheckStatusChangedWithDataIfExists( + kPasswords, + static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)); + EXPECT_TRUE(event2); + VerifyDisplayString(event2, base::UTF8ToUTF16("2/3 passwords checked…")); + + // Final update comes after status change, so no new progress message should + // be present. + test_passwords_delegate_.SetPasswordCheckState( + extensions::api::passwords_private::PASSWORD_CHECK_STATE_IDLE); + test_passwords_delegate_.SetProgress(3, 3); + static_cast<password_manager::BulkLeakCheckService::Observer*>( + safety_check_.get()) + ->OnCredentialDone(credential, is_leaked); + const base::DictionaryValue* event3 = + GetSafetyCheckStatusChangedWithDataIfExists( + kPasswords, + static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)); + EXPECT_TRUE(event3); + // Still 2/3 event. + VerifyDisplayString(event3, base::UTF8ToUTF16("2/3 passwords checked…")); +} + TEST_F(SafetyCheckHandlerTest, CheckExtensions_NoExtensions) { safety_check_->PerformSafetyCheck(); EXPECT_TRUE(GetSafetyCheckStatusChangedWithDataIfExists(
diff --git a/chrome/browser/wake_lock/wake_lock_permission_context.cc b/chrome/browser/wake_lock/wake_lock_permission_context.cc index 457bff0..5696552 100644 --- a/chrome/browser/wake_lock/wake_lock_permission_context.cc +++ b/chrome/browser/wake_lock/wake_lock_permission_context.cc
@@ -10,9 +10,12 @@ WakeLockPermissionContext::WakeLockPermissionContext( content::BrowserContext* browser_context, ContentSettingsType content_settings_type) - : PermissionContextBase(browser_context, - content_settings_type, - blink::mojom::FeaturePolicyFeature::kWakeLock), + : PermissionContextBase( + browser_context, + content_settings_type, + content_settings_type == ContentSettingsType::WAKE_LOCK_SCREEN + ? blink::mojom::FeaturePolicyFeature::kScreenWakeLock + : blink::mojom::FeaturePolicyFeature::kNotFound), content_settings_type_(content_settings_type) { DCHECK(content_settings_type == ContentSettingsType::WAKE_LOCK_SCREEN || content_settings_type == ContentSettingsType::WAKE_LOCK_SYSTEM);
diff --git a/chrome/browser/web_applications/components/app_registry_controller.cc b/chrome/browser/web_applications/components/app_registry_controller.cc index 2368f66..6a2be8e 100644 --- a/chrome/browser/web_applications/components/app_registry_controller.cc +++ b/chrome/browser/web_applications/components/app_registry_controller.cc
@@ -17,8 +17,8 @@ void AppRegistryController::SetExperimentalTabbedWindowMode(const AppId& app_id, bool enabled) { - DCHECK(base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip)); if (enabled) { + DCHECK(base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip)); UpdateBoolWebAppPref(profile()->GetPrefs(), app_id, kExperimentalTabbedWindowMode, true);
diff --git a/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.cc b/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.cc index f7c648d5..6aa65dc2 100644 --- a/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.cc +++ b/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.cc
@@ -5,12 +5,12 @@ #include "chrome/services/sharing/public/cpp/sharing_webrtc_metrics.h" #include "base/metrics/histogram_functions.h" -#include "base/strings/strcat.h" +#include "base/strings/string_util.h" namespace { // Common prefix for all webrtc metric in Sharing service. -const char kMetricsPrefix[] = "Sharing.WebRtc."; +const char kMetricsPrefix[] = "Sharing.WebRtc"; // Return values must be kept in sync with "SharingWebRtcTimingEvent" in // src/tools/metrics/histograms/histograms.xml. @@ -47,6 +47,15 @@ } } +// Return values must be kept in sync with "SharingWebRtcTimingEventRole" in +// src/tools/metrics/histograms/histograms.xml. +std::string SenderReceiverSuffix(base::Optional<bool> is_sender) { + if (!is_sender.has_value()) + return "Unknown"; + + return *is_sender ? "Sender" : "Receiver"; +} + } // namespace namespace sharing { @@ -69,46 +78,57 @@ } void LogWebRtcAddIceCandidate(bool success) { - base::UmaHistogramBoolean(base::StrCat({kMetricsPrefix, "AddIceCandidate"}), - success); + base::UmaHistogramBoolean( + base::JoinString({kMetricsPrefix, "AddIceCandidate"}, "."), success); } void LogWebRtcIceConfigFetched(int count) { base::UmaHistogramExactLinear( - base::StrCat({kMetricsPrefix, "IceConfigFetched"}), count, + base::JoinString({kMetricsPrefix, "IceConfigFetched"}, "."), count, /*value_max=*/10); } void LogWebRtcTimeout(WebRtcTimeoutState state) { - base::UmaHistogramEnumeration(base::StrCat({kMetricsPrefix, "Timeout"}), - state); + base::UmaHistogramEnumeration( + base::JoinString({kMetricsPrefix, "Timeout"}, "."), state); } void LogWebRtcConnectionType(WebRtcConnectionType type) { base::UmaHistogramEnumeration( - base::StrCat({kMetricsPrefix, "ConnectionType"}), type); + base::JoinString({kMetricsPrefix, "ConnectionType"}, "."), type); } void LogWebRtcSendMessageResult(WebRtcSendMessageResult result) { base::UmaHistogramEnumeration( - base::StrCat({kMetricsPrefix, "SendMessageResult"}), result); + base::JoinString({kMetricsPrefix, "SendMessageResult"}, "."), result); } void LogWebRtcConnectionErrorReason(WebRtcConnectionErrorReason reason) { base::UmaHistogramEnumeration( - base::StrCat({kMetricsPrefix, "ConnectionErrorReason"}), reason); + base::JoinString({kMetricsPrefix, "ConnectionErrorReason"}, "."), reason); } -void LogWebRtcTimingEvent(WebRtcTimingEvent event, base::TimeDelta delay) { - base::UmaHistogramMediumTimes(base::StrCat({kMetricsPrefix, "TimingEvents.", - TimingEventToString(event)}), - delay); +void LogWebRtcTimingEvent(WebRtcTimingEvent event, + base::TimeDelta delay, + base::Optional<bool> is_sender) { + base::UmaHistogramMediumTimes( + base::JoinString( + {kMetricsPrefix, "TimingEvents", TimingEventToString(event)}, "."), + delay); + + base::UmaHistogramMediumTimes( + base::JoinString( + {kMetricsPrefix, "TimingEvents", SenderReceiverSuffix(is_sender), + TimingEventToString(event)}, + "."), + delay); } void LogSharingWebRtcOnMessageReceivedResult( WebRtcOnMessageReceivedResult result) { base::UmaHistogramEnumeration( - base::StrCat({kMetricsPrefix, "OnMessageReceivedResult"}), result); + base::JoinString({kMetricsPrefix, "OnMessageReceivedResult"}, "."), + result); } } // namespace sharing
diff --git a/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.h b/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.h index b06580b..7c4468f2 100644 --- a/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.h +++ b/chrome/services/sharing/public/cpp/sharing_webrtc_metrics.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/optional.h" #include "base/time/time.h" namespace sharing { @@ -124,7 +125,9 @@ void LogWebRtcConnectionErrorReason(WebRtcConnectionErrorReason reason); // Logs the timing for |event| to UMA. -void LogWebRtcTimingEvent(WebRtcTimingEvent event, base::TimeDelta delay); +void LogWebRtcTimingEvent(WebRtcTimingEvent event, + base::TimeDelta delay, + base::Optional<bool> is_sender); // Logs the result of receiving a message via WebRTC. void LogSharingWebRtcOnMessageReceivedResult(
diff --git a/chrome/services/sharing/webrtc/sharing_webrtc_connection.cc b/chrome/services/sharing/webrtc/sharing_webrtc_connection.cc index c5d4247..7140265 100644 --- a/chrome/services/sharing/webrtc/sharing_webrtc_connection.cc +++ b/chrome/services/sharing/webrtc/sharing_webrtc_connection.cc
@@ -260,6 +260,10 @@ const std::string& offer, OnOfferReceivedCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Only the receiver receives an offer from the sender and it's the first + // thing it does. + timing_recorder_.set_is_sender(false); + timing_recorder_.LogEvent(WebRtcTimingEvent::kOfferReceived); std::unique_ptr<webrtc::SessionDescriptionInterface> description( @@ -296,6 +300,11 @@ void SharingWebRtcConnection::SendMessage(const std::vector<uint8_t>& message, SendMessageCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // We know that we're the sender if there is no data channel yet because the + // receiver only sends ack messages after receiving via a data channel. + if (!channel_) + timing_recorder_.set_is_sender(true); + timing_recorder_.LogEvent(WebRtcTimingEvent::kQueuingMessage); if (message.empty()) {
diff --git a/chrome/services/sharing/webrtc/sharing_webrtc_connection_integration_test.cc b/chrome/services/sharing/webrtc/sharing_webrtc_connection_integration_test.cc index 2e47cfbe..11a82d2 100644 --- a/chrome/services/sharing/webrtc/sharing_webrtc_connection_integration_test.cc +++ b/chrome/services/sharing/webrtc/sharing_webrtc_connection_integration_test.cc
@@ -4,7 +4,9 @@ #include "chrome/services/sharing/webrtc/sharing_webrtc_connection.h" +#include "base/strings/strcat.h" #include "base/test/bind_test_util.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "chrome/services/sharing/webrtc/test/mock_sharing_connection_host.h" #include "jingle/glue/thread_wrapper.h" @@ -168,10 +170,29 @@ base::Unretained(this))); } + enum class Role { kSender, kReceiver, kSenderAndReceiver }; + + void ExpectTimingHistogram(const std::string& name, Role role) { + int expected_count = role == Role::kSenderAndReceiver ? 2 : 1; + histograms_.ExpectTotalCount( + base::StrCat({"Sharing.WebRtc.TimingEvents.", name}), expected_count); + + if (role == Role::kSender || role == Role::kSenderAndReceiver) { + histograms_.ExpectTotalCount( + base::StrCat({"Sharing.WebRtc.TimingEvents.Sender.", name}), 1); + } + + if (role == Role::kReceiver || role == Role::kSenderAndReceiver) { + histograms_.ExpectTotalCount( + base::StrCat({"Sharing.WebRtc.TimingEvents.Receiver.", name}), 1); + } + } + protected: base::test::SingleThreadTaskEnvironment task_environment_{ base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME}; rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> webrtc_pc_factory_; + base::HistogramTester histograms_; }; TEST_F(SharingWebRtcConnectionIntegrationTest, SendMessage_Success) { @@ -205,6 +226,17 @@ send_run_loop.Run(); receive_run_loop.Run(); + + ExpectTimingHistogram("OfferCreated", Role::kSender); + ExpectTimingHistogram("AnswerReceived", Role::kSender); + ExpectTimingHistogram("QueuingMessage", Role::kSender); + ExpectTimingHistogram("SendingMessage", Role::kSender); + ExpectTimingHistogram("OfferReceived", Role::kReceiver); + ExpectTimingHistogram("AnswerCreated", Role::kReceiver); + ExpectTimingHistogram("MessageReceived", Role::kReceiver); + ExpectTimingHistogram("SignalingStable", Role::kSenderAndReceiver); + ExpectTimingHistogram("IceCandidateReceived", Role::kSenderAndReceiver); + ExpectTimingHistogram("DataChannelOpen", Role::kSenderAndReceiver); } } // namespace sharing
diff --git a/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.cc b/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.cc index 7d00c6b..d457f86b 100644 --- a/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.cc +++ b/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.cc
@@ -51,7 +51,8 @@ if (!to_iter.second) return; - LogWebRtcTimingEvent(event, to_iter.first->second - from_iter->second); + base::TimeDelta delay = to_iter.first->second - from_iter->second; + LogWebRtcTimingEvent(event, delay, is_sender_); } } // namespace sharing
diff --git a/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.h b/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.h index a254df1..d52be05 100644 --- a/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.h +++ b/chrome/services/sharing/webrtc/sharing_webrtc_timing_recorder.h
@@ -7,6 +7,7 @@ #include <map> +#include "base/optional.h" #include "base/time/time.h" #include "chrome/services/sharing/public/cpp/sharing_webrtc_metrics.h" @@ -25,9 +26,16 @@ // is determined by the |event_start_map| in GetEventStart. void LogEvent(WebRtcTimingEvent event); + // Sets whether we should log events with the sender or receiver suffix in + // addition to the non-suffixed version. Only the non-suffixed version is + // logged by default. + void set_is_sender(bool is_sender) { is_sender_ = is_sender; } + private: // Map of the timing event to the first timestamp it got logged. std::map<WebRtcTimingEvent, base::TimeTicks> timings_; + // Whether we should log events with the sender or receiver suffix. + base::Optional<bool> is_sender_; }; } // namespace sharing
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 6087c40..8be16486 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2231,6 +2231,7 @@ "../browser/chromeos/login/screens/mock_wrong_hwid_screen.cc", "../browser/chromeos/login/screens/mock_wrong_hwid_screen.h", "../browser/chromeos/login/screens/network_screen_browsertest.cc", + "../browser/chromeos/login/screens/packaged_license_screen_browsertest.cc", "../browser/chromeos/login/screens/recommend_apps/scoped_test_recommend_apps_fetcher_factory.cc", "../browser/chromeos/login/screens/recommend_apps/scoped_test_recommend_apps_fetcher_factory.h", "../browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc", @@ -3666,6 +3667,7 @@ "//components/optimization_guide", "//components/optimization_guide:test_support", "//components/os_crypt:test_support", + "//components/page_info", "//components/page_load_metrics/browser", "//components/page_load_metrics/browser:test_support", "//components/page_load_metrics/common:test_support",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java index aa996c2..299a9fdc 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/NewTabPageTestUtils.java
@@ -19,8 +19,8 @@ import org.chromium.chrome.browser.suggestions.tile.TileSource; import org.chromium.chrome.browser.suggestions.tile.TileTitleSource; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; import org.chromium.content_public.browser.test.util.Criteria; @@ -98,7 +98,7 @@ FakeAccountManagerDelegate fakeAccountManager = new FakeAccountManagerDelegate( FakeAccountManagerDelegate.ENABLE_PROFILE_DATA_SOURCE); AccountManagerFacadeProvider.overrideAccountManagerFacadeForTests(fakeAccountManager); - Account account = AccountManagerFacade.createAccountFromName("test@gmail.com"); + Account account = AccountUtils.createAccountFromName("test@gmail.com"); fakeAccountManager.addAccountHolderExplicitly(new AccountHolder.Builder(account).build()); assertFalse(AccountManagerFacadeProvider.getInstance().isUpdatePending().get()); assertFalse(SharedPreferencesManager.getInstance().readBoolean(
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java index 2752717..cf3ed7f 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -18,8 +18,8 @@ import org.chromium.chrome.browser.signin.SigninManager; import org.chromium.chrome.browser.signin.SigninPreferencesManager; import org.chromium.chrome.browser.sync.ProfileSyncService; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.metrics.SigninAccessPoint; @@ -96,7 +96,7 @@ * Add an account with a given name. */ public static Account addTestAccount(String name) { - Account account = AccountManagerFacade.createAccountFromName(name); + Account account = AccountUtils.createAccountFromName(name); AccountHolder accountHolder = AccountHolder.builder(account).alwaysAccept(true).build(); sAccountManager.addAccountHolderBlocking(accountHolder); sAddedAccounts.add(accountHolder);
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py index b83ce8d..d40ecc84b 100644 --- a/chrome/test/chromedriver/client/chromedriver.py +++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -215,7 +215,7 @@ log_types = ['client', 'driver', 'browser', 'server', 'performance', 'devtools'] log_levels = ['ALL', 'DEBUG', 'INFO', 'WARNING', 'SEVERE', 'OFF'] - for log_type, log_level in logging_prefs.iteritems(): + for log_type, log_level in logging_prefs.items(): assert log_type in log_types assert log_level in log_levels else:
diff --git a/chrome/test/chromedriver/cpp_source.py b/chrome/test/chromedriver/cpp_source.py index b0f8159..4c094d9 100644 --- a/chrome/test/chromedriver/cpp_source.py +++ b/chrome/test/chromedriver/cpp_source.py
@@ -34,7 +34,7 @@ # Write header file. externs = [] - for name in global_string_map.iterkeys(): + for name in global_string_map.keys(): externs += ['extern const char %s[];' % name] temp = '_'.join(dir_from_src.split('/') + [base_name]) @@ -58,7 +58,7 @@ return line.replace('\\', '\\\\').replace('"', '\\"') definitions = [] - for name, contents in global_string_map.iteritems(): + for name, contents in global_string_map.items(): lines = [] if '\n' not in contents: lines = [' "%s"' % EscapeLine(contents)]
diff --git a/chrome/test/chromedriver/log_replay/client_replay.py b/chrome/test/chromedriver/log_replay/client_replay.py index c4d2a04..687742b 100755 --- a/chrome/test/chromedriver/log_replay/client_replay.py +++ b/chrome/test/chromedriver/log_replay/client_replay.py
@@ -308,7 +308,7 @@ id_map: mapping from old to new IDs that should be replaced. """ if isinstance(payload, dict): - for key, value in payload.iteritems(): + for key, value in payload.items(): if isinstance(value, basestring) and value in id_map: payload[key] = id_map[value] else: @@ -831,7 +831,7 @@ response = [ {u"id": key, u"capabilities": val["response"].GetPayloadPrimitive()} - for key, val in command_response_pairs.iteritems() + for key, val in command_response_pairs.items() ] self._last_response = _GetSessionsResponseEntry(response)
diff --git a/chrome/test/chromedriver/test/webserver.py b/chrome/test/chromedriver/test/webserver.py index 9a5d76a..f2b93563 100644 --- a/chrome/test/chromedriver/test/webserver.py +++ b/chrome/test/chromedriver/test/webserver.py
@@ -29,7 +29,7 @@ def SendHeaders(self, headers={}, content_length=None): """Sends headers for OK response.""" self._handler.send_response(200) - for field, value in headers.iteritems(): + for field, value in headers.items(): self._handler.send_header(field, value) if content_length: self._handler.send_header('Content-Length', content_length)
diff --git a/chrome/test/data/extensions/api_test/debugger_inspect_worker/background.js b/chrome/test/data/extensions/api_test/debugger_inspect_worker/background.js new file mode 100644 index 0000000..c104c77 --- /dev/null +++ b/chrome/test/data/extensions/api_test/debugger_inspect_worker/background.js
@@ -0,0 +1,35 @@ +// 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. + +const protocolVersion = '1.3'; + +chrome.test.getConfig(config => chrome.test.runTests([ + async function testInspectWorkerForbidden() { + const tab = await new Promise(resolve => + chrome.tabs.create({url: config.customArg}, resolve)); + const debuggee = {tabId: tab.id}; + await new Promise(resolve => + chrome.debugger.attach(debuggee, protocolVersion, resolve)); + chrome.debugger.sendCommand(debuggee, 'ServiceWorker.enable', null); + let workerReadyCallback; + chrome.debugger.onEvent.addListener((source, method, params) => { + if (method !== 'ServiceWorker.workerVersionUpdated') + return; + const versions = params.versions; + if (!versions.length || versions[0].runningStatus !== 'running') + return; + workerReadyCallback(versions[0].versionId); + }); + const versionId = await new Promise(resolve => + workerReadyCallback = resolve); + await new Promise(resolve => + chrome.debugger.sendCommand(debuggee, 'ServiceWorker.inspectWorker', + {versionId}, resolve)) + chrome.test.assertTrue(!!chrome.runtime.lastError, + 'Expected ServiceWorker.inspectWorker to fail'); + chrome.test.assertEq('Permission denied', + JSON.parse(chrome.runtime.lastError.message).message); + chrome.test.succeed(); + } +]));
diff --git a/chrome/test/data/extensions/api_test/debugger_inspect_worker/inspected_page.html b/chrome/test/data/extensions/api_test/debugger_inspect_worker/inspected_page.html new file mode 100644 index 0000000..c50ef83 --- /dev/null +++ b/chrome/test/data/extensions/api_test/debugger_inspect_worker/inspected_page.html
@@ -0,0 +1,5 @@ +<html> +<script> +navigator.serviceWorker.register("./service_worker.js"); +</script> +</html> \ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/debugger_inspect_worker/manifest.json b/chrome/test/data/extensions/api_test/debugger_inspect_worker/manifest.json new file mode 100644 index 0000000..6ca4cde --- /dev/null +++ b/chrome/test/data/extensions/api_test/debugger_inspect_worker/manifest.json
@@ -0,0 +1,11 @@ +{ + "name": "Debugger API test for inpectWorker CDP command", + "version": "1.0", + "manifest_version": 2, + "background": { + "scripts": ["background.js"] + }, + "permissions": [ + "debugger" + ] +}
diff --git a/chrome/test/data/extensions/api_test/debugger_inspect_worker/service_worker.js b/chrome/test/data/extensions/api_test/debugger_inspect_worker/service_worker.js new file mode 100644 index 0000000..12bc989f --- /dev/null +++ b/chrome/test/data/extensions/api_test/debugger_inspect_worker/service_worker.js
@@ -0,0 +1,5 @@ +// 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. + +// It's empty, yes.
diff --git a/chrome/test/data/webui/media/media_feeds_webui_browsertest.js b/chrome/test/data/webui/media/media_feeds_webui_browsertest.js index 65e2a405a..72c293b 100644 --- a/chrome/test/data/webui/media/media_feeds_webui_browsertest.js +++ b/chrome/test/data/webui/media/media_feeds_webui_browsertest.js
@@ -6,10 +6,6 @@ * @fileoverview Test suite for the Media Feeds WebUI. */ -const EXAMPLE_URL_1 = 'http://example.com/feed.json'; - -GEN('#include "base/run_loop.h"'); -GEN('#include "chrome/browser/media/history/media_history_keyed_service.h"'); GEN('#include "chrome/browser/ui/browser.h"'); GEN('#include "media/base/media_switches.h"'); @@ -24,97 +20,6 @@ isAsync: true, - testGenPreamble: function() { - GEN('auto* service ='); - GEN(' media_history::MediaHistoryKeyedService::Get('); - GEN(' browser()->profile());'); - GEN('service->DiscoverMediaFeed(GURL("' + EXAMPLE_URL_1 + '"));'); - GEN('auto items = std::vector<media_feeds::mojom::MediaFeedItemPtr>();'); - GEN('auto item = media_feeds::mojom::MediaFeedItem::New();'); - GEN('item->name = base::ASCIIToUTF16("The Movie");'); - GEN('item->type = media_feeds::mojom::MediaFeedItemType::kMovie;'); - GEN('item->date_published = base::Time::FromDeltaSinceWindowsEpoch('); - GEN(' base::TimeDelta::FromMinutes(10));'); - GEN('item->is_family_friendly = true;'); - GEN('item->action_status ='); - GEN(' media_feeds::mojom::MediaFeedItemActionStatus::kPotential;'); - GEN('item->genre = base::ASCIIToUTF16("test");'); - GEN('item->duration = base::TimeDelta::FromSeconds(30);'); - GEN('item->live = media_feeds::mojom::LiveDetails::New();'); - GEN('item->live->start_time = base::Time::FromDeltaSinceWindowsEpoch('); - GEN(' base::TimeDelta::FromMinutes(20));'); - GEN('item->live->end_time = base::Time::FromDeltaSinceWindowsEpoch('); - GEN(' base::TimeDelta::FromMinutes(30));'); - GEN('item->shown_count = 3;'); - GEN('item->clicked = true;'); - GEN('item->author = media_feeds::mojom::Author::New();'); - GEN('item->author->name = "Media Site";'); - GEN('item->author->url = GURL("https://www.example.com");'); - GEN('item->action = media_feeds::mojom::Action::New();'); - GEN('item->action->start_time = base::TimeDelta::FromSeconds(3);'); - GEN('item->action->url = GURL("https://www.example.com");'); - GEN('item->interaction_counters.emplace('); - GEN(' media_feeds::mojom::InteractionCounterType::kLike, 10000);'); - GEN('item->interaction_counters.emplace('); - GEN(' media_feeds::mojom::InteractionCounterType::kDislike, 20000);'); - GEN('item->interaction_counters.emplace('); - GEN(' media_feeds::mojom::InteractionCounterType::kWatch, 30000);'); - GEN('item->content_ratings.push_back('); - GEN(' media_feeds::mojom::ContentRating::New("MPAA", "PG-13"));'); - GEN('item->content_ratings.push_back('); - GEN(' media_feeds::mojom::ContentRating::New("agency", "TEST2"));'); - GEN('item->identifiers.push_back('); - GEN(' media_feeds::mojom::Identifier::New('); - GEN(' media_feeds::mojom::Identifier::Type::kPartnerId, "TEST1"));'); - GEN('item->identifiers.push_back('); - GEN(' media_feeds::mojom::Identifier::New('); - GEN(' media_feeds::mojom::Identifier::Type::kTMSId, "TEST2"));'); - GEN('item->tv_episode = media_feeds::mojom::TVEpisode::New();'); - GEN('item->tv_episode->name = "TV Episode Name";'); - GEN('item->tv_episode->season_number = 1;'); - GEN('item->tv_episode->episode_number = 2;'); - GEN('item->tv_episode->identifiers.push_back('); - GEN(' media_feeds::mojom::Identifier::New('); - GEN(' media_feeds::mojom::Identifier::Type::kPartnerId, "TEST3"));'); - GEN('item->play_next_candidate = '); - GEN(' media_feeds::mojom::PlayNextCandidate::New();'); - GEN('item->play_next_candidate->name = "Next TV Episode Name";'); - GEN('item->play_next_candidate->season_number = 1;'); - GEN('item->play_next_candidate->episode_number = 3;'); - GEN('item->play_next_candidate->duration ='); - GEN(' base::TimeDelta::FromSeconds(10);'); - GEN('item->play_next_candidate->action = '); - GEN(' media_feeds::mojom::Action::New();'); - GEN('item->play_next_candidate->action->start_time ='); - GEN(' base::TimeDelta::FromSeconds(3);'); - GEN('item->play_next_candidate->action->url = '); - GEN(' GURL("https://www.example.com");'); - GEN('item->play_next_candidate->identifiers.push_back('); - GEN(' media_feeds::mojom::Identifier::New('); - GEN(' media_feeds::mojom::Identifier::Type::kPartnerId, "TEST4"));'); - GEN('media_session::MediaImage image1;'); - GEN('image1.src = GURL("https://www.example.org/image1.png");'); - GEN('item->images.push_back(image1);'); - GEN('media_session::MediaImage image2;'); - GEN('image2.src = GURL("https://www.example.org/image2.png");'); - GEN('item->images.push_back(image2);'); - GEN('items.push_back(std::move(item));'); - GEN('std::vector<media_session::MediaImage> logos;'); - GEN('media_session::MediaImage logo1;'); - GEN('logo1.src = GURL("https://www.example.org/logo1.png");'); - GEN('logos.push_back(logo1);'); - GEN('media_session::MediaImage logo2;'); - GEN('logo2.src = GURL("https://www.example.org/logo2.png");'); - GEN('logos.push_back(logo2);'); - GEN('service->StoreMediaFeedFetchResult('); - GEN(' 1, std::move(items), media_feeds::mojom::FetchResult::kSuccess,'); - GEN(' base::Time::FromDeltaSinceWindowsEpoch('); - GEN(' base::TimeDelta::FromMinutes(40)), logos, "Test Feed");'); - GEN('base::RunLoop run_loop;'); - GEN('service->PostTaskToDBForTest(run_loop.QuitClosure());'); - GEN('run_loop.Run();'); - }, - extraLibraries: [ '//third_party/mocha/mocha.js', '//chrome/test/data/webui/mocha_adapter.js', @@ -127,7 +32,7 @@ }); test('check feeds table is loaded', function() { - const feedsHeaders = + let feedHeaders = Array.from(document.querySelector('#feed-table-header').children); assertDeepEquals( @@ -135,93 +40,9 @@ 'ID', 'Url', 'Display Name', 'Last Discovery Time', 'Last Fetch Time', 'User Status', 'Last Fetch Result', 'Fetch Failed Count', 'Cache Expiry Time', 'Last Fetch Item Count', - 'Last Fetch Play Next Count', 'Last Fetch Content Types', 'Logos', - 'Actions' + 'Last Fetch Play Next Count', 'Last Fetch Content Types', 'Logos' ], - feedsHeaders.map(x => x.textContent.trim())); - - const feedsContents = - document.querySelector('#feed-table-body').childNodes[0]; - - assertEquals('1', feedsContents.childNodes[0].textContent.trim()); - assertEquals(EXAMPLE_URL_1, feedsContents.childNodes[1].textContent.trim()); - assertEquals('Test Feed', feedsContents.childNodes[2].textContent.trim()); - assertEquals('Auto', feedsContents.childNodes[5].textContent.trim()); - assertEquals('Success', feedsContents.childNodes[6].textContent.trim()); - assertEquals('0', feedsContents.childNodes[7].textContent.trim()); - assertNotEquals('', feedsContents.childNodes[8].textContent.trim()); - assertEquals('1', feedsContents.childNodes[9].textContent.trim()); - assertEquals('1', feedsContents.childNodes[10].textContent.trim()); - assertEquals('Movie', feedsContents.childNodes[11].textContent.trim()); - assertEquals( - 'https://www.example.org/logo1.pnghttps://www.example.org/logo2.png', - feedsContents.childNodes[12].textContent.trim()); - assertEquals( - 'Show Contents', feedsContents.childNodes[13].textContent.trim()); - - // Click on the show contents button. - feedsContents.childNodes[13].firstChild.click(); - - return whenFeedTableIsPopulatedForTest().then(() => { - assertEquals( - EXAMPLE_URL_1, document.querySelector('#current-feed').textContent); - - const feedItemsHeaders = Array.from( - document.querySelector('#feed-items-table thead tr').children); - - assertDeepEquals( - [ - 'Type', 'Name', 'Author', 'Date Published', 'Family Friendly', - 'Action Status', 'Action URL', 'Action Start Time (secs)', - 'Interaction Counters', 'Content Ratings', 'Genre', 'Live Details', - 'TV Episode', 'Play Next Candidate', 'Identifiers', 'Shown Count', - 'Clicked', 'Images' - ], - feedItemsHeaders.map(x => x.textContent.trim())); - - const feedItemsContents = - document.querySelector('#feed-items-table tbody').childNodes[0]; - - assertEquals('Movie', feedItemsContents.childNodes[0].textContent.trim()); - assertEquals( - 'The Movie', feedItemsContents.childNodes[1].textContent.trim()); - assertEquals( - 'Media Site', feedItemsContents.childNodes[2].textContent.trim()); - assertEquals( - '12/31/1600, 4:17:02 PM', - feedItemsContents.childNodes[3].textContent.trim()); - assertEquals('Yes', feedItemsContents.childNodes[4].textContent.trim()); - assertEquals( - 'Potential', feedItemsContents.childNodes[5].textContent.trim()); - assertEquals( - 'https://www.example.com/', - feedItemsContents.childNodes[6].textContent.trim()); - assertEquals('3', feedItemsContents.childNodes[7].textContent.trim()); - assertEquals( - 'Watch=30000 Like=10000 Dislike=20000', - feedItemsContents.childNodes[8].textContent.trim()); - assertEquals( - 'MPAA PG-13, agency TEST2', - feedItemsContents.childNodes[9].textContent.trim()); - assertEquals('test', feedItemsContents.childNodes[10].textContent.trim()); - assertEquals( - 'Live StartTime=12/31/1600, 4:27:02 PM EndTime=12/31/1600, 4:37:02 PM', - feedItemsContents.childNodes[11].textContent.trim()); - assertEquals( - 'TV Episode Name EpisodeNumber=2 SeasonNumber=1 PartnerId=TEST3', - feedItemsContents.childNodes[12].textContent.trim()); - assertEquals( - 'Next TV Episode Name EpisodeNumber=3 SeasonNumber=1 PartnerId=TEST4 ActionURL=https://www.example.com/ ActionStartTimeSecs=3 DurationSecs=10', - feedItemsContents.childNodes[13].textContent.trim()); - assertEquals( - 'PartnerId=TEST1 TMSId=TEST2', - feedItemsContents.childNodes[14].textContent.trim()); - assertEquals('3', feedItemsContents.childNodes[15].textContent.trim()); - assertEquals('Yes', feedItemsContents.childNodes[16].textContent.trim()); - assertEquals( - 'https://www.example.org/image1.pnghttps://www.example.org/image2.png', - feedItemsContents.childNodes[17].textContent.trim()); - }); + feedHeaders.map(x => x.textContent.trim())); }); mocha.run();
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js index 84a2abc..5c891a4 100644 --- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js +++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
@@ -155,6 +155,6 @@ } }; -TEST_F('NewTabPageLogoTest', 'All', function() { +TEST_F('NewTabPageLogoTest', 'DISABLE_All', function() { mocha.run(); });
diff --git a/chrome/test/data/webui/settings/password_check_test.js b/chrome/test/data/webui/settings/password_check_test.js index a1dabc7c..ac710c11 100644 --- a/chrome/test/data/webui/settings/password_check_test.js +++ b/chrome/test/data/webui/settings/password_check_test.js
@@ -999,7 +999,7 @@ checkPasswordSection.$.menuEditPassword.click(); // Since we did not specify a plaintext password above, this request // should fail. - await passwordManager.whenCalled('getPlainttextCompromisedPassword'); + await passwordManager.whenCalled('getPlaintextCompromisedPassword'); // Verify that the edit dialog has not become visible. Polymer.dom.flush(); expectFalse(isElementVisible( @@ -1027,7 +1027,7 @@ node.$.more.click(); checkPasswordSection.$.menuEditPassword.click(); const {credential, reason} = - await passwordManager.whenCalled('getPlainttextCompromisedPassword'); + await passwordManager.whenCalled('getPlaintextCompromisedPassword'); expectEquals(passwordManager.data.leakedCredentials[0], credential); expectEquals(chrome.passwordsPrivate.PlaintextReason.EDIT, reason); @@ -1085,6 +1085,70 @@ PasswordManagerProxy.PasswordCheckInteraction .START_CHECK_AUTOMATICALLY, interaction); + settings.Router.getInstance().resetRouteForTesting(); + }); + + // Verify clicking show password in menu reveal password. + test('showHidePasswordMenuItemSuccess', async function() { + passwordManager.data.leakedCredentials = + [autofill_test_util.makeCompromisedCredential( + 'google.com', 'jdoerrie', 'LEAKED')]; + passwordManager.plaintextPassword_ = 'test4'; + const checkPasswordSection = createCheckPasswordSection(); + + await passwordManager.whenCalled('getCompromisedCredentials'); + + Polymer.dom.flush(); + const listElements = checkPasswordSection.$.leakedPasswordList; + const node = listElements.children[1]; + assertEquals('password', node.$.leakedPassword.type); + assertNotEquals('test4', node.$.leakedPassword.value); + + // Open the more actions menu and click 'Show Password'. + node.$.more.click(); + checkPasswordSection.$.menuShowPassword.click(); + + const interaction = + await passwordManager.whenCalled('recordPasswordCheckInteraction'); + + assertEquals( + PasswordManagerProxy.PasswordCheckInteraction.SHOW_PASSWORD, + interaction); + const {reason} = + await passwordManager.whenCalled('getPlaintextCompromisedPassword'); + expectEquals(chrome.passwordsPrivate.PlaintextReason.VIEW, reason); + assertEquals('text', node.$.leakedPassword.type); + assertEquals('test4', node.$.leakedPassword.value); + + // Open the more actions menu and click 'Hide Password'. + node.$.more.click(); + checkPasswordSection.$.menuShowPassword.click(); + + assertEquals('password', node.$.leakedPassword.type); + assertNotEquals('test4', node.$.leakedPassword.value); + }); + + // Verify if getPlaintext fails password will not be shown + test('showHidePasswordMenuItemFail', async function() { + passwordManager.data.leakedCredentials = + [autofill_test_util.makeCompromisedCredential( + 'google.com', 'jdoerrie', 'LEAKED')]; + const checkPasswordSection = createCheckPasswordSection(); + await passwordManager.whenCalled('getCompromisedCredentials'); + + Polymer.dom.flush(); + const listElements = checkPasswordSection.$.leakedPasswordList; + const node = listElements.children[1]; + assertEquals('password', node.$.leakedPassword.type); + assertNotEquals('test4', node.$.leakedPassword.value); + + // Open the more actions menu and click 'Show Password'. + node.$.more.click(); + checkPasswordSection.$.menuShowPassword.click(); + await passwordManager.whenCalled('getPlaintextCompromisedPassword'); + // Verify that password field didn't change + assertEquals('password', node.$.leakedPassword.type); + assertNotEquals('test4', node.$.leakedPassword.value); }); }); // #cr_define_end
diff --git a/chrome/test/data/webui/settings/test_password_manager_proxy.js b/chrome/test/data/webui/settings/test_password_manager_proxy.js index da2169f..d79d1b7d 100644 --- a/chrome/test/data/webui/settings/test_password_manager_proxy.js +++ b/chrome/test/data/webui/settings/test_password_manager_proxy.js
@@ -22,7 +22,7 @@ 'stopBulkPasswordCheck', 'getCompromisedCredentials', 'getPasswordCheckStatus', - 'getPlainttextCompromisedPassword', + 'getPlaintextCompromisedPassword', 'changeCompromisedCredential', 'removeCompromisedCredential', 'recordPasswordCheckInteraction', @@ -199,7 +199,7 @@ /** @override */ getPlaintextCompromisedPassword(credential, reason) { - this.methodCalled('getPlainttextCompromisedPassword', {credential, reason}); + this.methodCalled('getPlaintextCompromisedPassword', {credential, reason}); if (!this.plaintextPassword_) { return Promise.reject('Could not obtain plaintext password'); }
diff --git a/components/captive_portal/OWNERS b/components/captive_portal/OWNERS index 0ece4fb..7e5ec6e 100644 --- a/components/captive_portal/OWNERS +++ b/components/captive_portal/OWNERS
@@ -1,4 +1,3 @@ -mmenke@chromium.org - +file://net/OWNERS # COMPONENT: Internals>Network # TEAM: net-dev@chromium.org
diff --git a/components/components_settings_strings.grdp b/components/components_settings_strings.grdp index 59d3fec..6b26a09f 100644 --- a/components/components_settings_strings.grdp +++ b/components/components_settings_strings.grdp
@@ -15,4 +15,7 @@ <message name="IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON" desc="The label of the 'Configure proxy settings' button"> Change proxy settings... </message> + <message name="IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL" desc="Header for multiple automatic downloads page on Content Settings dialog"> + Automatic Downloads + </message> </grit-part>
diff --git a/components/page_info/BUILD.gn b/components/page_info/BUILD.gn new file mode 100644 index 0000000..8fecfec4 --- /dev/null +++ b/components/page_info/BUILD.gn
@@ -0,0 +1,54 @@ +if (is_android) { + import("//build/config/android/rules.gni") +} + +static_library("page_info") { + sources = [ + "page_info.cc", + "page_info.h", + "page_info_delegate.h", + "page_info_ui.cc", + "page_info_ui.h", + "page_info_ui_delegate.h", + ] + + deps = [ + "//base", + "//components/browsing_data/content", + "//components/content_settings/core/browser", + "//components/password_manager/core/browser", + "//components/permissions", + "//components/safe_browsing:buildflags", + "//components/safe_browsing/content/password_protection", + "//components/safe_browsing/content/password_protection:password_protection_metrics_util", + "//components/safe_browsing/core:csd_proto", + "//components/security_interstitials/content:security_interstitial_page", + "//components/security_interstitials/core", + "//components/security_state/core", + "//components/signin/public/identity_manager", + "//components/ssl_errors:ssl_errors", + "//components/strings:components_chromium_strings_grit", + "//components/strings:components_strings_grit", + "//components/subresource_filter/core/browser", + "//components/ukm/content", + "//components/url_formatter", + "//components/vector_icons:vector_icons", + "//content/public/browser:browser", + "//services/device/public/cpp:device_features", + "//services/metrics/public/cpp:ukm_builders", + ] + + if (is_android) { + deps += [ + "//components/browser_ui/util/android", + "//components/password_manager/core/browser:password_manager_java_enums_srcjar", + "//components/resources:android_resources", + ] + } +} + +if (is_android) { + java_cpp_enum("page_info_action_javagen") { + sources = [ "page_info.h" ] + } +}
diff --git a/components/page_info/DEPS b/components/page_info/DEPS new file mode 100644 index 0000000..840067c --- /dev/null +++ b/components/page_info/DEPS
@@ -0,0 +1,33 @@ +include_rules = [ + "+components/browser_ui/util/android/url_constants.h", + "+components/browsing_data/content/local_storage_helper.h", + "+components/content_settings/core", + "+components/password_manager/core/browser/password_manager_metrics_util.h", + "+components/permissions", + "+components/prefs/pref_service.h", + "+components/resources/android", + "+components/safe_browsing", + "+components/security_interstitials/content/stateful_ssl_host_state_delegate.h", + "+components/security_interstitials/core/common_string_util.h", + "+components/security_state/core", + "+components/signin/public/identity_manager/account_info.h", + "+components/ssl_errors/error_info.h", + "+components/strings/grit", + "+components/subresource_filter/core/browser/subresource_filter_features.h", + "+components/ukm/content/source_url_recorder.h", + "+components/url_formatter/elide_url.h", + "+components/vector_icons/vector_icons.h", + "+content/public/browser", + "+content/public/common", + "+media/base/media_switches.h", + "+net/cert/cert_status_flags.h", + "+net/cert/x509_certificate.h", + "+net/ssl/ssl_cipher_suite_names.h", + "+net/ssl/ssl_connection_status_flags.h", + "+ppapi/buildflags/buildflags.h", + "+services/device/public/cpp/device_features.h", + "+services/metrics/public/cpp", + "+third_party/boringssl/src/include/openssl/ssl.h", + "+ui/base/l10n/l10n_util.h", + "+ui/gfx", +]
diff --git a/components/page_info/android/BUILD.gn b/components/page_info/android/BUILD.gn index d2ca446..dfbb1ae 100644 --- a/components/page_info/android/BUILD.gn +++ b/components/page_info/android/BUILD.gn
@@ -27,6 +27,21 @@ android_resources("java_resources") { sources = [ + "java/res/drawable-hdpi/pageinfo_bad.png", + "java/res/drawable-hdpi/pageinfo_good.png", + "java/res/drawable-hdpi/pageinfo_warning.png", + "java/res/drawable-mdpi/pageinfo_bad.png", + "java/res/drawable-mdpi/pageinfo_good.png", + "java/res/drawable-mdpi/pageinfo_warning.png", + "java/res/drawable-xhdpi/pageinfo_bad.png", + "java/res/drawable-xhdpi/pageinfo_good.png", + "java/res/drawable-xhdpi/pageinfo_warning.png", + "java/res/drawable-xxhdpi/pageinfo_bad.png", + "java/res/drawable-xxhdpi/pageinfo_good.png", + "java/res/drawable-xxhdpi/pageinfo_warning.png", + "java/res/drawable-xxxhdpi/pageinfo_bad.png", + "java/res/drawable-xxxhdpi/pageinfo_good.png", + "java/res/drawable-xxxhdpi/pageinfo_warning.png", "java/res/layout/cookie_controls_view.xml", "java/res/layout/page_info.xml", "java/res/layout/page_info_permission_row.xml",
diff --git a/chrome/android/java/res/drawable-hdpi/pageinfo_bad.png b/components/page_info/android/java/res/drawable-hdpi/pageinfo_bad.png similarity index 100% rename from chrome/android/java/res/drawable-hdpi/pageinfo_bad.png rename to components/page_info/android/java/res/drawable-hdpi/pageinfo_bad.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pageinfo_good.png b/components/page_info/android/java/res/drawable-hdpi/pageinfo_good.png similarity index 100% rename from chrome/android/java/res/drawable-hdpi/pageinfo_good.png rename to components/page_info/android/java/res/drawable-hdpi/pageinfo_good.png Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/pageinfo_warning.png b/components/page_info/android/java/res/drawable-hdpi/pageinfo_warning.png similarity index 100% rename from chrome/android/java/res/drawable-hdpi/pageinfo_warning.png rename to components/page_info/android/java/res/drawable-hdpi/pageinfo_warning.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pageinfo_bad.png b/components/page_info/android/java/res/drawable-mdpi/pageinfo_bad.png similarity index 100% rename from chrome/android/java/res/drawable-mdpi/pageinfo_bad.png rename to components/page_info/android/java/res/drawable-mdpi/pageinfo_bad.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pageinfo_good.png b/components/page_info/android/java/res/drawable-mdpi/pageinfo_good.png similarity index 100% rename from chrome/android/java/res/drawable-mdpi/pageinfo_good.png rename to components/page_info/android/java/res/drawable-mdpi/pageinfo_good.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/pageinfo_warning.png b/components/page_info/android/java/res/drawable-mdpi/pageinfo_warning.png similarity index 100% rename from chrome/android/java/res/drawable-mdpi/pageinfo_warning.png rename to components/page_info/android/java/res/drawable-mdpi/pageinfo_warning.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pageinfo_bad.png b/components/page_info/android/java/res/drawable-xhdpi/pageinfo_bad.png similarity index 100% rename from chrome/android/java/res/drawable-xhdpi/pageinfo_bad.png rename to components/page_info/android/java/res/drawable-xhdpi/pageinfo_bad.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pageinfo_good.png b/components/page_info/android/java/res/drawable-xhdpi/pageinfo_good.png similarity index 100% rename from chrome/android/java/res/drawable-xhdpi/pageinfo_good.png rename to components/page_info/android/java/res/drawable-xhdpi/pageinfo_good.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/pageinfo_warning.png b/components/page_info/android/java/res/drawable-xhdpi/pageinfo_warning.png similarity index 100% rename from chrome/android/java/res/drawable-xhdpi/pageinfo_warning.png rename to components/page_info/android/java/res/drawable-xhdpi/pageinfo_warning.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pageinfo_bad.png b/components/page_info/android/java/res/drawable-xxhdpi/pageinfo_bad.png similarity index 100% rename from chrome/android/java/res/drawable-xxhdpi/pageinfo_bad.png rename to components/page_info/android/java/res/drawable-xxhdpi/pageinfo_bad.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pageinfo_good.png b/components/page_info/android/java/res/drawable-xxhdpi/pageinfo_good.png similarity index 100% rename from chrome/android/java/res/drawable-xxhdpi/pageinfo_good.png rename to components/page_info/android/java/res/drawable-xxhdpi/pageinfo_good.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/pageinfo_warning.png b/components/page_info/android/java/res/drawable-xxhdpi/pageinfo_warning.png similarity index 100% rename from chrome/android/java/res/drawable-xxhdpi/pageinfo_warning.png rename to components/page_info/android/java/res/drawable-xxhdpi/pageinfo_warning.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pageinfo_bad.png b/components/page_info/android/java/res/drawable-xxxhdpi/pageinfo_bad.png similarity index 100% rename from chrome/android/java/res/drawable-xxxhdpi/pageinfo_bad.png rename to components/page_info/android/java/res/drawable-xxxhdpi/pageinfo_bad.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pageinfo_good.png b/components/page_info/android/java/res/drawable-xxxhdpi/pageinfo_good.png similarity index 100% rename from chrome/android/java/res/drawable-xxxhdpi/pageinfo_good.png rename to components/page_info/android/java/res/drawable-xxxhdpi/pageinfo_good.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/pageinfo_warning.png b/components/page_info/android/java/res/drawable-xxxhdpi/pageinfo_warning.png similarity index 100% rename from chrome/android/java/res/drawable-xxxhdpi/pageinfo_warning.png rename to components/page_info/android/java/res/drawable-xxxhdpi/pageinfo_warning.png Binary files differ
diff --git a/chrome/browser/ui/page_info/page_info.cc b/components/page_info/page_info.cc similarity index 97% rename from chrome/browser/ui/page_info/page_info.cc rename to components/page_info/page_info.cc index 8965158c..8c34cb80 100644 --- a/chrome/browser/ui/page_info/page_info.cc +++ b/components/page_info/page_info.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/page_info/page_info.h" +#include "components/page_info/page_info.h" #include <stddef.h> #include <stdint.h> @@ -23,9 +23,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" -#include "chrome/browser/ui/page_info/page_info_delegate.h" -#include "chrome/browser/ui/page_info/page_info_ui.h" -#include "chrome/grit/theme_resources.h" #include "components/browser_ui/util/android/url_constants.h" #include "components/browsing_data/content/local_storage_helper.h" #include "components/content_settings/core/browser/content_settings_registry.h" @@ -34,6 +31,8 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_utils.h" +#include "components/page_info/page_info_delegate.h" +#include "components/page_info/page_info_ui.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" @@ -41,6 +40,9 @@ #include "components/permissions/permission_result.h" #include "components/permissions/permission_uma_util.h" #include "components/permissions/permission_util.h" +#if defined(OS_ANDROID) +#include "components/resources/android/theme_resources.h" +#endif #include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/content/password_protection/metrics_util.h" #include "components/safe_browsing/content/password_protection/password_protection_service.h" @@ -70,15 +72,6 @@ #include "ui/base/l10n/l10n_util.h" #include "url/origin.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/policy/policy_cert_service.h" -#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h" -#endif - -#if !defined(OS_ANDROID) -#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" -#endif - using base::ASCIIToUTF16; using base::UTF16ToUTF8; using base::UTF8ToUTF16; @@ -345,11 +338,11 @@ // Record the total time the Page Info UI was open for all opens as well as // split between whether any action was taken. - base::UmaHistogramCustomTimes( - security_state::GetSecurityLevelHistogramName( - kPageInfoTimePrefix, security_level_), - base::TimeTicks::Now() - start_time_, - base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100); + base::UmaHistogramCustomTimes(security_state::GetSecurityLevelHistogramName( + kPageInfoTimePrefix, security_level_), + base::TimeTicks::Now() - start_time_, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromHours(1), 100); base::UmaHistogramCustomTimes( security_state::GetSafetyTipHistogramName(kPageInfoTimePrefix, safety_tip_info_.status), @@ -363,8 +356,8 @@ if (did_perform_action_) { base::UmaHistogramCustomTimes( - security_state::GetSecurityLevelHistogramName( - kPageInfoTimeActionPrefix, security_level_), + security_state::GetSecurityLevelHistogramName(kPageInfoTimeActionPrefix, + security_level_), base::TimeTicks::Now() - start_time_, base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromHours(1), 100);
diff --git a/chrome/browser/ui/page_info/page_info.h b/components/page_info/page_info.h similarity index 98% rename from chrome/browser/ui/page_info/page_info.h rename to components/page_info/page_info.h index 1e2309d..3275d422 100644 --- a/chrome/browser/ui/page_info/page_info.h +++ b/components/page_info/page_info.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_H_ -#define CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_H_ +#ifndef COMPONENTS_PAGE_INFO_PAGE_INFO_H_ +#define COMPONENTS_PAGE_INFO_PAGE_INFO_H_ #include <vector> @@ -342,4 +342,4 @@ DISALLOW_COPY_AND_ASSIGN(PageInfo); }; -#endif // CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_H_ +#endif // COMPONENTS_PAGE_INFO_PAGE_INFO_H_
diff --git a/chrome/browser/ui/page_info/page_info_delegate.h b/components/page_info/page_info_delegate.h similarity index 94% rename from chrome/browser/ui/page_info/page_info_delegate.h rename to components/page_info/page_info_delegate.h index e9d7394..bc4d6ed 100644 --- a/chrome/browser/ui/page_info/page_info_delegate.h +++ b/components/page_info/page_info_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_DELEGATE_H_ -#define CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_DELEGATE_H_ +#ifndef COMPONENTS_PAGE_INFO_PAGE_INFO_DELEGATE_H_ +#define COMPONENTS_PAGE_INFO_PAGE_INFO_DELEGATE_H_ #include "base/strings/string16.h" #include "build/build_config.h" @@ -88,4 +88,4 @@ virtual bool IsContentDisplayedInVrHeadset() = 0; }; -#endif // CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_DELEGATE_H_ +#endif // COMPONENTS_PAGE_INFO_PAGE_INFO_DELEGATE_H_
diff --git a/chrome/browser/ui/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc similarity index 96% rename from chrome/browser/ui/page_info/page_info_ui.cc rename to components/page_info/page_info_ui.cc index 51585bc..7cf58fb8 100644 --- a/chrome/browser/ui/page_info/page_info_ui.cc +++ b/components/page_info/page_info_ui.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/page_info/page_info_ui.h" +#include "components/page_info/page_info_ui.h" #include <utility> @@ -12,11 +12,11 @@ #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "chrome/browser/ui/page_info/page_info_ui_delegate.h" -#include "chrome/grit/generated_resources.h" +#include "components/page_info/page_info_ui_delegate.h" #include "components/permissions/permission_manager.h" #include "components/permissions/permission_result.h" #include "components/permissions/permission_util.h" +#include "components/prefs/pref_service.h" #include "components/safe_browsing/buildflags.h" #include "components/security_interstitials/core/common_string_util.h" #include "components/strings/grit/components_chromium_strings.h" @@ -26,12 +26,9 @@ #include "services/device/public/cpp/device_features.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" - #if defined(OS_ANDROID) -#include "chrome/browser/android/android_theme_resources.h" +#include "components/resources/android/theme_resources.h" #else -#include "chrome/app/vector_icons/vector_icons.h" -#include "components/prefs/pref_service.h" #include "media/base/media_switches.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" @@ -554,13 +551,13 @@ icon = &vector_icons::kCookieIcon; break; case ContentSettingsType::IMAGES: - icon = &kPhotoIcon; + icon = &vector_icons::kPhotoIcon; break; case ContentSettingsType::JAVASCRIPT: - icon = &kCodeIcon; + icon = &vector_icons::kCodeIcon; break; case ContentSettingsType::POPUPS: - icon = &kLaunchIcon; + icon = &vector_icons::kLaunchIcon; break; #if BUILDFLAG(ENABLE_PLUGINS) case ContentSettingsType::PLUGINS: @@ -580,30 +577,30 @@ icon = &vector_icons::kVideocamIcon; break; case ContentSettingsType::AUTOMATIC_DOWNLOADS: - icon = &kFileDownloadIcon; + icon = &vector_icons::kFileDownloadIcon; break; #if defined(OS_CHROMEOS) case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER: - icon = &kProtectedContentIcon; + icon = &vector_icons::kProtectedContentIcon; break; #endif case ContentSettingsType::MIDI_SYSEX: icon = &vector_icons::kMidiIcon; break; case ContentSettingsType::BACKGROUND_SYNC: - icon = &kSyncIcon; + icon = &vector_icons::kSyncIcon; break; case ContentSettingsType::ADS: - icon = &kAdsIcon; + icon = &vector_icons::kAdsIcon; break; case ContentSettingsType::SOUND: - icon = &kVolumeUpIcon; + icon = &vector_icons::kVolumeUpIcon; break; case ContentSettingsType::CLIPBOARD_READ_WRITE: - icon = &kPageInfoContentPasteIcon; + icon = &vector_icons::kPageInfoContentPasteIcon; break; case ContentSettingsType::SENSORS: - icon = &kSensorsIcon; + icon = &vector_icons::kSensorsIcon; break; case ContentSettingsType::USB_GUARD: icon = &vector_icons::kUsbIcon; @@ -618,7 +615,7 @@ icon = &vector_icons::kBluetoothScanningIcon; break; case ContentSettingsType::NATIVE_FILE_SYSTEM_WRITE_GUARD: - icon = &kSaveOriginalFileIcon; + icon = &vector_icons::kSaveOriginalFileIcon; break; case ContentSettingsType::VR: case ContentSettingsType::AR: @@ -638,7 +635,7 @@ return gfx::CreateVectorIconWithBadge( *icon, kVectorIconSize, color_utils::DeriveDefaultIconColor(related_text_color), - kBlockedBadgeIcon); + vector_icons::kBlockedBadgeIcon); } return gfx::CreateVectorIcon( *icon, kVectorIconSize, @@ -676,7 +673,7 @@ return gfx::CreateVectorIconWithBadge( *icon, kVectorIconSize, color_utils::DeriveDefaultIconColor(related_text_color), - kBlockedBadgeIcon); + vector_icons::kBlockedBadgeIcon); } return gfx::CreateVectorIcon( *icon, kVectorIconSize, @@ -687,7 +684,7 @@ const gfx::ImageSkia PageInfoUI::GetCertificateIcon( const SkColor related_text_color) { return gfx::CreateVectorIcon( - kCertificateIcon, kVectorIconSize, + vector_icons::kCertificateIcon, kVectorIconSize, color_utils::DeriveDefaultIconColor(related_text_color)); }
diff --git a/chrome/browser/ui/page_info/page_info_ui.h b/components/page_info/page_info_ui.h similarity index 97% rename from chrome/browser/ui/page_info/page_info_ui.h rename to components/page_info/page_info_ui.h index bd354944..07907da 100644 --- a/chrome/browser/ui/page_info/page_info_ui.h +++ b/components/page_info/page_info_ui.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_UI_H_ -#define CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_UI_H_ +#ifndef COMPONENTS_PAGE_INFO_PAGE_INFO_UI_H_ +#define COMPONENTS_PAGE_INFO_PAGE_INFO_UI_H_ #include <memory> #include <string> @@ -11,9 +11,9 @@ #include "base/strings/string16.h" #include "build/build_config.h" -#include "chrome/browser/ui/page_info/page_info.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/page_info/page_info.h" #include "components/permissions/chooser_context_base.h" #include "components/safe_browsing/buildflags.h" #include "ui/gfx/native_widget_types.h" @@ -261,4 +261,4 @@ typedef PageInfoUI::PermissionInfoList PermissionInfoList; typedef PageInfoUI::ChosenObjectInfoList ChosenObjectInfoList; -#endif // CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_UI_H_ +#endif // COMPONENTS_PAGE_INFO_PAGE_INFO_UI_H_
diff --git a/chrome/browser/ui/page_info/page_info_ui_delegate.h b/components/page_info/page_info_ui_delegate.h similarity index 76% rename from chrome/browser/ui/page_info/page_info_ui_delegate.h rename to components/page_info/page_info_ui_delegate.h index 7ce69098..e5865512 100644 --- a/chrome/browser/ui/page_info/page_info_ui_delegate.h +++ b/components/page_info/page_info_ui_delegate.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_UI_DELEGATE_H_ -#define CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_UI_DELEGATE_H_ +#ifndef COMPONENTS_PAGE_INFO_PAGE_INFO_UI_DELEGATE_H_ +#define COMPONENTS_PAGE_INFO_PAGE_INFO_UI_DELEGATE_H_ #include "build/build_config.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -21,4 +21,4 @@ const GURL& url) = 0; }; -#endif // CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_UI_DELEGATE_H_ +#endif // COMPONENTS_PAGE_INFO_PAGE_INFO_UI_DELEGATE_H_
diff --git a/components/password_manager/core/browser/multi_store_password_save_manager.cc b/components/password_manager/core/browser/multi_store_password_save_manager.cc index 5370ec53..46d4f39 100644 --- a/components/password_manager/core/browser/multi_store_password_save_manager.cc +++ b/components/password_manager/core/browser/multi_store_password_save_manager.cc
@@ -9,7 +9,6 @@ #include "components/password_manager/core/browser/form_saver_impl.h" #include "components/password_manager/core/browser/password_feature_manager_impl.h" #include "components/password_manager/core/browser/password_form_metrics_recorder.h" -#include "components/password_manager/core/browser/password_generation_manager.h" #include "components/password_manager/core/browser/password_manager_util.h" using autofill::PasswordForm; @@ -52,6 +51,50 @@ return false; } +PendingCredentialsState ResolvePendingCredentialsStates( + PendingCredentialsState profile_state, + PendingCredentialsState account_state) { + // Resolve the two states to a single canonical one, according to the + // following hierarchy: + // AUTOMATIC_SAVE > EQUAL_TO_SAVED_MATCH > UPDATE > NEW_LOGIN + // Note that UPDATE and NEW_LOGIN will result in an Update or Save bubble to + // be shown, while AUTOMATIC_SAVE and EQUAL_TO_SAVED_MATCH will result in a + // silent save/update. + // Some interesting cases: + // NEW_LOGIN means that store doesn't know about the credential yet. If the + // other store knows anything at all, then that always wins. + // EQUAL_TO_SAVED_MATCH vs UPDATE: This means one store had a match, the other + // had a mismatch (same username but different password). We want to silently + // update the mismatch, which EQUAL achieves (since it'll still result in an + // update to date_last_used, and updates always go to both stores). + // TODO(crbug.com/1012203): AUTOMATIC_SAVE vs EQUAL: We should still perform + // the silent update for EQUAL (so last_use_date gets updated). + // TODO(crbug.com/1012203): AUTOMATIC_SAVE vs UPDATE: What's the expected + // outcome? Currently we'll auto-save the PSL match and ignore the update + // (which isn't too bad, since on the next submission the update will become + // a silent update through EQUAL_TO_SAVED_MATCH). + // TODO(crbug.com/1012203): AUTOMATIC_SAVE vs AUTOMATIC_SAVE: Somehow make + // sure that the save goes to both stores. + if (profile_state == PendingCredentialsState::AUTOMATIC_SAVE || + account_state == PendingCredentialsState::AUTOMATIC_SAVE) { + return PendingCredentialsState::AUTOMATIC_SAVE; + } + if (profile_state == PendingCredentialsState::EQUAL_TO_SAVED_MATCH || + account_state == PendingCredentialsState::EQUAL_TO_SAVED_MATCH) { + return PendingCredentialsState::EQUAL_TO_SAVED_MATCH; + } + if (profile_state == PendingCredentialsState::UPDATE || + account_state == PendingCredentialsState::UPDATE) { + return PendingCredentialsState::UPDATE; + } + if (profile_state == PendingCredentialsState::NEW_LOGIN || + account_state == PendingCredentialsState::NEW_LOGIN) { + return PendingCredentialsState::NEW_LOGIN; + } + NOTREACHED(); + return PendingCredentialsState::NONE; +} + } // namespace MultiStorePasswordSaveManager::MultiStorePasswordSaveManager( @@ -62,12 +105,6 @@ MultiStorePasswordSaveManager::~MultiStorePasswordSaveManager() = default; -FormSaver* MultiStorePasswordSaveManager::GetFormSaverForGeneration() { - return IsAccountStoreEnabled() && account_store_form_saver_ - ? account_store_form_saver_.get() - : form_saver_.get(); -} - void MultiStorePasswordSaveManager::SaveInternal( const std::vector<const PasswordForm*>& matches, const base::string16& old_password) { @@ -141,10 +178,6 @@ return result; } -bool MultiStorePasswordSaveManager::IsAccountStoreEnabled() { - return client_->GetPasswordFeatureManager()->IsOptedInForAccountStorage(); -} - void MultiStorePasswordSaveManager::MoveCredentialsToAccountStore() { // TODO(crbug.com/1032992): Moving credentials upon an update. FormFetch will // have an outdated credentials. Fix it if this turns out to be a product @@ -183,4 +216,51 @@ } } +std::pair<const autofill::PasswordForm*, PendingCredentialsState> +MultiStorePasswordSaveManager::FindSimilarSavedFormAndComputeState( + const PasswordForm& parsed_submitted_form) const { + const std::vector<const PasswordForm*> matches = + form_fetcher_->GetBestMatches(); + const PasswordForm* similar_saved_form_from_profile_store = + password_manager_util::GetMatchForUpdating(parsed_submitted_form, + ProfileStoreMatches(matches)); + const PasswordForm* similar_saved_form_from_account_store = + password_manager_util::GetMatchForUpdating(parsed_submitted_form, + AccountStoreMatches(matches)); + + // Compute the PendingCredentialsState (i.e. what to do - save, update, silent + // update) separately for the two stores. + PendingCredentialsState profile_state = ComputePendingCredentialsState( + parsed_submitted_form, similar_saved_form_from_profile_store); + PendingCredentialsState account_state = ComputePendingCredentialsState( + parsed_submitted_form, similar_saved_form_from_account_store); + + // Resolve the two states to a single canonical one. + PendingCredentialsState state = + ResolvePendingCredentialsStates(profile_state, account_state); + + // Choose which of the saved forms (if any) to use as the base for updating, + // based on which of the two states won the resolution. + // Note that if we got the same state for both stores, then it doesn't really + // matter which one we pick for updating, since the result will be the same + // anyway. + const PasswordForm* similar_saved_form = nullptr; + if (state == profile_state) + similar_saved_form = similar_saved_form_from_profile_store; + else if (state == account_state) + similar_saved_form = similar_saved_form_from_account_store; + + return std::make_pair(similar_saved_form, state); +} + +FormSaver* MultiStorePasswordSaveManager::GetFormSaverForGeneration() { + return IsAccountStoreEnabled() && account_store_form_saver_ + ? account_store_form_saver_.get() + : form_saver_.get(); +} + +bool MultiStorePasswordSaveManager::IsAccountStoreEnabled() { + return client_->GetPasswordFeatureManager()->IsOptedInForAccountStorage(); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/multi_store_password_save_manager.h b/components/password_manager/core/browser/multi_store_password_save_manager.h index a7bceef..2582472 100644 --- a/components/password_manager/core/browser/multi_store_password_save_manager.h +++ b/components/password_manager/core/browser/multi_store_password_save_manager.h
@@ -42,6 +42,9 @@ void MoveCredentialsToAccountStore() override; protected: + std::pair<const autofill::PasswordForm*, PendingCredentialsState> + FindSimilarSavedFormAndComputeState( + const autofill::PasswordForm& parsed_submitted_form) const override; FormSaver* GetFormSaverForGeneration() override; private:
diff --git a/components/password_manager/core/browser/password_manager_util.cc b/components/password_manager/core/browser/password_manager_util.cc index bb7f3f8..5403015 100644 --- a/components/password_manager/core/browser/password_manager_util.cc +++ b/components/password_manager/core/browser/password_manager_util.cc
@@ -383,52 +383,31 @@ if (!submitted_form.federation_origin.opaque()) return nullptr; - // Find any form(s) that match by username or by username+password. - const PasswordForm* username_password_match = nullptr; - const PasswordForm* username_match = nullptr; - const base::string16& password_to_save = - submitted_form.new_password_value.empty() - ? submitted_form.password_value - : submitted_form.new_password_value; - for (const PasswordForm* form : credentials) { - if (!username_password_match && - form->username_value == submitted_form.username_value && - form->password_value == password_to_save) { - username_password_match = form; - } - if (!username_match && - form->username_value == submitted_form.username_value) { - username_match = form; - } - } + // Try to return form with matching |username_value|. + const PasswordForm* username_match = + FindFormByUsername(credentials, submitted_form.username_value); + if (username_match) { + if (!username_match->is_public_suffix_match) + return username_match; - // First, try to return a non-PSL match. Prefer if the password also matches. - if (username_password_match && - !username_password_match->is_public_suffix_match) { - return username_password_match; + const auto& password_to_save = submitted_form.new_password_value.empty() + ? submitted_form.password_value + : submitted_form.new_password_value; + // Normally, the copy of the PSL matched credentials, adapted for the + // current domain, is saved automatically without asking the user, because + // the copy likely represents the same account, i.e., the one for which + // the user already agreed to store a password. + // + // However, if the user changes the suggested password, it might indicate + // that the autofilled credentials and |submitted_password_form| + // actually correspond to two different accounts (see + // http://crbug.com/385619). + return password_to_save == username_match->password_value ? username_match + : nullptr; } - if (username_match && !username_match->is_public_suffix_match) - return username_match; - - // All matches (if there are any) are PSL matches. We only want to return - // PSL matches if the password also matches: - // - // Normally, the copy of the PSL matched credentials, adapted for the - // current domain, is saved automatically without asking the user, because - // the copy likely represents the same account, i.e., the one for which - // the user already agreed to store a password. - // - // However, if the user changes the suggested password, it might indicate - // that the autofilled credentials and |submitted_password_form| - // actually correspond to two different accounts (see - // http://crbug.com/385619). - if (username_password_match) - return username_password_match; // Next attempt is to find a match by password value. It should not be tried // when the username was actually detected. - if (username_match) - return nullptr; if (submitted_form.type == PasswordForm::Type::kApi || !submitted_form.username_value.empty()) { return nullptr;
diff --git a/components/password_manager/core/browser/password_manager_util_unittest.cc b/components/password_manager/core/browser/password_manager_util_unittest.cc index f5dc0af..3928c582 100644 --- a/components/password_manager/core/browser/password_manager_util_unittest.cc +++ b/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -392,24 +392,6 @@ GetMatchForUpdating(parsed, {&stored3, &stored2, &stored1})); } -TEST(PasswordManagerUtil, - GetMatchForUpdating_DuplicateUsernamePickMatchingPassword) { - // Two credentials with a matching username are stored. One has the same - // password as well, the other has a different password. This can happen when - // one credential comes from the profile store, the other from the password - // store. - autofill::PasswordForm parsed = GetTestCredential(); - autofill::PasswordForm stored_samepw = parsed; - autofill::PasswordForm stored_diffpw = parsed; - stored_diffpw.password_value = base::ASCIIToUTF16("different"); - - // The order of the two stored credentials shouldn't matter. - EXPECT_EQ(&stored_samepw, - GetMatchForUpdating(parsed, {&stored_diffpw, &stored_samepw})); - EXPECT_EQ(&stored_samepw, - GetMatchForUpdating(parsed, {&stored_samepw, &stored_diffpw})); -} - TEST(PasswordManagerUtil, MakeNormalizedBlacklistedForm_Android) { autofill::PasswordForm blacklisted_credential = MakeNormalizedBlacklistedForm( password_manager::PasswordStore::FormDigest(GetTestAndroidCredential()));
diff --git a/components/password_manager/core/browser/password_save_manager_impl.cc b/components/password_manager/core/browser/password_save_manager_impl.cc index b2856654..7f1dc904 100644 --- a/components/password_manager/core/browser/password_save_manager_impl.cc +++ b/components/password_manager/core/browser/password_save_manager_impl.cc
@@ -151,104 +151,6 @@ votes_uploader_ = votes_uploader; } -// static -PendingCredentialsState PasswordSaveManagerImpl::ComputePendingCredentialsState( - const PasswordForm& parsed_submitted_form, - const PasswordForm* similar_saved_form) { - ValueElementPair password_to_save(PasswordToSave(parsed_submitted_form)); - // Check if there are previously saved credentials (that were available to - // autofilling) matching the actually submitted credentials. - if (!similar_saved_form) - return PendingCredentialsState::NEW_LOGIN; - - // A similar credential exists in the store already. - if (similar_saved_form->password_value != password_to_save.first) - return PendingCredentialsState::UPDATE; - - // If the autofilled credentials were a PSL match, store a copy with the - // current origin and signon realm. This ensures that on the next visit, a - // precise match is found. - if (similar_saved_form->is_public_suffix_match) - return PendingCredentialsState::AUTOMATIC_SAVE; - - return PendingCredentialsState::EQUAL_TO_SAVED_MATCH; -} - -// static -PasswordForm PasswordSaveManagerImpl::BuildPendingCredentials( - PendingCredentialsState pending_credentials_state, - const PasswordForm& parsed_submitted_form, - const FormData& observed_form, - const FormData& submitted_form, - const base::Optional<base::string16>& generated_password, - bool is_http_auth, - bool is_credential_api_save, - const PasswordForm* similar_saved_form) { - PasswordForm pending_credentials; - - ValueElementPair password_to_save(PasswordToSave(parsed_submitted_form)); - - switch (pending_credentials_state) { - case PendingCredentialsState::NEW_LOGIN: - // No stored credentials can be matched to the submitted form. Offer to - // save new credentials. - pending_credentials = PendingCredentialsForNewCredentials( - parsed_submitted_form, observed_form, password_to_save.second, - is_http_auth, is_credential_api_save); - break; - case PendingCredentialsState::EQUAL_TO_SAVED_MATCH: - case PendingCredentialsState::UPDATE: - pending_credentials = *similar_saved_form; - break; - case PendingCredentialsState::AUTOMATIC_SAVE: - pending_credentials = *similar_saved_form; - - // Update credential to reflect that it has been used for submission. - // If this isn't updated, then password generation uploads are off for - // sites where PSL matching is required to fill the login form, as two - // PASSWORD votes are uploaded per saved password instead of one. - password_manager_util::UpdateMetadataForUsage(&pending_credentials); - - // Update |pending_credentials| in order to be able correctly save it. - pending_credentials.origin = parsed_submitted_form.origin; - pending_credentials.signon_realm = parsed_submitted_form.signon_realm; - pending_credentials.action = parsed_submitted_form.action; - break; - case PendingCredentialsState::NONE: - NOTREACHED(); - break; - } - - pending_credentials.password_value = - generated_password.value_or(password_to_save.first); - pending_credentials.date_last_used = base::Time::Now(); - pending_credentials.form_has_autofilled_value = - parsed_submitted_form.form_has_autofilled_value; - pending_credentials.all_possible_passwords = - parsed_submitted_form.all_possible_passwords; - CopyFieldPropertiesMasks(submitted_form, &pending_credentials.form_data); - - // If we're dealing with an API-driven provisionally saved form, then take - // the server provided values. We don't do this for non-API forms, as - // those will never have those members set. - if (parsed_submitted_form.type == PasswordForm::Type::kApi) { - pending_credentials.skip_zero_click = parsed_submitted_form.skip_zero_click; - pending_credentials.display_name = parsed_submitted_form.display_name; - pending_credentials.federation_origin = - parsed_submitted_form.federation_origin; - pending_credentials.icon_url = parsed_submitted_form.icon_url; - // It's important to override |signon_realm| for federated credentials - // because it has format "federation://" + origin_host + "/" + - // federation_host - pending_credentials.signon_realm = parsed_submitted_form.signon_realm; - } - - if (generated_password.has_value()) - pending_credentials.type = PasswordForm::Type::kGenerated; - - return pending_credentials; -} - void PasswordSaveManagerImpl::CreatePendingCredentials( const PasswordForm& parsed_submitted_form, const FormData& observed_form, @@ -257,17 +159,9 @@ bool is_credential_api_save) { DCHECK(votes_uploader_); - // This function might be called multiple times so set variables that are - // changed in this function to initial states. - pending_credentials_ = PasswordForm(); - votes_uploader_->set_password_overridden(false); - - const PasswordForm* similar_saved_form = - password_manager_util::GetMatchForUpdating( - parsed_submitted_form, form_fetcher_->GetBestMatches()); - - pending_credentials_state_ = - ComputePendingCredentialsState(parsed_submitted_form, similar_saved_form); + const PasswordForm* similar_saved_form; + std::tie(similar_saved_form, pending_credentials_state_) = + FindSimilarSavedFormAndComputeState(parsed_submitted_form); base::Optional<base::string16> generated_password; if (HasGeneratedPassword()) @@ -278,6 +172,7 @@ submitted_form, generated_password, is_http_auth, is_credential_api_save, similar_saved_form); + votes_uploader_->set_password_overridden(false); switch (pending_credentials_state_) { case PendingCredentialsState::NEW_LOGIN: { // Generate username correction votes. @@ -445,17 +340,127 @@ return result; } +// static +PendingCredentialsState PasswordSaveManagerImpl::ComputePendingCredentialsState( + const PasswordForm& parsed_submitted_form, + const PasswordForm* similar_saved_form) { + ValueElementPair password_to_save(PasswordToSave(parsed_submitted_form)); + // Check if there are previously saved credentials (that were available to + // autofilling) matching the actually submitted credentials. + if (!similar_saved_form) + return PendingCredentialsState::NEW_LOGIN; + + // A similar credential exists in the store already. + if (similar_saved_form->password_value != password_to_save.first) + return PendingCredentialsState::UPDATE; + + // If the autofilled credentials were a PSL match, store a copy with the + // current origin and signon realm. This ensures that on the next visit, a + // precise match is found. + if (similar_saved_form->is_public_suffix_match) + return PendingCredentialsState::AUTOMATIC_SAVE; + + return PendingCredentialsState::EQUAL_TO_SAVED_MATCH; +} + +// static +PasswordForm PasswordSaveManagerImpl::BuildPendingCredentials( + PendingCredentialsState pending_credentials_state, + const PasswordForm& parsed_submitted_form, + const FormData& observed_form, + const FormData& submitted_form, + const base::Optional<base::string16>& generated_password, + bool is_http_auth, + bool is_credential_api_save, + const PasswordForm* similar_saved_form) { + PasswordForm pending_credentials; + + ValueElementPair password_to_save(PasswordToSave(parsed_submitted_form)); + + switch (pending_credentials_state) { + case PendingCredentialsState::NEW_LOGIN: + // No stored credentials can be matched to the submitted form. Offer to + // save new credentials. + pending_credentials = PendingCredentialsForNewCredentials( + parsed_submitted_form, observed_form, password_to_save.second, + is_http_auth, is_credential_api_save); + break; + case PendingCredentialsState::EQUAL_TO_SAVED_MATCH: + case PendingCredentialsState::UPDATE: + pending_credentials = *similar_saved_form; + break; + case PendingCredentialsState::AUTOMATIC_SAVE: + pending_credentials = *similar_saved_form; + + // Update credential to reflect that it has been used for submission. + // If this isn't updated, then password generation uploads are off for + // sites where PSL matching is required to fill the login form, as two + // PASSWORD votes are uploaded per saved password instead of one. + password_manager_util::UpdateMetadataForUsage(&pending_credentials); + + // Update |pending_credentials| in order to be able correctly save it. + pending_credentials.origin = parsed_submitted_form.origin; + pending_credentials.signon_realm = parsed_submitted_form.signon_realm; + pending_credentials.action = parsed_submitted_form.action; + break; + case PendingCredentialsState::NONE: + NOTREACHED(); + break; + } + + pending_credentials.password_value = + generated_password.value_or(password_to_save.first); + pending_credentials.date_last_used = base::Time::Now(); + pending_credentials.form_has_autofilled_value = + parsed_submitted_form.form_has_autofilled_value; + pending_credentials.all_possible_passwords = + parsed_submitted_form.all_possible_passwords; + CopyFieldPropertiesMasks(submitted_form, &pending_credentials.form_data); + + // If we're dealing with an API-driven provisionally saved form, then take + // the server provided values. We don't do this for non-API forms, as + // those will never have those members set. + if (parsed_submitted_form.type == PasswordForm::Type::kApi) { + pending_credentials.skip_zero_click = parsed_submitted_form.skip_zero_click; + pending_credentials.display_name = parsed_submitted_form.display_name; + pending_credentials.federation_origin = + parsed_submitted_form.federation_origin; + pending_credentials.icon_url = parsed_submitted_form.icon_url; + // It's important to override |signon_realm| for federated credentials + // because it has format "federation://" + origin_host + "/" + + // federation_host + pending_credentials.signon_realm = parsed_submitted_form.signon_realm; + } + + if (generated_password.has_value()) + pending_credentials.type = PasswordForm::Type::kGenerated; + + return pending_credentials; +} + +std::pair<const autofill::PasswordForm*, PendingCredentialsState> +PasswordSaveManagerImpl::FindSimilarSavedFormAndComputeState( + const PasswordForm& parsed_submitted_form) const { + const PasswordForm* similar_saved_form = + password_manager_util::GetMatchForUpdating( + parsed_submitted_form, form_fetcher_->GetBestMatches()); + return std::make_pair(similar_saved_form, + ComputePendingCredentialsState(parsed_submitted_form, + similar_saved_form)); +} + void PasswordSaveManagerImpl::SavePendingToStore( const PasswordForm& parsed_submitted_form, bool update) { - const PasswordForm* saved_form = password_manager_util::GetMatchForUpdating( - parsed_submitted_form, form_fetcher_->GetBestMatches()); + const PasswordForm* similar_saved_form = + FindSimilarSavedFormAndComputeState(parsed_submitted_form).first; if ((update || IsPasswordUpdate()) && !pending_credentials_.IsFederatedCredential()) { - DCHECK(saved_form); + DCHECK(similar_saved_form); } - base::string16 old_password = - saved_form ? saved_form->password_value : base::string16(); + base::string16 old_password = similar_saved_form + ? similar_saved_form->password_value + : base::string16(); if (HasGeneratedPassword()) { generation_manager_->CommitGeneratedPassword( pending_credentials_, form_fetcher_->GetAllRelevantMatches(),
diff --git a/components/password_manager/core/browser/password_save_manager_impl.h b/components/password_manager/core/browser/password_save_manager_impl.h index b7f6986..328d13e 100644 --- a/components/password_manager/core/browser/password_save_manager_impl.h +++ b/components/password_manager/core/browser/password_save_manager_impl.h
@@ -97,6 +97,10 @@ bool is_credential_api_save, const autofill::PasswordForm* similar_saved_form); + virtual std::pair<const autofill::PasswordForm*, PendingCredentialsState> + FindSimilarSavedFormAndComputeState( + const autofill::PasswordForm& parsed_submitted_form) const; + // Returns the form_saver to be used for generated passwords. Subclasses will // override this method to provide different logic for get the form saver. virtual FormSaver* GetFormSaverForGeneration();
diff --git a/components/permissions/BUILD.gn b/components/permissions/BUILD.gn index d70ee05f..2a4eb7e 100644 --- a/components/permissions/BUILD.gn +++ b/components/permissions/BUILD.gn
@@ -61,8 +61,6 @@ "android/permission_dialog_delegate.h", "android/permission_prompt_android.cc", "android/permission_prompt_android.h", - "android/resource_id.h", - "android/theme_resources.h", "contexts/geolocation_permission_context_android.cc", "contexts/geolocation_permission_context_android.h", ] @@ -72,6 +70,7 @@ "//components/location/android:settings", "//components/permissions/android:jni_headers", "//components/prefs", + "//components/resources:android_resources", "//ui/android", ] } else { @@ -107,6 +106,9 @@ "//ui/gfx", "//url", ] + if (is_android) { + deps += [ "//components/resources:android_resources" ] + } } source_set("unit_tests") {
diff --git a/components/permissions/DEPS b/components/permissions/DEPS index 701faa8..24f11b1f 100644 --- a/components/permissions/DEPS +++ b/components/permissions/DEPS
@@ -2,6 +2,7 @@ "+components/content_settings/core", "+components/keyed_service/content", "+components/keyed_service/core", + "+components/resources/android", "+components/strings", "+components/sync_preferences", "+components/ukm/content",
diff --git a/components/permissions/android/permission_prompt_android.cc b/components/permissions/android/permission_prompt_android.cc index 57730f9..852b148 100644 --- a/components/permissions/android/permission_prompt_android.cc +++ b/components/permissions/android/permission_prompt_android.cc
@@ -9,9 +9,9 @@ #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_manager.h" #include "components/permissions/android/permission_dialog_delegate.h" -#include "components/permissions/android/theme_resources.h" #include "components/permissions/permission_request.h" #include "components/permissions/permissions_client.h" +#include "components/resources/android/theme_resources.h" #include "components/strings/grit/components_strings.h" #include "components/url_formatter/elide_url.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/components/permissions/permission_request_impl.cc b/components/permissions/permission_request_impl.cc index 54960201..e740cb7 100644 --- a/components/permissions/permission_request_impl.cc +++ b/components/permissions/permission_request_impl.cc
@@ -13,7 +13,7 @@ #include "ui/base/l10n/l10n_util.h" #if defined(OS_ANDROID) -#include "components/permissions/android/theme_resources.h" +#include "components/resources/android/theme_resources.h" #include "media/base/android/media_drm_bridge.h" #else #include "components/vector_icons/vector_icons.h"
diff --git a/components/permissions/quota_permission_context_impl.cc b/components/permissions/quota_permission_context_impl.cc index d145631b..fff8d90 100644 --- a/components/permissions/quota_permission_context_impl.cc +++ b/components/permissions/quota_permission_context_impl.cc
@@ -27,7 +27,7 @@ #include "url/gurl.h" #if defined(OS_ANDROID) -#include "components/permissions/android/theme_resources.h" +#include "components/resources/android/theme_resources.h" #else #include "components/vector_icons/vector_icons.h" #endif
diff --git a/components/permissions/test/mock_permission_request.cc b/components/permissions/test/mock_permission_request.cc index 7144503d..0e62cbb 100644 --- a/components/permissions/test/mock_permission_request.cc +++ b/components/permissions/test/mock_permission_request.cc
@@ -8,7 +8,7 @@ #include "base/strings/utf_string_conversions.h" #if defined(OS_ANDROID) -#include "components/permissions/android/theme_resources.h" +#include "components/resources/android/theme_resources.h" #else #include "components/vector_icons/vector_icons.h" #endif
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn index db5699e..49a0480 100644 --- a/components/resources/BUILD.gn +++ b/components/resources/BUILD.gn
@@ -7,6 +7,10 @@ import("//printing/buildflags/buildflags.gni") import("//tools/grit/grit_rule.gni") +if (is_android) { + import("//build/config/android/rules.gni") +} + about_credits_file = "$target_gen_dir/about_credits.html" group("resources") { @@ -100,3 +104,13 @@ rebase_path(about_credits_file, root_build_dir), ] } + +if (is_android) { + source_set("android_resources") { + sources = [ + "android/page_info_resource_id.h", + "android/permissions_resource_id.h", + "android/theme_resources.h", + ] + } +}
diff --git a/components/resources/android/page_info_resource_id.h b/components/resources/android/page_info_resource_id.h new file mode 100644 index 0000000..f1612bd --- /dev/null +++ b/components/resources/android/page_info_resource_id.h
@@ -0,0 +1,41 @@ +// 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. + +// This file maps resource IDs to Android resource IDs. + +// Presence of regular include guards is checked by: +// 1. cpplint +// 2. a custom presubmit in src/PRESUBMIT.py +// 3. clang (but it only checks the guard is correct if present) +// Disable the first two with these magic comments: +// NOLINT(build/header_guard) +// no-include-guard-because-multiply-included + +// LINK_RESOURCE_ID is used for IDs that come from a .grd file. +#ifndef LINK_RESOURCE_ID +#error "LINK_RESOURCE_ID should be defined before including this file" +#endif +// DECLARE_RESOURCE_ID is used for IDs that don't have .grd entries, and +// are only declared in this file. +#ifndef DECLARE_RESOURCE_ID +#error "DECLARE_RESOURCE_ID should be defined before including this file" +#endif + +// PageInfoUI images, used in ConnectionInfoPopup +// Good: +DECLARE_RESOURCE_ID(IDR_PAGEINFO_GOOD, R.drawable.pageinfo_good) +// Warnings: +DECLARE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MINOR, R.drawable.pageinfo_warning) +// Bad: +DECLARE_RESOURCE_ID(IDR_PAGEINFO_BAD, R.drawable.pageinfo_bad) +// Should never occur, use warning just in case: +// Enterprise managed: ChromeOS only. +DECLARE_RESOURCE_ID(IDR_PAGEINFO_ENTERPRISE_MANAGED, + R.drawable.pageinfo_warning) +// Info: Only shown on chrome:// urls, which don't show the connection info +// popup. +DECLARE_RESOURCE_ID(IDR_PAGEINFO_INFO, R.drawable.pageinfo_warning) +// Major warning: Used on insecure pages, which don't show the connection info +// popup. +DECLARE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MAJOR, R.drawable.pageinfo_warning)
diff --git a/components/permissions/android/resource_id.h b/components/resources/android/permissions_resource_id.h similarity index 100% rename from components/permissions/android/resource_id.h rename to components/resources/android/permissions_resource_id.h
diff --git a/components/permissions/android/theme_resources.h b/components/resources/android/theme_resources.h similarity index 66% rename from components/permissions/android/theme_resources.h rename to components/resources/android/theme_resources.h index 1d73e9f2..a84712d 100644 --- a/components/permissions/android/theme_resources.h +++ b/components/resources/android/theme_resources.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_PERMISSIONS_ANDROID_THEME_RESOURCES_H_ -#define COMPONENTS_PERMISSIONS_ANDROID_THEME_RESOURCES_H_ +#ifndef COMPONENTS_RESOURCES_ANDROID_THEME_RESOURCES_H_ +#define COMPONENTS_RESOURCES_ANDROID_THEME_RESOURCES_H_ // LINK_RESOURCE_ID will use an ID defined by grit, so no-op. #define LINK_RESOURCE_ID(c_id, java_id) @@ -11,16 +11,15 @@ #define DECLARE_RESOURCE_ID(c_id, java_id) c_id, enum { - // TODO: If more components need to use resource ID mapping, move this to a - // common location. // Not used; just provides a starting value for the enum. These must // not conflict with IDR_* values, which top out at 2^16 - 1. ANDROID_COMPONENTS_RESOURCE_ID_NONE = 1 << 16, -#include "components/permissions/android/resource_id.h" +#include "components/resources/android/page_info_resource_id.h" +#include "components/resources/android/permissions_resource_id.h" ANDROID_COMPONENTS_RESOURCE_ID_MAX, }; #undef LINK_RESOURCE_ID #undef DECLARE_RESOURCE_ID -#endif // COMPONENTS_PERMISSIONS_ANDROID_THEME_RESOURCES_H_ +#endif // COMPONENTS_RESOURCES_ANDROID_THEME_RESOURCES_H_
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java index 710127c..15a166a3 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
@@ -46,7 +46,6 @@ */ public class AccountManagerFacade { private static final String TAG = "Sync_Signin"; - public static final String GOOGLE_ACCOUNT_TYPE = "com.google"; /** * An account feature (corresponding to a Gaia service flag) that specifies whether the account @@ -129,15 +128,6 @@ } /** - * Creates an Account object for the given name. - * TODO(https://crbug.com/1064877): Move this method to AccountUtils - */ - @AnyThread - public static Account createAccountFromName(String name) { - return new Account(name, GOOGLE_ACCOUNT_TYPE); - } - - /** * Runs a callback after the account list cache is populated. In the callback * {@link #getGoogleAccounts()} and similar methods are guaranteed to return instantly (without * blocking and waiting for the cache to be populated). If the cache has already been populated, @@ -296,7 +286,7 @@ public boolean hasGoogleAccountAuthenticator() { AuthenticatorDescription[] descs = mDelegate.getAuthenticatorTypes(); for (AuthenticatorDescription desc : descs) { - if (GOOGLE_ACCOUNT_TYPE.equals(desc.type)) return true; + if (AccountUtils.GOOGLE_ACCOUNT_TYPE.equals(desc.type)) return true; } return false; }
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountUtils.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountUtils.java index 7007a48..7723c75 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountUtils.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountUtils.java
@@ -4,17 +4,31 @@ package org.chromium.components.signin; +import android.accounts.Account; + +import androidx.annotation.VisibleForTesting; + import java.util.Locale; import java.util.regex.Pattern; /** * AccountUtils groups some static util methods for account. */ -class AccountUtils { +public class AccountUtils { private static final Pattern AT_SYMBOL = Pattern.compile("@"); private static final String GMAIL_COM = "gmail.com"; private static final String GOOGLEMAIL_COM = "googlemail.com"; + @VisibleForTesting + public static final String GOOGLE_ACCOUNT_TYPE = "com.google"; + + /** + * Creates an Account object for the given name. + */ + public static Account createAccountFromName(String name) { + return new Account(name, GOOGLE_ACCOUNT_TYPE); + } + /** * Canonicalizes the account name. */
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java index fbbab80..730e5a8 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java
@@ -40,7 +40,7 @@ long nativeAccountFetcherService, String accountId, String accountName) { mNativeAccountFetcherService = nativeAccountFetcherService; mAccountId = accountId; - mAccount = AccountManagerFacade.createAccountFromName(accountName); + mAccount = AccountUtils.createAccountFromName(accountName); // Register for notifications about flag changes in the future. mAccountFlagsChangedReceiver = new BroadcastReceiver() {
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java index 4327b1bd..f12d1ad 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java
@@ -42,7 +42,7 @@ if (syncAccountName == null) { return null; } - return AccountManagerFacade.createAccountFromName(syncAccountName); + return AccountUtils.createAccountFromName(syncAccountName); } public boolean isSignedIn() {
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java index 3763244e..4fb1f3d8 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
@@ -136,7 +136,7 @@ @Override public String getAuthToken(Account account, String authTokenScope) throws AuthException { assert !ThreadUtils.runningOnUiThread(); - assert AccountManagerFacade.GOOGLE_ACCOUNT_TYPE.equals(account.type); + assert AccountUtils.GOOGLE_ACCOUNT_TYPE.equals(account.type); try { return GoogleAuthUtil.getTokenWithNotification( ContextUtils.getApplicationContext(), account, authTokenScope, null);
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java index 331152a..bf5b7f52 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
@@ -19,8 +19,8 @@ import org.chromium.base.ObserverList; import org.chromium.base.ThreadUtils; import org.chromium.components.signin.AccountManagerDelegate; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.AccountsChangeObserver; import org.chromium.components.signin.AuthException; import org.chromium.components.signin.ProfileDataSource; @@ -287,8 +287,8 @@ @Override public AuthenticatorDescription[] getAuthenticatorTypes() { - AuthenticatorDescription googleAuthenticator = new AuthenticatorDescription( - AccountManagerFacade.GOOGLE_ACCOUNT_TYPE, "p1", 0, 0, 0, 0); + AuthenticatorDescription googleAuthenticator = + new AuthenticatorDescription(AccountUtils.GOOGLE_ACCOUNT_TYPE, "p1", 0, 0, 0, 0); return new AuthenticatorDescription[] {googleAuthenticator}; }
diff --git a/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java b/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java index 15f7d6a9..8c474e3 100644 --- a/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java +++ b/components/signin/core/browser/android/junit/src/org/chromium/components/signin/test/AccountManagerFacadeRobolectricTest.java
@@ -29,6 +29,7 @@ import org.chromium.components.signin.AccountManagerDelegateException; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChildAccountStatus; import org.chromium.components.signin.ProfileDataSource; import org.chromium.components.signin.test.util.AccountHolder; @@ -241,7 +242,7 @@ } private Account addTestAccount(String accountName, String... features) { - Account account = AccountManagerFacade.createAccountFromName(accountName); + Account account = AccountUtils.createAccountFromName(accountName); AccountHolder holder = AccountHolder.builder(account) .alwaysAccept(true) .featureSet(new HashSet<>(Arrays.asList(features)))
diff --git a/components/signin/public/android/DEPS b/components/signin/public/android/DEPS index a373d81..93b627e 100644 --- a/components/signin/public/android/DEPS +++ b/components/signin/public/android/DEPS
@@ -1,6 +1,6 @@ specific_include_rules = { "CoreAccountInfo.java": [ - "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java", + "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountUtils.java", ], "IdentityManager.java": [ "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java",
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/base/CoreAccountInfo.java b/components/signin/public/android/java/src/org/chromium/components/signin/base/CoreAccountInfo.java index d8b06f87..8d1cce8 100644 --- a/components/signin/public/android/java/src/org/chromium/components/signin/base/CoreAccountInfo.java +++ b/components/signin/public/android/java/src/org/chromium/components/signin/base/CoreAccountInfo.java
@@ -10,7 +10,7 @@ import androidx.annotation.Nullable; import org.chromium.base.annotations.CalledByNative; -import org.chromium.components.signin.AccountManagerFacade; +import org.chromium.components.signin.AccountUtils; /** * Structure storing the core information about a Google account that is always known. The {@link @@ -91,9 +91,8 @@ * @return {@link Account} for the argument if it is not null, null otherwise. */ public static @Nullable Account getAndroidAccountFrom(@Nullable CoreAccountInfo accountInfo) { - return accountInfo == null - ? null - : AccountManagerFacade.createAccountFromName(accountInfo.getEmail()); + return accountInfo == null ? null + : AccountUtils.createAccountFromName(accountInfo.getEmail()); } /**
diff --git a/components/sync/android/javatests/src/org/chromium/components/sync/AndroidSyncSettingsTest.java b/components/sync/android/javatests/src/org/chromium/components/sync/AndroidSyncSettingsTest.java index 383ab6b4..6741359 100644 --- a/components/sync/android/javatests/src/org/chromium/components/sync/AndroidSyncSettingsTest.java +++ b/components/sync/android/javatests/src/org/chromium/components/sync/AndroidSyncSettingsTest.java
@@ -20,8 +20,8 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Feature; -import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.AccountManagerFacadeProvider; +import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.test.util.AccountHolder; import org.chromium.components.signin.test.util.FakeAccountManagerDelegate; @@ -146,7 +146,7 @@ } private Account addTestAccount(String name) { - Account account = AccountManagerFacade.createAccountFromName(name); + Account account = AccountUtils.createAccountFromName(name); AccountHolder holder = AccountHolder.builder(account).alwaysAccept(true).build(); mAccountManager.addAccountHolderBlocking(holder); return account;
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn index d6ac30d..1c74f0b 100644 --- a/components/vector_icons/BUILD.gn +++ b/components/vector_icons/BUILD.gn
@@ -9,15 +9,19 @@ icons = [ "accessibility.icon", + "ads.icon", "back_arrow.icon", + "blocked_badge.icon", "bluetooth.icon", "bluetooth_connected.icon", "bluetooth_scanning.icon", "business.icon", "call.icon", + "certificate.icon", "check_circle.icon", "close.icon", "close_rounded.icon", + "code.icon", "content_paste.icon", "cookie.icon", "devices.icon", @@ -25,6 +29,7 @@ "error.icon", "ethernet.icon", "extension.icon", + "file_download.icon", "folder.icon", "folder_managed.icon", "folder_managed_touch.icon", @@ -36,6 +41,7 @@ "help_outline.icon", "info_outline.icon", "insert_drive_file_outline.icon", + "launch.icon", "lightbulb_outline.icon", "location_on.icon", "lock.icon", @@ -54,18 +60,25 @@ "notifications.icon", "notifications_off.icon", "open_in_new.icon", + "page_info_content_paste.icon", "pause.icon", + "photo.icon", "play_arrow.icon", + "protected_content.icon", "protocol_handler.icon", "reload.icon", "replay.icon", + "save_original_file.icon", "screen_share.icon", "search.icon", + "sensors.icon", "serial_port.icon", "settings.icon", + "sync.icon", "usb.icon", "videocam.icon", "videogame_asset.icon", + "volume_up.icon", "vr_headset.icon", "warning.icon", "wifi_add.icon",
diff --git a/chrome/app/vector_icons/ads.icon b/components/vector_icons/ads.icon similarity index 100% rename from chrome/app/vector_icons/ads.icon rename to components/vector_icons/ads.icon
diff --git a/chrome/app/vector_icons/blocked_badge.icon b/components/vector_icons/blocked_badge.icon similarity index 100% rename from chrome/app/vector_icons/blocked_badge.icon rename to components/vector_icons/blocked_badge.icon
diff --git a/chrome/app/vector_icons/certificate.icon b/components/vector_icons/certificate.icon similarity index 100% rename from chrome/app/vector_icons/certificate.icon rename to components/vector_icons/certificate.icon
diff --git a/chrome/app/vector_icons/code.icon b/components/vector_icons/code.icon similarity index 100% rename from chrome/app/vector_icons/code.icon rename to components/vector_icons/code.icon
diff --git a/chrome/app/vector_icons/file_download.icon b/components/vector_icons/file_download.icon similarity index 100% rename from chrome/app/vector_icons/file_download.icon rename to components/vector_icons/file_download.icon
diff --git a/chrome/app/vector_icons/launch.icon b/components/vector_icons/launch.icon similarity index 100% rename from chrome/app/vector_icons/launch.icon rename to components/vector_icons/launch.icon
diff --git a/chrome/app/vector_icons/page_info_content_paste.icon b/components/vector_icons/page_info_content_paste.icon similarity index 100% rename from chrome/app/vector_icons/page_info_content_paste.icon rename to components/vector_icons/page_info_content_paste.icon
diff --git a/chrome/app/vector_icons/photo.icon b/components/vector_icons/photo.icon similarity index 100% rename from chrome/app/vector_icons/photo.icon rename to components/vector_icons/photo.icon
diff --git a/chrome/app/vector_icons/protected_content.icon b/components/vector_icons/protected_content.icon similarity index 100% rename from chrome/app/vector_icons/protected_content.icon rename to components/vector_icons/protected_content.icon
diff --git a/chrome/app/vector_icons/save_original_file.icon b/components/vector_icons/save_original_file.icon similarity index 100% rename from chrome/app/vector_icons/save_original_file.icon rename to components/vector_icons/save_original_file.icon
diff --git a/chrome/app/vector_icons/sensors.icon b/components/vector_icons/sensors.icon similarity index 100% rename from chrome/app/vector_icons/sensors.icon rename to components/vector_icons/sensors.icon
diff --git a/chrome/app/vector_icons/sync.icon b/components/vector_icons/sync.icon similarity index 100% rename from chrome/app/vector_icons/sync.icon rename to components/vector_icons/sync.icon
diff --git a/chrome/app/vector_icons/volume_up.icon b/components/vector_icons/volume_up.icon similarity index 100% rename from chrome/app/vector_icons/volume_up.icon rename to components/vector_icons/volume_up.icon
diff --git a/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc b/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc index de120cc2..f5c8d98 100644 --- a/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc +++ b/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
@@ -6,9 +6,9 @@ #include <memory> -#include "base/macros.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkCanvas.h" #include "ui/compositor/compositor.h" @@ -29,32 +29,25 @@ namespace { -class TestPlatformWindowDelegate : public ui::PlatformWindowDelegate { +class TestSurfaceOzoneCanvas : public ui::SurfaceOzoneCanvas { public: - TestPlatformWindowDelegate() : widget_(gfx::kNullAcceleratedWidget) {} - ~TestPlatformWindowDelegate() override {} + TestSurfaceOzoneCanvas() = default; + ~TestSurfaceOzoneCanvas() override = default; - gfx::AcceleratedWidget GetAcceleratedWidget() const { return widget_; } - - // ui::PlatformWindowDelegate: - void OnBoundsChanged(const gfx::Rect& new_bounds) override {} - void OnDamageRect(const gfx::Rect& damaged_region) override {} - void DispatchEvent(ui::Event* event) override {} - void OnCloseRequest() override {} - void OnClosed() override {} - void OnWindowStateChanged(ui::PlatformWindowState new_state) override {} - void OnLostCapture() override {} - void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override { - widget_ = widget; + // ui::SurfaceOzoneCanvas override: + SkCanvas* GetCanvas() override { return surface_->getCanvas(); } + void ResizeCanvas(const gfx::Size& viewport_size) override { + surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul( + viewport_size.width(), viewport_size.height())); } - void OnAcceleratedWidgetDestroyed() override {} - void OnActivationChanged(bool active) override {} - void OnMouseEnter() override {} + std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override { + return nullptr; + } + + MOCK_METHOD1(PresentCanvas, void(const gfx::Rect& damage)); private: - gfx::AcceleratedWidget widget_; - - DISALLOW_COPY_AND_ASSIGN(TestPlatformWindowDelegate); + sk_sp<SkSurface> surface_; }; } // namespace @@ -63,6 +56,9 @@ public: SoftwareOutputDeviceOzoneTest(); ~SoftwareOutputDeviceOzoneTest() override; + SoftwareOutputDeviceOzoneTest(const SoftwareOutputDeviceOzoneTest&) = delete; + SoftwareOutputDeviceOzoneTest& operator=( + const SoftwareOutputDeviceOzoneTest&) = delete; void SetUp() override; void TearDown() override; @@ -71,95 +67,49 @@ std::unique_ptr<SoftwareOutputDeviceOzone> output_device_; bool enable_pixel_output_ = false; - private: - std::unique_ptr<ui::TestContextFactories> context_factories_; - std::unique_ptr<ui::Compositor> compositor_; - TestPlatformWindowDelegate window_delegate_; - - DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceOzoneTest); + TestSurfaceOzoneCanvas* surface_ozone_ = nullptr; }; SoftwareOutputDeviceOzoneTest::SoftwareOutputDeviceOzoneTest() = default; SoftwareOutputDeviceOzoneTest::~SoftwareOutputDeviceOzoneTest() = default; void SoftwareOutputDeviceOzoneTest::SetUp() { - ui::OzonePlatform::InitParams params; - params.single_process = true; - ui::OzonePlatform::InitializeForUI(params); - ui::OzonePlatform::InitializeForGPU(params); - - ui::PlatformWindowInitProperties properties; - properties.bounds = gfx::Rect(800, 600, 100, 100); - auto platform_window = ui::OzonePlatform::GetInstance()->CreatePlatformWindow( - &window_delegate_, std::move(properties)); - platform_window->Show(); - - context_factories_ = - std::make_unique<ui::TestContextFactories>(enable_pixel_output_); - - const gfx::Size size(500, 400); - compositor_ = std::make_unique<ui::Compositor>( - FrameSinkId(1, 1), context_factories_->GetContextFactory(), - base::ThreadTaskRunnerHandle::Get(), false /* enable_pixel_canvas */); - compositor_->SetAcceleratedWidget(window_delegate_.GetAcceleratedWidget()); - compositor_->SetScaleAndSize(1.0f, size, LocalSurfaceIdAllocation()); - - ui::SurfaceFactoryOzone* factory = - ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone(); - std::unique_ptr<ui::PlatformWindowSurface> platform_window_surface = - factory->CreatePlatformWindowSurface(compositor_->widget()); - std::unique_ptr<ui::SurfaceOzoneCanvas> surface_ozone = - factory->CreateCanvasForWidget(compositor_->widget(), nullptr); - if (!surface_ozone) { - LOG(ERROR) << "SurfaceOzoneCanvas not constructible on this platform"; - } else { - output_device_ = std::make_unique<SoftwareOutputDeviceOzone>( - std::move(platform_window_surface), std::move(surface_ozone)); - } - if (output_device_) - output_device_->Resize(size, 1.f); + std::unique_ptr<TestSurfaceOzoneCanvas> surface_ozone = + std::make_unique<TestSurfaceOzoneCanvas>(); + surface_ozone_ = surface_ozone.get(); + output_device_ = std::make_unique<SoftwareOutputDeviceOzone>( + nullptr, std::move(surface_ozone)); } void SoftwareOutputDeviceOzoneTest::TearDown() { output_device_.reset(); - compositor_.reset(); - context_factories_.reset(); -} - -class SoftwareOutputDeviceOzonePixelTest - : public SoftwareOutputDeviceOzoneTest { - protected: - void SetUp() override; -}; - -void SoftwareOutputDeviceOzonePixelTest::SetUp() { - enable_pixel_output_ = true; - SoftwareOutputDeviceOzoneTest::SetUp(); } TEST_F(SoftwareOutputDeviceOzoneTest, CheckCorrectResizeBehavior) { - // Check if software rendering mode is not supported. - if (!output_device_) - return; - - gfx::Rect damage(0, 0, 100, 100); - gfx::Size size(200, 100); + constexpr gfx::Size size(200, 100); // Reduce size. output_device_->Resize(size, 1.f); - SkCanvas* canvas = output_device_->BeginPaint(damage); + constexpr gfx::Rect damage1(0, 0, 100, 100); + SkCanvas* canvas = output_device_->BeginPaint(damage1); + ASSERT_TRUE(canvas); gfx::Size canvas_size(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().height()); - EXPECT_EQ(size.ToString(), canvas_size.ToString()); + EXPECT_EQ(size, canvas_size); + EXPECT_CALL(*surface_ozone_, PresentCanvas(damage1)).Times(1); + output_device_->EndPaint(); - size.SetSize(1000, 500); + constexpr gfx::Size size2(1000, 500); // Increase size. - output_device_->Resize(size, 1.f); + output_device_->Resize(size2, 1.f); - canvas = output_device_->BeginPaint(damage); + constexpr gfx::Rect damage2(0, 0, 50, 60); + canvas = output_device_->BeginPaint(damage2); canvas_size.SetSize(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().height()); - EXPECT_EQ(size.ToString(), canvas_size.ToString()); + EXPECT_EQ(size2, canvas_size); + EXPECT_CALL(*surface_ozone_, PresentCanvas(damage2)).Times(1); + output_device_->EndPaint(); } } // namespace viz
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 40f7ad4..9355cd6 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -328,6 +328,10 @@ RunCSSTest(FILE_PATH_LITERAL("table-data-display-other.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSOverflow) { + RunCSSTest(FILE_PATH_LITERAL("overflow.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSTransform) { RunCSSTest(FILE_PATH_LITERAL("transform.html")); }
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc index 2d0ca48..b209ce3 100644 --- a/content/browser/devtools/protocol/service_worker_handler.cc +++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -179,8 +179,9 @@ } // namespace -ServiceWorkerHandler::ServiceWorkerHandler() +ServiceWorkerHandler::ServiceWorkerHandler(bool allow_inspect_worker) : DevToolsDomainHandler(ServiceWorker::Metainfo::domainName), + allow_inspect_worker_(allow_inspect_worker), enabled_(false), browser_context_(nullptr), storage_partition_(nullptr) {} @@ -313,7 +314,8 @@ return CreateDomainNotEnabledErrorResponse(); if (!context_) return CreateContextErrorResponse(); - + if (!allow_inspect_worker_) + return Response::ServerError("Permission denied"); int64_t id = blink::mojom::kInvalidServiceWorkerVersionId; if (!base::StringToInt64(version_id, &id)) return CreateInvalidVersionIdErrorResponse();
diff --git a/content/browser/devtools/protocol/service_worker_handler.h b/content/browser/devtools/protocol/service_worker_handler.h index 848540dc..2139fa30 100644 --- a/content/browser/devtools/protocol/service_worker_handler.h +++ b/content/browser/devtools/protocol/service_worker_handler.h
@@ -31,7 +31,7 @@ class ServiceWorkerHandler : public DevToolsDomainHandler, public ServiceWorker::Backend { public: - ServiceWorkerHandler(); + explicit ServiceWorkerHandler(bool allow_inspect_worker); ~ServiceWorkerHandler() override; void Wire(UberDispatcher* dispatcher) override; @@ -72,6 +72,7 @@ void OpenNewDevToolsWindow(int process_id, int devtools_agent_route_id); void ClearForceUpdate(); + const bool allow_inspect_worker_; scoped_refptr<ServiceWorkerContextWrapper> context_; std::unique_ptr<ServiceWorker::Frontend> frontend_; bool enabled_;
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 5382734..01e6767 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -318,10 +318,12 @@ }, base::Unretained(this)))); session->AddHandler(std::make_unique<protocol::SchemaHandler>()); - session->AddHandler(std::make_unique<protocol::ServiceWorkerHandler>()); + const bool may_attach_to_brower = session->GetClient()->MayAttachToBrowser(); + session->AddHandler(std::make_unique<protocol::ServiceWorkerHandler>( + /* allow_inspect_worker= */ may_attach_to_brower)); session->AddHandler(std::make_unique<protocol::StorageHandler>()); session->AddHandler(std::make_unique<protocol::TargetHandler>( - session->GetClient()->MayAttachToBrowser() + may_attach_to_brower ? protocol::TargetHandler::AccessMode::kRegular : protocol::TargetHandler::AccessMode::kAutoAttachOnly, GetId(), GetRendererChannel(), session->GetRootSession()));
diff --git a/content/browser/frame_host/mixed_content_navigation_throttle.cc b/content/browser/frame_host/mixed_content_navigation_throttle.cc index 608f464..b401e44 100644 --- a/content/browser/frame_host/mixed_content_navigation_throttle.cc +++ b/content/browser/frame_host/mixed_content_navigation_throttle.cc
@@ -75,6 +75,7 @@ params.main_resource_url = mixed_content_url; params.mixed_content_url = navigation_request->GetURL(); params.request_context_type = navigation_request->request_context_type(); + params.request_destination = navigation_request->request_destination(); params.was_allowed = was_allowed; params.had_redirect = for_redirect; params.source_location =
diff --git a/content/browser/frame_host/mixed_content_navigation_throttle.h b/content/browser/frame_host/mixed_content_navigation_throttle.h index b0b5977..f2131465 100644 --- a/content/browser/frame_host/mixed_content_navigation_throttle.h +++ b/content/browser/frame_host/mixed_content_navigation_throttle.h
@@ -12,6 +12,7 @@ #include "content/common/content_export.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" +#include "services/network/public/mojom/fetch_api.mojom.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h" #include "third_party/blink/public/platform/web_mixed_content_context_type.h"
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index dbfc243..797feb48 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -99,6 +99,7 @@ #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/resource_request_body.h" #include "services/network/public/cpp/url_loader_completion_status.h" +#include "services/network/public/mojom/fetch_api.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/blink/public/common/blob/blob_utils.h" #include "third_party/blink/public/common/frame/sandbox_flags.h" @@ -685,6 +686,7 @@ auto navigation_params = mojom::BeginNavigationParams::New( extra_headers, net::LOAD_NORMAL, false /* skip_service_worker */, blink::mojom::RequestContextType::LOCATION, + network::mojom::RequestDestination::kDocument, blink::WebMixedContentContextType::kBlockable, is_form_submission, false /* was_initiated_by_link_click */, GURL() /* searchable_form_url */, std::string() /* searchable_form_encoding */,
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index da2c6b0..7364dd3 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -508,6 +508,10 @@ return begin_params_->request_context_type; } + network::mojom::RequestDestination request_destination() const { + return begin_params_->request_destination; + } + blink::WebMixedContentContextType mixed_content_context_type() const { return begin_params_->mixed_content_context_type; }
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc index c3e41901..588d0cd0 100644 --- a/content/browser/loader/navigation_url_loader_impl_unittest.cc +++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -172,6 +172,7 @@ mojom::BeginNavigationParams::New( headers, net::LOAD_NORMAL, false /* skip_service_worker */, blink::mojom::RequestContextType::LOCATION, + network::mojom::RequestDestination::kDocument, blink::WebMixedContentContextType::kBlockable, false /* is_form_submission */, false /* was_initiated_by_link_click */,
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc index a2c85587..186beac9 100644 --- a/content/browser/loader/navigation_url_loader_unittest.cc +++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -60,6 +60,7 @@ std::string() /* headers */, net::LOAD_NORMAL, false /* skip_service_worker */, blink::mojom::RequestContextType::LOCATION, + network::mojom::RequestDestination::kDocument, blink::WebMixedContentContextType::kBlockable, false /* is_form_submission */, false /* was_initiated_by_link_click */,
diff --git a/content/browser/media/audio_stream_monitor_unittest.cc b/content/browser/media/audio_stream_monitor_unittest.cc index d6d1c8b..2604c053 100644 --- a/content/browser/media/audio_stream_monitor_unittest.cc +++ b/content/browser/media/audio_stream_monitor_unittest.cc
@@ -16,7 +16,7 @@ #include "content/public/browser/invalidate_type.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/test/test_renderer_host.h" -#include "media/audio/audio_power_monitor.h" +#include "media/base/audio_power_monitor.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index e802bfe0..43d4b85 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -1519,6 +1519,7 @@ std::string() /* headers */, net::LOAD_NORMAL, false /* skip_service_worker */, blink::mojom::RequestContextType::LOCATION, + network::mojom::RequestDestination::kDocument, blink::WebMixedContentContextType::kBlockable, false /* is_form_submission */, false /* was_initiated_by_link_click */,
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc index 54fec83..b8ace915 100644 --- a/content/browser/service_worker/service_worker_registration.cc +++ b/content/browser/service_worker/service_worker_registration.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/debug/alias.h" #include "base/threading/thread_task_runner_handle.h" #include "content/browser/service_worker/embedded_worker_status.h" #include "content/browser/service_worker/service_worker_container_host.h" @@ -39,6 +40,48 @@ return version->GetInfo(); } +// TODO(crbug.com/1015692): Remove this and CrashDueToControllee() once we +// identified the cause of crash. +struct ControlleeInfo { + std::string client_uuid; + ServiceWorkerVersion* controller; + ServiceWorkerRegistration* controller_registration; + bool is_context_secure_for_service_worker; + + explicit ControlleeInfo(const ServiceWorkerContainerHost& container_host) + : client_uuid(container_host.client_uuid()), + controller(container_host.controller()), + controller_registration(container_host.controller_registration()), + is_context_secure_for_service_worker( + container_host.IsContextSecureForServiceWorker()) {} +}; + +void CrashDueToControllee( + ServiceWorkerRegistration* registration, + scoped_refptr<ServiceWorkerVersion> exiting_version, + scoped_refptr<ServiceWorkerVersion> activating_version) { + std::vector<ControlleeInfo> controllees_in_exiting; + for (const auto& it : exiting_version->controllee_map()) { + ControlleeInfo info(*it.second); + controllees_in_exiting.push_back(info); + } + std::vector<ControlleeInfo> controllees_in_activating; + for (const auto& it : activating_version->controllee_map()) { + ControlleeInfo info(*it.second); + controllees_in_activating.push_back(info); + } + + bool exiting_version_skip_waiting = exiting_version->skip_waiting(); + bool activating_version_skip_waiting = activating_version->skip_waiting(); + + base::debug::Alias(®istration); + base::debug::Alias(&controllees_in_exiting); + base::debug::Alias(&controllees_in_activating); + base::debug::Alias(&exiting_version_skip_waiting); + base::debug::Alias(&activating_version_skip_waiting); + CHECK(false); +} + } // namespace ServiceWorkerRegistration::ServiceWorkerRegistration( @@ -505,9 +548,9 @@ observer.OnSkippedWaiting(this); } - // TODO(crbug.com/951571): Remove this once we identified the cause of crash. - if (exiting_version) { - CHECK(!exiting_version->HasControllee()); + // TODO(crbug.com/1015692): Remove this once we identified the cause of crash. + if (exiting_version && exiting_version->HasControllee()) { + CrashDueToControllee(this, exiting_version, activating_version); } // "10. Queue a task to fire an event named activate..."
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 7419cc6..0224341 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -448,6 +448,7 @@ IPC_STRUCT_MEMBER(GURL, main_resource_url) IPC_STRUCT_MEMBER(GURL, mixed_content_url) IPC_STRUCT_MEMBER(blink::mojom::RequestContextType, request_context_type) + IPC_STRUCT_MEMBER(network::mojom::RequestDestination, request_destination) IPC_STRUCT_MEMBER(bool, was_allowed) IPC_STRUCT_MEMBER(bool, had_redirect) IPC_STRUCT_MEMBER(network::mojom::SourceLocation, source_location)
diff --git a/content/common/navigation_params.mojom b/content/common/navigation_params.mojom index 1a77477..f904ff6 100644 --- a/content/common/navigation_params.mojom +++ b/content/common/navigation_params.mojom
@@ -10,6 +10,7 @@ import "mojo/public/mojom/base/unguessable_token.mojom"; import "mojo/public/mojom/base/values.mojom"; import "services/network/public/mojom/content_security_policy.mojom"; +import "services/network/public/mojom/fetch_api.mojom"; import "services/network/public/mojom/ip_address_space.mojom"; import "services/network/public/mojom/source_location.mojom"; import "services/network/public/mojom/url_loader.mojom"; @@ -101,6 +102,9 @@ // Indicates the request context type. blink.mojom.RequestContextType request_context_type; + // Indicates the request destination. + network.mojom.RequestDestination request_destination; + // The mixed content context type for potential mixed content checks. MixedContentContextType mixed_content_context_type;
diff --git a/content/renderer/loader/web_url_request_util.cc b/content/renderer/loader/web_url_request_util.cc index 2226987..828286e 100644 --- a/content/renderer/loader/web_url_request_util.cc +++ b/content/renderer/loader/web_url_request_util.cc
@@ -254,6 +254,12 @@ request.GetRequestContext()); } +network::mojom::RequestDestination GetRequestDestinationForWebURLRequest( + const WebURLRequest& request) { + return static_cast<network::mojom::RequestDestination>( + request.GetRequestDestination()); +} + blink::WebMixedContentContextType GetMixedContentContextTypeForWebURLRequest( const WebURLRequest& request) { return blink::WebMixedContent::ContextTypeFromRequestContext(
diff --git a/content/renderer/loader/web_url_request_util.h b/content/renderer/loader/web_url_request_util.h index 3434e58..540daa4 100644 --- a/content/renderer/loader/web_url_request_util.h +++ b/content/renderer/loader/web_url_request_util.h
@@ -48,6 +48,8 @@ const blink::WebURLRequest& request); blink::mojom::RequestContextType GetRequestContextTypeForWebURLRequest( const blink::WebURLRequest& request); +network::mojom::RequestDestination GetRequestDestinationForWebURLRequest( + const blink::WebURLRequest& request); blink::WebMixedContentContextType GetMixedContentContextTypeForWebURLRequest( const blink::WebURLRequest& request);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 1d37c33..ebb5745 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -6284,6 +6284,7 @@ GetWebURLRequestHeadersAsString(info->url_request), load_flags, info->url_request.GetSkipServiceWorker(), GetRequestContextTypeForWebURLRequest(info->url_request), + GetRequestDestinationForWebURLRequest(info->url_request), GetMixedContentContextTypeForWebURLRequest(info->url_request), is_form_submission, was_initiated_by_link_click, searchable_form_url, searchable_form_encoding, client_side_redirect_url,
diff --git a/content/test/data/accessibility/aria/aria-focusable-subwidget-not-editable-expected-win.txt b/content/test/data/accessibility/aria/aria-focusable-subwidget-not-editable-expected-win.txt index f3c560d..c49088d 100644 --- a/content/test/data/accessibility/aria/aria-focusable-subwidget-not-editable-expected-win.txt +++ b/content/test/data/accessibility/aria/aria-focusable-subwidget-not-editable-expected-win.txt
@@ -1,6 +1,6 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ++IA2_ROLE_SECTION value='cats<newline>dogs' FOCUSABLE IA2_STATE_EDITABLE IA2_STATE_MULTI_LINE -++++ROLE_SYSTEM_OUTLINE FOCUSABLE IA2_STATE_EDITABLE +++++ROLE_SYSTEM_OUTLINE IA2_STATE_EDITABLE ++++++ROLE_SYSTEM_OUTLINEITEM name='cats' FOCUSABLE ++++++++ROLE_SYSTEM_STATICTEXT name='cats' IA2_STATE_EDITABLE ++++++ROLE_SYSTEM_OUTLINEITEM name='dogs' FOCUSABLE
diff --git a/content/test/data/accessibility/html/portal-expected-blink.txt b/content/test/data/accessibility/html/portal-expected-blink.txt index ed825c8e..efabb3c1 100644 --- a/content/test/data/accessibility/html/portal-expected-blink.txt +++ b/content/test/data/accessibility/html/portal-expected-blink.txt
@@ -1,9 +1,9 @@ -rootWebArea +rootWebArea focusable ++genericContainer ignored ++++paragraph ++++++staticText name='Before portal' ++++++++inlineTextBox name='Before portal' -++++portal name='portal' +++++portal focusable name='portal' ++++++rootWebArea name='Text in iframe' ++++paragraph ++++++staticText name='After portal'
diff --git a/content/test/data/accessibility/html/portal.html b/content/test/data/accessibility/html/portal.html index 4fc4d69..40db31b 100644 --- a/content/test/data/accessibility/html/portal.html +++ b/content/test/data/accessibility/html/portal.html
@@ -1,3 +1,6 @@ +<!-- +@BLINK-ALLOW:focusable +--> <!DOCTYPE html> <html> <body>
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py index 724d536..dd651ac 100644 --- a/content/test/gpu/gpu_tests/gpu_helper.py +++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -185,7 +185,8 @@ return DRIVER_TAG_MATCHER.match(tag.lower()) -def EvaluateVersionComparison(version1, operation, version2): +def EvaluateVersionComparison(version, operation, ref_version, + os_name=None, driver_vendor=None): def parse_version(ver): if ver.isdigit(): return int(ver), '' @@ -193,8 +194,32 @@ if not ver[i].isdigit(): return int(ver[:i]) if i > 0 else 0, ver[i:] - ver_list1 = version1.split('.') - ver_list2 = version2.split('.') + def is_old_intel_driver(ver_list): + assert len(ver_list) == 4 + num, suffix = parse_version(ver_list[2]) + assert not suffix + return num < 100 + + ver_list1 = version.split('.') + ver_list2 = ref_version.split('.') + # On Windows, if the driver vendor is Intel, the driver version should be + # compared based on the Intel graphics driver version schema. + # https://www.intel.com/content/www/us/en/support/articles/000005654/graphics-drivers.html + if os_name == 'win' and driver_vendor == 'intel': + # If either of the two versions doesn't match the Intel driver version + # schema, or they belong to different generation of version schema, they + # should not be compared. + if len(ver_list1) != 4 or len(ver_list2) != 4: + return operation == 'ne' + if is_old_intel_driver(ver_list1) != is_old_intel_driver(ver_list2): + return operation == 'ne' + if is_old_intel_driver(ver_list1): + ver_list1 = ver_list1[3:] + ver_list2 = ver_list2[3:] + else: + ver_list1 = ver_list1[2:] + ver_list2 = ver_list2[2:] + for i in range(0, max(len(ver_list1), len(ver_list2))): ver1 = ver_list1[i] if i < len(ver_list1) else '0' ver2 = ver_list2[i] if i < len(ver_list2) else '0'
diff --git a/content/test/gpu/gpu_tests/test_expectations_unittest.py b/content/test/gpu/gpu_tests/test_expectations_unittest.py index 6d6040c..7d4234e 100644 --- a/content/test/gpu/gpu_tests/test_expectations_unittest.py +++ b/content/test/gpu/gpu_tests/test_expectations_unittest.py
@@ -45,6 +45,39 @@ ResultType = json_results.ResultType +INTEL_DRIVER_VERSION_SCHEMA = ''' +The version format of Intel graphics driver is AA.BB.CCC.DDDD. +DDDD(old schema) or CCC.DDDD(new schema) is the build number. That is, +indicates the actual driver number. The comparison between old schema +and new schema is NOT valid. In such a condition the only comparison +operator that returns true is "not equal". + +AA.BB: You are free to specify the real number here, but they are meaningless +when comparing two version numbers. Usually it's okay to leave it to "0.0". + +CCC: It's necessary for new schema. Regarding to old schema, you can specify +the real number or any number less than 100 in order to differentiate from +new schema. + +DDDD: It's always meaningful. It must not be "0" under old schema. + +Legal: "24.20.100.7000", "0.0.100.7000", "0.0.0.7000", "0.0.100.0" +Illegal: "24.0.0.0", "24.20.0.0", "0.0.99.0" +''' + + +def check_intel_driver_version(version): + ver_list = version.split('.') + if len(ver_list) != 4: + return False + for ver in ver_list: + if not ver.isdigit(): + return False + if int(ver_list[2]) < 100 and ver_list[3] == '0': + return False + return True + + def _MapGpuDevicesToVendors(tag_sets): for tag_set in tag_sets: if any(gpu in tag_set for gpu in GPU_CONDITIONS): @@ -297,7 +330,12 @@ for tag_set in parser.tag_sets: if gpu_helper.MatchDriverTag(list(tag_set)[0]): for tag in tag_set: - assert gpu_helper.MatchDriverTag(tag) + match = gpu_helper.MatchDriverTag(tag) + assert match + if match.group(1) == 'intel': + if not check_intel_driver_version(match.group(3)): + assert False, INTEL_DRIVER_VERSION_SCHEMA + assert not driver_tag_set driver_tag_set = tag_set else: @@ -416,3 +454,37 @@ self.assertIn('3: Expectation with pattern \'a/b/d\' does not match' ' any tests in the GpuIntegrationTest test suite', str(context.exception)) + +def testDriverVersionComparision(self): + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000', 'eq', '24.20.100.7000')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100', 'ne', '24.20.100.7000')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000', 'gt', '24.20.100')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000a', 'gt', '24.20.100.7000')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000', 'lt', '24.20.100.7001')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000', 'lt', '24.20.200.6000')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000', 'lt', '25.30.100.6000', 'linux', 'intel')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000', 'gt', '25.30.100.6000', 'win', 'intel')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.101.6000', 'gt', '25.30.100.7000', 'win', 'intel')) + self.assertFalse(gpu_helper.EvaluateVersionComparison( + '24.20.99.7000', 'gt', '24.20.100.7000', 'win', 'intel')) + self.assertFalse(gpu_helper.EvaluateVersionComparison( + '24.20.99.7000', 'lt', '24.20.100.7000', 'win', 'intel')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.99.7000', 'ne', '24.20.100.7000', 'win', 'intel')) + self.assertFalse(gpu_helper.EvaluateVersionComparison( + '24.20.100', 'lt', '24.20.100.7000', 'win', 'intel')) + self.assertFalse(gpu_helper.EvaluateVersionComparison( + '24.20.100', 'gt', '24.20.100.7000', 'win', 'intel')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100', 'ne', '24.20.100.7000', 'win', 'intel')) + self.assertTrue(gpu_helper.EvaluateVersionComparison( + '24.20.100.7000', 'eq', '25.20.100.7000', 'win', 'intel'))
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py index 5fbd02b..07a0aa1f 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
@@ -499,7 +499,8 @@ assert match if (driver_vendor == match.group(1) and gpu_helper.EvaluateVersionComparison( - driver_version, match.group(2), match.group(3))): + driver_version, match.group(2), match.group(3), + browser.platform.GetOSName(), driver_vendor)): tags.append(tag) return tags
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc index d404f30..bb63405 100644 --- a/content/test/navigation_simulator_impl.cc +++ b/content/test/navigation_simulator_impl.cc
@@ -1128,6 +1128,7 @@ std::string() /* headers */, net::LOAD_NORMAL, false /* skip_service_worker */, blink::mojom::RequestContextType::HYPERLINK, + network::mojom::RequestDestination::kDocument, blink::WebMixedContentContextType::kBlockable, is_form_submission_, was_initiated_by_link_click_, GURL() /* searchable_form_url */, std::string() /* searchable_form_encoding */,
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 2b78e77b..718f48f 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -327,6 +327,7 @@ std::string() /* headers */, net::LOAD_NORMAL, false /* skip_service_worker */, blink::mojom::RequestContextType::HYPERLINK, + network::mojom::RequestDestination::kDocument, blink::WebMixedContentContextType::kBlockable, false /* is_form_submission */, false /* was_initiated_by_link_click */,
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc index eda38b5..b4ab820 100644 --- a/gpu/config/gpu_control_list.cc +++ b/gpu/config/gpu_control_list.cc
@@ -96,6 +96,14 @@ return 0; } +bool isOldIntelDriver(const std::vector<std::string>& version) { + DCHECK_EQ(4u, version.size()); + unsigned value = 0; + bool valid = base::StringToUint(version[2], &value); + DCHECK(valid); + return value < 100; +} + // A mismatch is identified only if both |input| and |pattern| are not empty. bool StringMismatch(const std::string& input, const std::string& pattern) { if (input.empty() || pattern.empty()) @@ -234,14 +242,59 @@ control_list_logging_name.c_str()); } -bool GpuControlList::DriverInfo::Contains(const GPUInfo& gpu_info) const { +bool GpuControlList::DriverInfo::Contains(const GPUInfo& gpu_info, + VersionSchema version_schema) const { const GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu(); if (StringMismatch(active_gpu.driver_vendor, driver_vendor)) { return false; } - if (driver_version.IsSpecified() && !active_gpu.driver_version.empty() && - !driver_version.Contains(active_gpu.driver_version)) { - return false; + if (driver_version.IsSpecified() && !active_gpu.driver_version.empty()) { + if (version_schema == kCommon) { + if (!driver_version.Contains(active_gpu.driver_version)) + return false; + } else if (version_schema == kIntelDriver) { + std::vector<std::string> version; + if (!ProcessVersionString(active_gpu.driver_version, '.', &version)) + return false; + std::vector<std::string> ref_version, ref_version2; + bool valid = ProcessVersionString(driver_version.value1, '.', + &ref_version); + DCHECK(valid); + if (driver_version.value2) { + valid = ProcessVersionString(driver_version.value2, '.', &ref_version2); + DCHECK(valid); + } + // If either of the two versions doesn't match the Intel driver version + // schema, or they belong to different generation of version schema, they + // should not be compared. + if (version.size() != 4 || ref_version.size() != 4) + return false; + if (isOldIntelDriver(version) != isOldIntelDriver(ref_version)) + return false; + if (!ref_version2.empty()) { + if (ref_version2.size() != 4 + || isOldIntelDriver(ref_version) != isOldIntelDriver(ref_version2)) + return false; + } + + std::string build_num, ref_build_num, ref_build_num2; + if (isOldIntelDriver(version)) { + build_num = version[3]; + ref_build_num = ref_version[3]; + if (!ref_version2.empty()) + ref_build_num2 = ref_version2[3]; + } else { + build_num = version[2] + "." + version[3]; + ref_build_num = ref_version[2] + "." + ref_version[3]; + if (!ref_version2.empty()) + ref_build_num2 = ref_version2[2] + "." + ref_version2[3]; + } + Version ref_driver_version(driver_version); + ref_driver_version.value1 = ref_build_num.c_str(); + if (!ref_build_num2.empty()) + ref_driver_version.value2 = ref_build_num2.c_str(); + if (!ref_driver_version.Contains(build_num)) + return false; + } } return true; } @@ -448,8 +501,30 @@ case kMultiGpuStyleNone: break; } - if (driver_info && !driver_info->Contains(gpu_info)) { - return false; + + if (driver_info) { + // On Windows, if either current gpu or the gpu condition is from Intel, + // the driver version should be compared based on the Intel graphics driver + // version schema. + // https://www.intel.com/content/www/us/en/support/articles/000005654/graphics-drivers.html + VersionSchema version_schema = kCommon; + if (target_os_type == kOsWin) { + if (vendor_id == 0x8086 + || intel_gpu_series_list_size > 0 + || intel_gpu_generation.IsSpecified() + || (driver_info->driver_vendor + && std::string(driver_info->driver_vendor).find("Intel") + != std::string::npos)) { + version_schema = kIntelDriver; + } else { + const GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu(); + if (active_gpu.vendor_id == 0x8086 + || active_gpu.driver_vendor.find("Intel") != std::string::npos) + version_schema = kIntelDriver; + } + } + if (!driver_info->Contains(gpu_info, version_schema)) + return false; } if (gl_strings && !gl_strings->Contains(gpu_info)) { return false;
diff --git a/gpu/config/gpu_control_list.h b/gpu/config/gpu_control_list.h index 2cadf67..063da31a 100644 --- a/gpu/config/gpu_control_list.h +++ b/gpu/config/gpu_control_list.h
@@ -85,6 +85,15 @@ kVersionStyleUnknown }; + enum VersionSchema { + // All digits are meaningful when distinguishing versions. + kCommon, + // The version format of Intel graphics driver is AA.BB.CCC.DDDD. + // DDDD(old schema) or CCC.DDDD(new schema) is the build number. + // That is, indicates the actual driver number. + kIntelDriver, + }; + enum SupportedOrNot { kSupported, kUnsupported, @@ -124,7 +133,8 @@ const char* driver_vendor; Version driver_version; - bool Contains(const GPUInfo& gpu_info) const; + bool Contains(const GPUInfo& gpu_info, + VersionSchema version_schema = kCommon) const; }; struct GPU_EXPORT GLStrings {
diff --git a/gpu/config/gpu_control_list_entry_unittest.cc b/gpu/config/gpu_control_list_entry_unittest.cc index 046690d..03f97c1 100644 --- a/gpu/config/gpu_control_list_entry_unittest.cc +++ b/gpu/config/gpu_control_list_entry_unittest.cc
@@ -1111,4 +1111,59 @@ EXPECT_TRUE(entry.Contains(kOsChromeOS, "10.0", gpu_info)); } +TEST_F(GpuControlListEntryTest, IntelDriverVendorEntry) { + const Entry& entry = + GetEntry(kGpuControlListEntryTest_IntelDriverVendorEntry); + GPUInfo gpu_info; + gpu_info.gpu.driver_vendor = "Intel(R) UHD Graphics 630"; + gpu_info.gpu.driver_version = "25.20.100.5000"; + EXPECT_TRUE(entry.Contains(kOsLinux, "", gpu_info)); + gpu_info.gpu.driver_version = "23.20.100.6500"; + EXPECT_FALSE(entry.Contains(kOsLinux, "", gpu_info)); + + gpu_info.gpu.driver_version = "25.20.100.5000"; + EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "23.20.100.6500"; + EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info)); +} + +TEST_F(GpuControlListEntryTest, IntelDriverVersionEntry) { + const Entry& entry = + GetEntry(kGpuControlListEntryTest_IntelDriverVersionEntry); + GPUInfo gpu_info; + gpu_info.gpu.vendor_id = 0x8086; + gpu_info.gpu.driver_version = "23.20.100.8000"; + EXPECT_TRUE(entry.Contains(kOsLinux, "", gpu_info)); + gpu_info.gpu.driver_version = "25.20.100.6000"; + EXPECT_FALSE(entry.Contains(kOsLinux, "", gpu_info)); + + gpu_info.gpu.driver_version = "23.20.100.8000"; + EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "25.20.100.6000"; + EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "24.20.99.6000"; + EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "24.20.101.6000"; + EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "25.20.100.7000"; + EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info)); +} + +TEST_F(GpuControlListEntryTest, IntelOldDriverVersionEntry) { + const Entry& entry = + GetEntry(kGpuControlListEntryTest_IntelOldDriverVersionEntry); + GPUInfo gpu_info; + gpu_info.gpu.vendor_id = 0x8086; + gpu_info.gpu.driver_version = "23.20.10.8000"; + EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "25.20.10.6000"; + EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "24.20.100.6000"; + EXPECT_FALSE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "24.20.11.6000"; + EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info)); + gpu_info.gpu.driver_version = "25.20.9.7000"; + EXPECT_TRUE(entry.Contains(kOsWin, "", gpu_info)); +} + } // namespace gpu
diff --git a/gpu/config/gpu_control_list_testing.json b/gpu/config/gpu_control_list_testing.json index 9054a606..84505407 100644 --- a/gpu/config/gpu_control_list_testing.json +++ b/gpu/config/gpu_control_list_testing.json
@@ -224,7 +224,7 @@ "vendor_id": "0x8086", "driver_version": { "op": "<", - "value": "10.7" + "value": "24.20.100.7000" }, "features": [ "test_feature_1" @@ -899,6 +899,43 @@ "features": [ "test_feature_0" ] + }, + { + "id": 75, + "description": "GpuControlListEntryTest.IntelDriverVendorEntry", + "driver_vendor": "Intel.*", + "driver_version": { + "op": "between", + "value": "24.20.100.6000", + "value2": "26.20.100.7000" + }, + "features": [ + "test_feature_0" + ] + }, + { + "id": 76, + "description": "GpuControlListEntryTest.IntelDriverVersionEntry", + "vendor_id": "0x8086", + "driver_version": { + "op": "<=", + "value": "24.20.100.7000" + }, + "features": [ + "test_feature_0" + ] + }, + { + "id": 77, + "description": "GpuControlListEntryTest.IntelOldDriverVersionEntry", + "vendor_id": "0x8086", + "driver_version": { + "op": "<=", + "value": "24.20.10.7000" + }, + "features": [ + "test_feature_0" + ] } ] }
diff --git a/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h b/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h index ab6171f7..167430b 100644 --- a/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h +++ b/gpu/config/gpu_control_list_testing_arrays_and_structs_autogen.h
@@ -525,8 +525,8 @@ const GpuControlList::DriverInfo kDriverInfoForGpuControlTestingEntry20 = { nullptr, // driver_vendor - {GpuControlList::kLT, GpuControlList::kVersionStyleNumerical, "10.7", - nullptr}, // driver_version + {GpuControlList::kLT, GpuControlList::kVersionStyleNumerical, + "24.20.100.7000", nullptr}, // driver_version }; const GpuControlList::More kMoreForEntry20_1440601243 = { @@ -2061,6 +2061,87 @@ GpuControlList::kDontCare, // subpixel_font_rendering }; +const int kFeatureListForGpuControlTestingEntry75[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::DriverInfo kDriverInfoForGpuControlTestingEntry75 = { + "Intel.*", // driver_vendor + {GpuControlList::kBetween, GpuControlList::kVersionStyleNumerical, + "24.20.100.6000", "26.20.100.7000"}, // driver_version +}; + +const GpuControlList::More kMoreForEntry75_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group + GpuControlList::kDontCare, // subpixel_font_rendering +}; + +const int kFeatureListForGpuControlTestingEntry76[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::DriverInfo kDriverInfoForGpuControlTestingEntry76 = { + nullptr, // driver_vendor + {GpuControlList::kLE, GpuControlList::kVersionStyleNumerical, + "24.20.100.7000", nullptr}, // driver_version +}; + +const GpuControlList::More kMoreForEntry76_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group + GpuControlList::kDontCare, // subpixel_font_rendering +}; + +const int kFeatureListForGpuControlTestingEntry77[1] = { + TEST_FEATURE_0, +}; + +const GpuControlList::DriverInfo kDriverInfoForGpuControlTestingEntry77 = { + nullptr, // driver_vendor + {GpuControlList::kLE, GpuControlList::kVersionStyleNumerical, + "24.20.10.7000", nullptr}, // driver_version +}; + +const GpuControlList::More kMoreForEntry77_1440601243 = { + GpuControlList::kGLTypeNone, // gl_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gl_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // pixel_shader_version + false, // in_process_gpu + 0, // gl_reset_notification_strategy + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // direct_rendering_version + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, nullptr, + nullptr}, // gpu_count + GpuControlList::kDontCare, // hardware_overlay + 0, // test_group + GpuControlList::kDontCare, // subpixel_font_rendering +}; + } // namespace gpu #endif // GPU_CONFIG_GPU_CONTROL_LIST_TESTING_ARRAYS_AND_STRUCTS_AUTOGEN_H_
diff --git a/gpu/config/gpu_control_list_testing_autogen.cc b/gpu/config/gpu_control_list_testing_autogen.cc index 78a175fd..3245838 100644 --- a/gpu/config/gpu_control_list_testing_autogen.cc +++ b/gpu/config/gpu_control_list_testing_autogen.cc
@@ -2394,6 +2394,102 @@ 0, // exceptions count nullptr, // exceptions }, + { + 75, // id + "GpuControlListEntryTest.IntelDriverVendorEntry", + base::size(kFeatureListForGpuControlTestingEntry75), // features size + kFeatureListForGpuControlTestingEntry75, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x00, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + &kDriverInfoForGpuControlTestingEntry75, // driver info + nullptr, // GL strings + nullptr, // machine model info + 0, // intel_gpu_series size + nullptr, // intel_gpu_series + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // intel_gpu_generation + &kMoreForEntry75_1440601243, // more data + }, + 0, // exceptions count + nullptr, // exceptions + }, + { + 76, // id + "GpuControlListEntryTest.IntelDriverVersionEntry", + base::size(kFeatureListForGpuControlTestingEntry76), // features size + kFeatureListForGpuControlTestingEntry76, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x8086, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + &kDriverInfoForGpuControlTestingEntry76, // driver info + nullptr, // GL strings + nullptr, // machine model info + 0, // intel_gpu_series size + nullptr, // intel_gpu_series + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // intel_gpu_generation + &kMoreForEntry76_1440601243, // more data + }, + 0, // exceptions count + nullptr, // exceptions + }, + { + 77, // id + "GpuControlListEntryTest.IntelOldDriverVersionEntry", + base::size(kFeatureListForGpuControlTestingEntry77), // features size + kFeatureListForGpuControlTestingEntry77, // features + 0, // DisabledExtensions size + nullptr, // DisabledExtensions + 0, // DisabledWebGLExtensions size + nullptr, // DisabledWebGLExtensions + 0, // CrBugs size + nullptr, // CrBugs + { + GpuControlList::kOsAny, // os_type + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // os_version + 0x8086, // vendor_id + 0, // DeviceIDs size + nullptr, // DeviceIDs + GpuControlList::kMultiGpuCategoryNone, // multi_gpu_category + GpuControlList::kMultiGpuStyleNone, // multi_gpu_style + &kDriverInfoForGpuControlTestingEntry77, // driver info + nullptr, // GL strings + nullptr, // machine model info + 0, // intel_gpu_series size + nullptr, // intel_gpu_series + {GpuControlList::kUnknown, GpuControlList::kVersionStyleNumerical, + nullptr, nullptr}, // intel_gpu_generation + &kMoreForEntry77_1440601243, // more data + }, + 0, // exceptions count + nullptr, // exceptions + }, }; -const size_t kGpuControlListTestingEntryCount = 74; +const size_t kGpuControlListTestingEntryCount = 77; } // namespace gpu
diff --git a/gpu/config/gpu_control_list_testing_entry_enums_autogen.h b/gpu/config/gpu_control_list_testing_entry_enums_autogen.h index f70d8b3..fc12d78 100644 --- a/gpu/config/gpu_control_list_testing_entry_enums_autogen.h +++ b/gpu/config/gpu_control_list_testing_entry_enums_autogen.h
@@ -87,6 +87,9 @@ kGpuControlListEntryTest_GpuGenerationSecondary = 71, kGpuControlListEntryTest_SubpixelFontRendering = 72, kGpuControlListEntryTest_SubpixelFontRenderingDontCare = 73, + kGpuControlListEntryTest_IntelDriverVendorEntry = 74, + kGpuControlListEntryTest_IntelDriverVersionEntry = 75, + kGpuControlListEntryTest_IntelOldDriverVersionEntry = 76, }; } // namespace gpu
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index aa54cf59..7fee20a 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -682,8 +682,8 @@ }, "vendor_id": "0x8086", "driver_version": { - "op": "<=", - "value": "9.18.0.0" + "op": "<", + "value": "0.0.0.3000" }, "features": [ "disable_d3d11" @@ -3002,8 +3002,8 @@ "type": "win" }, "driver_version": { - "op": ">=", - "value": "24" + "op": ">", + "value": "0.0.100.0" }, "hardware_overlay": "unsupported", "features": [ @@ -3184,7 +3184,7 @@ "vendor_id": "0x8086", "driver_version": { "op": "<", - "value": "24.0.0.0" + "value": "0.0.0.9999" }, "features": [ "disable_nv12_dynamic_textures"
diff --git a/gpu/config/process_json.py b/gpu/config/process_json.py index dc052fe..08c56a2 100755 --- a/gpu/config/process_json.py +++ b/gpu/config/process_json.py
@@ -36,6 +36,38 @@ '': 'kOsAny', } +INTEL_DRIVER_VERSION_SCHEMA = ''' +The version format of Intel graphics driver is AA.BB.CCC.DDDD. +DDDD(old schema) or CCC.DDDD(new schema) is the build number. That is, +indicates the actual driver number. The comparison between old schema +and new schema is NOT valid. In such a condition the only comparison +operator that returns true is "not equal". + +AA.BB: You are free to specify the real number here, but they are meaningless +when comparing two version numbers. Usually it's okay to leave it to "0.0". + +CCC: It's necessary for new schema. Regarding to old schema, you can speicy +the real number or any number less than 100 in order to differentiate from +new schema. + +DDDD: It's always meaningful. It must not be "0" under old schema. + +Legal: "24.20.100.7000", "0.0.100.7000", "0.0.0.7000", "0.0.100.0" +Illegal: "24.0.0.0", "24.20.0.0", "0.0.99.0" +''' + + +def check_intel_driver_version(version): + ver_list = version.split('.') + if len(ver_list) != 4: + return False + for ver in ver_list: + if not ver.isdigit(): + return False + if int(ver_list[2]) < 100 and ver_list[3] == '0': + return False + return True + def load_software_rendering_list_features(feature_type_filename): header_file = open(feature_type_filename, 'r') @@ -485,6 +517,15 @@ write_multi_gpu_style(multi_gpu_style, data_file) # group driver info if driver_vendor != '' or driver_version != None: + if driver_version and os_type == 'win': + if (format(vendor_id, '#04x') == '0x8086' or intel_gpu_series_list + or intel_gpu_generation or 'Intel' in driver_vendor): + if not check_intel_driver_version(driver_version['value']): + assert False, INTEL_DRIVER_VERSION_SCHEMA + if driver_version.has_key('value2'): + if not check_intel_driver_version(driver_version['value2']): + assert False, INTEL_DRIVER_VERSION_SCHEMA + write_driver_info(entry_id, is_exception, exception_id, driver_vendor, driver_version, unique_symbol_id, data_file, data_helper_file)
diff --git a/gpu/config/software_rendering_list.json b/gpu/config/software_rendering_list.json index 7eefd99..68bed9e 100644 --- a/gpu/config/software_rendering_list.json +++ b/gpu/config/software_rendering_list.json
@@ -1443,9 +1443,8 @@ }, "vendor_id": "0x8086", "driver_version": { - "comment": "INF_version: 8.16.0.0", "op": "<", - "value": "8.16.0.0" + "value": "0.0.0.3000" }, "features": [ "accelerated_webgl2"
diff --git a/gpu/vulkan/BUILD.gn b/gpu/vulkan/BUILD.gn index 26e22a3c..32e981584 100644 --- a/gpu/vulkan/BUILD.gn +++ b/gpu/vulkan/BUILD.gn
@@ -126,11 +126,14 @@ deps += [ "//ui/gfx/x" ] configs += [ "//build/config/linux:x11" ] } + if (is_win) { + sources += [ "tests/native_window_win.cc" ] + } } # TODO(penghuang): support more platforms # https://crbug.com/1065499 - if (is_android || use_x11) { + if (is_android || use_x11 || is_win) { test("vulkan_tests") { sources = [ "tests/basic_vulkan_test.cc",
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py index 0b9ab4c..cd10c516 100755 --- a/gpu/vulkan/generate_bindings.py +++ b/gpu/vulkan/generate_bindings.py
@@ -67,6 +67,14 @@ ] }, { + 'ifdef': 'defined(OS_WIN)', + 'extension': 'VK_KHR_WIN32_SURFACE_EXTENSION_NAME', + 'functions': [ + 'vkCreateWin32SurfaceKHR', + 'vkGetPhysicalDeviceWin32PresentationSupportKHR', + ] + }, + { 'ifdef': 'defined(OS_ANDROID)', 'extension': 'VK_KHR_ANDROID_SURFACE_EXTENSION_NAME', 'functions': [ @@ -329,6 +337,10 @@ #include <vulkan/vulkan_xlib.h> #endif +#if defined(OS_WIN) +#include <vulkan/vulkan_win32.h> +#endif + namespace gpu { struct VulkanFunctionPointers;
diff --git a/gpu/vulkan/init/vulkan_factory.cc b/gpu/vulkan/init/vulkan_factory.cc index 5bfcb40..74791620 100644 --- a/gpu/vulkan/init/vulkan_factory.cc +++ b/gpu/vulkan/init/vulkan_factory.cc
@@ -30,7 +30,7 @@ bool use_swiftshader, bool allow_protected_memory, bool enforce_protected_memory) { -#if !defined(USE_X11) +#if !defined(USE_X11) && !defined(OS_WIN) // TODO(samans): Support Swiftshader on more platforms. // https://crbug.com/963988 DCHECK(!use_swiftshader) @@ -50,7 +50,7 @@ ->CreateVulkanImplementation(allow_protected_memory, enforce_protected_memory); #elif defined(OS_WIN) - return std::make_unique<VulkanImplementationWin32>(); + return std::make_unique<VulkanImplementationWin32>(use_swiftshader); #else #error Unsupported Vulkan Platform. #endif
diff --git a/gpu/vulkan/tests/basic_vulkan_test.cc b/gpu/vulkan/tests/basic_vulkan_test.cc index 5724b56..6968ebd 100644 --- a/gpu/vulkan/tests/basic_vulkan_test.cc +++ b/gpu/vulkan/tests/basic_vulkan_test.cc
@@ -4,6 +4,7 @@ #include "gpu/vulkan/tests/basic_vulkan_test.h" +#include "base/command_line.h" #include "gpu/vulkan/init/vulkan_factory.h" #include "gpu/vulkan/tests/native_window.h" #include "gpu/vulkan/vulkan_surface.h" @@ -22,17 +23,21 @@ void BasicVulkanTest::SetUp() { platform_event_source_ = ui::PlatformEventSource::CreateDefault(); -#if defined(USE_X11) +#if defined(USE_X11) || defined(OS_WIN) + bool use_swiftshader = + base::CommandLine::ForCurrentProcess()->HasSwitch("use-swiftshader"); const gfx::Rect kDefaultBounds(10, 10, 100, 100); window_ = CreateNativeWindow(kDefaultBounds); #elif defined(OS_ANDROID) + // Vulkan swiftshader is not supported on Android. + bool use_swiftshader = false; // TODO(penghuang): Not depend on gl. uint texture = 0; surface_texture_ = gl::SurfaceTexture::Create(texture); window_ = surface_texture_->CreateSurface(); ASSERT_TRUE(window_ != gfx::kNullAcceleratedWidget); #endif - vulkan_implementation_ = CreateVulkanImplementation(); + vulkan_implementation_ = CreateVulkanImplementation(use_swiftshader); ASSERT_TRUE(vulkan_implementation_); ASSERT_TRUE(vulkan_implementation_->InitializeVulkanInstance()); device_queue_ = gpu::CreateVulkanDeviceQueue( @@ -43,7 +48,7 @@ } void BasicVulkanTest::TearDown() { -#if defined(USE_X11) +#if defined(USE_X11) || defined(OS_WIN) DestroyNativeWindow(window_); #elif defined(OS_ANDROID) ANativeWindow_release(window_);
diff --git a/gpu/vulkan/tests/native_window_win.cc b/gpu/vulkan/tests/native_window_win.cc new file mode 100644 index 0000000..64f6094 --- /dev/null +++ b/gpu/vulkan/tests/native_window_win.cc
@@ -0,0 +1,53 @@ +// 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 "gpu/vulkan/tests/native_window.h" + +#include <windows.h> + +#include <memory> + +#include "base/containers/flat_map.h" +#include "ui/gfx/win/window_impl.h" + +namespace gpu { + +class Window; + +base::flat_map<gfx::AcceleratedWidget, std::unique_ptr<Window>> g_windows_; + +class Window : public gfx::WindowImpl { + public: + Window() { set_window_style(WS_VISIBLE | WS_POPUP); } + ~Window() override = default; + + private: + // Overridden from gfx::WindowImpl: + BOOL ProcessWindowMessage(HWND window, + UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT& result, + DWORD msg_map_id) override { + return false; // Results in DefWindowProc(). + } +}; + +gfx::AcceleratedWidget CreateNativeWindow(const gfx::Rect& bounds) { + auto window = std::make_unique<Window>(); + window->Init(/*parent=*/nullptr, bounds); + gfx::AcceleratedWidget widget = window->hwnd(); + g_windows_[widget] = std::move(window); + return widget; +} + +void DestroyNativeWindow(gfx::AcceleratedWidget window) { + auto it = g_windows_.find(window); + DCHECK(it != g_windows_.end()); + + it->second.reset(); + g_windows_.erase(it); +} + +} // namespace gpu
diff --git a/gpu/vulkan/vulkan_fence_helper.h b/gpu/vulkan/vulkan_fence_helper.h index 52c04552..20fdfe11 100644 --- a/gpu/vulkan/vulkan_fence_helper.h +++ b/gpu/vulkan/vulkan_fence_helper.h
@@ -28,7 +28,7 @@ // Class representing a fence registered with this system. Should be treated // as an opaque handle. - class FenceHandle { + class VULKAN_EXPORT FenceHandle { public: FenceHandle(); FenceHandle(const FenceHandle& other);
diff --git a/gpu/vulkan/vulkan_function_pointers.cc b/gpu/vulkan/vulkan_function_pointers.cc index 3012f232..77c2a79a 100644 --- a/gpu/vulkan/vulkan_function_pointers.cc +++ b/gpu/vulkan/vulkan_function_pointers.cc
@@ -261,6 +261,29 @@ } #endif // defined(USE_VULKAN_XLIB) +#if defined(OS_WIN) + if (gfx::HasExtension(enabled_extensions, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) { + vkCreateWin32SurfaceKHRFn = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>( + vkGetInstanceProcAddr(vk_instance, "vkCreateWin32SurfaceKHR")); + if (!vkCreateWin32SurfaceKHRFn) { + DLOG(WARNING) << "Failed to bind vulkan entrypoint: " + << "vkCreateWin32SurfaceKHR"; + return false; + } + + vkGetPhysicalDeviceWin32PresentationSupportKHRFn = + reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>( + vkGetInstanceProcAddr( + vk_instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR")); + if (!vkGetPhysicalDeviceWin32PresentationSupportKHRFn) { + DLOG(WARNING) << "Failed to bind vulkan entrypoint: " + << "vkGetPhysicalDeviceWin32PresentationSupportKHR"; + return false; + } + } +#endif // defined(OS_WIN) + #if defined(OS_ANDROID) if (gfx::HasExtension(enabled_extensions, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h index 1c82c67..290a7ea 100644 --- a/gpu/vulkan/vulkan_function_pointers.h +++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -36,6 +36,10 @@ #include <vulkan/vulkan_xlib.h> #endif +#if defined(OS_WIN) +#include <vulkan/vulkan_win32.h> +#endif + namespace gpu { struct VulkanFunctionPointers; @@ -134,6 +138,12 @@ vkGetPhysicalDeviceXlibPresentationSupportKHRFn; #endif // defined(USE_VULKAN_XLIB) +#if defined(OS_WIN) + VulkanFunction<PFN_vkCreateWin32SurfaceKHR> vkCreateWin32SurfaceKHRFn; + VulkanFunction<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR> + vkGetPhysicalDeviceWin32PresentationSupportKHRFn; +#endif // defined(OS_WIN) + #if defined(OS_ANDROID) VulkanFunction<PFN_vkCreateAndroidSurfaceKHR> vkCreateAndroidSurfaceKHRFn; #endif // defined(OS_ANDROID) @@ -317,6 +327,14 @@ ->vkGetPhysicalDeviceXlibPresentationSupportKHRFn #endif // defined(USE_VULKAN_XLIB) +#if defined(OS_WIN) +#define vkCreateWin32SurfaceKHR \ + gpu::GetVulkanFunctionPointers()->vkCreateWin32SurfaceKHRFn +#define vkGetPhysicalDeviceWin32PresentationSupportKHR \ + gpu::GetVulkanFunctionPointers() \ + ->vkGetPhysicalDeviceWin32PresentationSupportKHRFn +#endif // defined(OS_WIN) + #if defined(OS_ANDROID) #define vkCreateAndroidSurfaceKHR \ gpu::GetVulkanFunctionPointers()->vkCreateAndroidSurfaceKHRFn
diff --git a/gpu/vulkan/win32/vulkan_implementation_win32.cc b/gpu/vulkan/win32/vulkan_implementation_win32.cc index bc8b38c..1961307 100644 --- a/gpu/vulkan/win32/vulkan_implementation_win32.cc +++ b/gpu/vulkan/win32/vulkan_implementation_win32.cc
@@ -17,44 +17,32 @@ namespace gpu { +VulkanImplementationWin32::VulkanImplementationWin32(bool use_swiftshader) + : VulkanImplementation(use_swiftshader) {} + VulkanImplementationWin32::~VulkanImplementationWin32() = default; bool VulkanImplementationWin32::InitializeVulkanInstance(bool using_surface) { DCHECK(using_surface); std::vector<const char*> required_extensions = { - VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME}; + VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME, + }; VulkanFunctionPointers* vulkan_function_pointers = gpu::GetVulkanFunctionPointers(); + base::FilePath path(use_swiftshader() ? L"vk_swiftshader.dll" + : L"vulkan-1.dll"); + base::NativeLibraryLoadError native_library_load_error; - vulkan_function_pointers->vulkan_loader_library = base::LoadNativeLibrary( - base::FilePath(L"vulkan-1.dll"), &native_library_load_error); + vulkan_function_pointers->vulkan_loader_library = + base::LoadNativeLibrary(path, &native_library_load_error); if (!vulkan_function_pointers->vulkan_loader_library) return false; if (!vulkan_instance_.Initialize(required_extensions, {})) return false; - - // Initialize platform function pointers - vkGetPhysicalDeviceWin32PresentationSupportKHR_ = - reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>( - vkGetInstanceProcAddr( - vulkan_instance_.vk_instance(), - "vkGetPhysicalDeviceWin32PresentationSupportKHR")); - if (!vkGetPhysicalDeviceWin32PresentationSupportKHR_) { - LOG(ERROR) << "vkGetPhysicalDeviceWin32PresentationSupportKHR not found"; - return false; - } - - vkCreateWin32SurfaceKHR_ = - reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(vkGetInstanceProcAddr( - vulkan_instance_.vk_instance(), "vkCreateWin32SurfaceKHR")); - if (!vkCreateWin32SurfaceKHR_) { - LOG(ERROR) << "vkCreateWin32SurfaceKHR not found"; - return false; - } - return true; } @@ -70,7 +58,7 @@ surface_create_info.hinstance = reinterpret_cast<HINSTANCE>(GetWindowLongPtr(window, GWLP_HINSTANCE)); surface_create_info.hwnd = window; - VkResult result = vkCreateWin32SurfaceKHR_( + VkResult result = vkCreateWin32SurfaceKHR( vulkan_instance_.vk_instance(), &surface_create_info, nullptr, &surface); if (VK_SUCCESS != result) { DLOG(ERROR) << "vkCreatWin32SurfaceKHR() failed: " << result; @@ -86,13 +74,15 @@ VkPhysicalDevice device, const std::vector<VkQueueFamilyProperties>& queue_family_properties, uint32_t queue_family_index) { - return vkGetPhysicalDeviceWin32PresentationSupportKHR_(device, - queue_family_index); + return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, + queue_family_index); } std::vector<const char*> VulkanImplementationWin32::GetRequiredDeviceExtensions() { - return {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; + return { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + }; } std::vector<const char*>
diff --git a/gpu/vulkan/win32/vulkan_implementation_win32.h b/gpu/vulkan/win32/vulkan_implementation_win32.h index 45c2110c..8e6b649 100644 --- a/gpu/vulkan/win32/vulkan_implementation_win32.h +++ b/gpu/vulkan/win32/vulkan_implementation_win32.h
@@ -5,8 +5,6 @@ #ifndef GPU_VULKAN_WIN32_VULKAN_IMPLEMENTATION_WIN32_H_ #define GPU_VULKAN_WIN32_VULKAN_IMPLEMENTATION_WIN32_H_ -#include <memory> - #include "base/component_export.h" #include "gpu/vulkan/vulkan_implementation.h" #include "gpu/vulkan/vulkan_instance.h" @@ -16,7 +14,7 @@ class COMPONENT_EXPORT(VULKAN_WIN32) VulkanImplementationWin32 : public VulkanImplementation { public: - VulkanImplementationWin32() = default; + explicit VulkanImplementationWin32(bool use_swiftshader); ~VulkanImplementationWin32() override; // VulkanImplementation: @@ -51,10 +49,6 @@ private: VulkanInstance vulkan_instance_; - PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR - vkGetPhysicalDeviceWin32PresentationSupportKHR_ = nullptr; - PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(VulkanImplementationWin32); };
diff --git a/infra/config/buckets/ci.star b/infra/config/buckets/ci.star index 8777c01..016a7236c 100644 --- a/infra/config/buckets/ci.star +++ b/infra/config/buckets/ci.star
@@ -953,6 +953,7 @@ name = 'mac-upload-perfetto', os = os.MAC_DEFAULT, schedule = 'with 3h interval', + triggered_by = [], ) ci.fyi_builder( @@ -960,6 +961,7 @@ name = 'win-upload-perfetto', os = os.WINDOWS_DEFAULT, schedule = 'with 3h interval', + triggered_by = [], ) ci.fyi_celab_builder(
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg index 09b90b8..a5ac826c 100644 --- a/infra/config/generated/luci-scheduler.cfg +++ b/infra/config/generated/luci-scheduler.cfg
@@ -10481,7 +10481,6 @@ triggers: "mac-code-coverage" triggers: "mac-hermetic-upgrade-rel" triggers: "mac-mojo-rel" - triggers: "mac-upload-perfetto" triggers: "win-annotator-rel" triggers: "win-archive-dbg" triggers: "win-archive-rel" @@ -10493,7 +10492,6 @@ triggers: "win-swangle-tot-swiftshader-x86" triggers: "win-swangle-x64" triggers: "win-swangle-x86" - triggers: "win-upload-perfetto" triggers: "win10-code-coverage" triggers: "win32-archive-dbg" triggers: "win32-archive-rel"
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn index 1d835f5d..25c60f0c 100644 --- a/ios/chrome/app/application_delegate/BUILD.gn +++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -57,6 +57,7 @@ "//ios/chrome/browser/u2f", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/main", + "//ios/chrome/browser/ui/main:scene", "//ios/chrome/browser/ui/main/test", "//ios/chrome/browser/ui/safe_mode", "//ios/chrome/browser/ui/settings",
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm index 0f763ae5..8bc869b 100644 --- a/ios/chrome/app/application_delegate/app_state.mm +++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -308,10 +308,8 @@ GetApplicationContext()->OnAppEnterForeground(); - [MetricsMediator - logLaunchMetricsWithStartupInformation:_startupInformation - interfaceProvider:_browserLauncher - .interfaceProvider]; + [MetricsMediator logLaunchMetricsWithStartupInformation:_startupInformation + connectedScenes:self.connectedScenes]; [memoryHelper resetForegroundMemoryWarningCount]; // Use the mainBVC as the ContentSuggestions can only be started in non-OTR.
diff --git a/ios/chrome/app/application_delegate/app_state_unittest.mm b/ios/chrome/app/application_delegate/app_state_unittest.mm index 15e895a5..8161ddc 100644 --- a/ios/chrome/app/application_delegate/app_state_unittest.mm +++ b/ios/chrome/app/application_delegate/app_state_unittest.mm
@@ -37,6 +37,7 @@ #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/ui/main/browser_interface_provider.h" +#import "ios/chrome/browser/ui/main/test/fake_scene_state.h" #import "ios/chrome/browser/ui/main/test/stub_browser_interface.h" #import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h" #import "ios/chrome/browser/ui/safe_mode/safe_mode_coordinator.h" @@ -263,14 +264,15 @@ ScopedBlockSwizzler swizzler( [MetricsMediator class], - @selector(logLaunchMetricsWithStartupInformation:interfaceProvider:), + @selector(logLaunchMetricsWithStartupInformation:connectedScenes:), swizzleBlock); [appState applicationWillEnterForeground:application metricsMediator:metricsMediator memoryHelper:memoryHelper tabOpener:tabOpener]; - + // TODO(crbug.com/1065815): Inject scene states for multiwindow as well. + app_state_.mainSceneState = [[FakeSceneState alloc] init]; initializeIncognitoBlocker(window); return appState; @@ -282,6 +284,8 @@ [[AppState alloc] initWithBrowserLauncher:browser_launcher_mock_ startupInformation:startup_information_mock_ applicationDelegate:main_application_delegate_]; + // TODO(crbug.com/1065815): Inject scene states for multiwindow as well. + app_state_.mainSceneState = [[FakeSceneState alloc] init]; [app_state_ setWindow:window_]; } return app_state_; @@ -293,6 +297,8 @@ [[AppState alloc] initWithBrowserLauncher:browser_launcher_mock_ startupInformation:startup_information_mock_ applicationDelegate:main_application_delegate_]; + // TODO(crbug.com/1065815): Inject scene states for multiwindow as well. + app_state_.mainSceneState = [[FakeSceneState alloc] init]; [app_state_ setWindow:window]; [window makeKeyAndVisible]; } @@ -738,7 +744,7 @@ ScopedBlockSwizzler swizzler( [MetricsMediator class], - @selector(logLaunchMetricsWithStartupInformation:interfaceProvider:), + @selector(logLaunchMetricsWithStartupInformation:connectedScenes:), swizzleBlock); // Actions.
diff --git a/ios/chrome/app/application_delegate/metrics_mediator.h b/ios/chrome/app/application_delegate/metrics_mediator.h index 81e60326..1aae453 100644 --- a/ios/chrome/app/application_delegate/metrics_mediator.h +++ b/ios/chrome/app/application_delegate/metrics_mediator.h
@@ -7,9 +7,7 @@ #import <UIKit/UIKit.h> -@protocol StartupInformation; - -@protocol BrowserInterfaceProvider; +@class SceneState; @protocol StartupInformation; namespace metrics_mediator { @@ -38,8 +36,7 @@ // Logs the number of tabs open and the start type. + (void)logLaunchMetricsWithStartupInformation: (id<StartupInformation>)startupInformation - interfaceProvider:(id<BrowserInterfaceProvider>) - interfaceProvider; + connectedScenes:(NSArray<SceneState*>*)scenes; // Logs in UserDefaults the current date with kAppEnteredBackgroundDateKey as // key. + (void)logDateInUserDefaults;
diff --git a/ios/chrome/app/application_delegate/metrics_mediator.mm b/ios/chrome/app/application_delegate/metrics_mediator.mm index 90b22b65..1f8a608 100644 --- a/ios/chrome/app/application_delegate/metrics_mediator.mm +++ b/ios/chrome/app/application_delegate/metrics_mediator.mm
@@ -22,13 +22,14 @@ #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/crash_report/breakpad_helper.h" +#include "ios/chrome/browser/main/browser.h" #include "ios/chrome/browser/metrics/first_user_action_recorder.h" #import "ios/chrome/browser/metrics/previous_session_info.h" #import "ios/chrome/browser/net/connection_type_observer_bridge.h" #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/system_flags.h" -#import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/main/browser_interface_provider.h" +#import "ios/chrome/browser/ui/main/scene_state.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/chrome/common/app_group/app_group_metrics_mainapp.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" @@ -143,10 +144,13 @@ + (void)logLaunchMetricsWithStartupInformation: (id<StartupInformation>)startupInformation - interfaceProvider:(id<BrowserInterfaceProvider>) - interfaceProvider { - int numTabs = - static_cast<int>(interfaceProvider.mainInterface.tabModel.count); + connectedScenes:(NSArray<SceneState*>*)scenes { + int numTabs = 0; + for (SceneState* scene in scenes) { + numTabs += scene.interfaceProvider.mainInterface.browser->GetWebStateList() + ->count(); + } + if (startupInformation.isColdStart) { [self recordNumTabAtStartup:numTabs]; } else { @@ -169,15 +173,27 @@ [startupInformation activateFirstUserActionRecorderWithBackgroundTime:interval]; - web::WebState* currentWebState = interfaceProvider.currentInterface.tabModel - .webStateList->GetActiveWebState(); - if (currentWebState && - currentWebState->GetLastCommittedURL() == kChromeUINewTabURL) { - startupInformation.firstUserActionRecorder->RecordStartOnNTP(); - [startupInformation resetFirstUserActionRecorder]; - } else { - [startupInformation - expireFirstUserActionRecorderAfterDelay:kFirstUserActionTimeout]; + SceneState* activeScene = nil; + for (SceneState* scene in scenes) { + if (scene.activationLevel == SceneActivationLevelForegroundActive) { + activeScene = scene; + break; + } + } + + if (activeScene) { + web::WebState* currentWebState = + activeScene.interfaceProvider.currentInterface.browser + ->GetWebStateList() + ->GetActiveWebState(); + if (currentWebState && + currentWebState->GetLastCommittedURL() == kChromeUINewTabURL) { + startupInformation.firstUserActionRecorder->RecordStartOnNTP(); + [startupInformation resetFirstUserActionRecorder]; + } else { + [startupInformation + expireFirstUserActionRecorderAfterDelay:kFirstUserActionTimeout]; + } } // Remove the value so it's not reused if the app crashes. [[NSUserDefaults standardUserDefaults]
diff --git a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm index e22adb08..a0ac288 100644 --- a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm +++ b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
@@ -10,16 +10,20 @@ #include "components/metrics/metrics_service.h" #import "ios/chrome/app/application_delegate/startup_information.h" #include "ios/chrome/browser/application_context.h" +#import "ios/chrome/browser/main/test_browser.h" #import "ios/chrome/browser/metrics/previous_session_info.h" #import "ios/chrome/browser/metrics/previous_session_info_private.h" #import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/ui/main/browser_interface_provider.h" -#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h" -#import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h" +#import "ios/chrome/browser/ui/main/scene_state.h" +#import "ios/chrome/browser/ui/main/test/fake_scene_state.h" #import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_opener.h" #import "ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.h" #import "ios/testing/scoped_block_swizzler.h" +#import "ios/web/public/test/fakes/test_web_state.h" +#import "ios/web/public/test/web_task_environment.h" #include "net/base/network_change_notifier.h" #include "testing/platform_test.h" #import "third_party/breakpad/breakpad/src/client/ios/BreakpadController.h" @@ -124,22 +128,9 @@ class MetricsMediatorLogLaunchTest : public PlatformTest { protected: - MetricsMediatorLogLaunchTest() - : has_been_called_(FALSE), - web_state_list_( - std::make_unique<WebStateList>(&web_state_list_delegate_)) {} + MetricsMediatorLogLaunchTest() : has_been_called_(FALSE) {} void initiateMetricsMediator(BOOL coldStart, int tabCount) { - id mainTabModel = [OCMockObject mockForClass:[TabModel class]]; - [[[mainTabModel stub] andReturnValue:@(tabCount)] count]; - WebStateList* web_state_list = web_state_list_.get(); - [[[mainTabModel stub] andReturnValue:OCMOCK_VALUE(web_state_list)] - webStateList]; - StubBrowserInterfaceProvider* concreteProvider = - [[StubBrowserInterfaceProvider alloc] init]; - concreteProvider.mainInterface.tabModel = mainTabModel; - interface_provider_ = concreteProvider; - swizzle_block_ = [^(id self, int numTab) { has_been_called_ = YES; // Tests. @@ -158,17 +149,12 @@ void verifySwizzleHasBeenCalled() { EXPECT_TRUE(has_been_called_); } - id<BrowserInterfaceProvider> getInterfaceProvider() { - return interface_provider_; - } - - private: - id<BrowserInterfaceProvider> interface_provider_; + web::WebTaskEnvironment task_environment_; + NSArray<FakeSceneState*>* connected_scenes_; __block BOOL has_been_called_; logLaunchMetricsBlock swizzle_block_; std::unique_ptr<ScopedBlockSwizzler> uma_histogram_swizzler_; - std::unique_ptr<WebStateList> web_state_list_; - FakeWebStateListDelegate web_state_list_delegate_; + std::set<std::unique_ptr<TestBrowser>> browsers_; }; // Verifies that the log of the number of open tabs is sent and verifies @@ -177,6 +163,13 @@ // Setup. BOOL coldStart = YES; initiateMetricsMediator(coldStart, 23); + // 23 tabs across three scenes. + connected_scenes_ = [FakeSceneState sceneArrayWithCount:3]; + [connected_scenes_[0] appendWebStatesWithURL:GURL() count:9]; + [connected_scenes_[1] appendWebStatesWithURL:GURL() count:9]; + [connected_scenes_[2] appendWebStatesWithURL:GURL() count:5]; + // Mark one of the scenes as active. + connected_scenes_[0].activationLevel = SceneActivationLevelForegroundActive; const NSTimeInterval kFirstUserActionTimeout = 30.0; @@ -191,9 +184,8 @@ forKey:metrics_mediator::kAppEnteredBackgroundDateKey]; // Action. - [MetricsMediator - logLaunchMetricsWithStartupInformation:startupInformation - interfaceProvider:getInterfaceProvider()]; + [MetricsMediator logLaunchMetricsWithStartupInformation:startupInformation + connectedScenes:connected_scenes_]; // Tests. NSDate* dateStored = [[NSUserDefaults standardUserDefaults] @@ -209,6 +201,13 @@ // Setup. BOOL coldStart = NO; initiateMetricsMediator(coldStart, 32); + // 32 tabs across five scenes. + connected_scenes_ = [FakeSceneState sceneArrayWithCount:5]; + [connected_scenes_[0] appendWebStatesWithURL:GURL() count:8]; + [connected_scenes_[1] appendWebStatesWithURL:GURL() count:8]; + // Scene 2 has zero tabs. + [connected_scenes_[3] appendWebStatesWithURL:GURL() count:8]; + [connected_scenes_[4] appendWebStatesWithURL:GURL() count:8]; id startupInformation = [OCMockObject mockForProtocol:@protocol(StartupInformation)]; @@ -218,10 +217,8 @@ removeObjectForKey:metrics_mediator::kAppEnteredBackgroundDateKey]; // Action. - [MetricsMediator - logLaunchMetricsWithStartupInformation:startupInformation - interfaceProvider:getInterfaceProvider()]; - + [MetricsMediator logLaunchMetricsWithStartupInformation:startupInformation + connectedScenes:connected_scenes_]; // Tests. verifySwizzleHasBeenCalled(); }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 3d6f65b..8d4c441 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -540,7 +540,7 @@ [self scheduleStartupCleanupTasks]; [MetricsMediator logLaunchMetricsWithStartupInformation:self - interfaceProvider:self.interfaceProvider]; + connectedScenes:self.appState.connectedScenes]; if (self.isColdStart) { [ContentSuggestionsSchedulerNotifications notifyColdStart:self.mainBrowserState];
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm index 304c750..14e5931 100644 --- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge_unittests.mm
@@ -323,7 +323,8 @@ // Tests to send a request with no cookies set in the cookie store and receive // multiples cookies from the request. // TODO(crbug.com/1065349): this test is flaky. -TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FetchWithEmptyCookieStore) { +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, + DISABLED_FetchWithEmptyCookieStore) { ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); OCMExpect([http_cookie_storage_mock_ storeCookies:@[] @@ -345,7 +346,8 @@ // Tests to send a request with one cookie set in the cookie store and receive // another cookies from the request. // TODO(crbug.com/1065349): this test is flaky. -TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FLAKY_FetchWithCookieStore) { +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, + DISABLED_FetchWithCookieStore) { NSArray* cookies_to_send = @[ GetCookie1() ]; AddCookiesToCookieManager(cookies_to_send); ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); @@ -368,7 +370,7 @@ // Tests to a request with a redirect. One cookie is received by the first // request, and a second one by the redirected request. // TODO(crbug.com/1065349): this test is flaky. -TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, FLAKY_FetchWithRedirect) { +TEST_F(GaiaAuthFetcherIOSNSURLSessionBridgeTest, DISABLED_FetchWithRedirect) { ns_url_session_bridge_->Fetch(GetFetchGURL(), "", "", false); OCMExpect([http_cookie_storage_mock_ storeCookies:@[]
diff --git a/ios/chrome/browser/test/perf_test_with_bvc_ios.mm b/ios/chrome/browser/test/perf_test_with_bvc_ios.mm index d6db722..443c263c 100644 --- a/ios/chrome/browser/test/perf_test_with_bvc_ios.mm +++ b/ios/chrome/browser/test/perf_test_with_bvc_ios.mm
@@ -123,8 +123,6 @@ bvc_ = [[BrowserViewController alloc] initWithBrowser:browser_.get() dependencyFactory:bvc_factory_ - applicationCommandEndpoint:nil - browsingDataCommandEndpoint:nil browserContainerViewController:[[BrowserContainerViewController alloc] init]]; [bvc_ setActive:YES];
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.h b/ios/chrome/browser/ui/browser_view/browser_coordinator.h index 28666d45..100eaf9 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.h +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.h
@@ -8,8 +8,6 @@ #include "base/ios/block_types.h" #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" -@protocol ApplicationCommands; -@protocol BrowsingDataCommands; @class BrowserViewController; class AppUrlLoadingService; @@ -27,11 +25,6 @@ // The main view controller. @property(nonatomic, strong, readonly) BrowserViewController* viewController; -// Command handler for ApplicationCommands. -@property(nonatomic, weak) id<ApplicationCommands> applicationCommandHandler; -// Command handler for BrowsingDataCommands. -@property(nonatomic, weak) id<BrowsingDataCommands> browsingDataCommandHandler; - // The application level component for url loading. Should be used only by // browser state level UrlLoadingService instances. @property(nonatomic, assign) AppUrlLoadingService* appURLLoadingService;
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index ff65788..3342827c 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -296,8 +296,6 @@ _viewController = [[BrowserViewController alloc] initWithBrowser:self.browser dependencyFactory:factory - applicationCommandEndpoint:self.applicationCommandHandler - browsingDataCommandEndpoint:self.browsingDataCommandHandler browserContainerViewController:self.browserContainerCoordinator .viewController]; } @@ -726,17 +724,17 @@ #pragma mark - FormInputAccessoryCoordinatorNavigator - (void)openPasswordSettings { - [self.applicationCommandHandler + [HandlerForProtocol(self.dispatcher, ApplicationCommands) showSavedPasswordsSettingsFromViewController:self.viewController]; } - (void)openAddressSettings { - [self.applicationCommandHandler + [HandlerForProtocol(self.dispatcher, ApplicationCommands) showProfileSettingsFromViewController:self.viewController]; } - (void)openCreditCardSettings { - [self.applicationCommandHandler + [HandlerForProtocol(self.dispatcher, ApplicationCommands) showCreditCardSettingsFromViewController:self.viewController]; }
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.h b/ios/chrome/browser/ui/browser_view/browser_view_controller.h index d9ec30b..c3be42a 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.h +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.h
@@ -49,10 +49,6 @@ - (instancetype)initWithBrowser:(Browser*)browser dependencyFactory: (BrowserViewControllerDependencyFactory*)factory - applicationCommandEndpoint: - (id<ApplicationCommands>)applicationCommandEndpoint - browsingDataCommandEndpoint: - (id<BrowsingDataCommands>)browsingDataCommandEndpoint browserContainerViewController: (BrowserContainerViewController*)browserContainerViewController NS_DESIGNATED_INITIALIZER;
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index b16b3dd..6bf41ca8 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -713,10 +713,6 @@ - (instancetype)initWithBrowser:(Browser*)browser dependencyFactory: (BrowserViewControllerDependencyFactory*)factory - applicationCommandEndpoint: - (id<ApplicationCommands>)applicationCommandEndpoint - browsingDataCommandEndpoint: - (id<BrowsingDataCommands>)browsingDataCommandEndpoint browserContainerViewController: (BrowserContainerViewController*)browserContainerViewController { self = [super initWithNibName:nil bundle:base::mac::FrameworkBundle()]; @@ -731,22 +727,7 @@ [self.commandDispatcher startDispatchingToTarget:self forProtocol:@protocol(BrowserCommands)]; - [self.commandDispatcher - startDispatchingToTarget:applicationCommandEndpoint - forProtocol:@protocol(ApplicationCommands)]; - // -startDispatchingToTarget:forProtocol: doesn't pick up protocols the - // passed protocol conforms to, so ApplicationSettingsCommands is explicitly - // dispatched to the endpoint as well. Since this is potentially - // fragile, DCHECK that it should still work (if the endpoint is nonnull). - DCHECK(!applicationCommandEndpoint || - [applicationCommandEndpoint - conformsToProtocol:@protocol(ApplicationSettingsCommands)]); - [self.commandDispatcher - startDispatchingToTarget:applicationCommandEndpoint - forProtocol:@protocol(ApplicationSettingsCommands)]; - [self.commandDispatcher - startDispatchingToTarget:browsingDataCommandEndpoint - forProtocol:@protocol(BrowsingDataCommands)]; + _toolbarCoordinatorAdaptor = [[ToolbarCoordinatorAdaptor alloc] initWithDispatcher:self.dispatcher]; self.toolbarInterface = _toolbarCoordinatorAdaptor;
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm index 8778f054..775754b 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
@@ -129,6 +129,20 @@ startDispatchingToTarget:mockPageInfoCommandHandler forProtocol:@protocol(PageInfoCommands)]; + // Set up ApplicationCommands mock. Because ApplicationCommands conforms + // to ApplicationSettingsCommands, that needs to be mocked and dispatched + // as well. + id mockApplicationCommandHandler = + OCMProtocolMock(@protocol(ApplicationCommands)); + id mockApplicationSettingsCommandHandler = + OCMProtocolMock(@protocol(ApplicationSettingsCommands)); + [browser_->GetCommandDispatcher() + startDispatchingToTarget:mockApplicationCommandHandler + forProtocol:@protocol(ApplicationCommands)]; + [browser_->GetCommandDispatcher() + startDispatchingToTarget:mockApplicationSettingsCommandHandler + forProtocol:@protocol(ApplicationSettingsCommands)]; + // Create three web states. for (int i = 0; i < 3; i++) { web::WebState::CreateParams params(chrome_browser_state_.get()); @@ -145,15 +159,9 @@ chrome_browser_state_.get()); template_url_service->Load(); - // Instantiate the BVC. - id mockApplicationCommandHandler = - OCMProtocolMock(@protocol(ApplicationCommands)); - bvc_ = [[BrowserViewController alloc] initWithBrowser:browser_.get() dependencyFactory:factory - applicationCommandEndpoint:mockApplicationCommandHandler - browsingDataCommandEndpoint:nil browserContainerViewController:[[BrowserContainerViewController alloc] init]];
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm index f95489ab..f014a856 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -22,6 +22,9 @@ #import "ios/chrome/browser/ui/browser_view/browser_coordinator.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" +#import "ios/chrome/browser/ui/commands/browsing_data_commands.h" +#import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/url_loading/app_url_loading_service.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" @@ -170,6 +173,7 @@ BrowserList* browserList = BrowserListFactory::GetForBrowserState(_mainBrowser->GetBrowserState()); browserList->AddBrowser(_mainBrowser.get()); + [self dispatchToEndpointsForBrowser:_mainBrowser.get()]; [self restoreSessionToBrowser:_mainBrowser.get()]; [self addObserversToWebStateList:_mainBrowser->GetWebStateList()]; @@ -381,6 +385,7 @@ BrowserList* browserList = BrowserListFactory::GetForBrowserState(browser->GetBrowserState()); browserList->AddIncognitoBrowser(browser.get()); + [self dispatchToEndpointsForBrowser:browser.get()]; if (restorePersistedState) [self restoreSessionToBrowser:browser.get()]; @@ -393,12 +398,29 @@ BrowserCoordinator* coordinator = [[BrowserCoordinator alloc] initWithBaseViewController:nil browser:browser]; - coordinator.applicationCommandHandler = _applicationCommandEndpoint; - coordinator.browsingDataCommandHandler = _browsingDataCommandEndpoint; coordinator.appURLLoadingService = _appURLLoadingService; return coordinator; } +- (void)dispatchToEndpointsForBrowser:(Browser*)browser { + [browser->GetCommandDispatcher() + startDispatchingToTarget:_applicationCommandEndpoint + forProtocol:@protocol(ApplicationCommands)]; + // -startDispatchingToTarget:forProtocol: doesn't pick up protocols the + // passed protocol conforms to, so ApplicationSettingsCommands is explicitly + // dispatched to the endpoint as well. Since this is potentially + // fragile, DCHECK that it should still work (if the endpoint is non-nil). + DCHECK(!_applicationCommandEndpoint || + [_applicationCommandEndpoint + conformsToProtocol:@protocol(ApplicationSettingsCommands)]); + [browser->GetCommandDispatcher() + startDispatchingToTarget:_applicationCommandEndpoint + forProtocol:@protocol(ApplicationSettingsCommands)]; + [browser->GetCommandDispatcher() + startDispatchingToTarget:_browsingDataCommandEndpoint + forProtocol:@protocol(BrowsingDataCommands)]; +} + - (void)restoreSessionToBrowser:(Browser*)browser { SessionWindowIOS* sessionWindow = nil; NSString* statePath = base::SysUTF8ToNSString(
diff --git a/ios/chrome/browser/ui/main/test/BUILD.gn b/ios/chrome/browser/ui/main/test/BUILD.gn index 9d3709a..a2e9ab2 100644 --- a/ios/chrome/browser/ui/main/test/BUILD.gn +++ b/ios/chrome/browser/ui/main/test/BUILD.gn
@@ -4,11 +4,21 @@ source_set("test") { configs += [ "//build/config/compiler:enable_arc" ] + testonly = true sources = [ + "fake_scene_state.h", + "fake_scene_state.mm", "stub_browser_interface.h", "stub_browser_interface.mm", "stub_browser_interface_provider.h", "stub_browser_interface_provider.mm", ] - deps = [ "//ios/chrome/browser/ui/main" ] + deps = [ + "//ios/chrome/browser/main:public", + "//ios/chrome/browser/main:test_support", + "//ios/chrome/browser/ui/main", + "//ios/chrome/browser/ui/main:scene", + "//ios/chrome/browser/web_state_list", + "//ios/web/public/test/fakes", + ] }
diff --git a/ios/chrome/browser/ui/main/test/fake_scene_state.h b/ios/chrome/browser/ui/main/test/fake_scene_state.h new file mode 100644 index 0000000..113cc80 --- /dev/null +++ b/ios/chrome/browser/ui/main/test/fake_scene_state.h
@@ -0,0 +1,27 @@ +// 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_MAIN_TEST_FAKE_SCENE_STATE_H_ +#define IOS_CHROME_BROWSER_UI_MAIN_TEST_FAKE_SCENE_STATE_H_ + +#import "ios/chrome/browser/ui/main/scene_state.h" +#import "url/gurl.h" + +// Test double for SceneState, created with appropriate interface objects backed +// by a browser. No incognito interface is created by default. +// Any test using objects of this class must include a TaskEnvironment member +// because of the embedded test browser state. +@interface FakeSceneState : SceneState + +// Creates an array of |count| instances. ++ (NSArray<FakeSceneState*>*)sceneArrayWithCount:(int)count; + +// Append a suitable web state test double to the receiver's main interface. +- (void)appendWebStateWithURL:(const GURL)URL; +// Append |count| web states, all with |url| as the current URL, to the +- (void)appendWebStatesWithURL:(const GURL)URL count:(int)count; + +@end + +#endif // IOS_CHROME_BROWSER_UI_MAIN_TEST_FAKE_SCENE_STATE_H_
diff --git a/ios/chrome/browser/ui/main/test/fake_scene_state.mm b/ios/chrome/browser/ui/main/test/fake_scene_state.mm new file mode 100644 index 0000000..90d1a91 --- /dev/null +++ b/ios/chrome/browser/ui/main/test/fake_scene_state.mm
@@ -0,0 +1,68 @@ +// 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/main/test/fake_scene_state.h" + +#import "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/main/test_browser.h" +#import "ios/chrome/browser/ui/main/test/stub_browser_interface.h" +#import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_opener.h" +#import "ios/web/public/test/fakes/test_web_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface FakeSceneState () +// Redeclare interface provider readwrite. +@property(nonatomic, strong, readwrite) id<BrowserInterfaceProvider> + interfaceProvider; +@end + +@implementation FakeSceneState { + // Owning pointer for the browser that backs the interface provider. + std::unique_ptr<TestBrowser> _browser; +} + +@synthesize interfaceProvider = _interfaceProvider; + +- (instancetype)init { + if (self = [super init]) { + self.activationLevel = SceneActivationLevelForegroundInactive; + self.interfaceProvider = [[StubBrowserInterfaceProvider alloc] init]; + StubBrowserInterface* mainInterface = static_cast<StubBrowserInterface*>( + self.interfaceProvider.mainInterface); + _browser = std::make_unique<TestBrowser>(); + mainInterface.browser = _browser.get(); + } + return self; +} + ++ (NSArray<FakeSceneState*>*)sceneArrayWithCount:(int)count { + NSMutableArray<SceneState*>* scenes = [NSMutableArray array]; + for (int i = 0; i < count; i++) { + [scenes addObject:[[self alloc] init]]; + } + return [scenes copy]; +} + +- (void)appendWebStateWithURL:(const GURL)URL { + auto test_web_state = std::make_unique<web::TestWebState>(); + test_web_state->SetCurrentURL(URL); + WebStateList* web_state_list = + self.interfaceProvider.mainInterface.browser->GetWebStateList(); + web_state_list->InsertWebState( + WebStateList::kInvalidIndex, std::move(test_web_state), + WebStateList::INSERT_NO_FLAGS, WebStateOpener()); +} + +- (void)appendWebStatesWithURL:(const GURL)URL count:(int)count { + for (int i = 0; i < count; i++) { + [self appendWebStateWithURL:URL]; + } +} + +@end
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn index a0de7b03..8d348c9 100644 --- a/ios/chrome/browser/ui/popup_menu/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -151,6 +151,7 @@ ] deps = [ ":constants", + "//base/test:test_support", "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/test/earl_grey:eg_test_support+eg2", @@ -174,6 +175,7 @@ ] deps = [ "//base", + "//base/test:test_support", "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser/ui/popup_menu:constants",
diff --git a/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm b/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm index 7e3260436..2b0bbac 100644 --- a/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm +++ b/ios/chrome/browser/ui/popup_menu/request_desktop_mobile_site_egtest.mm
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/strings/sys_string_conversions.h" +#import "base/test/ios/wait_util.h" #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h" #include "ios/chrome/grit/ios_strings.h" @@ -31,6 +32,17 @@ const char kDesktopSiteLabel[] = "Desktop"; const char kDesktopPlatformLabel[] = "MacIntel"; +// URL to be used when the page needs to be reloaded on back/forward +// navigations. +const char kPurgeURL[] = "url-purge.com"; +// JavaScript used to reload the page on back/forward navigations. +const char kJavaScriptReload[] = + "<script>window.onpageshow = function(event) {" + " if (event.persisted) {" + " window.location.href = window.location.href + \"?reloaded\"" + " }" + "};</script>"; + // Custom timeout used when waiting for a web state after requesting desktop // or mobile mode. const NSTimeInterval kWaitForUserAgentChangeTimeout = 15.0; @@ -79,15 +91,20 @@ return; } + std::string purge_additions = ""; + if (request.url.path().find(kPurgeURL) != std::string::npos) { + purge_additions = kJavaScriptReload; + } + *headers = web::ResponseProvider::GetDefaultResponseHeaders(); std::string userAgent; std::string desktop_user_agent = web::BuildUserAgentFromProduct(web::UserAgentType::DESKTOP, ""); if (request.headers.GetHeader("User-Agent", &userAgent) && userAgent == desktop_user_agent) { - response_body->assign("Desktop"); + response_body->assign(std::string("Desktop\n") + purge_additions); } else { - response_body->assign("Mobile"); + response_body->assign(std::string("Mobile\n") + purge_additions); } } }; @@ -168,6 +185,45 @@ [ChromeEarlGrey waitForWebStateContainingText:kMobileSiteLabel]; } +// Tests that when requesting desktop on another page and coming back to a page +// that has been purged from memory, we still display the mobile page. +- (void)testRequestDesktopSiteGoBackToMobilePurged { + if (@available(iOS 13, *)) { + } else { + EARL_GREY_TEST_DISABLED(@"On iOS 12, the User Agent can be wrong when " + @"doing back/forward navigations"); + } + + std::unique_ptr<web::DataResponseProvider> provider( + new UserAgentResponseProvider()); + web::test::SetUpHttpServer(std::move(provider)); + + [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl( + "http://" + std::string(kPurgeURL))]; + // Verify initial reception of the mobile site. + [ChromeEarlGrey waitForWebStateContainingText:kMobileSiteLabel]; + + [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl("http://2.com")]; + + // Request and verify reception of the desktop site. + [ChromeEarlGreyUI openToolsMenu]; + [RequestDesktopButton() performAction:grey_tap()]; + [ChromeEarlGrey waitForWebStateContainingText:kDesktopSiteLabel + timeout:kWaitForUserAgentChangeTimeout]; + + // Verify that going back returns to the mobile site. + [[EarlGrey selectElementWithMatcher:chrome_test_util::BackButton()] + performAction:grey_tap()]; + GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForPageLoadTimeout, + ^bool { + return [ChromeEarlGrey webStateVisibleURL].query() == + "reloaded"; + }), + @"Page did not reload"); + [ChromeEarlGrey waitForWebStateContainingText:kMobileSiteLabel]; +} + // Tests that requesting mobile site of a page works and the user agent // propagates to the next navigations in the same tab. - (void)testRequestMobileSitePropagatesToNextNavigations {
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index c774202..6dc9484f 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -54,12 +54,8 @@ "content_settings_table_view_controller.mm", "dataplan_usage_table_view_controller.h", "dataplan_usage_table_view_controller.mm", - "handoff_table_view_controller.h", - "handoff_table_view_controller.mm", "import_data_table_view_controller.h", "import_data_table_view_controller.mm", - "privacy_table_view_controller.h", - "privacy_table_view_controller.mm", "search_engine_table_view_controller.h", "search_engine_table_view_controller.mm", "settings_navigation_controller.mm", @@ -105,7 +101,6 @@ "//components/content_settings/core/browser", "//components/content_settings/core/common", "//components/feature_engagement", - "//components/handoff", "//components/history/core/browser", "//components/image_fetcher/ios", "//components/keyed_service/core", @@ -160,6 +155,7 @@ "//ios/chrome/browser/ui/settings/language:language", "//ios/chrome/browser/ui/settings/language:language_ui", "//ios/chrome/browser/ui/settings/password", + "//ios/chrome/browser/ui/settings/privacy", "//ios/chrome/browser/ui/settings/sync", "//ios/chrome/browser/ui/settings/sync/utils", "//ios/chrome/browser/ui/settings/utils", @@ -255,7 +251,6 @@ "content_settings_table_view_controller_unittest.mm", "dataplan_usage_table_view_controller_unittest.mm", "import_data_table_view_controller_unittest.mm", - "privacy_table_view_controller_unittest.mm", "search_engine_table_view_controller_unittest.mm", "settings_navigation_controller_unittest.mm", "settings_root_table_view_controller_unittest.mm",
diff --git a/ios/chrome/browser/ui/settings/privacy/BUILD.gn b/ios/chrome/browser/ui/settings/privacy/BUILD.gn new file mode 100644 index 0000000..ba0895b --- /dev/null +++ b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
@@ -0,0 +1,65 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("privacy") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "handoff_table_view_controller.h", + "handoff_table_view_controller.mm", + "privacy_table_view_controller.h", + "privacy_table_view_controller.mm", + ] + deps = [ + "//base", + "//components/handoff", + "//components/prefs", + "//components/prefs/ios", + "//components/strings", + "//ios/chrome/app/strings", + "//ios/chrome/browser", + "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/browsing_data:feature_flags", + "//ios/chrome/browser/main:public", + "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/colors", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/settings:constants", + "//ios/chrome/browser/ui/settings:settings_root", + "//ios/chrome/browser/ui/settings/cells", + "//ios/chrome/browser/ui/settings/clear_browsing_data:clear_browsing_data", + "//ios/chrome/browser/ui/settings/sync/utils", + "//ios/chrome/browser/ui/settings/utils", + "//ios/chrome/browser/ui/table_view", + "//ios/chrome/browser/ui/table_view/cells", + "//ios/chrome/browser/ui/table_view/cells:cells_constants", + "//ui/base", + ] +} + +source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + sources = [ "privacy_table_view_controller_unittest.mm" ] + deps = [ + "//base/test:test_support", + "//components/handoff", + "//components/prefs", + "//components/prefs/ios", + "//components/strings", + "//components/sync_preferences", + "//components/sync_preferences:test_support", + "//ios/chrome/app/strings", + "//ios/chrome/browser", + "//ios/chrome/browser/browser_state:test_support", + "//ios/chrome/browser/browsing_data:feature_flags", + "//ios/chrome/browser/main:test_support", + "//ios/chrome/browser/prefs:browser_prefs", + "//ios/chrome/browser/ui/settings/privacy", + "//ios/chrome/browser/ui/table_view:test_support", + "//ios/chrome/test:test_support", + "//ios/web/public/test", + "//testing/gtest", + "//ui/base", + ] +}
diff --git a/ios/chrome/browser/ui/settings/handoff_table_view_controller.h b/ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.h similarity index 73% rename from ios/chrome/browser/ui/settings/handoff_table_view_controller.h rename to ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.h index e60017d..7007123 100644 --- a/ios/chrome/browser/ui/settings/handoff_table_view_controller.h +++ b/ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_HANDOFF_TABLE_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_HANDOFF_TABLE_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_HANDOFF_TABLE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_HANDOFF_TABLE_VIEW_CONTROLLER_H_ #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" @@ -20,4 +20,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_HANDOFF_TABLE_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_HANDOFF_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/handoff_table_view_controller.mm b/ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.mm similarity index 94% rename from ios/chrome/browser/ui/settings/handoff_table_view_controller.mm rename to ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.mm index 351c4b3..89b4545 100644 --- a/ios/chrome/browser/ui/settings/handoff_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/handoff_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.h" #import "base/mac/foundation_util.h" #include "components/handoff/pref_names_ios.h" @@ -93,8 +93,8 @@ - (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { - UITableViewCell* cell = - [super tableView:tableView cellForRowAtIndexPath:indexPath]; + UITableViewCell* cell = [super tableView:tableView + cellForRowAtIndexPath:indexPath]; ItemType itemType = static_cast<ItemType>( [self.tableViewModel itemTypeForIndexPath:indexPath]);
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller.h b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.h similarity index 72% rename from ios/chrome/browser/ui/settings/privacy_table_view_controller.h rename to ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.h index f12369e..a82822d0 100644 --- a/ios/chrome/browser/ui/settings/privacy_table_view_controller.h +++ b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_TABLE_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_TABLE_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_PRIVACY_TABLE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_PRIVACY_TABLE_VIEW_CONTROLLER_H_ #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" @@ -21,4 +21,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_TABLE_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PRIVACY_PRIVACY_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.mm similarity index 97% rename from ios/chrome/browser/ui/settings/privacy_table_view_controller.mm rename to ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.mm index 9772d45..10a6777 100644 --- a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/privacy_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.h" #include "base/logging.h" #import "base/mac/foundation_util.h" @@ -20,7 +20,7 @@ #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_table_view_controller.h" #import "ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_ui_delegate.h" -#import "ios/chrome/browser/ui/settings/handoff_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/privacy/handoff_table_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_detail_icon_item.h" @@ -189,8 +189,8 @@ - (UIView*)tableView:(UITableView*)tableView viewForFooterInSection:(NSInteger)section { - UIView* footerView = - [super tableView:tableView viewForFooterInSection:section]; + UIView* footerView = [super tableView:tableView + viewForFooterInSection:section]; TableViewLinkHeaderFooterView* footer = base::mac::ObjCCast<TableViewLinkHeaderFooterView>(footerView); if (footer) {
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller_unittest.mm similarity index 97% rename from ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm rename to ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller_unittest.mm index 495738f..061a656 100644 --- a/ios/chrome/browser/ui/settings/privacy_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/settings/privacy_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.h" #include <memory>
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm index 4b8ce94..1048ce93 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -57,7 +57,7 @@ #import "ios/chrome/browser/ui/settings/language/language_settings_mediator.h" #import "ios/chrome/browser/ui/settings/language/language_settings_table_view_controller.h" #import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h" -#import "ios/chrome/browser/ui/settings/privacy_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.h" #import "ios/chrome/browser/ui/settings/search_engine_table_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h" #import "ios/chrome/browser/ui/settings/sync/utils/sync_util.h"
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 5bd02b3..3127073 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -292,6 +292,7 @@ "//ios/chrome/browser/ui/settings/credit_card_scanner:unit_tests", "//ios/chrome/browser/ui/settings/language:unit_tests", "//ios/chrome/browser/ui/settings/password:unit_tests", + "//ios/chrome/browser/ui/settings/privacy:unit_tests", "//ios/chrome/browser/ui/settings/sync:unit_tests", "//ios/chrome/browser/ui/side_swipe:unit_tests", "//ios/chrome/browser/ui/tab_grid:unit_tests",
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 392f4a3b..018be6a7 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -299,6 +299,7 @@ "//ios/chrome/browser/ui/settings/google_services:constants", "//ios/chrome/browser/ui/settings/password:eg_test_support", "//ios/chrome/browser/ui/settings/password:password_constants", + "//ios/chrome/browser/ui/settings/privacy", "//ios/chrome/browser/ui/settings/sync", "//ios/chrome/browser/ui/tab_grid:tab_grid_ui_constants", "//ios/chrome/browser/ui/tab_grid/grid:grid_ui_constants", @@ -458,6 +459,7 @@ "//ios/chrome/browser/ui/settings/language:eg_app_support+eg2", "//ios/chrome/browser/ui/settings/password:eg_app_support+eg2", "//ios/chrome/browser/ui/settings/password:password_constants", + "//ios/chrome/browser/ui/settings/privacy", "//ios/chrome/browser/ui/settings/sync", "//ios/chrome/browser/ui/signin_interaction:eg_app_support+eg2", "//ios/chrome/browser/ui/tab_grid:tab_grid_ui_constants",
diff --git a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm index 1968237..280ea852 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_matchers_app_interface.mm
@@ -42,7 +42,7 @@ #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_constants.h" #import "ios/chrome/browser/ui/settings/import_data_table_view_controller.h" #import "ios/chrome/browser/ui/settings/password/passwords_table_view_constants.h" -#import "ios/chrome/browser/ui/settings/privacy_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_root_table_constants.h" #import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h"
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm index 6c22128..710f56c 100644 --- a/ios/web/navigation/crw_wk_navigation_handler.mm +++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -181,6 +181,21 @@ } } + if (item && userAgentType == web::UserAgentType::NONE && + web::GetWebClient()->IsAppSpecificURL(item->GetVirtualURL())) { + // In case the URL to be loaded is a WebUI URL and the user agent is nil, + // get the mobile user agent. + userAgentType = web::UserAgentType::MOBILE; + } + + if (userAgentType != web::UserAgentType::NONE) { + NSString* userAgentString = base::SysUTF8ToNSString( + web::GetWebClient()->GetUserAgent(userAgentType)); + if (![webView.customUserAgent isEqualToString:userAgentString]) { + webView.customUserAgent = userAgentString; + } + } + WKContentMode contentMode = userAgentType == web::UserAgentType::DESKTOP ? WKContentModeDesktop : WKContentModeMobile;
diff --git a/ios/web/web_state/ui/crw_web_request_controller.mm b/ios/web/web_state/ui/crw_web_request_controller.mm index aed49085..8622250 100644 --- a/ios/web/web_state/ui/crw_web_request_controller.mm +++ b/ios/web/web_state/ui/crw_web_request_controller.mm
@@ -573,11 +573,18 @@ itemUserAgentType = web::UserAgentType::MOBILE; } - if (itemUserAgentType != web::UserAgentType::NONE) { - NSString* userAgentString = base::SysUTF8ToNSString( - web::GetWebClient()->GetUserAgent(itemUserAgentType)); - if (![self.webView.customUserAgent isEqualToString:userAgentString]) { - self.webView.customUserAgent = userAgentString; + if (@available(iOS 13, *)) { + } else { + // On iOS 13, this is done in + // webView:decidePolicyForNavigationAction:preferences:decisionHandler:. As + // the method only exists for iOS 13, this check still need to be there for + // iOS 12. + if (itemUserAgentType != web::UserAgentType::NONE) { + NSString* userAgentString = base::SysUTF8ToNSString( + web::GetWebClient()->GetUserAgent(itemUserAgentType)); + if (![self.webView.customUserAgent isEqualToString:userAgentString]) { + self.webView.customUserAgent = userAgentString; + } } }
diff --git a/ios/web_view/public/cwv_ui_delegate.h b/ios/web_view/public/cwv_ui_delegate.h index 809fa07..fe54339a 100644 --- a/ios/web_view/public/cwv_ui_delegate.h +++ b/ios/web_view/public/cwv_ui_delegate.h
@@ -68,7 +68,7 @@ defaultText:(NSString*)defaultText pageURL:(NSURL*)URL completionHandler: - (void (^)(NSString*))completionHandler; + (void (^)(NSString* _Nullable))completionHandler; // Determines whether the given link with |linkURL| should show a preview on // force touch. Return value NO is assumed if the method is not implemented. @@ -98,7 +98,7 @@ - (void)webView:(CWVWebView*)webView contextMenuConfigurationForLinkWithURL:(NSURL*)linkURL completionHandler: - (void (^)(UIContextMenuConfiguration*)) + (void (^)(UIContextMenuConfiguration* _Nullable)) completionHandler API_AVAILABLE(ios(13.0)); // Equivalent of -[WKUIDelegate
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index a86080cf..5acdb01 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -103,8 +103,6 @@ "audio_output_resampler.h", "audio_output_stream_sink.cc", "audio_output_stream_sink.h", - "audio_power_monitor.cc", - "audio_power_monitor.h", "audio_sink_parameters.cc", "audio_sink_parameters.h", "audio_source_diverter.h", @@ -377,7 +375,6 @@ "audio_output_device_unittest.cc", "audio_output_proxy_unittest.cc", "audio_output_unittest.cc", - "audio_power_monitor_unittest.cc", "audio_system_impl_unittest.cc", "audio_thread_hang_monitor_unittest.cc", "power_observer_helper_unittest.cc",
diff --git a/media/audio/audio_output_device.cc b/media/audio/audio_output_device.cc index 75ad621..86239ef1 100644 --- a/media/audio/audio_output_device.cc +++ b/media/audio/audio_output_device.cc
@@ -68,7 +68,7 @@ AudioOutputDevice::~AudioOutputDevice() { { // Abort any pending callbacks. Technically we don't need to acquire the - // lock here since ther eshould be no other calls outstanding, but because + // lock here since there should be no other calls outstanding, but because // we've used the GUARDED_BY compiler syntax, we'll get an error without it. base::AutoLock auto_lock(device_info_lock_); if (pending_device_info_cb_) {
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index b1791a0a..60b6abb 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -60,6 +60,8 @@ "audio_fifo.h", "audio_hash.cc", "audio_hash.h", + "audio_power_monitor.cc", + "audio_power_monitor.h", "audio_processing.cc", "audio_processing.h", "audio_pull_fifo.cc", @@ -518,6 +520,7 @@ "audio_latency_unittest.cc", "audio_parameters_unittest.cc", "audio_point_unittest.cc", + "audio_power_monitor_unittest.cc", "audio_pull_fifo_unittest.cc", "audio_push_fifo_unittest.cc", "audio_renderer_mixer_input_unittest.cc",
diff --git a/media/audio/audio_power_monitor.cc b/media/base/audio_power_monitor.cc similarity index 85% rename from media/audio/audio_power_monitor.cc rename to media/base/audio_power_monitor.cc index 77a848e..70d9afd 100644 --- a/media/audio/audio_power_monitor.cc +++ b/media/base/audio_power_monitor.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/audio/audio_power_monitor.h" +#include "media/base/audio_power_monitor.h" #include <algorithm> #include <cmath> @@ -15,10 +15,10 @@ namespace media { -AudioPowerMonitor::AudioPowerMonitor( - int sample_rate, const base::TimeDelta& time_constant) - : sample_weight_( - 1.0f - expf(-1.0f / (sample_rate * time_constant.InSecondsF()))) { +AudioPowerMonitor::AudioPowerMonitor(int sample_rate, + base::TimeDelta time_constant) + : sample_weight_(1.0f - + expf(-1.0f / (sample_rate * time_constant.InSecondsF()))) { Reset(); } @@ -80,8 +80,9 @@ // Convert power level to dBFS units, and pin it down to zero if it is // insignificantly small. const float kInsignificantPower = 1.0e-10f; // -100 dBFS - const float power_dbfs = power_reading_ < kInsignificantPower ? zero_power() : - 10.0f * log10f(power_reading_); + const float power_dbfs = power_reading_ < kInsignificantPower + ? zero_power() + : 10.0f * log10f(power_reading_); const bool clipped = clipped_reading_; clipped_reading_ = false;
diff --git a/media/audio/audio_power_monitor.h b/media/base/audio_power_monitor.h similarity index 93% rename from media/audio/audio_power_monitor.h rename to media/base/audio_power_monitor.h index 1703d24..d95b2836 100644 --- a/media/audio/audio_power_monitor.h +++ b/media/base/audio_power_monitor.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef MEDIA_AUDIO_AUDIO_POWER_MONITOR_H_ -#define MEDIA_AUDIO_AUDIO_POWER_MONITOR_H_ +#ifndef MEDIA_BASE_AUDIO_POWER_MONITOR_H_ +#define MEDIA_BASE_AUDIO_POWER_MONITOR_H_ #include <limits> #include <utility> @@ -40,7 +40,7 @@ // characterizes how samples are averaged over time to determine the power // level; and is the amount of time it takes a zero power level to increase to // ~63.2% of maximum given a step input signal. - AudioPowerMonitor(int sample_rate, const base::TimeDelta& time_constant); + AudioPowerMonitor(int sample_rate, base::TimeDelta time_constant); ~AudioPowerMonitor(); @@ -85,4 +85,4 @@ } // namespace media -#endif // MEDIA_AUDIO_AUDIO_POWER_MONITOR_H_ +#endif // MEDIA_BASE_AUDIO_POWER_MONITOR_H_
diff --git a/media/audio/audio_power_monitor_unittest.cc b/media/base/audio_power_monitor_unittest.cc similarity index 78% rename from media/audio/audio_power_monitor_unittest.cc rename to media/base/audio_power_monitor_unittest.cc index 8d8eed0..7ce16e0 100644 --- a/media/audio/audio_power_monitor_unittest.cc +++ b/media/base/audio_power_monitor_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/audio/audio_power_monitor.h" +#include "media/base/audio_power_monitor.h" #include <limits> #include <memory> @@ -24,8 +24,11 @@ // Container for each parameterized test's data (input and expected results). class TestScenario { public: - TestScenario(const float* data, int num_channels, int num_frames, - float expected_power, bool expected_clipped) + TestScenario(const float* data, + int num_channels, + int num_frames, + float expected_power, + bool expected_clipped) : expected_power_(expected_power), expected_clipped_(expected_clipped) { CreatePopulatedBuffer(data, num_channels, num_frames); } @@ -48,23 +51,18 @@ return result; } - const AudioBus& data() const { - return *bus_; - } + const AudioBus& data() const { return *bus_; } - float expected_power() const { - return expected_power_; - } + float expected_power() const { return expected_power_; } - bool expected_clipped() const { - return expected_clipped_; - } + bool expected_clipped() const { return expected_clipped_; } private: // Creates an AudioBus, sized and populated with kFramesPerBuffer frames of // data. The given test |data| is repeated to fill the buffer. - void CreatePopulatedBuffer( - const float* data, int num_channels, int num_frames) { + void CreatePopulatedBuffer(const float* data, + int num_channels, + int num_frames) { bus_ = AudioBus::Create(num_channels, kFramesPerBuffer); for (int ch = 0; ch < num_channels; ++ch) { for (int frames = 0; frames < kFramesPerBuffer; frames += num_frames) { @@ -85,8 +83,7 @@ ::std::ostream& operator<<(::std::ostream& os, const TestScenario& ts) { return os << "{" << ts.data().channels() << "-channel signal} --> {" << ts.expected_power() << " dBFS, " - << (ts.expected_clipped() ? "clipped" : "not clipped") - << "}"; + << (ts.expected_clipped() ? "clipped" : "not clipped") << "}"; } // An observer that receives power measurements. Each power measurement should @@ -99,17 +96,11 @@ last_power_measurement_(AudioPowerMonitor::zero_power()), last_clipped_(false) {} - int measurement_count() const { - return measurement_count_; - } + int measurement_count() const { return measurement_count_; } - float last_power_measurement() const { - return last_power_measurement_; - } + float last_power_measurement() const { return last_power_measurement_; } - bool last_clipped() const { - return last_clipped_; - } + bool last_clipped() const { return last_clipped_; } void OnPowerMeasured(float cur_power_measurement, bool clipped) { if (measurement_count_ == 0) { @@ -159,8 +150,9 @@ base::TimeDelta::FromMilliseconds(kTimeConstantMillis)) { } - void FeedAndCheckExpectedPowerIsMeasured( - const AudioBus& bus, float power, bool clipped) { + void FeedAndCheckExpectedPowerIsMeasured(const AudioBus& bus, + float power, + bool clipped) { // Feed the AudioPowerMonitor, read measurements from it, and record them in // MeasurementObserver. static const int kNumFeedIters = 100; @@ -195,83 +187,70 @@ // Send a "zero power" audio signal, then this scenario's audio signal, then // the "zero power" audio signal again; testing that the power monitor // measurements match expected values. - FeedAndCheckExpectedPowerIsMeasured( - *zeroed_bus, AudioPowerMonitor::zero_power(), false); + FeedAndCheckExpectedPowerIsMeasured(*zeroed_bus, + AudioPowerMonitor::zero_power(), false); FeedAndCheckExpectedPowerIsMeasured( scenario.data(), scenario.expected_power(), scenario.expected_clipped()); - FeedAndCheckExpectedPowerIsMeasured( - *zeroed_bus, AudioPowerMonitor::zero_power(), false); + FeedAndCheckExpectedPowerIsMeasured(*zeroed_bus, + AudioPowerMonitor::zero_power(), false); } -static const float kMonoSilentNoise[] = { - 0.01f, -0.01f -}; +static const float kMonoSilentNoise[] = {0.01f, -0.01f}; -static const float kMonoMaxAmplitude[] = { - 1.0f -}; +static const float kMonoMaxAmplitude[] = {1.0f}; -static const float kMonoMaxAmplitude2[] = { - -1.0f, 1.0f -}; +static const float kMonoMaxAmplitude2[] = {-1.0f, 1.0f}; -static const float kMonoHalfMaxAmplitude[] = { - 0.5f, -0.5f, 0.5f, -0.5f -}; +static const float kMonoHalfMaxAmplitude[] = {0.5f, -0.5f, 0.5f, -0.5f}; -static const float kMonoAmplitudeClipped[] = { - 2.0f, -2.0f -}; +static const float kMonoAmplitudeClipped[] = {2.0f, -2.0f}; -static const float kMonoMaxAmplitudeWithClip[] = { - 2.0f, 0.0, 0.0f, 0.0f -}; +static const float kMonoMaxAmplitudeWithClip[] = {2.0f, 0.0, 0.0f, 0.0f}; -static const float kMonoMaxAmplitudeWithClip2[] = { - 4.0f, 0.0, 0.0f, 0.0f -}; +static const float kMonoMaxAmplitudeWithClip2[] = {4.0f, 0.0, 0.0f, 0.0f}; static const float kStereoSilentNoise[] = { - // left channel - 0.005f, -0.005f, - // right channel - 0.005f, -0.005f -}; + // left channel + 0.005f, -0.005f, + // right channel + 0.005f, -0.005f}; static const float kStereoMaxAmplitude[] = { - // left channel - 1.0f, -1.0f, - // right channel - -1.0f, 1.0f -}; + // left channel + 1.0f, -1.0f, + // right channel + -1.0f, 1.0f}; static const float kRightChannelMaxAmplitude[] = { - // left channel - 0.0f, 0.0f, 0.0f, 0.0f, - // right channel - -1.0f, 1.0f, -1.0f, 1.0f -}; + // left channel + 0.0f, 0.0f, 0.0f, 0.0f, + // right channel + -1.0f, 1.0f, -1.0f, 1.0f}; static const float kLeftChannelHalfMaxAmplitude[] = { - // left channel - 0.5f, -0.5f, 0.5f, -0.5f, - // right channel - 0.0f, 0.0f, 0.0f, 0.0f, + // left channel + 0.5f, + -0.5f, + 0.5f, + -0.5f, + // right channel + 0.0f, + 0.0f, + 0.0f, + 0.0f, }; static const float kStereoMixed[] = { - // left channel - 0.5f, -0.5f, 0.5f, -0.5f, - // right channel - -1.0f, 1.0f, -1.0f, 1.0f -}; + // left channel + 0.5f, -0.5f, 0.5f, -0.5f, + // right channel + -1.0f, 1.0f, -1.0f, 1.0f}; static const float kStereoMixed2[] = { - // left channel - 1.0f, -1.0f, 0.75f, -0.75f, 0.5f, -0.5f, 0.25f, -0.25f, - // right channel - 0.25f, -0.25f, 0.5f, -0.5f, 0.75f, -0.75f, 1.0f, -1.0f -}; + // left channel + 1.0f, -1.0f, 0.75f, -0.75f, 0.5f, -0.5f, 0.25f, -0.25f, + // right channel + 0.25f, -0.25f, 0.5f, -0.5f, 0.75f, -0.75f, 1.0f, -1.0f}; INSTANTIATE_TEST_SUITE_P( Scenarios,
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index 3df95d9a..8eeaa0a 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -620,13 +620,17 @@ protected_video_type = gfx::ProtectedVideoType::kSoftwareProtected; } + const gfx::Vector2dF offset( + static_cast<float>(visible_rect.x()) / coded_size.width(), + static_cast<float>(visible_rect.y()) / coded_size.height()); + auto* texture_quad = render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); - texture_quad->SetNew(shared_quad_state, quad_rect, visible_quad_rect, - needs_blending, frame_resources_[0].id, - premultiplied_alpha, uv_top_left, uv_bottom_right, - SK_ColorTRANSPARENT, opacity, flipped, - nearest_neighbor, false, protected_video_type); + texture_quad->SetNew( + shared_quad_state, quad_rect, visible_quad_rect, needs_blending, + frame_resources_[0].id, premultiplied_alpha, uv_top_left + offset, + uv_bottom_right + offset, SK_ColorTRANSPARENT, opacity, flipped, + nearest_neighbor, false, protected_video_type); texture_quad->set_resource_size_in_pixels(coded_size); for (viz::ResourceId resource_id : texture_quad->resources) { resource_provider_->ValidateResource(resource_id);
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 5c2bc6ef..202206cd 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -362,13 +362,13 @@ true) // If true, QuicSession\'s various write methods will set transmission type. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_write_with_transmission, false) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_write_with_transmission, true) // If true, fix a bug in QUIC BBR where bandwidth estimate becomes 0 after a // loss only event. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_fix_zero_bw_on_loss_only_event, - false) + true) // If true, trigger QUIC_BUG in two ShouldCreateIncomingStream() overrides when // called with locally initiated stream ID.
diff --git a/services/audio/output_controller.cc b/services/audio/output_controller.cc index 9307774..862f90b 100644 --- a/services/audio/output_controller.cc +++ b/services/audio/output_controller.cc
@@ -31,7 +31,8 @@ namespace { // Time in seconds between two successive measurements of audio power levels. -constexpr int kPowerMonitorLogIntervalSeconds = 15; +constexpr base::TimeDelta kPowerMonitorLogInterval = + base::TimeDelta::FromSeconds(15); // Used to log the result of rendering startup. // Elements in this enum should not be deleted or rearranged; the only @@ -485,8 +486,7 @@ power_monitor_.Scan(*dest, frames); const auto now = base::TimeTicks::Now(); - if ((now - last_audio_level_log_time_).InSeconds() > - kPowerMonitorLogIntervalSeconds) { + if ((now - last_audio_level_log_time_) > kPowerMonitorLogInterval) { LogAudioPowerLevel(__func__); last_audio_level_log_time_ = now; }
diff --git a/services/audio/output_controller.h b/services/audio/output_controller.h index 8550d37f..4cc74781 100644 --- a/services/audio/output_controller.h +++ b/services/audio/output_controller.h
@@ -25,8 +25,8 @@ #include "build/build_config.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" -#include "media/audio/audio_power_monitor.h" #include "media/audio/audio_source_diverter.h" +#include "media/base/audio_power_monitor.h" #include "services/audio/loopback_group_member.h" #include "services/audio/stream_monitor_coordinator.h"
diff --git a/services/network/origin_policy/origin_policy_parsed_header.cc b/services/network/origin_policy/origin_policy_parsed_header.cc index 93d37a8..90c99b07 100644 --- a/services/network/origin_policy/origin_policy_parsed_header.cc +++ b/services/network/origin_policy/origin_policy_parsed_header.cc
@@ -32,19 +32,17 @@ return base::nullopt; } - // TODO(domenic): when https://crbug.com/1061139 gets fixed we can - // make this a const reference. - sh::Dictionary& parsed_header = *parsed_header_opt; + const sh::Dictionary& parsed_header = *parsed_header_opt; std::vector<OriginPolicyAllowedValue> allowed; if (parsed_header.contains("allowed")) { - if (!parsed_header["allowed"].member_is_inner_list) { + if (!parsed_header.at("allowed").member_is_inner_list) { return base::nullopt; } const std::vector<sh::ParameterizedItem>& raw_allowed_list = - parsed_header["allowed"].member; + parsed_header.at("allowed").member; for (const auto& parameterized_item : raw_allowed_list) { base::Optional<OriginPolicyAllowedValue> result; @@ -74,11 +72,11 @@ base::Optional<OriginPolicyPreferredValue> preferred; if (parsed_header.contains("preferred")) { - if (parsed_header["preferred"].member_is_inner_list) { + if (parsed_header.at("preferred").member_is_inner_list) { return base::nullopt; } - const sh::Item& item = parsed_header["preferred"].member[0].item; + const sh::Item& item = parsed_header.at("preferred").member[0].item; if (item.is_string()) { const std::string& string = item.GetString(); if (string.empty()) {
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json index 33e99d3..f70e2ee 100644 --- a/testing/buildbot/chromium.ci.json +++ b/testing/buildbot/chromium.ci.json
@@ -226837,11 +226837,17 @@ ] }, "linux-upload-perfetto": { - "scripts": [ + "gtest_tests": [ { - "name": "upload_perfetto_script", - "script": "//tools/perf/core/perfetto_binary_roller/upload_trace_processor", - "swarming": {} + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "upload_trace_processor", + "test_target": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor" } ] }, @@ -231836,11 +231842,17 @@ ] }, "mac-upload-perfetto": { - "scripts": [ + "gtest_tests": [ { - "name": "upload_perfetto_script", - "script": "//tools/perf/core/perfetto_binary_roller/upload_trace_processor", - "swarming": {} + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "upload_trace_processor", + "test_target": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor" } ] }, @@ -235021,11 +235033,17 @@ ] }, "win-upload-perfetto": { - "scripts": [ + "gtest_tests": [ { - "name": "upload_perfetto_script", - "script": "//tools/perf/core/perfetto_binary_roller/upload_trace_processor", - "swarming": {} + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "upload_trace_processor", + "test_target": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor" } ] },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index c085ee02..7007faf 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -38582,11 +38582,17 @@ ] }, "linux-upload-perfetto": { - "scripts": [ + "gtest_tests": [ { - "name": "upload_perfetto_script", - "script": "//tools/perf/core/perfetto_binary_roller/upload_trace_processor", - "swarming": {} + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "upload_trace_processor", + "test_target": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor" } ] }, @@ -41942,11 +41948,17 @@ ] }, "mac-upload-perfetto": { - "scripts": [ + "gtest_tests": [ { - "name": "upload_perfetto_script", - "script": "//tools/perf/core/perfetto_binary_roller/upload_trace_processor", - "swarming": {} + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "upload_trace_processor", + "test_target": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor" } ] }, @@ -42182,11 +42194,17 @@ ] }, "win-upload-perfetto": { - "scripts": [ + "gtest_tests": [ { - "name": "upload_perfetto_script", - "script": "//tools/perf/core/perfetto_binary_roller/upload_trace_processor", - "swarming": {} + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "upload_trace_processor", + "test_target": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor" } ] },
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index f0deb0ad..8f415f44 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1724,6 +1724,10 @@ "label": "//chrome/updater:updater_tests", "type": "console_test_launcher", }, + "upload_trace_processor": { + "label": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor", + "type": "raw", + }, "url_unittests": { "label": "//url:url_unittests", "type": "console_test_launcher",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index f148b79..1914923 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3593,10 +3593,7 @@ }, 'upload_perfetto': { - 'upload_perfetto_script': { - 'script': - '//tools/perf/core/perfetto_binary_roller/upload_trace_processor', - }, + 'upload_trace_processor': {}, }, 'vr_platform_specific_chromium_gtests': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index d7414315d..7267d5ed 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2088,8 +2088,9 @@ }, 'linux-upload-perfetto': { 'test_suites': { - 'scripts': 'upload_perfetto', + 'gtest_tests': 'upload_perfetto', }, + 'use_swarming': False, }, 'linux-wpt-fyi-rel': { 'mixins': [ @@ -2133,8 +2134,9 @@ }, 'mac-upload-perfetto': { 'test_suites': { - 'scripts': 'upload_perfetto', + 'gtest_tests': 'upload_perfetto', }, + 'use_swarming': False, }, 'mac10.10-blink-rel-dummy': { 'test_suites': { @@ -2244,8 +2246,9 @@ }, 'win-upload-perfetto': { 'test_suites': { - 'scripts': 'upload_perfetto', + 'gtest_tests': 'upload_perfetto', }, + 'use_swarming': False, }, 'win10-blink-rel-dummy': { 'swarming': {
diff --git a/third_party/blink/common/feature_policy/feature_policy.cc b/third_party/blink/common/feature_policy/feature_policy.cc index d3b99496..94bf3a9 100644 --- a/third_party/blink/common/feature_policy/feature_policy.cc +++ b/third_party/blink/common/feature_policy/feature_policy.cc
@@ -595,7 +595,7 @@ {mojom::FeaturePolicyFeature::kVerticalScroll, FeatureDefaultValue(FeaturePolicy::FeatureDefault::EnableForAll, mojom::PolicyValueType::kBool)}, - {mojom::FeaturePolicyFeature::kWakeLock, + {mojom::FeaturePolicyFeature::kScreenWakeLock, FeatureDefaultValue(FeaturePolicy::FeatureDefault::EnableForSelf, mojom::PolicyValueType::kBool)}, {mojom::FeaturePolicyFeature::kWebVr,
diff --git a/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom b/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom index fd03c34e..d231671 100644 --- a/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom +++ b/third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom
@@ -64,8 +64,8 @@ kLazyLoad = 29, // Restricts the usage of layout-causing animations in a document. kLayoutAnimations = 30, - // Controls access to WakeLock - kWakeLock = 31, + // Controls access to Screen Wake Lock + kScreenWakeLock = 31, // These are the defined sandbox features implemented as policy-controlled // features.
diff --git a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h index 6da9a04..0d76a982 100644 --- a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h +++ b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
@@ -277,6 +277,8 @@ // Callback used to fulfill video.requestAnimationFrame() requests. void OnNewFramePresentedCallback(); + void SendLogMessage(const WTF::String& message) const; + std::unique_ptr<MediaStreamInternalFrameWrapper> internal_frame_; WebMediaPlayer::NetworkState network_state_;
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc index 81457a2..c7eb05b 100644 --- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -176,7 +176,9 @@ if (evaluate_csp_for_eval) { ContentSecurityPolicy* csp = GetFrame()->GetDocument()->GetContentSecurityPolicyForWorld(); - context->AllowCodeGenerationFromStrings(!csp->ShouldCheckEval()); + // Configure V8 to check Blink for every 'eval' attempts. + // See CodeGenerationCheckCallbackInMainThread. + context->AllowCodeGenerationFromStrings(false); context->SetErrorMessageForCodeGenerationFromStrings( V8String(GetIsolate(), csp->EvalDisabledErrorMessage())); }
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index 696a6170..e514c85 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -423,9 +423,29 @@ return {true, V8String(context->GetIsolate(), stringified_source)}; } +namespace { + +// Check whether a given |context| have some CSP or TrustedType policies to be +// checked before evaluating a string. +bool ShouldCheckEval(v8::Local<v8::Context> v8_context) { + ExecutionContext* context = ToExecutionContext(v8_context); + if (!context) + return false; + + ContentSecurityPolicy* policy = context->GetContentSecurityPolicyForWorld(); + if (!policy) + return false; + + return policy->ShouldCheckEval(); +} +} // namespace + static v8::ModifyCodeGenerationFromStringsResult CodeGenerationCheckCallbackInMainThread(v8::Local<v8::Context> context, v8::Local<v8::Value> source) { + if (!ShouldCheckEval(context)) + return {/* allowed */ true, /* modified source */ {}}; + // With Trusted Types, we always run the TT check first because of reporting, // and because a default policy might want to stringify or modify the original // source. When TT enforcement is disabled, codegen is always allowed, and we
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py b/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py index dbcbc660..cda6ef7 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/blink_v8_bridge.py
@@ -166,9 +166,19 @@ if (real_type.is_sequence or real_type.is_frozen_array or real_type.is_variadic): - element_type = blink_type_info(real_type.element_type) + element_type = real_type.element_type + element_type_info = blink_type_info(real_type.element_type) + if element_type.type_definition_object is not None: + # In order to support recursive IDL data structures, we have to + # avoid recursive C++ header inclusions and utilize C++ forward + # declarations. Since |VectorOf| requires complete type + # definition, |HeapVector<Member<T>>| is preferred as it + # requires only forward declaration. + vector_fmt = "HeapVector<Member<{}>>" + else: + vector_fmt = "VectorOf<{}>" return TypeInfo( - "VectorOf<{}>".format(element_type.typename), + vector_fmt.format(element_type_info.typename), ref_fmt="{}&", const_ref_fmt="const {}&")
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py index af5a7b28..2e29538 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
@@ -316,7 +316,7 @@ for node in outers: if node.own_template_vars is None: continue - for name, value in node.own_template_vars.iteritems(): + for name, value in node.own_template_vars.items(): assert name not in bindings, ( "Duplicated template variable binding: {}".format(name)) bindings[name] = value @@ -341,7 +341,7 @@ def add_template_vars(self, template_vars): assert isinstance(template_vars, dict) - for name, value in template_vars.iteritems(): + for name, value in template_vars.items(): self.add_template_var(name, value) @property @@ -357,7 +357,7 @@ def set_base_template_vars(self, template_vars): assert isinstance(template_vars, dict) - for name, value in template_vars.iteritems(): + for name, value in template_vars.items(): assert isinstance(name, str) assert not isinstance(value, CodeNode) assert self._base_template_vars is None @@ -507,7 +507,7 @@ gensym = CodeNode.gensym() gensym_args.append("${{{}}}".format(gensym)) template_vars[gensym] = arg - for key, value in kwargs.iteritems(): + for key, value in kwargs.items(): assert isinstance(key, (int, long, str)) assert isinstance(value, (CodeNode, int, long, str)) gensym = CodeNode.gensym() @@ -732,7 +732,7 @@ scope = scope_chain[0] scope_to_likeliness[scope] = max( likeliness, scope_to_likeliness.get(scope, likeliness)) - for likeliness in scope_to_likeliness.itervalues(): + for likeliness in scope_to_likeliness.values(): counts[DIRECT_CHILD_SCOPES] += 1 counts[likeliness] += 1 return counts
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py index 6ffc5e5..0350727a 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/codegen_context.py
@@ -26,6 +26,23 @@ NON_MAIN_WORLDS = "other" ALL_WORLDS = "all" + # "v8_callback_type" attribute values + # + # void (*)(const v8::FunctionCallbackInfo<v8::Value>&) + V8_FUNCTION_CALLBACK = "v8::FunctionCallback" + # void (*)(v8::Local<v8::Name>, + # const v8::PropertyCallbackInfo<v8::Value>&) + V8_ACCESSOR_NAME_GETTER_CALLBACK = "v8::AccessorNameGetterCallback" + # void (*)(v8::Local<v8::Name>, v8::Local<v8::Value>, + # const v8::PropertyCallbackInfo<void>&) + V8_ACCESSOR_NAME_SETTER_CALLBACK = "v8::AccessorNameSetterCallback" + # void (*)(v8::Local<v8::Name>, v8::Local<v8::Value>, + # const v8::PropertyCallbackInfo<v8::Value>&) + V8_GENERIC_NAMED_PROPERTY_SETTER_CALLBACK = ( + "v8::GenericNamedPropertySetterCallback") + # Others + V8_OTHER_CALLBACK = "other callback type" + @classmethod def init(cls): """Initialize the class. Must be called exactly once.""" @@ -70,7 +87,13 @@ "class_name": None, # Main world or all worlds + # Used via [PerWorldBindings] to optimize the code path of the main + # world. "for_world": cls.ALL_WORLDS, + + # Type of V8 callback function which implements IDL attribute, + # IDL operation, etc. + "v8_callback_type": cls.V8_FUNCTION_CALLBACK } # List of computational attribute names @@ -89,7 +112,7 @@ ) # Define public readonly properties of this class. - for attr in cls._context_attrs.iterkeys(): + for attr in cls._context_attrs.keys(): def make_get(): _attr = cls._internal_attr(attr) @@ -108,11 +131,11 @@ def __init__(self, **kwargs): assert CodeGenContext._was_initialized - for arg in kwargs.iterkeys(): + for arg in kwargs.keys(): assert arg in self._context_attrs, "Unknown argument: {}".format( arg) - for attr, default_value in self._context_attrs.iteritems(): + for attr, default_value in self._context_attrs.items(): value = kwargs[attr] if attr in kwargs else default_value assert (default_value is None or type(value) is type(default_value)), ( @@ -124,13 +147,13 @@ Returns a copy of this context applying the updates given as the arguments. """ - for arg in kwargs.iterkeys(): + for arg in kwargs.keys(): assert arg in self._context_attrs, "Unknown argument: {}".format( arg) new_object = copy.copy(self) - for attr, new_value in kwargs.iteritems(): + for attr, new_value in kwargs.items(): old_value = getattr(self, attr) assert old_value is None or type(new_value) is type(old_value), ( "Type mismatch at argument: {}".format(attr)) @@ -147,7 +170,7 @@ """ bindings = {} - for attr in self._context_attrs.iterkeys(): + for attr in self._context_attrs.keys(): value = getattr(self, attr) if value is None: value = NonRenderable(attr)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index 3424b6b..3629f02 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -90,7 +90,9 @@ return name -def callback_function_name(cg_context, overload_index=None): +def callback_function_name(cg_context, + overload_index=None, + for_cross_origin=False): assert isinstance(cg_context, CodeGenContext) def _cxx_name(name): @@ -133,10 +135,12 @@ elif cg_context.stringifier: kind = "Operation" - if overload_index is None: - callback_suffix = "Callback" + if for_cross_origin: + suffix = "CrossOrigin" + elif overload_index is not None: + suffix = "Overload{}".format(overload_index + 1) else: - callback_suffix = "Overload{}".format(overload_index + 1) + suffix = "Callback" if cg_context.for_world == CodeGenContext.MAIN_WORLD: world_suffix = "ForMainWorld" @@ -145,7 +149,7 @@ elif cg_context.for_world == CodeGenContext.ALL_WORLDS: world_suffix = "" - return name_style.func(property_name, kind, callback_suffix, world_suffix) + return name_style.func(property_name, kind, suffix, world_suffix) def constant_name(cg_context): @@ -195,7 +199,7 @@ if cg_context.attribute_set: name = "arg1_value" - v8_value = "${info}[0]" + v8_value = "${v8_property_value}" code_node.register_code_symbol( make_v8_to_blink_value(name, v8_value, cg_context.attribute.idl_type)) @@ -342,6 +346,15 @@ text = _format(pattern, _1=_1) local_vars.append(S("blink_receiver", text)) + # v8_property_value + if cg_context.v8_callback_type == CodeGenContext.V8_FUNCTION_CALLBACK: + # In case of V8_ACCESSOR_NAME_SETTER_CALLBACK, |v8_property_value| is + # defined as an argument. In case of V8_FUNCTION_CALLBACK (of IDL + # attribute set function), |info[0]| is the value to be set. + local_vars.append( + S("v8_property_value", + "v8::Local<v8::Value> ${v8_property_value} = ${info}[0];")) + code_node.register_code_symbols(local_vars) code_node.add_template_vars(template_vars) @@ -663,6 +676,9 @@ T = TextNode F = lambda *args, **kwargs: T(_format(*args, **kwargs)) + if cg_context.v8_callback_type != CodeGenContext.V8_FUNCTION_CALLBACK: + return None + if cg_context.attribute_get: num_of_required_args = 0 elif cg_context.attribute_set: @@ -672,8 +688,8 @@ "TreatNonObjectAsNull" in idl_type.unwrap().extended_attributes or "PutForwards" in cg_context.attribute.extended_attributes or "Replaceable" in cg_context.attribute.extended_attributes): - # ES undefined in ${info}[0] will cause a TypeError anyway, so omit - # the check against the number of arguments. + # ES undefined in ${v8_property_value} will cause a TypeError + # anyway, so omit the check against the number of arguments. return None num_of_required_args = 1 elif cg_context.function_like: @@ -826,7 +842,7 @@ _4 = "" elif cg_context.attribute_set: _1 = "LogSetter" - _4 = ", ${info}[0]" + _4 = ", ${v8_property_value}" elif cg_context.operation_group: _1 = "LogMethod" _4 = ", ${info}" @@ -1218,8 +1234,9 @@ "(${v8_receiver}, ${info}.GetReturnValue().Get());") -def make_runtime_call_timer_scope(cg_context): +def make_runtime_call_timer_scope(cg_context, overriding_name=None): assert isinstance(cg_context, CodeGenContext) + assert _is_none_or_str(overriding_name) target = cg_context.member_like or cg_context.property_ @@ -1230,16 +1247,6 @@ suffix = "_Setter" elif cg_context.exposed_construct: suffix = "_ConstructorGetterCallback" - elif cg_context.indexed_property_getter: - suffix = "_IndexedPropertyGetter" - elif cg_context.indexed_property_setter: - suffix = "_IndexedPropertySetter" - elif cg_context.named_property_getter: - suffix = "_NamedPropertyGetter" - elif cg_context.named_property_setter: - suffix = "_NamedPropertySetter" - elif cg_context.named_property_deleter: - suffix = "_NamedPropertyDeleter" counter = (target and target.extended_attributes.value_of("RuntimeCallStatsCounter")) @@ -1250,8 +1257,8 @@ else: macro_name = "RUNTIME_CALL_TIMER_SCOPE_DISABLED_BY_DEFAULT" counter_name = "\"Blink_{}_{}{}\"".format( - blink_class_name(cg_context.class_like), - target.identifier if target else "", suffix) + blink_class_name(cg_context.class_like), overriding_name + or target.identifier, suffix) return TextNode( _format( @@ -1321,7 +1328,7 @@ T("if (!target.As<v8::Object>()->Set(${current_context}, " "V8AtomicString(${isolate}, " "\"${attribute.extended_attributes.value_of(\"PutForwards\")}\"" - "), ${info}[0]).To(&did_set)) {{\n" + "), ${v8_property_value}).To(&did_set)) {{\n" " return;\n" "}}"), ]) @@ -1337,7 +1344,7 @@ T("bool did_create;"), T("if (!${v8_receiver}->CreateDataProperty(${current_context}, " "V8AtomicString(${isolate}, ${property_name}), " - "${info}[0]).To(&did_create)) {\n" + "${v8_property_value}).To(&did_create)) {\n" " return;\n" "}"), ]) @@ -1411,19 +1418,44 @@ "ToV8(${return_value}, ${creation_context_object}, ${isolate}));") -def _make_empty_callback_def(cg_context, function_name, arg_decls=None): +def _make_empty_callback_def(cg_context, function_name): assert isinstance(cg_context, CodeGenContext) assert isinstance(function_name, str) - if arg_decls is None: + if cg_context.v8_callback_type == CodeGenContext.V8_FUNCTION_CALLBACK: arg_decls = ["const v8::FunctionCallbackInfo<v8::Value>& info"] + arg_names = ["info"] + elif (cg_context.v8_callback_type == CodeGenContext. + V8_ACCESSOR_NAME_GETTER_CALLBACK): + arg_decls = [ + "v8::Local<v8::Name> v8_property_name", + "const v8::PropertyCallbackInfo<v8::Value>& info", + ] + arg_names = ["v8_property_name", "info"] + elif (cg_context.v8_callback_type == CodeGenContext. + V8_ACCESSOR_NAME_SETTER_CALLBACK): + arg_decls = [ + "v8::Local<v8::Name> v8_property_name", + "v8::Local<v8::Value> v8_property_value", + "const v8::PropertyCallbackInfo<void>& info", + ] + arg_names = ["v8_property_name", "v8_property_value", "info"] + elif (cg_context.v8_callback_type == CodeGenContext. + V8_GENERIC_NAMED_PROPERTY_SETTER_CALLBACK): + arg_decls = [ + "v8::Local<v8::Name> v8_property_name", + "v8::Local<v8::Value> v8_property_value", + "const v8::PropertyCallbackInfo<v8::Value>& info", + ] + arg_names = ["v8_property_name", "v8_property_value", "info"] func_def = CxxFuncDefNode( name=function_name, arg_decls=arg_decls, return_type="void") func_def.set_base_template_vars(cg_context.template_bindings()) - body = func_def.body - body.add_template_var("info", "info") + + for arg_name in arg_names: + body.add_template_var(arg_name, arg_name) bind_callback_local_vars(body, cg_context) if cg_context.attribute or cg_context.function_like: @@ -1496,7 +1528,7 @@ if "Setter" in cg_context.property_.extended_attributes.values_of( "Custom"): - text = _format("${class_name}::{}(${info}[0], ${info});", + text = _format("${class_name}::{}(${v8_property_value}, ${info});", custom_function_name(cg_context)) body.append(TextNode(text)) return func_def @@ -1536,13 +1568,7 @@ if not logging_nodes: return None - func_def = _make_empty_callback_def( - cg_context, - function_name, - arg_decls=[ - "v8::Local<v8::Name> property", - "const v8::PropertyCallbackInfo<v8::Value>& info", - ]) + func_def = _make_empty_callback_def(cg_context, function_name) body = func_def.body v8_set_return_value = _format( @@ -1672,13 +1698,7 @@ assert isinstance(cg_context, CodeGenContext) assert isinstance(function_name, str) - func_def = _make_empty_callback_def( - cg_context, - function_name, - arg_decls=[ - "v8::Local<v8::Name> property", - "const v8::PropertyCallbackInfo<v8::Value>& info", - ]) + func_def = _make_empty_callback_def(cg_context, function_name) body = func_def.body v8_set_return_value = _format( @@ -1800,7 +1820,7 @@ bind_return_value(body, cg_context, overriding_args=["${index}"]) body.extend([ - make_runtime_call_timer_scope(cg_context), + make_runtime_call_timer_scope(cg_context, "IndexedPropertyGetter"), EmptyNode(), make_v8_set_return_value(cg_context), ]) @@ -1849,7 +1869,7 @@ argument_index=2)) body.extend([ - make_runtime_call_timer_scope(cg_context), + make_runtime_call_timer_scope(cg_context, "IndexedPropertySetter"), EmptyNode(), make_steps_of_ce_reactions(cg_context), EmptyNode(), @@ -2052,7 +2072,7 @@ body, cg_context, overriding_args=["${blink_property_name}"]) body.extend([ - make_runtime_call_timer_scope(cg_context), + make_runtime_call_timer_scope(cg_context, "NamedPropertyGetter"), EmptyNode(), ]) @@ -2075,7 +2095,7 @@ arg_decls = [ "v8::Local<v8::Name> v8_property_name", - "v8::Local<v8::Value> v8_value", + "v8::Local<v8::Value> v8_property_value", "const v8::PropertyCallbackInfo<v8::Value>& info", ] return_type = "void" @@ -2094,7 +2114,7 @@ func_def.set_base_template_vars(cg_context.template_bindings()) body = func_def.body body.add_template_var("v8_property_name", "v8_property_name") - body.add_template_var("v8_value", "v8_value") + body.add_template_var("v8_property_value", "v8_property_value") body.add_template_var("info", "info") bind_callback_local_vars(body, cg_context) bind_return_value( @@ -2104,19 +2124,19 @@ body.register_code_symbol( make_v8_to_blink_value( "blink_value", - "${v8_value}", + "${v8_property_value}", cg_context.named_property_setter.arguments[1].idl_type, argument_index=2)) body.extend([ - make_runtime_call_timer_scope(cg_context), + make_runtime_call_timer_scope(cg_context, "NamedPropertySetter"), EmptyNode(), ]) if "Custom" in cg_context.named_property_setter.extended_attributes: text = _format( "${class_name}::{}" - "(${blink_property_name}, ${v8_value}, ${info});", + "(${blink_property_name}, ${v8_property_value}, ${info});", custom_function_name(cg_context)) body.append(TextNode(text)) else: @@ -2351,12 +2371,12 @@ TextNode("""\ Vector<String> blink_property_names; ${blink_receiver}->NamedPropertyEnumerator( - blink_property_names, ${exception_state}); + blink_property_names, ${exception_state}); if (${exception_state}.HadException()) return; bindings::V8SetReturnValue( - ${info}, - ToV8(blink_property_names, ${creation_context_object}, ${isolate})); + ${info}, + ToV8(blink_property_names, ${creation_context_object}, ${isolate})); """)) return func_decl, func_def @@ -2379,6 +2399,295 @@ # ---------------------------------------------------------------------------- +# Callback functions of cross origin properties +# ---------------------------------------------------------------------------- + + +def make_cross_origin_access_check_callback(cg_context, function_name): + assert isinstance(cg_context, CodeGenContext) + assert isinstance(function_name, str) + + func_def = CxxFuncDefNode( + name=function_name, + arg_decls=[ + "v8::Local<v8::Context> accessing_context", + "v8::Local<v8::Object> accessed_object", + "v8::Local<v8::Value> unused_data", + ], + return_type="bool") + func_def.set_base_template_vars(cg_context.template_bindings()) + body = func_def.body + body.add_template_var("accessing_context", "accessing_context") + body.add_template_var("accessed_object", "accessed_object") + bind_callback_local_vars(body, cg_context) + + if cg_context.interface.identifier == "Window": + blink_class = "DOMWindow" + else: + blink_class = blink_class_name(cg_context.interface) + body.extend([ + TextNode( + _format( + "{blink_class}* blink_accessed_object = " + "${class_name}::ToWrappableUnsafe(${accessed_object});", + blink_class=blink_class)), + TextNode("return BindingSecurity::ShouldAllowAccessTo(" + "ToLocalDOMWindow(${accessing_context}), " + "blink_accessed_object, " + "BindingSecurity::ErrorReportOption::kDoNotReport);"), + ]) + + return func_def + + +def make_cross_origin_property_getter_callback(cg_context, function_name): + assert isinstance(cg_context, CodeGenContext) + assert isinstance(function_name, str) + + func_def = CxxFuncDefNode( + name=function_name, + arg_decls=[ + "v8::Local<v8::Name> v8_property_name", + "const v8::PropertyCallbackInfo<v8::Value>& info", + ], + return_type="void") + func_def.set_base_template_vars(cg_context.template_bindings()) + body = func_def.body + body.add_template_var("v8_property_name", "v8_property_name") + body.add_template_var("info", "info") + bind_callback_local_vars(body, cg_context) + + string_case_body = [] + string_case_body.append( + TextNode("""\ +for (const auto& attribute : kCrossOriginAttributeTable) { + if (${blink_property_name} != attribute.name) + continue; + if (UNLIKELY(!attribute.get_value)) { + BindingSecurity::FailedAccessCheckFor( + ${info}.GetIsolate(), + ${class_name}::GetWrapperTypeInfo(), + ${info}.This()); + return; + } + return attribute.get_value(${v8_property_name}, ${info}); +} +for (const auto& operation : kCrossOriginOperationTable) { + if (${blink_property_name} != operation.name) + continue; + v8::Local<v8::Function> function; + if (bindings::GetCrossOriginFunction( + ${info}.GetIsolate(), operation.callback, operation.func_length, + ${class_name}::GetWrapperTypeInfo()) + .ToLocal(&function)) { + bindings::V8SetReturnValue(${info}, function); + } + return; +} +% if interface.identifier == "Window": + +// Window object's document-tree child browsing context name property set +// +// TODO(yukishiino): Update the following hard-coded call to an appropriate +// one. +V8Window::NamedPropertyGetterCustom(${blink_property_name}, ${info}); +if (!${info}.GetReturnValue().Get()->IsUndefined()) + return; +% endif""")) + + body.extend([ + make_runtime_call_timer_scope(cg_context, "CrossOriginPropertyGetter"), + EmptyNode(), + CxxLikelyIfNode( + cond="${v8_property_name}->IsString()", body=string_case_body), + EmptyNode(), + TextNode("""\ +// 7.2.3.2 CrossOriginPropertyFallback ( P ) +// https://html.spec.whatwg.org/C/#crossoriginpropertyfallback-(-p-) +if (bindings::IsSupportedInCrossOriginPropertyFallback( + ${info}.GetIsolate(), ${v8_property_name})) { + return ${info}.GetReturnValue().SetUndefined(); +} +BindingSecurity::FailedAccessCheckFor( + ${info}.GetIsolate(), + ${class_name}::GetWrapperTypeInfo(), + ${info}.This());"""), + ]) + + return func_def + + +def make_cross_origin_property_setter_callback(cg_context, function_name): + assert isinstance(cg_context, CodeGenContext) + assert isinstance(function_name, str) + + func_def = CxxFuncDefNode( + name=function_name, + arg_decls=[ + "v8::Local<v8::Name> v8_property_name", + "v8::Local<v8::Value> v8_property_value", + "const v8::PropertyCallbackInfo<v8::Value>& info", + ], + return_type="void") + func_def.set_base_template_vars(cg_context.template_bindings()) + body = func_def.body + body.add_template_var("v8_property_name", "v8_property_name") + body.add_template_var("v8_property_value", "v8_property_value") + body.add_template_var("info", "info") + bind_callback_local_vars(body, cg_context) + + string_case_body = [] + string_case_body.append( + TextNode("""\ +for (const auto& attribute : kCrossOriginAttributeTable) { + if (${blink_property_name} == attribute.name && attribute.set_value) { + return attribute.set_value( + ${v8_property_name}, ${v8_property_value}, ${info}); + } +}""")) + + body.extend([ + make_runtime_call_timer_scope(cg_context, "CrossOriginPropertySetter"), + EmptyNode(), + CxxLikelyIfNode( + cond="${v8_property_name}->IsString()", body=string_case_body), + EmptyNode(), + TextNode("""\ +BindingSecurity::FailedAccessCheckFor( + ${info}.GetIsolate(), + ${class_name}::GetWrapperTypeInfo(), + ${info}.This());"""), + ]) + + return func_def + + +def make_cross_origin_property_descriptor_callback(cg_context, function_name): + assert isinstance(cg_context, CodeGenContext) + assert isinstance(function_name, str) + + func_def = CxxFuncDefNode( + name=function_name, + arg_decls=[ + "v8::Local<v8::Name> v8_property_name", + "const v8::PropertyCallbackInfo<v8::Value>& info", + ], + return_type="void") + func_def.set_base_template_vars(cg_context.template_bindings()) + body = func_def.body + body.add_template_var("v8_property_name", "v8_property_name") + body.add_template_var("info", "info") + bind_callback_local_vars(body, cg_context) + + string_case_body = [] + string_case_body.append( + TextNode("""\ +// 7.2.3.4 CrossOriginGetOwnPropertyHelper ( O, P ) +// https://html.spec.whatwg.org/C/#crossorigingetownpropertyhelper-(-o,-p-) +for (const auto& attribute : kCrossOriginAttributeTable) { + if (${blink_property_name} != attribute.name) + continue; + v8::Local<v8::Value> get; + v8::Local<v8::Value> set; + if (!bindings::GetCrossOriginFunctionOrUndefined( + ${info}.GetIsolate(), attribute.get_callback, 0, + ${class_name}::GetWrapperTypeInfo()) + .ToLocal(&get) || + !bindings::GetCrossOriginFunctionOrUndefined( + ${info}.GetIsolate(), attribute.set_callback, 1, + ${class_name}::GetWrapperTypeInfo()) + .ToLocal(&set)) { + return; + } + v8::PropertyDescriptor desc(get, set); + desc.set_enumerable(false); + desc.set_configurable(true); + return; +} +for (const auto& operation : kCrossOriginOperationTable) { + if (${blink_property_name} != operation.name) + continue; + v8::Local<v8::Function> function; + if (!bindings::GetCrossOriginFunction( + ${info}.GetIsolate(), operation.callback, operation.func_length, + ${class_name}::GetWrapperTypeInfo()) + .ToLocal(&function)) { + return; + } + v8::PropertyDescriptor desc(function, /*writable=*/false); + desc.set_enumerable(false); + desc.set_configurable(true); + bindings::V8SetReturnValue(${info}, desc); + return; +} +% if interface.identifier == "Window": + +// Window object's document-tree child browsing context name property set +// +// TODO(yukishiino): Update the following hard-coded call to an appropriate +// one. +V8Window::NamedPropertyGetterCustom(${blink_property_name}, ${info}); +if (!${info}.GetReturnValue().Get()->IsUndefined()) { + v8::PropertyDescriptor desc(${info}.GetReturnValue().Get(), + /*writable=*/false); + desc.set_enumerable(false); + desc.set_configurable(true); + bindings::V8SetReturnValue(${info}, desc); + return; +} +% endif""")) + + body.extend([ + CxxLikelyIfNode( + cond="${v8_property_name}->IsString()", body=string_case_body), + EmptyNode(), + TextNode("""\ +// 7.2.3.2 CrossOriginPropertyFallback ( P ) +// https://html.spec.whatwg.org/C/#crossoriginpropertyfallback-(-p-) +if (bindings::IsSupportedInCrossOriginPropertyFallback( + ${info}.GetIsolate(), ${v8_property_name})) { + v8::PropertyDescriptor desc(v8::Undefined(${info}.GetIsolate()), + /*writable=*/false); + desc.set_enumerable(false); + desc.set_configurable(true); + bindings::V8SetReturnValue(${info}, desc); + return; +} +BindingSecurity::FailedAccessCheckFor( + ${info}.GetIsolate(), + ${class_name}::GetWrapperTypeInfo(), + ${info}.This());"""), + ]) + + return func_def + + +def make_cross_origin_property_enumerator_callback(cg_context, function_name): + assert isinstance(cg_context, CodeGenContext) + assert isinstance(function_name, str) + + func_def = CxxFuncDefNode( + name=function_name, + arg_decls=["const v8::PropertyCallbackInfo<v8::Array>& info"], + return_type="void") + func_def.set_base_template_vars(cg_context.template_bindings()) + body = func_def.body + body.add_template_var("info", "info") + bind_callback_local_vars(body, cg_context) + + body.append( + TextNode("""\ +bindings::V8SetReturnValue( + ${info}, + bindings::EnumerateCrossOriginProperties( + ${isolate}, + kCrossOriginAttributeTable, + kCrossOriginOperationTable));""")) + + return func_def + + +# ---------------------------------------------------------------------------- # Installer functions # ---------------------------------------------------------------------------- @@ -2868,7 +3177,10 @@ def process_constant(constant, is_context_dependent, exposure_conditional, world): - cgc = cg_context.make_copy(constant=constant, for_world=world) + cgc = cg_context.make_copy( + constant=constant, + for_world=world, + v8_callback_type=CodeGenContext.V8_ACCESSOR_NAME_GETTER_CALLBACK) const_callback_name = callback_function_name(cgc) const_callback_node = make_constant_callback_def( cgc, const_callback_name) @@ -2917,7 +3229,9 @@ def process_exposed_construct(exposed_construct, is_context_dependent, exposure_conditional, world): cgc = cg_context.make_copy( - exposed_construct=exposed_construct, for_world=world) + exposed_construct=exposed_construct, + for_world=world, + v8_callback_type=CodeGenContext.V8_ACCESSOR_NAME_GETTER_CALLBACK) prop_callback_name = callback_function_name(cgc) prop_callback_node = make_exposed_construct_callback_def( cgc, prop_callback_name) @@ -2988,11 +3302,11 @@ return callback_def_nodes -def make_install_interface_template(cg_context, function_name, class_name, - trampoline_var_name, constructor_entries, - indexed_and_named_property_install_nodes, - install_unconditional_func_name, - install_context_independent_func_name): +def make_install_interface_template( + cg_context, function_name, class_name, trampoline_var_name, + constructor_entries, indexed_and_named_property_install_nodes, + cross_origin_property_install_nodes, install_unconditional_func_name, + install_context_independent_func_name): """ Returns: A triplet of CodeNode of: @@ -3009,6 +3323,8 @@ assert all( isinstance(entry, _PropEntryConstructorGroup) for entry in constructor_entries) + assert isinstance(indexed_and_named_property_install_nodes, SequenceNode) + assert isinstance(cross_origin_property_install_nodes, SequenceNode) assert _is_none_or_str(install_unconditional_func_name) assert _is_none_or_str(install_context_independent_func_name) @@ -3084,6 +3400,37 @@ assert False body.append(EmptyNode()) + if cross_origin_property_install_nodes: + body.extend([ + cross_origin_property_install_nodes, + EmptyNode(), + ]) + + if cg_context.class_like.identifier == "Location": + body.append( + T("""\ +// https://html.spec.whatwg.org/C/#the-location-interface +// To create a Location object, run these steps: +// step 3. Let valueOf be location's relevant +// Realm.[[Intrinsics]].[[%ObjProto_valueOf%]]. +// step 3. Perform ! location.[[DefineOwnProperty]]("valueOf", +// { [[Value]]: valueOf, [[Writable]]: false, [[Enumerable]]: false, +// [[Configurable]]: false }). +${instance_template}->SetIntrinsicDataProperty( + V8AtomicString(${isolate}, "valueOf"), + v8::kObjProto_valueOf, + static_cast<v8::PropertyAttribute>( + int(v8::ReadOnly) | int(v8::DontEnum) | int(v8::DontDelete))); +// step 4. Perform ! location.[[DefineOwnProperty]](@@toPrimitive, +// { [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false, +// [[Configurable]]: false }). +${instance_template}->Set( + v8::Symbol::GetToPrimitive(${isolate}), + v8::Undefined(${isolate}), + static_cast<v8::PropertyAttribute>( + int(v8::ReadOnly) | int(v8::DontEnum) | int(v8::DontDelete))); +""")) + if indexed_and_named_property_install_nodes: body.extend([ indexed_and_named_property_install_nodes, @@ -3265,7 +3612,7 @@ TextNode(installer_call_text), ])) body.append(EmptyNode()) - for conditional, entries in conditional_to_entries.iteritems(): + for conditional, entries in conditional_to_entries.items(): body.append( CxxUnlikelyIfNode( cond=conditional, @@ -3361,7 +3708,7 @@ assert isinstance(cg_context, CodeGenContext) func_decls = ListNode() - func_defs = SequenceNode() + func_defs = ListNode() install_nodes = SequenceNode() interface = cg_context.interface @@ -3379,21 +3726,20 @@ key = lambda interface: len(interface.inclusive_inherited_interfaces) return sorted(filter(None, interfaces), key=key)[-1] + cg_context = cg_context.make_copy( + v8_callback_type=CodeGenContext.V8_OTHER_CALLBACK) + if props.own_indexed_getter or props.own_indexed_setter: add_callback(*make_indexed_property_getter_callback( cg_context.make_copy(indexed_property_getter=props.indexed_getter), "IndexedPropertyGetterCallback")) - add_callback(*make_indexed_property_setter_callback( cg_context.make_copy(indexed_property_setter=props.indexed_setter), "IndexedPropertySetterCallback")) - add_callback(*make_indexed_property_definer_callback( cg_context, "IndexedPropertyDefinerCallback")) - add_callback(*make_indexed_property_descriptor_callback( cg_context, "IndexedPropertyDescriptorCallback")) - add_callback(*make_indexed_property_enumerator_callback( cg_context, "IndexedPropertyEnumeratorCallback")) @@ -3413,19 +3759,19 @@ pattern = """\ // Indexed properties ${instance_template}->SetHandler( - v8::IndexedPropertyHandlerConfiguration( - {impl_bridge}::IndexedPropertyGetterCallback, + v8::IndexedPropertyHandlerConfiguration( + {impl_bridge}::IndexedPropertyGetterCallback, % if interface.indexed_and_named_properties.indexed_setter: - {impl_bridge}::IndexedPropertySetterCallback, + {impl_bridge}::IndexedPropertySetterCallback, % else: - nullptr, // setter + nullptr, // setter % endif - {impl_bridge}::IndexedPropertyDescriptorCallback, - nullptr, // deleter - {impl_bridge}::IndexedPropertyEnumeratorCallback, - {impl_bridge}::IndexedPropertyDefinerCallback, - v8::Local<v8::Value>(), - {property_handler_flags}));""" + {impl_bridge}::IndexedPropertyDescriptorCallback, + nullptr, // deleter + {impl_bridge}::IndexedPropertyEnumeratorCallback, + {impl_bridge}::IndexedPropertyDefinerCallback, + v8::Local<v8::Value>(), + {property_handler_flags}));""" install_nodes.append( TextNode( _format( @@ -3438,21 +3784,16 @@ add_callback(*make_named_property_getter_callback( cg_context.make_copy(named_property_getter=props.named_getter), "NamedPropertyGetterCallback")) - add_callback(*make_named_property_setter_callback( cg_context.make_copy(named_property_setter=props.named_setter), "NamedPropertySetterCallback")) - add_callback(*make_named_property_deleter_callback( cg_context.make_copy(named_property_deleter=props.named_deleter), "NamedPropertyDeleterCallback")) - add_callback(*make_named_property_definer_callback( cg_context, "NamedPropertyDefinerCallback")) - add_callback(*make_named_property_descriptor_callback( cg_context, "NamedPropertyDescriptorCallback")) - add_callback(*make_named_property_enumerator_callback( cg_context, "NamedPropertyEnumeratorCallback")) @@ -3475,27 +3816,27 @@ pattern = """\ // Named properties ${instance_template}->SetHandler( - v8::NamedPropertyHandlerConfiguration( - {impl_bridge}::NamedPropertyGetterCallback, + v8::NamedPropertyHandlerConfiguration( + {impl_bridge}::NamedPropertyGetterCallback, % if interface.indexed_and_named_properties.named_setter: - {impl_bridge}::NamedPropertySetterCallback, + {impl_bridge}::NamedPropertySetterCallback, % else: - nullptr, // setter + nullptr, // setter % endif - {impl_bridge}::NamedPropertyDescriptorCallback, + {impl_bridge}::NamedPropertyDescriptorCallback, % if interface.indexed_and_named_properties.named_deleter: - {impl_bridge}::NamedPropertyDeleterCallback, + {impl_bridge}::NamedPropertyDeleterCallback, % else: - nullptr, // deleter + nullptr, // deleter % endif % if interface.indexed_and_named_properties.is_named_property_enumerable: - {impl_bridge}::NamedPropertyEnumeratorCallback, + {impl_bridge}::NamedPropertyEnumeratorCallback, % else: - nullptr, // enumerator + nullptr, // enumerator % endif - {impl_bridge}::NamedPropertyDefinerCallback, - v8::Local<v8::Value>(), - {property_handler_flags}));""" + {impl_bridge}::NamedPropertyDefinerCallback, + v8::Local<v8::Value>(), + {property_handler_flags}));""" install_nodes.append( TextNode( _format( @@ -3506,6 +3847,157 @@ return func_decls, func_defs, install_nodes +def make_cross_origin_property_callbacks_and_install_nodes( + cg_context, attribute_entries, operation_entries): + assert isinstance(cg_context, CodeGenContext) + + callback_defs = [] + install_nodes = SequenceNode() + + CROSS_ORIGIN_INTERFACES = ("Window", "Location") + if cg_context.interface.identifier not in CROSS_ORIGIN_INTERFACES: + return callback_defs, install_nodes + + entry_nodes = [] + for entry in attribute_entries: + attribute = entry.property_ + if "CrossOrigin" not in attribute.extended_attributes: + continue + assert entry.world == CodeGenContext.ALL_WORLDS + values = attribute.extended_attributes.values_of("CrossOrigin") + get_func = "nullptr" + set_func = "nullptr" + get_value = "nullptr" + set_value = "nullptr" + if not values or "Getter" in values: + get_func = entry.attr_get_callback_name + cgc = cg_context.make_copy( + attribute=attribute, + attribute_get=True, + v8_callback_type=( + CodeGenContext.V8_ACCESSOR_NAME_GETTER_CALLBACK)) + get_value = callback_function_name(cgc, for_cross_origin=True) + func_def = make_attribute_get_callback_def(cgc, get_value) + callback_defs.extend([func_def, EmptyNode()]) + if (not values or "Setter" in values) and entry.attr_set_callback_name: + set_func = entry.attr_set_callback_name + cgc = cg_context.make_copy( + attribute=attribute, + attribute_set=True, + v8_callback_type=( + CodeGenContext.V8_GENERIC_NAMED_PROPERTY_SETTER_CALLBACK)) + set_value = callback_function_name(cgc, for_cross_origin=True) + func_def = make_attribute_set_callback_def(cgc, set_value) + callback_defs.extend([func_def, EmptyNode()]) + pattern = ("{{\"{property_name}\", " + "{get_func}, {set_func}, {get_value}, {set_value}}},") + entry_nodes.append( + TextNode( + _format( + pattern, + property_name=attribute.identifier, + get_func=get_func, + set_func=set_func, + get_value=get_value, + set_value=set_value))) + callback_defs.append( + ListNode([ + TextNode("constexpr bindings::CrossOriginAttributeTableEntry " + "kCrossOriginAttributeTable[] = {"), + ListNode(entry_nodes), + TextNode("};"), + EmptyNode(), + ])) + + entry_nodes = [] + for entry in operation_entries: + operation_group = entry.property_ + if "CrossOrigin" not in operation_group.extended_attributes: + continue + assert entry.world == CodeGenContext.ALL_WORLDS + entry_nodes.append( + TextNode( + _format( + "{{\"{property_name}\", {op_callback}, {op_func_length}}},", + property_name=operation_group.identifier, + op_callback=entry.op_callback_name, + op_func_length=entry.op_func_length))) + callback_defs.append( + ListNode([ + TextNode("constexpr bindings::CrossOriginOperationTableEntry " + "kCrossOriginOperationTable[] = {"), + ListNode(entry_nodes), + TextNode("};"), + EmptyNode(), + ])) + + cg_context = cg_context.make_copy( + v8_callback_type=CodeGenContext.V8_OTHER_CALLBACK) + + callback_defs.extend([ + make_cross_origin_access_check_callback( + cg_context, "CrossOriginAccessCheckCallback"), + EmptyNode(), + make_cross_origin_property_getter_callback( + cg_context, "CrossOriginPropertyGetterCallback"), + EmptyNode(), + make_cross_origin_property_setter_callback( + cg_context, "CrossOriginPropertySetterCallback"), + EmptyNode(), + make_cross_origin_property_descriptor_callback( + cg_context, "CrossOriginPropertyDescriptorCallback"), + EmptyNode(), + make_cross_origin_property_enumerator_callback( + cg_context, "CrossOriginPropertyEnumeratorCallback"), + ]) + + text = """\ +// Cross origin properties +${instance_template}->SetAccessCheckCallbackAndHandler( + CrossOriginAccessCheckCallback, + v8::NamedPropertyHandlerConfiguration( + CrossOriginPropertyGetterCallback, + CrossOriginPropertySetterCallback, + CrossOriginPropertyDescriptorCallback, + nullptr, // deleter + CrossOriginPropertyEnumeratorCallback, + nullptr, // definer, + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone), +% if interface.indexed_and_named_properties and \ + interface.indexed_and_named_properties.has_indexed_properties: + // Reuse non-cross origin indexed property callbacks. + v8::IndexedPropertyHandlerConfiguration( + ${class_name}::IndexedPropertyGetterCallback, + nullptr, // setter + ${class_name}::IndexedPropertyDescriptorCallback, + nullptr, // deleter + ${class_name}::IndexedPropertyEnumeratorCallback, + nullptr, // definer + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone), +% else: + v8::IndexedPropertyHandlerConfiguration( + nullptr, // getter + nullptr, // setter + nullptr, // descriptor + nullptr, // deleter + nullptr, // enumerator + nullptr, // definer + v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kNone), +% endif + v8::Local<v8::Value>());""" + install_nodes.append(TextNode(text)) + install_nodes.accumulate( + CodeGenAccumulator.require_include_headers([ + "third_party/blink/renderer/bindings/core/v8/binding_security.h", + "third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h", + ])) + + return callback_defs, install_nodes + + def make_cross_component_init( cg_context, function_name, class_name, has_unconditional_props, has_context_independent_props, has_context_dependent_props): @@ -3869,11 +4361,20 @@ arg_decls=["const v8::FunctionCallbackInfo<v8::Value>&"]) for attribute in interface.attributes: custom_values = attribute.extended_attributes.values_of("Custom") + is_cross_origin = "CrossOrigin" in attribute.extended_attributes + cross_origin_values = attribute.extended_attributes.values_of( + "CrossOrigin") if "Getter" in custom_values: add_custom_callback_impl_decl( attribute=attribute, attribute_get=True, arg_decls=["const v8::FunctionCallbackInfo<v8::Value>&"]) + if is_cross_origin and (not cross_origin_values + or "Getter" in cross_origin_values): + add_custom_callback_impl_decl( + attribute=attribute, + attribute_get=True, + arg_decls=["const v8::PropertyCallbackInfo<v8::Value>&"]) if "Setter" in custom_values: add_custom_callback_impl_decl( attribute=attribute, @@ -3882,6 +4383,15 @@ "v8::Local<v8::Value>", "const v8::FunctionCallbackInfo<v8::Value>&", ]) + if is_cross_origin and (not cross_origin_values + or "Setter" in cross_origin_values): + add_custom_callback_impl_decl( + attribute=attribute, + attribute_set=True, + arg_decls=[ + "v8::Local<v8::Value>", + "const v8::PropertyCallbackInfo<v8::Value>&", + ]) for operation_group in interface.operation_groups: if "Custom" in operation_group.extended_attributes: add_custom_callback_impl_decl( @@ -3903,7 +4413,7 @@ named_property_setter=operation, arg_decls=[ "const AtomicString& property_name", - "v8::Local<v8::Value> v8_value", + "v8::Local<v8::Value> v8_property_value", "const v8::PropertyCallbackInfo<v8::Value>&", ]) operation = props.own_named_deleter @@ -3949,6 +4459,13 @@ make_indexed_and_named_property_callbacks_and_install_nodes( cg_context)) + # Cross origin properties + (cross_origin_property_callback_defs, + cross_origin_property_install_nodes) = ( + make_cross_origin_property_callbacks_and_install_nodes( + cg_context, attribute_entries, operation_entries)) + callback_defs.extend(cross_origin_property_callback_defs) + # Installer functions is_unconditional = lambda entry: entry.exposure_conditional.is_always_true is_context_dependent = lambda entry: entry.is_context_dependent @@ -4000,6 +4517,8 @@ constructor_entries=constructor_entries, indexed_and_named_property_install_nodes=( indexed_and_named_property_install_nodes), + cross_origin_property_install_nodes=( + cross_origin_property_install_nodes), install_unconditional_func_name=(install_unconditional_props_def and FN_INSTALL_UNCONDITIONAL_PROPS), install_context_independent_func_name=(
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py b/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py index e03ae3f6..b4c7055 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/mako_renderer.py
@@ -166,7 +166,7 @@ """Returns the best-guessed name of |caller|.""" try: # Outer CodeNode may have a binding to the caller. - for name, value in caller.outer.template_vars.iteritems(): + for name, value in caller.outer.template_vars.items(): if value is caller: return name try:
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py b/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py index a5c0f21b..36a858ce 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/name_style.py
@@ -140,7 +140,7 @@ assert isinstance(format_string, str) args = map(style_func, map(_tokenize, args)) - for key, value in kwargs.iteritems(): + for key, value in kwargs.items(): kwargs[key] = style_func(_tokenize(value)) return format_string.format(*args, **kwargs)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py b/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py index 42fd7d2..47d6c08b 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/path_manager.py
@@ -58,7 +58,7 @@ cls._root_gen_dir = os.path.abspath(root_gen_dir) cls._component_reldirs = { component: posixpath.normpath(rel_dir) - for component, rel_dir in component_reldirs.iteritems() + for component, rel_dir in component_reldirs.items() } cls._is_initialized = True
diff --git a/third_party/blink/renderer/bindings/scripts/code_generator_v8.py b/third_party/blink/renderer/bindings/scripts/code_generator_v8.py index a5973457..f296d48 100644 --- a/third_party/blink/renderer/bindings/scripts/code_generator_v8.py +++ b/third_party/blink/renderer/bindings/scripts/code_generator_v8.py
@@ -95,7 +95,7 @@ def resolve(self, definitions, definition_name): """Traverse definitions and resolves typedefs with the actual types.""" self.typedefs = {} - for name, typedef in self.info_provider.typedefs.iteritems(): + for name, typedef in self.info_provider.typedefs.items(): self.typedefs[name] = typedef.idl_type self.additional_header_includes = set() definitions.accept(self) @@ -338,7 +338,7 @@ # idl_definitions.py. What we do instead is to resolve typedefs in # _generate_container_code() whenever a new union file is generated. self.typedefs = {} - for name, typedef in self.info_provider.typedefs.iteritems(): + for name, typedef in self.info_provider.typedefs.items(): self.typedefs[name] = typedef.idl_type def _generate_container_code(self, union_type): @@ -441,7 +441,7 @@ if not callback_functions: return () outputs = set() - for callback_function_dict in callback_functions.itervalues(): + for callback_function_dict in callback_functions.values(): if callback_function_dict['component_dir'] != self.target_component: continue callback_function = callback_function_dict['callback_function']
diff --git a/third_party/blink/renderer/bindings/scripts/compute_global_objects.py b/third_party/blink/renderer/bindings/scripts/compute_global_objects.py index 81dc51f..7fa1c022 100755 --- a/third_party/blink/renderer/bindings/scripts/compute_global_objects.py +++ b/third_party/blink/renderer/bindings/scripts/compute_global_objects.py
@@ -48,7 +48,7 @@ def dict_union(dicts): - return dict((k, v) for d in dicts for k, v in d.iteritems()) + return dict((k, v) for d in dicts for k, v in d.items()) def idl_file_to_global_names(idl_filename):
diff --git a/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py b/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py index 06b88aa..01c23ba 100755 --- a/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py +++ b/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_individual.py
@@ -238,7 +238,7 @@ self.union_types.update(this_union_types) self.typedefs.update(definitions.typedefs) for callback_function_name, callback_function in \ - definitions.callback_functions.iteritems(): + definitions.callback_functions.items(): # Set 'component_dir' to specify a directory that callback function files belong to self.callback_functions[callback_function_name] = { 'callback_function': callback_function, @@ -253,7 +253,7 @@ self.enumerations.update(definitions.enumerations) if definitions.interfaces: - definition = next(definitions.interfaces.itervalues()) + definition = next(iter(definitions.interfaces.values())) interface_info = { 'is_callback_interface': definition.is_callback, @@ -270,7 +270,7 @@ get_put_forward_interfaces_from_definition(definition), } elif definitions.dictionaries: - definition = next(definitions.dictionaries.itervalues()) + definition = next(iter(definitions.dictionaries.values())) interface_info = { 'is_callback_interface': False, 'is_dictionary': True,
diff --git a/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py b/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py index 98f0a5f..235cf0f 100755 --- a/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py +++ b/third_party/blink/renderer/bindings/scripts/compute_interfaces_info_overall.py
@@ -127,12 +127,12 @@ Needed for merging partial_interface_files across components. """ - for key, value in other.iteritems(): + for key, value in other.items(): if key not in existing: existing[key] = value continue existing_value = existing[key] - for inner_key, inner_value in value.iteritems(): + for inner_key, inner_value in value.items(): existing_value[inner_key].extend(inner_value) @@ -178,7 +178,7 @@ garbage_collected_interfaces = set() callback_interfaces = set() - for interface_name, interface_info in interfaces_info.iteritems(): + for interface_name, interface_info in interfaces_info.items(): component_dirs[interface_name] = idl_filename_to_component( interface_info['full_path']) @@ -220,10 +220,10 @@ partial_interface_files, info['partial_interface_files']) # Record inheritance information individually - for interface_name, interface_info in interfaces_info.iteritems(): + for interface_name, interface_info in interfaces_info.items(): extended_attributes = interface_info['extended_attributes'] inherited_extended_attributes_by_interface[interface_name] = dict( - (key, value) for key, value in extended_attributes.iteritems() + (key, value) for key, value in extended_attributes.items() if key in INHERITED_EXTENDED_ATTRIBUTES) parent = interface_info['parent'] if parent: @@ -241,7 +241,7 @@ # 'includes'). # Note that moving an 'includes' statement between files does not change the # info itself (or hence cause a rebuild)! - for mixin_name, interface_info in interfaces_info.iteritems(): + for mixin_name, interface_info in interfaces_info.items(): for interface_name in interface_info['included_by_interfaces']: interfaces_info[interface_name]['including_mixins'].append( mixin_name) @@ -249,7 +249,7 @@ # An IDL file's dependencies are partial interface files that extend it, # and files for other interfaces that this interfaces include. - for interface_name, interface_info in interfaces_info.iteritems(): + for interface_name, interface_info in interfaces_info.items(): partial_interface_paths = partial_interface_files[interface_name] partial_interfaces_full_paths = partial_interface_paths['full_paths'] # Partial interface definitions each need an include, as they are @@ -311,7 +311,7 @@ }) # Clean up temporary private information - for interface_info in interfaces_info.itervalues(): + for interface_info in interfaces_info.values(): del interface_info['extended_attributes'] del interface_info['union_types'] del interface_info['is_legacy_treat_as_partial_interface']
diff --git a/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py b/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py index 6cc7bf0..987f737c 100755 --- a/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py +++ b/third_party/blink/renderer/bindings/scripts/generate_global_constructors.py
@@ -120,7 +120,7 @@ extended_attributes_list = [ name + (('=' + extended_attributes[name]) if extended_attributes[name] else '') - for name in 'RuntimeEnabled', 'ContextEnabled', 'SecureContext' + for name in ['RuntimeEnabled', 'ContextEnabled', 'SecureContext'] if name in extended_attributes ] if extended_attributes_list:
diff --git a/third_party/blink/renderer/bindings/scripts/idl_definitions.py b/third_party/blink/renderer/bindings/scripts/idl_definitions.py index f42bc78..11f6846 100644 --- a/third_party/blink/renderer/bindings/scripts/idl_definitions.py +++ b/third_party/blink/renderer/bindings/scripts/idl_definitions.py
@@ -137,22 +137,22 @@ def accept(self, visitor): visitor.visit_definitions(self) - for interface in self.interfaces.itervalues(): + for interface in self.interfaces.values(): interface.accept(visitor) - for callback_function in self.callback_functions.itervalues(): + for callback_function in self.callback_functions.values(): callback_function.accept(visitor) - for dictionary in self.dictionaries.itervalues(): + for dictionary in self.dictionaries.values(): dictionary.accept(visitor) - for enumeration in self.enumerations.itervalues(): + for enumeration in self.enumerations.values(): enumeration.accept(visitor) for include in self.includes: include.accept(visitor) - for typedef in self.typedefs.itervalues(): + for typedef in self.typedefs.values(): typedef.accept(visitor) def update(self, other): """Update with additional IdlDefinitions.""" - for interface_name, new_interface in other.interfaces.iteritems(): + for interface_name, new_interface in other.interfaces.items(): if not new_interface.is_partial: # Add as new interface self.interfaces[interface_name] = new_interface
diff --git a/third_party/blink/renderer/bindings/scripts/idl_types.py b/third_party/blink/renderer/bindings/scripts/idl_types.py index 0618f3c7..cd4f0c35 100644 --- a/third_party/blink/renderer/bindings/scripts/idl_types.py +++ b/third_party/blink/renderer/bindings/scripts/idl_types.py
@@ -642,7 +642,7 @@ def __str__(self): annotation = ', '.join( (key + ('' if val is None else '=' + val)) - for key, val in self.extended_attributes.iteritems()) + for key, val in self.extended_attributes.items()) return '[%s] %s' % (annotation, str(self.inner_type)) def __getattr__(self, name): @@ -670,7 +670,7 @@ def name(self): annotation = ''.join( (key + ('' if val is None else val)) - for key, val in sorted(self.extended_attributes.iteritems())) + for key, val in sorted(self.extended_attributes.items())) return self.inner_type.name + annotation def resolve_typedefs(self, typedefs):
diff --git a/third_party/blink/renderer/bindings/scripts/idl_validator.py b/third_party/blink/renderer/bindings/scripts/idl_validator.py index 59eb8e1..64e84ef7d 100644 --- a/third_party/blink/renderer/bindings/scripts/idl_validator.py +++ b/third_party/blink/renderer/bindings/scripts/idl_validator.py
@@ -51,7 +51,7 @@ def validate_extended_attributes(self, definitions): # FIXME: this should be done when parsing the file, rather than after. - for interface in definitions.interfaces.itervalues(): + for interface in definitions.interfaces.values(): self.validate_extended_attributes_node(interface) for attribute in interface.attributes: self.validate_extended_attributes_node(attribute) @@ -59,17 +59,17 @@ self.validate_extended_attributes_node(operation) for argument in operation.arguments: self.validate_extended_attributes_node(argument) - for dictionary in definitions.dictionaries.itervalues(): + for dictionary in definitions.dictionaries.values(): self.validate_extended_attributes_node(dictionary) for member in dictionary.members: self.validate_extended_attributes_node(member) - for callback_function in definitions.callback_functions.itervalues(): + for callback_function in definitions.callback_functions.values(): self.validate_extended_attributes_node(callback_function) for argument in callback_function.arguments: self.validate_extended_attributes_node(argument) def validate_extended_attributes_node(self, node): - for name, values_string in node.extended_attributes.iteritems(): + for name, values_string in node.extended_attributes.items(): self.validate_name_values_string(name, values_string) def validate_name_values_string(self, name, values_string):
diff --git a/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py b/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py index 1a6b9bc..030ca1c9 100644 --- a/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py +++ b/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
@@ -101,7 +101,7 @@ 'this definition: %s, because this should ' 'have a dictionary.' % definitions.idl_name) - target_interface = next(definitions.interfaces.itervalues()) + target_interface = next(iter(definitions.interfaces.values())) interface_name = target_interface.name interface_info = self.interfaces_info[interface_name] @@ -163,7 +163,7 @@ dependency_idl_filename) dependency_interface = next( - dependency_definitions.interfaces.itervalues()) + iter(dependency_definitions.interfaces.values())) transfer_extended_attributes(dependency_interface, dependency_idl_filename) @@ -361,8 +361,8 @@ interface.get('cpp_includes', {}).get(component, {})) return unforgeable_attributes, referenced_interfaces, cpp_includes - for component, definitions in resolved_definitions.iteritems(): - for interface_name, interface in definitions.interfaces.iteritems(): + for component, definitions in resolved_definitions.items(): + for interface_name, interface in definitions.interfaces.items(): interface_info = interfaces_info[interface_name] inherited_unforgeable_attributes, referenced_interfaces, cpp_includes = \ collect_unforgeable_attributes_in_ancestors(
diff --git a/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py b/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py index baaf0e73..309de69 100644 --- a/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py +++ b/third_party/blink/renderer/bindings/scripts/overload_set_algorithm.py
@@ -183,7 +183,7 @@ # Filter to only methods that are actually overloaded method_counts = Counter(method['name'] for method in methods) overloaded_method_names = set( - name for name, count in method_counts.iteritems() if count > 1) + name for name, count in method_counts.items() if count > 1) overloaded_methods = [ method for method in methods if method['name'] in overloaded_method_names
diff --git a/third_party/blink/renderer/bindings/scripts/utilities.py b/third_party/blink/renderer/bindings/scripts/utilities.py index 8529b5a..e52de46c 100644 --- a/third_party/blink/renderer/bindings/scripts/utilities.py +++ b/third_party/blink/renderer/bindings/scripts/utilities.py
@@ -219,7 +219,7 @@ |target| will be updated with |diff|. Part of |diff| may be re-used in |target|. """ - for key, value in diff.iteritems(): + for key, value in diff.items(): if key not in target: target[key] = value elif type(value) == dict: @@ -324,7 +324,7 @@ def read_pickle_file(pickle_filename): - with open(pickle_filename) as pickle_file: + with open(pickle_filename, 'rb') as pickle_file: return pickle.load(pickle_file)
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/database.py b/third_party/blink/renderer/bindings/scripts/web_idl/database.py index 33ac805..c92cf48e 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/database.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/database.py
@@ -48,17 +48,17 @@ ) @classmethod - def itervalues(cls): + def values(cls): return cls._ALL_ENTRIES.__iter__() def __init__(self): self._defs = {} - for kind in DatabaseBody.Kind.itervalues(): + for kind in DatabaseBody.Kind.values(): self._defs[kind] = {} def register(self, kind, user_defined_type): assert isinstance(user_defined_type, (Typedef, Union, UserDefinedType)) - assert kind in DatabaseBody.Kind.itervalues() + assert kind in DatabaseBody.Kind.values() try: self.find_by_identifier(user_defined_type.identifier) assert False, user_defined_type.identifier @@ -67,7 +67,7 @@ self._defs[kind][user_defined_type.identifier] = user_defined_type def find_by_identifier(self, identifier): - for defs_per_kind in self._defs.itervalues(): + for defs_per_kind in self._defs.values(): if identifier in defs_per_kind: return defs_per_kind[identifier] raise KeyError(identifier) @@ -156,4 +156,4 @@ return self._view_by_kind(Database._Kind.UNION) def _view_by_kind(self, kind): - return self._impl.find_by_kind(kind).viewvalues() + return self._impl.find_by_kind(kind).values()
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py b/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py index 52c04173..36eec862 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/extended_attribute.py
@@ -190,7 +190,7 @@ def _on_ext_attrs_updated(self): self._keys = tuple(sorted(self._ext_attrs.keys())) self._length = 0 - for ext_attrs in self._ext_attrs.itervalues(): + for ext_attrs in self._ext_attrs.values(): self._length += len(ext_attrs) @classmethod
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py index 46096964..9ad0852 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
@@ -299,7 +299,7 @@ self._ir_map.move_to_new_phase() - for identifier, old_dictionary in old_dictionaries.iteritems(): + for identifier, old_dictionary in old_dictionaries.items(): new_dictionary = make_copy(old_dictionary) self._ir_map.add(new_dictionary) for partial_dictionary in old_partial_dictionaries.get( @@ -331,7 +331,7 @@ ir_sets_to_merge = [(interface, [ mixins[include.mixin_identifier] for include in includes.get(identifier, []) - ]) for identifier, interface in interfaces.iteritems()] + ]) for identifier, interface in interfaces.items()] self._ir_map.move_to_new_phase() @@ -380,7 +380,7 @@ self._ir_map.move_to_new_phase() - for old_interface in old_interfaces.itervalues(): + for old_interface in old_interfaces.values(): new_interface = make_copy(old_interface) self._ir_map.add(new_interface) inheritance_chain = create_inheritance_chain( @@ -644,13 +644,13 @@ grouped_typedefs = {} # {unique key: list of typedefs to the union} all_typedefs = self._db.find_by_kind(DatabaseBody.Kind.TYPEDEF) - for typedef in all_typedefs.itervalues(): + for typedef in all_typedefs.values(): if not typedef.idl_type.is_union: continue key = unique_key(typedef.idl_type) grouped_typedefs.setdefault(key, []).append(typedef) - for key, union_types in grouped_unions.iteritems(): + for key, union_types in grouped_unions.items(): self._db.register( DatabaseBody.Kind.UNION, Union(
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py index 4184196..1d7ae80 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type.py
@@ -265,14 +265,14 @@ } value_counts = {None: 0, False: 0, True: 0} - for value in switches.itervalues(): + for value in switches.values(): assert value is None or isinstance(value, bool) value_counts[value] += 1 assert value_counts[False] == 0 or value_counts[True] == 0, ( "Specify only True or False arguments. Unspecified arguments are " "automatically set to the opposite value.") default = value_counts[True] == 0 - for arg, value in switches.iteritems(): + for arg, value in switches.items(): if value is None: switches[arg] = default
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py index 1f44473..b3d097a7 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_type_test.py
@@ -83,7 +83,7 @@ 'void': 'Void', 'symbol': 'Symbol', } - for name, expect in type_names.iteritems(): + for name, expect in type_names.items(): self.assertEqual(expect, factory.simple_type(name).type_name) short_type = factory.simple_type('short')
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py b/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py index f95cbd9..91806523 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/ir_map.py
@@ -190,11 +190,11 @@ """Returns a flattened list of IRs of the given kind.""" if IRMap.IR.Kind.does_support_multiple_defs(kind): accumulated = [] - for irs in self.find_by_kind(kind).itervalues(): + for irs in self.find_by_kind(kind).values(): accumulated.extend(irs) return accumulated else: - return list(self.find_by_kind(kind).itervalues()) + return list(self.find_by_kind(kind).values()) def irs_of_kinds(self, *kinds): """
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py b/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py index b9a22eb..a7a2b11 100644 --- a/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py +++ b/third_party/blink/renderer/bindings/scripts/web_idl/make_copy.py
@@ -48,11 +48,11 @@ if isinstance(obj, dict): return memoize( cls([(make_copy(key, memo), make_copy(value, memo)) - for key, value in obj.iteritems()])) + for key, value in obj.items()])) if hasattr(obj, '__dict__'): copy = memoize(cls.__new__(cls)) - for name, value in obj.__dict__.iteritems(): + for name, value in obj.__dict__.items(): setattr(copy, name, make_copy(value, memo)) return copy
diff --git a/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py b/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py index e0735b1..75dda00 100644 --- a/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py +++ b/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from __future__ import print_function + def _RunBindingsTests(input_api, output_api): pardir = input_api.os_path.pardir
diff --git a/third_party/blink/renderer/build/scripts/gperf.py b/third_party/blink/renderer/build/scripts/gperf.py index 73dd62ad..5ee49056 100644 --- a/third_party/blink/renderer/build/scripts/gperf.py +++ b/third_party/blink/renderer/build/scripts/gperf.py
@@ -71,7 +71,7 @@ gperf_args.extend(gperf_extra_args) return generate_gperf(gperf_path, gperf_input, gperf_args) - generator_internal.func_name = generator.func_name + generator_internal.__name__ = generator.__name__ return generator_internal return wrapper
diff --git a/third_party/blink/renderer/build/scripts/in_file.py b/third_party/blink/renderer/build/scripts/in_file.py index 9d1f7c3..28adc05 100644 --- a/third_party/blink/renderer/build/scripts/in_file.py +++ b/third_party/blink/renderer/build/scripts/in_file.py
@@ -26,6 +26,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import print_function + import copy import os @@ -175,5 +177,5 @@ def _fatal(self, message): # FIXME: This should probably raise instead of exit(1) - print message + print(message) exit(1)
diff --git a/third_party/blink/renderer/build/scripts/in_generator.py b/third_party/blink/renderer/build/scripts/in_generator.py index f66347b2..e46740a 100644 --- a/third_party/blink/renderer/build/scripts/in_generator.py +++ b/third_party/blink/renderer/build/scripts/in_generator.py
@@ -26,6 +26,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import print_function + import os import os.path import shlex @@ -94,7 +96,7 @@ script_name = os.path.basename(argv[0]) args = argv[1:] if len(args) < 1: - print "USAGE: %s INPUT_FILES" % script_name + print("USAGE: %s INPUT_FILES" % script_name) exit(1) parser = optparse.OptionParser()
diff --git a/third_party/blink/renderer/build/scripts/make_event_factory.py b/third_party/blink/renderer/build/scripts/make_event_factory.py index 0050b386..a7ceb451 100755 --- a/third_party/blink/renderer/build/scripts/make_event_factory.py +++ b/third_party/blink/renderer/build/scripts/make_event_factory.py
@@ -27,6 +27,8 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import print_function + import os.path import sys @@ -103,7 +105,7 @@ } def _fatal(self, message): - print 'FATAL ERROR: ' + message + print('FATAL ERROR: ' + message) exit(1) def _headers_header_include_path(self, entry):
diff --git a/third_party/blink/renderer/build/scripts/make_names.py b/third_party/blink/renderer/build/scripts/make_names.py index 39c5db7..3f7520a7 100755 --- a/third_party/blink/renderer/build/scripts/make_names.py +++ b/third_party/blink/renderer/build/scripts/make_names.py
@@ -84,6 +84,7 @@ entries = json5_generator.remove_duplicates(entries) else: json5_generator.reject_duplicates(entries) + entries.sort(key=lambda x: _symbol(x)) basename, _ = os.path.splitext(os.path.basename(json5_file_path[0])) self._outputs = {
diff --git a/third_party/blink/renderer/build/scripts/make_origin_trials.py b/third_party/blink/renderer/build/scripts/make_origin_trials.py index 672f9d7..db5b93a9 100755 --- a/third_party/blink/renderer/build/scripts/make_origin_trials.py +++ b/third_party/blink/renderer/build/scripts/make_origin_trials.py
@@ -48,8 +48,7 @@ self._implied_mappings = self._make_implied_mappings() self._trial_to_features_map = self._make_trial_to_features_map() self._max_features_per_trial = max( - len(features) - for features in self._trial_to_features_map.itervalues()) + len(features) for features in self._trial_to_features_map.values()) self._set_trial_types() @property
diff --git a/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl b/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl index 6b62497..f6dd475 100644 --- a/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/make_names.h.tmpl
@@ -19,7 +19,7 @@ namespace blink { namespace {{namespace}} { -{% for entry in entries|sort %} +{% for entry in entries %} {{symbol_export}}extern const WTF::AtomicString& {{entry|symbol}}; {% endfor %}
diff --git a/third_party/blink/renderer/core/animation/BUILD.gn b/third_party/blink/renderer/core/animation/BUILD.gn index 12ceb359..d2a6c965 100644 --- a/third_party/blink/renderer/core/animation/BUILD.gn +++ b/third_party/blink/renderer/core/animation/BUILD.gn
@@ -92,6 +92,8 @@ "css_image_list_interpolation_type.h", "css_image_slice_interpolation_type.cc", "css_image_slice_interpolation_type.h", + "css_interpolation_environment.cc", + "css_interpolation_environment.h", "css_interpolation_type.cc", "css_interpolation_type.h", "css_interpolation_types_map.cc",
diff --git a/third_party/blink/renderer/core/animation/animation_test_helper.cc b/third_party/blink/renderer/core/animation/animation_test_helper.cc index 4bafa54..88cc4e0 100644 --- a/third_party/blink/renderer/core/animation/animation_test_helper.cc +++ b/third_party/blink/renderer/core/animation/animation_test_helper.cc
@@ -8,7 +8,6 @@ #include "third_party/blink/renderer/core/animation/css_interpolation_environment.h" #include "third_party/blink/renderer/core/animation/css_interpolation_types_map.h" #include "third_party/blink/renderer/core/animation/invalidatable_interpolation.h" -#include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h" #include "third_party/blink/renderer/core/css/resolver/style_cascade.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" #include "third_party/blink/renderer/core/dom/document.h" @@ -55,13 +54,8 @@ ActiveInterpolationsMap map; map.Set(PropertyHandle("--unused"), interpolations); - using Entry = CascadeInterpolations::Entry; - CascadeInterpolations cascade_interpolations(Vector<Entry, 4>{ - Entry{&map, CascadeOrigin::kAnimation}, - }); - - cascade.Analyze(cascade_interpolations, CascadeFilter()); - cascade.Apply(cascade_interpolations, CascadeFilter()); + cascade.AddInterpolations(&map, CascadeOrigin::kAnimation); + cascade.Apply(); } else { CSSInterpolationTypesMap map(state.GetDocument().GetPropertyRegistry(), state.GetDocument());
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_environment.cc b/third_party/blink/renderer/core/animation/css_interpolation_environment.cc new file mode 100644 index 0000000..bb8bb38f --- /dev/null +++ b/third_party/blink/renderer/core/animation/css_interpolation_environment.cc
@@ -0,0 +1,25 @@ +// 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/animation/css_interpolation_environment.h" + +#include "third_party/blink/renderer/core/animation/property_handle.h" +#include "third_party/blink/renderer/core/css/resolver/cascade_resolver.h" +#include "third_party/blink/renderer/core/css/resolver/style_cascade.h" + +namespace blink { + +const CSSValue* CSSInterpolationEnvironment::Resolve( + const PropertyHandle& property, + const CSSValue* value) const { + DCHECK(RuntimeEnabledFeatures::CSSCascadeEnabled()); + DCHECK(cascade_); + DCHECK(cascade_resolver_); + if (!value) + return value; + return cascade_->Resolve(property.GetCSSPropertyName(), *value, + *cascade_resolver_); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_environment.h b/third_party/blink/renderer/core/animation/css_interpolation_environment.h index 6a68781..7e15b15f 100644 --- a/third_party/blink/renderer/core/animation/css_interpolation_environment.h +++ b/third_party/blink/renderer/core/animation/css_interpolation_environment.h
@@ -6,13 +6,14 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_INTERPOLATION_ENVIRONMENT_H_ #include "third_party/blink/renderer/core/animation/interpolation_environment.h" -#include "third_party/blink/renderer/core/css/resolver/style_cascade.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" namespace blink { +class CascadeResolver; class ComputedStyle; class CSSVariableResolver; +class StyleCascade; class CSSInterpolationEnvironment : public InterpolationEnvironment { public: @@ -27,7 +28,7 @@ explicit CSSInterpolationEnvironment(const InterpolationTypesMap& map, StyleResolverState& state, StyleCascade* cascade, - StyleCascade::Resolver* cascade_resolver) + CascadeResolver* cascade_resolver) : InterpolationEnvironment(map), state_(&state), style_(state.Style()), @@ -67,23 +68,14 @@ } // TODO(crbug.com/985023): This effective violates const. - const CSSValue* Resolve(const PropertyHandle& property, - const CSSValue* value) const { - DCHECK(RuntimeEnabledFeatures::CSSCascadeEnabled()); - DCHECK(cascade_); - DCHECK(cascade_resolver_); - if (!value) - return value; - return cascade_->Resolve(property.GetCSSPropertyName(), *value, - *cascade_resolver_); - } + const CSSValue* Resolve(const PropertyHandle&, const CSSValue*) const; private: StyleResolverState* state_ = nullptr; const ComputedStyle* style_ = nullptr; CSSVariableResolver* variable_resolver_ = nullptr; StyleCascade* cascade_ = nullptr; - StyleCascade::Resolver* cascade_resolver_ = nullptr; + CascadeResolver* cascade_resolver_ = nullptr; }; template <>
diff --git a/third_party/blink/renderer/core/css/BUILD.gn b/third_party/blink/renderer/core/css/BUILD.gn index 9f1e812..183fd3f 100644 --- a/third_party/blink/renderer/core/css/BUILD.gn +++ b/third_party/blink/renderer/core/css/BUILD.gn
@@ -475,6 +475,8 @@ "resolver/cascade_map.h", "resolver/cascade_origin.h", "resolver/cascade_priority.h", + "resolver/cascade_resolver.cc", + "resolver/cascade_resolver.h", "resolver/css_property_priority.h", "resolver/css_to_style_map.cc", "resolver/css_to_style_map.h",
diff --git a/third_party/blink/renderer/core/css/page_rule_collector.cc b/third_party/blink/renderer/core/css/page_rule_collector.cc index ff844b8..0b20fc6 100644 --- a/third_party/blink/renderer/core/css/page_rule_collector.cc +++ b/third_party/blink/renderer/core/css/page_rule_collector.cc
@@ -64,10 +64,12 @@ } PageRuleCollector::PageRuleCollector(const ComputedStyle* root_element_style, - int page_index) + int page_index, + MatchResult& match_result) : is_left_page_(IsLeftPage(root_element_style, page_index)), is_first_page_(IsFirstPage(page_index)), - page_name_(PageName(page_index)) {} + page_name_(PageName(page_index)), + result_(match_result) {} void PageRuleCollector::MatchPageRules(RuleSet* rules) { if (!rules)
diff --git a/third_party/blink/renderer/core/css/page_rule_collector.h b/third_party/blink/renderer/core/css/page_rule_collector.h index 065618b..f8fe90e 100644 --- a/third_party/blink/renderer/core/css/page_rule_collector.h +++ b/third_party/blink/renderer/core/css/page_rule_collector.h
@@ -34,7 +34,9 @@ STACK_ALLOCATED(); public: - PageRuleCollector(const ComputedStyle* root_element_style, int page_index); + PageRuleCollector(const ComputedStyle* root_element_style, + int page_index, + MatchResult&); void MatchPageRules(RuleSet* rules); const MatchResult& MatchedResult() { return result_; } @@ -59,7 +61,7 @@ const bool is_first_page_; const String page_name_; - MatchResult result_; + MatchResult& result_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/longhand.h b/third_party/blink/renderer/core/css/properties/longhand.h index 6bdebb7b..161366c 100644 --- a/third_party/blink/renderer/core/css/properties/longhand.h +++ b/third_party/blink/renderer/core/css/properties/longhand.h
@@ -43,9 +43,7 @@ } protected: - constexpr Longhand(CSSPropertyID id, - uint16_t flags, - char repetition_separator) + constexpr Longhand(CSSPropertyID id, Flags flags, char repetition_separator) : CSSProperty(id, flags | kLonghand, repetition_separator) {} };
diff --git a/third_party/blink/renderer/core/css/properties/shorthand.h b/third_party/blink/renderer/core/css/properties/shorthand.h index a4743b27..6970ad40 100644 --- a/third_party/blink/renderer/core/css/properties/shorthand.h +++ b/third_party/blink/renderer/core/css/properties/shorthand.h
@@ -31,9 +31,7 @@ } protected: - constexpr Shorthand(CSSPropertyID id, - uint16_t flags, - char repetition_separator) + constexpr Shorthand(CSSPropertyID id, Flags flags, char repetition_separator) : CSSProperty(id, flags | kShorthand, repetition_separator) {} };
diff --git a/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h b/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h index 6a6e3b4b..a2a9fb2 100644 --- a/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h +++ b/third_party/blink/renderer/core/css/resolver/cascade_interpolations.h
@@ -25,9 +25,10 @@ CascadeOrigin origin = CascadeOrigin::kNone; }; - CascadeInterpolations() = default; - CascadeInterpolations(Vector<Entry, 4> entries) - : entries_(std::move(entries)) {} + void Add(const ActiveInterpolationsMap* map, CascadeOrigin origin) { + DCHECK(map); + entries_.push_back(Entry{map, origin}); + } bool IsEmpty() const { return GetEntries().IsEmpty(); } @@ -39,6 +40,8 @@ return entries_; } + void Reset() { entries_.clear(); } + private: // We need to add at most four entries (see CSSAnimationUpdate): //
diff --git a/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc b/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc index 7a6e37a6..005809d 100644 --- a/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc +++ b/third_party/blink/renderer/core/css/resolver/cascade_interpolations_test.cc
@@ -15,16 +15,32 @@ "Unexpected max. If the limit increased, evaluate whether it " "still makes sense to run this test"); - using Entry = CascadeInterpolations::Entry; + ActiveInterpolationsMap map; - CascadeInterpolations at_max(Vector<Entry, 4>(max + 1)); - CascadeInterpolations above_max(Vector<Entry, 4>(max + 2)); + CascadeInterpolations interpolations; + for (size_t i = 0; i <= max; ++i) + interpolations.Add(&map, CascadeOrigin::kAuthor); - EXPECT_EQ(max + 1, at_max.GetEntries().size()); - EXPECT_FALSE(at_max.IsEmpty()); + // At maximum + EXPECT_FALSE(interpolations.IsEmpty()); - EXPECT_FALSE(above_max.GetEntries().size()); - EXPECT_TRUE(above_max.IsEmpty()); + interpolations.Add(&map, CascadeOrigin::kAuthor); + + // Maximum + 1 + EXPECT_TRUE(interpolations.IsEmpty()); +} + +TEST(CascadeInterpolationsTest, Reset) { + ActiveInterpolationsMap map; + + CascadeInterpolations interpolations; + EXPECT_TRUE(interpolations.IsEmpty()); + + interpolations.Add(&map, CascadeOrigin::kAuthor); + EXPECT_FALSE(interpolations.IsEmpty()); + + interpolations.Reset(); + EXPECT_TRUE(interpolations.IsEmpty()); } } // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/cascade_resolver.cc b/third_party/blink/renderer/core/css/resolver/cascade_resolver.cc new file mode 100644 index 0000000..164a54a --- /dev/null +++ b/third_party/blink/renderer/core/css/resolver/cascade_resolver.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 "third_party/blink/renderer/core/css/resolver/cascade_resolver.h" + +#include "third_party/blink/renderer/core/animation/css/css_animations.h" +#include "third_party/blink/renderer/core/css/css_variable_data.h" +#include "third_party/blink/renderer/core/css/properties/css_property.h" + +namespace blink { + +bool CascadeResolver::IsLocked(const CSSProperty& property) const { + return IsLocked(property.GetCSSPropertyName()); +} + +bool CascadeResolver::IsLocked(const CSSPropertyName& name) const { + return stack_.Contains(name); +} + +bool CascadeResolver::AllowSubstitution(CSSVariableData* data) const { + if (data && data->IsAnimationTainted() && stack_.size()) { + const CSSPropertyName& name = stack_.back(); + if (name.IsCustomProperty()) + return true; + const CSSProperty& property = CSSProperty::Get(name.Id()); + return !CSSAnimations::IsAnimationAffectingProperty(property); + } + return true; +} + +bool CascadeResolver::DetectCycle(const CSSProperty& property) { + wtf_size_t index = stack_.Find(property.GetCSSPropertyName()); + if (index == kNotFound) + return false; + cycle_depth_ = std::min(cycle_depth_, index); + return true; +} + +bool CascadeResolver::InCycle() const { + return cycle_depth_ != kNotFound; +} + +CascadeResolver::AutoLock::AutoLock(const CSSProperty& property, + CascadeResolver& resolver) + : AutoLock(property.GetCSSPropertyName(), resolver) {} + +CascadeResolver::AutoLock::AutoLock(const CSSPropertyName& name, + CascadeResolver& resolver) + : resolver_(resolver) { + DCHECK(!resolver.IsLocked(name)); + resolver_.stack_.push_back(name); +} + +CascadeResolver::AutoLock::~AutoLock() { + resolver_.stack_.pop_back(); + if (resolver_.stack_.size() <= resolver_.cycle_depth_) + resolver_.cycle_depth_ = kNotFound; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/cascade_resolver.h b/third_party/blink/renderer/core/css/resolver/cascade_resolver.h new file mode 100644 index 0000000..8e3e204 --- /dev/null +++ b/third_party/blink/renderer/core/css/resolver/cascade_resolver.h
@@ -0,0 +1,104 @@ +// 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_RESOLVER_CASCADE_RESOLVER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_RESOLVER_H_ + +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_property_name.h" +#include "third_party/blink/renderer/core/css/properties/css_property.h" +#include "third_party/blink/renderer/core/css/resolver/cascade_filter.h" +#include "third_party/blink/renderer/core/css/rule_set.h" + +namespace blink { + +class CSSVariableData; +class CSSProperty; + +namespace cssvalue { + +class CSSPendingSubstitutionValue; + +} // namespace cssvalue + +// CascadeResolver is an object passed on the stack during Apply. Its most +// important job is to detect cycles during Apply (in general, keep track of +// which properties we're currently applying). +class CORE_EXPORT CascadeResolver { + STACK_ALLOCATED(); + + public: + // TODO(crbug.com/985047): Probably use a HashMap for this. + using NameStack = Vector<CSSPropertyName, 8>; + + // A 'locked' property is a property we are in the process of applying. + // In other words, once a property is locked, locking it again would form + // a cycle, and is therefore an error. + bool IsLocked(const CSSProperty&) const; + bool IsLocked(const CSSPropertyName&) const; + + // We do not allow substitution of animation-tainted values into + // an animation-affecting property. + // + // https://drafts.csswg.org/css-variables/#animation-tainted + bool AllowSubstitution(CSSVariableData*) const; + + // Automatically locks and unlocks the given property. (See + // CascadeResolver::IsLocked). + class CORE_EXPORT AutoLock { + STACK_ALLOCATED(); + + public: + AutoLock(const CSSProperty&, CascadeResolver&); + AutoLock(const CSSPropertyName&, CascadeResolver&); + ~AutoLock(); + + private: + CascadeResolver& resolver_; + }; + + private: + friend class AutoLock; + friend class StyleCascade; + friend class TestCascadeResolver; + + CascadeResolver(CascadeFilter filter, uint8_t generation) + : filter_(filter), generation_(generation) {} + + // If the given property is already being applied, returns true. + // The return value is the same value you would get from InCycle(), and + // is just returned for convenience. + // + // When a cycle has been detected, the CascadeResolver will *persist the cycle + // state* (i.e. InCycle() will continue to return true) until we reach + // the start of the cycle. + // + // The cycle state is cleared by ~AutoLock, once we have moved far enough + // up the stack. + bool DetectCycle(const CSSProperty&); + // Returns true whenever the CascadeResolver is in a cycle state. + // This DOES NOT detect cycles; the caller must call DetectCycle first. + bool InCycle() const; + + NameStack stack_; + wtf_size_t cycle_depth_ = kNotFound; + CascadeFilter filter_; + const uint8_t generation_ = 0; + + // A very simple cache for CSSPendingSubstitutionValues. We cache only the + // most recently parsed CSSPendingSubstitutionValue, such that consecutive + // calls to ResolvePendingSubstitution with the same value don't need to + // do the same parsing job all over again. + struct { + STACK_ALLOCATED(); + + public: + const cssvalue::CSSPendingSubstitutionValue* value = nullptr; + HeapVector<CSSPropertyValue, 256> parsed_properties; + } shorthand_cache_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_RESOLVER_CASCADE_RESOLVER_H_
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc index 7eb2e07..545faf87 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/css/property_registry.h" #include "third_party/blink/renderer/core/css/resolver/cascade_expansion.h" #include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h" +#include "third_party/blink/renderer/core/css/resolver/cascade_resolver.h" #include "third_party/blink/renderer/core/css/resolver/css_property_priority.h" #include "third_party/blink/renderer/core/css/resolver/style_builder.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" @@ -96,49 +97,22 @@ } // namespace -void StyleCascade::Analyze(const MatchResult& match_result, - CascadeFilter filter) { - for (auto e : match_result.Expansions(GetDocument(), filter)) { - for (; !e.AtEnd(); e.Next()) - map_.Add(e.Name(), e.Priority()); - } +MatchResult& StyleCascade::MutableMatchResult() { + needs_match_result_analyze_ = true; + return match_result_; } -void StyleCascade::Analyze(const CascadeInterpolations& interpolations, - CascadeFilter filter) { - const auto& entries = interpolations.GetEntries(); - for (size_t i = 0; i < entries.size(); ++i) { - for (const auto& active_interpolation : *entries[i].map) { - uint32_t position = EncodeInterpolationPosition( - i, active_interpolation.key.IsPresentationAttribute()); - CascadePriority priority(entries[i].origin, false, 0, position); - - auto name = active_interpolation.key.GetCSSPropertyName(); - CSSPropertyRef ref(name, GetDocument()); - DCHECK(ref.IsValid()); - const CSSProperty& property = ref.GetProperty(); - - if (filter.Rejects(property)) - continue; - - map_.Add(name, priority); - - // Since an interpolation for an unvisited property also causes an - // interpolation of the visited property, add the visited property to - // the map as well. - // TODO(crbug.com/1062217): Interpolate visited colors separately - if (const CSSProperty* visited = property.GetVisitedProperty()) { - if (!filter.Rejects(*visited)) - map_.Add(visited->GetCSSPropertyName(), priority); - } - } - } +void StyleCascade::AddInterpolations(const ActiveInterpolationsMap* map, + CascadeOrigin origin) { + DCHECK(map); + needs_interpolations_analyze_ = true; + interpolations_.Add(map, origin); } -void StyleCascade::Apply(const MatchResult* match_result, - const CascadeInterpolations* interpolations, - CascadeFilter filter) { - Resolver resolver(filter, match_result, interpolations, ++generation_); +void StyleCascade::Apply(CascadeFilter filter) { + AnalyzeIfNeeded(); + + CascadeResolver resolver(filter, ++generation_); // Affects the computed value of 'color', hence needs to happen before // high-priority properties. @@ -152,13 +126,11 @@ ApplyHighPriority(resolver); - if (match_result) - ApplyMatchResult(*match_result, resolver); - - if (interpolations) - ApplyInterpolations(*interpolations, resolver); + ApplyMatchResult(resolver); + ApplyInterpolations(resolver); if (map_.Find(CSSPropertyName(CSSPropertyID::kWebkitAppearance)) && + !resolver.filter_.Rejects(GetCSSPropertyWebkitAppearance()) && state_.Style()->HasAppearance()) { state_.Style()->SetHasAuthorBackground(HasAuthorBackground()); state_.Style()->SetHasAuthorBorder(HasAuthorBorder()); @@ -167,13 +139,15 @@ void StyleCascade::Reset() { map_.Reset(); + match_result_.Reset(); + interpolations_.Reset(); generation_ = 0; } StyleCascade::Surrogate StyleCascade::ResolveSurrogate( const CSSProperty& surrogate, CascadePriority priority, - Resolver& resolver) { + CascadeResolver& resolver) { DCHECK(surrogate.IsSurrogate()); const CSSProperty* original = surrogate.SurrogateFor( state_.Style()->Direction(), state_.Style()->GetWritingMode()); @@ -186,7 +160,7 @@ const CSSValue* StyleCascade::Resolve(const CSSPropertyName& name, const CSSValue& value, - Resolver& resolver) { + CascadeResolver& resolver) { CSSPropertyRef ref(name, state_.GetDocument()); const CSSValue* resolved = Resolve(ref.GetProperty(), value, resolver); @@ -199,7 +173,50 @@ return resolved; } -void StyleCascade::ApplyHighPriority(Resolver& resolver) { +void StyleCascade::AnalyzeIfNeeded() { + if (needs_match_result_analyze_) { + AnalyzeMatchResult(); + needs_match_result_analyze_ = false; + } + if (needs_interpolations_analyze_) { + AnalyzeInterpolations(); + needs_interpolations_analyze_ = true; + } +} + +void StyleCascade::AnalyzeMatchResult() { + for (auto e : match_result_.Expansions(GetDocument(), CascadeFilter())) { + for (; !e.AtEnd(); e.Next()) + map_.Add(e.Name(), e.Priority()); + } +} + +void StyleCascade::AnalyzeInterpolations() { + const auto& entries = interpolations_.GetEntries(); + for (size_t i = 0; i < entries.size(); ++i) { + for (const auto& active_interpolation : *entries[i].map) { + uint32_t position = EncodeInterpolationPosition( + i, active_interpolation.key.IsPresentationAttribute()); + CascadePriority priority(entries[i].origin, false, 0, position); + + auto name = active_interpolation.key.GetCSSPropertyName(); + CSSPropertyRef ref(name, GetDocument()); + DCHECK(ref.IsValid()); + const CSSProperty& property = ref.GetProperty(); + + map_.Add(name, priority); + + // Since an interpolation for an unvisited property also causes an + // interpolation of the visited property, add the visited property to + // the map as well. + // TODO(crbug.com/1062217): Interpolate visited colors separately + if (const CSSProperty* visited = property.GetVisitedProperty()) + map_.Add(visited->GetCSSPropertyName(), priority); + } + } +} + +void StyleCascade::ApplyHighPriority(CascadeResolver& resolver) { uint64_t bits = map_.HighPriorityBits(); if (bits) { @@ -230,7 +247,7 @@ } } -void StyleCascade::ApplyWebkitBorderImage(Resolver& resolver) { +void StyleCascade::ApplyWebkitBorderImage(CascadeResolver& resolver) { const CascadePriority* priority = map_.Find(CSSPropertyName(CSSPropertyID::kWebkitBorderImage)); if (!priority) @@ -256,9 +273,8 @@ } } -void StyleCascade::ApplyMatchResult(const MatchResult& match_result, - Resolver& resolver) { - for (auto e : match_result.Expansions(GetDocument(), resolver.filter_)) { +void StyleCascade::ApplyMatchResult(CascadeResolver& resolver) { + for (auto e : match_result_.Expansions(GetDocument(), resolver.filter_)) { for (; !e.AtEnd(); e.Next()) { auto priority = CascadePriority(e.Priority(), resolver.generation_); CascadePriority* p = map_.Find(e.Name()); @@ -274,10 +290,8 @@ } } -void StyleCascade::ApplyInterpolations( - const CascadeInterpolations& interpolations, - Resolver& resolver) { - const auto& entries = interpolations.GetEntries(); +void StyleCascade::ApplyInterpolations(CascadeResolver& resolver) { + const auto& entries = interpolations_.GetEntries(); for (size_t i = 0; i < entries.size(); ++i) { const auto& entry = entries[i]; ApplyInterpolationMap(*entry.map, entry.origin, i, resolver); @@ -287,7 +301,7 @@ void StyleCascade::ApplyInterpolationMap(const ActiveInterpolationsMap& map, CascadeOrigin origin, size_t index, - Resolver& resolver) { + CascadeResolver& resolver) { for (const auto& entry : map) { auto name = entry.key.GetCSSPropertyName(); uint32_t position = @@ -319,7 +333,7 @@ const CSSProperty& property, CascadePriority priority, const ActiveInterpolations& interpolations, - Resolver& resolver) { + CascadeResolver& resolver) { const Interpolation& interpolation = *interpolations.front(); if (IsA<InvalidatableInterpolation>(interpolation)) { CSSInterpolationTypesMap map(state_.GetDocument().GetPropertyRegistry(), @@ -355,14 +369,14 @@ } void StyleCascade::LookupAndApply(const CSSPropertyName& name, - Resolver& resolver) { + CascadeResolver& resolver) { CSSPropertyRef ref(name, state_.GetDocument()); DCHECK(ref.IsValid()); LookupAndApply(ref.GetProperty(), resolver); } void StyleCascade::LookupAndApply(const CSSProperty& property, - Resolver& resolver) { + CascadeResolver& resolver) { CSSPropertyName name = property.GetCSSPropertyName(); DCHECK(!resolver.IsLocked(name)); @@ -379,23 +393,17 @@ if (ResolveIfSurrogate(property, priority, resolver) == Surrogate::kSkip) return; - const MatchResult* match_result = resolver.match_result_; - const CascadeInterpolations* interpolations = resolver.interpolations_; - - if (priority.GetOrigin() < CascadeOrigin::kAnimation && match_result) { - LookupAndApplyDeclaration(property, priority, *match_result, resolver); - } else if (priority.GetOrigin() >= CascadeOrigin::kAnimation && - interpolations) { - LookupAndApplyInterpolation(property, priority, *interpolations, resolver); - } + if (priority.GetOrigin() < CascadeOrigin::kAnimation) + LookupAndApplyDeclaration(property, priority, resolver); + else if (priority.GetOrigin() >= CascadeOrigin::kAnimation) + LookupAndApplyInterpolation(property, priority, resolver); } void StyleCascade::LookupAndApplyDeclaration(const CSSProperty& property, CascadePriority priority, - const MatchResult& result, - Resolver& resolver) { + CascadeResolver& resolver) { DCHECK(priority.GetOrigin() < CascadeOrigin::kAnimation); - const CSSValue* value = ValueAt(result, priority.GetPosition()); + const CSSValue* value = ValueAt(match_result_, priority.GetPosition()); DCHECK(value); value = Resolve(property, *value, resolver); DCHECK(!value->IsVariableReferenceValue()); @@ -403,11 +411,9 @@ StyleBuilder::ApplyProperty(property, state_, *value); } -void StyleCascade::LookupAndApplyInterpolation( - const CSSProperty& property, - CascadePriority priority, - const CascadeInterpolations& interpolations, - Resolver& resolver) { +void StyleCascade::LookupAndApplyInterpolation(const CSSProperty& property, + CascadePriority priority, + CascadeResolver& resolver) { // Interpolations for -internal-visited properties are applied via the // interpolation for the main (unvisited) property, so we don't need to // apply it twice. @@ -416,8 +422,8 @@ return; DCHECK(priority.GetOrigin() >= CascadeOrigin::kAnimation); size_t index = DecodeInterpolationIndex(priority.GetPosition()); - DCHECK_LE(index, interpolations.GetEntries().size()); - const ActiveInterpolationsMap& map = *interpolations.GetEntries()[index].map; + DCHECK_LE(index, interpolations_.GetEntries().size()); + const ActiveInterpolationsMap& map = *interpolations_.GetEntries()[index].map; PropertyHandle handle = ToPropertyHandle(property, priority); const auto& entry = map.find(handle); DCHECK_NE(entry, map.end()); @@ -467,7 +473,7 @@ const CSSValue* StyleCascade::Resolve(const CSSProperty& property, const CSSValue& value, - Resolver& resolver) { + CascadeResolver& resolver) { if (const auto* v = DynamicTo<CSSCustomPropertyDeclaration>(value)) return ResolveCustomProperty(property, *v, resolver); if (const auto* v = DynamicTo<CSSVariableReferenceValue>(value)) @@ -480,9 +486,9 @@ const CSSValue* StyleCascade::ResolveCustomProperty( const CSSProperty& property, const CSSCustomPropertyDeclaration& decl, - Resolver& resolver) { + CascadeResolver& resolver) { DCHECK(!resolver.IsLocked(property)); - AutoLock lock(property, resolver); + CascadeResolver::AutoLock lock(property, resolver); // TODO(andruud): Don't transport css-wide keywords in this value. if (!decl.Value()) @@ -512,9 +518,9 @@ const CSSValue* StyleCascade::ResolveVariableReference( const CSSProperty& property, const CSSVariableReferenceValue& value, - Resolver& resolver) { + CascadeResolver& resolver) { DCHECK(!resolver.IsLocked(property)); - AutoLock lock(property, resolver); + CascadeResolver::AutoLock lock(property, resolver); const CSSVariableData* data = value.VariableDataValue(); const CSSParserContext* context = GetParserContext(value); @@ -537,9 +543,9 @@ const CSSValue* StyleCascade::ResolvePendingSubstitution( const CSSProperty& property, const cssvalue::CSSPendingSubstitutionValue& value, - Resolver& resolver) { + CascadeResolver& resolver) { DCHECK(!resolver.IsLocked(property)); - AutoLock lock(property, resolver); + CascadeResolver::AutoLock lock(property, resolver); CascadePriority priority = map_.At(property.GetCSSPropertyName()); DCHECK_NE(property.PropertyID(), CSSPropertyID::kVariable); @@ -600,7 +606,7 @@ scoped_refptr<CSSVariableData> StyleCascade::ResolveVariableData( CSSVariableData* data, - Resolver& resolver) { + CascadeResolver& resolver) { DCHECK(data && data->NeedsVariableResolution()); TokenSequence sequence(data); @@ -612,7 +618,7 @@ } bool StyleCascade::ResolveTokensInto(CSSParserTokenRange range, - Resolver& resolver, + CascadeResolver& resolver, TokenSequence& out) { bool success = true; while (!range.AtEnd()) { @@ -628,7 +634,7 @@ } bool StyleCascade::ResolveVarInto(CSSParserTokenRange range, - Resolver& resolver, + CascadeResolver& resolver, TokenSequence& out) { AtomicString variable_name = ConsumeVariableName(range); DCHECK(range.AtEnd() || (range.Peek().GetType() == kCommaToken)); @@ -690,7 +696,7 @@ } bool StyleCascade::ResolveEnvInto(CSSParserTokenRange range, - Resolver& resolver, + CascadeResolver& resolver, TokenSequence& out) { AtomicString variable_name = ConsumeVariableName(range); DCHECK(range.AtEnd() || (range.Peek().GetType() == kCommaToken)); @@ -771,54 +777,6 @@ state_.Style()->SetHasVariableReferenceFromNonInheritedProperty(); } -bool StyleCascade::Resolver::IsLocked(const CSSProperty& property) const { - return IsLocked(property.GetCSSPropertyName()); -} - -bool StyleCascade::Resolver::IsLocked(const CSSPropertyName& name) const { - return stack_.Contains(name); -} - -bool StyleCascade::Resolver::AllowSubstitution(CSSVariableData* data) const { - if (data && data->IsAnimationTainted() && stack_.size()) { - const CSSPropertyName& name = stack_.back(); - if (name.IsCustomProperty()) - return true; - const CSSProperty& property = CSSProperty::Get(name.Id()); - return !CSSAnimations::IsAnimationAffectingProperty(property); - } - return true; -} - -bool StyleCascade::Resolver::DetectCycle(const CSSProperty& property) { - wtf_size_t index = stack_.Find(property.GetCSSPropertyName()); - if (index == kNotFound) - return false; - cycle_depth_ = std::min(cycle_depth_, index); - return true; -} - -bool StyleCascade::Resolver::InCycle() const { - return cycle_depth_ != kNotFound; -} - -StyleCascade::AutoLock::AutoLock(const CSSProperty& property, - Resolver& resolver) - : AutoLock(property.GetCSSPropertyName(), resolver) {} - -StyleCascade::AutoLock::AutoLock(const CSSPropertyName& name, - Resolver& resolver) - : resolver_(resolver) { - DCHECK(!resolver.IsLocked(name)); - resolver_.stack_.push_back(name); -} - -StyleCascade::AutoLock::~AutoLock() { - resolver_.stack_.pop_back(); - if (resolver_.stack_.size() <= resolver_.cycle_depth_) - resolver_.cycle_depth_ = kNotFound; -} - const Document& StyleCascade::GetDocument() const { return state_.GetDocument(); }
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.h b/third_party/blink/renderer/core/css/resolver/style_cascade.h index 7de7440..22b2c859 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.h +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.h
@@ -13,15 +13,19 @@ #include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/core/css/resolver/cascade_filter.h" +#include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h" #include "third_party/blink/renderer/core/css/resolver/cascade_map.h" #include "third_party/blink/renderer/core/css/resolver/cascade_origin.h" #include "third_party/blink/renderer/core/css/resolver/cascade_priority.h" +#include "third_party/blink/renderer/core/css/resolver/match_result.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { +class CascadeInterpolations; +class CascadeResolver; class CSSCustomPropertyDeclaration; class CSSParserContext; class CSSProperty; @@ -29,9 +33,8 @@ class CSSVariableData; class CSSVariableReferenceValue; class CustomProperty; -class StyleResolverState; class MatchResult; -class CascadeInterpolations; +class StyleResolverState; namespace cssvalue { @@ -39,19 +42,17 @@ } // namespace cssvalue -// StyleCascade can analyze a MatchResult/CascadeInterpolations object to figure -// out which declarations should be skipped (e.g. due to a subsequent -// declaration with a higher priority), and which should be applied. +// StyleCascade analyzes declarations provided by CSS rules and animations, +// and figures out which declarations should be skipped, and which should be +// applied (and in which order). // // Usage: // -// MatchResult result; -// AddRulesSomehow(result); -// // StyleCascade cascade(state); -// CascadeFilter allow_all; -// cascade.Analyze(result, allow_all); -// cascade.Apply(result, allow_all); +// cascade.MutableMatchResult().AddMatchedProperties(...matched rule...); +// cascade.MutableMatchResult().AddMatchedProperties(...another rule...); +// cascade.AddInterpolation(...); // Optional +// cascade.Apply(); // // [1] https://drafts.csswg.org/css-cascade/#cascade class CORE_EXPORT StyleCascade { @@ -60,133 +61,36 @@ using CSSPendingSubstitutionValue = cssvalue::CSSPendingSubstitutionValue; public: - class Resolver; - class AutoLock; - StyleCascade(StyleResolverState& state) : state_(state) {} - // The Analyze pass goes through the MatchResult (or CascadeInterpolations), - // and produces a CascadePriority for each declaration. Each declaration - // is compared against the currently stored priority for the associated - // property, and either added the CascadeMap, or discarded, depending on which - // priority is greater. - // - // Note that the MatchResult/CascadeInterpolations (and their values) are - // not retained by StyleCascade. The caller must provide the same object - // (or a compatible object) when calling Apply. - void Analyze(const MatchResult&, CascadeFilter); - void Analyze(const CascadeInterpolations&, CascadeFilter); + const MatchResult& GetMatchResult() { return match_result_; } - // The Apply pass goes through the MatchResult (or CascadeInterpolations), - // and produces a CascadePriority for each declaration. If the priority of - // the declaration is equal to the priority stored for the associated - // property, then we Apply that declaration to the ComputedStyle. Otherwise, - // the declaration is skipped. - void Apply(const MatchResult& result, CascadeFilter filter) { - Apply(&result, nullptr, filter); - } - void Apply(const CascadeInterpolations& i, CascadeFilter filter) { - Apply(nullptr, &i, filter); - } - // Applying a MatchResult and CascadeInterpolations at the same time means - // that dependency resolution can take place across the two "declaration - // sources". + // Access the MatchResult in order to add declarations to it. + // The modifications made will be taken into account during the next call to + // Apply. // - // For example, if there is an interpolation currently taking place on - // 'font-size', static declarations from the MatchResult object that contain - // 'em' units would be responsive to to that interpolation. This would not be - // the case if two are applied separately. - void Apply(const MatchResult*, const CascadeInterpolations*, CascadeFilter); + // TODO(andruud): ElementRuleCollector could emit MatchedProperties + // directly to the cascade. + MatchResult& MutableMatchResult(); + + // Add ActiveInterpolationsMap to the cascade. The interpolations present + // in the map will be taken into account during the next call to Apply. + // + // Note that it's assumed that the incoming ActiveInterpolationsMap outlives + // the StyleCascade object. + void AddInterpolations(const ActiveInterpolationsMap*, CascadeOrigin); + + // Applies the current CSS declarations and animations to the + // StyleResolverState. + // + // It is valid to call Apply multiple times (up to 15), and each call may + // provide a different filter. + void Apply(CascadeFilter = CascadeFilter()); // Resets the cascade to its initial state. Note that this does not undo // any changes already applied to the StyleResolverState/ComputedStyle. void Reset(); - // Resolver is an object passed on the stack during Apply. Its most important - // job is to detect cycles during Apply (in general, keep track of which - // properties we're currently applying). - class CORE_EXPORT Resolver { - STACK_ALLOCATED(); - - public: - // TODO(crbug.com/985047): Probably use a HashMap for this. - using NameStack = Vector<CSSPropertyName, 8>; - - // A 'locked' property is a property we are in the process of applying. - // In other words, once a property is locked, locking it again would form - // a cycle, and is therefore an error. - bool IsLocked(const CSSProperty&) const; - bool IsLocked(const CSSPropertyName&) const; - - // We do not allow substitution of animation-tainted values into - // an animation-affecting property. - // - // https://drafts.csswg.org/css-variables/#animation-tainted - bool AllowSubstitution(CSSVariableData*) const; - - private: - friend class AutoLock; - friend class StyleCascade; - friend class TestCascadeResolver; - - Resolver(CascadeFilter filter, - const MatchResult* match_result, - const CascadeInterpolations* interpolations, - uint8_t generation) - : filter_(filter), - match_result_(match_result), - interpolations_(interpolations), - generation_(generation) {} - - // If the given property is already being applied, returns true. - // The return value is the same value you would get from InCycle(), and - // is just returned for convenience. - // - // When a cycle has been detected, the Resolver will *persist the cycle - // state* (i.e. InCycle() will continue to return true) until we reach - // the start of the cycle. - // - // The cycle state is cleared by ~AutoLock, once we have moved far enough - // up the stack. - bool DetectCycle(const CSSProperty&); - // Returns true whenever the Resolver is in a cycle state. - // This DOES NOT detect cycles; the caller must call DetectCycle first. - bool InCycle() const; - - NameStack stack_; - wtf_size_t cycle_depth_ = kNotFound; - CascadeFilter filter_; - const MatchResult* match_result_; - const CascadeInterpolations* interpolations_; - const uint8_t generation_ = 0; - - // A very simple cache for CSSPendingSubstitutionValues. We cache only the - // most recently parsed CSSPendingSubstitutionValue, such that consecutive - // calls to ResolvePendingSubstitution with the same value don't need to - // do the same parsing job all over again. - struct { - STACK_ALLOCATED(); - - public: - const CSSPendingSubstitutionValue* value = nullptr; - HeapVector<CSSPropertyValue, 256> parsed_properties; - } shorthand_cache_; - }; - - // Automatically locks and unlocks the given property. (See - // Resolver::IsLocked). - class CORE_EXPORT AutoLock { - STACK_ALLOCATED(); - - public: - AutoLock(const CSSProperty&, Resolver&); - AutoLock(const CSSPropertyName&, Resolver&); - ~AutoLock(); - - private: - Resolver& resolver_; - }; - // Applying interpolations may involve resolving values, since we may be // applying a keyframe from e.g. "color: var(--x)" to "color: var(--y)". // Hence that code needs an entry point to the resolving process. @@ -196,7 +100,9 @@ // StyleCascade, however). // // See documentation the other Resolve* functions for what resolve means. - const CSSValue* Resolve(const CSSPropertyName&, const CSSValue&, Resolver&); + const CSSValue* Resolve(const CSSPropertyName&, + const CSSValue&, + CascadeResolver&); private: friend class TestCascade; @@ -207,17 +113,28 @@ // https://drafts.csswg.org/css-variables/#long-variables static const size_t kMaxSubstitutionTokens = 16384; + // Before we can Apply the cascade, the MatchResult and CascadeInterpolations + // must be Analyzed. This means going through all the declarations, and + // adding them to the CascadeMap, which gives us a complete picture of which + // declarations won the cascade. + // + // We analyze only if needed (i.e. if MatchResult or CascadeInterpolations) + // has been mutated since the last call to AnalyzeIfNeeded. + void AnalyzeIfNeeded(); + void AnalyzeMatchResult(); + void AnalyzeInterpolations(); + // Applies kHighPropertyPriority properties. // // In theory, it would be possible for each property/value that contains // em/ch/etc to dynamically apply font-size (and related properties), but // in practice, it is very inconvenient to detect these dependencies. Hence, // we apply font-affecting properties (among others) before all the others. - void ApplyHighPriority(Resolver&); + void ApplyHighPriority(CascadeResolver&); // Applies -webkit-appearance, and excludes -internal-ua-* properties if // we don't have an appearance. - void ApplyAppearance(Resolver&); + void ApplyAppearance(CascadeResolver&); // Applies -webkit-border-image (if present), and skips any border-image // longhands found with lower priority than -webkit-border-image. @@ -225,30 +142,28 @@ // The -webkit-border-image property is unique (in a bad way), since it's // a surrogate of a shorthand. Therefore it needs special treatment to // behave correctly. - void ApplyWebkitBorderImage(Resolver&); + void ApplyWebkitBorderImage(CascadeResolver&); - void ApplyMatchResult(const MatchResult&, Resolver&); - void ApplyInterpolations(const CascadeInterpolations&, Resolver&); + void ApplyMatchResult(CascadeResolver&); + void ApplyInterpolations(CascadeResolver&); void ApplyInterpolationMap(const ActiveInterpolationsMap&, CascadeOrigin, size_t index, - Resolver&); + CascadeResolver&); void ApplyInterpolation(const CSSProperty&, CascadePriority, const ActiveInterpolations&, - Resolver&); + CascadeResolver&); // Looks up a value with random access, and applies it. - void LookupAndApply(const CSSPropertyName&, Resolver&); - void LookupAndApply(const CSSProperty&, Resolver&); + void LookupAndApply(const CSSPropertyName&, CascadeResolver&); + void LookupAndApply(const CSSProperty&, CascadeResolver&); void LookupAndApplyDeclaration(const CSSProperty&, CascadePriority, - const MatchResult&, - Resolver&); + CascadeResolver&); void LookupAndApplyInterpolation(const CSSProperty&, CascadePriority, - const CascadeInterpolations&, - Resolver&); + CascadeResolver&); // Whether or not we are calculating the style for the root element. // We need to know this to detect cycles with 'rem' units. @@ -336,11 +251,13 @@ // Surrogate properties should be skipped (i.e. not applied after all) if // the corresponding original property has a higher priority. // - Surrogate ResolveSurrogate(const CSSProperty&, CascadePriority, Resolver&); + Surrogate ResolveSurrogate(const CSSProperty&, + CascadePriority, + CascadeResolver&); inline Surrogate ResolveIfSurrogate(const CSSProperty& property, CascadePriority priority, - Resolver& resolver) { + CascadeResolver& resolver) { if (!property.IsSurrogate()) return Surrogate::kNoSurrogate; return ResolveSurrogate(property, priority, resolver); @@ -363,19 +280,21 @@ // other words, we must first Apply '--y'. Hence, resolving 'width' will // Apply '--y' as a side-effect. (This process would then continue to '--x'). - const CSSValue* Resolve(const CSSProperty&, const CSSValue&, Resolver&); + const CSSValue* Resolve(const CSSProperty&, + const CSSValue&, + CascadeResolver&); const CSSValue* ResolveCustomProperty(const CSSProperty&, const CSSCustomPropertyDeclaration&, - Resolver&); + CascadeResolver&); const CSSValue* ResolveVariableReference(const CSSProperty&, const CSSVariableReferenceValue&, - Resolver&); + CascadeResolver&); const CSSValue* ResolvePendingSubstitution(const CSSProperty&, const CSSPendingSubstitutionValue&, - Resolver&); + CascadeResolver&); scoped_refptr<CSSVariableData> ResolveVariableData(CSSVariableData*, - Resolver&); + CascadeResolver&); // The Resolve*Into functions either resolve dependencies, append to the // TokenSequence accordingly, and return true; or it returns false when @@ -385,9 +304,9 @@ // // [1] https://drafts.csswg.org/css-variables/#invalid-at-computed-value-time - bool ResolveTokensInto(CSSParserTokenRange, Resolver&, TokenSequence&); - bool ResolveVarInto(CSSParserTokenRange, Resolver&, TokenSequence&); - bool ResolveEnvInto(CSSParserTokenRange, Resolver&, TokenSequence&); + bool ResolveTokensInto(CSSParserTokenRange, CascadeResolver&, TokenSequence&); + bool ResolveVarInto(CSSParserTokenRange, CascadeResolver&, TokenSequence&); + bool ResolveEnvInto(CSSParserTokenRange, CascadeResolver&, TokenSequence&); CSSVariableData* GetVariableData(const CustomProperty&) const; CSSVariableData* GetEnvironmentVariable(const AtomicString&) const; @@ -417,6 +336,8 @@ bool HasAuthorBackground() const; StyleResolverState& state_; + MatchResult match_result_; + CascadeInterpolations interpolations_; CascadeMap map_; // Generational Apply // @@ -457,6 +378,9 @@ // enough for our needs. uint8_t generation_ = 0; + bool needs_match_result_analyze_ = false; + bool needs_interpolations_analyze_ = false; + DISALLOW_COPY_AND_ASSIGN(StyleCascade); };
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc index 37eb866e..e9384e5 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h" #include "third_party/blink/renderer/core/css/resolver/cascade_map.h" #include "third_party/blink/renderer/core/css/resolver/cascade_priority.h" +#include "third_party/blink/renderer/core/css/resolver/cascade_resolver.h" #include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/css/style_engine.h" @@ -67,39 +68,15 @@ state_.StyleRef().InheritFrom(*parent); } - // TestCascade has two main APIs: - - // 1. Direct Analyze & Apply. This is a simple wrapper for Analyze & Apply - // on the inner cascade. - - void Analyze(const MatchResult& result, - CascadeFilter filter = CascadeFilter()) { - cascade_.Analyze(result, filter); - } - - void Apply(const MatchResult& result, - CascadeFilter filter = CascadeFilter()) { - cascade_.Apply(result, filter); - } - - // 2. "Add" API. This allows the caller to build a MatchResult from strings. - // - // TestCascade cascade(GetDocument()); - // cascade.Add("color:green;top:1px", CascadeOrigin::kUserAgent); - // cascade.Add("color:red"); - // cascade.Apply(); - // - // The Add() functions will parse the declaration blocks and add the result - // to an internal MatchResult object. The param-less Apply() function will - // then Analyze that MatchResult and immediately Apply it. - // // Note that because of how MatchResult works, declarations must be added // in "origin order", i.e. UserAgent first, then User, then Author. - void Add(String block, CascadeOrigin origin = CascadeOrigin::kAuthor) { + void Add(String block, + CascadeOrigin origin = CascadeOrigin::kAuthor, + unsigned link_match_type = CSSSelector::kMatchAll) { CSSParserMode mode = origin == CascadeOrigin::kUserAgent ? kUASheetMode : kHTMLStandardMode; - Add(ParseDeclarationBlock(block, mode), origin, CSSSelector::kMatchAll); + Add(ParseDeclarationBlock(block, mode), origin, link_match_type); } void Add(String name, String value, CascadeOrigin origin = Origin::kAuthor) { @@ -112,16 +89,12 @@ DCHECK_LE(origin, CascadeOrigin::kAuthor) << "Animations not supported"; DCHECK_LE(current_origin_, origin) << "Please add declarations in order"; EnsureAtLeast(origin); - match_result_.AddMatchedProperties(set, link_match_type); + cascade_.MutableMatchResult().AddMatchedProperties(set, link_match_type); } void Apply(CascadeFilter filter = CascadeFilter()) { EnsureAtLeast(CascadeOrigin::kAuthor); - cascade_.Analyze(match_result_, filter); - auto interpolations = GetInterpolations(); - cascade_.Apply(&match_result_, - interpolations.IsEmpty() ? nullptr : &interpolations, - filter); + cascade_.Apply(filter); } String ComputedValue(String name) const { @@ -153,6 +126,7 @@ CSSAnimations::CalculateTransitionUpdate( state_.AnimationUpdate(), CSSAnimations::PropertyPass::kStandard, &state_.GetElement(), *state_.Style()); + AddTransitions(); } void CalculateAnimationUpdate() { @@ -160,15 +134,7 @@ state_.AnimationUpdate(), &state_.GetElement(), state_.GetElement(), *state_.Style(), state_.ParentStyle(), &GetDocument().EnsureStyleResolver()); - } - - void AnalyzeAnimations(CascadeFilter filter = CascadeFilter()) { - CalculateAnimationUpdate(); - cascade_.Analyze(GetInterpolations(), filter); - } - void AnalyzeTransitions(CascadeFilter filter = CascadeFilter()) { - CalculateTransitionUpdate(); - cascade_.Analyze(GetInterpolations(), filter); + AddAnimations(); } void Reset() { cascade_.Reset(); } @@ -190,11 +156,11 @@ void FinishOrigin() { switch (current_origin_) { case CascadeOrigin::kUserAgent: - match_result_.FinishAddingUARules(); + cascade_.MutableMatchResult().FinishAddingUARules(); current_origin_ = CascadeOrigin::kUser; break; case CascadeOrigin::kUser: - match_result_.FinishAddingUserRules(); + cascade_.MutableMatchResult().FinishAddingUserRules(); current_origin_ = CascadeOrigin::kAuthor; break; case CascadeOrigin::kAuthor: @@ -209,25 +175,31 @@ FinishOrigin(); } - CascadeInterpolations GetInterpolations() { + void AddAnimations() { const auto& update = state_.AnimationUpdate(); if (update.IsEmpty()) - return CascadeInterpolations(); - using Entry = CascadeInterpolations::Entry; - return CascadeInterpolations(Vector<Entry, 4>({ - Entry{&update.ActiveInterpolationsForCustomAnimations(), - CascadeOrigin::kAnimation}, - Entry{&update.ActiveInterpolationsForStandardAnimations(), - CascadeOrigin::kAnimation}, - Entry{&update.ActiveInterpolationsForCustomTransitions(), - CascadeOrigin::kTransition}, - Entry{&update.ActiveInterpolationsForStandardTransitions(), - CascadeOrigin::kTransition}, - })); + return; + cascade_.AddInterpolations( + &update.ActiveInterpolationsForCustomAnimations(), + CascadeOrigin::kAnimation); + cascade_.AddInterpolations( + &update.ActiveInterpolationsForStandardAnimations(), + CascadeOrigin::kAnimation); + } + + void AddTransitions() { + const auto& update = state_.AnimationUpdate(); + if (update.IsEmpty()) + return; + cascade_.AddInterpolations( + &update.ActiveInterpolationsForCustomTransitions(), + CascadeOrigin::kTransition); + cascade_.AddInterpolations( + &update.ActiveInterpolationsForStandardTransitions(), + CascadeOrigin::kTransition); } CascadeOrigin current_origin_ = CascadeOrigin::kUserAgent; - MatchResult match_result_; StyleResolverState state_; StyleCascade cascade_; }; @@ -237,7 +209,7 @@ public: explicit TestCascadeResolver(Document& document) - : document_(document), resolver_(CascadeFilter(), nullptr, nullptr, 0) {} + : document_(document), resolver_(CascadeFilter(), 0) {} bool InCycle() const { return resolver_.InCycle(); } bool DetectCycle(String name) { CSSPropertyRef ref(name, document_); @@ -251,7 +223,7 @@ friend class TestCascadeAutoLock; Document& document_; - StyleCascade::Resolver resolver_; + CascadeResolver resolver_; }; class TestCascadeAutoLock { @@ -263,7 +235,7 @@ : lock_(name, resolver.resolver_) {} private: - StyleCascade::AutoLock lock_; + CascadeResolver::AutoLock lock_; }; class StyleCascadeTest : public PageTestBase, private ScopedCSSCascadeForTest { @@ -1421,7 +1393,7 @@ EXPECT_EQ("rgb(255, 0, 0)", cascade.ComputedValue("background-color")); } -TEST_F(StyleCascadeTest, AnimationAnalyzeFilter) { +TEST_F(StyleCascadeTest, AnimationApplyFilter) { AppendSheet(R"HTML( @keyframes test { from { color: white; background-color: white; } @@ -1431,20 +1403,22 @@ TestCascade cascade(GetDocument()); - cascade.Add("animation: test 1s"); + cascade.Add("animation: test linear 10s -5s"); + cascade.Add("color:green"); cascade.Apply(); - cascade.AnalyzeAnimations(CascadeFilter(CSSProperty::kInherited, true)); + cascade.CalculateAnimationUpdate(); + cascade.Apply(CascadeFilter(CSSProperty::kInherited, true)); - EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("background-color")); - EXPECT_EQ(CascadeOrigin::kNone, cascade.GetOrigin("color")); + EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color")); + EXPECT_EQ("rgb(192, 192, 192)", cascade.ComputedValue("background-color")); } -TEST_F(StyleCascadeTest, TransitionAnalyzeFilter) { +TEST_F(StyleCascadeTest, TransitionApplyFilter) { TestCascade cascade1(GetDocument()); cascade1.Add("background-color: white"); cascade1.Add("color: white"); - cascade1.Add("transition: all 1s"); + cascade1.Add("transition: all steps(2, start) 100s"); cascade1.Apply(); // Set the old style on the element, so that the transition @@ -1455,13 +1429,14 @@ TestCascade cascade2(GetDocument()); cascade2.Add("background-color: gray"); cascade2.Add("color: gray"); - cascade2.Add("transition: all 1s"); + cascade2.Add("transition: all steps(2, start) 100s"); cascade2.Apply(); - cascade2.AnalyzeTransitions(CascadeFilter(CSSProperty::kInherited, true)); + cascade2.CalculateTransitionUpdate(); + cascade2.Apply(CascadeFilter(CSSProperty::kInherited, true)); - EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("background-color")); - EXPECT_EQ(CascadeOrigin::kAuthor, cascade2.GetOrigin("color")); + EXPECT_EQ("rgb(128, 128, 128)", cascade2.ComputedValue("color")); + EXPECT_EQ("rgb(192, 192, 192)", cascade2.ComputedValue("background-color")); } TEST_F(StyleCascadeTest, PendingKeyframeAnimation) { @@ -1480,7 +1455,8 @@ cascade.Add("animation-duration", "1s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); + cascade.Apply(); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin()); } @@ -1503,10 +1479,10 @@ cascade.Add("animation-delay", "-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); + cascade.Apply(); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetPriority("--x").GetOrigin()); - cascade.Apply(); EXPECT_EQ("15px", cascade.ComputedValue("--x")); } @@ -1529,7 +1505,8 @@ cascade2.Add("transition", "--x 1s"); cascade2.Apply(); - cascade2.AnalyzeTransitions(); + cascade2.CalculateTransitionUpdate(); + cascade2.Apply(); EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetPriority("--x").GetOrigin()); @@ -1556,7 +1533,8 @@ cascade2.Add("transition", "--x 1s, width 1s"); cascade2.Apply(); - cascade2.AnalyzeTransitions(); + cascade2.CalculateTransitionUpdate(); + cascade2.Apply(); EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("--x")); EXPECT_EQ(CascadeOrigin::kTransition, cascade2.GetOrigin("width")); @@ -1581,7 +1559,7 @@ cascade.Add("animation-delay", "-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Add("--from", "10px"); cascade.Add("--to", "20px"); cascade.Add("--y", "var(--x)"); @@ -1607,10 +1585,10 @@ cascade.Add("animation-delay", "-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); - EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width")); - + cascade.CalculateAnimationUpdate(); cascade.Apply(); + + EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width")); EXPECT_EQ("15px", cascade.ComputedValue("width")); } @@ -1632,11 +1610,12 @@ cascade.Add("height:40px !important"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); + cascade.Apply(); + EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("width")); EXPECT_EQ(CascadeOrigin::kAuthor, cascade.GetOrigin("height")); - cascade.Apply(); EXPECT_EQ("15px", cascade.ComputedValue("width")); EXPECT_EQ("40px", cascade.ComputedValue("height")); } @@ -1660,7 +1639,7 @@ cascade2.Add("transition:all 1s"); cascade2.Apply(); - cascade2.AnalyzeTransitions(); + cascade2.CalculateTransitionUpdate(); cascade2.Apply(); EXPECT_EQ(CascadeOrigin::kTransition, @@ -1687,7 +1666,7 @@ cascade.Add("animation-delay", "-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Add("--x", "2em"); cascade.Add("width", "10em"); @@ -1714,7 +1693,7 @@ cascade.Add("animation-delay", "-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Add("--from", "10px"); cascade.Add("--to", "20px"); @@ -1740,13 +1719,14 @@ cascade.Add("animation-delay", "-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); + cascade.Apply(); + EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top")); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-right")); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-bottom")); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left")); - cascade.Apply(); EXPECT_EQ("15px", cascade.ComputedValue("margin-top")); EXPECT_EQ("15px", cascade.ComputedValue("margin-right")); EXPECT_EQ("15px", cascade.ComputedValue("margin-bottom")); @@ -1772,7 +1752,7 @@ cascade.Add("animation-delay:-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Apply(); EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("background-color")); @@ -1800,7 +1780,7 @@ cascade.Add("animation:test 10s -5s linear"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Apply(); EXPECT_EQ("rgb(150, 150, 150)", cascade.ComputedValue("color")); @@ -1829,7 +1809,7 @@ cascade.Apply(); EXPECT_FALSE(cascade.State().HasImportantOverrides()); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Apply(); EXPECT_TRUE(cascade.State().HasImportantOverrides()); } @@ -1848,7 +1828,7 @@ cascade.Apply(); EXPECT_FALSE(cascade.State().HasImportantOverrides()); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Apply(); EXPECT_FALSE(cascade.State().HasImportantOverrides()); } @@ -1868,7 +1848,7 @@ cascade.Apply(); EXPECT_FALSE(cascade.State().HasImportantOverrides()); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Apply(); EXPECT_TRUE(cascade.State().HasImportantOverrides()); } @@ -1890,7 +1870,7 @@ cascade.Apply(); EXPECT_FALSE(cascade.State().HasImportantOverrides()); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Apply(); EXPECT_TRUE(cascade.State().HasImportantOverrides()); } @@ -1913,16 +1893,16 @@ cascade.Add("animation-delay", "-5s"); cascade.Apply(); - cascade.AnalyzeAnimations(); + cascade.CalculateAnimationUpdate(); cascade.Add("--from", "10px"); cascade.Add("--to", "20px"); + cascade.Apply(); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-top")); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-right")); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-bottom")); EXPECT_EQ(CascadeOrigin::kAnimation, cascade.GetOrigin("margin-left")); - cascade.Apply(); EXPECT_EQ("15px", cascade.ComputedValue("margin-top")); EXPECT_EQ("15px", cascade.ComputedValue("margin-right")); EXPECT_EQ("15px", cascade.ComputedValue("margin-bottom")); @@ -2153,18 +2133,12 @@ } TEST_F(StyleCascadeTest, InternalVisitedColorLonghand) { - MatchResult result; - result.FinishAddingUARules(); - result.FinishAddingUserRules(); - result.AddMatchedProperties(ParseDeclarationBlock("color:green")); - result.AddMatchedProperties(ParseDeclarationBlock("color:red"), - CSSSelector::kMatchVisited); - result.FinishAddingAuthorRulesForTreeScope(); - TestCascade cascade(GetDocument()); + cascade.Add("color:green", CascadeOrigin::kAuthor); + cascade.Add("color:red", CascadeOrigin::kAuthor, CSSSelector::kMatchVisited); + cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink); - cascade.Analyze(result); - cascade.Apply(result); + cascade.Apply(); EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color")); @@ -2174,21 +2148,15 @@ } TEST_F(StyleCascadeTest, VarInInternalVisitedColorShorthand) { - MatchResult result; - result.FinishAddingUARules(); - result.FinishAddingUserRules(); - result.AddMatchedProperties(ParseDeclarationBlock("--x:red")); - result.AddMatchedProperties( - ParseDeclarationBlock("outline:medium solid var(--x)"), - CSSSelector::kMatchVisited); - result.AddMatchedProperties(ParseDeclarationBlock("outline-color:green"), - CSSSelector::kMatchLink); - result.FinishAddingAuthorRulesForTreeScope(); - TestCascade cascade(GetDocument()); + cascade.Add("--x:red", CascadeOrigin::kAuthor); + cascade.Add("outline:medium solid var(--x)", CascadeOrigin::kAuthor, + CSSSelector::kMatchVisited); + cascade.Add("outline-color:green", CascadeOrigin::kAuthor, + CSSSelector::kMatchLink); + cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink); - cascade.Analyze(result); - cascade.Apply(result); + cascade.Apply(); EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("outline-color")); @@ -2213,10 +2181,10 @@ } TEST_F(StyleCascadeTest, HasAuthorBackground) { - Vector<String> properties = {"background-attachment", "background-blend-mode", + Vector<String> properties = {"background-attachment"/*, "background-blend-mode", "background-clip", "background-image", "background-origin", "background-position-x", - "background-position-y", "background-size"}; + "background-position-y", "background-size"*/}; for (String property : properties) { TestCascade cascade(GetDocument()); @@ -2264,23 +2232,16 @@ } TEST_F(StyleCascadeTest, AnalyzeMatchResult) { - TestCascade cascade(GetDocument()); - - MatchResult result; - result.AddMatchedProperties(ParseDeclarationBlock("display:none;left:5px")); - result.AddMatchedProperties( - ParseDeclarationBlock("font-size:1px !important")); - result.FinishAddingUARules(); - result.FinishAddingUserRules(); - result.AddMatchedProperties(ParseDeclarationBlock("display:block;color:red")); - result.AddMatchedProperties(ParseDeclarationBlock("font-size:3px")); - result.FinishAddingAuthorRulesForTreeScope(); - - cascade.Analyze(result); - auto ua = CascadeOrigin::kUserAgent; auto author = CascadeOrigin::kAuthor; + TestCascade cascade(GetDocument()); + cascade.Add("display:none;left:5px", ua); + cascade.Add("font-size:1px !important", ua); + cascade.Add("display:block;color:red", author); + cascade.Add("font-size:3px", author); + cascade.Apply(); + EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author); EXPECT_EQ(cascade.GetPriority("left").GetOrigin(), ua); EXPECT_EQ(cascade.GetPriority("color").GetOrigin(), author); @@ -2288,22 +2249,15 @@ } TEST_F(StyleCascadeTest, AnalyzeMatchResultAll) { - TestCascade cascade(GetDocument()); - - MatchResult result; - result.AddMatchedProperties(ParseDeclarationBlock("display:block")); - result.AddMatchedProperties( - ParseDeclarationBlock("font-size:1px !important")); - result.FinishAddingUARules(); - result.FinishAddingUserRules(); - result.AddMatchedProperties(ParseDeclarationBlock("all:unset")); - result.FinishAddingAuthorRulesForTreeScope(); - - cascade.Analyze(result); - auto ua = CascadeOrigin::kUserAgent; auto author = CascadeOrigin::kAuthor; + TestCascade cascade(GetDocument()); + cascade.Add("display:block", ua); + cascade.Add("font-size:1px !important", ua); + cascade.Add("all:unset", author); + cascade.Apply(); + EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author); EXPECT_EQ(cascade.GetPriority("font-size").GetOrigin(), ua); @@ -2312,44 +2266,33 @@ EXPECT_EQ(cascade.GetPriority("color"), cascade.GetPriority("display")); } -TEST_F(StyleCascadeTest, AnalyzeMatchResultFilter) { +TEST_F(StyleCascadeTest, ApplyMatchResultFilter) { TestCascade cascade(GetDocument()); + cascade.Add("display:block"); + cascade.Add("color:green"); + cascade.Add("font-size:3px"); + cascade.Apply(); - MatchResult result; - result.FinishAddingUARules(); - result.FinishAddingUserRules(); - result.AddMatchedProperties(ParseDeclarationBlock("display:block")); - result.AddMatchedProperties(ParseDeclarationBlock("color:red")); - result.AddMatchedProperties(ParseDeclarationBlock("font-size:3px")); - result.FinishAddingAuthorRulesForTreeScope(); + cascade.Add("display:inline"); + cascade.Add("color:red"); + cascade.Apply(CascadeFilter(CSSProperty::kInherited, true)); - cascade.Analyze(result, CascadeFilter(CSSProperty::kInherited, true)); - - auto none = CascadeOrigin::kNone; - auto author = CascadeOrigin::kAuthor; - - EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author); - EXPECT_EQ(cascade.GetPriority("color").GetOrigin(), none); - EXPECT_EQ(cascade.GetPriority("font-size").GetOrigin(), none); + EXPECT_EQ("inline", cascade.ComputedValue("display")); + EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color")); + EXPECT_EQ("3px", cascade.ComputedValue("font-size")); } -TEST_F(StyleCascadeTest, AnalyzeMatchResultAllFilter) { +TEST_F(StyleCascadeTest, ApplyMatchResultAllFilter) { TestCascade cascade(GetDocument()); + cascade.Add("color:green"); + cascade.Add("display:block"); + cascade.Apply(); - MatchResult result; - result.FinishAddingUARules(); - result.FinishAddingUserRules(); - result.AddMatchedProperties(ParseDeclarationBlock("all:unset")); - result.FinishAddingAuthorRulesForTreeScope(); + cascade.Add("all:unset"); + cascade.Apply(CascadeFilter(CSSProperty::kInherited, true)); - cascade.Analyze(result, CascadeFilter(CSSProperty::kInherited, true)); - - auto none = CascadeOrigin::kNone; - auto author = CascadeOrigin::kAuthor; - - EXPECT_EQ(cascade.GetPriority("display").GetOrigin(), author); - EXPECT_EQ(cascade.GetPriority("color").GetOrigin(), none); - EXPECT_EQ(cascade.GetPriority("font-size").GetOrigin(), none); + EXPECT_EQ("rgb(0, 128, 0)", cascade.ComputedValue("color")); + EXPECT_EQ("inline", cascade.ComputedValue("display")); } TEST_F(StyleCascadeTest, MarkHasReferenceLonghand) {
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 ac4742a..366a27a 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -61,7 +61,6 @@ #include "third_party/blink/renderer/core/css/part_names.h" #include "third_party/blink/renderer/core/css/properties/css_property.h" #include "third_party/blink/renderer/core/css/properties/css_property_ref.h" -#include "third_party/blink/renderer/core/css/resolver/cascade_interpolations.h" #include "third_party/blink/renderer/core/css/resolver/css_variable_animator.h" #include "third_party/blink/renderer/core/css/resolver/css_variable_resolver.h" #include "third_party/blink/renderer/core/css/resolver/match_result.h" @@ -173,16 +172,14 @@ } // When force-computing the base computed style for validation purposes, -// we need to reset the StyleCascade/MatchResult when the base computed style -// optimization is used. This is because we don't want the computation of -// the base to populate the cascade/MatchResult, as they are supposed to be -// empty when the optimization is in use. This is to match the behavior of -// non-DCHECK builds. -void MaybeResetCascade(StyleCascade* cascade, MatchResult& match_result) { +// we need to reset the StyleCascade when the base computed style optimization +// is used. This is because we don't want the computation of the base to +// populate the cascade, as they are supposed to be empty when the optimization +// is in use. This is to match the behavior of non-DCHECK builds. +void MaybeResetCascade(StyleCascade* cascade) { #if DCHECK_IS_ON() if (cascade) cascade->Reset(); - match_result.Reset(); #endif // DCHECK_IS_ON() } @@ -831,12 +828,11 @@ StyleCascade* cascade_ptr = RuntimeEnabledFeatures::CSSCascadeEnabled() ? &cascade : nullptr; - MatchResult match_result; - ApplyBaseComputedStyle(element, state, cascade_ptr, match_result, - matching_behavior, + ApplyBaseComputedStyle(element, state, cascade_ptr, + cascade.MutableMatchResult(), matching_behavior, can_cache_animation_base_computed_style); - if (ApplyAnimatedStandardProperties(state, match_result, cascade_ptr)) { + if (ApplyAnimatedStandardProperties(state, cascade_ptr)) { INCREMENT_STYLE_STATS_COUNTER(GetDocument().GetStyleEngine(), styles_animated, 1); StyleAdjuster::AdjustComputedStyle(state, element); @@ -967,7 +963,7 @@ if (RuntimeEnabledFeatures::CSSCascadeEnabled()) { DCHECK(cascade); - CascadeAndApplyMatchedProperties(state, *cascade, match_result); + CascadeAndApplyMatchedProperties(state, *cascade); } else { ApplyMatchedProperties(state, match_result); } @@ -993,7 +989,7 @@ state.SetParentStyle(InitialStyleForElement(GetDocument())); state.SetLayoutParentStyle(state.ParentStyle()); } - MaybeResetCascade(cascade, match_result); + MaybeResetCascade(cascade); INCREMENT_STYLE_STATS_COUNTER(GetDocument().GetStyleEngine(), base_styles_used, 1); } @@ -1012,15 +1008,12 @@ state.SetStyle(ComputedStyle::Clone(base_style)); if (value) { if (RuntimeEnabledFeatures::CSSCascadeEnabled()) { - MatchResult result; + STACK_UNINITIALIZED StyleCascade cascade(state); auto* set = MakeGarbageCollected<MutableCSSPropertyValueSet>( state.GetParserMode()); set->SetProperty(property.GetCSSProperty().PropertyID(), *value); - result.AddMatchedProperties(set); - - STACK_UNINITIALIZED StyleCascade cascade(state); - cascade.Analyze(result, CascadeFilter()); - cascade.Apply(result, CascadeFilter()); + cascade.MutableMatchResult().AddMatchedProperties(set); + cascade.Apply(); } else { StyleBuilder::ApplyProperty(property.GetCSSPropertyName(), state, *value); state.GetFontBuilder().CreateFont( @@ -1052,7 +1045,6 @@ StyleCascade* cascade_ptr = RuntimeEnabledFeatures::CSSCascadeEnabled() ? &cascade : nullptr; - MatchResult match_result; if (ShouldComputeBaseComputedStyle(animation_base_computed_style)) { if (pseudo_style_request.AllowsInheritance(state.ParentStyle())) { scoped_refptr<ComputedStyle> style = ComputedStyle::Create(); @@ -1070,7 +1062,7 @@ // Check UA, user and author rules. ElementRuleCollector collector(state.ElementContext(), selector_filter_, - match_result, state.Style(), + cascade.MutableMatchResult(), state.Style(), state.Style()->InsideLink()); collector.SetPseudoElementStyleRequest(pseudo_style_request); @@ -1108,9 +1100,9 @@ } if (RuntimeEnabledFeatures::CSSCascadeEnabled()) - CascadeAndApplyMatchedProperties(state, cascade, match_result); + CascadeAndApplyMatchedProperties(state, cascade); else - ApplyMatchedProperties(state, match_result); + ApplyMatchedProperties(state, cascade.GetMatchResult()); ApplyCallbackSelectors(state); @@ -1131,10 +1123,10 @@ if (animation_base_computed_style) { state.SetStyle(ComputedStyle::Clone(*animation_base_computed_style)); state.Style()->SetStyleType(pseudo_style_request.pseudo_id); - MaybeResetCascade(cascade_ptr, match_result); + MaybeResetCascade(cascade_ptr); } - if (ApplyAnimatedStandardProperties(state, match_result, cascade_ptr)) + if (ApplyAnimatedStandardProperties(state, cascade_ptr)) StyleAdjuster::AdjustComputedStyle(state, nullptr); GetDocument().GetStyleEngine().IncStyleForElementCount(); @@ -1193,7 +1185,10 @@ style->InheritFrom(*root_element_style); state.SetStyle(std::move(style)); - PageRuleCollector collector(root_element_style, page_index); + STACK_UNINITIALIZED StyleCascade cascade(state); + + PageRuleCollector collector(root_element_style, page_index, + cascade.MutableMatchResult()); collector.MatchPageRules( CSSDefaultStyleSheets::Instance().DefaultPrintStyle()); @@ -1208,9 +1203,7 @@ const MatchResult& result = collector.MatchedResult(); if (RuntimeEnabledFeatures::CSSCascadeEnabled()) { - StyleCascade cascade(state); - cascade.Analyze(result, CascadeFilter()); - cascade.Apply(result, CascadeFilter()); + cascade.Apply(); } else { ApplyMatchedProperties<kAnimationPropertyPriority, kUpdateNeedsApplyPass>( state, result.AllRules(), false, inherited_only, needs_apply_pass); @@ -1347,7 +1340,6 @@ bool StyleResolver::ApplyAnimatedStandardProperties( StyleResolverState& state, - const MatchResult& match_result, StyleCascade* cascade) { Element& element = state.GetElement(); @@ -1388,22 +1380,20 @@ if (RuntimeEnabledFeatures::CSSCascadeEnabled()) { DCHECK(cascade); - CascadeFilter filter; + cascade->AddInterpolations(&standard_animations, CascadeOrigin::kAnimation); + cascade->AddInterpolations(&standard_transitions, + CascadeOrigin::kTransition); + cascade->AddInterpolations(&custom_animations, CascadeOrigin::kAnimation); + cascade->AddInterpolations(&custom_transitions, CascadeOrigin::kTransition); - using Entry = CascadeInterpolations::Entry; - class CascadeInterpolations interpolations(Vector<Entry, 4>{ - Entry{&standard_animations, CascadeOrigin::kAnimation}, - Entry{&standard_transitions, CascadeOrigin::kTransition}, - Entry{&custom_animations, CascadeOrigin::kAnimation}, - Entry{&custom_transitions, CascadeOrigin::kTransition}, - }); + CascadeFilter filter; if (IsForcedColorsModeEnabled(state)) filter = filter.Add(CSSProperty::kIsAffectedByForcedColors, true); if (state.Style()->StyleType() == kPseudoIdMarker) filter = filter.Add(CSSProperty::kValidForMarker, false); filter = filter.Add(CSSProperty::kAnimation, true); - cascade->Analyze(interpolations, filter); - cascade->Apply(&match_result, &interpolations, filter); + + cascade->Apply(filter); } else { ApplyAnimatedStandardProperties<kHighPropertyPriority>(state, standard_animations); @@ -2105,22 +2095,16 @@ Element& element, ActiveInterpolationsMap& interpolations) { StyleResolverState state(GetDocument(), element); - - MatchResult match_result; STACK_UNINITIALIZED StyleCascade cascade(state); if (RuntimeEnabledFeatures::CSSCascadeEnabled()) { - ApplyBaseComputedStyle(&element, state, &cascade, match_result, - kMatchAllRules, true); - using Entry = CascadeInterpolations::Entry; - class CascadeInterpolations cascade_interpolations(Vector<Entry, 4>({ - Entry{&interpolations, CascadeOrigin::kAnimation}, - })); - cascade.Analyze(cascade_interpolations, CascadeFilter()); - cascade.Apply(&match_result, &cascade_interpolations, CascadeFilter()); + ApplyBaseComputedStyle(&element, state, &cascade, + cascade.MutableMatchResult(), kMatchAllRules, true); + cascade.AddInterpolations(&interpolations, CascadeOrigin::kAnimation); + cascade.Apply(); } else { - ApplyBaseComputedStyle(&element, state, nullptr /* cascade */, match_result, - kMatchAllRules, true); + ApplyBaseComputedStyle(&element, state, nullptr /* cascade */, + cascade.MutableMatchResult(), kMatchAllRules, true); ApplyAnimatedStandardProperties<kHighPropertyPriority>(state, interpolations); UpdateFont(state); @@ -2131,31 +2115,22 @@ return state.TakeStyle(); } -void StyleResolver::CascadeAndApplyMatchedProperties( - StyleResolverState& state, - StyleCascade& cascade, - const MatchResult& result) { +void StyleResolver::CascadeAndApplyMatchedProperties(StyleResolverState& state, + StyleCascade& cascade) { DCHECK(RuntimeEnabledFeatures::CSSCascadeEnabled()); + const MatchResult& result = cascade.GetMatchResult(); CacheSuccess cache_success = ApplyMatchedCache(state, result); - CascadeFilter filter; - if (cache_success.IsFullCacheHit()) return; - cascade.Analyze(result, filter); - if (cache_success.ShouldApplyInheritedOnly()) { - auto reject_inherited = filter.Add(CSSProperty::kInherited, true); - auto reject_non_inherited = filter.Add(CSSProperty::kInherited, false); - - cascade.Apply(result, reject_non_inherited); - + cascade.Apply(CascadeFilter(CSSProperty::kInherited, false)); if (cache_success.EffectiveZoomOrFontChanged(state.StyleRef())) - cascade.Apply(result, reject_inherited); + cascade.Apply(CascadeFilter(CSSProperty::kInherited, true)); } else { - cascade.Apply(result, filter); + cascade.Apply(); } CascadeAndApplyForcedColors(state, result); @@ -2175,7 +2150,7 @@ Color prev_bg_color = state.Style()->BackgroundColor().GetColor(); - MatchResult amended_result; + STACK_UNINITIALIZED StyleCascade cascade(state); const CSSValue* unset = cssvalue::CSSUnsetValue::Create(); const CSSValue* canvas = CSSIdentifierValue::Create(CSSValueID::kCanvas); @@ -2197,20 +2172,18 @@ set->SetProperty(CSSPropertyID::kWebkitTapHighlightColor, *unset); set->SetProperty(CSSPropertyID::kWebkitTextEmphasisColor, *unset); - amended_result.AddMatchedProperties(set); + cascade.MutableMatchResult().AddMatchedProperties(set); for (const auto& matched_properties : result.UaRules()) { - amended_result.AddMatchedProperties( + cascade.MutableMatchResult().AddMatchedProperties( matched_properties.properties, matched_properties.types_.link_match_type, static_cast<ValidPropertyFilter>( matched_properties.types_.valid_property_filter)); } - STACK_UNINITIALIZED StyleCascade cascade(state); CascadeFilter filter(CSSProperty::kIsAffectedByForcedColors, false); - cascade.Analyze(amended_result, filter); - cascade.Apply(amended_result, filter); + cascade.Apply(filter); Color current_bg_color = state.Style()->BackgroundColor().GetColor(); Color bg_color(current_bg_color.Red(), current_bg_color.Green(),
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.h b/third_party/blink/renderer/core/css/resolver/style_resolver.h index 169f4b8..7f64e22e 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.h
@@ -273,13 +273,11 @@ void CascadeAndApplyForcedColors(StyleResolverState&, const MatchResult&); void CascadeAndApplyMatchedProperties(StyleResolverState&, - StyleCascade& cascade, - const MatchResult&); + StyleCascade& cascade); void CalculateAnimationUpdate(StyleResolverState&); bool ApplyAnimatedStandardProperties(StyleResolverState&, - const MatchResult&, StyleCascade* cascade = nullptr); void ApplyCallbackSelectors(StyleResolverState&);
diff --git a/third_party/blink/renderer/core/css/vision_deficiency.cc b/third_party/blink/renderer/core/css/vision_deficiency.cc index 3e8e5250..6ab3903 100644 --- a/third_party/blink/renderer/core/css/vision_deficiency.cc +++ b/third_party/blink/renderer/core/css/vision_deficiency.cc
@@ -23,40 +23,46 @@ AtomicString CreateVisionDeficiencyFilterUrl( VisionDeficiency vision_deficiency) { + // The filter color matrices are based on the following research paper: + // Gustavo M. Machado, Manuel M. Oliveira, and Leandro A. F. Fernandes + // "A Physiologically-based Model for Simulation of Color Vision Deficiency". + // IEEE Transactions on Visualization and Computer Graphics. Volume 15 (2009), + // Number 6, November/December 2009. pp. 1291-1298. + // https://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html switch (vision_deficiency) { 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 " + "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 stdDeviation=\"2\"/>"); 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 " + " 0.367 0.861 -0.228 0.000 0.000 " + " 0.280 0.673 0.047 0.000 0.000 " + "-0.012 0.043 0.969 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 " + " 0.152 1.053 -0.205 0.000 0.000 " + " 0.115 0.786 0.099 0.000 0.000 " + "-0.004 -0.048 1.052 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 " + " 1.256 -0.077 -0.179 0.000 0.000 " + "-0.078 0.931 0.148 0.000 0.000 " + " 0.005 0.691 0.304 0.000 0.000 " + " 0.000 0.000 0.000 1.000 0.000 " "\"/>"); case VisionDeficiency::kNoVisionDeficiency: NOTREACHED();
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy.dict b/third_party/blink/renderer/core/feature_policy/feature_policy.dict index d4a0523d..9c3841f 100644 --- a/third_party/blink/renderer/core/feature_policy/feature_policy.dict +++ b/third_party/blink/renderer/core/feature_policy/feature_policy.dict
@@ -27,6 +27,7 @@ "pointer-lock" "popups" "presentation" +"screen-wake-lock" "scripts" "serial" "speaker" @@ -36,7 +37,6 @@ "unsized-media" "usb" "vertical-scroll" -"wake-lock" "vr" "\"https://example.com/\"" "*"
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5 b/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5 index 6dfc2f3c..7e0db36 100644 --- a/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5 +++ b/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5
@@ -246,6 +246,11 @@ depends_on: ["WebAuthenticationFeaturePolicy"], }, { + name: "ScreenWakeLock", + feature_policy_name: "screen-wake-lock", + depends_on: ["WakeLock"], + }, + { name: "Script", feature_policy_name: "scripts", depends_on: ["FeaturePolicyForSandbox"], @@ -285,11 +290,6 @@ depends_on: ["ExperimentalProductivityFeatures"], }, { - name: "WakeLock", - feature_policy_name: "wake-lock", - depends_on: ["WakeLock"], - }, - { name: "WebXr", feature_policy_name: "xr-spatial-tracking", depends_on: ["WebXR"],
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc index f5bd38f8..555520d 100644 --- a/third_party/blink/renderer/core/html/forms/html_select_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -781,8 +781,12 @@ } else if (change.type == ChildrenChangeType::kAllChildrenRemoved) { DCHECK(change.removed_nodes); for (Node* node : *change.removed_nodes) { - if (auto* option = DynamicTo<HTMLOptionElement>(node)) + if (auto* option = DynamicTo<HTMLOptionElement>(node)) { OptionRemoved(*option); + } else if (auto* optgroup = DynamicTo<HTMLOptGroupElement>(node)) { + for (auto& option : Traversal<HTMLOptionElement>::ChildrenOf(*optgroup)) + OptionRemoved(option); + } } } }
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element_test.cc b/third_party/blink/renderer/core/html/forms/html_select_element_test.cc index e947b14..f92a9abb 100644 --- a/third_party/blink/renderer/core/html/forms/html_select_element_test.cc +++ b/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
@@ -481,6 +481,23 @@ ASSERT_TRUE(select->GetLayoutObject()); } +TEST_F(HTMLSelectElementTest, CrashOnAttachingMenuList2) { + // crbug.com/1065125 + // This test passes if no crash. + SetHtmlInnerHTML("<select><optgroup><option>o1</select>"); + auto* select = To<HTMLSelectElement>(GetDocument().body()->firstChild()); + select->setTextContent("foo"); + + // Detach LayoutObject. + select->setAttribute("style", "display:none;"); + GetDocument().UpdateStyleAndLayoutTree(); + + // Attach LayoutObject. It triggered a DCHECK failure in + // MenuListSelectType::OptionToBeShown() + select->removeAttribute("style"); + GetDocument().UpdateStyleAndLayoutTree(); +} + TEST_F(HTMLSelectElementTest, SlotAssignmentRecalcDuringOptionRemoval) { // crbug.com/1056094 // This test passes if no CHECK failure about IsSlotAssignmentRecalcForbidden.
diff --git a/third_party/blink/renderer/core/style/computed_style_test.cc b/third_party/blink/renderer/core/style/computed_style_test.cc index 1d0d5e5..f200764 100644 --- a/third_party/blink/renderer/core/style/computed_style_test.cc +++ b/third_party/blink/renderer/core/style/computed_style_test.cc
@@ -612,25 +612,18 @@ ParseDeclarationBlock("color:-internal-light-dark-color(black, white)"); auto* dark_declaration = ParseDeclarationBlock("color-scheme:dark"); auto* light_declaration = ParseDeclarationBlock("color-scheme:light"); - CascadeFilter filter; - - MatchResult result1; - result1.AddMatchedProperties(color_declaration); - result1.AddMatchedProperties(dark_declaration); StyleCascade cascade1(state); - cascade1.Analyze(result1, filter); - cascade1.Apply(result1, filter); + cascade1.MutableMatchResult().AddMatchedProperties(color_declaration); + cascade1.MutableMatchResult().AddMatchedProperties(dark_declaration); + cascade1.Apply(); EXPECT_EQ(Color::kWhite, style->VisitedDependentColor(GetCSSPropertyColor())); - MatchResult result2; - result2.AddMatchedProperties(color_declaration); - result2.AddMatchedProperties(light_declaration); - StyleCascade cascade2(state); - cascade2.Analyze(result2, filter); - cascade2.Apply(result2, filter); + cascade2.MutableMatchResult().AddMatchedProperties(color_declaration); + cascade2.MutableMatchResult().AddMatchedProperties(light_declaration); + cascade2.Apply(); EXPECT_EQ(Color::kBlack, style->VisitedDependentColor(GetCSSPropertyColor())); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index b6fdfb64..1806def4 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -214,7 +214,7 @@ return kIgnoreObject; } - if (CanSetFocusAttribute() && GetNode() && !IsA<HTMLBodyElement>(GetNode())) + if (GetNode() && !IsA<HTMLBodyElement>(GetNode()) && CanSetFocusAttribute()) return kIncludeObject; if (IsLink() || IsInPageLinkTarget()) @@ -3180,8 +3180,7 @@ // using AOM. To be extra safe, exclude objects that are clickable themselves. // This won't prevent anyone from having a click handler on the object's // container. - if (!IsClickable() && element->FastHasAttribute(html_names::kIdAttr) && - CanBeActiveDescendant()) { + if (!IsClickable() && CanBeActiveDescendant()) { return OnNativeClickAction(); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 65659087..c10fdee 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -39,6 +39,7 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h" #include "third_party/blink/renderer/core/html/custom/element_internals.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/html_select_element.h" @@ -1320,20 +1321,6 @@ return cached_has_inherited_presentational_role_; } -bool AXObject::CanReceiveAccessibilityFocus() const { - const Element* elem = GetElement(); - if (!elem) - return false; - - // Focusable, and not forwarding the focus somewhere else - if (elem->IsFocusable() && - !GetAOMPropertyOrARIAAttribute(AOMRelationProperty::kActiveDescendant)) - return true; - - // aria-activedescendant focus - return elem->FastHasAttribute(html_names::kIdAttr) && CanBeActiveDescendant(); -} - bool AXObject::CanSetValueAttribute() const { switch (RoleValue()) { case ax::mojom::Role::kColorWell: @@ -1353,42 +1340,95 @@ return false; } +// This does not use Element::IsFocusable(), as that can sometimes recalculate +// styles because of IsFocusableStyle() check, resetting the document lifecycle. bool AXObject::CanSetFocusAttribute() const { - Node* node = GetNode(); - if (!node) + if (IsDetached()) return false; - // Elements inside a portal should not be focusable. + // NOT focusable: anything inside a <portal> (the portal element itself is). if (GetDocument() && GetDocument()->GetPage() && - GetDocument()->GetPage()->InsidePortal()) + GetDocument()->GetPage()->InsidePortal()) { return false; + } + // Focusable: web area -- this is the only focusable non-element. if (IsWebArea()) return true; - // Children of elements with an aria-activedescendant attribute should be - // focusable if they have a (non-presentational) ARIA role. - if (!IsPresentational() && AriaRoleAttribute() != ax::mojom::Role::kUnknown && - CanBeActiveDescendant()) { - return true; - } - - // NOTE: It would be more accurate to ask the document whether - // setFocusedNode() would do anything. For example, setFocusedNode() will do - // nothing if the current focused node will not relinquish the focus. - if (IsDisabledFormControl(node)) + // NOT focusable: objects with no DOM node, e.g. extra layout blocks inserted + // as filler, or objects where the node is not an element, such as a text + // node or an HTML comment. + Element* elem = GetElement(); + if (!elem) return false; - // Check for options here because AXListBoxOption and AXMenuListOption - // don't help when the <option> is canvas fallback, and because - // a common case for aria-owns from a textbox that points to a list - // does not change the hierarchy (textboxes don't support children) - if (RoleValue() == ax::mojom::Role::kListBoxOption || - RoleValue() == ax::mojom::Role::kMenuListOption) + // NOT focusable: inert elements. + if (elem->IsInert()) + return false; + + // NOT focusable: disabled form controls. + if (IsDisabledFormControl(elem)) + return false; + + // Focusable: options in a combobox or listbox. + // Even though they are not treated as supporting focus by Blink (the parent + // widget is), they are considered focusable in the accessibility sense, + // behaving like potential active descendants, and handling focus actions. + // Menu list options are handled before visibility check, because they + // are considered focusable even when part of collapsed drop down. + if (RoleValue() == ax::mojom::Role::kMenuListOption) return true; - auto* element = DynamicTo<Element>(node); - return element && element->SupportsFocus(); + // NOT focusable: hidden elements. + // This is imperfect, because the only way to really know whether something + // is hidden via style is to EnsureComputedStyle(). The method + // AXObject::IsHiddenViaStyle() does this, but it relies on + // EnsureComputedStyle() which could cause instability in callers. + // This code assumes that a canvas descendant has the same visibility as + // the canvas itself. + // TODO(aleventhal) Consider caching visibility when it's safe to compute. + if (!IsA<HTMLAreaElement>(elem)) { + if (!GetLayoutObject()) { + if (!elem->IsInCanvasSubtree()) + return false; + const HTMLCanvasElement* canvas = + Traversal<HTMLCanvasElement>::FirstAncestorOrSelf(*elem); + if (!canvas->GetLayoutObject() || + canvas->GetLayoutObject()->Style()->Visibility() != + EVisibility::kVisible) { + return false; + } + } else if (GetLayoutObject()->Style()->Visibility() != + EVisibility::kVisible) { + return false; + } + } + + // Focusable: options in a combobox or listbox. + // Similar to menu list option treatment above, but not focusable if hidden. + if (RoleValue() == ax::mojom::Role::kListBoxOption) + return true; + + // Focusable: element supports focus. + if (elem->SupportsFocus()) + return true; + + // TODO(accessibility) Focusable: scrollable with the keyboard. + // Keyboard-focusable scroll containers feature: + // https://www.chromestatus.com/feature/5231964663578624 + // When adding here, remove similar check from ::NameFromContents(). + // if (RuntimeEnabledFeatures::KeyboardFocusableScrollersEnabled() && + // IsUserScrollable()) { + // return true; + // } + + // Focusable: can be an active descendant. + if (CanBeActiveDescendant()) + return true; + + // NOT focusable: everything else. + return false; } // From ARIA 1.1. @@ -1401,6 +1441,25 @@ // textbox or is a logical descendant of that controlled element as indicated by // the aria-owns attribute. bool AXObject::CanBeActiveDescendant() const { + // Require an element with an id attribute. + // TODO(accessibility): this code currently requires both an id and role + // attribute, as well as an ancestor or controlling aria-activedescendant. + // However, with element reflection it may be possible to set an active + // descendant without an id, so at some point we may need to remove the + // requirement for an id attribute. + if (!GetElement() || !GetElement()->FastHasAttribute(html_names::kIdAttr)) + return false; + + // Does not make sense to use aria-activedescendant to point to a + // presentational object. + if (IsPresentational()) + return false; + + // Does not make sense to use aria-activedescendant to point to an HTML + // element that requires real focus, therefore an ARIA role is necessary. + if (AriaRoleAttribute() == ax::mojom::Role::kUnknown) + return false; + return IsARIAControlledByTextboxWithActiveDescendant() || AncestorExposesActiveDescendant(); } @@ -1932,10 +1991,8 @@ // a click action means the user should trigger the action via a simulated // click. If this object cannot receive focus, it's impossible to trigger it // with a key press. - if (RoleValue() == ax::mojom::Role::kButton && - !CanReceiveAccessibilityFocus()) { + if (RoleValue() == ax::mojom::Role::kButton && !CanSetFocusAttribute()) return ax::mojom::DefaultActionVerb::kClick; - } switch (RoleValue()) { case ax::mojom::Role::kButton: @@ -2114,7 +2171,7 @@ if (is_disabled) return kRestrictionDisabled; } else if (CanSetFocusAttribute() && IsDescendantOfDisabledNode()) { - // No aria-disabled, but other markup says it's disabled. + // aria-disabled on an ancestor propagates to focusable descendants. return kRestrictionDisabled; } @@ -3716,7 +3773,30 @@ case ax::mojom::Role::kSection: case ax::mojom::Role::kStrong: case ax::mojom::Role::kTime: - result = recursive || (CanReceiveAccessibilityFocus() && !IsEditable()); + if (recursive) { + // Use contents if part of a recursive name computation. + result = true; + } else { + // Use contents if focusable, so that there is a name in the case + // where the author mistakenly forgot to provide one. + // Exceptions: + // 1.Elements with contenteditable, where using the contents as a name + // would cause them to be double-announced. + // 2.Containers with aria-activedescendant, where the focus is being + // forwarded somewhere else. + // TODO(accessibility) Scrollables are currently whitelisted here in + // order to keep the current behavior. In the future, this can be + // removed because this code will be handled in IsFocusable(), once + // KeyboardFocusableScrollersEnabled is permanently enabled. + // Note: this uses the same scrollable check that element.cc uses. + bool is_focusable_scrollable = + RuntimeEnabledFeatures::KeyboardFocusableScrollersEnabled() && + IsUserScrollable(); + bool is_focusable = is_focusable_scrollable || CanSetFocusAttribute(); + result = is_focusable && !IsEditable() && + !GetAOMPropertyOrARIAAttribute( + AOMRelationProperty::kActiveDescendant); + } break; case ax::mojom::Role::kPdfActionableHighlight:
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 0a7c91c..4d1c24f 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -496,10 +496,12 @@ virtual bool IsVisible() const; virtual bool IsVisited() const { return false; } - // Check whether certain properties can be modified. - bool CanSetFocusAttribute() const; + // Check whether value can be modified. bool CanSetValueAttribute() const; + // Is the element focusable? + bool CanSetFocusAttribute() const; + // Whether objects are ignored, i.e. hidden from the AT. bool AccessibilityIsIgnored() const; // Whether objects are ignored but included in the tree. @@ -1083,7 +1085,6 @@ return nullptr; } - bool CanReceiveAccessibilityFocus() const; bool NameFromContents(bool recursive) const; bool NameFromSelectedOption(bool recursive) const;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc b/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc index 0d3fa5b..cb6e666 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory_impl.cc
@@ -39,6 +39,10 @@ : base::UnguessableToken(); } +void SendLogMessage(const WTF::String& message) { + WebRtcLogMessage("MSRFI::" + message.Utf8()); +} + } // namespace std::unique_ptr<WebMediaStreamRendererFactory> @@ -78,15 +82,16 @@ WebLocalFrame* web_frame, const WebString& device_id) { DCHECK(!web_stream.IsNull()); + SendLogMessage(String::Format("%s({web_stream_id=%s}, {device_id=%s})", + __func__, web_stream.Id().Utf8().c_str(), + device_id.Utf8().c_str())); WebVector<WebMediaStreamTrack> audio_tracks = web_stream.AudioTracks(); if (audio_tracks.empty()) { - WebRtcLogMessage("No audio tracks in media stream (return null)."); + SendLogMessage(String::Format( + "%s => (ERROR: no audio tracks in media stream)", __func__)); return nullptr; } - DVLOG(1) << "MediaStreamRendererFactoryImpl::GetAudioRenderer stream:" - << web_stream.Id().Utf8(); - // TODO(tommi): We need to fix the data flow so that // it works the same way for all track implementations, local, remote or what // have you. @@ -99,7 +104,8 @@ if (!audio_track) { // This can happen if the track was cloned. // TODO(tommi, perkj): Fix cloning of tracks to handle extra data too. - WebRtcLogMessage("Error: No native track for WebMediaStreamTrack"); + SendLogMessage(String::Format( + "%s => (ERROR: no native track for WebMediaStreamTrack)", __func__)); return nullptr; } @@ -108,9 +114,10 @@ if (!PeerConnectionRemoteAudioTrack::From(audio_track)) { // TODO(xians): Add support for the case where the media stream contains // multiple audio tracks. - DVLOG(1) << "Creating TrackAudioRenderer for " - << (audio_track->is_local_track() ? "local" : "remote") - << " track."; + SendLogMessage(String::Format( + "%s => (creating TrackAudioRenderer for %s audio track)", __func__, + audio_track->is_local_track() ? "local" : "remote")); + return new TrackAudioRenderer(audio_tracks[0], web_frame, /*session_id=*/base::UnguessableToken(), String(device_id)); @@ -120,13 +127,19 @@ WebRtcAudioDeviceImpl* audio_device = PeerConnectionDependencyFactory::GetInstance()->GetWebRtcAudioDevice(); DCHECK(audio_device); - + SendLogMessage(String::Format( + "%s => (media stream is a remote WebRTC stream)", __func__)); // Share the existing renderer if any, otherwise create a new one. scoped_refptr<WebRtcAudioRenderer> renderer(audio_device->renderer()); + if (renderer) { - DVLOG(1) << "Using existing WebRtcAudioRenderer for remote WebRTC track."; + SendLogMessage(String::Format( + "%s => (using existing WebRtcAudioRenderer for remote stream)", + __func__)); } else { - DVLOG(1) << "Creating WebRtcAudioRenderer for remote WebRTC track."; + SendLogMessage(String::Format( + "%s => (creating new WebRtcAudioRenderer for remote stream)", + __func__)); renderer = new WebRtcAudioRenderer( PeerConnectionDependencyFactory::GetInstance() @@ -135,14 +148,17 @@ device_id.Utf8()); if (!audio_device->SetAudioRenderer(renderer.get())) { - WebRtcLogMessage("Error: SetAudioRenderer failed for remote track."); + SendLogMessage(String::Format( + "%s => (ERROR: WRADI::SetAudioRenderer failed)", __func__)); return nullptr; } } auto ret = renderer->CreateSharedAudioRendererProxy(web_stream); - if (!ret) - WebRtcLogMessage("Error: CreateSharedAudioRendererProxy failed."); + if (!ret) { + SendLogMessage(String::Format( + "%s => (ERROR: CreateSharedAudioRendererProxy failed)", __func__)); + } return ret; }
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc index f40539f..f404aa6 100644 --- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc +++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
@@ -57,6 +57,51 @@ blink::WebMediaStreamSource::kReadyStateEnded; } +const char* LoadTypeToString(blink::WebMediaPlayer::LoadType type) { + switch (type) { + case blink::WebMediaPlayer::kLoadTypeURL: + return "URL"; + case blink::WebMediaPlayer::kLoadTypeMediaSource: + return "MediaSource"; + case blink::WebMediaPlayer::kLoadTypeMediaStream: + return "MediaStream"; + } +} + +const char* ReadyStateToString(blink::WebMediaPlayer::ReadyState state) { + switch (state) { + case blink::WebMediaPlayer::kReadyStateHaveNothing: + return "HaveNothing"; + case blink::WebMediaPlayer::kReadyStateHaveMetadata: + return "HaveMetadata"; + case blink::WebMediaPlayer::kReadyStateHaveCurrentData: + return "HaveCurrentData"; + case blink::WebMediaPlayer::kReadyStateHaveFutureData: + return "HaveFutureData"; + case blink::WebMediaPlayer::kReadyStateHaveEnoughData: + return "HaveEnoughData"; + } +} + +const char* NetworkStateToString(blink::WebMediaPlayer::NetworkState state) { + switch (state) { + case blink::WebMediaPlayer::kNetworkStateEmpty: + return "Empty"; + case blink::WebMediaPlayer::kNetworkStateIdle: + return "Idle"; + case blink::WebMediaPlayer::kNetworkStateLoading: + return "Loading"; + case blink::WebMediaPlayer::kNetworkStateLoaded: + return "Loaded"; + case blink::WebMediaPlayer::kNetworkStateFormatError: + return "FormatError"; + case blink::WebMediaPlayer::kNetworkStateNetworkError: + return "NetworkError"; + case blink::WebMediaPlayer::kNetworkStateDecodeError: + return "DecodeError"; + } +} + } // namespace namespace WTF { @@ -287,11 +332,13 @@ create_bridge_callback_(std::move(create_bridge_callback)), submitter_(std::move(submitter)), surface_layer_mode_(surface_layer_mode) { - DVLOG(1) << __func__; DCHECK(client); DCHECK(delegate_); weak_this_ = weak_factory_.GetWeakPtr(); delegate_id_ = delegate_->AddObserver(this); + SendLogMessage(String::Format("%s({delegate_id=%d}, {is_audio_element=%s})", + __func__, delegate_id_, + client->IsAudioElement() ? "true" : "false")); // TODO(tmathmeyer) WebMediaPlayerImpl gets the URL from the WebLocalFrame. // doing that here causes a nullptr deref. @@ -299,7 +346,6 @@ } WebMediaPlayerMS::~WebMediaPlayerMS() { - DVLOG(1) << __func__; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!web_stream_.IsNull()) @@ -334,8 +380,9 @@ LoadType load_type, const WebMediaPlayerSource& source, CorsMode /*cors_mode*/) { - DVLOG(1) << __func__; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s({load_type=%s})", __func__, + LoadTypeToString(load_type))); // TODO(acolwell): Change this to DCHECK_EQ(load_type, LoadTypeMediaStream) // once Blink-side changes land. @@ -361,6 +408,8 @@ std::string stream_id = web_stream_.IsNull() ? std::string() : web_stream_.Id().Utf8(); media_log_->AddEvent<media::MediaLogEvent::kLoad>(stream_id); + SendLogMessage( + String::Format("%s => (stream_id=%s)", __func__, stream_id.c_str())); frame_deliverer_.reset(new WebMediaPlayerMS::FrameDeliverer( weak_this_, @@ -383,11 +432,15 @@ web_stream_, internal_frame_->web_frame(), initial_audio_output_device_id_); - if (!audio_renderer_) - WebRtcLogMessage("Warning: Failed to instantiate audio renderer."); + if (!audio_renderer_) { + SendLogMessage(String::Format( + "%s => (WARNING: failed to instantiate audio renderer)", __func__)); + } if (!video_frame_provider_ && !audio_renderer_) { SetNetworkState(WebMediaPlayer::kNetworkStateNetworkError); + SendLogMessage(String::Format( + "%s => (ERROR: WebMediaPlayer::kNetworkStateNetworkError)", __func__)); return WebMediaPlayer::LoadTiming::kImmediate; } @@ -395,31 +448,35 @@ audio_renderer_->SetVolume(volume_); audio_renderer_->Start(); - // Store the ID of audio track being played in |current_video_track_id_| + // Store the ID of audio track being played in |current_audio_track_id_|. if (!web_stream_.IsNull()) { WebVector<WebMediaStreamTrack> audio_tracks = web_stream_.AudioTracks(); DCHECK_GT(audio_tracks.size(), 0U); current_audio_track_id_ = audio_tracks[0].Id(); + SendLogMessage(String::Format("%s => (audio_track_id=%s)", __func__, + current_audio_track_id_.Utf8().c_str())); } } if (video_frame_provider_) { video_frame_provider_->Start(); - // Store the ID of video track being played in |current_video_track_id_| + // Store the ID of video track being played in |current_video_track_id_|. if (!web_stream_.IsNull()) { WebVector<WebMediaStreamTrack> video_tracks = web_stream_.VideoTracks(); DCHECK_GT(video_tracks.size(), 0U); current_video_track_id_ = video_tracks[0].Id(); + SendLogMessage(String::Format("%s => (video_track_id=%s)", __func__, + current_video_track_id_.Utf8().c_str())); } } // When associated with an <audio> element, we don't want to wait for the - // first video fram to become available as we do for <video> elements + // first video frame to become available as we do for <video> elements // (<audio> elements can also be assigned video tracks). // For more details, see https://crbug.com/738379 if (audio_renderer_ && (client_->IsAudioElement() || !video_frame_provider_)) { - // This is audio-only mode. + SendLogMessage(String::Format("%s => (audio only mode)", __func__)); SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata); SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData); } @@ -453,20 +510,26 @@ } void WebMediaPlayerMS::TrackAdded(const WebMediaStreamTrack& track) { + SendLogMessage( + String::Format("%s({track_id=%s})", __func__, track.Id().Utf8().c_str())); Reload(); } void WebMediaPlayerMS::TrackRemoved(const WebMediaStreamTrack& track) { + SendLogMessage( + String::Format("%s({track_id=%s})", __func__, track.Id().Utf8().c_str())); Reload(); } void WebMediaPlayerMS::ActiveStateChanged(bool is_active) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s({is_active=%s})", __func__, + is_active ? "true" : "false")); // The case when the stream becomes active is handled by TrackAdded(). if (is_active) return; - // This makes the media element elegible to be garbage collected. Otherwise, + // This makes the media element eligible to be garbage collected. Otherwise, // the element will be considered active and will never be garbage // collected. SetNetworkState(kNetworkStateIdle); @@ -553,6 +616,7 @@ DCHECK(!web_stream_.IsNull()); if (!internal_frame_->web_frame()) return; + SendLogMessage(String::Format("%s()", __func__)); WebVector<WebMediaStreamTrack> audio_tracks = web_stream_.AudioTracks(); @@ -597,8 +661,8 @@ } void WebMediaPlayerMS::Play() { - DVLOG(1) << __func__; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s()", __func__)); media_log_->AddEvent<media::MediaLogEvent::kPlay>(); if (!paused_) @@ -631,8 +695,8 @@ } void WebMediaPlayerMS::Pause() { - DVLOG(1) << __func__; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s()", __func__)); should_play_upon_shown_ = false; media_log_->AddEvent<media::MediaLogEvent::kPause>(); @@ -663,8 +727,8 @@ } void WebMediaPlayerMS::SetVolume(double volume) { - DVLOG(1) << __func__ << "(volume=" << volume << ")"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s({volume=%.2f})", __func__, volume)); volume_ = volume; if (audio_renderer_.get()) audio_renderer_->SetVolume(volume_ * volume_multiplier_); @@ -693,14 +757,21 @@ void WebMediaPlayerMS::SetSinkId( const WebString& sink_id, WebSetSinkIdCompleteCallback completion_callback) { - DVLOG(1) << __func__; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage( + String::Format("%s({sink_id=%s})", __func__, sink_id.Utf8().c_str())); + if (!audio_renderer_) { + SendLogMessage(String::Format( + "%s => (WARNING: failed to instantiate audio renderer)", __func__)); + } media::OutputDeviceStatusCB callback = ConvertToOutputDeviceStatusCB(std::move(completion_callback)); if (audio_renderer_) { audio_renderer_->SwitchOutputDevice(sink_id.Utf8(), std::move(callback)); } else { std::move(callback).Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); + SendLogMessage(String::Format( + "%s => (ERROR: OUTPUT_DEVICE_STATUS_ERROR_INTERNAL)", __func__)); } } @@ -776,13 +847,11 @@ } WebMediaPlayer::NetworkState WebMediaPlayerMS::GetNetworkState() const { - DVLOG(2) << __func__ << ", state:" << network_state_; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return network_state_; } WebMediaPlayer::ReadyState WebMediaPlayerMS::GetReadyState() const { - DVLOG(1) << __func__ << ", state:" << ready_state_; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return ready_state_; } @@ -953,6 +1022,8 @@ } void WebMediaPlayerMS::OnMuted(bool muted) { + SendLogMessage( + String::Format("%s({muted=%s})", __func__, muted ? "true" : "false")); client_->RequestMuted(muted); } @@ -1181,6 +1252,8 @@ void WebMediaPlayerMS::SetNetworkState(WebMediaPlayer::NetworkState state) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s => (state=%s)", __func__, + NetworkStateToString(network_state_))); network_state_ = state; // Always notify to ensure client has the latest value. get_client()->NetworkStateChanged(); @@ -1188,6 +1261,8 @@ void WebMediaPlayerMS::SetReadyState(WebMediaPlayer::ReadyState state) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s => (state=%s)", __func__, + ReadyStateToString(ready_state_))); ready_state_ = state; // Always notify to ensure client has the latest value. get_client()->ReadyStateChanged(); @@ -1234,6 +1309,12 @@ client_->OnRequestAnimationFrame(); } +void WebMediaPlayerMS::SendLogMessage(const WTF::String& message) const { + blink::WebRtcLogMessage( + "WMPMS::" + message.Utf8() + + String::Format(" [delegate_id=%d]", delegate_id_).Utf8()); +} + std::unique_ptr<WebMediaPlayer::VideoFramePresentationMetadata> WebMediaPlayerMS::GetVideoFramePresentationMetadata() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.cc index 36f9388..dffb6fb 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.cc
@@ -25,6 +25,14 @@ frame_data_ = data; } +uint32_t RTCEncodedAudioFrame::synchronizationSource() const { + return 0; +} + +Vector<uint32_t> RTCEncodedAudioFrame::contributingSources() const { + return Vector<uint32_t>(); +} + String RTCEncodedAudioFrame::toString() const { StringBuilder sb; sb.Append("RTCEncodedAudioFrame{timestamp: ");
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h index a8ff051..ff0cb07 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.h
@@ -25,6 +25,8 @@ DOMArrayBuffer* data() const; DOMArrayBuffer* additionalData() const; void setData(DOMArrayBuffer*); + uint32_t synchronizationSource() const; + Vector<uint32_t> contributingSources() const; String toString() const; void Trace(Visitor*) override;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl index 197a0eba..a5996bc 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_frame.idl
@@ -10,8 +10,10 @@ interface RTCEncodedAudioFrame { readonly attribute unsigned long long timestamp; // microseconds attribute ArrayBuffer data; - // TODO(crbug.com/1052765): Replace this ArrayBuffer with structured data - // once we have decided what will be exposed. + // TODO(crbug.com/1052765): Replace the following fields with a dictionary + // with structured data once we have decided what will be exposed. readonly attribute ArrayBuffer additionalData; + readonly attribute unsigned long synchronizationSource; + readonly attribute FrozenArray<unsigned long> contributingSources; stringifier; };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc index c4fcbe8..e9fa44b 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.cc
@@ -13,9 +13,11 @@ RTCEncodedVideoFrame::RTCEncodedVideoFrame( std::unique_ptr<webrtc::video_coding::EncodedFrame> delegate, - Vector<uint8_t> additional_data) + Vector<uint8_t> additional_data, + uint32_t ssrc) : delegate_(std::move(delegate)), - additional_data_vector_(std::move(additional_data)) {} + additional_data_vector_(std::move(additional_data)), + ssrc_(ssrc) {} String RTCEncodedVideoFrame::type() const { if (!delegate_) @@ -44,6 +46,10 @@ return additional_data_; } +uint32_t RTCEncodedVideoFrame::synchronizationSource() const { + return ssrc_; +} + void RTCEncodedVideoFrame::setData(DOMArrayBuffer* data) { frame_data_ = data; }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.h b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.h index e8054a7..b52cc557 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.h
@@ -30,7 +30,8 @@ public: explicit RTCEncodedVideoFrame( std::unique_ptr<webrtc::video_coding::EncodedFrame> delegate, - Vector<uint8_t> generic_descriptor); + Vector<uint8_t> generic_descriptor, + uint32_t ssrc); // rtc_encoded_video_frame.idl implementation. String type() const; @@ -39,6 +40,7 @@ DOMArrayBuffer* data() const; DOMArrayBuffer* additionalData() const; void setData(DOMArrayBuffer*); + uint32_t synchronizationSource() const; String toString() const; // Internal API @@ -53,6 +55,7 @@ private: std::unique_ptr<webrtc::video_coding::EncodedFrame> delegate_; Vector<uint8_t> additional_data_vector_; + const uint32_t ssrc_; // Exposes encoded frame data from |delegate_|. mutable Member<DOMArrayBuffer> frame_data_; // Exposes data from |additional_data_vector_|.
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl index 97eed3a2..14de6bbc 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.idl
@@ -17,8 +17,9 @@ readonly attribute RTCCodedVideoFrameType type; readonly attribute unsigned long long timestamp; // microseconds attribute ArrayBuffer data; - // TODO(crbug.com/1052765): Replace this ArrayBuffer with structured data - // once we have decided what will be exposed. + // TODO(crbug.com/1052765): Replace the following fields with a dictionary + // with structured data once we have decided what will be exposed. readonly attribute ArrayBuffer additionalData; + readonly attribute unsigned long synchronizationSource; stringifier; };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc index c597ce0..9d793d8 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
@@ -69,7 +69,7 @@ ScriptValue CreateEncodedVideoFrameChunk(ScriptState* script_state) { RTCEncodedVideoFrame* frame = MakeGarbageCollected<RTCEncodedVideoFrame>( - /*frame_delegate=*/nullptr, Vector<uint8_t>()); + /*frame_delegate=*/nullptr, Vector<uint8_t>(), 0); return ScriptValue(script_state->GetIsolate(), ToV8(frame, script_state->GetContext()->Global(), script_state->GetIsolate()));
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.cc index 27f472e..abac0c1 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.cc
@@ -50,7 +50,8 @@ void RTCEncodedVideoUnderlyingSource::OnFrameFromSource( std::unique_ptr<webrtc::video_coding::EncodedFrame> webrtc_frame, - std::vector<uint8_t> additional_data) { + std::vector<uint8_t> additional_data, + uint32_t ssrc) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // If the source is canceled or there are too many queued frames, // drop the new frame. @@ -67,7 +68,7 @@ RTCEncodedVideoFrame* encoded_frame = MakeGarbageCollected<RTCEncodedVideoFrame>( - std::move(webrtc_frame), std::move(wtf_additional_data)); + std::move(webrtc_frame), std::move(wtf_additional_data), ssrc); Controller()->Enqueue(encoded_frame); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.h b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.h index cba48cf5..45136e3 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source.h
@@ -29,7 +29,8 @@ ScriptPromise Cancel(ScriptState*, ScriptValue reason) override; void OnFrameFromSource(std::unique_ptr<webrtc::video_coding::EncodedFrame>, - std::vector<uint8_t> additional_data); + std::vector<uint8_t> additional_data, + uint32_t ssrc); void Close(); void Trace(Visitor*) override;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source_test.cc index 5610d816..1ef26a7c 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_source_test.cc
@@ -41,7 +41,7 @@ ScriptPromiseTester read_tester(script_state, reader->read(script_state, exception_state)); EXPECT_FALSE(read_tester.IsFulfilled()); - source->OnFrameFromSource(nullptr, std::vector<uint8_t>()); + source->OnFrameFromSource(nullptr, std::vector<uint8_t>(), 0); read_tester.WaitUntilSettled(); EXPECT_TRUE(read_tester.IsFulfilled()); @@ -70,12 +70,12 @@ for (int i = 0; i > RTCEncodedVideoUnderlyingSource::kMinQueueDesiredSize; --i) { EXPECT_EQ(source->Controller()->DesiredSize(), i); - source->OnFrameFromSource(nullptr, std::vector<uint8_t>()); + source->OnFrameFromSource(nullptr, std::vector<uint8_t>(), 0); } EXPECT_EQ(source->Controller()->DesiredSize(), RTCEncodedVideoUnderlyingSource::kMinQueueDesiredSize); - source->OnFrameFromSource(nullptr, std::vector<uint8_t>()); + source->OnFrameFromSource(nullptr, std::vector<uint8_t>(), 0); EXPECT_EQ(source->Controller()->DesiredSize(), RTCEncodedVideoUnderlyingSource::kMinQueueDesiredSize);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc index ed576047..6f1830243 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -402,7 +402,7 @@ uint32_t ssrc) { if (video_from_depacketizer_underlying_source_) { video_from_depacketizer_underlying_source_->OnFrameFromSource( - std::move(encoded_video_frame), std::move(additional_data)); + std::move(encoded_video_frame), std::move(additional_data), ssrc); } }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc index e4115f8..3b48515 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -758,7 +758,7 @@ uint32_t ssrc) { if (video_from_encoder_underlying_source_) { video_from_encoder_underlying_source_->OnFrameFromSource( - std::move(frame), std::move(additional_data)); + std::move(frame), std::move(additional_data), ssrc); } }
diff --git a/third_party/blink/renderer/modules/shapedetection/face_detector.cc b/third_party/blink/renderer/modules/shapedetection/face_detector.cc index 2012392..766f30a 100644 --- a/third_party/blink/renderer/modules/shapedetection/face_detector.cc +++ b/third_party/blink/renderer/modules/shapedetection/face_detector.cc
@@ -31,7 +31,7 @@ FaceDetector::FaceDetector(ExecutionContext* context, const FaceDetectorOptions* options) - : ShapeDetector() { + : face_service_(context) { auto face_detector_options = shape_detection::mojom::blink::FaceDetectorOptions::New(); face_detector_options->max_detected_faces = options->maxDetectedFaces(); @@ -54,7 +54,7 @@ ScriptPromise FaceDetector::DoDetect(ScriptPromiseResolver* resolver, SkBitmap bitmap) { ScriptPromise promise = resolver->Promise(); - if (!face_service_) { + if (!face_service_.is_bound()) { resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kNotSupportedError, "Face detection service unavailable.")); @@ -116,6 +116,7 @@ void FaceDetector::Trace(Visitor* visitor) { ShapeDetector::Trace(visitor); + visitor->Trace(face_service_); visitor->Trace(face_service_requests_); }
diff --git a/third_party/blink/renderer/modules/shapedetection/face_detector.h b/third_party/blink/renderer/modules/shapedetection/face_detector.h index 97dc3be..bdfc333 100644 --- a/third_party/blink/renderer/modules/shapedetection/face_detector.h +++ b/third_party/blink/renderer/modules/shapedetection/face_detector.h
@@ -5,13 +5,14 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_FACE_DETECTOR_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_FACE_DETECTOR_H_ -#include "mojo/public/cpp/bindings/remote.h" #include "services/shape_detection/public/mojom/facedetection.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/shapedetection/shape_detector.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" namespace blink { @@ -37,7 +38,9 @@ Vector<shape_detection::mojom::blink::FaceDetectionResultPtr>); void OnFaceServiceConnectionError(); - mojo::Remote<shape_detection::mojom::blink::FaceDetection> face_service_; + HeapMojoRemote<shape_detection::mojom::blink::FaceDetection, + HeapMojoWrapperMode::kWithoutContextObserver> + face_service_; HeapHashSet<Member<ScriptPromiseResolver>> face_service_requests_; };
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc index 919d34f..e7dfc4a 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
@@ -68,23 +68,27 @@ return ScriptPromise(); } - // 2.1. If document is not allowed to use the policy-controlled feature named - // "wake-lock", reject promise with a "NotAllowedError" DOMException and - // return promise. + // 2.1 If type is 'screen' and the document is not allowed to use the + // policy-controlled feature named "screen-wake-lock", reject promise with + // a "NotAllowedError" DOMException and return promise. // [N.B. Per https://github.com/w3c/webappsec-feature-policy/issues/207 there // is no official support for workers in the Feature Policy spec, but we can // perform FP checks in workers in Blink] // 2.2. If the user agent denies the wake lock of this type for document, // reject promise with a "NotAllowedError" DOMException and return // promise. - if (!context->IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kWakeLock, - ReportOptions::kReportOnFailure)) { + if (type == "screen" && + !context->IsFeatureEnabled( + mojom::blink::FeaturePolicyFeature::kScreenWakeLock, + ReportOptions::kReportOnFailure)) { exception_state.ThrowDOMException( DOMExceptionCode::kNotAllowedError, - "Access to WakeLock features is disallowed by feature policy"); + "Access to Screen Wake Lock features is disallowed by feature policy"); return ScriptPromise(); } + // TODO: Check feature policy enabling for System Wake Lock + if (context->IsDedicatedWorkerGlobalScope()) { // 3. If the current global object is the DedicatedWorkerGlobalScope object: // 3.1. If the current global object's owner set is empty, reject promise
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.cc index 30b1b8bb..579fdf7 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.cc +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.cc
@@ -17,7 +17,9 @@ WakeLockManager::WakeLockManager(ExecutionContext* execution_context, WakeLockType type) - : wake_lock_type_(type), execution_context_(execution_context) { + : wake_lock_(execution_context), + wake_lock_type_(type), + execution_context_(execution_context) { DCHECK_NE(execution_context, nullptr); } @@ -36,15 +38,16 @@ // document and type. // 4.3. Add lock to record.[[ActiveLocks]]. // 5. Return active. - if (!wake_lock_) { + if (!wake_lock_.is_bound()) { mojo::Remote<mojom::blink::WakeLockService> wake_lock_service; execution_context_->GetBrowserInterfaceBroker().GetInterface( wake_lock_service.BindNewPipeAndPassReceiver()); - wake_lock_service->GetWakeLock(ToMojomWakeLockType(wake_lock_type_), - device::mojom::blink::WakeLockReason::kOther, - "Blink Wake Lock", - wake_lock_.BindNewPipeAndPassReceiver()); + wake_lock_service->GetWakeLock( + ToMojomWakeLockType(wake_lock_type_), + device::mojom::blink::WakeLockReason::kOther, "Blink Wake Lock", + wake_lock_.BindNewPipeAndPassReceiver( + execution_context_->GetTaskRunner(TaskType::kMiscPlatformAPI))); wake_lock_.set_disconnect_handler(WTF::Bind( &WakeLockManager::OnWakeLockConnectionError, WrapWeakPersistent(this))); wake_lock_->RequestWakeLock(); @@ -99,6 +102,7 @@ void WakeLockManager::Trace(Visitor* visitor) { visitor->Trace(execution_context_); visitor->Trace(wake_lock_sentinels_); + visitor->Trace(wake_lock_); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.h b/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.h index 4a5ce7f..1375d9e5 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.h +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_manager.h
@@ -6,11 +6,12 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WAKE_LOCK_WAKE_LOCK_MANAGER_H_ #include "base/gtest_prod_util.h" -#include "mojo/public/cpp/bindings/remote.h" #include "services/device/public/mojom/wake_lock.mojom-blink-forward.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" namespace blink { @@ -42,7 +43,9 @@ // An actual platform WakeLock. If bound, it means there is an active wake // lock for a given type. - mojo::Remote<device::mojom::blink::WakeLock> wake_lock_; + HeapMojoRemote<device::mojom::blink::WakeLock, + HeapMojoWrapperMode::kWithoutContextObserver> + wake_lock_; WakeLockType wake_lock_type_; // ExecutionContext from which we will connect to |wake_lock_service_|.
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_manager_test.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_manager_test.cc index 720fd5a..dcb9df8 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock_manager_test.cc +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_manager_test.cc
@@ -194,6 +194,7 @@ context.WaitForPromiseFulfillment(promise1); context.WaitForPromiseFulfillment(promise2); + EXPECT_TRUE(manager->wake_lock_.is_bound()); EXPECT_EQ(2U, manager->wake_lock_sentinels_.size()); // Unbind and wait for the disconnection to reach |wake_lock_|'s @@ -202,7 +203,7 @@ manager->wake_lock_.FlushForTesting(); EXPECT_EQ(0U, manager->wake_lock_sentinels_.size()); - EXPECT_FALSE(manager->wake_lock_); + EXPECT_FALSE(manager->wake_lock_.is_bound()); EXPECT_FALSE(system_lock.is_acquired()); }
diff --git a/third_party/blink/renderer/modules/webrtc/DEPS b/third_party/blink/renderer/modules/webrtc/DEPS index 9a092ef..d12ed38 100644 --- a/third_party/blink/renderer/modules/webrtc/DEPS +++ b/third_party/blink/renderer/modules/webrtc/DEPS
@@ -5,6 +5,7 @@ "+media/base/audio_bus.h", "+media/base/audio_capturer_source.h", "+media/base/audio_decoder.h", + "+media/base/audio_power_monitor.h", "+media/base/audio_latency.h", "+media/base/audio_parameters.h", "+media/base/audio_pull_fifo.h",
diff --git a/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc b/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc index 481bf01..e8f6097 100644 --- a/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc +++ b/third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.cc
@@ -36,7 +36,7 @@ initialized_(false), playing_(false), recording_(false) { - SendLogMessage(base::StringPrintf("WebRtcAudioDeviceImpl({id=%s})", + SendLogMessage(base::StringPrintf("%s({id=%s})", __func__, GetAudioProcessingId().ToString().c_str())); // This object can be constructed on either the signaling thread or the main // thread, so we need to detach these thread checkers here and have them @@ -49,7 +49,7 @@ } WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { - SendLogMessage(base::StringPrintf("~WebRtcAudioDeviceImpl([id=%s])", + SendLogMessage(base::StringPrintf("%s() [id=%s]", __func__, GetAudioProcessingId().ToString().c_str())); DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); DCHECK(!initialized_) << "Terminate must have been called."; @@ -142,6 +142,9 @@ void WebRtcAudioDeviceImpl::SetOutputDeviceForAec( const String& output_device_id) { DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); + SendLogMessage(base::StringPrintf("%s({output_device_id=%s}) [id=%s]", + __func__, output_device_id.Utf8().c_str(), + GetAudioProcessingId().ToString().c_str())); output_device_id_for_aec_ = output_device_id; base::AutoLock lock(lock_); for (auto* capturer : capturers_) { @@ -156,7 +159,7 @@ int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback( webrtc::AudioTransport* audio_callback) { DCHECK_CALLED_ON_VALID_THREAD(signaling_thread_checker_); - SendLogMessage(base::StringPrintf("RegisterAudioCallback([id=%s])", + SendLogMessage(base::StringPrintf("%s() [id=%s]", __func__, GetAudioProcessingId().ToString().c_str())); base::AutoLock lock(lock_); DCHECK_EQ(!audio_transport_callback_, !!audio_callback); @@ -269,7 +272,7 @@ int32_t WebRtcAudioDeviceImpl::StartRecording() { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); DCHECK(initialized_); - SendLogMessage(base::StringPrintf("StartRecording([id=%s])", + SendLogMessage(base::StringPrintf("%s() [id=%s]", __func__, GetAudioProcessingId().ToString().c_str())); base::AutoLock auto_lock(lock_); if (!audio_transport_callback_) { @@ -292,7 +295,7 @@ DCHECK(signaling_thread_checker_.CalledOnValidThread() || worker_thread_checker_.CalledOnValidThread()); #endif - SendLogMessage(base::StringPrintf("StopRecording([id=%s])", + SendLogMessage(base::StringPrintf("%s() [id=%s]", __func__, GetAudioProcessingId().ToString().c_str())); base::AutoLock auto_lock(lock_); recording_ = false; @@ -394,7 +397,7 @@ void WebRtcAudioDeviceImpl::AddAudioCapturer( ProcessedLocalAudioSource* capturer) { DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); - SendLogMessage(base::StringPrintf("AddAudioCapturer([id=%s])", + SendLogMessage(base::StringPrintf("%s() [id=%s]", __func__, GetAudioProcessingId().ToString().c_str())); DCHECK(capturer); DCHECK(!capturer->device().id.empty()); @@ -408,7 +411,7 @@ void WebRtcAudioDeviceImpl::RemoveAudioCapturer( ProcessedLocalAudioSource* capturer) { DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); - SendLogMessage(base::StringPrintf("RemoveAudioCapturer([id=%s])", + SendLogMessage(base::StringPrintf("%s() [id=%s]", __func__, GetAudioProcessingId().ToString().c_str())); DCHECK(capturer); base::AutoLock auto_lock(lock_);
diff --git a/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc b/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc index d0993d5e..ad23ef6 100644 --- a/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc +++ b/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.cc
@@ -24,8 +24,10 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/webrtc/peer_connection_remote_audio_source.h" #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/webrtc/api/media_stream_interface.h" namespace WTF { @@ -47,10 +49,45 @@ const media::AudioParameters::Format kFormat = media::AudioParameters::AUDIO_PCM_LOW_LATENCY; +// Time constant for AudioPowerMonitor. See See AudioPowerMonitor ctor comments +// for details. +constexpr base::TimeDelta kPowerMeasurementTimeConstant = + base::TimeDelta::FromMilliseconds(10); + +// Time in seconds between two successive measurements of audio power levels. +constexpr base::TimeDelta kPowerMonitorLogInterval = + base::TimeDelta::FromSeconds(15); + // Used for UMA histograms. const int kRenderTimeHistogramMinMicroseconds = 100; const int kRenderTimeHistogramMaxMicroseconds = 1 * 1000 * 1000; // 1 second +const char* OutputDeviceStatusToString(media::OutputDeviceStatus status) { + switch (status) { + case media::OUTPUT_DEVICE_STATUS_OK: + return "OK"; + case media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND: + return "ERROR_NOT_FOUND"; + case media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED: + return "ERROR_NOT_AUTHORIZED"; + case media::OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT: + return "ERROR_TIMED_OUT"; + case media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL: + return "ERROR_INTERNAL"; + } +} + +const char* StateToString(WebRtcAudioRenderer::State state) { + switch (state) { + case WebRtcAudioRenderer::UNINITIALIZED: + return "UNINITIALIZED"; + case WebRtcAudioRenderer::PLAYING: + return "PLAYING"; + case WebRtcAudioRenderer::PAUSED: + return "PAUSED"; + } +} + // This is a simple wrapper class that's handed out to users of a shared // WebRtcAudioRenderer instance. This class maintains the per-user 'playing' // and 'started' states to avoid problems related to incorrect usage which @@ -178,25 +215,109 @@ WeakPersistent<LocalFrame> frame_; }; +WebRtcAudioRenderer::AudioStreamTracker::AudioStreamTracker( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + WebRtcAudioRenderer* renderer, + int sample_rate) + : task_runner_(std::move(task_runner)), + renderer_(renderer), + start_time_(base::TimeTicks::Now()), + render_callbacks_started_(false), + check_alive_timer_(task_runner_, + this, + &WebRtcAudioRenderer::AudioStreamTracker::CheckAlive), + power_monitor_(sample_rate, kPowerMeasurementTimeConstant), + last_audio_level_log_time_(base::TimeTicks::Now()) { + weak_this_ = weak_factory_.GetWeakPtr(); + // CheckAlive() will look to see if |render_callbacks_started_| is true + // after the timeout expires and log this. If the stream is paused/closed + // before the timer fires, a warning is logged instead. + check_alive_timer_.StartOneShot(base::TimeDelta::FromSeconds(5), FROM_HERE); +} + +WebRtcAudioRenderer::AudioStreamTracker::~AudioStreamTracker() { + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(renderer_); + const auto duration = base::TimeTicks::Now() - start_time_; + renderer_->SendLogMessage( + String::Format("%s => (media stream duration=%" PRId64 " seconds)", + __func__, duration.InSeconds())); +} + +void WebRtcAudioRenderer::AudioStreamTracker::OnRenderCallbackCalled() { + DCHECK(renderer_->CurrentThreadIsRenderingThread()); + // Indicate that render callbacks has started as expected and within a + // reasonable time. Since this thread is the only writer of + // |render_callbacks_started_| once the thread starts, it's safe to compare + // and then change the state once. + if (!render_callbacks_started_) + render_callbacks_started_ = true; +} + +void WebRtcAudioRenderer::AudioStreamTracker::MeasurePower( + const media::AudioBus& buffer, + int frames) { + DCHECK(renderer_->CurrentThreadIsRenderingThread()); + // Update the average power estimate on the rendering thread to avoid posting + // a task which also has to copy the audio bus. According to comments in + // AudioPowerMonitor::Scan(), it should be safe. Note that, we only check the + // power once every ten seconds (on the |task_runner_| thread) and the result + // is only used for logging purposes. + power_monitor_.Scan(buffer, frames); + const auto now = base::TimeTicks::Now(); + if ((now - last_audio_level_log_time_) > kPowerMonitorLogInterval) { + // Log the current audio level but avoid using the render thread to reduce + // its load and to ensure that |power_monitor_| is mainly accessed on one + // thread. |weak_ptr_factory_| ensures that the task is canceled when + // |this| is destroyed since we can't guarantee that |this| outlives the + // task. + PostCrossThreadTask( + *task_runner_, FROM_HERE, + CrossThreadBindOnce(&AudioStreamTracker::LogAudioPowerLevel, + weak_this_)); + last_audio_level_log_time_ = now; + } +} + +void WebRtcAudioRenderer::AudioStreamTracker::LogAudioPowerLevel() { + DCHECK(task_runner_->BelongsToCurrentThread()); + std::pair<float, bool> power_and_clip = + power_monitor_.ReadCurrentPowerAndClip(); + renderer_->SendLogMessage(String::Format( + "%s => (average audio level=%.2f dBFS)", __func__, power_and_clip.first)); +} + +void WebRtcAudioRenderer::AudioStreamTracker::CheckAlive(TimerBase*) { + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(renderer_); + renderer_->SendLogMessage(String::Format( + "%s => (%s)", __func__, + render_callbacks_started_ ? "stream is alive" + : "WARNING: stream is not alive")); +} + WebRtcAudioRenderer::WebRtcAudioRenderer( const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, const WebMediaStream& media_stream, WebLocalFrame* web_frame, const base::UnguessableToken& session_id, const std::string& device_id) - : state_(UNINITIALIZED), + : task_runner_(Thread::Current()->GetTaskRunner()), + state_(UNINITIALIZED), source_internal_frame_(std::make_unique<InternalFrame>(web_frame)), session_id_(session_id), signaling_thread_(signaling_thread), media_stream_(media_stream), + media_stream_id_(media_stream_.Id().Utf8()), source_(nullptr), play_ref_count_(0), start_ref_count_(0), sink_params_(kFormat, media::CHANNEL_LAYOUT_STEREO, 0, 0), output_device_id_(device_id) { - WebRtcLogMessage(base::StringPrintf("WAR::WAR. session_id=%s, effects=%i", - session_id.ToString().c_str(), - sink_params_.effects())); + SendLogMessage( + String::Format("%s({session_id=%s}, {device_id=%s})", __func__, + session_id.is_empty() ? "" : session_id.ToString().c_str(), + device_id.c_str())); } WebRtcAudioRenderer::~WebRtcAudioRenderer() { @@ -205,16 +326,16 @@ } bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) { - DVLOG(1) << "WebRtcAudioRenderer::Initialize()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(source); DCHECK(!sink_.get()); - // DCHECK_GE(session_id_, 0); { base::AutoLock auto_lock(lock_); DCHECK_EQ(state_, UNINITIALIZED); DCHECK(!source_); } + SendLogMessage( + String::Format("%s([state=%s])", __func__, StateToString(state_))); media::AudioSinkParameters sink_params(session_id_, output_device_id_); sink_params.processing_id = source->GetAudioProcessingId(); @@ -226,15 +347,19 @@ sink_->GetOutputDeviceInfo().device_status(); UMA_HISTOGRAM_ENUMERATION("Media.Audio.WebRTCAudioRenderer.DeviceStatus", sink_status, media::OUTPUT_DEVICE_STATUS_MAX + 1); + SendLogMessage(String::Format("%s => (sink device_status=%s)", __func__, + OutputDeviceStatusToString(sink_status))); if (sink_status != media::OUTPUT_DEVICE_STATUS_OK) { + SendLogMessage(String::Format("%s => (ERROR: invalid output device status)", + __func__)); sink_->Stop(); return false; } PrepareSink(); { - // No need to reassert the preconditions because the other thread accessing - // the fields only reads them. + // No need to reassert the preconditions because the other thread + // accessing the fields only reads them. base::AutoLock auto_lock(lock_); source_ = source; @@ -272,15 +397,16 @@ } void WebRtcAudioRenderer::Start() { - DVLOG(1) << "WebRtcAudioRenderer::Start()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage( + String::Format("%s([state=%s])", __func__, StateToString(state_))); ++start_ref_count_; } void WebRtcAudioRenderer::Play() { - DVLOG(1) << "WebRtcAudioRenderer::Play()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - + SendLogMessage( + String::Format("%s([state=%s])", __func__, StateToString(state_))); if (playing_state_.playing()) return; @@ -293,6 +419,8 @@ DVLOG(1) << "WebRtcAudioRenderer::EnterPlayState()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; + SendLogMessage( + String::Format("%s([state=%s])", __func__, StateToString(state_))); base::AutoLock auto_lock(lock_); if (state_ == UNINITIALIZED) return; @@ -303,16 +431,22 @@ if (state_ != PLAYING) { state_ = PLAYING; + audio_stream_tracker_.emplace(task_runner_, this, + sink_params_.sample_rate()); + if (audio_fifo_) { audio_delay_ = base::TimeDelta(); audio_fifo_->Clear(); } } + SendLogMessage( + String::Format("%s => (state=%s)", __func__, StateToString(state_))); } void WebRtcAudioRenderer::Pause() { - DVLOG(1) << "WebRtcAudioRenderer::Pause()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage( + String::Format("%s([state=%s])", __func__, StateToString(state_))); if (!playing_state_.playing()) return; @@ -322,9 +456,10 @@ } void WebRtcAudioRenderer::EnterPauseState() { - DVLOG(1) << "WebRtcAudioRenderer::EnterPauseState()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_GT(start_ref_count_, 0) << "Did you forget to call Start()?"; + SendLogMessage( + String::Format("%s([state=%s])", __func__, StateToString(state_))); base::AutoLock auto_lock(lock_); if (state_ == UNINITIALIZED) return; @@ -333,12 +468,15 @@ DCHECK_GT(play_ref_count_, 0); if (!--play_ref_count_) state_ = PAUSED; + SendLogMessage( + String::Format("%s => (state=%s)", __func__, StateToString(state_))); } void WebRtcAudioRenderer::Stop() { - DVLOG(1) << "WebRtcAudioRenderer::Stop()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); { + SendLogMessage( + String::Format("%s([state=%s])", __func__, StateToString(state_))); base::AutoLock auto_lock(lock_); if (state_ == UNINITIALIZED) return; @@ -346,8 +484,7 @@ if (--start_ref_count_) return; - DVLOG(1) << "Calling RemoveAudioRenderer and Stop()."; - + audio_stream_tracker_.reset(); source_->RemoveAudioRenderer(this); source_ = nullptr; state_ = UNINITIALIZED; @@ -363,6 +500,8 @@ static_cast<int>(max_render_time_.InMicroseconds()), kRenderTimeHistogramMinMicroseconds, kRenderTimeHistogramMaxMicroseconds, 50); + SendLogMessage(String::Format("%s => (max_render_time=%.3f ms)", __func__, + max_render_time_.InMillisecondsF())); max_render_time_ = base::TimeDelta(); } @@ -393,9 +532,12 @@ void WebRtcAudioRenderer::SwitchOutputDevice( const std::string& device_id, media::OutputDeviceStatusCB callback) { - DVLOG(1) << "WebRtcAudioRenderer::SwitchOutputDevice()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + SendLogMessage(String::Format("%s({device_id=%s} [state=%s])", __func__, + device_id.c_str(), StateToString(state_))); if (!source_) { + SendLogMessage(String::Format( + "%s => (ERROR: OUTPUT_DEVICE_STATUS_ERROR_INTERNAL)", __func__)); std::move(callback).Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); return; } @@ -416,8 +558,12 @@ UMA_HISTOGRAM_ENUMERATION( "Media.Audio.WebRTCAudioRenderer.SwitchDeviceStatus", status, media::OUTPUT_DEVICE_STATUS_MAX + 1); + SendLogMessage(String::Format("%s => (sink device_status=%s)", __func__, + OutputDeviceStatusToString(status))); if (status != media::OUTPUT_DEVICE_STATUS_OK) { + SendLogMessage( + String::Format("%s => (ERROR: invalid sink device status)", __func__)); new_sink->Stop(); std::move(callback).Run(status); return; @@ -451,9 +597,6 @@ if (!source_) return 0; - DVLOG(2) << "WebRtcAudioRenderer::Render()"; - DVLOG(2) << "audio_delay: " << delay; - audio_delay_ = delay; // If there are skipped frames, pull and throw away the same amount. We always @@ -483,6 +626,12 @@ else SourceCallback(0, audio_bus); + if (state_ == PLAYING && audio_stream_tracker_) { + // Mark the stream as alive the first time this method is called. + audio_stream_tracker_->OnRenderCallbackCalled(); + audio_stream_tracker_->MeasurePower(*audio_bus, audio_bus->frames()); + } + return (state_ == PLAYING) ? audio_bus->frames() : 0; } @@ -496,7 +645,7 @@ media::AudioBus* audio_bus) { DCHECK(sink_->CurrentThreadIsRenderingThread()); base::TimeTicks start_time = base::TimeTicks::Now(); - DVLOG(2) << "WebRtcAudioRenderer::SourceCallback(" << fifo_frame_delay << ", " + DVLOG(2) << "WRAR::SourceCallback(" << fifo_frame_delay << ", " << audio_bus->channels() << ", " << audio_bus->frames() << ")"; int output_delay_milliseconds = @@ -556,7 +705,8 @@ if (volume > 10.0f) volume = 10.0f; - DVLOG(1) << "Setting remote source volume: " << volume; + SendLogMessage(String::Format("%s => (source volume changed to %.2f)", + __func__, volume)); if (!signaling_thread_->BelongsToCurrentThread()) { // Libjingle hands out proxy objects in most cases, but the audio source // object is an exception (bug?). So, to work around that, we need to make @@ -655,7 +805,6 @@ } void WebRtcAudioRenderer::PrepareSink() { - DVLOG(1) << "WebRtcAudioRenderer::PrepareSink()"; DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); media::AudioParameters new_sink_params; { @@ -665,20 +814,22 @@ const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo(); DCHECK_EQ(device_info.device_status(), media::OUTPUT_DEVICE_STATUS_OK); - DVLOG(1) << "Sink parameters: " << sink_params_.AsHumanReadableString(); - DVLOG(1) << "Hardware parameters: " - << device_info.output_params().AsHumanReadableString(); + SendLogMessage(String::Format( + "%s => (hardware parameters=[%s])", __func__, + device_info.output_params().AsHumanReadableString().c_str())); - // WebRTC does not yet support higher rates than 96000 on the client side + // WebRTC does not yet support higher rates than 192000 on the client side // and 48000 is the preferred sample rate. Therefore, if 192000 is detected, // we change the rate to 48000 instead. The consequence is that the native // layer will be opened up at 192kHz but WebRTC will provide data at 48kHz // which will then be resampled by the audio converted on the browser side // to match the native audio layer. int sample_rate = device_info.output_params().sample_rate(); - DVLOG(1) << "Audio output hardware sample rate: " << sample_rate; if (sample_rate >= 192000) { - DVLOG(1) << "Resampling from 48000 to " << sample_rate << " is required"; + SendLogMessage( + String::Format("%s => (WARNING: WebRTC provides audio at 48kHz and " + "resampling takes place to match %dHz)", + __func__, sample_rate)); sample_rate = 48000; } media::AudioSampleRate asr; @@ -694,7 +845,8 @@ // use 10 ms of data since the WebRTC client only supports multiples of 10 ms // as buffer size where 10 ms is preferred for lowest possible delay. const int source_frames_per_buffer = (sample_rate / 100); - DVLOG(1) << "Using WebRTC output buffer size: " << source_frames_per_buffer; + SendLogMessage(String::Format("%s => (source_frames_per_buffer=%d)", __func__, + source_frames_per_buffer)); // Setup sink parameters using same channel configuration as the source. // This sink is an AudioRendererSink which is implemented by an @@ -708,7 +860,8 @@ // WebRTC does not support channel remixing for more than 8 channels (7.1). // This is an attempt to "support" more than 8 channels by falling back to // stereo instead. See crbug.com/1003735. - LOG(WARNING) << "Falling back to stereo sink"; + SendLogMessage( + String::Format("%s => (WARNING: sink falls back to stereo)", __func__)); channels = 2; channel_layout = media::CHANNEL_LAYOUT_STEREO; } @@ -719,7 +872,6 @@ if (channel_layout == media::CHANNEL_LAYOUT_DISCRETE) { new_sink_params.set_channels_for_discrete(channels); } - DVLOG(1) << new_sink_params.AsHumanReadableString(); DCHECK(new_sink_params.IsValid()); // Create a FIFO if re-buffering is required to match the source input with @@ -728,8 +880,9 @@ const bool different_source_sink_frames = source_frames_per_buffer != new_sink_params.frames_per_buffer(); if (different_source_sink_frames) { - DVLOG(1) << "Rebuffering from " << source_frames_per_buffer << " to " - << new_sink_params.frames_per_buffer(); + SendLogMessage(String::Format("%s => (INFO: rebuffering from %d to %d)", + __func__, source_frames_per_buffer, + new_sink_params.frames_per_buffer())); } { base::AutoLock lock(lock_); @@ -743,7 +896,9 @@ CrossThreadUnretained(this)))); } sink_params_ = new_sink_params; - DVLOG(1) << "New sink parameters: " << sink_params_.AsHumanReadableString(); + SendLogMessage( + String::Format("%s => (sink_params=[%s])", __func__, + sink_params_.AsHumanReadableString().c_str())); } // Specify the latency info to be passed to the browser side. @@ -753,4 +908,10 @@ sink_->Initialize(new_sink_params, this); } +void WebRtcAudioRenderer::SendLogMessage(const WTF::String& message) { + WebRtcLogMessage(String::Format("WRAR::%s [label=%s]", message.Utf8().c_str(), + media_stream_id_.c_str()) + .Utf8()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.h b/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.h index d9ab184..ba7df5b 100644 --- a/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.h +++ b/third_party/blink/renderer/modules/webrtc/webrtc_audio_renderer.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <atomic> #include <map> #include <memory> #include <string> @@ -14,19 +15,25 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/sequence_checker.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/threading/thread_checker.h" +#include "base/time/time.h" #include "base/unguessable_token.h" #include "media/base/audio_decoder.h" +#include "media/base/audio_power_monitor.h" #include "media/base/audio_pull_fifo.h" #include "media/base/audio_renderer_sink.h" #include "media/base/channel_layout.h" #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_renderer.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/timer.h" #include "third_party/blink/renderer/platform/webrtc/webrtc_source.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace webrtc { class AudioSourceInterface; @@ -81,6 +88,12 @@ SEQUENCE_CHECKER(sequence_checker_); }; + enum State { + UNINITIALIZED, + PLAYING, + PAUSED, + }; + WebRtcAudioRenderer( const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread, const blink::WebMediaStream& media_stream, @@ -130,6 +143,76 @@ void SwitchOutputDevice(const std::string& device_id, media::OutputDeviceStatusCB callback) override; + // Private utility class which keeps track of the state and duration of + // playing (rendered on an HTML5 audio tag) audio streams. Mainly intended + // for logging purposes to track down "can't hear" type of issues. + class AudioStreamTracker { + public: + // The internal on-shot timer will use the same |task_runner| as the outer + // class (OC) who creates this object. |renderer| must outlive the + // AudioStreamTracker. See comments for |AudioStreamTracker::renderer_| why + // it is safe to use a raw pointer here. |sample_rate| is the current sample + // rate used by the audio sink (see WebRtcAudioRenderer::sink_params_). + explicit AudioStreamTracker( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + WebRtcAudioRenderer* renderer, + int sample_rate); + + // Note: the destructor takes care of logging of the duration of the stream. + ~AudioStreamTracker(); + + // This function should be called from the audio device callback thread, + // i.e., the so-called render thread. + void OnRenderCallbackCalled(); + + // Scans the provided audio samples and updates a power measurement. The + // "average power" is a running average calculated by using a first-order + // low-pass filter over the square of the samples scanned. + // Called from the audio render thread and it is safe. See comments in + // AudioPowerMonitor::Scan() for more details. + void MeasurePower(const media::AudioBus& buffer, int frames); + + private: + // Called by the timer when it fires once after a delay of ~5 seconds from + // start. Reads the state of atomic |render_callbacks_started_|. + void CheckAlive(TimerBase*); + + void LogAudioPowerLevel(); + + // Task runner of outer class (the creating WebRtcAudioRenderer). + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + + // Using a raw pointer is safe since the OC instance will outlive this + // object. + WebRtcAudioRenderer* const renderer_; + + // Stores when the timer starts. Used to calculate the stream duration. + const base::TimeTicks start_time_; + + // Set to true in first render callback by the high-priority audio thread. + // Use an atomic variable since it can also be read by the outer class (OC) + // thread once to verify that callbacks started as intended. See comments + // for CheckAlive(). + std::atomic_bool render_callbacks_started_; + + // One-shot timer that fires ~5 seconds after rendering should start and + // calls the calls CheckAlive() which checks if |render_callbacks_started_| + // has been set to true or not. A message is logged to track this state. + // The timer uses the same task runner as the OC. Hence, the only writer of + // |render_callbacks_started_| is the render thread and the only reader is + // the OC thread. DCHECKs are used to confirm this. + TaskRunnerTimer<AudioStreamTracker> check_alive_timer_; + + // Scans audio samples from Render() as input to compute power levels. + media::AudioPowerMonitor power_monitor_; + + // Updated each time a power measurement is logged. + base::TimeTicks last_audio_level_log_time_; + + base::WeakPtr<AudioStreamTracker> weak_this_; + base::WeakPtrFactory<AudioStreamTracker> weak_factory_{this}; + }; + // Called when an audio renderer, either the main or a proxy, starts playing. // Here we maintain a reference count of how many renderers are currently // playing so that the shared play state of all the streams can be reflected @@ -144,12 +227,6 @@ ~WebRtcAudioRenderer() override; private: - enum State { - UNINITIALIZED, - PLAYING, - PAUSED, - }; - // Holds raw pointers to PlaingState objects. Ownership is managed outside // of this type. typedef std::vector<PlayingState*> PlayingStates; @@ -161,6 +238,9 @@ // Used to DCHECK that we are called on the correct thread. THREAD_CHECKER(thread_checker_); + // Task runner of the creating thread. + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + // Flag to keep track the state of the renderer. State state_; @@ -206,6 +286,8 @@ // |sink_|. void PrepareSink(); + void SendLogMessage(const WTF::String& message); + // The WebLocalFrame in which the audio is rendered into |sink_|. // // TODO(crbug.com/704136): Replace |source_internal_frame_| with regular @@ -223,6 +305,12 @@ // The media stream that holds the audio tracks that this renderer renders. const blink::WebMediaStream media_stream_; + // Contains a copy the unique id of the media stream. By taking a copy at + // construction, we can convert the id from a WebString to an std::string + // once and that saves resources when |media_stream_id_| is added to log + // messages. + std::string media_stream_id_; + // Audio data source from the browser process. // // TODO(crbug.com/704136): Make it a Member. @@ -230,7 +318,8 @@ // Protects access to |state_|, |source_|, |audio_fifo_|, // |audio_delay_milliseconds_|, |fifo_delay_milliseconds_|, |current_time_|, - // |sink_params_|, |render_callback_count_| and |max_render_time_|. + // |sink_params_|, |render_callback_count_|, |max_render_time_| and + // |audio_stream_tracker_|. mutable base::Lock lock_; // Ref count for the MediaPlayers which are playing audio. @@ -270,6 +359,11 @@ // for logging UMA data. Logged and reset when Stop() is called. base::TimeDelta max_render_time_; + // Used for keeping track of and logging stats for playing audio streams. + // Created when a stream starts and destroyed when a stream stops. + // See comments for AudioStreamTracker for more details. + base::Optional<AudioStreamTracker> audio_stream_tracker_; + DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioRenderer); };
diff --git a/third_party/blink/renderer/modules/webtransport/incoming_stream.cc b/third_party/blink/renderer/modules/webtransport/incoming_stream.cc index 9c82363..06f4c9f 100644 --- a/third_party/blink/renderer/modules/webtransport/incoming_stream.cc +++ b/third_party/blink/renderer/modules/webtransport/incoming_stream.cc
@@ -228,18 +228,36 @@ } void IncomingStream::ReadFromPipeAndEnqueue() { - DVLOG(1) << "IncomingStream::ReadFromPipeAndEnqueue() this=" << this; + DVLOG(1) << "IncomingStream::ReadFromPipeAndEnqueue() this=" << this + << " in_two_phase_read_=" << in_two_phase_read_ + << " read_pending_=" << read_pending_; + + // Protect against re-entrancy. + if (in_two_phase_read_) { + read_pending_ = true; + return; + } + DCHECK(!read_pending_); const void* buffer = nullptr; uint32_t buffer_num_bytes = 0; auto result = data_pipe_->BeginReadData(&buffer, &buffer_num_bytes, MOJO_BEGIN_READ_DATA_FLAG_NONE); - switch (result) { - case MOJO_RESULT_OK: + case MOJO_RESULT_OK: { + in_two_phase_read_ = true; + // EnqueueBytes() may re-enter this method via pull(). EnqueueBytes(buffer, buffer_num_bytes); data_pipe_->EndReadData(buffer_num_bytes); + in_two_phase_read_ = false; + if (read_pending_) { + read_pending_ = false; + // pull() will not be called when another pull() is in progress, so the + // maximum recursion depth is 1. + ReadFromPipeAndEnqueue(); + } break; + } case MOJO_RESULT_SHOULD_WAIT: read_watcher_.ArmOrNotify(); @@ -250,7 +268,7 @@ return; default: - DLOG(FATAL) << "FATAL ERROR"; + NOTREACHED() << "Unexpected result: " << result; return; } }
diff --git a/third_party/blink/renderer/modules/webtransport/incoming_stream.h b/third_party/blink/renderer/modules/webtransport/incoming_stream.h index 9ed4de75..82ede00 100644 --- a/third_party/blink/renderer/modules/webtransport/incoming_stream.h +++ b/third_party/blink/renderer/modules/webtransport/incoming_stream.h
@@ -153,6 +153,14 @@ // True when |data_pipe_| has been detected to be closed. The close is not // processed until |fin_received_| is also set. bool is_pipe_closed_ = false; + + // Indicates if we are currently performing a two-phase read from the pipe and + // so can't start another read. + bool in_two_phase_read_ = false; + + // Indicates if we need to perform another read after the current one + // completes. + bool read_pending_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc b/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc index 0251898..3fcdeb5c 100644 --- a/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc +++ b/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc
@@ -72,8 +72,8 @@ void ClosePipe() { data_pipe_producer_.reset(); } // Copies the contents of a v8::Value containing a Uint8Array to a Vector. - Vector<uint8_t> ToVector(const V8TestingScope& scope, - v8::Local<v8::Value> v8value) { + static Vector<uint8_t> ToVector(const V8TestingScope& scope, + v8::Local<v8::Value> v8value) { Vector<uint8_t> ret; DOMUint8Array* value = @@ -94,19 +94,23 @@ // Performs a single read from |reader|, converting the output to the // Iterator type. Assumes that the readable stream is not errored. - Iterator Read(const V8TestingScope& scope, - ReadableStreamDefaultReader* reader) { + static Iterator Read(const V8TestingScope& scope, + ReadableStreamDefaultReader* reader) { auto* script_state = scope.GetScriptState(); ScriptPromise read_promise = reader->read(script_state, ASSERT_NO_EXCEPTION); ScriptPromiseTester tester(script_state, read_promise); tester.WaitUntilSettled(); EXPECT_TRUE(tester.IsFulfilled()); - v8::Local<v8::Value> result = tester.Value().V8Value(); + return IteratorFromReadResult(scope, tester.Value().V8Value()); + } + + static Iterator IteratorFromReadResult(const V8TestingScope& scope, + v8::Local<v8::Value> result) { CHECK(result->IsObject()); Iterator ret; v8::Local<v8::Value> v8value; - if (!V8UnpackIteratorResult(script_state, result.As<v8::Object>(), + if (!V8UnpackIteratorResult(scope.GetScriptState(), result.As<v8::Object>(), &ret.done) .ToLocal(&v8value)) { ADD_FAILURE() << "Couldn't unpack iterator"; @@ -378,6 +382,29 @@ EXPECT_FALSE(incoming_stream); } +TEST_F(IncomingStreamTest, WriteToPipeWithPendingRead) { + V8TestingScope scope; + + auto* incoming_stream = CreateIncomingStream(scope); + auto* script_state = scope.GetScriptState(); + auto* reader = + incoming_stream->readable()->getReader(script_state, ASSERT_NO_EXCEPTION); + ScriptPromise read_promise = reader->read(script_state, ASSERT_NO_EXCEPTION); + ScriptPromiseTester tester(script_state, read_promise); + + test::RunPendingTasks(); + + WriteToPipe({'A'}); + + tester.WaitUntilSettled(); + EXPECT_TRUE(tester.IsFulfilled()); + + Iterator result = IteratorFromReadResult(scope, tester.Value().V8Value()); + EXPECT_FALSE(result.done); + EXPECT_THAT(result.value, ElementsAre('A')); + EXPECT_CALL(*mock_close_proxy_, ForgetStream()); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 476cd2f..fe6d0c08 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -443,6 +443,8 @@ "bindings/v8_binding.h", "bindings/v8_binding_macros.h", "bindings/v8_cross_origin_callback_info.h", + "bindings/v8_cross_origin_property_support.cc", + "bindings/v8_cross_origin_property_support.h", "bindings/v8_dom_activity_logger.cc", "bindings/v8_dom_activity_logger.h", "bindings/v8_dom_wrapper.cc",
diff --git a/third_party/blink/renderer/platform/bindings/v8_binding.h b/third_party/blink/renderer/platform/bindings/v8_binding.h index 028ef596..ed84d11 100644 --- a/third_party/blink/renderer/platform/bindings/v8_binding.h +++ b/third_party/blink/renderer/platform/bindings/v8_binding.h
@@ -229,6 +229,12 @@ V8SetReturnValue(info, ToV8(value, creation_context, info.GetIsolate())); } +template <class CallbackInfo> +void V8SetReturnValue(const CallbackInfo& info, + bindings::DictionaryBase* value) { + V8SetReturnValue(info, ToV8(value, info.Holder(), info.GetIsolate())); +} + // Convert v8::String to a WTF::String. If the V8 string is not already // an external string then it is transformed into an external string at this // point to avoid repeated conversions.
diff --git a/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc b/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc new file mode 100644 index 0000000..a434695b --- /dev/null +++ b/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.cc
@@ -0,0 +1,96 @@ +// 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/bindings/v8_cross_origin_property_support.h" + +#include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "third_party/blink/renderer/platform/bindings/v8_binding.h" +#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" + +namespace blink { + +namespace bindings { + +v8::MaybeLocal<v8::Function> GetCrossOriginFunction( + v8::Isolate* isolate, + v8::FunctionCallback callback, + int func_length, + const WrapperTypeInfo* wrapper_type_info) { + v8::Local<v8::Context> current_context = isolate->GetCurrentContext(); + ScriptState* script_state = ScriptState::From(current_context); + V8PerIsolateData* per_isolate_data = V8PerIsolateData::From(isolate); + const void* callback_key = reinterpret_cast<const void*>(callback); + + // ES functions accessible across origins are not interface objects, but we + // reuse the cache of interface objects, which just works because both are + // V8 function template. + v8::Local<v8::FunctionTemplate> function_template = + per_isolate_data->FindInterfaceTemplate(script_state->World(), + callback_key); + if (function_template.IsEmpty()) { + v8::Local<v8::FunctionTemplate> interface_template = + per_isolate_data->FindInterfaceTemplate(script_state->World(), + wrapper_type_info); + v8::Local<v8::Signature> signature = + v8::Signature::New(isolate, interface_template); + function_template = v8::FunctionTemplate::New( + isolate, callback, v8::Local<v8::Value>(), signature, func_length, + v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasSideEffect); + per_isolate_data->SetInterfaceTemplate(script_state->World(), callback_key, + function_template); + } + return function_template->GetFunction(current_context); +} + +v8::MaybeLocal<v8::Value> GetCrossOriginFunctionOrUndefined( + v8::Isolate* isolate, + v8::FunctionCallback callback, + int func_length, + const WrapperTypeInfo* wrapper_type_info) { + if (!callback) { + return v8::Undefined(isolate); + } + v8::Local<v8::Function> function; + if (GetCrossOriginFunction(isolate, callback, func_length, wrapper_type_info) + .ToLocal(&function)) { + return function; + } + return v8::MaybeLocal<v8::Value>(); +} + +bool IsSupportedInCrossOriginPropertyFallback( + v8::Isolate* isolate, + v8::Local<v8::Name> property_name) { + return (property_name == V8AtomicString(isolate, "then") || + property_name == v8::Symbol::GetToStringTag(isolate) || + property_name == v8::Symbol::GetHasInstance(isolate) || + property_name == v8::Symbol::GetIsConcatSpreadable(isolate)); +} + +v8::Local<v8::Array> EnumerateCrossOriginProperties( + v8::Isolate* isolate, + base::span<const CrossOriginAttributeTableEntry> attributes, + base::span<const CrossOriginOperationTableEntry> operations) { + v8::Local<v8::Value> default_supported[] = { + V8AtomicString(isolate, "then"), + v8::Symbol::GetToStringTag(isolate), + v8::Symbol::GetHasInstance(isolate), + v8::Symbol::GetIsConcatSpreadable(isolate), + }; + const uint32_t length = + attributes.size() + operations.size() + base::size(default_supported); + Vector<v8::Local<v8::Value>> elements; + elements.ReserveCapacity(length); + for (const auto& attribute : attributes) + elements.UncheckedAppend(V8AtomicString(isolate, attribute.name)); + for (const auto& operation : operations) + elements.UncheckedAppend(V8AtomicString(isolate, operation.name)); + for (const auto& name : default_supported) + elements.UncheckedAppend(name); + return v8::Array::New(isolate, elements.data(), elements.size()); +} + +} // namespace bindings + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h b/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h new file mode 100644 index 0000000..d441696a --- /dev/null +++ b/third_party/blink/renderer/platform/bindings/v8_cross_origin_property_support.h
@@ -0,0 +1,65 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_PROPERTY_SUPPORT_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_PROPERTY_SUPPORT_H_ + +#include "base/containers/span.h" +#include "third_party/blink/renderer/platform/platform_export.h" +#include "v8/include/v8.h" + +// This file provides utilities to support implementation of cross origin +// properties in generated bindings code. Should be used only in generated +// bindings code. + +namespace blink { + +struct WrapperTypeInfo; + +namespace bindings { + +struct CrossOriginAttributeTableEntry final { + const char* name; + v8::FunctionCallback get_callback; + v8::FunctionCallback set_callback; + v8::GenericNamedPropertyGetterCallback get_value; + v8::GenericNamedPropertySetterCallback set_value; +}; + +struct CrossOriginOperationTableEntry final { + const char* name; + v8::FunctionCallback callback; + int func_length; +}; + +PLATFORM_EXPORT v8::MaybeLocal<v8::Function> GetCrossOriginFunction( + v8::Isolate* isolate, + v8::FunctionCallback callback, + int func_length, + const WrapperTypeInfo* wrapper_type_info); + +PLATFORM_EXPORT v8::MaybeLocal<v8::Value> GetCrossOriginFunctionOrUndefined( + v8::Isolate* isolate, + v8::FunctionCallback callback, + int func_length, + const WrapperTypeInfo* wrapper_type_info); + +// HTML 7.2.3.2 CrossOriginPropertyFallback ( P ) +// https://html.spec.whatwg.org/C/#crossoriginpropertyfallback-(-p-) +PLATFORM_EXPORT bool IsSupportedInCrossOriginPropertyFallback( + v8::Isolate* isolate, + v8::Local<v8::Name> property_name); + +// HTML 7.2.3.7 CrossOriginOwnPropertyKeys ( O ) +// https://html.spec.whatwg.org/C/#crossoriginownpropertykeys-(-o-) +PLATFORM_EXPORT v8::Local<v8::Array> EnumerateCrossOriginProperties( + v8::Isolate* isolate, + base::span<const CrossOriginAttributeTableEntry> attributes, + base::span<const CrossOriginOperationTableEntry> operations); + +} // namespace bindings + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_CROSS_ORIGIN_PROPERTY_SUPPORT_H_
diff --git a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h index ed639ef..6c7ffa11 100644 --- a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h +++ b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
@@ -116,7 +116,7 @@ // nullptr template <typename CallbackInfo> -void V8SetReturnValue(const CallbackInfo& info, nullptr_t) { +void V8SetReturnValue(const CallbackInfo& info, std::nullptr_t) { info.GetReturnValue().SetNull(); }
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc b/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc index 6a2d4fd..24f05b8f 100644 --- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc +++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
@@ -27,7 +27,7 @@ : WebPlatformMediaStreamTrack(is_local_track), is_enabled_(1) { SendLogMessage( base::StringPrintf("MediaStreamAudioTrack([this=%p] {is_local_track=%s})", - this, (is_local_track ? "local" : "remote"))); + this, (is_local_track ? "true" : "false"))); } MediaStreamAudioTrack::~MediaStreamAudioTrack() {
diff --git a/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h b/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h index cf456d9..dd5da3c 100644 --- a/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h +++ b/third_party/blink/renderer/platform/mojo/heap_mojo_remote.h
@@ -53,6 +53,7 @@ DCHECK(task_runner); wrapper_->remote().Bind(std::move(pending_remote), std::move(task_runner)); } + void FlushForTesting() { return wrapper_->remote().FlushForTesting(); } void Trace(Visitor* visitor) { visitor->Trace(wrapper_); }
diff --git a/third_party/blink/renderer/platform/wtf/linked_hash_set.h b/third_party/blink/renderer/platform/wtf/linked_hash_set.h index 7be2da08..9ddc8b8 100644 --- a/third_party/blink/renderer/platform/wtf/linked_hash_set.h +++ b/third_party/blink/renderer/platform/wtf/linked_hash_set.h
@@ -991,10 +991,10 @@ typedef typename HashTraits<Value>::PeekInType ValuePeekInType; NewLinkedHashSet(); - NewLinkedHashSet(const NewLinkedHashSet&); - NewLinkedHashSet(NewLinkedHashSet&&); - NewLinkedHashSet& operator=(const NewLinkedHashSet&); - NewLinkedHashSet& operator=(NewLinkedHashSet&&); + NewLinkedHashSet(const NewLinkedHashSet&) = default; + NewLinkedHashSet(NewLinkedHashSet&&) = default; + NewLinkedHashSet& operator=(const NewLinkedHashSet&) = default; + NewLinkedHashSet& operator=(NewLinkedHashSet&&) = default; ~NewLinkedHashSet() = default; @@ -1072,7 +1072,7 @@ }; template <typename T, typename Allocator> -NewLinkedHashSet<T, Allocator>::NewLinkedHashSet() { +inline NewLinkedHashSet<T, Allocator>::NewLinkedHashSet() { static_assert(Allocator::kIsGarbageCollected || !IsPointerToGarbageCollectedType<T>::value, "Cannot put raw pointers to garbage-collected classes into " @@ -1080,30 +1080,6 @@ "HeapNewLinkedHashSet<Member<T>> instead."); } -// TODO(keinakashima): add copy constructor after implementing iterator if -// anybody uses it. - -template <typename T, typename Allocator> -inline NewLinkedHashSet<T, Allocator>::NewLinkedHashSet( - NewLinkedHashSet&& other) { - Swap(other); -} - -template <typename T, typename Allocator> -inline NewLinkedHashSet<T, Allocator>& NewLinkedHashSet<T, Allocator>:: -operator=(const NewLinkedHashSet& other) { - NewLinkedHashSet tmp(other); - Swap(tmp); - return *this; -} - -template <typename T, typename Allocator> -inline NewLinkedHashSet<T, Allocator>& NewLinkedHashSet<T, Allocator>:: -operator=(NewLinkedHashSet&& other) { - Swap(other); - return *this; -} - template <typename T, typename Allocator> inline void NewLinkedHashSet<T, Allocator>::Swap(NewLinkedHashSet& other) { value_to_index_.swap(other.value_to_index_);
diff --git a/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc b/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc index 0c7622c..bcfb0be1 100644 --- a/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc +++ b/third_party/blink/renderer/platform/wtf/linked_hash_set_test.cc
@@ -7,13 +7,178 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/wtf/text/string_hash.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/blink/renderer/platform/wtf/wtf_test_helper.h" namespace WTF { -TEST(NewLinkedHashSetTest, Construct) { - NewLinkedHashSet<int> test; - EXPECT_EQ(test.size(), 0u); - EXPECT_TRUE(test.IsEmpty()); +TEST(NewLinkedHashSetTest, CopyConstructAndAssignInt) { + NewLinkedHashSet<int> set1; + EXPECT_EQ(set1.size(), 0u); + EXPECT_TRUE(set1.IsEmpty()); + set1.insert(1); + set1.insert(2); + set1.insert(3); + EXPECT_EQ(set1.size(), 3u); + NewLinkedHashSet<int> set2(set1); + EXPECT_EQ(set2.size(), 3u); + NewLinkedHashSet<int> set3; + EXPECT_EQ(set3.size(), 0u); + set3 = set2; + EXPECT_EQ(set3.size(), 3u); + auto it1 = set1.begin(); + auto it2 = set2.begin(); + auto it3 = set3.begin(); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(*it1, i + 1); + EXPECT_EQ(*it2, i + 1); + EXPECT_EQ(*it3, i + 1); + ++it1; + ++it2; + ++it3; + } +} + +TEST(NewLinkedHashSetTest, CopyConstructAndAssignIntPtr) { + NewLinkedHashSet<int*> set1; + EXPECT_EQ(set1.size(), 0u); + EXPECT_TRUE(set1.IsEmpty()); + std::unique_ptr<int> int1 = std::make_unique<int>(1); + std::unique_ptr<int> int2 = std::make_unique<int>(2); + std::unique_ptr<int> int3 = std::make_unique<int>(3); + set1.insert(int1.get()); + set1.insert(int2.get()); + set1.insert(int3.get()); + EXPECT_EQ(set1.size(), 3u); + NewLinkedHashSet<int*> set2(set1); + EXPECT_EQ(set2.size(), 3u); + NewLinkedHashSet<int*> set3; + EXPECT_EQ(set3.size(), 0u); + set3 = set2; + EXPECT_EQ(set3.size(), 3u); + auto it1 = set1.begin(); + auto it2 = set2.begin(); + auto it3 = set3.begin(); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(**it1, i + 1); + EXPECT_EQ(**it2, i + 1); + EXPECT_EQ(**it3, i + 1); + ++it1; + ++it2; + ++it3; + } + + for (int* ptr : set1) + *ptr += 1000; + it1 = set1.begin(); + it2 = set2.begin(); + it3 = set3.begin(); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(**it1, i + 1001); + EXPECT_EQ(**it2, i + 1001); + EXPECT_EQ(**it3, i + 1001); + ++it1; + ++it2; + ++it3; + } +} + +TEST(NewLinkedHashSetTest, CopyConstructAndAssignString) { + NewLinkedHashSet<String> set1; + EXPECT_EQ(set1.size(), 0u); + EXPECT_TRUE(set1.IsEmpty()); + set1.insert("1"); + set1.insert("2"); + set1.insert("3"); + EXPECT_EQ(set1.size(), 3u); + NewLinkedHashSet<String> set2(set1); + EXPECT_EQ(set2.size(), 3u); + NewLinkedHashSet<String> set3; + EXPECT_EQ(set3.size(), 0u); + set3 = set2; + EXPECT_EQ(set3.size(), 3u); + auto it1 = set1.begin(); + auto it2 = set2.begin(); + auto it3 = set3.begin(); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(*it1, String(Vector<UChar>({'1' + i}))); + EXPECT_EQ(*it2, String(Vector<UChar>({'1' + i}))); + EXPECT_EQ(*it3, String(Vector<UChar>({'1' + i}))); + ++it1; + ++it2; + ++it3; + } +} + +TEST(NewLinkedHashSetTest, MoveConstructAndAssignInt) { + NewLinkedHashSet<ValueInstanceCount<int>> set1; + EXPECT_EQ(set1.size(), 0u); + EXPECT_TRUE(set1.IsEmpty()); + int counter1 = 0; + int counter2 = 0; + int counter3 = 0; + set1.insert(ValueInstanceCount<int>(&counter1, 1)); + set1.insert(ValueInstanceCount<int>(&counter2, 2)); + set1.insert(ValueInstanceCount<int>(&counter3, 3)); + EXPECT_EQ(set1.size(), 3u); + NewLinkedHashSet<ValueInstanceCount<int>> set2(std::move(set1)); + EXPECT_EQ(set2.size(), 3u); + NewLinkedHashSet<ValueInstanceCount<int>> set3; + EXPECT_EQ(set3.size(), 0u); + set3 = std::move(set2); + EXPECT_EQ(set3.size(), 3u); + auto it = set3.begin(); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(it->Value(), i + 1); + ++it; + } + + // Only move constructors were used, each object is only in set3. + // Count 2x because each set uses hash map and vector. + EXPECT_EQ(counter1, 2); + EXPECT_EQ(counter2, 2); + EXPECT_EQ(counter3, 2); + + NewLinkedHashSet<ValueInstanceCount<int>> set4(set3); + // Copy constructor was used, each object is in set3 and set4. + EXPECT_EQ(counter1, 4); + EXPECT_EQ(counter2, 4); + EXPECT_EQ(counter3, 4); +} + +TEST(NewLinkedHashSetTest, MoveConstructAndAssignString) { + NewLinkedHashSet<ValueInstanceCount<String>> set1; + EXPECT_EQ(set1.size(), 0u); + EXPECT_TRUE(set1.IsEmpty()); + int counter1 = 0; + int counter2 = 0; + int counter3 = 0; + set1.insert(ValueInstanceCount<String>(&counter1, "1")); + set1.insert(ValueInstanceCount<String>(&counter2, "2")); + set1.insert(ValueInstanceCount<String>(&counter3, "3")); + EXPECT_EQ(set1.size(), 3u); + NewLinkedHashSet<ValueInstanceCount<String>> set2(std::move(set1)); + EXPECT_EQ(set2.size(), 3u); + NewLinkedHashSet<ValueInstanceCount<String>> set3; + EXPECT_EQ(set3.size(), 0u); + set3 = std::move(set2); + EXPECT_EQ(set3.size(), 3u); + auto it = set3.begin(); + for (int i = 0; i < 3; i++) { + EXPECT_EQ(it->Value(), String(Vector<UChar>({'1' + i}))); + ++it; + } + + // Only move constructors were used, each object is only in set3. + // Count 2x because each set uses hash map and vector. + EXPECT_EQ(counter1, 2); + EXPECT_EQ(counter2, 2); + EXPECT_EQ(counter3, 2); + + NewLinkedHashSet<ValueInstanceCount<String>> set4(set3); + // Copy constructor was used, each object is in set3 and set4. + EXPECT_EQ(counter1, 4); + EXPECT_EQ(counter2, 4); + EXPECT_EQ(counter3, 4); } TEST(NewLinkedHashSetTest, Iterator) {
diff --git a/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h b/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h index 02a481a..60383b8a 100644 --- a/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h +++ b/third_party/blink/renderer/platform/wtf/vector_backed_linked_list.h
@@ -44,13 +44,10 @@ next_index_(next_index), value_(std::move(value)) {} - VectorBackedLinkedListNode(const VectorBackedLinkedListNode& other) = delete; - + VectorBackedLinkedListNode(const VectorBackedLinkedListNode& other) = default; VectorBackedLinkedListNode(VectorBackedLinkedListNode&& other) = default; - VectorBackedLinkedListNode& operator=( - const VectorBackedLinkedListNode& other) = delete; - + const VectorBackedLinkedListNode& other) = default; VectorBackedLinkedListNode& operator=(VectorBackedLinkedListNode&& other) = default; @@ -119,9 +116,10 @@ VectorBackedLinkedList(); - // TODO(keinakashima): implement copy constructor & copy assignment operator - VectorBackedLinkedList(VectorBackedLinkedList&&); - VectorBackedLinkedList& operator=(VectorBackedLinkedList&&); + VectorBackedLinkedList(const VectorBackedLinkedList&) = default; + VectorBackedLinkedList(VectorBackedLinkedList&&) = default; + VectorBackedLinkedList& operator=(const VectorBackedLinkedList&) = default; + VectorBackedLinkedList& operator=(VectorBackedLinkedList&&) = default; ~VectorBackedLinkedList() = default; @@ -471,20 +469,6 @@ } template <typename T, typename Allocator> -inline VectorBackedLinkedList<T, Allocator>::VectorBackedLinkedList( - VectorBackedLinkedList&& other) { - swap(other); -} - -template <typename T, typename Allocator> -inline VectorBackedLinkedList<T, Allocator>& -VectorBackedLinkedList<T, Allocator>::operator=( - VectorBackedLinkedList&& other) { - swap(other); - return *this; -} - -template <typename T, typename Allocator> inline void VectorBackedLinkedList<T, Allocator>::swap( VectorBackedLinkedList& other) { nodes_.swap(other.nodes_);
diff --git a/third_party/blink/renderer/platform/wtf/wtf_test_helper.h b/third_party/blink/renderer/platform/wtf/wtf_test_helper.h index 8f31365..35b1e73c 100644 --- a/third_party/blink/renderer/platform/wtf/wtf_test_helper.h +++ b/third_party/blink/renderer/platform/wtf/wtf_test_helper.h
@@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_WTF_TEST_HELPER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_WTF_TEST_HELPER_H_ +#include <type_traits> + #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "testing/gtest/include/gtest/gtest.h" @@ -177,6 +179,75 @@ using Hash = CountCopyHash; }; +template <typename T> +class ValueInstanceCount final { + public: + ValueInstanceCount() : counter_(nullptr), value_(T()) {} + explicit ValueInstanceCount(int* counter, T value = T()) + : counter_(counter), value_(value) { + DCHECK(counter_); + *counter = 1; + } + ValueInstanceCount(const ValueInstanceCount& other) + : counter_(other.counter_), value_(other.value_) { + if (counter_) + ++*counter_; + } + ValueInstanceCount& operator=(const ValueInstanceCount& other) { + counter_ = other.counter_; + value_ = other.value_; + if (counter_) + ++*counter_; + return *this; + } + ~ValueInstanceCount() { + if (counter_) + --*counter_; + } + + const int* Counter() const { return counter_; } + const T& Value() const { return value_; } + + private: + int* counter_; + T value_; +}; + +template <typename T> +struct ValueInstanceCountHashTraits + : public GenericHashTraits<ValueInstanceCount<T>> { + static const bool kEmptyValueIsZero = false; + static const bool kHasIsEmptyValueFunction = true; + static bool IsEmptyValue(const ValueInstanceCount<T>& value) { + return !value.Counter(); + } + static void ConstructDeletedValue(ValueInstanceCount<T>& slot, bool) {} + static bool IsDeletedValue(const ValueInstanceCount<T>& value) { + return false; + } +}; + +template <typename T> +struct ValueInstanceCountHash : public PtrHash<const int*> { + static unsigned GetHash(const ValueInstanceCount<T>& value) { + return PtrHash<const int>::GetHash(value.Counter()); + } + static bool Equal(const ValueInstanceCount<T>& left, + const ValueInstanceCount<T>& right) { + return PtrHash<const int>::Equal(left.Counter(), right.Counter()); + } + static const bool safe_to_compare_to_empty_or_deleted = true; +}; + +template <typename T> +struct HashTraits<ValueInstanceCount<T>> + : public ValueInstanceCountHashTraits<T> {}; + +template <typename T> +struct DefaultHash<ValueInstanceCount<T>> { + using Hash = ValueInstanceCountHash<T>; +}; + class DummyRefCounted : public RefCounted<DummyRefCounted> { public: DummyRefCounted(bool& is_deleted) : is_deleted_(is_deleted) {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 7fceee1..dad01ff 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2938,6 +2938,7 @@ crbug.com/947951 [ Win ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch.html [ Pass Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac10.14 ] external/wpt/preload/download-resources.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] virtual/threaded/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-rl.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] virtual/threaded/external/wpt/requestidlecallback/callback-invoked.html [ Timeout ] crbug.com/626703 [ Mac10.10 ] virtual/threaded/external/wpt/css/css-animations/parsing/animation-shorthand.html [ Timeout ] @@ -4714,11 +4715,7 @@ crbug.com/791529 external/wpt/css/css-variables/variable-transitions-value-before-transition-property-variable.html [ Skip ] # Feature Policy changes fullscreen behaviour, tests need updating -crbug.com/718155 fullscreen/full-screen-iframe-not-allowed.html [ Failure ] crbug.com/718155 fullscreen/full-screen-restrictions.html [ Failure Timeout ] -crbug.com/718155 media/video-controls-fullscreen-iframe-not-allowed.html [ Failure ] -crbug.com/718155 virtual/audio-service/media/video-controls-fullscreen-iframe-not-allowed.html [ Failure ] -crbug.com/718155 virtual/android/fullscreen/full-screen-iframe-not-allowed.html [ Failure ] crbug.com/718155 virtual/android/fullscreen/full-screen-restrictions.html [ Failure Timeout ] crbug.com/852645 gamepad/full-screen-gamepad.html [ Timeout ] @@ -5718,19 +5715,6 @@ # Sheriff 2019-04-25 crbug.com/956736 virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-not-inherited-from-map.html [ Pass Failure ] -crbug.com/946534 [ Mac10.10 ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.11 ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.10 ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.11 ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.10 ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.11 ] external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.10 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.10 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.10 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ] -crbug.com/946534 [ Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ] - crbug.com/1065059 [ Linux ] virtual/threaded-no-composited-antialiasing/animations/animationworklet/scroll-timeline-non-scrollable.html [ Pass Crash ] crbug.com/1065059 [ Linux ] virtual/threaded-no-composited-antialiasing/animations/animationworklet/playback-rate-scroll-timeline-accelerated-property.html [ Pass Crash ] crbug.com/1065059 [ Linux ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Crash ]
diff --git a/third_party/blink/web_tests/css3/flexbox/minimum-size-image.html b/third_party/blink/web_tests/css3/flexbox/minimum-size-image.html deleted file mode 100644 index 67bd361..0000000 --- a/third_party/blink/web_tests/css3/flexbox/minimum-size-image.html +++ /dev/null
@@ -1,70 +0,0 @@ -<!DOCTYPE html> - -<link href="resources/flexbox.css" rel="stylesheet"> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../../resources/check-layout-th.js"></script> - -<body onload="checkLayout('.flexbox')"> -<div id=log></div> - -<div class="flexbox" style="width: 10px;" data-expected-width="10"> - <!-- should use content width, clamped by converted max-height, as minimum width. --> - <img src="../../images/resources/green-100.png" style="max-height: 5px;" - data-expected-width="5" data-expected-height="5"> -</div> - -<div class="flexbox" style="width: 10px;" data-expected-width="10"> - <!-- should use min(specified, content width) = 10px as minimum width, - which the image will shrink to due to default flex-shrink. --> - <img src="../../images/resources/green-10.png" style="width: 100px;" data-expected-width="10"> -</div> - - -<div class="flexbox" style="width: 10px;" data-expected-width="10"> - <!-- should use content width, clamped by converted min-height, as minimum width. --> - <img src="../../images/resources/green-100.png" style="max-height: 5px;" - data-expected-width="5" data-expected-height="5"> -</div> - -<div class="flexbox" style="width: 10px;" data-expected-width="10"> - <!-- should use content width, clamped by converted min-height, as minimum width. --> - <img src="../../images/resources/green-100.png" style="max-height: 5px; min-height: 10px;" - data-expected-width="10" data-expected-height="10"> -</div> - -<div class="flexbox" style="width: 10px;" data-expected-width="10"> - <!-- should use min(transferred, content width) = 10px as minimum width, - which the image will shrink to due to default flex-shrink. --> - <img src="../../images/resources/green-10.png" style="height: 100px;" data-expected-width="10"> -</div> - -<div class="flexbox column" style="height: 10px;" data-expected-height="10"> - <!-- should use content height, clamped by converted max-width, as minimum height. --> - <img src="../../images/resources/green-100.png" style="max-width: 5px;" - data-expected-width="5" data-expected-height="5"> -</div> - -<div class="flexbox column" style="height: 10px;" data-expected-height="10"> - <!-- should use min(specified, content height) = 10px as minimum height, - which the image will shrink to due to default flex-shrink. --> - <img src="../../images/resources/green-10.png" style="height: 100px;" data-expected-height="10"> -</div> - -<div class="flexbox" style="height: 10px;" data-expected-height="10"> - <!-- should use content height, clamped by converted min-height, as minimum height. --> - <img src="../../images/resources/green-100.png" style="max-height: 5px;" - data-expected-height="5" data-expected-height="5"> -</div> - -<div class="flexbox" style="height: 10px;" data-expected-height="10"> - <!-- should use content height, clamped by converted min-width, as minimum height. --> - <img src="../../images/resources/green-100.png" style="max-width: 5px; min-width: 10px;" - data-expected-height="10" data-expected-width="10"> -</div> - -<div class="flexbox column" style="height: 10px;" data-expected-height="10"> - <!-- should use min(transferred, content height) = 10px as minimum height, - which the image will shrink to due to default flex-shrink. --> - <img src="../../images/resources/green-10.png" style="width: 100px;" data-expected-height="10"> -</div>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json index 33fe265..c42401f 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -142448,6 +142448,9 @@ "css/css-flexbox/support/100x100-green.png": [ [] ], + "css/css-flexbox/support/10x10-green.png": [ + [] + ], "css/css-flexbox/support/1x1-green.png": [ [] ], @@ -142982,6 +142985,9 @@ "css/css-fonts/font-weight-xxx-large-ref.html": [ [] ], + "css/css-fonts/generic-family-keywords-001-expected.txt": [ + [] + ], "css/css-fonts/idlharness-expected.txt": [ [] ], @@ -143201,6 +143207,9 @@ "css/css-fonts/support/diamond.png": [ [] ], + "css/css-fonts/support/font-family-keywords.js": [ + [] + ], "css/css-fonts/support/font-weight-bolder-001-ref.png": [ [] ], @@ -163757,6 +163766,9 @@ "feature-policy/resources/feature-policy-report-json.js": [ [] ], + "feature-policy/resources/feature-policy-screen-wakelock.html": [ + [] + ], "feature-policy/resources/feature-policy-serial-worker.html": [ [] ], @@ -163775,9 +163787,6 @@ "feature-policy/resources/feature-policy-usb.html": [ [] ], - "feature-policy/resources/feature-policy-wakelock.html": [ - [] - ], "feature-policy/resources/featurepolicy.js": [ [] ], @@ -218804,6 +218813,12 @@ {} ] ], + "css/css-flexbox/flex-aspect-ratio-img-column-011.html": [ + [ + "css/css-flexbox/flex-aspect-ratio-img-column-011.html", + {} + ] + ], "css/css-flexbox/flex-basis-009.html": [ [ "css/css-flexbox/flex-basis-009.html", @@ -218864,6 +218879,12 @@ {} ] ], + "css/css-flexbox/flex-minimum-width-flex-items-014.html": [ + [ + "css/css-flexbox/flex-minimum-width-flex-items-014.html", + {} + ] + ], "css/css-flexbox/flex-outer-flexbox-column-recalculate-height-on-resize-001.html": [ [ "css/css-flexbox/flex-outer-flexbox-column-recalculate-height-on-resize-001.html", @@ -219368,12 +219389,6 @@ {} ] ], - "css/css-flexbox/intrinsic-min-width-applies-with-fixed-width.html": [ - [ - "css/css-flexbox/intrinsic-min-width-applies-with-fixed-width.html", - {} - ] - ], "css/css-flexbox/intrinsic-width-orthogonal-writing-mode.html": [ [ "css/css-flexbox/intrinsic-width-orthogonal-writing-mode.html", @@ -219386,6 +219401,12 @@ {} ] ], + "css/css-flexbox/max-width-violation.html": [ + [ + "css/css-flexbox/max-width-violation.html", + {} + ] + ], "css/css-flexbox/order_value.html": [ [ "css/css-flexbox/order_value.html", @@ -219746,6 +219767,12 @@ {} ] ], + "css/css-fonts/generic-family-keywords-002.html": [ + [ + "css/css-fonts/generic-family-keywords-002.html", + {} + ] + ], "css/css-fonts/idlharness.html": [ [ "css/css-fonts/idlharness.html", @@ -234704,6 +234731,12 @@ {} ] ], + "css/cssom/font-family-serialization-001.html": [ + [ + "css/cssom/font-family-serialization-001.html", + {} + ] + ], "css/cssom/font-shorthand-serialization.html": [ [ "css/cssom/font-shorthand-serialization.html", @@ -323203,6 +323236,14 @@ {} ] ], + "webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp.html": [ + [ + "webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp.html", + { + "timeout": "long" + } + ] + ], "webrtc-identity/RTCPeerConnection-constructor.html": [ [ "webrtc-identity/RTCPeerConnection-constructor.html", @@ -382069,6 +382110,10 @@ "70ebd378a4a7c00059bed9e7ff57febd5a252fba", "reftest" ], + "css/css-flexbox/flex-aspect-ratio-img-column-011.html": [ + "66cb0e015f6618eb7cc3daee99f29ddbf7ed4729", + "testharness" + ], "css/css-flexbox/flex-aspect-ratio-img-row-001.html": [ "14fabf760ca4293abf5af9e618b2e2ed627be2b2", "reftest" @@ -382501,6 +382546,10 @@ "6ee9ed10b5663b381f0238096117e8d70ca0347b", "reftest" ], + "css/css-flexbox/flex-minimum-width-flex-items-014.html": [ + "080169b52d7fdf39cbf6ff970c3100480e46d2a3", + "testharness" + ], "css/css-flexbox/flex-order-ref.html": [ "02f0eb35752e805aa2bc0bd339f73ff2b197c99e", "support" @@ -384741,10 +384790,6 @@ "684233223b82c7105a9550e4957597acc0153e75", "manual" ], - "css/css-flexbox/intrinsic-min-width-applies-with-fixed-width.html": [ - "080169b52d7fdf39cbf6ff970c3100480e46d2a3", - "testharness" - ], "css/css-flexbox/intrinsic-width-orthogonal-writing-mode.html": [ "79ce88a64c266f5ec02702d510668c642c0f91cb", "testharness" @@ -384809,6 +384854,10 @@ "1d860b44003fa9e2a765e37fdff8a8afbf78a27e", "reftest" ], + "css/css-flexbox/max-width-violation.html": [ + "ea2779d81c5e4bab26b77337173f64ac0c08f493", + "testharness" + ], "css/css-flexbox/negative-margins-001.html": [ "cd14ce0d4ede6f950ea6fd92176cfea662e45170", "reftest" @@ -385301,6 +385350,10 @@ "25b76c3c6f216793a36b1f29287dafd993898c67", "support" ], + "css/css-flexbox/support/10x10-green.png": [ + "8c39b0d02d342bbf1edd2ebbcc2ff4ff8b032e10", + "support" + ], "css/css-flexbox/support/1x1-green.png": [ "b98ca0ba0a03c580ac339e4a3653539cfa8edc71", "support" @@ -386821,8 +386874,16 @@ "480396ea16f81e96b411b7c75a7cd33e758b3e34", "testharness" ], + "css/css-fonts/generic-family-keywords-001-expected.txt": [ + "85ec8839fba729aa82168c814ca086c7daa88411", + "support" + ], "css/css-fonts/generic-family-keywords-001.html": [ - "aa9fb5a6a03bb330d35669f903a1ee7c0f138e18", + "bd39bac3ff8b3cda7e7eb60c75b0b5e6589f6110", + "testharness" + ], + "css/css-fonts/generic-family-keywords-002.html": [ + "7399860b03c6cd69dc48750b884221177112373b", "testharness" ], "css/css-fonts/idlharness-expected.txt": [ @@ -387501,6 +387562,10 @@ "51112efc7cab5b20a86bae9e4c2aebd68a5230b0", "support" ], + "css/css-fonts/support/font-family-keywords.js": [ + "fc5b723e6875c8abe4905a23b8ab631db9934dfd", + "support" + ], "css/css-fonts/support/font-weight-bolder-001-ref.png": [ "42675efe43e614e824ae500ce6cbd511a22f7a8e", "support" @@ -438337,6 +438402,10 @@ "721c6ea35572d42e2782d6f40f7e73539df35b3a", "testharness" ], + "css/cssom/font-family-serialization-001.html": [ + "6c59b985c4fd5483b4c3f186e2917a20b428ee5b", + "testharness" + ], "css/cssom/font-shorthand-serialization.html": [ "29082f83eaf75a0831e5175b8b1217c4ecf4ebcd", "testharness" @@ -455425,6 +455494,10 @@ "08a0ecaded8c5af917be1ae1287d455483205e45", "support" ], + "feature-policy/resources/feature-policy-screen-wakelock.html": [ + "7d3dab45af1d57c805f14cfdbed142ddb2415eba", + "support" + ], "feature-policy/resources/feature-policy-serial-worker.html": [ "9e6a7d02ba2b8eef1fcc12d8049af830688e6946", "support" @@ -455449,10 +455522,6 @@ "99d47c6f3929bd61f7dfdefb1c5488c396abc172", "support" ], - "feature-policy/resources/feature-policy-wakelock.html": [ - "7d3dab45af1d57c805f14cfdbed142ddb2415eba", - "support" - ], "feature-policy/resources/featurepolicy.js": [ "9aba0ab8c675352301802f2386f07470585d7e97", "support" @@ -521982,11 +522051,11 @@ "testharness" ], "wake-lock/wakelock-disabled-by-feature-policy.https.sub.html": [ - "3c902cc91952a3ee849ffc19a3ccc1e25098b107", + "821ec62885d61b214f766b4c8e173f8b67855f38", "testharness" ], "wake-lock/wakelock-disabled-by-feature-policy.https.sub.html.headers": [ - "1d3769ec794b353e8c614e64ce2c1b0b1010e528", + "5d910ce6df801980a26fb191589201f614ed02af", "support" ], "wake-lock/wakelock-document-hidden-manual.https.html": [ @@ -521994,27 +522063,27 @@ "manual" ], "wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html": [ - "f28a96141c8994125b04c29e440743d2e7837544", + "2b2e0c94cc744ff6c19f70397e4383fa2d809cff", "testharness" ], "wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html": [ - "5587a85d4b027d360c35103f99bb6e6afe31f18a", + "b8ab3b0301798bc7ceaed025e89b0a36dfa5b58c", "testharness" ], "wake-lock/wakelock-enabled-by-feature-policy.https.sub.html": [ - "d0f5a15c84bf83dfdaf801e8709d1d7c37f6d91a", + "376359e888d6191b9eb1241373b3d411bb5bd2d0", "testharness" ], "wake-lock/wakelock-enabled-by-feature-policy.https.sub.html.headers": [ - "34b7437443cd9998c423260d05202be05d7b5d38", + "7810751f8051c14818b290aa9ea7edab04bca3e9", "support" ], "wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html": [ - "73f343867e62c46c4f6e5a4458a384ef652bafd1", + "a2d3725857be76f33b33257c0c3373edb68396be", "testharness" ], "wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html.headers": [ - "6f05d23550e2b0c967fac5b436a5e3336222ffe2", + "6bc94277cf9a4610c33274bd5b984e41d389622a", "support" ], "wake-lock/wakelock-insecure-context.any.js": [ @@ -522034,7 +522103,7 @@ "testharness" ], "wake-lock/wakelock-supported-by-feature-policy.html": [ - "d6289fff43c8717ac6e9ace59713e6fd70bd249d", + "e7f9c8cb283c20d72c6d936398b9c352a2a0b88a", "testharness" ], "wake-lock/wakelock-type.https.any.js": [ @@ -526301,6 +526370,10 @@ "29dfc19a6b68900679b06b3c3527c177c4e38b48", "testharness" ], + "webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp.html": [ + "0902118a456e6f072d4a9b0791a4f2ea86a54e72", + "testharness" + ], "webrtc-identity/META.yml": [ "940144cee1da5f2f0f2bdd27a8dfc8f5bfcc6a1d", "support"
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html index 7dea4609..ceb5f2d7 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html
@@ -21,7 +21,13 @@ background-color: red; } + /* Hide scrollbars to avoid unnecessary visual issues related to them */ + #scroller::-webkit-scrollbar { + display: none; + } + #scroller { + scrollbar-width: none; overflow: auto; height: 100px; width: 100px; @@ -75,4 +81,4 @@ }); }); }); -</script> +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html index fe92232..1316d69a 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-ref.html
@@ -16,7 +16,13 @@ background-color: red; } + /* Hide scrollbars to avoid unnecessary visual issues related to them */ + #scroller::-webkit-scrollbar { + display: none; + } + #scroller { + scrollbar-width: none; overflow: auto; height: 100px; width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html index 5810e17..917b044 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller-ref.html
@@ -1,7 +1,13 @@ <!DOCTYPE html> <title>Reference for Scroll timeline with WorkletAnimation using the root scroller</title> <style> + /* Hide scrollbars to avoid unnecessary visual issues related to them */ + html::-webkit-scrollbar { + display: none; + } + html { + scrollbar-width: none; min-height: 100%; min-width: 100%; padding-bottom: 100px; @@ -34,4 +40,4 @@ const maxScroll = scroller.scrollHeight - scroller.clientHeight; scroller.scrollTop = 0.5 * maxScroll; }); -</script> +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html index be577dcc..2b2a383 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-root-scroller.https.html
@@ -1,7 +1,8 @@ <html class="reftest-wait"> <title>Scroll timeline with WorkletAnimation using the root scroller</title> <link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> -<meta name="assert" content="Worklet animation correctly updates values when using the root scroller as the source for the ScrollTimeline"> +<meta name="assert" + content="Worklet animation correctly updates values when using the root scroller as the source for the ScrollTimeline"> <link rel="match" href="worklet-animation-with-scroll-timeline-root-scroller-ref.html"> <script src="/web-animations/testcommon.js"></script> @@ -9,7 +10,13 @@ <script src="common.js"></script> <style> + /* Hide scrollbars to avoid unnecessary visual issues related to them */ + html::-webkit-scrollbar { + display: none; + } + html { + scrollbar-width: none; min-height: 100%; min-width: 100%; padding-bottom: 100px; @@ -33,15 +40,15 @@ <div id="covered"></div> <script> - registerPassthroughAnimator().then(()=>{ + registerPassthroughAnimator().then(() => { const box = document.getElementById('box'); const effect = new KeyframeEffect(box, [ - {transform: 'translateY(0)', opacity: 1}, - {transform: 'translateY(200px)', opacity: 0} + { transform: 'translateY(0)', opacity: 1 }, + { transform: 'translateY(200px)', opacity: 0 } ], { - duration: 1000, - } + duration: 1000, + } ); const scroller = document.scrollingElement;
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html index 7006f8f..35eaddc 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html
@@ -21,7 +21,13 @@ background-color: red; } + /* Hide scrollbars to avoid unnecessary visual issues related to them */ + #scroller::-webkit-scrollbar { + display: none; + } + #scroller { + scrollbar-width: none; overflow: auto; height: 100px; width: 100px; @@ -45,11 +51,11 @@ const box = document.getElementById('box'); const effect = new KeyframeEffect(box, [ - { transform: 'translateY(0)', opacity: 1}, - { transform: 'translateY(200px)', opacity: 0} + { transform: 'translateY(0)', opacity: 1 }, + { transform: 'translateY(200px)', opacity: 0 } ], { - duration: 1000, - } + duration: 1000, + } ); const scroller = document.getElementById('scroller'); @@ -65,4 +71,4 @@ takeScreenshot(); }); }); -</script> +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/animation-base-response-003.html b/third_party/blink/web_tests/external/wpt/css/css-animations/animation-base-response-003.html new file mode 100644 index 0000000..d6e6da7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-animations/animation-base-response-003.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<title>Tests that identical elements in the base style responds to font-size animation</title> +<link rel="help" href="https://drafts.csswg.org/css-animations/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + @keyframes font_size_animation { + from { font-size: 10px; } + to { font-size: 20px; } + } + div { + font-size: 1px; + min-width: 1em; + animation: font_size_animation steps(2, end) 1000s -500s; + } +</style> +<div></div> +<div></div> +<div></div> +<script> +test(() => { + let divs = document.querySelectorAll('div'); + for (let div of divs) + assert_equals(getComputedStyle(div).getPropertyValue('min-width'), '15px'); +}, 'Identical elements are all responsive to font-size animation'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-011.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-011.html new file mode 100644 index 0000000..66cb0e015 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-011.html
@@ -0,0 +1,77 @@ +<!DOCTYPE html> +<title>CSS Flexbox: images' aspect ratio in flex box with flex-direction: column for min-size: auto</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-containers"> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-direction-property"> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#min-size-auto"> +<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#replaced-intrinsic"> +<link rel="help" href="https://crbug.com/581535"> +<link rel="help" href="https://crbug.com/581361"> +<link href="support/flexbox.css" rel="stylesheet"> +<meta name="assert" content="Images maintain aspect ratio in flex box with column direction with min-size: auto."> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> + +<body onload="checkLayout('.flexbox')"> +<div id=log></div> + +<div class="flexbox" style="width: 10px;" data-expected-width="10"> + <!-- should use content width, clamped by converted max-height, as minimum width. --> + <img src="support/100x100-green.png" style="max-height: 5px;" + data-expected-width="5" data-expected-height="5"> +</div> + +<div class="flexbox" style="width: 10px;" data-expected-width="10"> + <!-- should use min(specified, content width) = 10px as minimum width, + which the image will shrink to due to default flex-shrink. --> + <img src="support/10x10-green.png" style="width: 100px;" data-expected-width="10"> +</div> + +<div class="flexbox" style="width: 10px;" data-expected-width="10"> + <!-- should use content width, clamped by converted min-height, as minimum width. --> + <img src="support/100x100-green.png" style="max-height: 5px;" + data-expected-width="5" data-expected-height="5"> +</div> + +<div class="flexbox" style="width: 10px;" data-expected-width="10"> + <!-- should use content width, clamped by converted min-height, as minimum width. --> + <img src="support/100x100-green.png" style="max-height: 5px; min-height: 10px;" + data-expected-width="10" data-expected-height="10"> +</div> + +<div class="flexbox" style="width: 10px;" data-expected-width="10"> + <!-- should use min(transferred, content width) = 10px as minimum width, + which the image will shrink to due to default flex-shrink. --> + <img src="support/10x10-green.png" style="height: 100px;" data-expected-width="10"> +</div> + +<div class="flexbox column" style="height: 10px;" data-expected-height="10"> + <!-- should use content height, clamped by converted max-width, as minimum height. --> + <img src="support/100x100-green.png" style="max-width: 5px;" + data-expected-width="5" data-expected-height="5"> +</div> + +<div class="flexbox column" style="height: 10px;" data-expected-height="10"> + <!-- should use min(specified, content height) = 10px as minimum height, + which the image will shrink to due to default flex-shrink. --> + <img src="support/10x10-green.png" style="height: 100px;" data-expected-height="10"> +</div> + +<div class="flexbox" style="height: 10px;" data-expected-height="10"> + <!-- should use content height, clamped by converted min-height, as minimum height. --> + <img src="support/100x100-green.png" style="max-height: 5px;" + data-expected-height="5" data-expected-height="5"> +</div> + +<div class="flexbox" style="height: 10px;" data-expected-height="10"> + <!-- should use content height, clamped by converted min-width, as minimum height. --> + <img src="support/100x100-green.png" style="max-width: 5px; min-width: 10px;" + data-expected-height="10" data-expected-width="10"> +</div> + +<div class="flexbox column" style="height: 10px;" data-expected-height="10"> + <!-- should use min(transferred, content height) = 10px as minimum height, + which the image will shrink to due to default flex-shrink. --> + <img src="support/10x10-green.png" style="width: 100px;" data-expected-height="10"> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/intrinsic-min-width-applies-with-fixed-width.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-014.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-flexbox/intrinsic-min-width-applies-with-fixed-width.html rename to third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-014.html
diff --git a/third_party/blink/web_tests/css3/flexbox/max-width-violation.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/max-width-violation.html similarity index 60% rename from third_party/blink/web_tests/css3/flexbox/max-width-violation.html rename to third_party/blink/web_tests/external/wpt/css/css-flexbox/max-width-violation.html index f5b0fe1..ea2779d 100644 --- a/third_party/blink/web_tests/css3/flexbox/max-width-violation.html +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/max-width-violation.html
@@ -1,5 +1,9 @@ <!DOCTYPE html> - +<title>CSS Flexbox: max-width of inflexible items</title> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#resolve-flexible-lengths"> +<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flexibility"> +<link rel="bookmark" href="https://crbug.com/617956"> +<meta name="assert" content="Inflexible items (flex factor 0 or flex basis violating the min/max size constraint) take max-width into account."> <style> .columns { display: flex; @@ -33,16 +37,14 @@ } </style> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../../resources/check-layout-th.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> <body onload="checkLayout('.columns')"> <div id=log></div> - <p>You should see no red</p> - <div class="columns"> <div class="red"></div> <div class="column1" data-expected-width="150"> @@ -54,7 +56,6 @@ </div> <p>This second part is just to ensure we don't assert</p> - <div class="columns"> <div class="column1 abspos" data-expected-width="150"> Column 1 @@ -63,4 +64,3 @@ Column 2 </div> </div> -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/support/10x10-green.png b/third_party/blink/web_tests/external/wpt/css/css-flexbox/support/10x10-green.png new file mode 100644 index 0000000..8c39b0d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/support/10x10-green.png Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-001-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-001-expected.txt new file mode 100644 index 0000000..85ec883 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-001-expected.txt
@@ -0,0 +1,16 @@ +This is a testharness.js-based test. +PASS @font-face matching for quoted and unquoted serif +PASS @font-face matching for quoted and unquoted sans-serif +PASS @font-face matching for quoted and unquoted cursive +PASS @font-face matching for quoted and unquoted fantasy +PASS @font-face matching for quoted and unquoted monospace +FAIL @font-face matching for quoted and unquoted system assert_equals: unquoted system does not match @font-face rule expected 25 but got 50 +FAIL @font-face matching for quoted and unquoted emoji assert_equals: unquoted emoji does not match @font-face rule expected 25 but got 50 +FAIL @font-face matching for quoted and unquoted math assert_equals: unquoted math does not match @font-face rule expected 25 but got 50 +FAIL @font-face matching for quoted and unquoted fangsong assert_equals: unquoted fangsong does not match @font-face rule expected 25 but got 50 +FAIL @font-face matching for quoted and unquoted ui-serif assert_equals: unquoted ui-serif does not match @font-face rule expected 25 but got 50 +FAIL @font-face matching for quoted and unquoted ui-sans-serif assert_equals: unquoted ui-sans-serif does not match @font-face rule expected 25 but got 50 +FAIL @font-face matching for quoted and unquoted ui-monospace assert_equals: unquoted ui-monospace does not match @font-face rule expected 25 but got 50 +FAIL @font-face matching for quoted and unquoted ui-rounded assert_equals: unquoted ui-rounded does not match @font-face rule expected 25 but got 50 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-001.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-001.html index aa9fb5a..bd39bac 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-001.html
@@ -1,36 +1,56 @@ <!DOCTYPE html> -<title>CSS Test: Test generic family keywords do not match @font-face</title> +<title>CSS Test: Test generic family keywords matching for @font-face</title> <link rel="help" href="https://drafts.csswg.org/css-fonts-4/#family-name-syntax"> <link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.com"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<script src="/css/css-fonts/support/font-family-keywords.js"></script> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css"/> <style> div { font-size: 10px; } +#ahem { + font-family: Ahem; +} </style> -<template id="fonts"> +<body> + <div><span id="ahem">00000</span></div> + <div><span id="test">00000</span></div> +<script> + setup({ explicit_done: true }); + window.addEventListener("load", () => { document.fonts.ready.then(runTests); }); + function runTests() { + let ahem = document.getElementById('ahem'); + let ahem_expected_width = ahem.offsetWidth; + kGenericFontFamilyKeywords.forEach(keyword => { + test(() => { + let element = document.getElementById('test'); + element.setAttribute("style", `font-family: ${keyword};`); + let expected_width = element.offsetWidth; + + // Insert the @font-face rules for quoted and unquoted keywords. + document.documentElement.insertAdjacentHTML('beforeend', ` <style> @font-face { - font-family: system-ui; + font-family: ${keyword}; src: local(Ahem), url('/fonts/Ahem.ttf'); } </style> -</template> -<body onload="onLoad()"> - <div><span id="system-ui" style="font-family: system-ui">00000</span></div> -<script> -function onLoad() { - test(() => { - let element = document.getElementById('system-ui'); - let expected_width = element.offsetWidth; +<style> +@font-face { + font-family: "${keyword}"; + src: local(Ahem), url('/fonts/Ahem.ttf'); +} +</style>`); - // Insert the @font-face rule. - let template = document.getElementById('fonts'); - document.documentElement.appendChild(template.content.cloneNode(true)); + assert_equals(element.offsetWidth, expected_width, `unquoted ${keyword} does not match @font-face rule`); - assert_equals(element.offsetWidth, expected_width); - }); -}; + element.setAttribute("style", `font-family: "${keyword}";`); + assert_equals(element.offsetWidth, ahem_expected_width, `quoted ${keyword} matches @font-face rule`); + }, `@font-face matching for quoted and unquoted ${keyword}`); + }); + done(); + } </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-002.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-002.html new file mode 100644 index 0000000..7399860b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/generic-family-keywords-002.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Generic font family: -webkit-* treated as <font-family></title> + <link rel="help" href="https://drafts.csswg.org/css-fonts-4/#generic-font-families"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/css/css-fonts/support/font-family-keywords.js"></script> + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css"/> + <style> + div { + font-size: 10px; + } + #ahem { + font-family: Ahem; + } + </style> + </head> + <body> + <div><span id="ahem">00000</span></div> + <div><span id="test">00000</span></div> + </body> +<script> + setup({ explicit_done: true }); + window.addEventListener("load", () => { document.fonts.ready.then(runTests); }); + function SetFontFamilyAndMeasure(fontFamilyValue) { + var element = document.getElementById('test'); + element.setAttribute("style", `font-family: ${fontFamilyValue}, Ahem;`); + return element.offsetWidth; + } + function runTests() { + let ahem = document.getElementById('ahem'); + let ahem_expected_width = ahem.offsetWidth; + let families = kGenericFontFamilyKeywords.map(keyword => `-webkit-${keyword}`).concat(kWebKitPrefixKeywords); + families.forEach(name => { + test(function() { + assert_equals(SetFontFamilyAndMeasure(name), ahem_expected_width); + }, `font-family: ${name} treated as <font-family>, not <generic-name>`); + }); + done(); + } +</script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/support/font-family-keywords.js b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/font-family-keywords.js new file mode 100644 index 0000000..fc5b723 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/support/font-family-keywords.js
@@ -0,0 +1,17 @@ +var kGenericFontFamilyKeywords = ["serif", + "sans-serif", + "cursive", + "fantasy", + "monospace", + "system", + "emoji", + "math", + "fangsong", + "ui-serif", + "ui-sans-serif", + "ui-monospace", + "ui-rounded"]; + +var kWebKitPrefixKeywords = ["-webkit-body", + "-webkit-standard", + "-webkit-pictograph"];
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-base-response-003.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-base-response-003.html new file mode 100644 index 0000000..045da5db --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-base-response-003.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Tests that identical elements in the base style responds to font-size transition</title> +<link rel="help" href="https://drafts.csswg.org/css-animations/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> + div { + font-size: 10px; + min-width: 1em; + transition: font-size steps(2, start) 10s; + } + .change { + font-size: 20px; + } +</style> +<div></div> +<div></div> +<div></div> +<script> +test(() => { + let divs = document.querySelectorAll('div'); + for (let div of divs) { + let unused = getComputedStyle(div).getPropertyValue('min-width'); + div.className = 'change'; + assert_equals(getComputedStyle(div).getPropertyValue('min-width'), '15px'); + } +}, 'Identical elements are all responsive to font-size transition'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/font-family-serialization-001.html b/third_party/blink/web_tests/external/wpt/css/cssom/font-family-serialization-001.html new file mode 100644 index 0000000..6c59b98 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/cssom/font-family-serialization-001.html
@@ -0,0 +1,44 @@ +<!DOCTYPE HTML> +<html> +<meta charset="utf-8"> +<title>Serialization of font-family</title> +<link rel="help" href="https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block"> +<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-family-prop"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/css-fonts/support/font-family-keywords.js"></script> +<div id="target"></div> +<script> + function SetFontFamilyAndSerialize(fontFamilyValue) { + var target = document.getElementById('target'); + target.setAttribute("style", `font-family: ${fontFamilyValue}`); + return window.getComputedStyle(target).getPropertyValue('font-family'); + } + test(function() { + kGenericFontFamilyKeywords.forEach(keyword => { + assert_equals(SetFontFamilyAndSerialize(keyword), keyword); + }); + }, "Serialization of <generic-family>"); + + test(function() { + kGenericFontFamilyKeywords.forEach(keyword => { + var quoted_keyword = `"${keyword}"`; + assert_equals(SetFontFamilyAndSerialize(quoted_keyword), quoted_keyword); + }); + }, "Serialization of quoted \"<generic-family>\""); + + test(function() { + kGenericFontFamilyKeywords.forEach(keyword => { + var prefixed_keyword = `-webkit-${keyword}`; + assert_equals(SetFontFamilyAndSerialize(prefixed_keyword), prefixed_keyword); + }); + }, "Serialization of prefixed -webkit-<generic-family>"); + + test(function() { + kWebKitPrefixKeywords.forEach(keyword => { + assert_equals(SetFontFamilyAndSerialize(keyword), keyword); + }); + }, `Serialization of ${kWebKitPrefixKeywords}`); + +</script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-wakelock.html b/third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-screen-wakelock.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-wakelock.html rename to third_party/blink/web_tests/external/wpt/feature-policy/resources/feature-policy-screen-wakelock.html
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html index 3c902cc..821ec628 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html
@@ -7,13 +7,13 @@ "use strict"; const same_origin_src = - "/feature-policy/resources/feature-policy-wakelock.html"; + "/feature-policy/resources/feature-policy-screen-wakelock.html"; const cross_origin_src = "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src; promise_test(t => { return promise_rejects_dom(t, "NotAllowedError", navigator.wakeLock.request("screen")); - }, 'Feature-Policy header {"wake-lock" : []} disallows the top-level document.'); + }, 'Feature-Policy header {"screen-wake-lock" : []} disallows the top-level document.'); async_test(t => { test_feature_availability( @@ -22,7 +22,7 @@ same_origin_src, expect_feature_unavailable_default ); - }, 'Feature-Policy header {"wake-lock" : []} disallows same-origin iframes.'); + }, 'Feature-Policy header {"screen-wake-lock" : []} disallows same-origin iframes.'); async_test(t => { test_feature_availability( @@ -31,6 +31,6 @@ cross_origin_src, expect_feature_unavailable_default ); - }, 'Feature-Policy header {"wake-lock" : []} disallows cross-origin iframes.'); + }, 'Feature-Policy header {"screen-wake-lock" : []} disallows cross-origin iframes.'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html.headers b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html.headers index 1d3769ec..5d910ce 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html.headers +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html.headers
@@ -1 +1 @@ -Feature-Policy: wake-lock 'none' +Feature-Policy: screen-wake-lock 'none'
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html index f28a961..2b2e0c9 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -6,7 +6,7 @@ <script> "use strict"; - const relative_path = "/feature-policy/resources/feature-policy-wakelock.html"; + const relative_path = "/feature-policy/resources/feature-policy-screen-wakelock.html"; const base_src = "/feature-policy/resources/redirect-on-load.html#"; const same_origin_src = base_src + relative_path; const cross_origin_src = @@ -18,9 +18,9 @@ t, same_origin_src, expect_feature_available_default, - "wake-lock" + "screen-wake-lock" ); - }, 'Feature-Policy allow="wake-lock" allows same-origin relocation'); + }, 'Feature-Policy allow="screen-wake-lock" allows same-origin relocation'); async_test(t => { test_feature_availability( @@ -28,9 +28,9 @@ t, cross_origin_src, expect_feature_unavailable_default, - "wake-lock" + "screen-wake-lock" ); - }, 'Feature-Policy allow="wake-lock" disallows cross-origin relocation'); + }, 'Feature-Policy allow="screen-wake-lock" disallows cross-origin relocation'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html index 5587a85..b8ab3b03 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html
@@ -7,7 +7,7 @@ "use strict"; const same_origin_src = - "/feature-policy/resources/feature-policy-wakelock.html"; + "/feature-policy/resources/feature-policy-screen-wakelock.html"; const cross_origin_src = "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src; @@ -17,9 +17,9 @@ t, same_origin_src, expect_feature_available_default, - "wake-lock" + "screen-wake-lock" ); - }, 'Feature policy "wake-lock" can be enabled in same-origin iframe using allow="wake-lock" attribute'); + }, 'Feature policy "screen-wake-lock" can be enabled in same-origin iframe using allow="screen-wake-lock" attribute'); async_test(t => { test_feature_availability( @@ -27,8 +27,8 @@ t, cross_origin_src, expect_feature_available_default, - "wake-lock" + "screen-wake-lock" ); - }, 'Feature policy "wake-lock" can be enabled in cross-origin iframe using allow="wake-lock" attribute'); + }, 'Feature policy "screen-wake-lock" can be enabled in cross-origin iframe using allow="screen-wake-lock" attribute'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html index d0f5a15..376359e 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html
@@ -9,7 +9,7 @@ "use strict"; const same_origin_src = - "/feature-policy/resources/feature-policy-wakelock.html"; + "/feature-policy/resources/feature-policy-screen-wakelock.html"; const cross_origin_src = "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src; @@ -17,7 +17,7 @@ await test_driver.set_permission( { name: 'wake-lock', type: 'screen' }, 'granted', false); await navigator.wakeLock.request('screen').then(lock => lock.release()); - }, 'Feature-Policy header {"wake-lock" : ["*"]} allows the top-level document.'); + }, 'Feature-Policy header {"screen-wake-lock" : ["*"]} allows the top-level document.'); async_test(t => { test_feature_availability( @@ -26,7 +26,7 @@ same_origin_src, expect_feature_available_default ); - }, 'Feature-Policy header {"wake-lock" : ["*"]} allows same-origin iframes.'); + }, 'Feature-Policy header {"screen-wake-lock" : ["*"]} allows same-origin iframes.'); async_test(t => { test_feature_availability( @@ -35,7 +35,7 @@ cross_origin_src, expect_feature_available_default ); - }, 'Feature-Policy header {"wake-lock" : ["*"]} allows cross-origin iframes.'); + }, 'Feature-Policy header {"screen-wake-lock" : ["*"]} allows cross-origin iframes.'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html.headers b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html.headers index 34b7437..7810751 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html.headers +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html.headers
@@ -1 +1 @@ -Feature-Policy: wake-lock * +Feature-Policy: screen-wake-lock *
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html index 73f3438..a2d3725 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html
@@ -10,7 +10,7 @@ "use strict"; const same_origin_src = - "/feature-policy/resources/feature-policy-wakelock.html"; + "/feature-policy/resources/feature-policy-screen-wakelock.html"; const cross_origin_src = "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src; @@ -18,7 +18,7 @@ await test_driver.set_permission( { name: 'wake-lock', type: 'screen' }, 'granted', false); await navigator.wakeLock.request('screen').then(lock => lock.release()); - }, 'Feature-Policy header wake-lock "self" allows the top-level document.'); + }, 'Feature-Policy header screen-wake-lock "self" allows the top-level document.'); async_test(t => { test_feature_availability( @@ -27,7 +27,7 @@ same_origin_src, expect_feature_available_default ); - }, 'Feature-Policy header wake-lock "self" allows same-origin iframes.'); + }, 'Feature-Policy header screen-wake-lock "self" allows same-origin iframes.'); async_test(t => { test_feature_availability( @@ -36,6 +36,6 @@ cross_origin_src, expect_feature_unavailable_default ); - }, 'Feature-Policy header wake-lock "self" disallows cross-origin iframes.'); + }, 'Feature-Policy header screen-wake-lock "self" disallows cross-origin iframes.'); </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html.headers b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html.headers index 6f05d235..6bc94277 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html.headers +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html.headers
@@ -1 +1 @@ -Feature-Policy: wake-lock 'self' +Feature-Policy: screen-wake-lock 'self'
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-supported-by-feature-policy.html b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-supported-by-feature-policy.html index d6289ff..e7f9c8cb 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-supported-by-feature-policy.html +++ b/third_party/blink/web_tests/external/wpt/wake-lock/wakelock-supported-by-feature-policy.html
@@ -6,6 +6,6 @@ <script src="/resources/testharnessreport.js"></script> <script> test(() => { - assert_in_array('wake-lock', document.featurePolicy.features()); -}, 'document.featurePolicy.features should advertise wake-lock.'); + assert_in_array('screen-wake-lock', document.featurePolicy.features()); +}, 'document.featurePolicy.features should advertise screen-wake-lock.'); </script>
diff --git a/third_party/blink/web_tests/fullscreen/full-screen-iframe-not-allowed.html b/third_party/blink/web_tests/fullscreen/full-screen-iframe-not-allowed.html deleted file mode 100644 index e9a92df..0000000 --- a/third_party/blink/web_tests/fullscreen/full-screen-iframe-not-allowed.html +++ /dev/null
@@ -1,26 +0,0 @@ -<p>Test for <a href="http://bugs.webkit.org/show_bug.cgi?id=56264">bug 56264</a>: -Handle entering full screen security restrictions</p> -<p>To test manually, click the "Go full screen" button - the page should not enter full screen mode.</p> -<script src="full-screen-test.js"></script> -<script> -function runTest() { - var frame = document.getElementById('frame'); - - waitForEvent(frame.contentDocument, 'webkitfullscreenchange', function() { - consoleWrite("FAIL - entered full screen!"); - endTest(); - }); - - waitForEventAndEnd(frame.contentDocument, 'webkitfullscreenerror', function() { - consoleWrite("SUCCEED - did not enter full screen!"); - }); - - var x = frame.getBoundingClientRect().left + 10; - var y = frame.getBoundingClientRect().top + 10; - eventSender.mouseMoveTo(x, y); - eventSender.mouseDown(); - eventSender.mouseUp(); -} -</script> -<iframe id="frame" src="resources/inner.html" onload="runTest()"> -</iframe>
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 index 6547710..d11895bf 100644 --- 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
@@ -8,15 +8,15 @@ <p>Emulating "none": <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg=="> <p>Emulating "deuteranopia": -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF9JREFUWIXt17ENwCAQBMGHYohdqKuhEsduBorYQyLYKeC0+uzbM8aqoO9/k3PVo2sHGEgZSBlIGUgZSBlIGUgZSBlItaoZ/UnSrr+ggZSBlIGUgZSBlIGUgZSBlIHUBmSnBbHzufJtAAAAAElFTkSuQmCC"> +<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAGJJREFUWIXt17ENgDAQBMG3AyLqcxkuxsXQFxEhFLGH5GCngNPqs29zHG8FretOzlWPrv3AQMpAykDKQMpAykDKQMpAykCq1flEf5K07S9oIGUgZSBlIGUgZSBlIGUgZSD1AVMZBlN0SH01AAAAAElFTkSuQmCC"> <p>Emulating "none": <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFRJREFUWIXt18ENACAMw8DA5N0chnCQePgGiKz+ujI5aZru3K6uPWAgZSBlIGUgZSBlIGUgZSBlILWS030iyr6/oIGUgZSBlIGUgZSBlIGUgZSB1AXNwwVLtuf+dAAAAABJRU5ErkJggg=="> <p>Emulating "protanopia": -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF9JREFUWIXt10ENwCAQBdEFI5VBahcnnEhVURHzm/QwT8DPZG/bxn2dCnr2TM5Vj659wEDKQMpAykDKQMpAykDKQMpAqlWt6E+S9vsLGkgZSBlIGUgZSBlIGUgZSBlIvZuvBc8DKP+1AAAAAElFTkSuQmCC"> +<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF1JREFUWIXt10ENACEQBMEFFwhExCnAEP5ARA/JPboETDr727ZmnQr6dnSuenTtAQMpAykDKQMpAykDKQMpAykDqVbjZJ+IsN9f0EDKQMpAykDKQMpAykDKQMpA6gJvXgZ9Xlbz3wAAAABJRU5ErkJggg=="> <p>Emulating "tritanopia": -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF5JREFUWIXt17ENwCAQBEGwEC0RuQBaoP8qnJgi9pAIdgo4rT772sf7l6BvzeRceaJrBxhIGUgZSBlIGUgZSBlIGUgZSLX0D5F2/QUNpAykDKQMpAykDKQMpAykDKQ2h2YFBXR3unwAAAAASUVORK5CYII="> +<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFhJREFUWIXt10ENACAQxEAgiMQJsnDHF0R0SXh0BGya+10tc5yStHZ0rkXXHjCQMpAykDKQMpAykDKQMpAykOrpHyLt+wsaSBlIGUgZSBlIGUgZSBlIGUhdCWsFapTFH60AAAAASUVORK5CYII="> <p>Emulating "tritanopia": -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF5JREFUWIXt17ENwCAQBEGwEC0RuQBaoP8qnJgi9pAIdgo4rT772sf7l6BvzeRceaJrBxhIGUgZSBlIGUgZSBlIGUgZSLX0D5F2/QUNpAykDKQMpAykDKQMpAykDKQ2h2YFBXR3unwAAAAASUVORK5CYII="> +<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFhJREFUWIXt10ENACAQxEAgiMQJsnDHF0R0SXh0BGya+10tc5yStHZ0rkXXHjCQMpAykDKQMpAykDKQMpAykOrpHyLt+wsaSBlIGUgZSBlIGUgZSBlIGUhdCWsFapTFH60AAAAASUVORK5CYII="> <p>Emulating "some-invalid-deficiency": { "code": -32602, @@ -48,7 +48,7 @@ "message": "Unknown vision deficiency type" } <p>Navigating… -<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAF5JREFUWIXt17ENwCAQBEGwEC0RuQBaoP8qnJgi9pAIdgo4rT772sf7l6BvzeRceaJrBxhIGUgZSBlIGUgZSBlIGUgZSLX0D5F2/QUNpAykDKQMpAykDKQMpAykDKQ2h2YFBXR3unwAAAAASUVORK5CYII="> +<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFhJREFUWIXt10ENACAQxEAgiMQJsnDHF0R0SXh0BGya+10tc5yStHZ0rkXXHjCQMpAykDKQMpAykDKQMpAykOrpHyLt+wsaSBlIGUgZSBlIGUgZSBlIGUhdCWsFapTFH60AAAAASUVORK5CYII="> <p>Emulating "achromatopsia": <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAFpJREFUWIXt10ENADEMxMD2eARR2IfQFYS3Uh8eACsrv+zu/lfQzCTn1hddu8BAykDKQMpAykDKQMpAykDKQGpXVfQnSXv+ggZSBlIGUgZSBlIGUgZSBlIGUgcPVwX7L3bHewAAAABJRU5ErkJggg==">
diff --git a/third_party/blink/web_tests/media/video-controls-fullscreen-iframe-not-allowed.html b/third_party/blink/web_tests/media/video-controls-fullscreen-iframe-not-allowed.html index a4457c7e..efccf4f 100644 --- a/third_party/blink/web_tests/media/video-controls-fullscreen-iframe-not-allowed.html +++ b/third_party/blink/web_tests/media/video-controls-fullscreen-iframe-not-allowed.html
@@ -8,7 +8,7 @@ <script src="video-controls-fullscreen.js"></script> </head> <body> - <iframe></iframe> + <iframe allow="fullscreen 'none';"></iframe> <script>fullscreen_iframe_test();</script> </body> </html>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt new file mode 100644 index 0000000..fbda0d6 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt
@@ -0,0 +1,19 @@ +This is a testharness.js-based test. +FAIL font-family: -webkit-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-sans-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-cursive treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-fantasy treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-monospace treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-system treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-emoji treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-math treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-fangsong treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-ui-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-ui-sans-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-ui-monospace treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-ui-rounded treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-body treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-standard treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-pictograph treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt new file mode 100644 index 0000000..d85a0cf --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt
@@ -0,0 +1,19 @@ +This is a testharness.js-based test. +FAIL font-family: -webkit-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-sans-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 28 +FAIL font-family: -webkit-cursive treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 26 +FAIL font-family: -webkit-fantasy treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 33 +FAIL font-family: -webkit-monospace treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +PASS font-family: -webkit-system treated as <font-family>, not <generic-name> +PASS font-family: -webkit-emoji treated as <font-family>, not <generic-name> +PASS font-family: -webkit-math treated as <font-family>, not <generic-name> +PASS font-family: -webkit-fangsong treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-serif treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-sans-serif treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-monospace treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-rounded treated as <font-family>, not <generic-name> +FAIL font-family: -webkit-body treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-standard treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-pictograph treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/css/cssom/font-family-serialization-001-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/css/cssom/font-family-serialization-001-expected.txt new file mode 100644 index 0000000..1adb625 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/css/cssom/font-family-serialization-001-expected.txt
@@ -0,0 +1,7 @@ +This is a testharness.js-based test. +PASS Serialization of <generic-family> +FAIL Serialization of quoted "<generic-family>" assert_equals: expected "\"serif\"" but got "serif" +FAIL Serialization of prefixed -webkit-<generic-family> assert_equals: expected "-webkit-serif" but got "serif" +FAIL Serialization of -webkit-body,-webkit-standard,-webkit-pictograph assert_equals: expected "-webkit-body" but got "Times" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt new file mode 100644 index 0000000..2ff76e0 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/css/css-fonts/generic-family-keywords-002-expected.txt
@@ -0,0 +1,19 @@ +This is a testharness.js-based test. +FAIL font-family: -webkit-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-sans-serif treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-cursive treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +FAIL font-family: -webkit-fantasy treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-monospace treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 30 +PASS font-family: -webkit-system treated as <font-family>, not <generic-name> +PASS font-family: -webkit-emoji treated as <font-family>, not <generic-name> +PASS font-family: -webkit-math treated as <font-family>, not <generic-name> +PASS font-family: -webkit-fangsong treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-serif treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-sans-serif treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-monospace treated as <font-family>, not <generic-name> +PASS font-family: -webkit-ui-rounded treated as <font-family>, not <generic-name> +FAIL font-family: -webkit-body treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-standard treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +FAIL font-family: -webkit-pictograph treated as <font-family>, not <generic-name> assert_equals: expected 50 but got 25 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/css/cssom/font-family-serialization-001-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/css/cssom/font-family-serialization-001-expected.txt new file mode 100644 index 0000000..3f14ad3d --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/css/cssom/font-family-serialization-001-expected.txt
@@ -0,0 +1,7 @@ +This is a testharness.js-based test. +PASS Serialization of <generic-family> +FAIL Serialization of quoted "<generic-family>" assert_equals: expected "\"serif\"" but got "serif" +FAIL Serialization of prefixed -webkit-<generic-family> assert_equals: expected "-webkit-serif" but got "serif" +FAIL Serialization of -webkit-body,-webkit-standard,-webkit-pictograph assert_equals: expected "-webkit-body" but got "\"times new roman\"" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt index 323b7a04..1734d1e 100644 --- a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
@@ -45,6 +45,7 @@ pointer-lock popups presentation +screen-wake-lock scripts serial sync-script @@ -53,6 +54,5 @@ trust-token-redemption usb vertical-scroll -wake-lock xr-spatial-tracking
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 4e524ef8..0a2db48 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6301,7 +6301,9 @@ interface RTCEncodedAudioFrame attribute @@toStringTag getter additionalData + getter contributingSources getter data + getter synchronizationSource getter timestamp method constructor method toString @@ -6310,6 +6312,7 @@ attribute @@toStringTag getter additionalData getter data + getter synchronizationSource getter timestamp getter type method constructor
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html index 410508f9..c407c6b 100644 --- a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html +++ b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-051.html
@@ -10,12 +10,6 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> -<style> -.auto { - subtree-visibility: auto; -} -</style> - <div id="hidden" style="subtree-visibility: auto"> foo <div id="child" tabindex="0"> @@ -29,19 +23,25 @@ } async_test(async(t) => { - const hiddenEl = document.getElementById("hidden"); - let axHidden = axElementById("hidden"); - t.step(() => { assert_equals(axHidden.childrenCount, 3, "Child count after acquire"); }); - axElementById("child").takeFocus(); + t.step(() => { + let axChild = axElementById("child"); + assert_false(Boolean(axChild.backgroundColor), "Background color after activation"); + }); - // Wait for the next frame for the ax object to be recreated. + axElementById("child").takeFocus(); // Use accessibility to set the focus. + + // Wait for a few frames for the ax tree to be refreshed. requestAnimationFrame(() => { requestAnimationFrame(() => { - axHidden = axElementById("hidden"); - t.step(() => { assert_equals(axHidden.childrenCount, 2, "Child count after activation"); }); - t.done(); +- requestAnimationFrame(() => { + - t.step(() => { + let axChild = axElementById("child"); + assert_equals(axChild.backgroundColor, 0xFFFFFFFF, "Background color after activation"); + }); + t.done(); + }); }); }); -}, "Accessiblility focus causes activatable hidden tree to activate"); +}, "Accessiblility focus causes activatable hidden tree to activate, and thus accessibility details such as background color become available"); </script>
diff --git a/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-075.html b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-075.html new file mode 100644 index 0000000..4c8b128 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/display-lock/css-subtree-visibility/subtree-visibility-075.html
@@ -0,0 +1,41 @@ +<!doctype HTML> +<html> +<meta charset="utf8"> +<title>Subtree Visibility: accessibility focus</title> +<link rel="author" title="Aaron Leventhal" href="mailto:aleventhal@chromium.org"> +<link rel="help" href="https://github.com/WICG/display-locking"> +<link rel="match" href="container-ref.html"> +<meta name="assert" content="subtree-visibility auto subtrees are exposed by accessibility focus"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +.auto { + subtree-visibility: auto; +} +</style> + +<div id="hidden" style="subtree-visibility: auto"> + foo + <div id="child" tabindex="0"> + bar + </div> +</div> + +<script> +function axElementById(id) { + return accessibilityController.accessibleElementById(id); +} + +async_test(async(t) => { + const hiddenEl = document.getElementById("hidden"); + let axHidden = axElementById("hidden"); + t.step(() => { + assert_equals(axHidden.childrenCount, 3, "Child count after acquire" ); + axHidden.childAtIndex(1).name; // Referring to the name should have no effect on the number of children. + assert_equals(axHidden.childrenCount, 3, "Child count after acquire, and accessing name of first child" ); + t.done(); + }); +}, "Accessiblility name calculation on child of subtree-visibility: auto does not destroy tree"); + +</script>
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index 93020d5..ae20bff 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -1577,19 +1577,26 @@ return section_sizes, raw_symbols -def CreateSizeInfo(section_sizes, - raw_symbols, - metadata=None, +def CreateSizeInfo(section_sizes_list, + raw_symbols_list, + metadata_list, normalize_names=True): """Performs operations on all symbols and creates a SizeInfo object.""" - file_format.SortSymbols(raw_symbols) - file_format.CalculatePadding(raw_symbols) + for raw_symbols in raw_symbols_list: + file_format.SortSymbols(raw_symbols) + file_format.CalculatePadding(raw_symbols) - # Do not call _NormalizeNames() during archive since that method tends to need - # tweaks over time. Calling it only when loading .size files allows for more - # flexibility. - if normalize_names: - _NormalizeNames(raw_symbols) + # Do not call _NormalizeNames() during archive since that method tends to + # need tweaks over time. Calling it only when loading .size files allows for + # more flexibility. + if normalize_names: + _NormalizeNames(raw_symbols) + + # TODO(huangs): Implement data fusing to compute the following for real. + assert len(section_sizes_list) == 1 + section_sizes = section_sizes_list[0] + raw_symbols = raw_symbols_list[0] + metadata = metadata_list[0] return models.SizeInfo(section_sizes, raw_symbols, metadata=metadata) @@ -1813,20 +1820,15 @@ return elf_path, map_path, apk_so_path -def _DeduceMainPaths(args, knobs, on_config_error): - """Computes main paths based on input, and deduces them if needed.""" - aab_or_apk = args.apk_file or args.minimal_apks_file +def _DeduceAuxPaths(args, apk_prefix): mapping_path = args.mapping_file resources_pathmap_path = args.resources_pathmap_file - if aab_or_apk: - # Allow either .minimal.apks or just .apks. - aab_or_apk = aab_or_apk.replace('.minimal.apks', '.aab') - aab_or_apk = aab_or_apk.replace('.apks', '.aab') + if apk_prefix: if not mapping_path: - mapping_path = aab_or_apk + '.mapping' + mapping_path = apk_prefix + '.mapping' logging.debug('Detected --mapping-file=%s', mapping_path) if not resources_pathmap_path: - possible_pathmap_path = aab_or_apk + '.pathmap.txt' + possible_pathmap_path = apk_prefix + '.pathmap.txt' # This could be pointing to a stale pathmap file if path shortening was # previously enabled but is disabled for the current build. However, since # current apk/aab will have unshortened paths, looking those paths up in @@ -1836,90 +1838,76 @@ resources_pathmap_path = possible_pathmap_path logging.debug('Detected --resources-pathmap-file=%s', resources_pathmap_path) + return mapping_path, resources_pathmap_path + + +def _DeduceMainPaths(args, knobs, on_config_error): + """Generates main paths (may be deduced) for each containers given by input. + + Yields: + For each container, main paths and other info needed to create size_info. + """ output_directory_finder = path_util.OutputDirectoryFinder( value=args.output_directory, any_path_within_output_directory=args.any_path_within_output_directory) - apk_path = args.extracted_minimal_apk_path or args.apk_file - linker_name = None - tool_prefix = None - if knobs.analyze_native: - elf_path, map_path, apk_so_path = _DeduceNativeInfo( - output_directory_finder.Tentative(), apk_path, args.elf_file, - args.map_file, on_config_error) - if map_path: - linker_name = _DetectLinkerName(map_path) - logging.info('Linker name: %s' % linker_name) + def _Inner(apk_prefix, apk_path): + """Inner helper for _DeduceMainPaths(), for one container. - tool_prefix_finder = path_util.ToolPrefixFinder( - value=args.tool_prefix, - output_directory_finder=output_directory_finder, - linker_name=linker_name) - tool_prefix = tool_prefix_finder.Finalized() + Params: + apk_prefix: Prefix used to search for auxiliary .apk related files. + apk_path: Path to .apk file that can be opened for processing, but whose + filename is unimportant (e.g., can be a temp file). + """ + if apk_prefix: + # Allow either .minimal.apks or just .apks. + apk_prefix = apk_prefix.replace('.minimal.apks', '.aab') + apk_prefix = apk_prefix.replace('.apks', '.aab') + + mapping_path, resources_pathmap_path = _DeduceAuxPaths(args, apk_prefix) + linker_name = None + tool_prefix = None + if knobs.analyze_native: + elf_path, map_path, apk_so_path = _DeduceNativeInfo( + output_directory_finder.Tentative(), apk_path, args.elf_file, + args.map_file, on_config_error) + if map_path: + linker_name = _DetectLinkerName(map_path) + logging.info('Linker name: %s' % linker_name) + + tool_prefix_finder = path_util.ToolPrefixFinder( + value=args.tool_prefix, + output_directory_finder=output_directory_finder, + linker_name=linker_name) + tool_prefix = tool_prefix_finder.Finalized() + else: + # Trust that these values will not be used, and set to None. + elf_path = None + map_path = None + apk_so_path = None + + # TODO(huangs): See if this can be pulled out of _Inner(). + output_directory = None + if not args.no_source_paths: + output_directory = output_directory_finder.Finalized() + + size_info_prefix = None + if output_directory and apk_prefix: + size_info_prefix = os.path.join(output_directory, 'size-info', + os.path.basename(apk_prefix)) + + return (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path, + elf_path, map_path, resources_pathmap_path, linker_name, + size_info_prefix) + + # Process each container. + # If needed, extract .apk file to a temp file and process that instead. + if args.minimal_apks_file: + with zip_util.UnzipToTemp(args.minimal_apks_file, _APKS_MAIN_APK) as temp: + yield _Inner(args.minimal_apks_file, temp) else: - # Trust that these values will not be used, and set to None. - elf_path = None - map_path = None - apk_so_path = None - - output_directory = None - if not args.no_source_paths: - output_directory = output_directory_finder.Finalized() - - size_info_prefix = None - if output_directory and aab_or_apk: - size_info_prefix = os.path.join( - output_directory, 'size-info', os.path.basename(aab_or_apk)) - - return (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path, - elf_path, map_path, resources_pathmap_path, linker_name, - size_info_prefix) - - -def _RunInternal(args, on_config_error): - knobs = SectionSizeKnobs(args.is_bundle) - knobs.ModifyWithArgs(args) - - (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path, elf_path, - map_path, resources_pathmap_path, linker_name, - size_info_prefix) = _DeduceMainPaths(args, knobs, on_config_error) - - # Note that |args.apk_file| is used instead of |apk_path|, since the latter - # may be an extracted temporary file. - metadata = CreateMetadata(map_path, elf_path, args.apk_file, - args.minimal_apks_file, tool_prefix, - output_directory, linker_name) - section_sizes, raw_symbols = CreateSectionSizesAndSymbols( - map_path=map_path, - tool_prefix=tool_prefix, - elf_path=elf_path, - apk_path=apk_path, - mapping_path=mapping_path, - output_directory=output_directory, - resources_pathmap_path=resources_pathmap_path, - track_string_literals=args.track_string_literals, - metadata=metadata, - apk_so_path=apk_so_path, - pak_files=args.pak_file, - pak_info_file=args.pak_info_file, - linker_name=linker_name, - size_info_prefix=size_info_prefix, - knobs=knobs) - size_info = CreateSizeInfo( - section_sizes, raw_symbols, metadata=metadata, normalize_names=False) - - if logging.getLogger().isEnabledFor(logging.DEBUG): - for line in describe.DescribeSizeInfoCoverage(size_info): - logging.debug(line) - logging.info('Recorded info for %d symbols', len(size_info.raw_symbols)) - logging.info('Recording metadata: \n %s', - '\n '.join(describe.DescribeMetadata(size_info.metadata))) - logging.info('Saving result to %s', args.size_file) - file_format.SaveSizeInfo( - size_info, args.size_file, include_padding=args.include_padding) - size_in_mb = os.path.getsize(args.size_file) / 1024.0 / 1024.0 - logging.info('Done. File size is %.2fMiB.', size_in_mb) + yield _Inner(args.apk_file, args.apk_file) def Run(args, on_config_error): @@ -1941,11 +1929,58 @@ 'Must pass at least one of --apk-file, --minimal-apks-file, ' '--elf-file, --map-file') setattr(args, 'any_path_within_output_directory', any_path) - setattr(args, 'extracted_minimal_apk_path', None) - if args.minimal_apks_file: - with zip_util.UnzipToTemp(args.minimal_apks_file, _APKS_MAIN_APK) as temp: - args.extracted_minimal_apk_path = temp - _RunInternal(args, on_config_error) - else: - _RunInternal(args, on_config_error) + knobs = SectionSizeKnobs(args.is_bundle) + knobs.ModifyWithArgs(args) + + metadata_list = [] + section_sizes_list = [] + raw_symbols_list = [] + # Generate one size info for each container. + for (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path, + elf_path, map_path, resources_pathmap_path, linker_name, + size_info_prefix) in _DeduceMainPaths(args, knobs, on_config_error): + # Note that |args.apk_file| is used instead of |apk_path|, since the latter + # may be an extracted temporary file. + metadata = CreateMetadata(map_path, elf_path, args.apk_file, + args.minimal_apks_file, tool_prefix, + output_directory, linker_name) + section_sizes, raw_symbols = CreateSectionSizesAndSymbols( + map_path=map_path, + tool_prefix=tool_prefix, + elf_path=elf_path, + apk_path=apk_path, + mapping_path=mapping_path, + output_directory=output_directory, + resources_pathmap_path=resources_pathmap_path, + track_string_literals=args.track_string_literals, + metadata=metadata, + apk_so_path=apk_so_path, + pak_files=args.pak_file, + pak_info_file=args.pak_info_file, + linker_name=linker_name, + size_info_prefix=size_info_prefix, + knobs=knobs) + + metadata_list.append(metadata) + section_sizes_list.append(section_sizes) + raw_symbols_list.append(raw_symbols) + + size_info = CreateSizeInfo( + section_sizes_list, + raw_symbols_list, + metadata_list, + normalize_names=False) + + if logging.getLogger().isEnabledFor(logging.DEBUG): + for line in describe.DescribeSizeInfoCoverage(size_info): + logging.debug(line) + logging.info('Recorded info for %d symbols', len(size_info.raw_symbols)) + logging.info('Recording metadata: \n %s', '\n '.join( + describe.DescribeMetadata(size_info.metadata))) + + logging.info('Saving result to %s', args.size_file) + file_format.SaveSizeInfo( + size_info, args.size_file, include_padding=args.include_padding) + size_in_mb = os.path.getsize(args.size_file) / 1024.0 / 1024.0 + logging.info('Done. File size is %.2fMiB.', size_in_mb)
diff --git a/tools/binary_size/libsupersize/file_format.py b/tools/binary_size/libsupersize/file_format.py index aa96839..eda89e16 100644 --- a/tools/binary_size/libsupersize/file_format.py +++ b/tools/binary_size/libsupersize/file_format.py
@@ -233,13 +233,15 @@ Args: size_info: Data to write to the file - file_obj: File opened for writing - sparse_symbols: If present, only save these symbols to the file + file_obj: File opened for writing. + include_padding: Whether to save padding data, useful if adding a subset of + symbols. + sparse_symbols: If present, only save these symbols to the file. """ if sparse_symbols is not None: - # Any aliases of sparse symbols must also be included, or else file parsing - # will attribute symbols that happen to follow an incomplete alias group to - # that alias group. + # Any aliases of sparse symbols must also be included, or else file + # parsing will attribute symbols that happen to follow an incomplete alias + # group to that alias group. raw_symbols = _ExpandSparseSymbols(sparse_symbols) else: raw_symbols = size_info.raw_symbols @@ -362,7 +364,7 @@ def _LoadSizeInfoFromFile(file_obj, size_path): """Loads a size_info from the given file. - See _SaveSizeInfoToFile for details on the .size file format. + See _SaveSizeInfoToFile() for details on the .size file format. Args: file_obj: File to read, should be a GzipFile
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py index 83f29ac..e11bdb1c 100755 --- a/tools/binary_size/libsupersize/integration_test.py +++ b/tools/binary_size/libsupersize/integration_test.py
@@ -216,7 +216,7 @@ size_info_prefix=size_info_prefix, knobs=knobs) IntegrationTest.cached_size_info[cache_key] = archive.CreateSizeInfo( - section_sizes, raw_symbols, metadata=metadata) + [section_sizes], [raw_symbols], [metadata]) return copy.deepcopy(IntegrationTest.cached_size_info[cache_key]) def _DoArchive(self,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4b479e8..2d4e57f6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -26913,7 +26913,7 @@ <int value="28" label="DocumentWrite"/> <int value="29" label="LazyLoad"/> <int value="30" label="LayoutAnimations"/> - <int value="31" label="WakeLock"/> + <int value="31" label="ScreenWakeLock"/> <int value="32" label="FontDisplay"/> <int value="33" label="TopNavigation"/> <int value="34" label="FormSubmission"/> @@ -50044,6 +50044,7 @@ <int value="3" label="Change password"/> <int value="4" label="Edit password"/> <int value="5" label="Remove password"/> + <int value="6" label="Show password"/> </enum> <enum name="PasswordCheckReferrer"> @@ -52192,6 +52193,30 @@ <int value="1" label="Error"/> </enum> +<enum name="PluginVmSetupFailureReason"> + <int value="1" label="SIGNAL_NOT_CONNECTED"/> + <int value="2" label="OPERATION_IN_PROGRESS"/> + <int value="3" label="NOT_ALLOWED"/> + <int value="4" label="INVALID_IMAGE_URL"/> + <int value="5" label="UNEXPECTED_DISK_IMAGE_STATUS"/> + <int value="6" label="INVALID_DISK_IMAGE_STATUS_RESPONSE"/> + <int value="7" label="DOWNLOAD_FAILED_UNKNOWN"/> + <int value="8" label="DOWNLOAD_FAILED_NETWORK"/> + <int value="9" label="DOWNLOAD_FAILED_ABORTED"/> + <int value="10" label="HASH_MISMATCH"/> + <int value="11" label="DISPATCHER_NOT_AVAILABLE"/> + <int value="12" label="CONCIERGE_NOT_AVAILABLE"/> + <int value="13" label="COULD_NOT_OPEN_IMAGE"/> + <int value="14" label="INVALID_IMPORT_RESPONSE"/> + <int value="15" label="IMAGE_IMPORT_FAILED"/> + <int value="18" label="DLC_INTERNAL"/> + <int value="19" label="DLC_UNSUPPORTED"/> + <int value="20" label="DLC_BUSY"/> + <int value="21" label="DLC_NEED_REBOOT"/> + <int value="22" label="DLC_NEED_SPACE"/> + <int value="23" label="INSUFFICIENT_DISK_SPACE"/> +</enum> + <enum name="PluginVmSetupResult"> <int value="0" label="Success"/> <int value="1" label="Plugin VM is not allowed for this user"/> @@ -52203,6 +52228,11 @@ <int value="6" label="Error while downloading Plugin VM DLC"/> <int value="7" label="User cancelled setup while downloading Plugin VM DLC"/> <int value="8" label="Plugin VM was already installed"/> + <int value="9" label="User cancelled setup while checking for existing VM"/> + <int value="10" label="User didn't meet minimum required free disk space"/> + <int value="11" label="User cancelled setup due to low free disk space"/> + <int value="12" label="User cancelled setup during disk space check"/> + <int value="13" label="Error, see PluginVm.SetupFailureReason"/> </enum> <enum name="PNaClOptionsOptLevelEnum">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 35824c2..fe391d9 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -14992,10 +14992,13 @@ </histogram> <histogram name="AutoScreenBrightness.AdapterDecisionAtUserChange.AlsDelta" - units="count" expires_after="2020-06-30"> + units="count" expires_after="2020-11-30"> <!-- Name completed by histogram_suffixes name="AlsBrightnessDirection" and name="AdapterDecision" --> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, we will ask the model whether it also thinks brightness should be changed. We also log the als-delta from the @@ -15006,10 +15009,13 @@ </histogram> <histogram name="AutoScreenBrightness.AdapterDecisionAtUserChange.AlsStd" - units="count" expires_after="2020-06-30"> + units="count" expires_after="2020-11-30"> <!-- Name completed by histogram_suffixes name="AlsBrightnessDirection" and name="AdapterDecision" --> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, we will ask the model whether it also thinks brightness should be changed. We also log the als-stddev in its @@ -15020,8 +15026,11 @@ <histogram name="AutoScreenBrightness.AdapterDecisionAtUserChange.BrightnessChange.Cause" - enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2020-09-20"> + enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, we will ask the model whether it also thinks brightness should be changed. This enum states the reason why the @@ -15031,10 +15040,13 @@ <histogram base="true" name="AutoScreenBrightness.AdapterDecisionAtUserChange.ModelIteration" - units="count" expires_after="2020-06-30"> + units="count" expires_after="2020-11-30"> <!-- Name completed by histogram_suffixes name="AdapterDecision" --> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, we will ask the model whether it also thinks brightness should be changed. We also log the number of model @@ -15045,8 +15057,11 @@ <histogram name="AutoScreenBrightness.AdapterDecisionAtUserChange.NoBrightnessChange.Cause" enum="AutoScreenBrightnessNoBrightnessChangeCause" - expires_after="2020-06-30"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, we will ask the model whether it also thinks brightness should be changed. This enum states the reason why the @@ -15056,10 +15071,13 @@ <histogram name="AutoScreenBrightness.AdapterDecisionAtUserChange.Unknown.AlsStd" - units="count" expires_after="2020-06-30"> + units="count" expires_after="2020-11-30"> <!-- Name completed by histogram_suffixes name="AdapterDecision" --> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, we will ask the model whether it also thinks brightness should be changed. We also log the als-stddev in its @@ -15069,31 +15087,42 @@ </histogram> <histogram name="AutoScreenBrightness.AlsReaderStatus" - enum="AutoScreenBrightnessAlsReaderStatus" expires_after="2020-07-26"> + enum="AutoScreenBrightnessAlsReaderStatus" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether the ALS is enabled or the error otherwise. Chrome OS only. </summary> </histogram> <histogram name="AutoScreenBrightness.BrightnessChange.Cause" - enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2020-09-20"> + enum="AutoScreenBrightnessBrightnessChangeCause" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary>Reason for the model to change brightness. Chrome OS only.</summary> </histogram> <histogram name="AutoScreenBrightness.BrightnessChange.ElapsedTime" units="ms" - expires_after="2020-05-03"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> The time between two consecutive auto brightness changes. Chrome OS only. </summary> </histogram> <histogram name="AutoScreenBrightness.BrightnessChange.ModelIteration" - units="count" expires_after="2020-05-10"> + units="count" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of model iterations when brightness is changed by a personal curve. Chrome OS only. @@ -15102,9 +15131,11 @@ <histogram name="AutoScreenBrightness.BrightnessMonitorStatus" enum="AutoScreenBrightnessBrightnessMonitorStatus" - expires_after="2020-09-01"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether the brightness monitor is enabled or the error otherwise. Chrome OS only. @@ -15112,8 +15143,11 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.Atlas" units="count" - expires_after="2020-07-26"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on an Atlas device with an ambient sensor that is supported by the auto screen @@ -15127,8 +15161,11 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.Eve" units="count" - expires_after="2020-09-06"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on an Eve device with an ambient sensor that is supported by the auto screen brightness @@ -15141,9 +15178,11 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.Kohaku" units="count" - expires_after="2020-08-02"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on a Kohaku device with an ambient sensor that is supported by the auto screen @@ -15157,8 +15196,11 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.NoAls" units="count" - expires_after="2020-07-26"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on a device without an ambient sensor. Reported daily. The count is accumulated through @@ -15171,9 +15213,11 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.Nocturne" - units="count" expires_after="2020-08-02"> + units="count" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on a Nocturne device with an ambient sensor that is supported by the auto screen @@ -15187,8 +15231,11 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.SupportedAls" - units="count" expires_after="2020-09-20"> + units="count" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on a device with an ambient sensor that is supported by the auto screen brightness model. @@ -15201,8 +15248,11 @@ </histogram> <histogram name="AutoScreenBrightness.DailyUserAdjustment.UnsupportedAls" - units="count" expires_after="2020-06-30"> + units="count" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Number of times that a user has made brightness adjustments on a device with an ambient sensor that is not supported by the auto screen brightness model. @@ -15215,8 +15265,11 @@ </histogram> <histogram name="AutoScreenBrightness.DataError" - enum="AutoScreenBrightnessDataError" expires_after="2020-06-30"> + enum="AutoScreenBrightnessDataError" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Type of error seen when handling data related to automatic screen brightness adjustments. Only reported on Chrome OS. @@ -15225,8 +15278,11 @@ <histogram name="AutoScreenBrightness.ElapsedTimeBetweenModelAndUserAdjustments" - units="ms" expires_after="2020-05-03"> + units="ms" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> The elapsed time from a model brightness adjustment to the next user manual brightness change. Chrome OS only. @@ -15234,24 +15290,31 @@ </histogram> <histogram name="AutoScreenBrightness.GlobalCurveResetOnInitialization" - enum="Boolean" expires_after="2020-12-31"> + enum="Boolean" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary>Whether the global curve is reset at initialization.</summary> </histogram> <histogram name="AutoScreenBrightness.MissingAlsWhenBrightnessChanged" - enum="BooleanError" expires_after="2020-12-31"> + enum="BooleanError" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether there was no recorded ALS reading when brightness was changed. </summary> </histogram> <histogram name="AutoScreenBrightness.MissingPriorUserBrightnessRequest" - enum="BooleanError" expires_after="2020-06-30"> + enum="BooleanError" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Under the current implementation of brightness monitor, user brightness request should be received before brightness change signal. Adapter operates @@ -15262,25 +15325,34 @@ </histogram> <histogram name="AutoScreenBrightness.ModelIterationCountAtInitialization" - units="count" expires_after="2020-06-30"> + units="count" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>napper@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Personal model iteration count when modeller is initialized. Chrome OS only. </summary> </histogram> <histogram name="AutoScreenBrightness.ModelLoadingStatus" - enum="AutoScreenBrightnessModelLoadingStatus" expires_after="2020-06-30"> + enum="AutoScreenBrightnessModelLoadingStatus" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>napper@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary>Status of the model loading from disk. Chrome OS only.</summary> </histogram> <histogram name="AutoScreenBrightness.ModelTraining.BrightnessChange" enum="AutoScreenBrightnessBoundedBrightnessChange" - expires_after="2020-05-31"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether a new brightness exceeds the preset bound that defines reasonble range of change. Chrome OS only. @@ -15288,8 +15360,11 @@ </histogram> <histogram name="AutoScreenBrightness.ModelTraining.BrightnessOutlier" - enum="Boolean" expires_after="2020-05-31"> + enum="Boolean" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether a training data is an outlier and should be discarded by the model during training. Chrome OS only. @@ -15297,9 +15372,12 @@ </histogram> <histogram name="AutoScreenBrightness.ModelTraining.Inaccuracy.NoUpdate" - units="%" expires_after="2020-05-31"> + units="%" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>napper@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When training data comes in, the model may or may not be updated. We measure the error of the model as compared with the target value from training data. @@ -15308,9 +15386,12 @@ </histogram> <histogram name="AutoScreenBrightness.ModelTraining.Inaccuracy.Update" - units="%" expires_after="2020-05-31"> + units="%" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> <owner>napper@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When training data comes in, the model may or may not be updated. We measure the error of the model as compared with the target value from training data. @@ -15319,8 +15400,11 @@ </histogram> <histogram name="AutoScreenBrightness.ModelTraining.ModelUserConsistent" - enum="Boolean" expires_after="2020-05-31"> + enum="Boolean" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether user brightness change is consistent with the model so that model is not updated. @@ -15328,8 +15412,11 @@ </histogram> <histogram name="AutoScreenBrightness.NewCurveSaved.Duration" units="ms" - expires_after="2020-06-28"> + expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> The time elapsed between training start and a new curve saved to disk. Only reported if a new curve was created and saved successfully to disk. Chrome @@ -15338,8 +15425,11 @@ </histogram> <histogram name="AutoScreenBrightness.NewCurveSaved.Success" - enum="BooleanSuccess" expires_after="2020-07-06"> + enum="BooleanSuccess" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether a new curve was successfully saved to disk. Only reported if a new curve was created during the training process. Chrome OS only. @@ -15347,8 +15437,11 @@ </histogram> <histogram name="AutoScreenBrightness.Opposite.UserModelBrightnessAdjustments" - units="count" expires_after="2020-07-06"> + units="count" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, if the previous change was caused by the model, then we log bucketized absolute brightness changes of the two @@ -15358,8 +15451,11 @@ </histogram> <histogram name="AutoScreenBrightness.ParameterError" - enum="AutoScreenBrightnessParameterError" expires_after="2020-06-30"> + enum="AutoScreenBrightnessParameterError" expires_after="2020-11-30"> + <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When there is an error in the automatic screen brightness parameters, this records which kind of parameter is invalid. Chrome OS only. @@ -15367,16 +15463,22 @@ </histogram> <histogram name="AutoScreenBrightness.PersonalCurveValid" enum="BooleanValid" - expires_after="2020-08-30"> + expires_after="2020-11-30"> + <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> Whether the user's personal brightness curve is valid. Chrome OS only. </summary> </histogram> <histogram name="AutoScreenBrightness.Same.UserModelBrightnessAdjustments" - units="count" expires_after="2020-06-28"> + units="count" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> When user changes brightness manually, if the previous change was caused by the model, then we log bucketized absolute brightness changes of the two @@ -15386,8 +15488,11 @@ </histogram> <histogram name="AutoScreenBrightness.TrainingCompleteDuration.NewCurve" - units="ms" expires_after="2020-07-13"> + units="ms" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> The time elapsed to complete training after which a new curve was generated. Chrome OS only. @@ -15395,8 +15500,11 @@ </histogram> <histogram name="AutoScreenBrightness.TrainingCompleteDuration.NoNewCurve" - units="ms" expires_after="2020-07-06"> + units="ms" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> The time elapsed to complete training after which no new curve was generated. Chrome OS only. @@ -15413,8 +15521,11 @@ </histogram> <histogram name="AutoScreenBrightness.UserAdjustmentEffect" - enum="AutoScreenBrightnessUserAdjustmentEffect" expires_after="2020-05-03"> + enum="AutoScreenBrightnessUserAdjustmentEffect" expires_after="2020-11-30"> <owner>jiameng@chromium.org</owner> + <owner>wrong@chromium.org</owner> + <owner>tby@chromium.org</owner> + <owner>thanhdng@chromium.org</owner> <summary> How user manual screen brightness adjustment changes the model. Chrome OS only. @@ -69631,6 +69742,10 @@ <histogram base="true" name="MachineLearningService.ElapsedTimeMicrosec" units="microseconds" expires_after="2020-02-01"> + <obsolete> + Removed 2020-02-01 because elapsed time should be measured by clients, if + they need it. + </obsolete> <!-- Name completed by histogram_suffixes name="MachineLearningServiceRequests" --> @@ -116922,7 +117037,7 @@ </histogram> <histogram name="PasswordManager.StoreDecryptionResult" - enum="PasswordDecryptionResult" expires_after="2020-05-01"> + enum="PasswordDecryptionResult" expires_after="2020-11-01"> <owner>cfroussios@chromium.org</owner> <owner>dvadym@chromium.org</owner> <summary> @@ -123504,13 +123619,22 @@ </summary> </histogram> +<histogram name="PluginVm.SetupFailureReason" enum="PluginVmSetupFailureReason" + expires_after="2020-12-31"> + <owner>kimjae@chromium.org</owner> + <owner>timloh@chromium.org</owner> + <summary>Recorded when the Plugin VM installer fails.</summary> +</histogram> + <histogram name="PluginVm.SetupResult" enum="PluginVmSetupResult" expires_after="2020-12-31"> <owner>aoldemeier@chromium.org</owner> <owner>okalitova@chromium.org</owner> <owner>timloh@chromium.org</owner> <summary> - Recorded at each attempt to set up PluginVm, recording the setup result. + Recorded at each attempt to set up PluginVm, recording the setup result. As + of M83, errors are grouped together here and broken down in + PluginVm.SetupFailureReason. </summary> </histogram> @@ -149926,7 +150050,8 @@ <histogram base="true" name="Sharing.WebRtc.TimingEvents" units="ms" expires_after="M84"> -<!-- Name completed by histogram_suffixes name="SharingWebRtcTimingEvent" --> +<!-- Name completed by histogram_suffixes name="SharingWebRtcTimingEventRole" + and name="SharingWebRtcTimingEvent" --> <owner>himanshujaju@chromium.org</owner> <owner>knollr@chromium.org</owner> @@ -150845,7 +150970,7 @@ </histogram> <histogram name="Signin.OAuth2MintToken.ApiCallResult" - enum="OAuth2MintTokenApiCallResult" expires_after="2020-05-02"> + enum="OAuth2MintTokenApiCallResult" expires_after="2020-09-02"> <owner>alexilin@chromium.org</owner> <owner>droger@chromium.org</owner> <summary> @@ -190392,7 +190517,12 @@ <affected-histogram name="MachineLearningService.CreateGraphExecutorResult.CpuTimeMicrosec"/> <affected-histogram - name="MachineLearningService.CreateGraphExecutorResult.ElapsedTimeMicrosec"/> + name="MachineLearningService.CreateGraphExecutorResult.ElapsedTimeMicrosec"> + <obsolete> + Removed 2020-02-01 because elapsed time should be measured by clients, if + they need it. + </obsolete> + </affected-histogram> <affected-histogram name="MachineLearningService.CreateGraphExecutorResult.Event"/> <affected-histogram @@ -190400,14 +190530,24 @@ <affected-histogram name="MachineLearningService.ExecuteResult.CpuTimeMicrosec"/> <affected-histogram - name="MachineLearningService.ExecuteResult.ElapsedTimeMicrosec"/> + name="MachineLearningService.ExecuteResult.ElapsedTimeMicrosec"> + <obsolete> + Removed 2020-02-01 because elapsed time should be measured by clients, if + they need it. + </obsolete> + </affected-histogram> <affected-histogram name="MachineLearningService.ExecuteResult.Event"/> <affected-histogram name="MachineLearningService.ExecuteResult.TotalMemoryDeltaKb"/> <affected-histogram name="MachineLearningService.LoadModelResult.CpuTimeMicrosec"/> <affected-histogram - name="MachineLearningService.LoadModelResult.ElapsedTimeMicrosec"/> + name="MachineLearningService.LoadModelResult.ElapsedTimeMicrosec"> + <obsolete> + Removed 2020-02-01 because elapsed time should be measured by clients, if + they need it. + </obsolete> + </affected-histogram> <affected-histogram name="MachineLearningService.LoadModelResult.Event"/> <affected-histogram name="MachineLearningService.LoadModelResult.TotalMemoryDeltaKb"/> @@ -198446,6 +198586,16 @@ <suffix name="SendingMessage" label="Message sending"/> <suffix name="SignalingStable" label="Signaling process stable"/> <affected-histogram name="Sharing.WebRtc.TimingEvents"/> + <affected-histogram name="Sharing.WebRtc.TimingEvents.Receiver"/> + <affected-histogram name="Sharing.WebRtc.TimingEvents.Sender"/> + <affected-histogram name="Sharing.WebRtc.TimingEvents.Unknown"/> +</histogram_suffixes> + +<histogram_suffixes name="SharingWebRtcTimingEventRole" separator="."> + <suffix name="Receiver" label="Receiver device"/> + <suffix name="Sender" label="Sender device"/> + <suffix name="Unknown" label="Unknown"/> + <affected-histogram name="Sharing.WebRtc.TimingEvents"/> </histogram_suffixes> <histogram_suffixes name="ShillCumulativeTimeOnline" separator=".">
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index 92bdb30..fb95731 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1151,6 +1151,10 @@ width: 36px; } +html:not(.pointer-active) .dialog-header.files-ng #search-box .clear:hover { + background-color: rgba(0, 0, 0, 4%); +} + .dialog-header.files-ng #search-box .clear > .icon { -webkit-mask-image: url(../images/files/ui/search_clear_filled.svg); }
diff --git a/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js b/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js index 77ec00d..9f5c056 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js +++ b/ui/file_manager/file_manager/foreground/elements/files_xf_elements_unittest.js
@@ -318,6 +318,41 @@ assertEquals('success', summaryPanelItem.status); } +function testFilesDisplayPanelMixedProgress() { + // Get the host display panel container element. + /** @type {!DisplayPanel|!Element} */ + const displayPanel = assert(document.querySelector('#test-xf-display-panel')); + + // Add a generic progress panel item to the display panel container. + const progressPanel = displayPanel.addPanelItem('testpanel1'); + progressPanel.panelType = progressPanel.panelTypeProgress; + progressPanel.progress = '1'; + + // Add a format progress panel item to the display panel container. + const formatProgressPanel = displayPanel.addPanelItem('testpanel2'); + formatProgressPanel.panelType = formatProgressPanel.panelTypeFormatProgress; + formatProgressPanel.progress = '2'; + + // Confirm that format progress panels do not have a cancel button. + assertEquals(null, formatProgressPanel.secondaryButton); + + // Add a drive sync progress panel item to the display panel container. + const syncProgressPanel = displayPanel.addPanelItem('testpanel3'); + syncProgressPanel.panelType = syncProgressPanel.panelTypeSyncProgress; + syncProgressPanel.progress = '6'; + + // Confirm that sync progress panels do not have a cancel button. + assertEquals(null, syncProgressPanel.secondaryButton); + + // Verify a summary panel item is created with the correct average. + const summaryContainer = displayPanel.shadowRoot.querySelector('#summary'); + const summaryPanelItem = summaryContainer.querySelector('xf-panel-item'); + assertEquals(summaryPanelItem.panelTypeSummary, summaryPanelItem.panelType); + assertEquals('largeprogress', summaryPanelItem.indicator); + assertEquals('hidden', summaryPanelItem.errorMarkerVisibility); + assertEquals('3', summaryPanelItem.progress); +} + function testFilesDisplayPanelCircularProgress() { // Get the host display panel container element. /** @type {!DisplayPanel|!Element} */
diff --git a/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js b/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js index 59fed822..28c3631 100644 --- a/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js +++ b/ui/file_manager/file_manager/foreground/elements/xf_display_panel.js
@@ -241,7 +241,9 @@ const connectedPanels = this.connectedPanelItems_(); for (const panel of connectedPanels) { // Only sum progress for attached progress panels. - if (panel.panelType === panel.panelTypeProgress) { + if (panel.panelType === panel.panelTypeProgress || + panel.panelType === panel.panelTypeFormatProgress || + panel.panelType === panel.panelTypeSyncProgress) { total += Number(panel.progress); progressCount++; } else if (panel.panelType === panel.panelTypeError) {
diff --git a/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js b/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js index 9d11c507..96e8a61 100644 --- a/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js +++ b/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js
@@ -27,6 +27,7 @@ this.panelTypeError = 3; this.panelTypeInfo = 4; this.panelTypeFormatProgress = 5; + this.panelTypeSyncProgress = 6; /** @private {number} */ this.panelType_ = this.panelTypeDefault; @@ -265,6 +266,9 @@ this.setAttribute('indicator', 'status'); this.setAttribute('status', 'hard-drive'); break; + case this.panelTypeSyncProgress: + this.setAttribute('indicator', 'progress'); + break; } this.panelType_ = type;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js index 49c115b0..43d60cc 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js +++ b/ui/file_manager/file_manager/foreground/js/ui/progress_center_panel.js
@@ -426,6 +426,8 @@ }, this.PENDING_TIME_MS_); if (item.type === 'format') { panelItem.panelType = panelItem.panelTypeFormatProgress; + } else if (item.type === 'sync') { + panelItem.panelType = panelItem.panelTypeSyncProgress; } else { panelItem.panelType = panelItem.panelTypeProgress; }
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn index 4322a623..e49ee587 100644 --- a/weblayer/BUILD.gn +++ b/weblayer/BUILD.gn
@@ -373,6 +373,7 @@ "//components/minidump_uploader", "//components/navigation_interception", "//components/permissions/android:native", + "//components/resources:android_resources", "//components/safe_browsing/content/common:interfaces", "//components/safe_browsing/content/renderer:throttles", "//components/safe_browsing/core/common",
diff --git a/weblayer/browser/DEPS b/weblayer/browser/DEPS index 22ae82e5..ef4fd49 100644 --- a/weblayer/browser/DEPS +++ b/weblayer/browser/DEPS
@@ -24,6 +24,7 @@ "+components/prefs", "+components/url_formatter", "+components/user_prefs", + "+components/resources/android", "+components/safe_browsing/core/common", "+components/safe_browsing/core/features.h", "+components/security_interstitials",
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java index b55fef9..8fd8e12c 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java
@@ -18,6 +18,7 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CallbackHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.weblayer.Browser; import org.chromium.weblayer.Tab; import org.chromium.weblayer.shell.InstrumentationActivity; @@ -34,6 +35,10 @@ private static final String INTENT_TO_CHROME_URL = "intent://play.google.com/store/apps/details?id=com.facebook.katana/#Intent;scheme=https;action=android.intent.action.VIEW;package=com.android.chrome;end"; private static final String NON_RESOLVABLE_INTENT_URL = "intent://garbage;end"; + private static final String LINK_WITH_INTENT_TO_CHROME_IN_SAME_TAB_FILE = + "link_with_intent_to_chrome_in_same_tab.html"; + private static final String LINK_WITH_INTENT_TO_CHROME_IN_NEW_TAB_FILE = + "link_with_intent_to_chrome_in_new_tab.html"; // The test server handles "echo" with a response containing "Echo" :). private final String mTestServerSiteUrl = mActivityTestRule.getTestServer().getURL("/echo"); @@ -135,6 +140,83 @@ } /** + * Tests that clicking on a link that goes to an external intent in the same tab results in the + * external intent being launched. + */ + @Test + @SmallTest + public void testExternalIntentInSameTabLaunchedOnLinkClick() throws Throwable { + InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(ABOUT_BLANK_URL); + IntentInterceptor intentInterceptor = new IntentInterceptor(); + activity.setIntentInterceptor(intentInterceptor); + + String url = mActivityTestRule.getTestDataURL(LINK_WITH_INTENT_TO_CHROME_IN_SAME_TAB_FILE); + + mActivityTestRule.navigateAndWait(url); + + mActivityTestRule.executeScriptSync( + "document.onclick = function() {document.getElementById('link').click()}", + true /* useSeparateIsolate */); + EventUtils.simulateTouchCenterOfView( + mActivityTestRule.getActivity().getWindow().getDecorView()); + + intentInterceptor.waitForIntent(); + + // The current URL should not have changed, and the intent should have been launched. + Assert.assertEquals(url, mActivityTestRule.getCurrentDisplayUrl()); + Intent intent = intentInterceptor.mLastIntent; + Assert.assertNotNull(intent); + Assert.assertEquals("com.android.chrome", intent.getPackage()); + Assert.assertEquals("android.intent.action.VIEW", intent.getAction()); + Assert.assertEquals("https://play.google.com/store/apps/details?id=com.facebook.katana/", + intent.getDataString()); + } + + /** + * Tests that clicking on a link that goes to an external intent in a new tab results in + * a new tab being opened whose URL is that of the intent and the intent being launched. + */ + @Test + @SmallTest + public void testExternalIntentInNewTabLaunchedOnLinkClick() throws Throwable { + InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(ABOUT_BLANK_URL); + IntentInterceptor intentInterceptor = new IntentInterceptor(); + activity.setIntentInterceptor(intentInterceptor); + + String url = mActivityTestRule.getTestDataURL(LINK_WITH_INTENT_TO_CHROME_IN_NEW_TAB_FILE); + + mActivityTestRule.navigateAndWait(url); + + // Grab the existing tab before causing a new one to be opened. + Tab tab = mActivityTestRule.getActivity().getTab(); + + mActivityTestRule.executeScriptSync( + "document.onclick = function() {document.getElementById('link').click()}", + true /* useSeparateIsolate */); + EventUtils.simulateTouchCenterOfView( + mActivityTestRule.getActivity().getWindow().getDecorView()); + + intentInterceptor.waitForIntent(); + + // The current URL should not have changed in the existing tab, and the intent should have + // been launched. + Assert.assertEquals(url, mActivityTestRule.getLastCommittedUrlInTab(tab)); + Intent intent = intentInterceptor.mLastIntent; + Assert.assertNotNull(intent); + Assert.assertEquals("com.android.chrome", intent.getPackage()); + Assert.assertEquals("android.intent.action.VIEW", intent.getAction()); + Assert.assertEquals("https://play.google.com/store/apps/details?id=com.facebook.katana/", + intent.getDataString()); + + // A new tab should have been created whose URL is that of the intent. + Browser browser = mActivityTestRule.getActivity().getBrowser(); + int numTabs = + TestThreadUtils.runOnUiThreadBlocking(() -> { return browser.getTabs().size(); }); + Assert.assertEquals(2, numTabs); + Assert.assertEquals(INTENT_TO_CHROME_URL, mActivityTestRule.getCurrentDisplayUrl()); + } + + /** * Tests that a navigation that redirects to an external intent with a fallback URL results in * the external intent being launched. */
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java index b5af1eb1..20e6fc0 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java
@@ -260,15 +260,22 @@ return getTestServer().getURL("/weblayer/test/data/" + path); } - public String getCurrentDisplayUrl() { + // Returns the display URL of the last committed navigation entry in |tab|. Note that this will + // return an empty URL if there have been no committed navigations in |tab|. + public String getLastCommittedUrlInTab(Tab tab) { return TestThreadUtils.runOnUiThreadBlockingNoException(() -> { - NavigationController navController = getActivity().getTab().getNavigationController(); + NavigationController navController = tab.getNavigationController(); return navController .getNavigationEntryDisplayUri(navController.getNavigationListCurrentIndex()) .toString(); }); } + // Returns the URL that is currently being displayed to the user. + public String getCurrentDisplayUrl() { + return getActivity().getCurrentDisplayUrl(); + } + public void setRetainInstance(boolean retain) { TestThreadUtils.runOnUiThreadBlocking(() -> getActivity().setRetainInstance(retain)); }
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java index 9eccc256..c20ea5cf 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java
@@ -12,6 +12,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.DisabledTest; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -119,6 +120,7 @@ @Test @SmallTest + @DisabledTest public void testEnumerateAllProfileNames() throws Exception { final String profileName = "TestEnumerateAllProfileNames"; final WebLayer weblayer = mActivityTestRule.getWebLayer();
diff --git a/weblayer/browser/android/resource_mapper.cc b/weblayer/browser/android/resource_mapper.cc index 3d091df..e7f1a4d6 100644 --- a/weblayer/browser/android/resource_mapper.cc +++ b/weblayer/browser/android/resource_mapper.cc
@@ -10,7 +10,7 @@ #include "base/android/jni_array.h" #include "base/logging.h" #include "base/no_destructor.h" -#include "components/permissions/android/theme_resources.h" +#include "components/resources/android/theme_resources.h" #include "weblayer/browser/java/jni/ResourceMapper_jni.h" namespace weblayer { @@ -37,7 +37,7 @@ (*GetIdMap())[c_id] = resource_id_list[next_id++]; #define DECLARE_RESOURCE_ID(c_id, java_id) \ (*GetIdMap())[c_id] = resource_id_list[next_id++]; -#include "components/permissions/android/resource_id.h" +#include "components/resources/android/permissions_resource_id.h" #undef LINK_RESOURCE_ID #undef DECLARE_RESOURCE_ID // Make sure ID list sizes match up.
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn index 123a4e8..2712bcd6 100644 --- a/weblayer/browser/java/BUILD.gn +++ b/weblayer/browser/java/BUILD.gn
@@ -23,7 +23,7 @@ java_cpp_template("resource_id_javagen") { sources = [ "ResourceId.template" ] package_path = "org/chromium/weblayer_private/resources" - inputs = [ "//components/permissions/android/resource_id.h" ] + inputs = [ "//components/resources/android/permissions_resource_id.h" ] } java_cpp_enum("generated_enums") {
diff --git a/weblayer/browser/java/ResourceId.template b/weblayer/browser/java/ResourceId.template index ec5f017..15429c1 100644 --- a/weblayer/browser/java/ResourceId.template +++ b/weblayer/browser/java/ResourceId.template
@@ -11,7 +11,7 @@ int[] resourceList = { #define LINK_RESOURCE_ID(c_id,java_id) java_id, #define DECLARE_RESOURCE_ID(c_id,java_id) java_id, -#include "components/permissions/android/resource_id.h" +#include "components/resources/android/permissions_resource_id.h" }; return resourceList; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java index 686e3bb..937fa2f 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java
@@ -300,21 +300,6 @@ mNotificationId = getNextNotificationId(); sMap.put(Integer.valueOf(mNotificationId), this); - Intent pauseIntent = createIntent(); - pauseIntent.setAction(PAUSE_INTENT); - pauseIntent.putExtra(EXTRA_NOTIFICATION_ID, mNotificationId); - - // See PendingIntent's documentation on why we must use a different requestId as we need - // multiple distinct PendingIntents at a time, one for each notification. - PendingIntent pausePendingIntent = PendingIntent.getBroadcast( - ContextUtils.getApplicationContext(), mNotificationId, pauseIntent, 0); - - Intent cancelIntent = createIntent(); - cancelIntent.setAction(CANCEL_INTENT); - cancelIntent.putExtra(EXTRA_NOTIFICATION_ID, mNotificationId); - PendingIntent cancelPendingIntent = PendingIntent.getBroadcast( - ContextUtils.getApplicationContext(), mNotificationId, cancelIntent, 0); - Intent deleteIntent = createIntent(); deleteIntent.setAction(DELETE_INTENT); deleteIntent.putExtra(EXTRA_NOTIFICATION_ID, mNotificationId); @@ -323,41 +308,17 @@ mBuilder = new NotificationCompat.Builder(ContextUtils.getApplicationContext(), CHANNEL_ID) .setSmallIcon(android.R.drawable.stat_sys_download) - .setContentTitle((new File(getLocation())).getName()) .setOngoing(true) - .addAction(0 /* no icon */, "Pause", pausePendingIntent) - .addAction(0 /* no icon */, "Cancel", cancelPendingIntent) .setDeleteIntent(deletePendingIntent) .setPriority(NotificationCompat.PRIORITY_DEFAULT); - if (getTotalBytes() == -1) { - mBuilder.setProgress(0, 0, true); - } else { - mBuilder.setProgress(100, 0, false); - } - - NotificationManagerCompat notificationManager = getNotificationManager(); - if (notificationManager != null) { - // mNotificationId is a unique int for each notification that you must define - notificationManager.notify(mNotificationId, mBuilder.build()); - } + updateNotification(); } public void downloadProgressChanged() { if (mBuilder == null) return; - // The filename might not have been available initially. - mBuilder.setContentTitle((new File(getLocation())).getName()); - if (getTotalBytes() > 0) { - int progressCurrent = (int) (getReceivedBytes() * 100 / getTotalBytes()); - - mBuilder.setProgress(100, progressCurrent, false); - - NotificationManagerCompat notificationManager = getNotificationManager(); - if (notificationManager != null) { - notificationManager.notify(mNotificationId, mBuilder.build()); - } - } + updateNotification(); } public void downloadCompleted() { @@ -392,6 +353,18 @@ NotificationManagerCompat notificationManager = getNotificationManager(); + // The filename might not have been available initially. + String location = getLocation(); + if (!TextUtils.isEmpty((location))) { + mBuilder.setContentTitle((new File(location)).getName()); + } + + if (getTotalBytes() > 0) { + int progressCurrent = (int) (getReceivedBytes() * 100 / getTotalBytes()); + + mBuilder.setProgress(100, progressCurrent, false); + } + @DownloadState int state = getState(); if (state == DownloadState.CANCELLED) { @@ -451,6 +424,7 @@ } if (notificationManager != null) { + // mNotificationId is a unique int for each notification that you must define. notificationManager.notify(mNotificationId, mBuilder.build()); } }
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java index d6cf0c8..573980b 100644 --- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java +++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
@@ -26,6 +26,8 @@ import org.chromium.base.ContextUtils; import org.chromium.weblayer.Browser; +import org.chromium.weblayer.NewTabCallback; +import org.chromium.weblayer.NewTabType; import org.chromium.weblayer.Profile; import org.chromium.weblayer.Tab; import org.chromium.weblayer.TabCallback; @@ -248,6 +250,26 @@ } }; mTab.registerTabCallback(mTabCallback); + + mTab.setNewTabCallback(new NewTabCallback() { + @Override + public void onNewTab(Tab newTab, @NewTabType int type) { + // NOTE: At this time there isn't a need to hang on to the previous tab as this + // activity doesn't support closing tabs. If needed that could be added following + // the implementation in WebLayerShellActivity.java. + mTab.unregisterTabCallback(mTabCallback); + mTabCallback = null; + mTab = null; + + setTab(newTab); + mBrowser.setActiveTab(newTab); + } + + @Override + public void onCloseTab() { + assert false; + } + }); } private Fragment getOrCreateBrowserFragment() { @@ -284,6 +306,10 @@ return fragment; } + public String getCurrentDisplayUrl() { + return mUrlView.getText().toString(); + } + public void loadUrl(String url) { mTab.getNavigationController().navigate(Uri.parse(url)); mUrlView.clearFocus();
diff --git a/weblayer/test/data/link_with_intent_to_chrome_in_new_tab.html b/weblayer/test/data/link_with_intent_to_chrome_in_new_tab.html new file mode 100644 index 0000000..44994a17 --- /dev/null +++ b/weblayer/test/data/link_with_intent_to_chrome_in_new_tab.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <meta name="viewport" + content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> +</head> +<body> + <a id='link' target='_blank' href='intent://play.google.com/store/apps/details?id=com.facebook.katana/#Intent;scheme=https;action=android.intent.action.VIEW;package=com.android.chrome;end'> + Click to intent to production Chrome in a new tab +</a> +</body> +</html>
diff --git a/weblayer/test/data/link_with_intent_to_chrome_in_same_tab.html b/weblayer/test/data/link_with_intent_to_chrome_in_same_tab.html new file mode 100644 index 0000000..e442dc92 --- /dev/null +++ b/weblayer/test/data/link_with_intent_to_chrome_in_same_tab.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <meta name="viewport" + content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> +</head> +<body> + <a id='link' href='intent://play.google.com/store/apps/details?id=com.facebook.katana/#Intent;scheme=https;action=android.intent.action.VIEW;package=com.android.chrome;end'> + Click to intent to production Chrome in this tab +</a> +</body> +</html>