diff --git a/DEPS b/DEPS index e5a5fdc..47d8f4d 100644 --- a/DEPS +++ b/DEPS
@@ -279,15 +279,15 @@ # 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': '747cd3ae5d474f09cba2498949a53b948f8754a3', + 'v8_revision': '2425750cbd27e8ed125d16e4a31cd779fd286aaa', # 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': 'a2fe4445dce56d79ef06e4bc8f3f70e3c20e8bea', + 'angle_revision': 'ae74bdb3db5154646af1a85bb8a9e102fa954efa', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'd070309f7d154d6764cbd514b1a5c8bfcef61d06', + 'swiftshader_revision': '51c43dc015b7a1d73cfd6baf4bf95718a92acb82', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # 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 Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:8.20220530.1.1', + 'fuchsia_version': 'version:8.20220530.2.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -354,7 +354,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': '4f8eb95593e80f31965ac653171f386db31cfc55', + 'devtools_frontend_revision': 'b6a3b2ae8a4c1d5847c2bb1535377e13ee3045be', # 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. @@ -390,7 +390,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': 'aa25d7ed2bfb2767ccbfd411e0b521d166b286b8', + 'dawn_revision': 'd7d55e48592070ebfe8a053dbfa342e8a6b2552d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -920,7 +920,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': '_BgrtGL0M9mSNIBsFxZ4z69R1FN_czTV0jN8uTXnODkC', + 'version': 'rub6aXBz5r6WR9pBd1H-bRnRkT8jX123XYM5pQG_xhwC', }, ], 'condition': 'checkout_android', @@ -1533,7 +1533,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '23339a6fac0aeb6c2289af885ee4d1df0a9aaf90', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'feeb5c1043fc9fe022b6c720aae568fbac7b0f1a', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1781,7 +1781,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3c3d2fcd96d1b03badcfb56aa17cc46455b40ecf', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@1de44161d87b560d5591e9794365c430a93035b0', 'condition': 'checkout_src_internal', }, @@ -1811,7 +1811,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'RAGJFGUzieQLuZwQMW08I0z_nV1O9sB1QaV-hShpRCEC', + 'version': 'NoHsPCu4CtYBPKLfOQEiCCOEOakwBbQzFvQdzkJE62IC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1822,7 +1822,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'P4RsJ7B5KwOErrFWaBhBccR2lbGgQuN5SHwJCtGy7-sC', + 'version': 'fAwvEhy-AStpxksGoC7k7vU4v19rjtfrnu-c8ElEg0wC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/base/files/file_path.cc b/base/files/file_path.cc index d077fbb8..df44a189 100644 --- a/base/files/file_path.cc +++ b/base/files/file_path.cc
@@ -152,13 +152,13 @@ for (auto* i : kCommonDoubleExtensions) { StringType extension(path, penultimate_dot + 1); - if (LowerCaseEqualsASCII(extension, i)) + if (EqualsCaseInsensitiveASCII(extension, i)) return penultimate_dot; } StringType extension(path, last_dot + 1); for (auto* i : kCommonDoubleExtensionSuffixes) { - if (LowerCaseEqualsASCII(extension, i)) { + if (EqualsCaseInsensitiveASCII(extension, i)) { if ((last_dot - penultimate_dot) <= 5U && (last_dot - penultimate_dot) > 1U) { return penultimate_dot;
diff --git a/build/android/gyp/create_app_bundle.py b/build/android/gyp/create_app_bundle.py index 4a979b39..87e396b 100755 --- a/build/android/gyp/create_app_bundle.py +++ b/build/android/gyp/create_app_bundle.py
@@ -7,7 +7,9 @@ """Create an Android application bundle from one or more bundle modules.""" import argparse +import concurrent.futures import json +import logging import os import shutil import sys @@ -405,6 +407,15 @@ return [s.attrib.get(android_name) for s in manifest.iter(tag_name)] +def _ClassesFromZip(module_zip): + classes = set() + for package in dexdump.Dump(module_zip): + for java_package, package_dict in package.items(): + java_package += '.' if java_package else '' + classes.update(java_package + c for c in package_dict['classes']) + return classes + + def _MaybeCheckServicesAndProvidersPresentInBase(bundle_path, module_zips): """Checks bundles with isolated splits define all services in the base module. @@ -413,13 +424,31 @@ startup, and keeping them in the base module gives more time for the chrome split to load. """ - base_manifest = _GetManifestForModule(bundle_path, 'base') + logging.info('Reading manifests and running dexdump') + base_zip = next(p for p in module_zips if os.path.basename(p) == 'base.zip') + module_names = [os.path.basename(p)[:-len('.zip')] for p in module_zips] + # Using threads makes these step go from 7s -> 1s on my machine. + with concurrent.futures.ThreadPoolExecutor() as executor: + # Create list of classes from the base module's dex. + classes_future = executor.submit(_ClassesFromZip, base_zip) + + # Create xmltrees of all module manifests. + manifest_futures = [ + executor.submit(_GetManifestForModule, bundle_path, name) + for name in module_names + ] + manifests_by_name = dict( + zip(module_names, (f.result() for f in manifest_futures))) + base_classes = classes_future.result() + + base_manifest = manifests_by_name['base'] isolated_splits = base_manifest.get('{%s}isolatedSplits' % manifest_utils.ANDROID_NAMESPACE) if isolated_splits != 'true': return # Collect service names from all split manifests. + logging.info('Performing checks') base_zip = None service_names = _GetComponentNames(base_manifest, 'service') provider_names = _GetComponentNames(base_manifest, 'provider') @@ -428,25 +457,13 @@ if name == 'base': base_zip = module_zip else: - service_names.extend( - _GetComponentNames(_GetManifestForModule(bundle_path, name), - 'service')) - module_providers = _GetComponentNames( - _GetManifestForModule(bundle_path, name), 'provider') + cur_manifest = manifests_by_name[name] + service_names += _GetComponentNames(cur_manifest, 'service') + module_providers = _GetComponentNames(cur_manifest, 'provider') if module_providers: raise Exception("Providers should all be declared in the base manifest." " '%s' module declared: %s" % (name, module_providers)) - # Extract classes from the base module's dex. - classes = set() - base_package_name = manifest_utils.GetPackage(base_manifest) - for package in dexdump.Dump(base_zip): - for name, package_dict in package.items(): - if not name: - name = base_package_name - classes.update('%s.%s' % (name, c) - for c in package_dict['classes'].keys()) - ignored_service_names = { # Defined in the chime DFM manifest, but unused. # org.chromium.chrome.browser.chime.ScheduledTaskService is used instead. @@ -461,7 +478,7 @@ # Ensure all services are present in base module. for service_name in service_names: - if service_name not in classes: + if service_name not in base_classes: if service_name in ignored_service_names: continue raise Exception("Service %s should be present in the base module's dex." @@ -469,13 +486,14 @@ # Ensure all providers are present in base module. for provider_name in provider_names: - if provider_name not in classes: + if provider_name not in base_classes: raise Exception( "Provider %s should be present in the base module's dex." % provider_name) def main(args): + build_utils.InitLogging('AAB_DEBUG') args = build_utils.ExpandFileArgs(args) options = _ParseArgs(args) @@ -485,15 +503,18 @@ with build_utils.TempDir() as tmp_dir: + logging.info('Splitting locale assets') module_zips = [ _SplitModuleForAssetTargeting(module, tmp_dir, split_dimensions) \ for module in options.module_zips] base_master_resource_ids = None if options.base_module_rtxt_path: + logging.info('Creating R.txt allowlist') base_master_resource_ids = _GenerateBaseResourcesAllowList( options.base_module_rtxt_path, options.base_allowlist_rtxt_path) + logging.info('Creating BundleConfig.pb.json') bundle_config = _GenerateBundleConfigJson(options.uncompressed_assets, options.compress_dex, options.compress_shared_libraries, @@ -509,6 +530,7 @@ with open(tmp_bundle_config, 'w') as f: f.write(bundle_config) + logging.info('Running bundletool') cmd_args = build_utils.JavaCmd(options.warnings_as_errors) + [ '-jar', bundletool.BUNDLETOOL_JAR_PATH, @@ -530,8 +552,10 @@ # isolated splits disabled and 2s for bundles with isolated splits # enabled. Consider making this run in parallel or move into a separate # step before enabling isolated splits by default. + logging.info('Validating isolated split manifests') _MaybeCheckServicesAndProvidersPresentInBase(tmp_bundle, module_zips) + logging.info('Writing final output artifacts') shutil.move(tmp_bundle, options.out_bundle) if options.rtxt_out_path:
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index dfd7e5b..89ee643 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -8.20220530.1.1 +8.20220530.2.1
diff --git a/cc/animation/element_animations_unittest.cc b/cc/animation/element_animations_unittest.cc index d947861..63d3e3d4 100644 --- a/cc/animation/element_animations_unittest.cc +++ b/cc/animation/element_animations_unittest.cc
@@ -695,6 +695,66 @@ EXPECT_FALSE(animation_impl_->keyframe_effect()->has_any_keyframe_model()); } +// Test an animation that finishes on impl but is deleted on main before the +// event is received. https://crbug.com/1325393. +TEST_F(ElementAnimationsTest, AnimationFinishedOnImplDeletedOnMain) { + CreateTestLayer(true, false); + AttachTimelineAnimationLayer(); + CreateImplTimelineAndAnimation(); + + auto events = CreateEventsForTesting(); + + AddOpacityTransitionToAnimation(animation_.get(), 1.0, 0.0f, 1.0f, false); + animation_->Tick(kInitialTickTime); + animation_->UpdateState(true, nullptr); + EXPECT_TRUE(animation_->keyframe_effect()->needs_push_properties()); + + PushProperties(); + EXPECT_FALSE(animation_->keyframe_effect()->needs_push_properties()); + + animation_impl_->ActivateKeyframeModels(); + + animation_impl_->Tick(kInitialTickTime + base::Milliseconds(500)); + animation_impl_->UpdateState(true, events.get()); + + // There should be a STARTED event for the animation. + EXPECT_EQ(1u, events->events_.size()); + EXPECT_EQ(AnimationEvent::STARTED, events->events_[0].type); + animation_->DispatchAndDelegateAnimationEvent(events->events_[0]); + + events = CreateEventsForTesting(); + animation_impl_->Tick(kInitialTickTime + base::Milliseconds(2000)); + animation_impl_->UpdateState(true, events.get()); + + EXPECT_TRUE(host_impl_->needs_push_properties()); + + // There should be a FINISHED event for the animation. + EXPECT_EQ(1u, events->events_.size()); + EXPECT_EQ(AnimationEvent::FINISHED, events->events_[0].type); + + // Before the FINISHED event is received, main aborts the keyframe + // and detaches the element. + animation_->AbortKeyframeModelsWithProperty(TargetProperty::OPACITY, false); + PushProperties(); + animation_->DetachElement(); + // Expect no keyframe model. + EXPECT_FALSE(animation_->keyframe_effect()->has_any_keyframe_model()); + + // Then we dispatch the FINISHED event. + animation_->DispatchAndDelegateAnimationEvent(events->events_[0]); + + EXPECT_TRUE(host_->needs_push_properties()); + + PushProperties(); + + // Both animations should now have deleted the animation. The impl animations + // should have deleted the animation even though activation has not occurred, + // since the animation was already waiting for deletion when + // PushPropertiesTo was called. + EXPECT_FALSE(animation_->keyframe_effect()->has_any_keyframe_model()); + EXPECT_FALSE(animation_impl_->keyframe_effect()->has_any_keyframe_model()); +} + // Tests that transitioning opacity from 0 to 1 works as expected. static std::unique_ptr<KeyframeModel> CreateKeyframeModel(
diff --git a/cc/animation/keyframe_effect.cc b/cc/animation/keyframe_effect.cc index 6e72d37b..804d1c5 100644 --- a/cc/animation/keyframe_effect.cc +++ b/cc/animation/keyframe_effect.cc
@@ -67,10 +67,15 @@ void KeyframeEffect::SetNeedsPushProperties() { needs_push_properties_ = true; + // The keyframe effect may have been removed from the main thread while + // an event was in flight from the compositor. In this case, we may need + // to push the removal to the compositor but do not expect to have a bound + // element animations instance. // TODO(smcgruer): We only need the below calls when needs_push_properties_ // goes from false to true - see http://crbug.com/764405 - DCHECK(element_animations()); - element_animations_->SetNeedsPushProperties(); + if (element_animations()) { + element_animations_->SetNeedsPushProperties(); + } animation_->SetNeedsPushProperties(); }
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index db52cf6..23efa96 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc
@@ -661,9 +661,8 @@ dump->AddScalar(MemoryAllocatorDump::kNameSize, MemoryAllocatorDump::kUnitsBytes, total_bytes); - if (is_free) { - dump->AddScalar("free_size", MemoryAllocatorDump::kUnitsBytes, total_bytes); - } + uint64_t free_size = is_free ? total_bytes : 0u; + dump->AddScalar("free_size", MemoryAllocatorDump::kUnitsBytes, free_size); } } // namespace cc
diff --git a/chrome/VERSION b/chrome/VERSION index 2cc68b1..40e610c 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=104 MINOR=0 -BUILD=5093 +BUILD=5094 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java index 1acbdf60..9ed2398 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java
@@ -119,6 +119,7 @@ Drawable accountImage = mProfileDataCache.getProfileDataOrDefault(signedInAccount).getImage(); errorCardView.getImage().setImageDrawable(accountImage); + errorCardView.getIllustration().setVisibility(View.GONE); errorCardView.getDismissButton().setVisibility(View.GONE); if (mSyncError == SyncError.SYNC_SETUP_INCOMPLETE) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/RedirectHandlerTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/RedirectHandlerTabHelper.java index fa6f652..1080dcd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/RedirectHandlerTabHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/RedirectHandlerTabHelper.java
@@ -14,7 +14,6 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.LaunchIntentDispatcher; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.components.external_intents.RedirectHandler; import org.chromium.content_public.browser.NavigationHandle; import org.chromium.ui.base.WindowAndroid; @@ -119,7 +118,6 @@ LaunchIntentDispatcher.isCustomTabIntent(intent), IntentUtils.safeGetBooleanExtra(intent, CustomTabIntentDataProvider.EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER, false), - ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_EXTERNAL_LINK_HANDLING), IntentUtils.safeGetBooleanExtra( intent, IntentHandler.EXTRA_STARTED_TABBED_CHROME_TASK, false)); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java index 84bc00d4..c5f15e6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java
@@ -32,7 +32,6 @@ import org.robolectric.annotation.Config; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.util.browser.Features; @@ -44,7 +43,6 @@ */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE, shadows = {ShadowUrlUtilities.class}) -@Features.DisableFeatures({ChromeFeatureList.CCT_EXTERNAL_LINK_HANDLING}) public class CustomTabActivityTabControllerUnitTest { @Rule public final CustomTabActivityContentTestEnvironment env =
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java index ff88643..3744f9a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
@@ -34,7 +34,6 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.password_manager.PasswordChangeSuccessTrackerBridge; import org.chromium.chrome.browser.password_manager.PasswordChangeSuccessTrackerBridgeJni; import org.chromium.chrome.browser.profiles.Profile; @@ -50,7 +49,6 @@ */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) -@Features.DisableFeatures({ChromeFeatureList.CCT_EXTERNAL_LINK_HANDLING}) public class CustomTabActivityUrlLoadingTest { public static final String PASSWORD_CHANGE_USERNAME = "Peter";
diff --git a/chrome/app/settings_chromium_strings.grdp b/chrome/app/settings_chromium_strings.grdp index 541432c..999dd94 100644 --- a/chrome/app/settings_chromium_strings.grdp +++ b/chrome/app/settings_chromium_strings.grdp
@@ -126,6 +126,11 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_PDFS_BLOCKED" desc="Label for the disabled option of the pdfs content setting."> Open PDFs in Chromium </message> + <if expr="not chromeos_ash and not chromeos_lacros"> + <message name="IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC" desc="Secondary text for the toggle that allows the user to automatically delete their cookies and site data when they close all browser windows. This sublabel clarifies that when the toggle is enabled the user will be signed out of Chrome each time they close all Chrome windows."> + When on, you'll also be signed out of Chromium + </message> + </if> <!-- Privacy Guide --> <message name="IDS_SETTINGS_PRIVACY_GUIDE_PROMO_BODY" desc="Body text of a card in the settings page that explains what the 'Privacy Guide' feature is.">
diff --git a/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC.png.sha1 b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC.png.sha1 new file mode 100644 index 0000000..3e1ce0f --- /dev/null +++ b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC.png.sha1
@@ -0,0 +1 @@ +059791f0a4af8e103f5c19d553060b3c76e353dc
diff --git a/chrome/app/settings_google_chrome_strings.grdp b/chrome/app/settings_google_chrome_strings.grdp index 6a83be6..01142088 100644 --- a/chrome/app/settings_google_chrome_strings.grdp +++ b/chrome/app/settings_google_chrome_strings.grdp
@@ -152,6 +152,11 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_PDFS_BLOCKED" desc="Label for the disabled option of the pdfs content setting."> Open PDFs in Chrome </message> + <if expr="not chromeos_ash and not chromeos_lacros"> + <message name="IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC" desc="Secondary text for the toggle that allows the user to automatically delete their cookies and site data when they close all browser windows. This sublabel clarifies that when the toggle is enabled the user will be signed out of Chrome each time they close all Chrome windows."> + When on, you'll also be signed out of Chrome + </message> + </if> <!-- Privacy Guide --> <message name="IDS_SETTINGS_PRIVACY_GUIDE_PROMO_BODY" desc="Body text of a card in the settings page that explains what the 'Privacy Guide' feature is.">
diff --git a/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC.png.sha1 b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC.png.sha1 new file mode 100644 index 0000000..3e1ce0f --- /dev/null +++ b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC.png.sha1
@@ -0,0 +1 @@ +059791f0a4af8e103f5c19d553060b3c76e353dc
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index c3a56c0..df6a635 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -129,6 +129,7 @@ #include "components/search/ntp_features.h" #include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h" #include "components/security_state/core/security_state.h" +#include "components/segmentation_platform/public/features.h" #include "components/send_tab_to_self/features.h" #include "components/services/heap_profiling/public/cpp/switches.h" #include "components/shared_highlighting/core/common/shared_highlighting_features.h" @@ -4040,6 +4041,12 @@ chrome::android::kAdaptiveButtonInTopToolbarCustomizationV2, kAdaptiveButtonInTopToolbarCustomizationVariations, "OptionalToolbarButtonCustomization")}, + {"contextual-page-actions-with-price-tracking", + flag_descriptions::kContextualPageActionsWithPriceTrackingName, + flag_descriptions::kContextualPageActionsWithPriceTrackingDescription, + kOsAndroid, + FEATURE_VALUE_TYPE(segmentation_platform::features:: + kContextualPageActionsWithPriceTracking)}, {"reader-mode-heuristics", flag_descriptions::kReaderModeHeuristicsName, flag_descriptions::kReaderModeHeuristicsDescription, kOsAndroid, MULTI_VALUE_TYPE(kReaderModeHeuristicsChoices)},
diff --git a/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc b/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc index 8e01ac8b..cb56262 100644 --- a/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc +++ b/chrome/browser/ash/lock_screen_apps/app_manager_impl.cc
@@ -72,12 +72,9 @@ kCount = 3 }; -ActionAvailability GetLockScreenNoteTakingAvailability( - ash::NoteTakingAppInfo* app_info) { - if (!app_info || !app_info->preferred) - return ActionAvailability::kNoActionHandlerApp; - - switch (app_info->lock_screen_support) { +ActionAvailability ToActionAvailability( + ash::NoteTakingLockScreenSupport lock_screen_support) { + switch (lock_screen_support) { case ash::NoteTakingLockScreenSupport::kNotSupported: return ActionAvailability::kAppNotSupportingLockScreen; case ash::NoteTakingLockScreenSupport::kSupported: @@ -353,13 +350,14 @@ } std::string AppManagerImpl::FindLockScreenAppId() const { - // Note that lock screen does not currently support Android apps, so - // it's enough to only check the state of the preferred Chrome app. - std::unique_ptr<ash::NoteTakingAppInfo> note_taking_app = - ash::NoteTakingHelper::Get()->GetPreferredLockScreenAppInfo( - primary_profile_); + ash::NoteTakingHelper* helper = ash::NoteTakingHelper::Get(); + std::string app_id = helper->GetPreferredAppId(primary_profile_); + ash::NoteTakingLockScreenSupport lock_screen_support = + helper->GetLockScreenSupportForApp(primary_profile_, app_id); + ActionAvailability availability = - GetLockScreenNoteTakingAvailability(note_taking_app.get()); + app_id.empty() ? ActionAvailability::kNoActionHandlerApp + : ToActionAvailability(lock_screen_support); // |lock_screen_profile_| is created only if a note taking app is available // on the lock screen. If an app is not available, the profile is expected to @@ -379,7 +377,7 @@ if (availability != ActionAvailability::kAvailable) return std::string(); - return note_taking_app->app_id; + return app_id; } AppManagerImpl::State AppManagerImpl::AddAppToLockScreenProfile(
diff --git a/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl.cc b/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl.cc index 43e3652..3ca3ea9 100644 --- a/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl.cc +++ b/chrome/browser/ash/lock_screen_apps/lock_screen_profile_creator_impl.cc
@@ -37,13 +37,12 @@ if (profile != primary_profile_) return; - std::unique_ptr<ash::NoteTakingAppInfo> note_taking_app = - ash::NoteTakingHelper::Get()->GetPreferredLockScreenAppInfo( - primary_profile_); + ash::NoteTakingHelper* helper = ash::NoteTakingHelper::Get(); + std::string app_id = helper->GetPreferredAppId(primary_profile_); + ash::NoteTakingLockScreenSupport support = + helper->GetLockScreenSupportForApp(primary_profile_, app_id); - if (!note_taking_app || !note_taking_app->preferred || - note_taking_app->lock_screen_support != - ash::NoteTakingLockScreenSupport::kEnabled) { + if (support != ash::NoteTakingLockScreenSupport::kEnabled) { return; }
diff --git a/chrome/browser/ash/note_taking_helper.cc b/chrome/browser/ash/note_taking_helper.cc index ca29872..a62b575 100644 --- a/chrome/browser/ash/note_taking_helper.cc +++ b/chrome/browser/ash/note_taking_helper.cc
@@ -86,14 +86,29 @@ return base::Contains(app_id, '.'); } +bool IsInstalledApp(const std::string& app_id, Profile* profile) { + if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) + return false; + auto& cache = + apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); + + bool result = false; + cache.ForOneApp(app_id, [&result](const apps::AppUpdate& update) { + if (apps_util::IsInstalled(update.Readiness())) { + result = true; + } + }); + return result; +} + bool IsInstalledWebApp(const std::string& app_id, Profile* profile) { if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) return false; - auto* cache = - &apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); + auto& cache = + apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); bool result = false; - cache->ForOneApp(app_id, [&result](const apps::AppUpdate& update) { + cache.ForOneApp(app_id, [&result](const apps::AppUpdate& update) { if (apps_util::IsInstalled(update.Readiness()) && update.AppType() == apps::AppType::kWeb) { result = true; @@ -118,10 +133,10 @@ std::string name; if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) return name; - auto* cache = - &apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); + auto& cache = + apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); - cache->ForOneApp(app_id, [&name](const apps::AppUpdate& update) { + cache.ForOneApp(app_id, [&name](const apps::AppUpdate& update) { if (apps_util::IsInstalled(update.Readiness())) name = update.Name(); }); @@ -163,30 +178,26 @@ return false; } -// Whether the app's manifest indicates that the app supports note taking on the -// lock screen. +// Whether the app's manifest indicates that the app supports use on the lock +// screen. // TODO(crbug.com/1006642): Move this to a lock-screen-specific place. -bool IsLockScreenEnabled(Profile* profile, const std::string& app_id) { +bool IsLockScreenCapable(Profile* profile, const std::string& app_id) { if (IsInstalledWebApp(app_id, profile)) { // TODO(crbug.com/1006642): Add lock screen web app support. return false; } - // `app_id` may be for a Chrome app. const extensions::Extension* chrome_app = extensions::ExtensionRegistry::Get(profile)->GetExtensionById( app_id, extensions::ExtensionRegistry::ENABLED); - if (chrome_app) { - if (!chrome_app->permissions_data()->HasAPIPermission( - extensions::mojom::APIPermissionID::kLockScreen)) { - return false; - } - return extensions::ActionHandlersInfo::HasLockScreenActionHandler( - chrome_app, app_runtime::ACTION_TYPE_NEW_NOTE); + if (!chrome_app) + return false; + if (!chrome_app->permissions_data()->HasAPIPermission( + extensions::mojom::APIPermissionID::kLockScreen)) { + return false; } - - // Android apps are not currently supported on the lock screen. - return false; + return extensions::ActionHandlersInfo::HasLockScreenActionHandler( + chrome_app, app_runtime::ACTION_TYPE_NEW_NOTE); } // Gets the set of app IDs that are allowed to be launched on the lock screen, @@ -233,11 +244,11 @@ DCHECK(IsInstalledWebApp(app_id, profile)); DCHECK( apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)); - auto* cache = - &apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); + auto& cache = + apps::AppServiceProxyFactory::GetForProfile(profile)->AppRegistryCache(); bool has_note_taking_intent_filter = false; - cache->ForOneApp( + cache.ForOneApp( app_id, [&has_note_taking_intent_filter](const apps::AppUpdate& update) { if (HasNoteTakingIntentFilter(update.IntentFilters())) has_note_taking_intent_filter = true; @@ -315,7 +326,7 @@ for (const auto& app_id : app_ids) { // TODO(crbug.com/1006642): Move this to a lock-screen-specific place. NoteTakingLockScreenSupport lock_screen_support = - GetLockScreenSupportForAppId(profile, app_id); + GetLockScreenSupportForApp(profile, app_id); infos.push_back(NoteTakingAppInfo{GetAppName(profile, app_id), app_id, false, lock_screen_support}); } @@ -336,42 +347,11 @@ return infos; } -// TODO(crbug.com/1006642): Move this to a lock-screen-specific place. -std::unique_ptr<NoteTakingAppInfo> -NoteTakingHelper::GetPreferredLockScreenAppInfo(Profile* profile) { - std::string preferred_app_id = - profile->GetPrefs()->GetString(prefs::kNoteTakingAppId); - if (LooksLikeAndroidPackageName(preferred_app_id)) - return nullptr; - - if (preferred_app_id.empty()) - preferred_app_id = kProdKeepExtensionId; - - if (IsInstalledWebApp(preferred_app_id, profile)) { - // TODO(crbug.com/1006642): Add lock screen web app support. - return nullptr; - } - - const extensions::Extension* chrome_app = - extensions::ExtensionRegistry::Get(profile)->GetExtensionById( - preferred_app_id, extensions::ExtensionRegistry::ENABLED); - if (!chrome_app) - return nullptr; - - if (!IsAllowedApp(preferred_app_id) && - !extensions::ActionHandlersInfo::HasActionHandler( - chrome_app, app_runtime::ACTION_TYPE_NEW_NOTE)) { - return nullptr; - } - - std::unique_ptr<NoteTakingAppInfo> info = - std::make_unique<NoteTakingAppInfo>(); - info->name = chrome_app->name(); - info->app_id = preferred_app_id; - info->preferred = true; - info->lock_screen_support = - GetLockScreenSupportForAppId(profile, preferred_app_id); - return info; +std::string NoteTakingHelper::GetPreferredAppId(Profile* profile) { + std::string app_id = profile->GetPrefs()->GetString(prefs::kNoteTakingAppId); + if (IsInstalledApp(app_id, profile)) + return app_id; + return std::string(); } void NoteTakingHelper::SetPreferredApp(Profile* profile, @@ -404,7 +384,7 @@ return false; NoteTakingLockScreenSupport current_state = - GetLockScreenSupportForAppId(profile, app_id); + GetLockScreenSupportForApp(profile, app_id); if ((enabled && current_state != NoteTakingLockScreenSupport::kSupported) || (!enabled && current_state != NoteTakingLockScreenSupport::kEnabled)) { @@ -478,11 +458,10 @@ extension_registry_observations_.AddObservation(registry); if (apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) { - auto* cache = &apps::AppServiceProxyFactory::GetForProfile(profile) - ->AppRegistryCache(); - DCHECK(cache); - DCHECK(!app_registry_observations_.IsObservingSource(cache)); - app_registry_observations_.AddObservation(cache); + auto& cache = apps::AppServiceProxyFactory::GetForProfile(profile) + ->AppRegistryCache(); + DCHECK(!app_registry_observations_.IsObservingSource(&cache)); + app_registry_observations_.AddObservation(&cache); } // TODO(derat): Remove this once OnArcPlayStoreEnabledChanged() is always @@ -521,11 +500,11 @@ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kNoteTakingAppIds); if (!switch_value.empty()) { - allowed_app_ids_ = base::SplitString( + force_allowed_app_ids_ = base::SplitString( switch_value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); } - allowed_app_ids_.insert( - allowed_app_ids_.end(), kDefaultAllowedAppIds, + force_allowed_app_ids_.insert( + force_allowed_app_ids_.end(), kDefaultAllowedAppIds, kDefaultAllowedAppIds + std::size(kDefaultAllowedAppIds)); // Track profiles so we can observe their app registries. @@ -540,9 +519,9 @@ if (apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile( profile)) { - auto* cache = &apps::AppServiceProxyFactory::GetForProfile(profile) - ->AppRegistryCache(); - app_registry_observations_.AddObservation(cache); + auto& cache = apps::AppServiceProxyFactory::GetForProfile(profile) + ->AppRegistryCache(); + app_registry_observations_.AddObservation(&cache); } // Check if the profile has already enabled Google Play Store. @@ -590,10 +569,6 @@ } } -bool NoteTakingHelper::IsAllowedApp(const std::string& app_id) const { - return base::Contains(allowed_app_ids_, app_id); -} - std::vector<std::string> NoteTakingHelper::GetNoteTakingAppIds( Profile* profile) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -608,7 +583,7 @@ } std::vector<std::string> app_ids; - for (const auto& id : allowed_app_ids_) { + for (const auto& id : force_allowed_app_ids_) { // TODO(crbug.com/1225848): Replace with a check for Chrome Apps in the // block below after Chrome Apps are published to App Service. if (enabled_extensions.Contains(id)) { @@ -775,7 +750,7 @@ void NoteTakingHelper::OnExtensionLoaded( content::BrowserContext* browser_context, const extensions::Extension* extension) { - if (IsAllowedApp(extension->id()) || + if (base::Contains(force_allowed_app_ids_, extension->id()) || extensions::ActionHandlersInfo::HasActionHandler( extension, app_runtime::ACTION_TYPE_NEW_NOTE)) { for (Observer& observer : observers_) @@ -787,7 +762,7 @@ content::BrowserContext* browser_context, const extensions::Extension* extension, extensions::UnloadedExtensionReason reason) { - if (IsAllowedApp(extension->id()) || + if (base::Contains(force_allowed_app_ids_, extension->id()) || extensions::ActionHandlersInfo::HasActionHandler( extension, app_runtime::ACTION_TYPE_NEW_NOTE)) { for (Observer& observer : observers_) @@ -820,13 +795,16 @@ } // TODO(crbug.com/1006642): Move this to a lock-screen-specific place. -NoteTakingLockScreenSupport NoteTakingHelper::GetLockScreenSupportForAppId( +NoteTakingLockScreenSupport NoteTakingHelper::GetLockScreenSupportForApp( Profile* profile, const std::string& app_id) { if (profile != profile_with_enabled_lock_screen_apps_) return NoteTakingLockScreenSupport::kNotSupported; - if (!IsLockScreenEnabled(profile, app_id)) + if (app_id.empty()) + return NoteTakingLockScreenSupport::kNotSupported; + + if (!IsLockScreenCapable(profile, app_id)) return NoteTakingLockScreenSupport::kNotSupported; if (allowed_lock_screen_apps_state_ == AllowedAppListState::kUndetermined) @@ -848,19 +826,17 @@ if (allowed_lock_screen_apps_state_ == AllowedAppListState::kUndetermined) return; - std::unique_ptr<NoteTakingAppInfo> preferred_app = - GetPreferredLockScreenAppInfo(profile_with_enabled_lock_screen_apps_); + std::string app_id = + GetPreferredAppId(profile_with_enabled_lock_screen_apps_); NoteTakingLockScreenSupport lock_screen_value_before_update = - preferred_app ? preferred_app->lock_screen_support - : NoteTakingLockScreenSupport::kNotSupported; + GetLockScreenSupportForApp(profile_with_enabled_lock_screen_apps_, + app_id); UpdateAllowedLockScreenAppsList(); - preferred_app = - GetPreferredLockScreenAppInfo(profile_with_enabled_lock_screen_apps_); NoteTakingLockScreenSupport lock_screen_value_after_update = - preferred_app ? preferred_app->lock_screen_support - : NoteTakingLockScreenSupport::kNotSupported; + GetLockScreenSupportForApp(profile_with_enabled_lock_screen_apps_, + app_id); // Do not notify observers about preferred app change if its lock screen // support status has not actually changed.
diff --git a/chrome/browser/ash/note_taking_helper.h b/chrome/browser/ash/note_taking_helper.h index f1e1a01..542ecfeb 100644 --- a/chrome/browser/ash/note_taking_helper.h +++ b/chrome/browser/ash/note_taking_helper.h
@@ -181,9 +181,14 @@ // shown in UI. std::vector<NoteTakingAppInfo> GetAvailableApps(Profile* profile); - // Returns info for the preferred lock screen app, if it exists. - std::unique_ptr<NoteTakingAppInfo> GetPreferredLockScreenAppInfo( - Profile* profile); + // Returns the ID of the preferred note-taking app. Empty if uninstalled or + // not set. + std::string GetPreferredAppId(Profile* profile); + + // Returns the state of the app's support for running on the lock screen. + NoteTakingLockScreenSupport GetLockScreenSupportForApp( + Profile* profile, + const std::string& app_id); // Sets the preferred note-taking app. |app_id| is a value from a // NoteTakingAppInfo object. @@ -234,10 +239,6 @@ NoteTakingHelper(); ~NoteTakingHelper() override; - // Returns whether |app_id| has been explicitly allowed as a note-taking app - // by command-line or default. |app_id| is a Chrome app or web app ID. - bool IsAllowedApp(const std::string& app_id) const; - // Queries and returns the app IDs of note-taking Chrome/web apps that are // installed, enabled, and allowed for |profile|. std::vector<std::string> GetNoteTakingAppIds(Profile* profile) const; @@ -265,12 +266,6 @@ void OnAppRegistryCacheWillBeDestroyed( apps::AppRegistryCache* cache) override; - // Determines the state of the app's support for lock screen note taking using - // installation information from |profile|. - NoteTakingLockScreenSupport GetLockScreenSupportForAppId( - Profile* profile, - const std::string& app_id); - // Called when kNoteTakingAppsLockScreenAllowlist pref changes for // |profile_with_enabled_lock_screen_apps_|. void OnAllowedNoteTakingAppsChanged(); @@ -295,8 +290,9 @@ // IDs of allowed (but not necessarily installed) Chrome apps or web apps for // note-taking, in the order in which they're chosen if the user hasn't - // expressed a preference. - std::vector<std::string> allowed_app_ids_; + // expressed a preference. Explicitly set by command-line and a default + // hard-coded list. + std::vector<std::string> force_allowed_app_ids_; // Cached information about available Android note-taking apps. std::vector<NoteTakingAppInfo> android_apps_;
diff --git a/chrome/browser/ash/note_taking_helper_unittest.cc b/chrome/browser/ash/note_taking_helper_unittest.cc index 253dbe8..4c99fbce 100644 --- a/chrome/browser/ash/note_taking_helper_unittest.cc +++ b/chrome/browser/ash/note_taking_helper_unittest.cc
@@ -372,22 +372,6 @@ TestingProfile::TestingFactories()); } - testing::AssertionResult PreferredAppMatches(Profile* profile, - NoteTakingAppInfo app_info) { - std::unique_ptr<NoteTakingAppInfo> preferred_app = - helper()->GetPreferredLockScreenAppInfo(profile); - if (!preferred_app) - return ::testing::AssertionFailure() << "No preferred app"; - - std::string expected = GetAppString(app_info); - std::string actual = GetAppString(*preferred_app); - if (expected != actual) { - return ::testing::AssertionFailure() << "Expected: " << expected << " " - << "Actual: " << actual; - } - return ::testing::AssertionSuccess(); - } - std::string NoteAppInfoListToString( const std::vector<NoteTakingAppInfo>& apps) { std::vector<std::string> app_strings; @@ -496,7 +480,7 @@ false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}, {kProdKeepAppName, NoteTakingHelper::kProdKeepExtensionId, false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_TRUE(helper()->GetPreferredLockScreenAppInfo(profile())); + EXPECT_TRUE(helper()->GetPreferredAppId(profile()).empty()); // Now install a random web app to check that it's ignored. web_app::test::InstallDummyWebApp(profile(), "Web App", @@ -514,7 +498,7 @@ false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}, {kProdKeepAppName, NoteTakingHelper::kProdKeepExtensionId, false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_TRUE(helper()->GetPreferredLockScreenAppInfo(profile())); + EXPECT_TRUE(helper()->GetPreferredAppId(profile()).empty()); // Mark the prod version as preferred. helper()->SetPreferredApp(profile(), NoteTakingHelper::kProdKeepExtensionId); @@ -524,11 +508,11 @@ false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}, {kProdKeepAppName, NoteTakingHelper::kProdKeepExtensionId, true /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - - EXPECT_TRUE(PreferredAppMatches( - profile(), - {kProdKeepAppName, NoteTakingHelper::kProdKeepExtensionId, - true /*preferred*/, NoteTakingLockScreenSupport::kNotSupported})); + EXPECT_EQ(helper()->GetPreferredAppId(profile()), + NoteTakingHelper::kProdKeepExtensionId); + EXPECT_EQ(helper()->GetLockScreenSupportForApp( + profile(), NoteTakingHelper::kProdKeepExtensionId), + NoteTakingLockScreenSupport::kNotSupported); } TEST_F(NoteTakingHelperTest, ListChromeAppsWithLockScreenNotesSupported) { @@ -553,7 +537,7 @@ profile(), {{kProdKeepAppName, NoteTakingHelper::kProdKeepExtensionId, false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_TRUE(helper()->GetPreferredLockScreenAppInfo(profile())); + EXPECT_TRUE(helper()->GetPreferredAppId(profile()).empty()); // Install additional Keep app - one that supports lock screen note taking. // This app should be reported to support note taking (given that @@ -567,7 +551,7 @@ false /*preferred*/, NoteTakingLockScreenSupport::kEnabled}, {kProdKeepAppName, NoteTakingHelper::kProdKeepExtensionId, false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_TRUE(helper()->GetPreferredLockScreenAppInfo(profile())); + EXPECT_TRUE(helper()->GetPreferredAppId(profile()).empty()); } TEST_F(NoteTakingHelperTest, PreferredAppEnabledOnLockScreen) { @@ -586,7 +570,6 @@ profile(), {{kDevKeepAppName, NoteTakingHelper::kDevKeepExtensionId, false /*preferred*/, NoteTakingLockScreenSupport::kEnabled}})); - EXPECT_FALSE(helper()->GetPreferredLockScreenAppInfo(profile())); // When the lock screen note taking pref is set and the Keep app is set as the // preferred note taking app, the app should be reported as selected as lock @@ -598,9 +581,11 @@ profile(), {{kDevKeepAppName, NoteTakingHelper::kDevKeepExtensionId, true /*preferred*/, NoteTakingLockScreenSupport::kEnabled}})); - EXPECT_TRUE(PreferredAppMatches( - profile(), {kDevKeepAppName, NoteTakingHelper::kDevKeepExtensionId, - true /*preferred*/, NoteTakingLockScreenSupport::kEnabled})); + EXPECT_EQ(helper()->GetPreferredAppId(profile()), + NoteTakingHelper::kDevKeepExtensionId); + EXPECT_EQ(helper()->GetLockScreenSupportForApp( + profile(), NoteTakingHelper::kDevKeepExtensionId), + NoteTakingLockScreenSupport::kEnabled); helper()->SetPreferredAppEnabledOnLockScreen(profile(), false); @@ -608,10 +593,11 @@ profile(), {{kDevKeepAppName, NoteTakingHelper::kDevKeepExtensionId, true /*preferred*/, NoteTakingLockScreenSupport::kSupported}})); - EXPECT_TRUE(PreferredAppMatches( - profile(), - {kDevKeepAppName, NoteTakingHelper::kDevKeepExtensionId, - true /*preferred*/, NoteTakingLockScreenSupport::kSupported})); + EXPECT_EQ(helper()->GetPreferredAppId(profile()), + NoteTakingHelper::kDevKeepExtensionId); + EXPECT_EQ(helper()->GetLockScreenSupportForApp( + profile(), NoteTakingHelper::kDevKeepExtensionId), + NoteTakingLockScreenSupport::kSupported); } TEST_F(NoteTakingHelperTest, PreferredAppWithNoLockScreenPermission) { @@ -632,10 +618,11 @@ profile(), {{kDevKeepAppName, NoteTakingHelper::kDevKeepExtensionId, true /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_TRUE(PreferredAppMatches( - profile(), - {kDevKeepAppName, NoteTakingHelper::kDevKeepExtensionId, - true /*preferred*/, NoteTakingLockScreenSupport::kNotSupported})); + EXPECT_EQ(helper()->GetPreferredAppId(profile()), + NoteTakingHelper::kDevKeepExtensionId); + EXPECT_EQ(helper()->GetLockScreenSupportForApp( + profile(), NoteTakingHelper::kDevKeepExtensionId), + NoteTakingLockScreenSupport::kNotSupported); } TEST_F(NoteTakingHelperTest, @@ -685,9 +672,9 @@ false /*preferred*/, NoteTakingLockScreenSupport::kEnabled}, {kName, kNewNoteId, true /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_TRUE(PreferredAppMatches( - profile(), {kName, kNewNoteId, true /*preferred*/, - NoteTakingLockScreenSupport::kNotSupported})); + EXPECT_EQ(helper()->GetPreferredAppId(profile()), kNewNoteId); + EXPECT_EQ(helper()->GetLockScreenSupportForApp(profile(), kNewNoteId), + NoteTakingLockScreenSupport::kNotSupported); } // Verify the note helper detects apps with "new_note" "action_handler" manifest @@ -1029,7 +1016,10 @@ NoteTakingLockScreenSupport::kNotSupported}, {kName2, kPackage2, false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_FALSE(helper()->GetPreferredLockScreenAppInfo(profile())); + // Preferred app is not actually installed, so no app ID should be returned. + EXPECT_TRUE(helper()->GetPreferredAppId(profile()).empty()); + EXPECT_EQ(helper()->GetLockScreenSupportForApp(profile(), ""), + NoteTakingLockScreenSupport::kNotSupported); // Disable Play Store and check that the apps are no longer returned. profile()->GetPrefs()->SetBoolean(arc::prefs::kArcEnabled, false); @@ -1549,10 +1539,11 @@ true /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}, {kUnsupportedAppName, kUnsupportedAppId, false /*preferred*/, NoteTakingLockScreenSupport::kNotSupported}})); - EXPECT_TRUE(PreferredAppMatches( - second_profile, - {kProdKeepAppName, NoteTakingHelper::kProdKeepExtensionId, - true /*preferred*/, NoteTakingLockScreenSupport::kNotSupported})); + EXPECT_EQ(helper()->GetPreferredAppId(second_profile), + NoteTakingHelper::kProdKeepExtensionId); + EXPECT_EQ(helper()->GetLockScreenSupportForApp( + second_profile, NoteTakingHelper::kProdKeepExtensionId), + NoteTakingLockScreenSupport::kNotSupported); } TEST_F(NoteTakingHelperTest, NoteTakingControllerClient) {
diff --git a/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn b/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn index 8377bcc..88e45202 100644 --- a/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn +++ b/chrome/browser/ash/system_extensions/api/window_management/BUILD.gn
@@ -23,6 +23,7 @@ "//chrome/browser/profiles:profile", "//components/services/app_service/public/cpp:instance_update", "//components/services/app_service/public/mojom", + "//content/public/browser", "//third_party/blink/public/mojom:mojom_platform", "//ui/aura", "//ui/views",
diff --git a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc index 5d3737c0..b119dae 100644 --- a/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc +++ b/chrome/browser/ash/system_extensions/api/window_management/cros_window_browsertest.cc
@@ -625,6 +625,50 @@ RunTest(test_code); } +IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, + CrosWindowPendingCallsToGetAllWindowsShouldNotCrash) { + const char test_code[] = R"( +async function cros_test() { + let getWindowsPromise = chromeos.windowManagement.getWindows(); + for (let i = 0; i < 100; i++) + chromeos.windowManagement.getWindows(); + await getWindowsPromise; +} + )"; + + RunTest(test_code); +} + +IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, + CrosWindowPendingCallsToGetWindowShouldNotCrash) { + const char test_code[] = R"( +async function cros_test() { + let [window] = await chromeos.windowManagement.getWindows(); + let movePromise = window.moveTo(0, 0); + for (let i = 0; i < 100; i++) + window.moveTo(0, 0); + await movePromise; +} + )"; + + RunTest(test_code); +} + +IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, + CrosWindowPendingCallsToGetWidgetShouldNotCrash) { + const char test_code[] = R"( +async function cros_test() { + let [window] = await chromeos.windowManagement.getWindows(); + let fullscreenPromise = window.setFullscreen(true); + for (let i = 0; i < 100; i++) + window.setFullscreen(true); + await fullscreenPromise; +} + )"; + + RunTest(test_code); +} + // Tests that the CrosWindowManagement object is an EventTarget. IN_PROC_BROWSER_TEST_F(CrosWindowBrowserTest, CrosWindowManagementEventTarget) { const char test_code[] = R"(
diff --git a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc index d09ee31..194d52a 100644 --- a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc +++ b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.cc
@@ -15,6 +15,8 @@ #include "components/services/app_service/public/cpp/instance.h" #include "components/services/app_service/public/mojom/types.mojom-shared.h" #include "components/services/app_service/public/mojom/types.mojom.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/render_process_host.h" #include "third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/focus_client.h" @@ -26,14 +28,20 @@ namespace ash { -WindowManagementImpl::WindowManagementImpl( - content::BrowserContext* browser_context) - : browser_context_(browser_context) {} +WindowManagementImpl::WindowManagementImpl(int32_t render_process_host_id) + : render_process_host_id_(render_process_host_id) {} void WindowManagementImpl::GetAllWindows(GetAllWindowsCallback callback) { - apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile( - Profile::FromBrowserContext(browser_context_)); std::vector<blink::mojom::CrosWindowInfoPtr> windows; + + Profile* profile = GetProfile(); + if (!profile) { + std::move(callback).Run(std::move(windows)); + return; + } + + apps::AppServiceProxy* proxy = + apps::AppServiceProxyFactory::GetForProfile(profile); proxy->InstanceRegistry().ForEachInstance( [&windows](const apps::InstanceUpdate& update) { auto window = blink::mojom::CrosWindowInfo::New(); @@ -225,11 +233,26 @@ std::move(callback).Run(blink::mojom::CrosWindowManagementStatus::kSuccess); } +Profile* WindowManagementImpl::GetProfile() { + content::RenderProcessHost* render_process_host = + content::RenderProcessHost::FromID(render_process_host_id_); + if (!render_process_host) + return nullptr; + + return Profile::FromBrowserContext(render_process_host->GetBrowserContext()); +} + aura::Window* WindowManagementImpl::GetWindow( const base::UnguessableToken& id) { aura::Window* target = nullptr; - apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile( - Profile::FromBrowserContext(browser_context_)); + + Profile* profile = GetProfile(); + if (!profile) { + return nullptr; + } + + apps::AppServiceProxy* proxy = + apps::AppServiceProxyFactory::GetForProfile(profile); proxy->InstanceRegistry().ForOneInstance( id, [&target](const apps::InstanceUpdate& update) { target = update.Window()->GetToplevelWindow();
diff --git a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h index 4fe488e..822beed 100644 --- a/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h +++ b/chrome/browser/ash/system_extensions/api/window_management/window_management_impl.h
@@ -6,13 +6,10 @@ #define CHROME_BROWSER_ASH_SYSTEM_EXTENSIONS_API_WINDOW_MANAGEMENT_WINDOW_MANAGEMENT_IMPL_H_ #include "base/unguessable_token.h" +#include "chrome/browser/profiles/profile.h" #include "third_party/blink/public/mojom/chromeos/system_extensions/window_management/cros_window_management.mojom.h" #include "ui/aura/window.h" -namespace content { -class BrowserContext; -} - namespace views { class Widget; } // namespace views @@ -21,7 +18,7 @@ class WindowManagementImpl : public blink::mojom::CrosWindowManagement { public: - explicit WindowManagementImpl(content::BrowserContext* browser_context); + explicit WindowManagementImpl(int32_t render_process_host_id); ~WindowManagementImpl() override = default; void GetAllWindows(GetAllWindowsCallback callback) override; @@ -61,13 +58,16 @@ void Close(const base::UnguessableToken& id, CloseCallback callback) override; private: + // Returns profile attached to the render process host id. + Profile* GetProfile(); + // Returns ptr to top level window from window at given id. aura::Window* GetWindow(const base::UnguessableToken& id); // Returns ptr to top level widget from window at given id. views::Widget* GetWidget(const base::UnguessableToken& id); - content::BrowserContext* browser_context_; + int32_t render_process_host_id_; }; } // namespace ash
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc index 3851632..e06bfc4 100644 --- a/chrome/browser/background/background_mode_manager.cc +++ b/chrome/browser/background/background_mode_manager.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/lifetime/browser_shutdown.h" +#include "chrome/browser/lifetime/termination_notification.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h" #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h" @@ -68,7 +69,6 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/startup_metric_utils/browser/startup_metric_utils.h" -#include "content/public/browser/notification_service.h" #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" @@ -350,8 +350,9 @@ StartBackgroundMode(); // Listen for the application shutting down so we can release our KeepAlive. - registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, - content::NotificationService::AllSources()); + on_app_terminating_subscription_ = + browser_shutdown::AddAppTerminatingCallback(base::BindOnce( + &BackgroundModeManager::OnAppTerminating, base::Unretained(this))); BrowserList::AddObserver(this); } @@ -483,13 +484,7 @@ } /////////////////////////////////////////////////////////////////////////////// -// BackgroundModeManager, content::NotificationObserver overrides -void BackgroundModeManager::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); - +void BackgroundModeManager::OnAppTerminating() { // Make sure we aren't still keeping the app alive (only happens if we // don't receive an EXTENSIONS_READY notification for some reason). ReleaseStartupKeepAlive(); @@ -498,7 +493,6 @@ EndBackgroundMode(); // Shutting down, so don't listen for any more notifications so we don't // try to re-enter/exit background mode again. - registrar_.RemoveAll(); for (const auto& it : background_mode_data_) it.second->applications()->RemoveObserver(this); }
diff --git a/chrome/browser/background/background_mode_manager.h b/chrome/browser/background/background_mode_manager.h index 6589516..1bf2e9d 100644 --- a/chrome/browser/background/background_mode_manager.h +++ b/chrome/browser/background/background_mode_manager.h
@@ -27,8 +27,6 @@ #include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "extensions/common/extension_id.h" class BackgroundModeOptimizer; @@ -63,8 +61,7 @@ // Additionally, when in background mode, Chrome will launch on OS login with // no open windows to allow apps with the "background" permission to run in the // background. -class BackgroundModeManager : public content::NotificationObserver, - public BrowserListObserver, +class BackgroundModeManager : public BrowserListObserver, public BackgroundApplicationListModel::Observer, public ProfileAttributesStorage::Observer, public StatusIconMenuModel::Delegate { @@ -271,10 +268,7 @@ using BackgroundModeInfoMap = std::map<const Profile*, std::unique_ptr<BackgroundModeData>>; - // content::NotificationObserver implementation. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void OnAppTerminating(); // Called when ExtensionSystem is ready. void OnExtensionsReady(Profile* profile); @@ -421,7 +415,7 @@ raw_ptr<ProfileAttributesStorage> profile_storage_; // Registrars for managing our change observers. - content::NotificationRegistrar registrar_; + base::CallbackListSubscription on_app_terminating_subscription_; PrefChangeRegistrar pref_registrar_; // The profile-keyed data for this background mode manager. Keyed on profile.
diff --git a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc index d1a87d8..452fafe 100644 --- a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc +++ b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
@@ -372,8 +372,7 @@ // ChildProcessSecurityPolicy::CanAccessDataForOrigin(). mojo::MakeSelfOwnedReceiver( - std::make_unique<ash::WindowManagementImpl>( - render_process_host->GetBrowserContext()), + std::make_unique<ash::WindowManagementImpl>(info.process_id), std::move(receiver)); })); }
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc index 367c366..8cca5e4 100644 --- a/chrome/browser/extensions/api/debugger/debugger_api.cc +++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/lifetime/termination_notification.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" @@ -40,8 +41,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_agent_host.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/web_contents.h" @@ -251,7 +250,6 @@ LAZY_INSTANCE_INITIALIZER; class ExtensionDevToolsClientHost : public content::DevToolsAgentHostClient, - public content::NotificationObserver, public ExtensionRegistryObserver { public: ExtensionDevToolsClientHost(Profile* profile, @@ -297,10 +295,7 @@ void SendDetachedEvent(); - // content::NotificationObserver implementation. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void OnAppTerminating(); // ExtensionRegistryObserver implementation. void OnExtensionUnloaded(content::BrowserContext* browser_context, @@ -311,7 +306,7 @@ scoped_refptr<DevToolsAgentHost> agent_host_; scoped_refptr<const Extension> extension_; Debuggee debuggee_; - content::NotificationRegistrar registrar_; + base::CallbackListSubscription on_app_terminating_subscription_; int last_request_id_ = 0; PendingRequests pending_requests_; base::CallbackListSubscription subscription_; @@ -342,8 +337,10 @@ // RVH-based agents disconnect from their clients when the app is terminating // but shared worker-based agents do not. // Disconnect explicitly to make sure that |this| observer is not leaked. - registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, - content::NotificationService::AllSources()); + on_app_terminating_subscription_ = + browser_shutdown::AddAppTerminatingCallback( + base::BindOnce(&ExtensionDevToolsClientHost::OnAppTerminating, + base::Unretained(this))); } bool ExtensionDevToolsClientHost::Attach() { @@ -441,11 +438,7 @@ Close(); } -void ExtensionDevToolsClientHost::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); +void ExtensionDevToolsClientHost::OnAppTerminating() { Close(); }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index f391c47..71aeef07 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -29,6 +29,11 @@ [ { + "name": "3p-intents-in-incognito", + "owners": ["qpubert@google.com", "djean@google.com"], + "expiry_milestone": 110 + }, + { "name": "access-code-cast-device-duration", "owners": [ "gbj@google.com", "cros-edu-team@google.com" ], "expiry_milestone": 105 @@ -951,6 +956,11 @@ "expiry_milestone": 83 }, { + "name": "contextual-page-actions-with-price-tracking", + "owners": [ "shaktisahu@google.com", "salg@google.com" ], + "expiry_milestone": 109 + }, + { "name": "contextual-search-debug", "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS" ], // This is used to enable debugging of server and backend code.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 667c38c..b4a6e18 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1443,6 +1443,11 @@ const char kGpuRasterizationName[] = "GPU rasterization"; const char kGpuRasterizationDescription[] = "Use GPU to rasterize web content."; +const char kContextualPageActionsWithPriceTrackingName[] = + "Contextual page actions with price tracking"; +const char kContextualPageActionsWithPriceTrackingDescription[] = + "Enables price tracking as a contextual page action."; + const char kHandwritingGestureEditingName[] = "Handwriting Gestures Editing"; const char kHandwritingGestureEditingDescription[] = "Enables editing with handwriting gestures within the virtual keyboard.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index a542f480..481e92f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -801,6 +801,9 @@ extern const char kCastForceEnableRemotingQueryName[]; extern const char kCastForceEnableRemotingQueryDescription[]; +extern const char kContextualPageActionsWithPriceTrackingName[]; +extern const char kContextualPageActionsWithPriceTrackingDescription[]; + extern const char kGpuRasterizationName[]; extern const char kGpuRasterizationDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 3f7ff1b..d585cd9 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -56,6 +56,7 @@ #include "components/query_tiles/switches.h" #include "components/reading_list/features/reading_list_switches.h" #include "components/safe_browsing/core/common/features.h" +#include "components/segmentation_platform/public/features.h" #include "components/send_tab_to_self/features.h" #include "components/shared_highlighting/core/common/shared_highlighting_features.h" #include "components/signin/public/base/signin_switches.h" @@ -179,7 +180,6 @@ &kCriticalPersistedTabData, &kCCTBackgroundTab, &kCCTClientDataHeader, - &kCCTExternalLinkHandling, &kCCTIncognito, &kCCTIncognitoAvailableToThirdParty, &kCCTNewDownloadTab, @@ -366,6 +366,7 @@ &query_tiles::features::kQueryTilesInNTP, &query_tiles::features::kQueryTilesSegmentation, &reading_list::switches::kReadLater, + &segmentation_platform::features::kContextualPageActionsWithPriceTracking, &send_tab_to_self::kSendTabToSelfSigninPromo, &send_tab_to_self::kSendTabToSelfV2, &share::kPersistShareHubOnAppSwitch, @@ -485,9 +486,6 @@ const base::Feature kCCTNewDownloadTab{"CCTNewDownloadTab", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kCCTExternalLinkHandling{"CCTExternalLinkHandling", - base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kCCTIncognito{"CCTIncognito", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index fdfd2cc..bcaf643 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -35,7 +35,6 @@ extern const base::Feature kCastDeviceFilter; extern const base::Feature kCCTBackgroundTab; extern const base::Feature kCCTClientDataHeader; -extern const base::Feature kCCTExternalLinkHandling; extern const base::Feature kCCTIncognito; extern const base::Feature kCCTIncognitoAvailableToThirdParty; extern const base::Feature kCCTNewDownloadTab;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index f61dfa1..a81eb01 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -246,7 +246,6 @@ public static final String CCT_INCOGNITO = "CCTIncognito"; public static final String CCT_INCOGNITO_AVAILABLE_TO_THIRD_PARTY = "CCTIncognitoAvailableToThirdParty"; - public static final String CCT_EXTERNAL_LINK_HANDLING = "CCTExternalLinkHandling"; public static final String CCT_NEW_DOWNLOAD_TAB = "CCTNewDownloadTab"; public static final String CCT_POST_MESSAGE_API = "CCTPostMessageAPI"; public static final String CCT_REDIRECT_PRECONNECT = "CCTRedirectPreconnect"; @@ -285,6 +284,8 @@ public static final String CONTEXT_MENU_TRANSLATE_WITH_GOOGLE_LENS = "ContextMenuTranslateWithGoogleLens"; public static final String LENS_CAMERA_ASSISTED_SEARCH = "LensCameraAssistedSearch"; + public static final String CONTEXTUAL_PAGE_ACTIONS_PRICE_TRACKING = + "ContextualPageActionsPriceTracking"; /** Used only in native code. */ public static final String CONTEXTUAL_SEARCH_DEBUG = "ContextualSearchDebug"; public static final String CONTEXTUAL_SEARCH_DELAYED_INTELLIGENCE =
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java index 835213c..6550359 100644 --- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java
@@ -47,7 +47,8 @@ void showIncognitoReauthDialog(boolean showFullScreen) { mModalDialogManager.showDialog(mModalDialogModel, (showFullScreen) ? ModalDialogManager.ModalDialogType.APP - : ModalDialogManager.ModalDialogType.TAB); + : ModalDialogManager.ModalDialogType.TAB, + ModalDialogManager.ModalDialogPriority.VERY_HIGH); } void dismissIncognitoReauthDialog(@DialogDismissalCause int dismissalCause) {
diff --git a/chrome/browser/page_load_metrics/integration_tests/data/largest_contentful_paint.html b/chrome/browser/page_load_metrics/integration_tests/data/largest_contentful_paint.html index c4f54555..60291c0 100644 --- a/chrome/browser/page_load_metrics/integration_tests/data/largest_contentful_paint.html +++ b/chrome/browser/page_load_metrics/integration_tests/data/largest_contentful_paint.html
@@ -59,9 +59,7 @@ po.observe({type: 'largest-contentful-paint', buffered: true}); </script> -<div id="content_div_1"> - <img src="images/green-16x16.png"></img> -</div> +<div id="content_div_1"></div> <div id="content_div_2"></div> <script> @@ -74,6 +72,14 @@ }); }; + // Adds the first image "green-16x16.png" to "content_div_1". We expect this + // operation to trigger a new LCP entry. + const add_first_image = () => { + let img = document.createElement("img"); + content_div_1.appendChild(img); + img.src = "images/green-16x16.png"; + }; + // Adds another image that is larger than "green-16x16.png". We expect this // operation to trigger a new LCP entry. const add_larger_image = () => { @@ -111,43 +117,59 @@ }); }; - const run_test = async () => { - // This test exerciess the following scenario + const test_first_image = async () => { + // This test exercises the following scenario // - have an initial page load with an image // - assert that LCP fires for that image - // - add a larger image to the page - // - assert that LCP fires for the new image - // - remove the larger image - // - wait for some rAFs - // - add the largest image to the page - // - asset that the new LCP is for the largest - const lcp_0 = await block_for_next_lcp(); - add_larger_image(); - const lcp_1 = await block_for_next_lcp(); - remove_larger_image(); - await waitForAnimationFrames(3); - add_largest_image(); - const lcp_2 = await block_for_next_lcp(); + add_first_image(); + const lcp = await block_for_next_lcp(); // Now that we've run through the scenario and collected our measurements, // return them in a structure that the C++ side can easily query. let output = [ - // lcp_0 + // lcp { - url: lcp_0.url, - time: lcp_0.startTime - }, - // lcp_1 + url: lcp.url, + time: lcp.startTime + }]; + return output; + }; + const test_larger_image = async () => { + // This test exercises the following scenario + // - add a larger image to the page + // - assert that LCP fires for the new image + // - remove the larger image + // - wait for some rAFs + add_larger_image(); + const lcp = await block_for_next_lcp(); + remove_larger_image(); + await waitForAnimationFrames(3); + + // Now that we've run through the scenario and collected our measurements, + // return them in a structure that the C++ side can easily query. + let output = [ + // lcp { - url: lcp_1.url, - time: lcp_1.startTime - }, - // lcp_2 + url: lcp.url, + time: lcp.startTime + }]; + return output; + }; + const test_largest_image = async () => { + // This test exercises the following scenario + // - add the largest image to the page + // - assert that the new LCP is for the largest + add_largest_image(); + const lcp = await block_for_next_lcp(); + + // Now that we've run through the scenario and collected our measurements, + // return them in a structure that the C++ side can easily query. + let output = [ + // lcp { - url: lcp_2.url, - time: lcp_2.startTime - } - ]; + url: lcp.url, + time: lcp.startTime + }]; return output; }; </script>
diff --git a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc index 943a13f..6d88e345 100644 --- a/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc +++ b/chrome/browser/page_load_metrics/integration_tests/largest_contentful_paint_browsertest.cc
@@ -83,8 +83,9 @@ } // namespace -// TODO(crbug.com/1223602): Flaky on all platforms. -IN_PROC_BROWSER_TEST_F(MetricIntegrationTest, DISABLED_LargestContentfulPaint) { +IN_PROC_BROWSER_TEST_F(MetricIntegrationTest, LargestContentfulPaint) { + auto waiter = std::make_unique<page_load_metrics::PageLoadMetricsTestWaiter>( + web_contents()); Start(); StartTracing({"loading"}); Load("/largest_contentful_paint.html"); @@ -100,24 +101,33 @@ base::StrCat({window_origin, "/images/blue96x96.png"}); const std::string image_3_url_expected = base::StrCat({window_origin, "/images/green-256x256.png"}); - - content::EvalJsResult result = EvalJs(web_contents(), "run_test()"); - EXPECT_EQ("", result.error); + const std::string expected_url[3] = { + image_1_url_expected, image_2_url_expected, image_3_url_expected}; // Verify that the JS API yielded three LCP reports. Note that, as we resolve // https://github.com/WICG/largest-contentful-paint/issues/41, this test may // need to be updated to reflect new semantics. - const auto& list = result.value.GetListDeprecated(); - const std::string expected_url[3] = { - image_1_url_expected, image_2_url_expected, image_3_url_expected}; + const std::string test_name[3] = {"test_first_image()", "test_larger_image()", + "test_largest_image()"}; absl::optional<double> lcp_timestamps[3]; for (size_t i = 0; i < 3; i++) { - const std::string* url = list[i].FindStringPath("url"); + waiter->AddPageExpectation(page_load_metrics::PageLoadMetricsTestWaiter:: + TimingField::kLargestContentfulPaint); + + // std::string function_name = base::StringPrintf("run_test%zu()", i); + content::EvalJsResult result = EvalJs(web_contents(), test_name[i]); + EXPECT_EQ("", result.error); + const auto& list = result.value.GetListDeprecated(); + EXPECT_EQ(1u, list.size()); + const std::string* url = list[0].FindStringPath("url"); EXPECT_TRUE(url); EXPECT_EQ(*url, expected_url[i]); - lcp_timestamps[i] = list[i].FindDoublePath("time"); + lcp_timestamps[i] = list[0].FindDoublePath("time"); EXPECT_TRUE(lcp_timestamps[i].has_value()); + + waiter->Wait(); } + EXPECT_LT(lcp_timestamps[0], lcp_timestamps[1]) << "The first LCP report should be before the second"; EXPECT_LT(lcp_timestamps[1], lcp_timestamps[2])
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index ed76813..16e6c26b2 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -68,6 +68,7 @@ deps = [ ":jni_headers", "//components/autofill/core/browser:browser", + "//components/crash/core/common:crash_key_lib", "//components/password_manager/core/browser:browser", "//components/password_manager/core/browser:password_form", "//components/password_manager/core/common:features",
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.cc b/chrome/browser/password_manager/android/password_store_android_backend.cc index 26aa12c..dd4581a 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.cc +++ b/chrome/browser/password_manager/android/password_store_android_backend.cc
@@ -11,6 +11,7 @@ #include "base/barrier_callback.h" #include "base/callback.h" +#include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/location.h" #include "base/memory/weak_ptr.h" @@ -26,6 +27,7 @@ #include "chrome/browser/password_manager/android/password_sync_controller_delegate_android.h" #include "chrome/browser/password_manager/android/password_sync_controller_delegate_bridge_impl.h" #include "components/autofill/core/browser/autofill_regexes.h" +#include "components/crash/core/common/crash_key.h" #include "components/password_manager/core/browser/login_database.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_store_backend.h" @@ -46,6 +48,8 @@ // a new foreground session since it's likely that Chrome missed the response. constexpr base::TimeDelta kAsyncTaskTimeout = base::Seconds(30); +constexpr int kGmsDeveloperErrorCode = 10; + using autofill::MatchesPattern; using base::UTF8ToUTF16; using password_manager::GetExpressionForFederatedMatching; @@ -195,6 +199,26 @@ error_code); } +// TODO(crbug.com/1324588): Remove once the dumps are replaced by DCHECK. +void SendDumpWithInfo(absl::optional<std::string> signon_realm, + absl::optional<std::string> origin) { + static crash_reporter::CrashKeyString<1024> signon_realm_key( + "PwdMgr.BackendError.signon_realm"); + static crash_reporter::CrashKeyString<1024> origin_key( + "PwdMgr.BackendError.origin"); + + if (signon_realm.has_value()) { + signon_realm_key.Set(signon_realm->substr(1020)); + } + if (origin.has_value()) { + origin_key.Set(origin->substr(1020)); + } + + base::debug::DumpWithoutCrashing(); + signon_realm_key.Clear(); + origin_key.Clear(); +} + } // namespace class PasswordStoreAndroidBackend::ClearAllLocalPasswordsMetricRecorder { @@ -236,15 +260,19 @@ PasswordStoreAndroidBackend::JobReturnHandler::JobReturnHandler( LoginsOrErrorReply callback, - PasswordStoreBackendMetricsRecorder metrics_recorder) + PasswordStoreBackendMetricsRecorder metrics_recorder, + base::OnceClosure crash_dump_callback) : success_callback_(std::move(callback)), - metrics_recorder_(std::move(metrics_recorder)) {} + metrics_recorder_(std::move(metrics_recorder)), + crash_dump_callback_(std::move(crash_dump_callback)) {} PasswordStoreAndroidBackend::JobReturnHandler::JobReturnHandler( PasswordStoreChangeListReply callback, - PasswordStoreBackendMetricsRecorder metrics_recorder) + PasswordStoreBackendMetricsRecorder metrics_recorder, + base::OnceClosure crash_dump_callback) : success_callback_(std::move(callback)), - metrics_recorder_(std::move(metrics_recorder)) {} + metrics_recorder_(std::move(metrics_recorder)), + crash_dump_callback_(std::move(crash_dump_callback)) {} PasswordStoreAndroidBackend::JobReturnHandler::JobReturnHandler( JobReturnHandler&&) = default; @@ -261,6 +289,10 @@ std::move(error)); } +void PasswordStoreAndroidBackend::JobReturnHandler::SendCrashDump() { + std::move(crash_dump_callback_).Run(); +} + base::TimeDelta PasswordStoreAndroidBackend::JobReturnHandler::GetElapsedTimeSinceStart() const { @@ -329,7 +361,8 @@ JobId job_id = bridge_->GetAutofillableLogins( GetAccount(sync_delegate_->GetSyncingAccount())); QueueNewJob(job_id, std::move(callback), - MetricInfix("GetAutofillableLoginsAsync")); + MetricInfix("GetAutofillableLoginsAsync"), + /*signon_realm=*/absl::nullopt, /*origin=*/absl::nullopt); } void PasswordStoreAndroidBackend::GetAllLoginsForAccountAsync( @@ -376,7 +409,8 @@ PasswordStoreChangeListReply callback) { JobId job_id = bridge_->AddLogin(form, GetAccount(sync_delegate_->GetSyncingAccount())); - QueueNewJob(job_id, std::move(callback), MetricInfix("AddLoginAsync")); + QueueNewJob(job_id, std::move(callback), MetricInfix("AddLoginAsync"), + form.signon_realm, form.url.spec()); } void PasswordStoreAndroidBackend::UpdateLoginAsync( @@ -384,7 +418,8 @@ PasswordStoreChangeListReply callback) { JobId job_id = bridge_->UpdateLogin( form, GetAccount(sync_delegate_->GetSyncingAccount())); - QueueNewJob(job_id, std::move(callback), MetricInfix("UpdateLoginAsync")); + QueueNewJob(job_id, std::move(callback), MetricInfix("UpdateLoginAsync"), + form.signon_realm, form.url.spec()); } void PasswordStoreAndroidBackend::RemoveLoginAsync( @@ -599,9 +634,11 @@ if (!reply.has_value()) return; // Task cleaned up after returning from background. if (error.api_error_code.has_value() && sync_service_) { - // TODO(crbug.com/1324588): DCHECK_EQ(api_error_code, 10) to catch dev - // errors. - DCHECK_EQ(AndroidBackendErrorType::kExternalError, error.type); + // TODO(crbug.com/1324588): DCHECK_EQ(api_error_code, 10) instead of dumping + // to catch dev errors. + if (error.api_error_code == kGmsDeveloperErrorCode) { + reply->SendCrashDump(); + } RecordApiErrorInCombinationWithSyncStatus(error.api_error_code.value(), sync_service_->GetAuthError()); } @@ -620,15 +657,20 @@ } template <typename Callback> -void PasswordStoreAndroidBackend::QueueNewJob(JobId job_id, - Callback callback, - MetricInfix metric_infix) { +void PasswordStoreAndroidBackend::QueueNewJob( + JobId job_id, + Callback callback, + MetricInfix metric_infix, + absl::optional<std::string> signon_realm, + absl::optional<std::string> origin) { DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); request_for_job_.emplace( - job_id, - JobReturnHandler(std::move(callback), PasswordStoreBackendMetricsRecorder( - BackendInfix("AndroidBackend"), - std::move(metric_infix)))); + job_id, JobReturnHandler( + std::move(callback), + PasswordStoreBackendMetricsRecorder( + BackendInfix("AndroidBackend"), std::move(metric_infix)), + base::BindOnce(SendDumpWithInfo, std::move(signon_realm), + std::move(origin)))); } absl::optional<PasswordStoreAndroidBackend::JobReturnHandler> @@ -648,10 +690,13 @@ JobId job_id = bridge_->GetLoginsForSignonRealm( FormToSignonRealmQuery(form, include_psl), GetAccount(sync_delegate_->GetSyncingAccount())); + std::string signon_realm = form.signon_realm; + std::string origin = form.url.spec(); QueueNewJob(job_id, base::BindOnce(&ValidateSignonRealm, std::move(form), include_psl, std::move(callback)), - MetricInfix("GetLoginsAsync")); + MetricInfix("GetLoginsAsync"), std::move(signon_realm), + std::move(origin)); } void PasswordStoreAndroidBackend::FilterAndDisableAutoSignIn( @@ -739,7 +784,8 @@ PasswordStoreAndroidBackendBridge::Account account, LoginsOrErrorReply callback) { JobId job_id = bridge_->GetAllLogins(std::move(account)); - QueueNewJob(job_id, std::move(callback), MetricInfix("GetAllLoginsAsync")); + QueueNewJob(job_id, std::move(callback), MetricInfix("GetAllLoginsAsync"), + /*signon_realm=*/absl::nullopt, /*origin=*/absl::nullopt); } void PasswordStoreAndroidBackend::RemoveLoginForAccount( @@ -747,7 +793,8 @@ PasswordStoreAndroidBackendBridge::Account account, PasswordStoreChangeListReply callback) { JobId job_id = bridge_->RemoveLogin(form, std::move(account)); - QueueNewJob(job_id, std::move(callback), MetricInfix("RemoveLoginAsync")); + QueueNewJob(job_id, std::move(callback), MetricInfix("RemoveLoginAsync"), + /*signon_realm=*/absl::nullopt, /*origin=*/absl::nullopt); } void PasswordStoreAndroidBackend::OnForegroundSessionStart() {
diff --git a/chrome/browser/password_manager/android/password_store_android_backend.h b/chrome/browser/password_manager/android/password_store_android_backend.h index b23a03e..3012d8e 100644 --- a/chrome/browser/password_manager/android/password_store_android_backend.h +++ b/chrome/browser/password_manager/android/password_store_android_backend.h
@@ -64,9 +64,11 @@ JobReturnHandler(); JobReturnHandler(LoginsOrErrorReply callback, - PasswordStoreBackendMetricsRecorder metrics_recorder); + PasswordStoreBackendMetricsRecorder metrics_recorder, + base::OnceClosure crash_dump_callback); JobReturnHandler(PasswordStoreChangeListReply callback, - PasswordStoreBackendMetricsRecorder metrics_recorder); + PasswordStoreBackendMetricsRecorder metrics_recorder, + base::OnceClosure crash_dump_callback); JobReturnHandler(JobReturnHandler&&); JobReturnHandler& operator=(JobReturnHandler&&); ~JobReturnHandler(); @@ -83,11 +85,14 @@ void RecordMetrics(absl::optional<AndroidBackendError> error) const; base::TimeDelta GetElapsedTimeSinceStart() const; + // TODO(crbug.com/1324588): Remove after disabling crash dumps. + void SendCrashDump(); private: absl::variant<LoginsOrErrorReply, PasswordStoreChangeListReply> success_callback_; PasswordStoreBackendMetricsRecorder metrics_recorder_; + base::OnceClosure crash_dump_callback_; }; using JobId = PasswordStoreAndroidBackendBridge::JobId; @@ -148,8 +153,14 @@ void OnError(PasswordStoreAndroidBackendBridge::JobId job_id, AndroidBackendError error) override; + // TODO(crbug.com/1324588): Remove signon_realm and origin after disabling + // crash dumps. template <typename Callback> - void QueueNewJob(JobId job_id, Callback callback, MetricInfix metric_infix); + void QueueNewJob(JobId job_id, + Callback callback, + MetricInfix metric_infix, + absl::optional<std::string> signon_realm, + absl::optional<std::string> origin); absl::optional<JobReturnHandler> GetAndEraseJob(JobId job_id); // Gets logins matching |form|.
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.h b/chrome/browser/policy/chrome_browser_policy_connector.h index 1dddd3b..e4dc91ad 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.h +++ b/chrome/browser/policy/chrome_browser_policy_connector.h
@@ -119,6 +119,10 @@ // The device settings used in Lacros. crosapi::mojom::DeviceSettings* GetDeviceSettings() const; + DeviceSettingsLacros* device_settings_for_test() { + return device_settings_.get(); + } + PolicyLoaderLacros* device_account_policy_loader() { return device_account_policy_loader_; }
diff --git a/chrome/browser/policy/test/note_taking_on_lock_screen_policy_browsertest.cc b/chrome/browser/policy/test/note_taking_on_lock_screen_policy_browsertest.cc index 667c4447..ad096ec 100644 --- a/chrome/browser/policy/test/note_taking_on_lock_screen_policy_browsertest.cc +++ b/chrome/browser/policy/test/note_taking_on_lock_screen_policy_browsertest.cc
@@ -62,14 +62,10 @@ UpdateProviderPolicy(policies); } - ash::NoteTakingLockScreenSupport GetAppLockScreenStatus( + ash::NoteTakingLockScreenSupport GetLockScreenSupportForApp( const std::string& app_id) { - std::unique_ptr<ash::NoteTakingAppInfo> info = - ash::NoteTakingHelper::Get()->GetPreferredLockScreenAppInfo( - browser()->profile()); - if (!info || info->app_id != app_id) - return ash::NoteTakingLockScreenSupport::kNotSupported; - return info->lock_screen_support; + return ash::NoteTakingHelper::Get()->GetLockScreenSupportForApp( + browser()->profile(), app_id); } // The test app ID. @@ -88,15 +84,15 @@ SetUserLevelPrefValue(app->id(), true); EXPECT_EQ(ash::NoteTakingLockScreenSupport::kEnabled, - GetAppLockScreenStatus(app->id())); + GetLockScreenSupportForApp(app->id())); SetPolicyValue(base::Value(base::Value::Type::LIST)); EXPECT_EQ(ash::NoteTakingLockScreenSupport::kNotAllowedByPolicy, - GetAppLockScreenStatus(app->id())); + GetLockScreenSupportForApp(app->id())); SetPolicyValue(absl::nullopt); EXPECT_EQ(ash::NoteTakingLockScreenSupport::kEnabled, - GetAppLockScreenStatus(app->id())); + GetLockScreenSupportForApp(app->id())); } IN_PROC_BROWSER_TEST_F(NoteTakingOnLockScreenPolicyTest, @@ -108,18 +104,18 @@ SetUserLevelPrefValue(app->id(), false); EXPECT_EQ(ash::NoteTakingLockScreenSupport::kSupported, - GetAppLockScreenStatus(app->id())); + GetLockScreenSupportForApp(app->id())); base::Value policy(base::Value::Type::LIST); policy.Append(kTestAppId); SetPolicyValue(std::move(policy)); EXPECT_EQ(ash::NoteTakingLockScreenSupport::kSupported, - GetAppLockScreenStatus(app->id())); + GetLockScreenSupportForApp(app->id())); SetUserLevelPrefValue(app->id(), true); EXPECT_EQ(ash::NoteTakingLockScreenSupport::kEnabled, - GetAppLockScreenStatus(app->id())); + GetLockScreenSupportForApp(app->id())); } } // namespace policy
diff --git a/chrome/browser/resources/settings/privacy_page/cookies_page.html b/chrome/browser/resources/settings/privacy_page/cookies_page.html index 4d9c703..ec09ee20 100644 --- a/chrome/browser/resources/settings/privacy_page/cookies_page.html +++ b/chrome/browser/resources/settings/privacy_page/cookies_page.html
@@ -135,6 +135,9 @@ <settings-toggle-button id="clearOnExit" class="hr" pref="{{prefs.generated.cookie_session_only}}" label="$i18n{cookiePageClearOnExit}" +<if expr="not chromeos_ash and not chromeos_lacros"> + sub-label="$i18n{cookiePageClearOnExitDesc}" +</if> on-settings-boolean-control-change="onClearOnExitChange_"> </settings-toggle-button> <settings-do-not-track-toggle id="doNotTrack"
diff --git a/chrome/browser/ui/android/signin/java/res/layout/personalized_signin_promo_view_header.xml b/chrome/browser/ui/android/signin/java/res/layout/personalized_signin_promo_view_header.xml index d4ce776..acec776 100644 --- a/chrome/browser/ui/android/signin/java/res/layout/personalized_signin_promo_view_header.xml +++ b/chrome/browser/ui/android/signin/java/res/layout/personalized_signin_promo_view_header.xml
@@ -18,8 +18,7 @@ android:layout_marginBottom="12dp" android:importantForAccessibility="no" app:srcCompat="@drawable/sync_promo_illustration" - style="@style/SigninPromoIllustrationVisibility" - android:visibility="gone"/> + style="@style/SigninPromoIllustrationVisibility"/> <ImageView android:id="@+id/new_signin_promo_image"
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java index 73705be3..6cf2df7 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SignOutDialogCoordinator.java
@@ -111,13 +111,13 @@ } } - private static void updateVisibility(CheckBox checkBox, String managedDomain) { + private static int getCheckBoxVisibility(String managedDomain) { // TODO(crbug.com/1294761): extract logic for whether data wiping is allowed into // SigninManager. final boolean allowDeletingData = UserPrefs.get(Profile.getLastUsedRegularProfile()) .getBoolean(Pref.ALLOW_DELETING_BROWSER_HISTORY); final boolean showCheckBox = (managedDomain == null) && allowDeletingData; - checkBox.setVisibility(showCheckBox ? View.VISIBLE : View.GONE); + return showCheckBox ? View.VISIBLE : View.GONE; } @VisibleForTesting @@ -129,7 +129,7 @@ .getManagementDomain(); final View view = inflateView(context, managedDomain, actionType); mCheckBox = view.findViewById(R.id.remove_local_data); - updateVisibility(mCheckBox, managedDomain); + mCheckBox.setVisibility(getCheckBoxVisibility(managedDomain)); mGaiaServiceType = gaiaServiceType; mListener = listener;
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java index 6bf42a3..39c716c 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java
@@ -486,8 +486,8 @@ view.getImage().setImageResource(R.drawable.chrome_sync_logo); setImageSize(context, view, R.dimen.signin_promo_cold_state_image_size); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_ILLUSTRATION)) { - view.getIllustration().setVisibility(View.VISIBLE); + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_ILLUSTRATION)) { + view.getIllustration().setVisibility(View.GONE); } if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_TITLE)) { @@ -513,8 +513,8 @@ view.getImage().setImageDrawable(accountImage); setImageSize(context, view, R.dimen.signin_promo_account_image_size); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_ILLUSTRATION)) { - view.getIllustration().setVisibility(View.VISIBLE); + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_ILLUSTRATION)) { + view.getIllustration().setVisibility(View.GONE); } if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_ANDROID_PROMOS_WITH_TITLE)) {
diff --git a/chrome/browser/ui/startup/lacros_first_run_service.cc b/chrome/browser/ui/startup/lacros_first_run_service.cc index 4d5f5ae9..6ea597cd 100644 --- a/chrome/browser/ui/startup/lacros_first_run_service.cc +++ b/chrome/browser/ui/startup/lacros_first_run_service.cc
@@ -18,7 +18,9 @@ #include "base/notreached.h" #include "base/scoped_observation.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/lacros/device_settings_lacros.h" #include "chrome/browser/lacros/lacros_prefs.h" +#include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_window.h" @@ -150,7 +152,11 @@ if (!profile->GetPrefs()->GetBoolean(prefs::kEnableSyncConsent)) return true; - // TODO(crbug.com/1324569): Also support ephemeral users. + crosapi::mojom::DeviceSettings* device_settings = + g_browser_process->browser_policy_connector()->GetDeviceSettings(); + if (device_settings->device_ephemeral_users_enabled == + crosapi::mojom::DeviceSettings::OptionalBool::kTrue) + return true; return false; }
diff --git a/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc b/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc index b8b876c..ad3a0ce 100644 --- a/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc +++ b/chrome/browser/ui/startup/lacros_first_run_service_browsertest.cc
@@ -13,7 +13,9 @@ #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/lacros/device_settings_lacros.h" #include "chrome/browser/lacros/lacros_prefs.h" +#include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_test_util.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" @@ -21,6 +23,9 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/crosapi/mojom/crosapi.mojom.h" +#include "chromeos/crosapi/mojom/device_settings_service.mojom.h" +#include "chromeos/startup/browser_init_params.h" #include "components/account_manager_core/chromeos/account_manager.h" #include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/prefs/pref_service.h" @@ -173,3 +178,39 @@ "Profile.LacrosPrimaryProfileFirstRunOutcome", ProfileMetrics::ProfileSignedInFlowOutcome::kSkippedByPolicies, 1); } + +IN_PROC_BROWSER_TEST_F( + LacrosFirstRunServiceBrowserTest, + TryMarkFirstRunAlreadyFinished_DeviceEphemeralUsersEnabled) { + base::CommandLine::ForCurrentProcess()->RemoveSwitch(switches::kNoFirstRun); + Profile* profile = browser()->profile(); + signin::IdentityManager* identity_manager = + identity_test_env()->identity_manager(); + base::HistogramTester histogram_tester; + + // The `DeviceEphemeralUsersEnabled` is read through DeviceSettings provided + // on startup. + auto init_params = chromeos::BrowserInitParams::Get()->Clone(); + init_params->device_settings->device_ephemeral_users_enabled = + crosapi::mojom::DeviceSettings::OptionalBool::kTrue; + auto device_settings = init_params->device_settings.Clone(); + + chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params)); + // TODO(crbug.com/1330310): Ideally this should be done as part of + // `SetInitParamsForTests()`. + g_browser_process->browser_policy_connector() + ->device_settings_for_test() + ->UpdateDeviceSettings(std::move(device_settings)); + + base::RunLoop run_loop; + fre_service()->TryMarkFirstRunAlreadyFinished(run_loop.QuitClosure()); + run_loop.Run(); + + EXPECT_TRUE(g_browser_process->local_state()->GetBoolean( + lacros_prefs::kPrimaryProfileFirstRunFinished)); + EXPECT_FALSE(ShouldOpenPrimaryProfileFirstRun(profile)); + EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); + histogram_tester.ExpectUniqueSample( + "Profile.LacrosPrimaryProfileFirstRunOutcome", + ProfileMetrics::ProfileSignedInFlowOutcome::kSkippedByPolicies, 1); +}
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc index aaf0346..b19b106 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc
@@ -31,6 +31,7 @@ #include "third_party/blink/public/common/features.h" #include "ui/events/base_event_utils.h" #include "ui/events/test/event_generator.h" +#include "ui/gfx/animation/animation_test_api.h" #include "ui/gfx/favicon_size.h" #include "ui/views/widget/any_widget_observer.h" #include "ui/views/widget/widget_utils.h" @@ -400,6 +401,9 @@ // DialogBrowserTest: void ShowUi(const std::string& name) override { + animation_mode_reset_ = gfx::AnimationTestApi::SetRichAnimationRenderMode( + gfx::Animation::RichAnimationRenderMode::FORCE_DISABLED); + std::vector<apps::IntentPickerAppInfo> app_info; const auto add_entry = [&app_info](const std::string& str) { app_info.emplace_back( @@ -428,6 +432,9 @@ ->toolbar_button_provider() ->GetPageActionIconView(PageActionIconType::kIntentPicker); } + + std::unique_ptr<base::AutoReset<gfx::Animation::RichAnimationRenderMode>> + animation_mode_reset_; }; IN_PROC_BROWSER_TEST_F(IntentPickerDialogTest, InvokeUi_default) {
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc index 9f91f75..c7312d0d 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -24,6 +24,7 @@ #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/image/canvas_image_source.h" #include "ui/gfx/image/image_skia_operations.h" +#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/background.h" #include "ui/views/controls/button/md_text_button.h" #include "ui/views/controls/image_view.h" @@ -103,12 +104,20 @@ const std::u16string letter_; }; -void SendAccessibilityEvent(views::Widget* widget) { +void SendAccessibilityEvent(views::Widget* widget, + std::u16string announcement) { if (!widget) return; - widget->GetRootView()->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, - true); + views::View* root_view = widget->GetRootView(); +#if BUILDFLAG(IS_MAC) + if (!announcement.empty()) + root_view->GetViewAccessibility().OverrideName(announcement); + root_view->NotifyAccessibilityEvent(ax::mojom::Event::kAlert, true); +#else + if (!announcement.empty()) + root_view->GetViewAccessibility().AnnounceText(announcement); +#endif } } // namespace @@ -460,7 +469,7 @@ // awkward, so we only want to do so when screen reader is enabled. if (accessibility_state_utils::IsScreenReaderEnabled()) continue_button_->RequestFocus(); - SendAccessibilityEvent(GetWidget()); + SendAccessibilityEvent(GetWidget(), std::u16string()); } void AccountSelectionBubbleView::OnAccountSelected( @@ -473,7 +482,8 @@ const content::IdentityRequestAccount& account) { verify_sheet_shown_ = true; RemoveNonHeaderChildViews(); - title_label_->SetText(l10n_util::GetStringUTF16(IDS_VERIFY_SHEET_TITLE)); + std::u16string title = l10n_util::GetStringUTF16(IDS_VERIFY_SHEET_TITLE); + title_label_->SetText(title); views::ProgressBar* progress_bar = AddChildView(std::make_unique<views::ProgressBar>(kProgressBarHeight)); // Use an infinite animation: SetValue(-1). @@ -488,7 +498,7 @@ SizeToContents(); PreferredSizeChanged(); - SendAccessibilityEvent(GetWidget()); + SendAccessibilityEvent(GetWidget(), title); } void AccountSelectionBubbleView::RemoveNonHeaderChildViews() {
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index b204569..02b141b1 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -884,7 +884,8 @@ return &NewWebUI<media_router::AccessCodeCastUI>; } if (base::FeatureList::IsEnabled(features::kSupportTool) && - url.host_piece() == chrome::kChromeUISupportToolHost) + url.host_piece() == chrome::kChromeUISupportToolHost && + SupportToolUI::IsEnabled(profile)) return &NewWebUI<SupportToolUI>; #endif // !BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 9701bf8..3026998 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -2138,6 +2138,9 @@ {"cookiePageBlockAllBulTwo", IDS_SETTINGS_COOKIES_BLOCK_ALL_BULLET_TWO}, {"cookiePageBlockAllBulThree", IDS_SETTINGS_COOKIES_BLOCK_ALL_BULLET_THREE}, {"cookiePageClearOnExit", IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT}, +#if !BUILDFLAG(IS_CHROMEOS) + {"cookiePageClearOnExitDesc", IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT_DESC}, +#endif {"cookiePageAllSitesLink", IDS_SETTINGS_COOKIES_ALL_SITES_LINK}, {"cookiePageAllowExceptions", IDS_SETTINGS_COOKIES_ALLOW_EXCEPTIONS}, {"cookiePageBlockExceptions", IDS_SETTINGS_COOKIES_BLOCK_EXCEPTIONS},
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc index 11f02cc5..8d2ddc6 100644 --- a/chrome/browser/ui/webui/support_tool/support_tool_ui.cc +++ b/chrome/browser/ui/webui/support_tool/support_tool_ui.cc
@@ -716,3 +716,7 @@ } SupportToolUI::~SupportToolUI() = default; + +bool SupportToolUI::IsEnabled(Profile* profile) { + return webui::IsEnterpriseManaged() || !profile->IsGuestSession(); +}
diff --git a/chrome/browser/ui/webui/support_tool/support_tool_ui.h b/chrome/browser/ui/webui/support_tool/support_tool_ui.h index df7ce474..bd21fa2c 100644 --- a/chrome/browser/ui/webui/support_tool/support_tool_ui.h +++ b/chrome/browser/ui/webui/support_tool/support_tool_ui.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SUPPORT_TOOL_SUPPORT_TOOL_UI_H_ #define CHROME_BROWSER_UI_WEBUI_SUPPORT_TOOL_SUPPORT_TOOL_UI_H_ +#include "chrome/browser/profiles/profile.h" #include "content/public/browser/web_ui_controller.h" // The C++ back-end for the chrome://support-tool webui page. @@ -16,6 +17,11 @@ SupportToolUI& operator=(const SupportToolUI&) = delete; ~SupportToolUI() override; + + // Returns if Support Tool should be enabled. Support Tool is only + // enabled in managed devices and logged-in sessions on consumer devices. It + // won't be available in guest sessions of consumer-owned devices. + static bool IsEnabled(Profile* profile); }; #endif // CHROME_BROWSER_UI_WEBUI_SUPPORT_TOOL_SUPPORT_TOOL_UI_H_
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index f785c06..3eeb423 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1653911525-bc6c69dfadd05727f8ff3f0b2a8a30a216286070.profdata +chrome-linux-main-1653933461-50eea8bf3349d44db7de6f5093a1d30b33455cd8.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 9da2c82..95b9b3c6 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1653911525-d54dc8c3a4f079ff8e9ffdf8620f6b6cb9b4e444.profdata +chrome-mac-main-1653933461-a95b214f374d3a69a0b4754936918c08fd08168d.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 73b2b14..b59b8b8d 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1653901050-ea64c0f1f97a6110406d1df594f687a0365d7ed8.profdata +chrome-win32-main-1653922768-611624f3d4743460a4ade7a89684f2731a459975.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 1f633e51..a9137148 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1653901050-13b3905958cb87d734e06845c5d6ce3b69a51661.profdata +chrome-win64-main-1653933461-4453083d56c04cc5d1b1700ba5cdc2c627fc229a.profdata
diff --git a/chrome/test/enterprise/e2e/policy/translate_enabled/translate_enabled.py b/chrome/test/enterprise/e2e/policy/translate_enabled/translate_enabled.py index d379a1e..6f4e8755d4e 100644 --- a/chrome/test/enterprise/e2e/policy/translate_enabled/translate_enabled.py +++ b/chrome/test/enterprise/e2e/policy/translate_enabled/translate_enabled.py
@@ -3,7 +3,10 @@ # found in the LICENSE file. import os -from chrome_ent_test.infra.core import environment, before_all, test +from chrome_ent_test.infra.core import before_all +from chrome_ent_test.infra.core import category +from chrome_ent_test.infra.core import environment +from chrome_ent_test.infra.core import test from infra import ChromeEnterpriseTestCase
diff --git a/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy_ash.cc b/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy_ash.cc index b0cb945..6ca216c 100644 --- a/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy_ash.cc +++ b/chromeos/components/cdm_factory_daemon/cdm_factory_daemon_proxy_ash.cc
@@ -59,7 +59,7 @@ ash::Shell::Get() ->display_configurator() ->content_protection_manager() - ->set_hdcp_key_request(base::BindRepeating( + ->SetProvisionedKeyRequest(base::BindRepeating( &CdmFactoryDaemonProxyAsh::GetHdcp14Key, base::Unretained(this))); }
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 000da32..82bb483 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -481,6 +481,7 @@ "//skia", "//third_party/abseil-cpp:absl", "//third_party/libaddressinput", + "//third_party/libaddressinput:strings_grit", "//ui/base", "//ui/gfx/geometry", "//ui/gfx/range",
diff --git a/components/autofill/core/browser/autofill_address_util.cc b/components/autofill/core/browser/autofill_address_util.cc index 1f38e26..3000d73 100644 --- a/components/autofill/core/browser/autofill_address_util.cc +++ b/components/autofill/core/browser/autofill_address_util.cc
@@ -35,6 +35,39 @@ namespace { +// Extend `components` using Autofill's address format extensions. These are +// used to add support for fields that are not strictly required for a valid +// address, and thus not provided by libaddressinput, but still commonly appear +// in forms. +void ExtendAddressComponents(std::vector<AddressUiComponent>& components, + const std::string& country_code, + const Localization& localization) { + AutofillCountry country(country_code); + for (const AutofillCountry::AddressFormatExtension& rule : + country.address_format_extensions()) { + // Find the location of `rule.placed_after` in `components`. + // `components.field` is only valid if `components.literal.empty()`. + auto prev_component = base::ranges::find_if( + components, [&rule](const AddressUiComponent& component) { + return component.literal.empty() && + component.field == rule.placed_after; + }); + DCHECK(prev_component != components.end()); + + // Insert the separator and `rule.type` afterwards. + components.insert( + ++prev_component, + {AddressUiComponent{.literal = + std::string(rule.separator_before_label)}, + AddressUiComponent{ + .field = rule.type, + .name = localization.GetString(rule.label_id), + .length_hint = rule.large_sized + ? AddressUiComponent::HINT_LONG + : AddressUiComponent::HINT_SHORT}}); + } +} + // Returns a vector of AddressUiComponent for `country_code` when using // `ui_language_code`. If no components are available for `country_code`, it // defaults back to the US. If `ui_language_code` is not valid, the default @@ -52,8 +85,10 @@ std::vector<AddressUiComponent> components = ::i18n::addressinput::BuildComponentsWithLiterals( country, localization, ui_language_code, components_language_code); - if (!components.empty()) + if (!components.empty()) { + ExtendAddressComponents(components, country, localization); return components; + } } NOTREACHED(); return {};
diff --git a/components/autofill/core/browser/autofill_address_util_unittest.cc b/components/autofill/core/browser/autofill_address_util_unittest.cc index 96d451d..047b9e45 100644 --- a/components/autofill/core/browser/autofill_address_util_unittest.cc +++ b/components/autofill/core/browser/autofill_address_util_unittest.cc
@@ -6,7 +6,9 @@ #include "base/guid.h" #include "base/memory/raw_ptr.h" +#include "base/test/scoped_feature_list.h" #include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/common/autofill_features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/resource/resource_bundle.h" @@ -50,6 +52,33 @@ base::ranges::any_of(lines, [](auto line) { return line.empty(); })); } +// Tests that address field extensions are applied to `GetAddressComponents()`, +// by checking that Great Britain's address format is extended by a state field. +TEST_F(AddressFormattingTest, GetAddressComponentsWithExtensions) { + base::test::ScopedFeatureList address_extension_feature; + address_extension_feature.InitAndEnableFeature( + features::kAutofillEnableExtendedAddressFormats); + + std::vector<std::vector<::i18n::addressinput::AddressUiComponent>> lines; + std::string components_language_code; + autofill::GetAddressComponents("GB", GetLocale(), /*include_literals=*/false, + &lines, &components_language_code); + + // Expect to find a line consisting solely of a state field. + // Because `include_literals=false`, accessing `.field` is valid. + auto state_line = base::ranges::find_if(lines, [](const auto& line) { + return line.size() == 1 && + line[0].field == ::i18n::addressinput::AddressField::ADMIN_AREA; + }); + ASSERT_NE(state_line, lines.end()); + EXPECT_EQ((*state_line)[0].length_hint, + ::i18n::addressinput::AddressUiComponent::HINT_LONG); + // The prior component on the previous line should be the postal code. + ASSERT_NE(state_line, lines.begin()); + EXPECT_EQ((--state_line)->back().field, + ::i18n::addressinput::AddressField::POSTAL_CODE); +} + TEST_F(AddressFormattingTest, GetEnvelopeStyleAddressSanity) { AutofillProfile profile = test::GetFullProfile(); std::u16string address = @@ -142,6 +171,30 @@ EXPECT_EQ(address.find(u" "), std::string::npos); } +// Tests that address field extensions are applied to +// `GetEnvelopeStyleAddress()`, by checking that Great Britain's address format +// is extended by a state field. +TEST_F(AddressFormattingTest, GetEnvelopeStyleAddressWithExtensions) { + base::test::ScopedFeatureList address_extension_feature; + address_extension_feature.InitAndEnableFeature( + features::kAutofillEnableExtendedAddressFormats); + + AutofillProfile profile(base::GenerateGUID(), /*origin=*/""); + test::SetProfileInfo(&profile, "FirstName", "MiddleName", "LastName", + "johndoe@hades.com", /*company=*/"", "666 Erebus St.", + "Apt 8", "Elysium", /*state=*/"Greater London", + "WC2H 8AG", "GB", "+44 20 7031 3000"); + + std::u16string address = + GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/true, + /*include_country=*/true); + // Expect the zip code, followed by a new line and the state. + EXPECT_NE( + address.find(profile.GetInfo(ADDRESS_HOME_ZIP, GetLocale()) + u"\n" + + profile.GetInfo(ADDRESS_HOME_STATE, GetLocale())), + std::string::npos); +} + TEST_F(AddressFormattingTest, GetEnvelopeStyleAddressHasNoDifferencesBetweenIdenticalProfiles) { AutofillProfile profile = test::GetFullProfile();
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc index 87a2197..a6a61be5 100644 --- a/components/autofill/core/browser/data_model/autofill_profile.cc +++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -49,7 +49,6 @@ #include "third_party/libaddressinput/chromium/addressinput_util.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_data.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_formatter.h" -#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h" #include "ui/base/l10n/l10n_util.h" using base::ASCIIToUTF16; @@ -857,13 +856,13 @@ AutofillProfile trimmed_profile(guid(), origin()); trimmed_profile.SetInfo(region_code_type, profile_region_code, app_locale); trimmed_profile.set_language_code(language_code()); + AutofillCountry country(address_region_code); std::vector<ServerFieldType> remaining_fields; for (size_t i = 0; i < included_fields_size && num_fields_to_use > 0; ++i) { ::i18n::addressinput::AddressField address_field; if (!i18n::FieldForType(included_fields[i], &address_field) || - !::i18n::addressinput::IsFieldUsed(address_field, - address_region_code) || + !country.IsAddressFieldSettingAccessible(address_field) || address_field == ::i18n::addressinput::COUNTRY) { remaining_fields.push_back(included_fields[i]); continue; @@ -1190,6 +1189,7 @@ ServerFieldTypeSet AutofillProfile::FindInaccessibleProfileValues( const std::string& country_code) const { ServerFieldTypeSet inaccessible_fields; + AutofillCountry country(country_code); // Consider only AddressFields which are invisible in the settings for some // countries. for (const AddressField& field_type : @@ -1197,8 +1197,8 @@ AddressField::DEPENDENT_LOCALITY, AddressField::POSTAL_CODE, AddressField::SORTING_CODE}) { ServerFieldType server_field_type = i18n::TypeForField(field_type); - if (!GetRawInfo(server_field_type).empty() && - !::i18n::addressinput::IsFieldUsed(field_type, country_code)) { + if (HasRawInfo(server_field_type) && + !country.IsAddressFieldSettingAccessible(field_type)) { inaccessible_fields.insert(server_field_type); } }
diff --git a/components/autofill/core/browser/geo/autofill_country.cc b/components/autofill/core/browser/geo/autofill_country.cc index 4a95ddd..5f0cdae2 100644 --- a/components/autofill/core/browser/geo/autofill_country.cc +++ b/components/autofill/core/browser/geo/autofill_country.cc
@@ -5,16 +5,23 @@ #include "components/autofill/core/browser/geo/autofill_country.h" #include <stddef.h> +#include <array> #include "base/containers/contains.h" +#include "base/containers/fixed_flat_map.h" #include "base/strings/string_util.h" #include "components/autofill/core/browser/geo/country_data.h" #include "components/autofill/core/browser/geo/country_names.h" +#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_internals/log_message.h" #include "components/autofill/core/common/logging/log_buffer.h" #include "third_party/icu/source/common/unicode/locid.h" +#include "third_party/libaddressinput/messages.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h" #include "ui/base/l10n/l10n_util.h" +using ::i18n::addressinput::AddressField; + namespace autofill { namespace { @@ -88,4 +95,50 @@ buffer << CTag{}; return buffer; } + +base::span<const AutofillCountry::AddressFormatExtension> +AutofillCountry::address_format_extensions() const { + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableExtendedAddressFormats)) { + return {}; + } + + // TODO(crbug.com/1300548): Extend more countries. FR and GB are used to test + // the feature, because libaddressinput already provides string literals. + static constexpr std::array<AddressFormatExtension, 1> fr_extensions{ + {{.type = AddressField::ADMIN_AREA, + .label_id = IDS_LIBADDRESSINPUT_PROVINCE, + .placed_after = AddressField::LOCALITY, + .separator_before_label = "\n", + .large_sized = true}}}; + static constexpr std::array<AddressFormatExtension, 1> gb_extensions{ + {{.type = AddressField::ADMIN_AREA, + .label_id = IDS_LIBADDRESSINPUT_COUNTY, + .placed_after = AddressField::POSTAL_CODE, + .separator_before_label = "\n", + .large_sized = true}}}; + + static constexpr auto extensions = + base::MakeFixedFlatMap<base::StringPiece, + base::span<const AddressFormatExtension>>({ + {"FR", fr_extensions}, + {"GB", gb_extensions}, + }); + + auto* it = extensions.find(country_code_); + if (it != extensions.end()) + return it->second; + return {}; +} + +bool AutofillCountry::IsAddressFieldSettingAccessible( + AddressField address_field) const { + // Check if `address_field` is part of libaddressinputs native address format + // or part of the Autofill's address extensions. + return ::i18n::addressinput::IsFieldUsed(address_field, country_code_) || + base::Contains( + address_format_extensions(), address_field, + [](const AddressFormatExtension& rule) { return rule.type; }); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/geo/autofill_country.h b/components/autofill/core/browser/geo/autofill_country.h index 3ac5a3c..3a46edff 100644 --- a/components/autofill/core/browser/geo/autofill_country.h +++ b/components/autofill/core/browser/geo/autofill_country.h
@@ -7,7 +7,10 @@ #include <string> +#include "base/containers/span.h" +#include "base/strings/string_piece.h" #include "components/autofill/core/browser/geo/country_data.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_field.h" namespace autofill { @@ -18,14 +21,44 @@ class AutofillCountry { public: // Returns country data corresponding to the two-letter ISO code - // |country_code|. - AutofillCountry(const std::string& country_code, const std::string& locale); + // `country_code`. + // `locale` is used translate the `name()` appropriately and can be ignored + // if the name is not queried. + explicit AutofillCountry(const std::string& country_code, + const std::string& locale = "en"); AutofillCountry(const AutofillCountry&) = delete; AutofillCountry& operator=(const AutofillCountry&) = delete; ~AutofillCountry(); + // Autofill relies on libaddressinput for its address format. + // AddressFormatExtensions are used to extend this format on a country-by- + // country basis. This is needed because while some field types are not + // strictly required for a valid address, we nonetheless see them in practise + // and want to offer filling support. + // This struct defines that a certain `type` is considered part of the address + // format in Autofill, specifies its `label` and placment after the existing + // type `placed_after` in the settings-UI. + // `large_sized` indicates if the field stretches the entire line (true) or + // half the line (false). + struct AddressFormatExtension { + ::i18n::addressinput::AddressField type; + int label_id; + ::i18n::addressinput::AddressField placed_after; + // Usually " " or "\n". Should not be empty. + base::StringPiece separator_before_label; + bool large_sized; + }; + + // Gets all the `AddressFormatExtension`s available for `country_code()`. + base::span<const AddressFormatExtension> address_format_extensions() const; + + // Returns true if the given `address_field` is part of Autofill's address + // format for `country_code()`. + bool IsAddressFieldSettingAccessible( + ::i18n::addressinput::AddressField address_field) const; + // Returns the likely country code for |locale|, or "US" as a fallback if no // mapping from the locale is available. static const std::string CountryCodeForLocale(const std::string& locale);
diff --git a/components/autofill/core/browser/geo/autofill_country_unittest.cc b/components/autofill/core/browser/geo/autofill_country_unittest.cc index 93c068f..b9ce700 100644 --- a/components/autofill/core/browser/geo/autofill_country_unittest.cc +++ b/components/autofill/core/browser/geo/autofill_country_unittest.cc
@@ -7,9 +7,12 @@ #include "base/containers/contains.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "components/autofill/core/browser/geo/autofill_country.h" #include "components/autofill/core/browser/geo/country_data.h" +#include "components/autofill/core/common/autofill_features.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_metadata.h" #if defined(ANDROID) #include "base/android/build_info.h" #endif @@ -153,10 +156,37 @@ country_data_map->GetCountryCodeForAlias("does_not_exist"); EXPECT_EQ(expected_country_code, actual_country_code); - // GB should map the UK. + // UK should map the GB. expected_country_code = "GB"; actual_country_code = country_data_map->GetCountryCodeForAlias("UK"); EXPECT_EQ(expected_country_code, actual_country_code); } +// Verifies that all address format extensions correspond to types that are +// not part of libaddressinputs expected types, but that they are placed +// after a field that is present in libaddressinput. +TEST(AutofillCountryTest, VerifyAddressFormatExtensions) { + base::test::ScopedFeatureList address_extension_feature; + address_extension_feature.InitAndEnableFeature( + features::kAutofillEnableExtendedAddressFormats); + + CountryDataMap* country_data_map = CountryDataMap::GetInstance(); + for (const std::string& country_code : country_data_map->country_codes()) { + AutofillCountry country(country_code); + for (const AutofillCountry::AddressFormatExtension& rule : + country.address_format_extensions()) { + // The separator should not be empty. + EXPECT_FALSE(rule.separator_before_label.empty()); + // `rule.type` is not part of `country_code`'s address format, but + // `rule.placed_after` is. + EXPECT_FALSE(::i18n::addressinput::IsFieldUsed(rule.type, country_code)); + EXPECT_TRUE( + ::i18n::addressinput::IsFieldUsed(rule.placed_after, country_code)); + // `IsAddressFieldSettingAccessible` considers `rule.type` + // setting-accessible. + EXPECT_TRUE(country.IsAddressFieldSettingAccessible(rule.type)); + } + } +} + } // namespace autofill
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 963b566..2d72a55f 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -210,6 +210,12 @@ "AutofillEnableDependentLocalityParsing", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables the augmentation layer for setting-inaccessible fields, which allows +// extending Autofill's address format by additional fields. +// TODO(crbug.com/1300548) Remove when launched. +const base::Feature kAutofillEnableExtendedAddressFormats{ + "AutofillEnableExtendedAddressFormats", base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls whether to save the first number in a form with multiple phone // numbers instead of aborting the import. // TODO(crbug.com/1167484) Remove once launched @@ -318,7 +324,7 @@ // TODO(crbug.com/1293341): Remove once launched. const base::Feature kAutofillFixServerQueriesIfPasswordManagerIsEnabled{ "AutofillFixServerQueriesIfPasswordManagerIsEnabled", - base::FEATURE_ENABLED_BY_DEFAULT}; + base::FEATURE_DISABLED_BY_DEFAULT}; // When enabled, the Autofill popup ignores second clicks for a certain period // (kAutofillIgnoreEarlyClicksOnPopupDuration) after the Autofill popup was
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 3376929d..da43e63 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -76,6 +76,8 @@ COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillEnableDependentLocalityParsing; COMPONENT_EXPORT(AUTOFILL) +extern const base::Feature kAutofillEnableExtendedAddressFormats; +COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillEnableImportWhenMultiplePhoneNumbers; COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillEnableMultiStepImports;
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json index 6d27ffd..646b625 100644 --- a/components/certificate_transparency/data/log_list.json +++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@ { - "version": "9.27", - "log_list_timestamp": "2022-05-29T12:54:51Z", + "version": "9.28", + "log_list_timestamp": "2022-05-30T12:54:20Z", "operators": [ { "name": "Google",
diff --git a/components/content_settings/core/common/content_settings_pattern_parser.cc b/components/content_settings/core/common/content_settings_pattern_parser.cc index f3a30dd..d033ac8 100644 --- a/components/content_settings/core/common/content_settings_pattern_parser.cc +++ b/components/content_settings/core/common/content_settings_pattern_parser.cc
@@ -180,7 +180,7 @@ } else { if (!ContentSettingsPattern::IsNonWildcardDomainNonPortScheme( scheme_piece) && - scheme_piece != url::kFileScheme) + !base::LowerCaseEqualsASCII(scheme_piece, url::kFileScheme)) builder->WithPortWildcard(); }
diff --git a/components/content_settings/core/common/content_settings_pattern_parser_fuzzer.cc b/components/content_settings/core/common/content_settings_pattern_parser_fuzzer.cc index cfefa00..52733619 100644 --- a/components/content_settings/core/common/content_settings_pattern_parser_fuzzer.cc +++ b/components/content_settings/core/common/content_settings_pattern_parser_fuzzer.cc
@@ -43,7 +43,10 @@ CHECK_EQ(recanonicalized_pattern.ToString(), canonical_pattern_spec) << "\n (originally '" << pattern_spec << "')"; CHECK_EQ(recanonicalized_pattern.Compare(canonical_pattern), - ContentSettingsPattern::Relation::IDENTITY); + ContentSettingsPattern::Relation::IDENTITY) + << "Canonical pattern\n" + << canonical_pattern.ToString() << "\nand recanonicalized pattern\n" + << recanonicalized_pattern.ToString() << "\nwere not identical"; return 0; }
diff --git a/components/content_settings/core/common/content_settings_pattern_parser_unittest.cc b/components/content_settings/core/common/content_settings_pattern_parser_unittest.cc index 0d506e350..747bc52 100644 --- a/components/content_settings/core/common/content_settings_pattern_parser_unittest.cc +++ b/components/content_settings/core/common/content_settings_pattern_parser_unittest.cc
@@ -370,6 +370,7 @@ "file://:/path", "file://:/:", // crbug.com/1196591 "file:///C:/Users/a.txt", + "filE:///foo/", // crbug.com/1323130 }; for (const std::string& spec : pattern_specs) { @@ -387,5 +388,7 @@ std::string canonical2 = pattern2.ToString(); EXPECT_EQ(canonical, canonical2); + EXPECT_EQ(pattern.Compare(pattern2), + ContentSettingsPattern::Relation::IDENTITY); } }
diff --git a/components/device_signals/core/browser/BUILD.gn b/components/device_signals/core/browser/BUILD.gn index 0423b68..1646818e 100644 --- a/components/device_signals/core/browser/BUILD.gn +++ b/components/device_signals/core/browser/BUILD.gn
@@ -7,12 +7,14 @@ "signals_aggregator.h", "signals_aggregator_impl.h", "signals_collector.h", + "user_context.h", "user_permission_service.h", "user_permission_service_impl.h", ] sources = [ "signals_aggregator_impl.cc", + "user_context.cc", "user_permission_service_impl.cc", ]
diff --git a/components/device_signals/core/browser/signals_aggregator.h b/components/device_signals/core/browser/signals_aggregator.h index e633282..6ff18d6e 100644 --- a/components/device_signals/core/browser/signals_aggregator.h +++ b/components/device_signals/core/browser/signals_aggregator.h
@@ -11,9 +11,11 @@ namespace device_signals { +struct UserContext; + class SignalsAggregator : public KeyedService { public: - using GetSignalsCallback = base::OnceCallback<void(base::Value::Dict)>; + using GetSignalsCallback = base::OnceCallback<void(base::Value)>; ~SignalsAggregator() override = default; @@ -21,10 +23,14 @@ // dictionary, where keys represent the names of the signals to be collected // and values represent their collection parameters. Invokes `callback` with // the collected signals stored in a dictionary, where the keys are the - // signal names and values are the collected values. + // signal names and values are the collected values. If signal collection + // failed, the value returned in the callback may be solely an error string. + // Will use `user_context` to validate that the user has permissions to the + // device's signals. // Currently only supports the collection of one signal (only one entry in // `parameter`). - virtual void GetSignals(const base::Value::Dict& parameters, + virtual void GetSignals(const UserContext& user_context, + base::Value::Dict parameters, GetSignalsCallback callback) = 0; };
diff --git a/components/device_signals/core/browser/signals_aggregator_impl.cc b/components/device_signals/core/browser/signals_aggregator_impl.cc index 8e2c411..f82a6289 100644 --- a/components/device_signals/core/browser/signals_aggregator_impl.cc +++ b/components/device_signals/core/browser/signals_aggregator_impl.cc
@@ -6,24 +6,50 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/logging.h" +#include "base/check.h" #include "base/strings/string_util.h" #include "base/values.h" #include "components/device_signals/core/browser/signals_collector.h" +#include "components/device_signals/core/browser/user_context.h" +#include "components/device_signals/core/browser/user_permission_service.h" +#include "components/device_signals/core/common/signals_constants.h" namespace device_signals { +namespace { + +std::string PermissionToError(const UserPermission permission) { + switch (permission) { + case UserPermission::kUnaffiliated: + return errors::kUnaffiliatedUser; + case UserPermission::kMissingConsent: + return errors::kConsentRequired; + case UserPermission::kConsumerUser: + case UserPermission::kUnknownUser: + return errors::kUnsupported; + case UserPermission::kGranted: + NOTREACHED(); + return ""; + } +} + +} // namespace + SignalsAggregatorImpl::SignalsAggregatorImpl( + UserPermissionService* permission_service, std::vector<std::unique_ptr<SignalsCollector>> collectors) - : collectors_(std::move(collectors)) {} + : permission_service_(permission_service), + collectors_(std::move(collectors)) { + DCHECK(permission_service_); +} SignalsAggregatorImpl::~SignalsAggregatorImpl() = default; -void SignalsAggregatorImpl::GetSignals(const base::Value::Dict& parameters, +void SignalsAggregatorImpl::GetSignals(const UserContext& user_context, + base::Value::Dict parameters, GetSignalsCallback callback) { - // TODO(b/229737384): Add CBCM-managed check. if (parameters.empty()) { - std::move(callback).Run(base::Value::Dict()); + std::move(callback).Run(base::Value(errors::kUnsupported)); return; } @@ -31,6 +57,22 @@ // first signal will be returned. DCHECK(parameters.size() == 1); + permission_service_->CanCollectSignals( + user_context, + base::BindOnce(&SignalsAggregatorImpl::OnUserPermissionChecked, + weak_factory_.GetWeakPtr(), std::move(parameters), + std::move(callback))); +} + +void SignalsAggregatorImpl::OnUserPermissionChecked( + base::Value::Dict parameters, + GetSignalsCallback callback, + const UserPermission user_permission) { + if (user_permission != UserPermission::kGranted) { + std::move(callback).Run(base::Value(PermissionToError(user_permission))); + return; + } + std::pair<const std::string&, const base::Value&> signal_request = *parameters.begin(); for (const auto& collector : collectors_) { @@ -50,7 +92,7 @@ } // Not a supported signal. - std::move(callback).Run(base::Value::Dict()); + std::move(callback).Run(base::Value(errors::kUnsupported)); } void SignalsAggregatorImpl::OnSignalCollected(const std::string signal_name, @@ -58,7 +100,7 @@ base::Value value) { base::Value::Dict return_value; return_value.Set(signal_name, std::move(value)); - std::move(callback).Run(std::move(return_value)); + std::move(callback).Run(base::Value(std::move(return_value))); } } // namespace device_signals
diff --git a/components/device_signals/core/browser/signals_aggregator_impl.h b/components/device_signals/core/browser/signals_aggregator_impl.h index b2607c52..949b7cb9 100644 --- a/components/device_signals/core/browser/signals_aggregator_impl.h +++ b/components/device_signals/core/browser/signals_aggregator_impl.h
@@ -14,10 +14,13 @@ namespace device_signals { class SignalsCollector; +class UserPermissionService; +enum class UserPermission; class SignalsAggregatorImpl : public SignalsAggregator { public: explicit SignalsAggregatorImpl( + UserPermissionService* permission_service, std::vector<std::unique_ptr<SignalsCollector>> collectors); SignalsAggregatorImpl(const SignalsAggregatorImpl&) = delete; @@ -26,14 +29,20 @@ ~SignalsAggregatorImpl() override; // SignalsAggregator: - void GetSignals(const base::Value::Dict& parameters, + void GetSignals(const UserContext& user_context, + base::Value::Dict parameters, GetSignalsCallback callback) override; private: + void OnUserPermissionChecked(base::Value::Dict parameters, + GetSignalsCallback callback, + const UserPermission user_permission); + void OnSignalCollected(const std::string signal_name, GetSignalsCallback callback, base::Value value); + base::raw_ptr<UserPermissionService> permission_service_; std::vector<std::unique_ptr<SignalsCollector>> collectors_; base::WeakPtrFactory<SignalsAggregatorImpl> weak_factory_{this};
diff --git a/components/device_signals/core/browser/signals_aggregator_impl_unittest.cc b/components/device_signals/core/browser/signals_aggregator_impl_unittest.cc index ef04ab00..bb18ff6 100644 --- a/components/device_signals/core/browser/signals_aggregator_impl_unittest.cc +++ b/components/device_signals/core/browser/signals_aggregator_impl_unittest.cc
@@ -10,6 +10,10 @@ #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "components/device_signals/core/browser/mock_signals_collector.h" +#include "components/device_signals/core/browser/mock_user_permission_service.h" +#include "components/device_signals/core/browser/user_context.h" +#include "components/device_signals/core/browser/user_permission_service.h" +#include "components/device_signals/core/common/signals_constants.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -26,6 +30,8 @@ constexpr char kFakeSignalName[] = "signal_name"; constexpr char kOtherFakeSignalName[] = "other_signal_name"; +constexpr char kGaiaId[] = "gaia-id"; + base::Value GetFakeSignalParameter() { return base::Value("some parameter needed by the signal collector"); } @@ -92,28 +98,41 @@ std::vector<std::unique_ptr<SignalsCollector>> collectors; collectors.push_back(std::move(fake_signal_collector)); collectors.push_back(std::move(other_fake_signal_collector)); - aggregator_ = - std::make_unique<SignalsAggregatorImpl>(std::move(collectors)); + aggregator_ = std::make_unique<SignalsAggregatorImpl>( + &mock_permission_service_, std::move(collectors)); + } + + void GrantUserPermission() { + EXPECT_CALL(mock_permission_service_, CanCollectSignals(user_context_, _)) + .WillOnce([](const UserContext&, + UserPermissionService::CanCollectCallback callback) { + std::move(callback).Run(UserPermission::kGranted); + }); } base::test::TaskEnvironment task_environment_; MockSignalsCollector* fake_signal_collector_; MockSignalsCollector* other_fake_signal_collector_; + testing::StrictMock<MockUserPermissionService> mock_permission_service_; + UserContext user_context_{kGaiaId}; std::unique_ptr<SignalsAggregatorImpl> aggregator_; }; // Tests that the aggregator will return an empty value when given an empty // parameter dictionary. TEST_F(SignalsAggregatorImplTest, GetSignals_NoSignal) { - base::test::TestFuture<base::Value::Dict> future; + base::test::TestFuture<base::Value> future; base::Value::Dict empty_value; - aggregator_->GetSignals(empty_value, future.GetCallback()); - EXPECT_EQ(future.Get(), empty_value); + aggregator_->GetSignals(user_context_, std::move(empty_value), + future.GetCallback()); + EXPECT_EQ(future.Get(), base::Value(errors::kUnsupported)); } // Tests how the aggregator behaves when given a parameter with a single signal // which is supported by one of the collectors. TEST_F(SignalsAggregatorImplTest, GetSignals_SingleSignal_Supported) { + GrantUserPermission(); + base::Value::Dict parameters; parameters.Set(kFakeSignalName, GetFakeSignalParameter()); @@ -123,18 +142,21 @@ EXPECT_CALL(*other_fake_signal_collector_, GetSignal(_, _, _)).Times(0); - base::test::TestFuture<base::Value::Dict> future; - aggregator_->GetSignals(parameters, future.GetCallback()); + base::test::TestFuture<base::Value> future; + aggregator_->GetSignals(user_context_, std::move(parameters), + future.GetCallback()); base::Value::Dict expected_value; expected_value.Set(kFakeSignalName, GetFakeSignalValue()); - EXPECT_EQ(future.Get(), expected_value); + EXPECT_EQ(future.Get(), base::Value(std::move(expected_value))); } // Tests how the aggregator behaves when given a parameter with a single signal // which is supported by another collector. TEST_F(SignalsAggregatorImplTest, GetSignals_SingleSignal_SupportedOther) { + GrantUserPermission(); + base::Value::Dict parameters; parameters.Set(kOtherFakeSignalName, GetOtherFakeSignalParameter()); @@ -146,24 +168,58 @@ EXPECT_CALL(*fake_signal_collector_, GetSignal(_, _, _)).Times(0); - base::test::TestFuture<base::Value::Dict> future; - aggregator_->GetSignals(parameters, future.GetCallback()); + base::test::TestFuture<base::Value> future; + aggregator_->GetSignals(user_context_, std::move(parameters), + future.GetCallback()); base::Value::Dict expected_value; expected_value.Set(kOtherFakeSignalName, GetOtherFakeSignalValue()); - EXPECT_EQ(future.Get(), expected_value); + EXPECT_EQ(future.Get(), base::Value(std::move(expected_value))); } // Tests how the aggregator behaves when given a parameter with a single signal // that no collector supports. TEST_F(SignalsAggregatorImplTest, GetSignals_SingleSignal_Unsupported) { + GrantUserPermission(); + base::Value::Dict parameters; parameters.Set("something unsupported", base::Value()); - base::test::TestFuture<base::Value::Dict> future; - aggregator_->GetSignals(parameters, future.GetCallback()); - EXPECT_EQ(future.Get(), base::Value::Dict()); + base::test::TestFuture<base::Value> future; + aggregator_->GetSignals(user_context_, std::move(parameters), + future.GetCallback()); + EXPECT_EQ(future.Get(), base::Value(errors::kUnsupported)); +} + +// Tests how the aggregator behaves when encountering user permission errors. +TEST_F(SignalsAggregatorImplTest, GetSignals_InvalidUserPermissions) { + std::map<UserPermission, std::string> permission_to_error_map; + permission_to_error_map[UserPermission::kUnaffiliated] = + errors::kUnaffiliatedUser; + permission_to_error_map[UserPermission::kMissingConsent] = + errors::kConsentRequired; + permission_to_error_map[UserPermission::kConsumerUser] = errors::kUnsupported; + permission_to_error_map[UserPermission::kUnknownUser] = errors::kUnsupported; + + for (const auto& test_case : permission_to_error_map) { + EXPECT_CALL(mock_permission_service_, CanCollectSignals(user_context_, _)) + .WillOnce( + [&test_case](const UserContext&, + UserPermissionService::CanCollectCallback callback) { + std::move(callback).Run(test_case.first); + }); + + // This value is not important for these test cases. + base::Value::Dict parameters; + parameters.Set("something unsupported", base::Value()); + + base::test::TestFuture<base::Value> future; + aggregator_->GetSignals(user_context_, std::move(parameters), + future.GetCallback()); + + EXPECT_EQ(future.Get(), base::Value(test_case.second)); + } } } // namespace device_signals
diff --git a/components/device_signals/core/browser/user_context.cc b/components/device_signals/core/browser/user_context.cc new file mode 100644 index 0000000..ed3d091 --- /dev/null +++ b/components/device_signals/core/browser/user_context.cc
@@ -0,0 +1,13 @@ +// Copyright (c) 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/device_signals/core/browser/user_context.h" + +namespace device_signals { + +bool operator==(const UserContext& l, const UserContext& r) { + return l.user_id == r.user_id; +} + +} // namespace device_signals
diff --git a/components/device_signals/core/browser/user_context.h b/components/device_signals/core/browser/user_context.h new file mode 100644 index 0000000..7bbeda2 --- /dev/null +++ b/components/device_signals/core/browser/user_context.h
@@ -0,0 +1,21 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DEVICE_SIGNALS_CORE_BROWSER_USER_CONTEXT_H_ +#define COMPONENTS_DEVICE_SIGNALS_CORE_BROWSER_USER_CONTEXT_H_ + +#include <string> + +namespace device_signals { + +struct UserContext { + // GAIA ID of the user. + std::string user_id; +}; + +bool operator==(const UserContext& l, const UserContext& r); + +} // namespace device_signals + +#endif // COMPONENTS_DEVICE_SIGNALS_CORE_BROWSER_USER_CONTEXT_H_
diff --git a/components/device_signals/core/browser/user_permission_service.h b/components/device_signals/core/browser/user_permission_service.h index 9c68362..e82c95c 100644 --- a/components/device_signals/core/browser/user_permission_service.h +++ b/components/device_signals/core/browser/user_permission_service.h
@@ -5,18 +5,12 @@ #ifndef COMPONENTS_DEVICE_SIGNALS_CORE_BROWSER_USER_PERMISSION_SERVICE_H_ #define COMPONENTS_DEVICE_SIGNALS_CORE_BROWSER_USER_PERMISSION_SERVICE_H_ -#include <string> -#include <vector> - #include "base/callback_forward.h" #include "components/keyed_service/core/keyed_service.h" namespace device_signals { -struct UserContext { - // GAIA ID of the user. - std::string user_id; -}; +struct UserContext; enum class UserPermission { // Returned when the user is part of an organization that is not affiliated
diff --git a/components/device_signals/core/browser/user_permission_service_impl.cc b/components/device_signals/core/browser/user_permission_service_impl.cc index 70f8bbf..15da7274 100644 --- a/components/device_signals/core/browser/user_permission_service_impl.cc +++ b/components/device_signals/core/browser/user_permission_service_impl.cc
@@ -5,6 +5,7 @@ #include "components/device_signals/core/browser/user_permission_service_impl.h" #include "base/check.h" +#include "components/device_signals/core/browser/user_context.h" #include "components/policy/core/common/management/management_service.h" #include "components/signin/public/identity_manager/identity_manager.h"
diff --git a/components/device_signals/core/browser/user_permission_service_impl_unittest.cc b/components/device_signals/core/browser/user_permission_service_impl_unittest.cc index 12ac3c4..3ce6548 100644 --- a/components/device_signals/core/browser/user_permission_service_impl_unittest.cc +++ b/components/device_signals/core/browser/user_permission_service_impl_unittest.cc
@@ -6,6 +6,7 @@ #include "base/test/task_environment.h" #include "base/test/test_future.h" +#include "components/device_signals/core/browser/user_context.h" #include "components/policy/core/common/management/management_service.h" #include "components/policy/core/common/management/scoped_management_service_override_for_testing.h" #include "components/signin/public/identity_manager/account_info.h"
diff --git a/components/device_signals/core/common/signals_constants.cc b/components/device_signals/core/common/signals_constants.cc index bc0a16e5..ffe429b0 100644 --- a/components/device_signals/core/common/signals_constants.cc +++ b/components/device_signals/core/common/signals_constants.cc
@@ -5,6 +5,7 @@ #include "components/device_signals/core/common/signals_constants.h" namespace device_signals { + namespace names { // Name of the signal for getting information of the AllowScreenLock @@ -136,4 +137,20 @@ const char kWindowsDomain[] = "windowsDomain"; } // namespace names + +namespace errors { + +// Returned when the user has not given explicit consent for a specific signal +// to be collected. +const char kConsentRequired[] = "CONSENT_REQUIRED"; + +// Returned when the user is not affiliated with the organization managing the +// browser. +const char kUnaffiliatedUser[] = "UNAFFILIATED_USER"; + +// Returned when the specified signal is not supported. +const char kUnsupported[] = "UNSUPPORTED"; + +} // namespace errors + } // namespace device_signals
diff --git a/components/device_signals/core/common/signals_constants.h b/components/device_signals/core/common/signals_constants.h index 587840a..8b51398 100644 --- a/components/device_signals/core/common/signals_constants.h +++ b/components/device_signals/core/common/signals_constants.h
@@ -46,6 +46,16 @@ } // namespace names +// Error strings that can be returned to indicated why signal values were not +// returned. +namespace errors { + +extern const char kConsentRequired[]; +extern const char kUnaffiliatedUser[]; +extern const char kUnsupported[]; + +} // namespace errors + } // namespace device_signals #endif // COMPONENTS_DEVICE_SIGNALS_CORE_COMMON_SIGNALS_CONSTANTS_H_
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java index 114f224..00c70620d 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/RedirectHandler.java
@@ -42,16 +42,16 @@ private static class IntentState { final Intent mInitialIntent; final boolean mIsCustomTabIntent; - final boolean mIsInitialIntentHeadingToChrome; + final boolean mPreferToStayInChrome; final boolean mExternalIntentStartedTask; // A resolver list which includes all resolvers of |mInitialIntent|. HashSet<ComponentName> mCachedResolvers = new HashSet<ComponentName>(); - IntentState(Intent initialIntent, boolean isInitialIntentHeadingToChrome, - boolean isCustomTabIntent, boolean externalIntentStartedTask) { + IntentState(Intent initialIntent, boolean preferToStayInChrome, boolean isCustomTabIntent, + boolean externalIntentStartedTask) { mInitialIntent = initialIntent; - mIsInitialIntentHeadingToChrome = isInitialIntentHeadingToChrome; + mPreferToStayInChrome = preferToStayInChrome; mIsCustomTabIntent = isCustomTabIntent; mExternalIntentStartedTask = externalIntentStartedTask; } @@ -90,28 +90,24 @@ * Resets |mIntentState| for the newly received Intent. */ public void updateIntent(Intent intent, boolean isCustomTabIntent, boolean sendToExternalApps, - boolean isCCTExternalLinkHandlingEnabled, boolean externalIntentStartedTask) { + boolean externalIntentStartedTask) { if (intent == null || !Intent.ACTION_VIEW.equals(intent.getAction())) { mIntentState = null; return; } - boolean isInitialIntentHeadingToChrome = false; - boolean checkIsToChrome = true; - // All custom tabs VIEW intents are by design explicit intents, so the presence of package - // name doesn't imply they have to be handled by Chrome explicitly. Check if external apps - // should be checked for handling the initial redirect chain. - if (isCustomTabIntent) { - checkIsToChrome = !(sendToExternalApps && isCCTExternalLinkHandlingEnabled); - } + boolean preferToStayInChrome = isIntentToChrome(intent); - if (checkIsToChrome) isInitialIntentHeadingToChrome = isIntentToChrome(intent); + // A Custom Tab Intent from a Custom Tab Session will always have the package set, so the + // Intent will always be to Chrome. Therefore, we provide an Extra to allow the initial + // Intent navigation chain to leave Chrome. + if (isCustomTabIntent && sendToExternalApps) preferToStayInChrome = false; // A sanitized copy of the initial intent for detecting if resolvers have changed. Intent initialIntent = new Intent(intent); ExternalNavigationHandler.sanitizeQueryIntentActivitiesIntent(initialIntent); - mIntentState = new IntentState(initialIntent, isInitialIntentHeadingToChrome, - isCustomTabIntent, externalIntentStartedTask); + mIntentState = new IntentState( + initialIntent, preferToStayInChrome, isCustomTabIntent, externalIntentStartedTask); } private static boolean isIntentToChrome(Intent intent) { @@ -248,8 +244,7 @@ public boolean shouldStayInApp(boolean hasExternalProtocol, boolean isForTrustedCallingApp) { // http://crbug/424029 : Need to stay in Chrome for an intent heading explicitly to Chrome. // http://crbug/881740 : Relax stay in Chrome restriction for Custom Tabs. - return (mIntentState != null && mIntentState.mIsInitialIntentHeadingToChrome - && !hasExternalProtocol) + return (mIntentState != null && mIntentState.mPreferToStayInChrome && !hasExternalProtocol) || shouldNavigationTypeStayInApp(isForTrustedCallingApp); }
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java index e051f64..7cb7bf0 100644 --- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java +++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -87,7 +87,6 @@ private static final boolean IS_CUSTOM_TAB_INTENT = true; private static final boolean SEND_TO_EXTERNAL_APPS = true; - private static final boolean IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED = true; private static final boolean HANDLES_INSTANT_APP_LAUNCHING_INTERNALLY = true; private static final boolean INTENT_STARTED_TASK = true; @@ -348,8 +347,7 @@ redirectHandler.updateIntent( Intent.parseUri("http://example.test", Intent.URI_INTENT_SCHEME), - !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading( PageTransition.LINK | PageTransition.FROM_API, false, false, 0, 0, true); redirectHandler.updateNewUrlLoading(PageTransition.FORM_SUBMIT, false, false, 0, 0, false); @@ -635,8 +633,8 @@ // Ignore if url is redirected, transition type is IncomingIntent and a new intent doesn't // have any new resolver. - redirectHandler.updateIntent(ytIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + ytIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); checkUrl(YOUTUBE_MOBILE_URL) @@ -647,8 +645,8 @@ .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE); // Do not ignore if a new intent has any new resolver. - redirectHandler.updateIntent(fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); checkUrl(YOUTUBE_MOBILE_URL) @@ -660,8 +658,8 @@ START_OTHER_ACTIVITY); // Do not ignore if a new intent cannot be handled by Chrome. - redirectHandler.updateIntent(fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); checkUrl("intent://myownurl") @@ -684,8 +682,8 @@ int transTypeLinkFromIntent = PageTransition.LINK | PageTransition.FROM_API; // Ignore if an initial Intent was heading to Chrome. - redirectHandler.updateIntent(fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); checkUrl(YOUTUBE_MOBILE_URL) @@ -696,8 +694,8 @@ .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE); // Do not ignore if the URI has an external protocol. - redirectHandler.updateIntent(fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); checkUrl("market://1234") @@ -720,8 +718,8 @@ // In Custom Tabs, if the first url is not a redirect, stay in chrome. Intent barIntent = Intent.parseUri(YOUTUBE_URL, Intent.URI_INTENT_SCHEME); barIntent.setPackage(mContext.getPackageName()); - redirectHandler.updateIntent(barIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + barIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); checkUrl(YOUTUBE_URL) .withPageTransition(transTypeLinkFromIntent) @@ -732,8 +730,8 @@ // In Custom Tabs, if the first url is a redirect, don't allow it to intent out. Intent fooIntent = Intent.parseUri("http://foo.com/", Intent.URI_INTENT_SCHEME); fooIntent.setPackage(mContext.getPackageName()); - redirectHandler.updateIntent(fooIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); checkUrl(YOUTUBE_URL) @@ -747,8 +745,8 @@ // url is a redirect. Intent extraIntent2 = Intent.parseUri(YOUTUBE_URL, Intent.URI_INTENT_SCHEME); extraIntent2.setPackage(mContext.getPackageName()); - redirectHandler.updateIntent(extraIntent2, IS_CUSTOM_TAB_INTENT, SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + extraIntent2, IS_CUSTOM_TAB_INTENT, SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); checkUrl(YOUTUBE_URL) @@ -761,8 +759,8 @@ Intent extraIntent3 = Intent.parseUri(YOUTUBE_URL, Intent.URI_INTENT_SCHEME); extraIntent3.setPackage(mContext.getPackageName()); - redirectHandler.updateIntent(extraIntent3, IS_CUSTOM_TAB_INTENT, SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + extraIntent3, IS_CUSTOM_TAB_INTENT, SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); checkUrl(YOUTUBE_URL) @@ -774,8 +772,8 @@ START_OTHER_ACTIVITY); // External intent for a user-initiated navigation should always be allowed. - redirectHandler.updateIntent(fooIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); // Simulate a real user navigation. redirectHandler.updateNewUrlLoading( @@ -798,8 +796,8 @@ Intent fooIntent = Intent.parseUri("http://foo.com/", Intent.URI_INTENT_SCHEME); fooIntent.putExtra(CustomTabsIntent.EXTRA_ENABLE_INSTANT_APPS, true); fooIntent.setPackage(mContext.getPackageName()); - redirectHandler.updateIntent(fooIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false); @@ -860,8 +858,8 @@ RedirectHandler redirectHandler = RedirectHandler.create(); Intent fooIntent = Intent.parseUri("http://instantappenabled.com", Intent.URI_INTENT_SCHEME); - redirectHandler.updateIntent(fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, - IS_CCT_EXTERNAL_LINK_HANDLING_ENABLED, !INTENT_STARTED_TASK); + redirectHandler.updateIntent( + fooIntent, !IS_CUSTOM_TAB_INTENT, !SEND_TO_EXTERNAL_APPS, !INTENT_STARTED_TASK); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, false, false, 0, 0, false); redirectHandler.updateNewUrlLoading(transTypeLinkFromIntent, true, false, 0, 0, false);
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java index 70f1d6f9..fe8d741 100644 --- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java +++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/RedirectHandlerTest.java
@@ -82,7 +82,7 @@ @Feature({"IntentHandling"}) public void testRealIntentRedirect() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -105,7 +105,7 @@ @Feature({"IntentHandling"}) public void testEffectiveIntentRedirect_linkNavigation() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -128,7 +128,7 @@ @Feature({"IntentHandling"}) public void testEffectiveIntentRedirect_formSubmit() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -151,7 +151,7 @@ @Feature({"IntentHandling"}) public void testNoIntent() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(null, false, false, false, false); + handler.updateIntent(null, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -174,7 +174,7 @@ @Feature({"IntentHandling"}) public void testClear() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -202,7 +202,7 @@ @Feature({"IntentHandling"}) public void testNonLinkFromIntent() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(PageTransition.TYPED, false, false, 0, 0, false); @@ -225,7 +225,7 @@ @Feature({"IntentHandling"}) public void testUserInteraction() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -260,7 +260,7 @@ RedirectHandler handler = RedirectHandler.create(); Intent fooIntent = new Intent(sFooIntent); fooIntent.putExtra(Browser.EXTRA_APPLICATION_ID, TEST_PACKAGE_NAME); - handler.updateIntent(fooIntent, false, false, false, false); + handler.updateIntent(fooIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -288,7 +288,7 @@ @Feature({"IntentHandling"}) public void testNavigationFromUserTyping() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(PageTransition.TYPED, false, false, 0, 0, false); @@ -315,7 +315,7 @@ RedirectHandler handler = RedirectHandler.create(); Intent fooIntent = new Intent(sFooIntent); fooIntent.setPackage(TEST_PACKAGE_NAME); - handler.updateIntent(fooIntent, false, false, false, false); + handler.updateIntent(fooIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); handler.updateNewUrlLoading(TRANS_TYPE_OF_LINK_FROM_INTENT, false, false, 0, 0, false); @@ -346,7 +346,7 @@ // 1. 3XX redirection should not override URL loading. ///////////////////////////////////////////////////// RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); handler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 0, false); Assert.assertFalse(handler.shouldNotOverrideUrlLoading()); @@ -360,7 +360,7 @@ // 2. Effective redirection should not override URL loading. ///////////////////////////////////////////////////// handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); handler.updateNewUrlLoading(PageTransition.LINK, false, true, 0, 0, false); Assert.assertFalse(handler.shouldNotOverrideUrlLoading()); @@ -386,7 +386,7 @@ @Feature({"IntentHandling"}) public void testNavigationFromLinkWithoutUserGesture() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); long lastUserInteractionTime = SystemClock.elapsedRealtime(); @@ -417,7 +417,7 @@ @Feature({"IntentHandling"}) public void testNavigationFromReload() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); long lastUserInteractionTime = SystemClock.elapsedRealtime(); @@ -448,7 +448,7 @@ @Feature({"IntentHandling"}) public void testNavigationWithForwardBack() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sYtIntent, false, false, false, false); + handler.updateIntent(sYtIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); long lastUserInteractionTime = SystemClock.elapsedRealtime(); @@ -506,7 +506,7 @@ @Feature({"IntentHandling"}) public void testClientRedirectWithoutUserGesture() { RedirectHandler handler = RedirectHandler.create(); - handler.updateIntent(sFooIntent, false, false, false, false); + handler.updateIntent(sFooIntent, false, false, false); Assert.assertFalse(handler.isOnNavigation()); Assert.assertFalse(handler.hasUserStartedNonInitialNavigation());
diff --git a/components/minidump_uploader/OWNERS b/components/minidump_uploader/OWNERS index c1dcc7b..201c993 100644 --- a/components/minidump_uploader/OWNERS +++ b/components/minidump_uploader/OWNERS
@@ -1,2 +1,4 @@ hazems@chromium.org +mheikal@chromium.org +smaier@chromium.org wnwen@chromium.org
diff --git a/components/minidump_uploader/rewrite_minidumps_as_mimes.cc b/components/minidump_uploader/rewrite_minidumps_as_mimes.cc index 0dbdc37..956b63dd 100644 --- a/components/minidump_uploader/rewrite_minidumps_as_mimes.cc +++ b/components/minidump_uploader/rewrite_minidumps_as_mimes.cc
@@ -103,12 +103,8 @@ static_cast<uint32_t>(crashpad::Signals::kSimulatedSigno)) { UMA_HISTOGRAM_ENUMERATION( "Stability.Android.ProcessedRealMinidumps", count_type); - } else { - UMA_HISTOGRAM_ENUMERATION( - "Stability.Android.ProcessedSimulatedMinidumps", count_type); } } - // TODO(wnwen): Add histogram for number of null exceptions. } #endif // BUILDFLAG(IS_ANDROID) }
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index 720ff53..8b69baa 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -666,10 +666,9 @@ } // Add WebAuthn credentials suitable for an ongoing request if available. - if (show_webauthn_credentials) { - WebAuthnCredentialsDelegate* delegate = - password_client_->GetWebAuthnCredentialsDelegate(); - DCHECK(delegate->IsWebAuthnAutofillEnabled()); + WebAuthnCredentialsDelegate* delegate = + password_client_->GetWebAuthnCredentialsDelegate(); + if (show_webauthn_credentials && delegate->IsWebAuthnAutofillEnabled()) { std::vector<autofill::Suggestion> webauthn_suggestions = delegate->GetWebAuthnSuggestions(); suggestions.insert(suggestions.end(), webauthn_suggestions.begin(),
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 7a7e22b..921055c 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -36,6 +36,7 @@ #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/possible_username_data.h" +#include "components/password_manager/core/browser/psl_matching_helper.h" #include "components/password_manager/core/browser/statistics_table.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -743,6 +744,7 @@ submitted_form_ = submitted_form; is_submitted_ = true; CalculateFillingAssistanceMetric(submitted_form); + CalculateSubmittedFormFrameMetric(); metrics_recorder_->set_possible_username_used(false); votes_uploader_.clear_single_username_vote_data(); @@ -1045,6 +1047,35 @@ ->ComputePasswordAccountStorageUsageLevel()); } +void PasswordFormManager::CalculateSubmittedFormFrameMetric() { + if (!driver_) + return; + + const PasswordForm& form = *GetSubmittedForm(); + metrics_util::SubmittedFormFrame frame; + if (driver_->IsInPrimaryMainFrame()) { + frame = metrics_util::SubmittedFormFrame::MAIN_FRAME; + } else if (form.url == client_->GetLastCommittedURL()) { + frame = + metrics_util::SubmittedFormFrame::IFRAME_WITH_SAME_URL_AS_MAIN_FRAME; + } else { + std::string main_frame_signon_realm = + GetSignonRealm(client_->GetLastCommittedURL()); + if (main_frame_signon_realm == form.signon_realm) { + frame = metrics_util::SubmittedFormFrame:: + IFRAME_WITH_DIFFERENT_URL_SAME_SIGNON_REALM_AS_MAIN_FRAME; + } else if (IsPublicSuffixDomainMatch(form.signon_realm, + main_frame_signon_realm)) { + frame = metrics_util::SubmittedFormFrame:: + IFRAME_WITH_PSL_MATCHED_SIGNON_REALM; + } else { + frame = metrics_util::SubmittedFormFrame:: + IFRAME_WITH_DIFFERENT_AND_NOT_PSL_MATCHED_SIGNON_REALM; + } + } + metrics_recorder_->set_submitted_form_frame(frame); +} + bool PasswordFormManager::IsPossibleSingleUsernameAvailable( const PossibleUsernameData* possible_username) const { if (!possible_username) {
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h index 430698f..dbeffa93 100644 --- a/components/password_manager/core/browser/password_form_manager.h +++ b/components/password_manager/core/browser/password_form_manager.h
@@ -319,6 +319,11 @@ void CalculateFillingAssistanceMetric( const autofill::FormData& submitted_form); + // Calculates SubmittedPasswordFormFrame metric value (main frame, iframe, + // etc) for |submitted_form|. The metric is recorded when the form manager is + // destroyed. + void CalculateSubmittedFormFrameMetric(); + // Save/update |pending_credentials_| to the password store. void SavePendingToStore(bool update);
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index 8314bb8..36fd0ba9 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -39,6 +39,7 @@ #include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/password_save_manager_impl.h" #include "components/password_manager/core/browser/possible_username_data.h" +#include "components/password_manager/core/browser/psl_matching_helper.h" #include "components/password_manager/core/browser/stub_form_saver.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" @@ -123,10 +124,15 @@ class MockPasswordManagerDriver : public StubPasswordManagerDriver { public: - MOCK_METHOD1(FillPasswordForm, void(const PasswordFormFillData&)); - MOCK_METHOD1(AllowPasswordGenerationForForm, void(const PasswordForm&)); - MOCK_METHOD1(FormEligibleForGenerationFound, - void(const autofill::PasswordFormGenerationData&)); + MOCK_METHOD(void, + FillPasswordForm, + (const PasswordFormFillData&), + (override)); + MOCK_METHOD(void, + FormEligibleForGenerationFound, + (const autofill::PasswordFormGenerationData&), + (override)); + MOCK_METHOD(bool, IsInPrimaryMainFrame, (), (const, override)); }; class MockAutofillDownloadManager : public autofill::AutofillDownloadManager { @@ -172,6 +178,7 @@ MOCK_METHOD(FieldInfoManager*, GetFieldInfoManager, (), (const, override)); MOCK_METHOD(signin::IdentityManager*, GetIdentityManager, (), (override)); MOCK_METHOD(PrefService*, GetPrefs, (), (const, override)); + MOCK_METHOD(const GURL&, GetLastCommittedURL, (), (const, override)); MOCK_METHOD(WebAuthnCredentialsDelegate*, GetWebAuthnCredentialsDelegate, (), @@ -444,6 +451,8 @@ ON_CALL(*client_.GetPasswordFeatureManager(), GetDefaultPasswordStore) .WillByDefault(Return(PasswordForm::Store::kProfileStore)); + ON_CALL(client_, GetLastCommittedURL()) + .WillByDefault(ReturnRef(observed_form_.url)); ON_CALL(client_, GetWebAuthnCredentialsDelegate) .WillByDefault(Return(&webauthn_credentials_delegate_)); ON_CALL(webauthn_credentials_delegate_, IsWebAuthnAutofillEnabled) @@ -2689,6 +2698,95 @@ EXPECT_TRUE(form_manager_->IsMovableToAccountStore()); } +TEST_P(PasswordFormManagerTest, ReportSubmittedFormFrameMainFrame) { + base::HistogramTester histogram_tester; + EXPECT_CALL(driver_, IsInPrimaryMainFrame).WillRepeatedly(Return(true)); + + form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr); + + // Check metrics recorded on the form manager destruction. + form_manager_.reset(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.SubmittedFormFrame2", + metrics_util::SubmittedFormFrame::MAIN_FRAME, 1); +} + +TEST_P(PasswordFormManagerTest, ReportSubmittedFormFrameSameOriginIframe) { + base::HistogramTester histogram_tester; + EXPECT_CALL(driver_, IsInPrimaryMainFrame).WillRepeatedly(Return(false)); + + EXPECT_CALL(client_, GetLastCommittedURL) + .WillOnce(ReturnRef(submitted_form_.url)); + form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr); + + // Check metrics recorded on the form manager destruction. + form_manager_.reset(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.SubmittedFormFrame2", + metrics_util::SubmittedFormFrame::IFRAME_WITH_SAME_URL_AS_MAIN_FRAME, 1); +} + +TEST_P(PasswordFormManagerTest, ReportSubmittedFormFrameSameSignOnRealmIframe) { + base::HistogramTester histogram_tester; + EXPECT_CALL(driver_, IsInPrimaryMainFrame).WillRepeatedly(Return(false)); + + GURL main_frame_url = GURL(GetSignonRealm(submitted_form_.url)); + ASSERT_NE(submitted_form_.url, main_frame_url); + EXPECT_CALL(client_, GetLastCommittedURL) + .WillRepeatedly(ReturnRef(main_frame_url)); + form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr); + + // Check metrics recorded on the form manager destruction. + form_manager_.reset(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.SubmittedFormFrame2", + metrics_util::SubmittedFormFrame:: + IFRAME_WITH_DIFFERENT_URL_SAME_SIGNON_REALM_AS_MAIN_FRAME, + 1); +} + +TEST_P(PasswordFormManagerTest, ReportSubmittedFormFramePSLMatchedIframe) { + base::HistogramTester histogram_tester; + EXPECT_CALL(driver_, IsInPrimaryMainFrame).WillRepeatedly(Return(false)); + + submitted_form_.url = GURL("http://facebook.com"); + GURL main_frame_url = GURL("http://m.facebook.com"); + ASSERT_TRUE(IsPublicSuffixDomainMatch(submitted_form_.url.spec(), + main_frame_url.spec())); + EXPECT_CALL(client_, GetLastCommittedURL) + .WillRepeatedly(ReturnRef(main_frame_url)); + form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr); + + // Check metrics recorded on the form manager destruction. + form_manager_.reset(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.SubmittedFormFrame2", + metrics_util::SubmittedFormFrame::IFRAME_WITH_PSL_MATCHED_SIGNON_REALM, + 1); +} + +TEST_P(PasswordFormManagerTest, ReportSubmittedFormFrameCrossOriginIframe) { + base::HistogramTester histogram_tester; + EXPECT_CALL(driver_, IsInPrimaryMainFrame).WillRepeatedly(Return(false)); + + GURL main_frame_url = GURL("http://www.crossorigin.com/login"); + ASSERT_NE(GetSignonRealm(submitted_form_.url), + GetSignonRealm(main_frame_url)); + ASSERT_FALSE(IsPublicSuffixDomainMatch(submitted_form_.url.spec(), + main_frame_url.spec())); + EXPECT_CALL(client_, GetLastCommittedURL) + .WillRepeatedly(ReturnRef(main_frame_url)); + form_manager_->ProvisionallySave(submitted_form_, &driver_, nullptr); + + // Check metrics recorded on the form manager destruction. + form_manager_.reset(); + histogram_tester.ExpectUniqueSample( + "PasswordManager.SubmittedFormFrame2", + metrics_util::SubmittedFormFrame:: + IFRAME_WITH_DIFFERENT_AND_NOT_PSL_MATCHED_SIGNON_REALM, + 1); +} + INSTANTIATE_TEST_SUITE_P(All, PasswordFormManagerTest, testing::Values(false, true));
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.cc b/components/password_manager/core/browser/password_form_metrics_recorder.cc index c2dfadad4..345fcb9 100644 --- a/components/password_manager/core/browser/password_form_metrics_recorder.cc +++ b/components/password_manager/core/browser/password_form_metrics_recorder.cc
@@ -273,6 +273,12 @@ generated_password_status_.value())); } + if (submitted_form_frame_.has_value()) { + base::UmaHistogramEnumeration( + "PasswordManager.SubmittedFormFrame2", submitted_form_frame_.value(), + metrics_util::SubmittedFormFrame::SUBMITTED_FORM_FRAME_COUNT); + } + if (password_generation_popup_shown_ != PasswordGenerationPopupShown::kNotShown) { UMA_HISTOGRAM_ENUMERATION("PasswordGeneration.PopupShown",
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.h b/components/password_manager/core/browser/password_form_metrics_recorder.h index 41033ac..3aa7490 100644 --- a/components/password_manager/core/browser/password_form_metrics_recorder.h +++ b/components/password_manager/core/browser/password_form_metrics_recorder.h
@@ -430,6 +430,11 @@ void set_clock_for_testing(base::Clock* clock) { clock_ = clock; } + void set_submitted_form_frame( + metrics_util::SubmittedFormFrame submitted_form_frame) { + submitted_form_frame_ = submitted_form_frame; + } + private: friend class base::RefCounted<PasswordFormMetricsRecorder>; @@ -518,6 +523,7 @@ absl::optional<FillingSource> filling_source_; absl::optional<metrics_util::PasswordAccountStorageUsageLevel> account_storage_usage_level_; + absl::optional<metrics_util::SubmittedFormFrame> submitted_form_frame_; // Whether a single username candidate was populated in prompt. bool possible_username_used_ = false;
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 92d23d1..a9e7e82 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -728,8 +728,6 @@ // compare the landing URL against the cached and report the difference. submitted_form_url_ = submitted_url; - ReportSubmittedFormFrameMetric(driver, *matched_manager->GetSubmittedForm()); - return matched_manager; } @@ -1285,30 +1283,6 @@ return nullptr; } -void PasswordManager::ReportSubmittedFormFrameMetric( - const PasswordManagerDriver* driver, - const PasswordForm& form) { - if (!driver) - return; - - metrics_util::SubmittedFormFrame frame; - if (driver->IsInPrimaryMainFrame()) { - frame = metrics_util::SubmittedFormFrame::MAIN_FRAME; - } else if (form.url == client()->GetLastCommittedURL()) { - frame = - metrics_util::SubmittedFormFrame::IFRAME_WITH_SAME_URL_AS_MAIN_FRAME; - } else { - std::string main_frame_signon_realm = - GetSignonRealm(client()->GetLastCommittedURL()); - frame = (main_frame_signon_realm == form.signon_realm) - ? metrics_util::SubmittedFormFrame:: - IFRAME_WITH_DIFFERENT_URL_SAME_SIGNON_REALM_AS_MAIN_FRAME - : metrics_util::SubmittedFormFrame:: - IFRAME_WITH_DIFFERENT_SIGNON_REALM; - } - metrics_util::LogSubmittedFormFrame(frame); -} - void PasswordManager::TryToFindPredictionsToPossibleUsernameData() { if (!possible_username_ || possible_username_->form_predictions) return;
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h index 6c75b59..bb070841 100644 --- a/components/password_manager/core/browser/password_manager.h +++ b/components/password_manager/core/browser/password_manager.h
@@ -314,10 +314,6 @@ PasswordFormManager* GetMatchedManager(PasswordManagerDriver* driver, autofill::FormRendererId form_id); - // Log a frame (main frame, iframe) of a submitted password form. - void ReportSubmittedFormFrameMetric(const PasswordManagerDriver* driver, - const PasswordForm& form); - // If |possible_username_.form_predictions| is missing, this functions tries // to find predictions for the form which contains |possible_username_| in // |predictions_|.
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index 2ebc2ef..4c60e71 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -266,11 +266,6 @@ "PasswordManager.AcceptedSaveUpdateSubmissionIndicatorEvent", event); } -void LogSubmittedFormFrame(SubmittedFormFrame frame) { - base::UmaHistogramEnumeration("PasswordManager.SubmittedFormFrame", frame, - SubmittedFormFrame::SUBMITTED_FORM_FRAME_COUNT); -} - void LogPasswordsCountFromAccountStoreAfterUnlock( int account_store_passwords_count) { base::UmaHistogramCounts100(
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index 39fecca6..2abc106 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -214,7 +214,10 @@ MAIN_FRAME = 0, IFRAME_WITH_SAME_URL_AS_MAIN_FRAME = 1, IFRAME_WITH_DIFFERENT_URL_SAME_SIGNON_REALM_AS_MAIN_FRAME = 2, - IFRAME_WITH_DIFFERENT_SIGNON_REALM = 3, + // Deprecated and replaced with a combination of buckets 4 & 5. + // IFRAME_WITH_DIFFERENT_SIGNON_REALM = 3, + IFRAME_WITH_PSL_MATCHED_SIGNON_REALM = 4, + IFRAME_WITH_DIFFERENT_AND_NOT_PSL_MATCHED_SIGNON_REALM = 5, SUBMITTED_FORM_FRAME_COUNT }; @@ -671,9 +674,6 @@ void LogPasswordAcceptedSaveUpdateSubmissionIndicatorEvent( autofill::mojom::SubmissionIndicatorEvent event); -// Log a frame of a submitted password form. -void LogSubmittedFormFrame(SubmittedFormFrame frame); - // Logs how many account-stored passwords are available for filling in the // current password form right after unlock. void LogPasswordsCountFromAccountStoreAfterUnlock(
diff --git a/components/policy/core/browser/browser_policy_connector.cc b/components/policy/core/browser/browser_policy_connector.cc index 56f8f7f..877cb99 100644 --- a/components/policy/core/browser/browser_policy_connector.cc +++ b/components/policy/core/browser/browser_policy_connector.cc
@@ -141,30 +141,31 @@ } std::string BrowserPolicyConnector::GetDeviceManagementUrl() const { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDeviceManagementUrl) && - IsCommandLineSwitchSupported()) - return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl); - else - return kDefaultDeviceManagementServerUrl; + return GetUrlOverride(switches::kDeviceManagementUrl, + kDefaultDeviceManagementServerUrl); } std::string BrowserPolicyConnector::GetRealtimeReportingUrl() const { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kRealtimeReportingUrl) && - IsCommandLineSwitchSupported()) - return command_line->GetSwitchValueASCII(switches::kRealtimeReportingUrl); - else - return kDefaultRealtimeReportingServerUrl; + return GetUrlOverride(switches::kRealtimeReportingUrl, + kDefaultRealtimeReportingServerUrl); } std::string BrowserPolicyConnector::GetEncryptedReportingUrl() const { + return GetUrlOverride(switches::kEncryptedReportingUrl, + kDefaultEncryptedReportingServerUrl); +} + +std::string BrowserPolicyConnector::GetUrlOverride( + const char* flag, + const char* default_value) const { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kEncryptedReportingUrl) && - IsCommandLineSwitchSupported()) - return command_line->GetSwitchValueASCII(switches::kEncryptedReportingUrl); - else - return kDefaultEncryptedReportingServerUrl; + if (command_line->HasSwitch(flag)) { + if (IsCommandLineSwitchSupported()) + return command_line->GetSwitchValueASCII(flag); + else + LOG(WARNING) << flag << " not supported on this channel"; + } + return default_value; } // static
diff --git a/components/policy/core/browser/browser_policy_connector.h b/components/policy/core/browser/browser_policy_connector.h index 6babaff..d03a5f1 100644 --- a/components/policy/core/browser/browser_policy_connector.h +++ b/components/policy/core/browser/browser_policy_connector.h
@@ -98,6 +98,11 @@ bool ProviderHasPolicies(const ConfigurationPolicyProvider* provider) const; private: + // Helper function to read URL overriding flags. If `flag` isn't set or if the + // Chrome channel doesn't allowing overriding, `default_value` is returned + // instead. + std::string GetUrlOverride(const char* flag, const char* default_value) const; + std::unique_ptr<PolicyStatisticsCollector> policy_statistics_collector_; std::unique_ptr<DeviceManagementService> device_management_service_;
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 497899e..4d1b1fb 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -20010,7 +20010,9 @@ Setting the policy to Disabled or leaving it unset means platform policy takes precedence if it conflicts with cloud policy. - This mandatory policy affects machine scope cloud policies.''', + This mandatory policy affects machine scope cloud policies. + + This policy is only available on <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>; it has no effect on <ph name="GOOGLE_UPDATE_NAME">Google Update</ph>.''', }, { 'name': 'CloudUserPolicyOverridesCloudMachinePolicy',
diff --git a/components/segmentation_platform/public/features.cc b/components/segmentation_platform/public/features.cc index 0974d9e7..9cc0195 100644 --- a/components/segmentation_platform/public/features.cc +++ b/components/segmentation_platform/public/features.cc
@@ -26,4 +26,8 @@ "SegmentationPlatformFeedSegmentFeature", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kContextualPageActionsWithPriceTracking{ + "ContextualPageActionsWithPriceTracking", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace segmentation_platform::features
diff --git a/components/segmentation_platform/public/features.h b/components/segmentation_platform/public/features.h index a791d90c..f0697f3e 100644 --- a/components/segmentation_platform/public/features.h +++ b/components/segmentation_platform/public/features.h
@@ -29,6 +29,9 @@ // Feature flag for enabling Feed user segments feature. extern const base::Feature kSegmentationPlatformFeedSegmentFeature; +// Feature flag for enabling price tracking feature. +extern const base::Feature kContextualPageActionsWithPriceTracking; + } // namespace segmentation_platform::features #endif // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_FEATURES_H_
diff --git a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc index 0ebf6bf0..868c9b48 100644 --- a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc +++ b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc
@@ -31,7 +31,6 @@ namespace { const char kAccountIdPrefix[] = "AccountId-"; -const size_t kAccountIdPrefixLength = 10; // Enum for the Signin.LoadTokenFromDB histogram. // Do not modify, or add or delete other than directly before @@ -58,17 +57,15 @@ return kAccountIdPrefix + account_id; } -bool IsLegacyRefreshTokenId(const std::string& service_id) { - return service_id == GaiaConstants::kGaiaOAuth2LoginRefreshToken; -} - -bool IsLegacyServiceId(const std::string& account_id) { - return account_id.compare(0u, kAccountIdPrefixLength, kAccountIdPrefix) != 0; -} - +// Checks that |prefixed_account_id| starts with the expected prefix +// (|prefixed_account_id|) and returns the non-prefixed account id or an empty +// account id if |prefixed_account_id| is not correctly prefixed. CoreAccountId RemoveAccountIdPrefix(const std::string& prefixed_account_id) { + if (!base::StartsWith(prefixed_account_id, kAccountIdPrefix)) + return CoreAccountId(); + return CoreAccountId::FromString( - prefixed_account_id.substr(kAccountIdPrefixLength)); + prefixed_account_id.substr(/*pos=*/strlen(kAccountIdPrefix))); } signin::LoadCredentialsState LoadCredentialsStateFromTokenResult( @@ -450,62 +447,58 @@ void MutableProfileOAuth2TokenServiceDelegate::LoadAllCredentialsIntoMemory( const std::map<std::string, std::string>& db_tokens) { - { - ScopedBatchChange batch(this); + VLOG(1) << "MutablePO2TS::LoadAllCredentialsIntoMemory; " << db_tokens.size() + << " redential(s)."; - VLOG(1) << "MutablePO2TS::LoadAllCredentialsIntoMemory; " - << db_tokens.size() << " Credential(s)."; - for (auto iter = db_tokens.begin(); iter != db_tokens.end(); ++iter) { - std::string prefixed_account_id = iter->first; - std::string refresh_token = iter->second; + ScopedBatchChange batch(this); + for (const auto& db_token : db_tokens) { + std::string prefixed_account_id = db_token.first; + std::string refresh_token = db_token.second; - if (IsLegacyRefreshTokenId(prefixed_account_id) || - IsLegacyServiceId(prefixed_account_id)) { - if (token_web_data_) { - VLOG(1) << "MutablePO2TS remove legacy refresh token for account id " - << prefixed_account_id; - token_web_data_->RemoveTokenForService(prefixed_account_id); - } - } else { - DCHECK(!refresh_token.empty()); - CoreAccountId account_id = RemoveAccountIdPrefix(prefixed_account_id); - DCHECK(!account_id.IsEmail()) - << "Expecting a Gaia ID as account id [ account_id = " << account_id - << "]"; - - // Only load secondary accounts when account consistency is enabled. - bool load_account = - account_id == loading_primary_account_id_ || - account_consistency_ == signin::AccountConsistencyMethod::kDice; - LoadTokenFromDBStatus load_token_status = - load_account - ? LoadTokenFromDBStatus::TOKEN_LOADED - : LoadTokenFromDBStatus::TOKEN_REVOKED_SECONDARY_ACCOUNT; - - if (load_account && revoke_all_tokens_on_load_) { - if (account_id == loading_primary_account_id_) { - RevokeCredentialsOnServer(refresh_token); - refresh_token = GaiaConstants::kInvalidRefreshToken; - PersistCredentials(account_id, refresh_token); - } else { - load_account = false; - } - load_token_status = LoadTokenFromDBStatus::TOKEN_REVOKED_ON_LOAD; - } - - UMA_HISTOGRAM_ENUMERATION( - "Signin.LoadTokenFromDB", load_token_status, - LoadTokenFromDBStatus::NUM_LOAD_TOKEN_FROM_DB_STATUS); - - if (load_account) { - UpdateCredentialsInMemory(account_id, refresh_token); - FireRefreshTokenAvailable(account_id); - } else { - RevokeCredentialsOnServer(refresh_token); - ClearPersistedCredentials(account_id); - FireRefreshTokenRevoked(account_id); - } + CoreAccountId account_id = RemoveAccountIdPrefix(prefixed_account_id); + if (account_id.empty()) { + if (token_web_data_) { + VLOG(1) << "MutablePO2TS remove refresh token for invalid account id [" + << prefixed_account_id << "]"; + token_web_data_->RemoveTokenForService(prefixed_account_id); } + continue; + } + + DCHECK(!account_id.IsEmail()) + << "Acount id should be a Gaia id [account_id = " << account_id << "]"; + DCHECK(!refresh_token.empty()); + + // Only load secondary accounts when account consistency is enabled. + bool load_account = + account_id == loading_primary_account_id_ || + account_consistency_ == signin::AccountConsistencyMethod::kDice; + LoadTokenFromDBStatus load_token_status = + load_account ? LoadTokenFromDBStatus::TOKEN_LOADED + : LoadTokenFromDBStatus::TOKEN_REVOKED_SECONDARY_ACCOUNT; + + if (load_account && revoke_all_tokens_on_load_) { + if (account_id == loading_primary_account_id_) { + RevokeCredentialsOnServer(refresh_token); + refresh_token = GaiaConstants::kInvalidRefreshToken; + PersistCredentials(account_id, refresh_token); + } else { + load_account = false; + } + load_token_status = LoadTokenFromDBStatus::TOKEN_REVOKED_ON_LOAD; + } + + UMA_HISTOGRAM_ENUMERATION( + "Signin.LoadTokenFromDB", load_token_status, + LoadTokenFromDBStatus::NUM_LOAD_TOKEN_FROM_DB_STATUS); + + if (load_account) { + UpdateCredentialsInMemory(account_id, refresh_token); + FireRefreshTokenAvailable(account_id); + } else { + RevokeCredentialsOnServer(refresh_token); + ClearPersistedCredentials(account_id); + FireRefreshTokenRevoked(account_id); } } }
diff --git a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc index 4416c0a..97c523d 100644 --- a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc +++ b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -46,7 +46,6 @@ // Defining constant here to handle backward compatiblity tests, but this // constant is no longer used in current versions of chrome. -static const char kLSOService[] = "lso"; static const char kEmail[] = "user@gmail.com"; class MutableProfileOAuth2TokenServiceDelegateTest @@ -245,11 +244,10 @@ InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDice); CoreAccountId primary_account_id("primaryAccount"); - // Populate DB with legacy tokens (Expected to be discarded). - AddAuthTokenManually(GaiaConstants::kSyncService, "syncServiceToken"); - AddAuthTokenManually(kLSOService, "lsoToken"); - AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken, - "primaryLegacyRefreshToken"); + // Populate DB with legacy service tokens (all expected to be discarded). + AddAuthTokenManually("chromiumsync", "syncServiceToken"); + AddAuthTokenManually("lso", "lsoToken"); + AddAuthTokenManually("kObfuscatedGaiaId", "primaryLegacyRefreshToken"); // Force LoadCredentials. oauth2_service_delegate_->LoadCredentials(primary_account_id,
diff --git a/components/viz/service/display/display_damage_tracker.cc b/components/viz/service/display/display_damage_tracker.cc index 2c477b6..94bcdf6 100644 --- a/components/viz/service/display/display_damage_tracker.cc +++ b/components/viz/service/display/display_damage_tracker.cc
@@ -176,11 +176,6 @@ return display_damaged; } -void DisplayDamageTracker::OnSurfaceDestroyed(const SurfaceId& surface_id) { - TRACE_EVENT0("viz", "DisplayDamageTracker::SurfaceDestroyed"); - aggregator_->ReleaseResources(surface_id); -} - void DisplayDamageTracker::OnSurfaceDamageExpected(const SurfaceId& surface_id, const BeginFrameArgs& args) { TRACE_EVENT1("viz", "DisplayDamageTracker::SurfaceDamageExpected",
diff --git a/components/viz/service/display/display_damage_tracker.h b/components/viz/service/display/display_damage_tracker.h index dfc451e..3abe233 100644 --- a/components/viz/service/display/display_damage_tracker.h +++ b/components/viz/service/display/display_damage_tracker.h
@@ -81,7 +81,6 @@ void OnSurfaceMarkedForDestruction(const SurfaceId& surface_id) override; bool OnSurfaceDamaged(const SurfaceId& surface_id, const BeginFrameAck& ack) override; - void OnSurfaceDestroyed(const SurfaceId& surface_id) override; void OnSurfaceDamageExpected(const SurfaceId& surface_id, const BeginFrameArgs& args) override;
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index 9b26cb4..e9915f8 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc
@@ -305,12 +305,16 @@ extra_pass_for_readback_option_(extra_pass_option) { DCHECK(manager_); DCHECK(provider_); + manager_->AddObserver(this); } SurfaceAggregator::~SurfaceAggregator() { - // Notify client of all surfaces being removed. + manager_->RemoveObserver(this); + contained_surfaces_.clear(); contained_frame_sinks_.clear(); + + // Notify client of all surfaces being removed. ProcessAddedAndRemovedSurfaces(); } @@ -533,10 +537,21 @@ sqs->de_jelly_delta_y == 0; } +void SurfaceAggregator::OnSurfaceDestroyed(const SurfaceId& surface_id) { + DCHECK(!is_inside_aggregate_); + + auto iter = resolved_frames_.find(surface_id); + if (iter != resolved_frames_.end()) { + TRACE_EVENT0("viz", "SurfaceAggregator::SurfaceDestroyed"); + ReleaseResources(surface_id); + resolved_frames_.erase(iter); + } +} + const ResolvedFrameData* SurfaceAggregator::GetLatestFrameData( const SurfaceId& surface_id) { - auto* surface = manager_->GetSurfaceForId(surface_id); - return GetResolvedFrame(surface, /*inside_aggregation=*/false); + DCHECK(!is_inside_aggregate_); + return GetResolvedFrame(surface_id); } ResolvedFrameData* SurfaceAggregator::GetResolvedFrame( @@ -545,59 +560,51 @@ // this aggregation, then find ResolvedFrameData for that surface. auto iter = resolved_surface_ranges_.find(range); if (iter == resolved_surface_ranges_.end()) { - iter = resolved_surface_ranges_ - .emplace(range, manager_->GetLatestInFlightSurface(range)) - .first; + auto* surface = manager_->GetLatestInFlightSurface(range); + SurfaceId surface_id = surface ? surface->surface_id() : SurfaceId(); + iter = resolved_surface_ranges_.emplace(range, surface_id).first; } - return GetResolvedFrame(iter->second, /*inside_aggregation=*/true); + if (!iter->second.is_valid()) { + // There is no surface for `range`. + return nullptr; + } + + return GetResolvedFrame(iter->second); } ResolvedFrameData* SurfaceAggregator::GetResolvedFrame( const SurfaceId& surface_id) { - return GetResolvedFrame(manager_->GetSurfaceForId(surface_id), - /*inside_aggregation=*/true); -} + DCHECK(surface_id.is_valid()); -ResolvedFrameData* SurfaceAggregator::GetResolvedFrame( - Surface* surface, - bool inside_aggregation) { - if (!surface || !surface->HasActiveFrame()) { - // If there is no resolved surface or the surface has no active frame there - // is no resolved frame data to return. - return nullptr; - } - - auto iter = resolved_frames_.find(surface); + auto iter = resolved_frames_.find(surface_id); if (iter == resolved_frames_.end()) { - iter = - resolved_frames_ - .emplace(std::piecewise_construct, std::forward_as_tuple(surface), - std::forward_as_tuple(surface->surface_id(), surface)) - .first; + auto* surface = manager_->GetSurfaceForId(surface_id); + if (!surface || !surface->HasActiveFrame()) { + // If there is no resolved surface or the surface has no active frame + // there is no resolved frame data to return. + return nullptr; + } + + iter = resolved_frames_ + .emplace(std::piecewise_construct, + std::forward_as_tuple(surface_id), + std::forward_as_tuple(surface->surface_id(), surface)) + .first; } ResolvedFrameData& resolved_frame = iter->second; - DCHECK_EQ(resolved_frame.surface(), surface); - - // Verify that a new surface wasn't created at the same address as a deleted - // surface with a different SurfaceId. - // TODO(kylechar): Invalidate cached resolved frame data when - // SurfaceObserver signals the surface has been destroyed instead. - if (resolved_frame.surface_id() != surface->surface_id()) { - resolved_frames_.erase(iter); - return GetResolvedFrame(surface, inside_aggregation); - } + Surface* surface = resolved_frame.surface(); // Mark the frame as used this aggregation so it persists. - bool first_use = inside_aggregation ? resolved_frame.MarkAsUsed() : true; + bool first_use = is_inside_aggregate_ ? resolved_frame.MarkAsUsed() : true; if (first_use) { // If there is a new CompositorFrame for `surface` compute resolved frame // data for the new resolved CompositorFrame. if (resolved_frame.frame_index() != surface->GetActiveFrameIndex() || surface->HasSurfaceAnimationDamage()) { - DCHECK(inside_aggregation); + DCHECK(is_inside_aggregate_); base::ElapsedTimer timer; ProcessResolvedFrame(resolved_frame); stats_->declare_resources_time += timer.Elapsed(); @@ -1980,23 +1987,26 @@ const gfx::Rect& target_damage, int64_t display_trace_id) { DCHECK(!expected_display_time.is_null()); - - root_surface_id_ = surface_id; - Surface* surface = manager_->GetSurfaceForId(surface_id); - DCHECK(surface); DCHECK(contained_surfaces_.empty()); - CheckFrameSinksChanged(surface); + DCHECK(!is_inside_aggregate_); + is_inside_aggregate_ = true; + + root_surface_id_ = surface_id; // Start recording new stats for this aggregation. stats_.emplace(); base::ElapsedTimer prewalk_timer; - ResolvedFrameData* resolved_frame = - GetResolvedFrame(surface, /*inside_aggregation=*/true); + ResolvedFrameData* resolved_frame = GetResolvedFrame(surface_id); - if (!resolved_frame || !resolved_frame->is_valid()) + if (!resolved_frame || !resolved_frame->is_valid()) { + ResetAfterAggregate(); return {}; + } + + Surface* surface = resolved_frame->surface(); + CheckFrameSinksChanged(surface); display_trace_id_ = display_trace_id; expected_display_time_ = expected_display_time; @@ -2160,6 +2170,9 @@ } void SurfaceAggregator::ResetAfterAggregate() { + DCHECK(is_inside_aggregate_); + + is_inside_aggregate_ = false; dest_pass_list_ = nullptr; surface_damage_rect_list_ = nullptr; current_zero_damage_rect_is_not_recorded_ = false;
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h index f02785f..03482fd 100644 --- a/components/viz/service/display/surface_aggregator.h +++ b/components/viz/service/display/surface_aggregator.h
@@ -23,6 +23,7 @@ #include "components/viz/common/surfaces/surface_range.h" #include "components/viz/service/display/aggregated_frame.h" #include "components/viz/service/display/resolved_frame_data.h" +#include "components/viz/service/surfaces/surface_observer.h" #include "components/viz/service/viz_service_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/gfx/delegated_ink_metadata.h" @@ -37,7 +38,7 @@ struct MaskFilterInfoExt; -class VIZ_SERVICE_EXPORT SurfaceAggregator { +class VIZ_SERVICE_EXPORT SurfaceAggregator : public SurfaceObserver { public: using SurfaceIndexMap = base::flat_map<SurfaceId, uint64_t>; using FrameSinkIdMap = base::flat_map<FrameSinkId, LocalSurfaceId>; @@ -73,7 +74,7 @@ SurfaceAggregator(const SurfaceAggregator&) = delete; SurfaceAggregator& operator=(const SurfaceAggregator&) = delete; - ~SurfaceAggregator(); + ~SurfaceAggregator() override; // These constants are used for all time related metrics recorded in // SurfaceAggregator. @@ -96,7 +97,6 @@ // Aggregate() to make sure no CompositorFrame did arrive between the calls. const ResolvedFrameData* GetLatestFrameData(const SurfaceId& surface_id); - void ReleaseResources(const SurfaceId& surface_id); const SurfaceIndexMap& previous_contained_surfaces() const { return previous_contained_surfaces_; } @@ -135,13 +135,16 @@ base::TimeDelta declare_resources_time; }; + // SurfaceObserver implementation. + void OnSurfaceDestroyed(const SurfaceId& surface_id) override; + + void ReleaseResources(const SurfaceId& surface_id); + // Get resolved frame data for the resolved surfaces active frame. Returns // null if there is no matching surface or the surface doesn't have an active // CompositorFrame. ResolvedFrameData* GetResolvedFrame(const SurfaceRange& range); ResolvedFrameData* GetResolvedFrame(const SurfaceId& surface_id); - ResolvedFrameData* GetResolvedFrame(Surface* surface, - bool inside_aggregation); // - |source_pass| is the render pass that contains |surface_quad|. // - |target_transform| is the transform from the coordinate space of @@ -388,6 +391,9 @@ const ExtraPassForReadbackOption extra_pass_for_readback_option_; + // Will be true for duration of Aggregate() function. + bool is_inside_aggregate_ = false; + bool output_is_secure_ = false; // Whether |CopyOutputRequests| should be moved over to the aggregated frame. @@ -408,6 +414,9 @@ // The id for the optional render pass used to apply the display transform. AggregatedRenderPassId display_transform_render_pass_id_; + // Persistent storage for ResolvedFrameData. + std::map<SurfaceId, ResolvedFrameData> resolved_frames_; + base::flat_map<SurfaceId, int> surface_id_to_resource_child_id_; // The following state is only valid for the duration of one Aggregate call @@ -437,8 +446,8 @@ base::TimeTicks expected_display_time_; int64_t display_trace_id_ = -1; - // Map from SurfaceRange to Surface for current aggregation. - base::flat_map<SurfaceRange, Surface*> resolved_surface_ranges_; + // Map from SurfaceRange to SurfaceId for current aggregation. + base::flat_map<SurfaceRange, SurfaceId> resolved_surface_ranges_; // The root damage rect of the currently-aggregating frame. gfx::Rect root_damage_rect_; @@ -501,9 +510,6 @@ // by FindQuadWithOverlayDamage(). bool current_zero_damage_rect_is_not_recorded_ = false; - // Persistent storage for ResolvedFrameData. - std::map<Surface*, ResolvedFrameData> resolved_frames_; - // Used to generate new unique render pass ids in the aggregated namespace. AggregatedRenderPassId::Generator render_pass_id_generator_; };
diff --git a/components/webcrypto/BUILD.gn b/components/webcrypto/BUILD.gn index 40bbe75c..dd646f3 100644 --- a/components/webcrypto/BUILD.gn +++ b/components/webcrypto/BUILD.gn
@@ -26,7 +26,6 @@ "algorithms/ec.h", "algorithms/ecdh.cc", "algorithms/ecdsa.cc", - "algorithms/ed25519.cc", "algorithms/hkdf.cc", "algorithms/hmac.cc", "algorithms/pbkdf2.cc", @@ -42,7 +41,6 @@ "algorithms/sha.cc", "algorithms/util.cc", "algorithms/util.h", - "algorithms/x25519.cc", "blink_key_handle.cc", "blink_key_handle.h", "generate_key_result.cc",
diff --git a/components/webcrypto/algorithm_implementations.h b/components/webcrypto/algorithm_implementations.h index ed8ba2a..186256c 100644 --- a/components/webcrypto/algorithm_implementations.h +++ b/components/webcrypto/algorithm_implementations.h
@@ -27,8 +27,6 @@ std::unique_ptr<AlgorithmImplementation> CreateEcdhImplementation(); std::unique_ptr<AlgorithmImplementation> CreateHkdfImplementation(); std::unique_ptr<AlgorithmImplementation> CreatePbkdf2Implementation(); -std::unique_ptr<AlgorithmImplementation> CreateEd25519Implementation(); -std::unique_ptr<AlgorithmImplementation> CreateX25519Implementation(); } // namespace webcrypto
diff --git a/components/webcrypto/algorithm_registry.cc b/components/webcrypto/algorithm_registry.cc index 0095214..3ca6d3e 100644 --- a/components/webcrypto/algorithm_registry.cc +++ b/components/webcrypto/algorithm_registry.cc
@@ -30,9 +30,7 @@ ecdsa_(CreateEcdsaImplementation()), ecdh_(CreateEcdhImplementation()), hkdf_(CreateHkdfImplementation()), - pbkdf2_(CreatePbkdf2Implementation()), - ed25519_(CreateEd25519Implementation()), - x25519_(CreateX25519Implementation()) { + pbkdf2_(CreatePbkdf2Implementation()) { crypto::EnsureOpenSSLInit(); } @@ -68,10 +66,6 @@ return hkdf_.get(); case blink::kWebCryptoAlgorithmIdPbkdf2: return pbkdf2_.get(); - case blink::kWebCryptoAlgorithmIdEd25519: - return ed25519_.get(); - case blink::kWebCryptoAlgorithmIdX25519: - return x25519_.get(); default: return nullptr; } @@ -91,8 +85,6 @@ const std::unique_ptr<AlgorithmImplementation> ecdh_; const std::unique_ptr<AlgorithmImplementation> hkdf_; const std::unique_ptr<AlgorithmImplementation> pbkdf2_; - const std::unique_ptr<AlgorithmImplementation> ed25519_; - const std::unique_ptr<AlgorithmImplementation> x25519_; }; } // namespace
diff --git a/components/webcrypto/algorithms/ed25519.cc b/components/webcrypto/algorithms/ed25519.cc deleted file mode 100644 index 9b88fed..0000000 --- a/components/webcrypto/algorithms/ed25519.cc +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/webcrypto/algorithm_implementation.h" -#include "components/webcrypto/status.h" - -namespace webcrypto { - -namespace { - -// This class implements the Ed25519 algorithm, which is a particular parameter -// choice for the EdDSA algorithm specified by RFC 8032. The underlying curve -// used by Ed25519 is equivalent to Curve25519 specified by RFC 7748. -// -// TODO(crbug.com/1032821): See also -// https://chromestatus.com/feature/4913922408710144. -class Ed25519Implementation : public AlgorithmImplementation { - public: - Status Sign(const blink::WebCryptoAlgorithm& algorithm, - const blink::WebCryptoKey& key, - base::span<const uint8_t> data, - std::vector<uint8_t>* buffer) const override { - // TODO(crbug.com/1032821): Implement this. - return Status::ErrorUnsupported(); - } - - Status Verify(const blink::WebCryptoAlgorithm& algorithm, - const blink::WebCryptoKey& key, - base::span<const uint8_t> signature, - base::span<const uint8_t> data, - bool* signature_match) const override { - // TODO(crbug.com/1032821): Implement this. - return Status::ErrorUnsupported(); - } -}; - -} // namespace - -std::unique_ptr<AlgorithmImplementation> CreateEd25519Implementation() { - return std::make_unique<Ed25519Implementation>(); -} - -} // namespace webcrypto
diff --git a/components/webcrypto/algorithms/x25519.cc b/components/webcrypto/algorithms/x25519.cc deleted file mode 100644 index aba892e..0000000 --- a/components/webcrypto/algorithms/x25519.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/webcrypto/algorithm_implementation.h" -#include "components/webcrypto/status.h" - -namespace webcrypto { - -namespace { - -// This class implements the key agreement algorithm using the X25519 function -// based on Curve25519 specified by RFC 7748, to which is also referred as the -// X25519 algorithm by RFC 8410. -// -// TODO(crbug.com/1032821): See also -// https://chromestatus.com/feature/4913922408710144. -class X25519Implementation : public AlgorithmImplementation { - public: - Status DeriveBits(const blink::WebCryptoAlgorithm& algorithm, - const blink::WebCryptoKey& base_key, - bool has_optional_length_bits, - unsigned int optional_length_bits, - std::vector<uint8_t>* derived_bytes) const override { - // TODO(crbug.com/1032821): Implement this. - return Status::ErrorUnsupported(); - } -}; - -} // namespace - -std::unique_ptr<AlgorithmImplementation> CreateX25519Implementation() { - return std::make_unique<X25519Implementation>(); -} - -} // namespace webcrypto
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc index 647347d3..fd80b02 100644 --- a/content/browser/cross_origin_opener_policy_browsertest.cc +++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -3515,6 +3515,126 @@ EXPECT_EQ(true, EvalJs(iframe_rfh, "parent.opener == null")); } +// Check whether not using COOP causes a RenderProcessHost change during +// same-origin navigations. This is a control test for the subsequent tests. +IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest, + Process_CoopUnsafeNone_SameOrigin) { + GURL url_1(https_server()->GetURL("a.test", "/empty.html?1")); + GURL url_2(https_server()->GetURL("a.test", "/empty.html?2")); + GURL url_3(https_server()->GetURL("a.test", "/empty.html?3")); + + EXPECT_TRUE(NavigateToURL(shell(), url_1)); + int rph_id_1 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_2)); + int rph_id_2 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_3)); + int rph_id_3 = current_frame_host()->GetProcess()->GetID(); + + EXPECT_EQ(rph_id_1, rph_id_2); + EXPECT_EQ(rph_id_2, rph_id_3); + EXPECT_EQ(rph_id_3, rph_id_1); +} + +// Check whether using COOP causes a RenderProcessHost change during +// same-origin navigations. +IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest, + Process_CoopSameOrigin_SameOrigin) { + GURL url_1(https_server()->GetURL( + "a.test", "/set-header?Cross-Origin-Opener-Policy: same-origin&1")); + GURL url_2(https_server()->GetURL( + "a.test", "/set-header?Cross-Origin-Opener-Policy: same-origin&2")); + GURL url_3(https_server()->GetURL( + "a.test", "/set-header?Cross-Origin-Opener-Policy: same-origin&3")); + + EXPECT_TRUE(NavigateToURL(shell(), url_1)); + int rph_id_1 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_2)); + int rph_id_2 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_3)); + int rph_id_3 = current_frame_host()->GetProcess()->GetID(); + + EXPECT_EQ(rph_id_1, rph_id_2); + EXPECT_EQ(rph_id_2, rph_id_3); + EXPECT_EQ(rph_id_3, rph_id_1); +} + +// Check whether COOP causes a RenderProcessHost change during same-origin +// navigations. +IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest, + Process_CoopAlternate_SameOrigin) { + GURL url_1(https_server()->GetURL("a.test", "/empty.html")); + GURL url_2(https_server()->GetURL( + "a.test", "/set-header?Cross-Origin-Opener-Policy: same-origin")); + GURL url_3(https_server()->GetURL("a.test", "/empty.html")); + + EXPECT_TRUE(NavigateToURL(shell(), url_1)); + int rph_id_1 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_2)); + int rph_id_2 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_3)); + int rph_id_3 = current_frame_host()->GetProcess()->GetID(); + + if (!SiteIsolationPolicy::IsSiteIsolationForCOOPEnabled() && + IsBackForwardCacheEnabled()) { + EXPECT_EQ(rph_id_1, rph_id_2); + EXPECT_EQ(rph_id_2, rph_id_3); + EXPECT_EQ(rph_id_3, rph_id_1); + } else { + EXPECT_NE(rph_id_1, rph_id_2); + EXPECT_NE(rph_id_2, rph_id_3); + EXPECT_NE(rph_id_3, rph_id_1); + } +} + +// Check whether COOP causes a RenderProcessHost change during same-site +// navigations. +IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest, + Process_CoopAlternate_SameSite) { + GURL url_1(https_server()->GetURL("a.a.test", "/empty.html")); + GURL url_2(https_server()->GetURL( + "b.a.test", "/set-header?Cross-Origin-Opener-Policy: same-origin")); + GURL url_3(https_server()->GetURL("c.a.test", "/empty.html")); + + EXPECT_TRUE(NavigateToURL(shell(), url_1)); + int rph_id_1 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_2)); + int rph_id_2 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_3)); + int rph_id_3 = current_frame_host()->GetProcess()->GetID(); + + if (!SiteIsolationPolicy::IsSiteIsolationForCOOPEnabled() && + IsBackForwardCacheEnabled()) { + EXPECT_EQ(rph_id_1, rph_id_2); + EXPECT_EQ(rph_id_2, rph_id_3); + EXPECT_EQ(rph_id_3, rph_id_1); + } else { + EXPECT_NE(rph_id_1, rph_id_2); + EXPECT_NE(rph_id_2, rph_id_3); + EXPECT_NE(rph_id_3, rph_id_1); + } +} + +// Check whether COOP causes a RenderProcessHost change during cross-origin +// navigations. +IN_PROC_BROWSER_TEST_P(CrossOriginOpenerPolicyBrowserTest, + Process_CoopSameOrigin_CrossOrigin) { + GURL url_1(https_server()->GetURL("a.test", "/empty.html")); + GURL url_2(https_server()->GetURL( + "b.test", "/set-header?Cross-Origin-Opener-Policy: same-origin")); + GURL url_3(https_server()->GetURL("c.test", "/empty.html")); + + EXPECT_TRUE(NavigateToURL(shell(), url_1)); + int rph_id_1 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_2)); + int rph_id_2 = current_frame_host()->GetProcess()->GetID(); + EXPECT_TRUE(NavigateToURL(shell(), url_3)); + int rph_id_3 = current_frame_host()->GetProcess()->GetID(); + + EXPECT_NE(rph_id_1, rph_id_2); + EXPECT_NE(rph_id_2, rph_id_3); + EXPECT_NE(rph_id_3, rph_id_1); +} + // TODO(https://crbug.com/1101339). Test inheritance of the virtual browsing // context group when using window.open from an iframe, same-origin and // cross-origin.
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index 2f4ddf6..3c459969 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -194,6 +194,13 @@ void BrowserCompositorMac::SetRenderWidgetHostIsHidden(bool hidden) { render_widget_host_is_hidden_ = hidden; UpdateState(); + if (state_ == UseParentLayerCompositor) { + // UpdateState might not call WasShown when showing a frame using the same + // ParentLayerCompositor, since it returns early on a no-op state + // transition. + delegated_frame_host_->WasShown(GetRendererLocalSurfaceId(), dfh_size_dip_, + {} /* record_tab_switch_time_request */); + } } void BrowserCompositorMac::SetViewVisible(bool visible) {
diff --git a/docs/vscode.md b/docs/vscode.md index c9ba6e5..2d0fb14 100644 --- a/docs/vscode.md +++ b/docs/vscode.md
@@ -88,6 +88,8 @@ `editor.formatOnSave` setting). * ***Python*** - Linting, intellisense, code formatting, refactoring, debugging, snippets. + * If you want type checking, add: `"python.analysis.typeCheckingMode": "basic",` + to your `settings.json` file (you can also find it in the settings UI). * ***Toggle Header/Source*** - Toggles between .cc and .h with `F4`. The C/C++ extension supports this as well through `Alt+O` but sometimes chooses the wrong file when there are
diff --git a/fuchsia/runners/cast/cast_runner.cml b/fuchsia/runners/cast/cast_runner.cml index 184963c..2359fd1 100644 --- a/fuchsia/runners/cast/cast_runner.cml +++ b/fuchsia/runners/cast/cast_runner.cml
@@ -14,6 +14,8 @@ capabilities: [ { protocol: [ + "chromium.cast.DataReset", + "fuchsia.web.FrameHost", "fuchsia.sys.Runner", ] } @@ -21,6 +23,8 @@ expose: [ { protocol: [ + "chromium.cast.DataReset", + "fuchsia.web.FrameHost", "fuchsia.sys.Runner", ], from: "self",
diff --git a/google_apis/gaia/gaia_constants.cc b/google_apis/gaia/gaia_constants.cc index f8ac94e..680155b 100644 --- a/google_apis/gaia/gaia_constants.cc +++ b/google_apis/gaia/gaia_constants.cc
@@ -15,14 +15,6 @@ // Service name for Gaia. Used to convert to cookie auth. const char kGaiaService[] = "gaia"; -// Service name for Picasa API. API is used to get user's image. -const char kPicasaService[] = "lh2"; - -// Service/scope names for sync. -const char kSyncService[] = "chromiumsync"; - -// Service name for remoting. -const char kRemotingService[] = "chromoting"; // OAuth scopes. const char kOAuth1LoginScope[] = "https://www.google.com/accounts/OAuthLogin"; @@ -175,7 +167,6 @@ const char kGaiaOAuthToken[] = "oauthToken"; const char kGaiaOAuthSecret[] = "oauthSecret"; const char kGaiaOAuthDuration[] = "3600"; -const char kGaiaOAuth2LoginRefreshToken[] = "oauth2LoginRefreshToken"; // Used to construct a channel ID for push messaging. const char kObfuscatedGaiaId[] = "obfuscatedGaiaId";
diff --git a/google_apis/gaia/gaia_constants.h b/google_apis/gaia/gaia_constants.h index 3561a9c1..75c8e888 100644 --- a/google_apis/gaia/gaia_constants.h +++ b/google_apis/gaia/gaia_constants.h
@@ -18,9 +18,6 @@ // Gaia services for requesting extern const char kGaiaService[]; // uber token -extern const char kPicasaService[]; -extern const char kSyncService[]; -extern const char kRemotingService[]; // OAuth2 scopes. extern const char kOAuth1LoginScope[]; @@ -70,7 +67,6 @@ extern const char kGaiaOAuthToken[]; extern const char kGaiaOAuthSecret[]; extern const char kGaiaOAuthDuration[]; -extern const char kGaiaOAuth2LoginRefreshToken[]; // Used to construct a channel ID for push messaging. extern const char kObfuscatedGaiaId[];
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc index 684e1c8..cf06cb6 100644 --- a/gpu/config/gpu_finch_features.cc +++ b/gpu/config/gpu_finch_features.cc
@@ -246,7 +246,7 @@ const base::FeatureParam<std::string> kVulkanBlockListByBoard{ &kVulkan, "BlockListByBoard", - "RM67*|RM68*|k68*|mt67*|oppo67*|oppo68*|QM215|rk30sdk"}; + "RM67*|RM68*|k68*|mt6*|oppo67*|oppo68*|QM215|rk30sdk"}; const base::FeatureParam<std::string> kVulkanBlockListByAndroidBuildFP{ &kVulkan, "BlockListByAndroidBuildFP", ""};
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 8b6ee7c..3c1ec86b 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -948,6 +948,9 @@ flag_descriptions::kContentSuggestionsUIModuleRefreshName, flag_descriptions::kContentSuggestionsUIModuleRefreshDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kContentSuggestionsUIModuleRefresh)}, + {"3p-intents-in-incognito", flag_descriptions::kIOS3PIntentsInIncognitoName, + flag_descriptions::kIOS3PIntentsInIncognitoDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(kIOS3PIntentsInIncognito)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index b495ad7..04fe0ffe 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -348,6 +348,11 @@ "an individual promotion causes that promotion but no other promotions to " "occur."; +const char kIOS3PIntentsInIncognitoName[] = "Third-party intents in Incognito"; +const char kIOS3PIntentsInIncognitoDescription[] = + "When enabled, an additional setting lets the user open links from other " + "apps in Incognito."; + const char kIOSEnablePasswordManagerBrandingUpdateName[] = "Enable new Google Password Manager branding"; const char kIOSEnablePasswordManagerBrandingUpdateDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index e032694..dde4561 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -309,6 +309,11 @@ extern const char kInProductHelpDemoModeName[]; extern const char kInProductHelpDemoModeDescription[]; +// Title and description for the flag to enable third-party intents in +// Incognito. +extern const char kIOS3PIntentsInIncognitoName[]; +extern const char kIOS3PIntentsInIncognitoDescription[]; + // Title and description for the flag to enable updated password manager // branding. extern const char kIOSEnablePasswordManagerBrandingUpdateName[];
diff --git a/ios/chrome/browser/pref_names.cc b/ios/chrome/browser/pref_names.cc index 0a2b657..c7585a3 100644 --- a/ios/chrome/browser/pref_names.cc +++ b/ios/chrome/browser/pref_names.cc
@@ -62,6 +62,11 @@ // 2 - Forced. All pages/sessions are forced into Incognito. const char kIncognitoModeAvailability[] = "incognito.mode_availability"; +// Boolean that is true when the Incognito interstitial for third-party intents +// is enabled. +const char kIncognitoInterstitialEnabled[] = + "ios.settings.incognito_interstitial_enabled"; + // Caches the folder id of user's position in the bookmark hierarchy navigator. const char kIosBookmarkCachedFolderId[] = "ios.bookmark.cached_folder_id";
diff --git a/ios/chrome/browser/pref_names.h b/ios/chrome/browser/pref_names.h index be450c7..acdbdaa 100644 --- a/ios/chrome/browser/pref_names.h +++ b/ios/chrome/browser/pref_names.h
@@ -21,6 +21,7 @@ extern const char kEnableDoNotTrack[]; extern const char kHttpServerProperties[]; extern const char kIncognitoModeAvailability[]; +extern const char kIncognitoInterstitialEnabled[]; extern const char kIosBookmarkCachedFolderId[]; extern const char kIosBookmarkCachedTopMostRow[]; extern const char kIosBookmarkFolderDefault[];
diff --git a/ios/chrome/browser/prefs/BUILD.gn b/ios/chrome/browser/prefs/BUILD.gn index 0fc1613..cfcbb33d 100644 --- a/ios/chrome/browser/prefs/BUILD.gn +++ b/ios/chrome/browser/prefs/BUILD.gn
@@ -81,6 +81,7 @@ "//ios/chrome/browser/policy:policy_util", "//ios/chrome/browser/prerender:prerender_pref", "//ios/chrome/browser/signin", + "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/authentication/signin", "//ios/chrome/browser/ui/bookmarks:constants",
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index 27a5219c..5abaf059 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -74,6 +74,7 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h" #include "ios/chrome/browser/ui/first_run/fre_field_trial.h" #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h" +#import "ios/chrome/browser/ui/ui_feature_flags.h" #include "ios/chrome/browser/voice/voice_search_prefs_registration.h" #import "ios/chrome/browser/web/font_size/font_size_tab_helper.h" #import "ios/web/common/features.h" @@ -345,6 +346,12 @@ registry->RegisterBooleanPref(prefs::kHttpsOnlyModeEnabled, false); + // Register pref storing whether the Incognito interstitial for third-party + // intents is enabled. + if (base::FeatureList::IsEnabled(kIOS3PIntentsInIncognito)) { + registry->RegisterBooleanPref(prefs::kIncognitoInterstitialEnabled, false); + } + // Register pref used to determine whether the User Policy notification was // already shown. registry->RegisterBooleanPref(
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc index 7fce2e0..ba210c1 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.cc +++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -30,6 +30,9 @@ const base::Feature kIncognitoNtpRevamp{"IncognitoNtpRevamp", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kIOS3PIntentsInIncognito{"kIOS3pIntentsInIncognito", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kDefaultBrowserFullscreenPromoExperiment{ "DefaultBrowserFullscreenPromoExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h index ce7097e..dfad6743 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.h +++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -37,6 +37,9 @@ // Feature flag to enable revamped Incognito NTP page. extern const base::Feature kIncognitoNtpRevamp; +// Feature flag to enable third-party intents in Incognito. +extern const base::Feature kIOS3PIntentsInIncognito; + // Feature flag that experiments with the default browser fullscreen promo UI. extern const base::Feature kDefaultBrowserFullscreenPromoExperiment;
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 023b6628..5f816ba5 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -4eeded0b4ce0ac50ec1264b0d9afe03228c09182 \ No newline at end of file +02c756e9b50ec56c9a3d00ee17d735b57695955e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 414686d..f69b908a 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -a42b79e7da78f126d44f9eb364b37ce4ce35a986 \ No newline at end of file +a0a9fda72f4a19815b06c8fc996921ad7a8bea4f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 4a18784..337dd02 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -2e251449db311f24a1cea7d24dbb60acbf90383d \ No newline at end of file +edec3dbec2c7c33ad90616f5ff100ca423e5b58b \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index 83f910ca..1937b7a 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -fb899520360fe504d1443dd4190da4c9342adaa2 \ No newline at end of file +cfa959bcaf3a44e7568507d5cfbd482f64d55fb8 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index 8af8e3c..69b9ebce 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -cb43561f62e08f16a6a6024ae4de2ff4fc2a5c9f \ No newline at end of file +e40954173493c7a1be91e5225d7a0ee1af8487a5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index 1b38f38..5ad5946 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -06ff62a0123a766a1dc3096ca8bf2272be84f7ed \ No newline at end of file +a45f0f2864fe5a1ff5c69947a09152befb61e559 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index d940d70..0aead53 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -7066e294ea277904bbc8a2b88faecfd400a36270 \ No newline at end of file +8e8d7cf0c6b33b0d891a11e8ad1203bb8fc5074e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 88b2668..e9347378 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -d24995eaeb8613e7692001d43a9ec01df06cb60c \ No newline at end of file +b1584a5db43609ee4725cd61c2d2fe2664bc80fc \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index d66dad0..c3f9aae 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -afd7adc0125c5f65fc11fdcc9d69e55f935e7008 \ No newline at end of file +2d1d7bafafae33131f23f05a2e2041f40661818c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index f46905d..40de4d9 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -768359bd58afc3bda7d25db6b7711c8aacb5bf1a \ No newline at end of file +ca6dbbf828a86fe0dffbd9e34379f3a57807cf15 \ No newline at end of file
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index c6f7a6e3..50a2d92 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5865,21 +5865,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5092.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -5892,7 +5892,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "isolate_profile_data": true, @@ -6030,21 +6030,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -6056,7 +6056,7 @@ }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "args": [ @@ -6176,21 +6176,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -6202,7 +6202,7 @@ }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 34d2ce66c..bdb33b50 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -88037,21 +88037,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5092.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -88059,7 +88059,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "isolate_profile_data": true, @@ -88172,28 +88172,28 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "args": [ @@ -88293,28 +88293,28 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "isolate_profile_data": true, @@ -89652,20 +89652,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5092.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -89679,7 +89679,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "merge": { @@ -89817,20 +89817,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -89843,7 +89843,7 @@ }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "args": [ @@ -89963,20 +89963,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -89989,7 +89989,7 @@ }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "merge": { @@ -91485,20 +91485,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5092.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -91512,7 +91512,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "merge": { @@ -91650,20 +91650,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -91676,7 +91676,7 @@ }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "args": [ @@ -91796,20 +91796,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5092.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -91822,7 +91822,7 @@ }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" }, { "merge": { @@ -92557,20 +92557,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5092.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5093.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5092.0", - "revision": "version:104.0.5092.0" + "location": "lacros_version_skew_tests_v104.0.5093.0", + "revision": "version:104.0.5093.0" } ], "dimension_sets": [ @@ -92583,7 +92583,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5092.0" + "variant_id": "Lacros version skew testing ash 104.0.5093.0" } ] },
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 280fe840..9088d61 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -5618,8 +5618,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7236,8 +7236,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7266,8 +7266,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7294,8 +7294,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7320,8 +7320,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7344,8 +7344,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7382,8 +7382,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7418,8 +7418,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7454,8 +7454,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7494,8 +7494,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7539,8 +7539,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7575,8 +7575,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7620,8 +7620,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7657,8 +7657,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7693,8 +7693,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7731,8 +7731,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600, @@ -7769,8 +7769,8 @@ "dimension_sets": [ { "gpu": "1002:7340", - "os": "Ubuntu", - "pool": "chromium.tests.gpu.experimental" + "os": "Ubuntu-18.04.6", + "pool": "chromium.tests.gpu" } ], "expiration": 21600,
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 680e908..13c4979b 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -659,8 +659,8 @@ 'swarming': { 'dimensions': { 'gpu': '1002:7340', - 'os': 'Ubuntu', - 'pool': 'chromium.tests.gpu.experimental', + 'os': 'Ubuntu-18.04.6', + 'pool': 'chromium.tests.gpu', }, }, },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 44062a2a..602626b 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5092.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5093.0/test_ash_chrome', ], - 'identifier': 'Lacros version skew testing ash 104.0.5092.0', + 'identifier': 'Lacros version skew testing ash 104.0.5093.0', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v104.0.5092.0', - 'revision': 'version:104.0.5092.0', + 'location': 'lacros_version_skew_tests_v104.0.5093.0', + 'revision': 'version:104.0.5093.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 8bc8614..030493d 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -68,6 +68,29 @@ ] } ], + "AlignWakeUps": [ + { + "platforms": [ + "android", + "android_weblayer", + "android_webview", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AlignWakeUps", + "ExplicitHighResolutionTimerWin" + ] + } + ] + } + ], "AllowHistoryDeletionForChildAccounts": [ { "platforms": [ @@ -1070,6 +1093,28 @@ ] } ], + "AutofillFixServerQueriesIfPasswordManagerIsEnabled": [ + { + "platforms": [ + "android", + "android_webview", + "chromeos", + "chromeos_lacros", + "ios", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillFixServerQueriesIfPasswordManagerIsEnabled" + ] + } + ] + } + ], "AutofillIgnoreAutocompleteForImport": [ { "platforms": [ @@ -4034,7 +4079,7 @@ { "name": "Enabled", "params": { - "strategy": "exponential-wakeups" + "strategy": "greedy-wakeups" }, "enable_features": [ "WakeUpStrategyFeature"
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index 1cec4d25..5c7349a1 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3568,6 +3568,10 @@ kV8MathMLElement_Focusgroup_AttributeSetter = 4247, kV8SVGElement_Focusgroup_AttributeGetter = 4248, kV8SVGElement_Focusgroup_AttributeSetter = 4249, + kCSSLegacyPerspectiveOrigin = 4250, + kCSSLegacyTransformOrigin = 4251, + kCSSLegacyBorderImage = 4252, + kCSSLegacyBorderImageWidth = 4253, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_crypto_algorithm.h b/third_party/blink/public/platform/web_crypto_algorithm.h index 297790f1..fce77bc 100644 --- a/third_party/blink/public/platform/web_crypto_algorithm.h +++ b/third_party/blink/public/platform/web_crypto_algorithm.h
@@ -72,10 +72,8 @@ kWebCryptoAlgorithmIdEcdh, kWebCryptoAlgorithmIdHkdf, kWebCryptoAlgorithmIdPbkdf2, - kWebCryptoAlgorithmIdEd25519, - kWebCryptoAlgorithmIdX25519, #if INSIDE_BLINK - kWebCryptoAlgorithmIdLast = kWebCryptoAlgorithmIdX25519, + kWebCryptoAlgorithmIdLast = kWebCryptoAlgorithmIdPbkdf2, #endif }; @@ -107,8 +105,6 @@ kWebCryptoAlgorithmParamsTypeAesDerivedKeyParams, kWebCryptoAlgorithmParamsTypeHkdfParams, kWebCryptoAlgorithmParamsTypePbkdf2Params, - kWebCryptoAlgorithmParamsTypeEd25519Params, - kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams, }; struct WebCryptoAlgorithmInfo { @@ -142,8 +138,6 @@ class WebCryptoAesDerivedKeyParams; class WebCryptoHkdfParams; class WebCryptoPbkdf2Params; -class WebCryptoEd25519Params; -class WebCryptoX25519KeyDeriveParams; class WebCryptoAlgorithmParams; class WebCryptoAlgorithmPrivate; @@ -215,9 +209,6 @@ AesDerivedKeyParams() const; BLINK_PLATFORM_EXPORT const WebCryptoHkdfParams* HkdfParams() const; BLINK_PLATFORM_EXPORT const WebCryptoPbkdf2Params* Pbkdf2Params() const; - BLINK_PLATFORM_EXPORT const WebCryptoEd25519Params* Ed25519Params() const; - BLINK_PLATFORM_EXPORT const WebCryptoX25519KeyDeriveParams* - X25519KeyDeriveParams() const; // Returns true if the provided algorithm ID is for a hash (in other words, // SHA-*)
diff --git a/third_party/blink/public/platform/web_crypto_algorithm_params.h b/third_party/blink/public/platform/web_crypto_algorithm_params.h index 1a0fbb1a..5f14604 100644 --- a/third_party/blink/public/platform/web_crypto_algorithm_params.h +++ b/third_party/blink/public/platform/web_crypto_algorithm_params.h
@@ -415,31 +415,6 @@ const unsigned iterations_; }; -class WebCryptoEd25519Params : public WebCryptoAlgorithmParamsWithHash { - public: - explicit WebCryptoEd25519Params(const WebCryptoAlgorithm& hash) - : WebCryptoAlgorithmParamsWithHash(hash) {} - - WebCryptoAlgorithmParamsType GetType() const override { - return kWebCryptoAlgorithmParamsTypeEd25519Params; - } -}; - -class WebCryptoX25519KeyDeriveParams : public WebCryptoAlgorithmParams { - public: - explicit WebCryptoX25519KeyDeriveParams(const WebCryptoKey& public_key) - : public_key_(public_key) {} - - WebCryptoAlgorithmParamsType GetType() const override { - return kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams; - } - - const WebCryptoKey& PublicKey() const { return public_key_; } - - private: - const WebCryptoKey public_key_; -}; - } // namespace blink #endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CRYPTO_ALGORITHM_PARAMS_H_
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc index 70d916c..ef8b9f1 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -277,10 +277,6 @@ return kHkdfTag; case kWebCryptoAlgorithmIdPbkdf2: return kPbkdf2Tag; - // TODO(crbug.com/1032821): Handle them explicitly for Lint. - case kWebCryptoAlgorithmIdEd25519: - case kWebCryptoAlgorithmIdX25519: - return 0; } NOTREACHED() << "Unknown algorithm ID " << id; return 0;
diff --git a/third_party/blink/renderer/core/css/resolver/cascade_resolver.h b/third_party/blink/renderer/core/css/resolver/cascade_resolver.h index 5c16666..f092648a 100644 --- a/third_party/blink/renderer/core/css/resolver/cascade_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/cascade_resolver.h
@@ -50,6 +50,13 @@ // https://drafts.csswg.org/css-variables/#animation-tainted bool AllowSubstitution(CSSVariableData*) const; + bool Rejects(const CSSProperty& property) { + if (!filter_.Rejects(property)) + return false; + rejected_flags_ |= property.GetFlags(); + return true; + } + // Collects CSSProperty::Flags from the given property. The Flags() function // can then be used to see which flags have been observed.. void CollectFlags(const CSSProperty& property, CascadeOrigin origin) { @@ -63,6 +70,9 @@ // Like Flags, but for the author origin only. CSSProperty::Flags AuthorFlags() const { return author_flags_; } + // The CSSProperty::Flags of all properties rejected by the CascadeFilter. + CSSProperty::Flags RejectedFlags() const { return rejected_flags_; } + // Automatically locks and unlocks the given property. (See // CascadeResolver::IsLocked). class CORE_EXPORT AutoLock { @@ -113,6 +123,7 @@ const uint8_t generation_ = 0; CSSProperty::Flags author_flags_ = 0; CSSProperty::Flags flags_ = 0; + CSSProperty::Flags rejected_flags_ = 0; // A very simple cache for CSSPendingSubstitutionValues. We cache only the // most recently parsed CSSPendingSubstitutionValue, such that consecutive
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 ecce7dc1..86352e5 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -250,6 +250,8 @@ if (resolver.Flags() & CSSProperty::kAnimation) state_.SetCanAffectAnimations(); + if (resolver.RejectedFlags() & CSSProperty::kLegacyOverlapping) + state_.SetRejectedLegacyOverlapping(); } std::unique_ptr<CSSBitset> StyleCascade::GetImportantSet() { @@ -505,9 +507,6 @@ // in a second phase so that we know which ones actually won the cascade // before we start applying, as some properties can affect others. void StyleCascade::ApplyMatchResult(CascadeResolver& resolver) { - // We only need to apply the resolver part of the filter here; - // the rest have been applied in the previous pass. - CascadeFilter filter = resolver.filter_; for (CSSPropertyID id : map_.NativeBitset()) { CascadePriority* p = map_.FindKnownToExist(id); const CascadePriority priority = *p; @@ -522,7 +521,7 @@ } const CSSProperty& property = CSSProperty::Get(id); - if (filter.Rejects(property)) { + if (resolver.Rejects(property)) { continue; } LookupAndApplyDeclaration(property, p, resolver); @@ -539,7 +538,7 @@ } CustomProperty property(name.ToAtomicString(), GetDocument()); - if (filter.Rejects(property)) { + if (resolver.Rejects(property)) { continue; } LookupAndApplyDeclaration(property, p, resolver); @@ -566,7 +565,7 @@ priority = CascadePriority(priority, resolver.generation_); CSSPropertyRef ref(name, GetDocument()); - if (resolver.filter_.Rejects(ref.GetProperty())) + if (resolver.Rejects(ref.GetProperty())) continue; const CSSProperty& property = ResolveSurrogate(ref.GetProperty()); @@ -636,7 +635,7 @@ if (!priority) return; - if (resolver.filter_.Rejects(property)) + if (resolver.Rejects(property)) return; LookupAndApplyValue(property, priority, resolver);
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 6a5e96c..baea574 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -273,6 +273,23 @@ return collector ? collector->GetPseudoId() : kPseudoIdNone; } +void UseCountLegacyOverlapping(Document& document, + const ComputedStyle& a, + const ComputedStyle& b) { + if (a.PerspectiveOrigin() != b.PerspectiveOrigin()) + document.CountUse(WebFeature::kCSSLegacyPerspectiveOrigin); + if (a.GetTransformOrigin() != b.GetTransformOrigin()) + document.CountUse(WebFeature::kCSSLegacyTransformOrigin); + if (a.BorderImage() != b.BorderImage()) + document.CountUse(WebFeature::kCSSLegacyBorderImage); + if ((a.BorderTopWidth() != b.BorderTopWidth()) || + (a.BorderRightWidth() != b.BorderRightWidth()) || + (a.BorderBottomWidth() != b.BorderBottomWidth()) || + (a.BorderLeftWidth() != b.BorderLeftWidth())) { + document.CountUse(WebFeature::kCSSLegacyBorderImageWidth); + } +} + } // namespace static CSSPropertyValueSet* LeftToRightDeclaration() { @@ -2002,12 +2019,30 @@ if (cache_success.IsFullCacheHit()) return; - if (cache_success.ShouldApplyInheritedOnly()) { - cascade.Apply(CascadeFilter(CSSProperty::kInherited, false)); - if (!cache_success.IsUsableAfterApplyInheritedOnly(state.StyleRef())) - cascade.Apply(CascadeFilter(CSSProperty::kInherited, true)); - } else { - cascade.Apply(); + auto apply = [&state, &cascade, &cache_success](CascadeFilter filter) { + if (cache_success.ShouldApplyInheritedOnly()) { + cascade.Apply(filter.Add(CSSProperty::kInherited, false)); + if (!cache_success.IsUsableAfterApplyInheritedOnly(state.StyleRef())) + cascade.Apply(filter.Add(CSSProperty::kInherited, true)); + } else { + cascade.Apply(filter); + } + }; + + // In order to use-count whether or not legacy overlapping properties + // made a real difference to the ComputedStyle, we first apply the cascade + // while filtering out such properties. If the filter did reject + // any legacy overlapping properties, we apply all overlapping properties + // again to get the correct result. + apply(CascadeFilter(CSSProperty::kLegacyOverlapping, true)); + + if (state.RejectedLegacyOverlapping()) { + scoped_refptr<ComputedStyle> non_legacy_style = + ComputedStyle::Clone(state.StyleRef()); + // Re-apply all overlapping properties (both legacy and non-legacy). + apply(CascadeFilter(CSSProperty::kOverlapping, false)); + UseCountLegacyOverlapping(GetDocument(), *non_legacy_style, + state.StyleRef()); } MaybeAddToMatchedPropertiesCache(state, cache_success, result);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h index dd77e27c..865ddea 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
@@ -185,6 +185,11 @@ } void SetAffectsCompositorSnapshots() { affects_compositor_snapshots_ = true; } + bool RejectedLegacyOverlapping() const { + return rejected_legacy_overlapping_; + } + void SetRejectedLegacyOverlapping() { rejected_legacy_overlapping_ = true; } + private: void UpdateLengthConversionData(); CSSToLengthConversionData UnzoomedLengthConversionData( @@ -236,6 +241,10 @@ // True if snapshots of composited keyframes require re-validation. bool affects_compositor_snapshots_ = false; + + // True if the cascade rejected any properties with the kLegacyOverlapping + // flag. + bool rejected_legacy_overlapping_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc index ae79b99..c8e5128 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -63,6 +63,10 @@ GetDocument().GetStyleEngine().GetStyleResolver().MatchAllRules( state, collector, false /* include_smil_properties */); } + + bool IsUseCounted(mojom::WebFeature feature) { + return GetDocument().IsUseCounted(feature); + } }; class StyleResolverTestCQ : public StyleResolverTest, @@ -2176,4 +2180,343 @@ << "Check that it is in fact the empty rule"; } +TEST_F(StyleResolverTest, LegacyOverlapPerspectiveOrigin_Single) { + SetBodyInnerHTML(R"HTML( + <style> + div { + perspective-origin: 1px 2px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyPerspectiveOrigin)) + << "Not counted when only perspective-origin is used"; +} + +TEST_F(StyleResolverTest, LegacyOverlapPerspectiveOrigin_Order) { + SetBodyInnerHTML(R"HTML( + <style> + div { + -webkit-perspective-origin-x: 1px; + -webkit-perspective-origin-y: 2px; + perspective-origin: 3px 4px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyPerspectiveOrigin)) + << "Not counted when perspective-origin is last"; +} + +TEST_F(StyleResolverTest, LegacyOverlapPerspectiveOrigin_Values) { + SetBodyInnerHTML(R"HTML( + <style> + div { + perspective-origin: 1px 2px; + -webkit-perspective-origin-x: 1px; + -webkit-perspective-origin-y: 2px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyPerspectiveOrigin)) + << "Not counted when values are the same"; +} + +TEST_F(StyleResolverTest, LegacyOverlapPerspectiveOrigin_Last) { + SetBodyInnerHTML(R"HTML( + <style> + div { + perspective-origin: 1px 2px; + -webkit-perspective-origin-x: 3px; + -webkit-perspective-origin-y: 4px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyPerspectiveOrigin)) + << "Counted when -webkit-perspective-* is last with different values"; +} + +TEST_F(StyleResolverTest, LegacyOverlapTransformOrigin_Single) { + SetBodyInnerHTML(R"HTML( + <style> + div { + transform-origin: 1px 2px 3px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyTransformOrigin)) + << "Not counted when only transform-origin is used"; +} + +TEST_F(StyleResolverTest, LegacyOverlapTransformOrigin_Order) { + SetBodyInnerHTML(R"HTML( + <style> + div { + -webkit-transform-origin-x: 1px; + -webkit-transform-origin-y: 2px; + -webkit-transform-origin-z: 3px; + transform-origin: 4px 5px 6px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyTransformOrigin)) + << "Not counted when transform-origin is last"; +} + +TEST_F(StyleResolverTest, LegacyOverlapTransformOrigin_Values) { + SetBodyInnerHTML(R"HTML( + <style> + div { + transform-origin: 1px 2px 3px; + -webkit-transform-origin-x: 1px; + -webkit-transform-origin-y: 2px; + -webkit-transform-origin-z: 3px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyTransformOrigin)) + << "Not counted when values are the same"; +} + +TEST_F(StyleResolverTest, LegacyOverlapTransformOrigin_Last) { + SetBodyInnerHTML(R"HTML( + <style> + div { + transform-origin: 1px 2px 3px; + -webkit-transform-origin-x: 4px; + -webkit-transform-origin-y: 5px; + -webkit-transform-origin-z: 6px; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyTransformOrigin)) + << "Counted when -webkit-transform-origin-* is last with different " + "values"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Single) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 fill / 2 / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Not counted when only border-image is used"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Order) { + SetBodyInnerHTML(R"HTML( + <style> + div { + -webkit-border-image: url("#b") 2 fill / 3 / 4 round; + border-image: url("#a") 1 fill / 2 / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Not counted when border-image is last"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Values) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 fill / 2 / 3 round; + -webkit-border-image: url("#a") 1 fill / 2 / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Not counted when values are the same"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Last_Source) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 fill / 2 / 3 round; + -webkit-border-image: url("#b") 1 fill / 2 / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Counted when border-image-source differs"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Last_Slice) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 fill / 2 / 3 round; + -webkit-border-image: url("#a") 2 fill / 2 / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Counted when border-image-slice differs"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Last_SliceFill) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 / 2 / 3 round; + -webkit-border-image: url("#a") 1 fill / 2 / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Counted when the fill keyword of border-image-slice differs"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_SliceFillImplicit) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 / 2 / 3 round; + -webkit-border-image: url("#a") 1 / 2 / 3 round; + } + </style> + <div>target</div> + )HTML"); + // Note that -webkit-border-image implicitly adds "fill", but + // border-image does not. + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Counted when fill-less values are the same"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Last_Width) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 fill / 2 / 3 round; + -webkit-border-image: url("#a") 1 fill / 5 / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Counted when border-image-slice differs"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Last_Outset) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 fill / 2 / 3 round; + -webkit-border-image: url("#a") 1 fill / 2 / 5 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Counted when border-image-outset differs"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImage_Last_Repeat) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border-image: url("#a") 1 fill / 2 / 3 round; + -webkit-border-image: url("#a") 1 fill / 2 / 3 space; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImage)) + << "Counted when border-image-repeat differs"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImageWidth_Single) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border: 1px solid black; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyBorderImageWidth)) + << "Not counted when only border is used"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImageWidth_Order) { + SetBodyInnerHTML(R"HTML( + <style> + div { + -webkit-border-image: url("#b") 2 fill / 3px / 4 round; + border: 1px solid black; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyBorderImageWidth)) + << "Not counted when border is last"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImageWidth_Values) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border: 1px solid black; + -webkit-border-image: url("#b") 2 fill / 1px / 4 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyBorderImageWidth)) + << "Not counted when values are the same"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImageWidth_Last_Border) { + SetBodyInnerHTML(R"HTML( + <style> + div { + border: 1px solid black; + -webkit-border-image: url("#a") 1 fill / 2px / 3 round; + } + </style> + <div>target</div> + )HTML"); + // Since -webkit-border-image also sets border-width, we would normally + // expect TRUE here. However, StyleCascade always applies + // -webkit-border-image *first*, and does not do anything to prevent + // border-width properties from also being applied. Hence border-width + // always wins. + EXPECT_FALSE(IsUseCounted(WebFeature::kCSSLegacyBorderImageWidth)) + << "Not even counted when -webkit-border-image is last"; +} + +TEST_F(StyleResolverTest, LegacyOverlapBorderImageWidth_Last_Style) { + // Note that border-style is relevant here because the used border-width + // is 0px if we don'y have any border-style. See e.g. + // ComputedStyle::BorderLeftWidth. + SetBodyInnerHTML(R"HTML( + <style> + div { + border-style: solid; + -webkit-border-image: url("#b") 1 fill / 2px / 3 round; + } + </style> + <div>target</div> + )HTML"); + EXPECT_TRUE(IsUseCounted(WebFeature::kCSSLegacyBorderImageWidth)) + << "Counted when -webkit-border-image is last and there's no " + "border-width"; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 302fa7d..aa2c54b 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3649,10 +3649,12 @@ return false; } - for (PortalContents* portal : DocumentPortals::From(*document).GetPortals()) { - auto* portal_frame = portal->GetFrame(); - if (portal_frame && portal_frame->IsLoading()) - return false; + if (auto* portals = DocumentPortals::Get(*document)) { + for (PortalContents* portal : portals->GetPortals()) { + auto* portal_frame = portal->GetFrame(); + if (portal_frame && portal_frame->IsLoading()) + return false; + } } return true; }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 6f9c5ac..863e6a9 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -356,15 +356,19 @@ } if (Document* document = frame_->GetDocument()) { - for (PortalContents* portal : - DocumentPortals::From(*document).GetPortals()) { - if (Frame* frame = portal->GetFrame()) - function(*frame->View()); + if (DocumentPortals* portals = DocumentPortals::Get(*document)) { + for (PortalContents* portal : portals->GetPortals()) { + if (Frame* frame = portal->GetFrame()) + function(*frame->View()); + } } - for (HTMLFencedFrameElement* fenced_frame : - DocumentFencedFrames::From(*document).GetFencedFrames()) { - if (Frame* frame = fenced_frame->ContentFrame()) - function(*frame->View()); + if (DocumentFencedFrames* fenced_frames = + DocumentFencedFrames::Get(*document)) { + for (HTMLFencedFrameElement* fenced_frame : + fenced_frames->GetFencedFrames()) { + if (Frame* frame = fenced_frame->ContentFrame()) + function(*frame->View()); + } } } } @@ -433,18 +437,23 @@ } } if (Document* document = frame_->GetDocument()) { - for (PortalContents* portal : - DocumentPortals::From(*document).GetPortals()) { - if (RemoteFrame* frame = portal->GetFrame()) { - if (RemoteFrameView* view = frame->View()) - function(*view); + if (DocumentPortals* portals = DocumentPortals::Get(*document)) { + for (PortalContents* portal : portals->GetPortals()) { + if (RemoteFrame* frame = portal->GetFrame()) { + if (RemoteFrameView* view = frame->View()) + function(*view); + } } } - for (HTMLFencedFrameElement* fenced_frame : - DocumentFencedFrames::From(*document).GetFencedFrames()) { - if (RemoteFrame* frame = To<RemoteFrame>(fenced_frame->ContentFrame())) { - if (RemoteFrameView* view = frame->View()) - function(*view); + if (DocumentFencedFrames* fenced_frames = + DocumentFencedFrames::Get(*document)) { + for (HTMLFencedFrameElement* fenced_frame : + fenced_frames->GetFencedFrames()) { + if (RemoteFrame* frame = + To<RemoteFrame>(fenced_frame->ContentFrame())) { + if (RemoteFrameView* view = frame->View()) + function(*view); + } } } } @@ -4288,21 +4297,25 @@ monotonic_time); } - for (PortalContents* portal : - DocumentPortals::From(*frame_->GetDocument()).GetPortals()) { - if (Frame* frame = portal->GetFrame()) { - needs_occlusion_tracking |= - frame->View()->UpdateViewportIntersectionsForSubtree(flags, - monotonic_time); + if (DocumentPortals* portals = DocumentPortals::Get(*frame_->GetDocument())) { + for (PortalContents* portal : portals->GetPortals()) { + if (Frame* frame = portal->GetFrame()) { + needs_occlusion_tracking |= + frame->View()->UpdateViewportIntersectionsForSubtree( + flags, monotonic_time); + } } } - for (HTMLFencedFrameElement* fenced_frame : - DocumentFencedFrames::From(*frame_->GetDocument()).GetFencedFrames()) { - if (Frame* frame = fenced_frame->ContentFrame()) { - needs_occlusion_tracking |= - frame->View()->UpdateViewportIntersectionsForSubtree(flags, - monotonic_time); + if (DocumentFencedFrames* fenced_frames = + DocumentFencedFrames::Get(*frame_->GetDocument())) { + for (HTMLFencedFrameElement* fenced_frame : + fenced_frames->GetFencedFrames()) { + if (Frame* frame = fenced_frame->ContentFrame()) { + needs_occlusion_tracking |= + frame->View()->UpdateViewportIntersectionsForSubtree( + flags, monotonic_time); + } } } return needs_occlusion_tracking;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index e3db4855..ccc376d 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -195,15 +195,18 @@ if (auto* local_frame = DynamicTo<LocalFrame>(frame)) { if (Document* document = local_frame->GetDocument()) { // Iterate on any portals owned by a local frame. - for (PortalContents* portal : - DocumentPortals::From(*document).GetPortals()) { - if (RemoteFrame* remote_frame = portal->GetFrame()) - callback.Run(remote_frame); + if (auto* portals = DocumentPortals::Get(*document)) { + for (PortalContents* portal : portals->GetPortals()) { + if (RemoteFrame* remote_frame = portal->GetFrame()) + callback.Run(remote_frame); + } } // Iterate on any fenced frames owned by a local frame. - for (HTMLFencedFrameElement* fenced_frame : - DocumentFencedFrames::From(*document).GetFencedFrames()) { - callback.Run(To<RemoteFrame>(fenced_frame->ContentFrame())); + if (auto* fenced_frames = DocumentFencedFrames::Get(*document)) { + for (HTMLFencedFrameElement* fenced_frame : + fenced_frames->GetFencedFrames()) { + callback.Run(To<RemoteFrame>(fenced_frame->ContentFrame())); + } } } }
diff --git a/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.cc b/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.cc index 26f0b32..14d4d45e 100644 --- a/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.cc +++ b/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.cc
@@ -17,7 +17,12 @@ const char DocumentFencedFrames::kSupplementName[] = "DocumentFencedFrame"; // static -DocumentFencedFrames& DocumentFencedFrames::From(Document& document) { +DocumentFencedFrames* DocumentFencedFrames::Get(Document& document) { + return Supplement<Document>::From<DocumentFencedFrames>(document); +} + +// static +DocumentFencedFrames& DocumentFencedFrames::GetOrCreate(Document& document) { DocumentFencedFrames* supplement = Supplement<Document>::From<DocumentFencedFrames>(document); if (!supplement) {
diff --git a/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h b/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h index 146e1451..c0864497 100644 --- a/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h +++ b/third_party/blink/renderer/core/html/fenced_frame/document_fenced_frames.h
@@ -19,7 +19,15 @@ public Supplement<Document> { public: static const char kSupplementName[]; - static DocumentFencedFrames& From(Document&); + + // Returns the supplement that stores the fenced frame elements + // that are associated with the document. Returns nullptr if + // `GetOrCreate` has yet been called yet. + static DocumentFencedFrames* Get(Document&); + + // Like `Get` but if the supplement has not been created yet it + // will be created. + static DocumentFencedFrames& GetOrCreate(Document&); explicit DocumentFencedFrames(Document&);
diff --git a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc index 419770b..761b9db 100644 --- a/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc +++ b/third_party/blink/renderer/core/html/fenced_frame/fenced_frame_mparch_delegate.cc
@@ -27,7 +27,7 @@ .value(), features::FencedFramesImplementationType::kMPArch); - DocumentFencedFrames::From(GetElement().GetDocument()) + DocumentFencedFrames::GetOrCreate(GetElement().GetDocument()) .RegisterFencedFrame(&GetElement()); mojo::PendingAssociatedRemote<mojom::blink::FencedFrameOwnerHost> remote; mojo::PendingAssociatedReceiver<mojom::blink::FencedFrameOwnerHost> receiver = @@ -49,8 +49,9 @@ void FencedFrameMPArchDelegate::Dispose() { DCHECK(remote_); remote_.reset(); - DocumentFencedFrames::From(GetElement().GetDocument()) - .DeregisterFencedFrame(&GetElement()); + auto* fenced_frames = DocumentFencedFrames::Get(GetElement().GetDocument()); + DCHECK(fenced_frames); + fenced_frames->DeregisterFencedFrame(&GetElement()); } void FencedFrameMPArchDelegate::AttachLayoutTree() {
diff --git a/third_party/blink/renderer/core/html/portal/document_portals.cc b/third_party/blink/renderer/core/html/portal/document_portals.cc index ba600abe..db1f7ca 100644 --- a/third_party/blink/renderer/core/html/portal/document_portals.cc +++ b/third_party/blink/renderer/core/html/portal/document_portals.cc
@@ -15,7 +15,12 @@ const char DocumentPortals::kSupplementName[] = "DocumentPortals"; // static -DocumentPortals& DocumentPortals::From(Document& document) { +DocumentPortals* DocumentPortals::Get(Document& document) { + return Supplement<Document>::From<DocumentPortals>(document); +} + +// static +DocumentPortals& DocumentPortals::GetOrCreate(Document& document) { DocumentPortals* supplement = Supplement<Document>::From<DocumentPortals>(document); if (!supplement) {
diff --git a/third_party/blink/renderer/core/html/portal/document_portals.h b/third_party/blink/renderer/core/html/portal/document_portals.h index e966162..3c510be 100644 --- a/third_party/blink/renderer/core/html/portal/document_portals.h +++ b/third_party/blink/renderer/core/html/portal/document_portals.h
@@ -26,7 +26,15 @@ public Supplement<Document> { public: static const char kSupplementName[]; - static DocumentPortals& From(Document&); + + // Returns the supplement that stores the portal elements + // that are associated with the document. Returns nullptr if + // `GetOrCreate` has yet been called yet. + static DocumentPortals* Get(Document&); + + // Like `Get` but if the supplement has not been created yet it + // will be created. + static DocumentPortals& GetOrCreate(Document&); void RegisterPortalContents(PortalContents*); void DeregisterPortalContents(PortalContents*);
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc index 756e4458..7c7441a 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element.cc +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -111,7 +111,8 @@ if (!portal_) return "The HTMLPortalElement is not associated with a portal context."; - if (DocumentPortals::From(GetDocument()).IsPortalInDocumentActivating()) + if (DocumentPortals::GetOrCreate(GetDocument()) + .IsPortalInDocumentActivating()) return "Another portal in this document is activating."; if (GetDocument().GetPage()->InsidePortal())
diff --git a/third_party/blink/renderer/core/html/portal/portal_contents.cc b/third_party/blink/renderer/core/html/portal/portal_contents.cc index 420d3f7..7c941fbc 100644 --- a/third_party/blink/renderer/core/html/portal/portal_contents.cc +++ b/third_party/blink/renderer/core/html/portal/portal_contents.cc
@@ -41,7 +41,7 @@ portal_client_receiver_(this, std::move(portal_client_receiver)) { remote_portal_.set_disconnect_handler( WTF::Bind(&PortalContents::DisconnectHandler, WrapWeakPersistent(this))); - DocumentPortals::From(GetDocument()).RegisterPortalContents(this); + DocumentPortals::GetOrCreate(GetDocument()).RegisterPortalContents(this); } PortalContents::~PortalContents() = default; @@ -58,8 +58,9 @@ DCHECK(portal_element_); // Mark this contents as having activation in progress. - DocumentPortals& document_portals = DocumentPortals::From(GetDocument()); - document_portals.SetActivatingPortalContents(this); + auto* document_portals = DocumentPortals::Get(GetDocument()); + DCHECK(document_portals); + document_portals->SetActivatingPortalContents(this); activation_delegate_ = delegate; uint64_t trace_id = base::trace_event::GetNextGlobalTraceId(); @@ -120,9 +121,10 @@ return; } - DocumentPortals& document_portals = DocumentPortals::From(GetDocument()); - DCHECK_EQ(document_portals.GetActivatingPortalContents(), this); - document_portals.ClearActivatingPortalContents(); + auto* document_portals = DocumentPortals::Get(GetDocument()); + DCHECK(document_portals); + DCHECK_EQ(document_portals->GetActivatingPortalContents(), this); + document_portals->ClearActivatingPortalContents(); activation_delegate_ = nullptr; @@ -181,7 +183,7 @@ portal_token_ = absl::nullopt; remote_portal_.reset(); portal_client_receiver_.reset(); - DocumentPortals::From(GetDocument()).DeregisterPortalContents(this); + DocumentPortals::GetOrCreate(GetDocument()).DeregisterPortalContents(this); } void PortalContents::DisconnectHandler() {
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager.cc b/third_party/blink/renderer/core/input/pointer_event_manager.cc index 459f9e7..185c636 100644 --- a/third_party/blink/renderer/core/input/pointer_event_manager.cc +++ b/third_party/blink/renderer/core/input/pointer_event_manager.cc
@@ -667,6 +667,12 @@ mojom::blink::UserActivationNotificationType::kInteraction); } + if (RuntimeEnabledFeatures::TouchActionEffectiveAtPointerDownEnabled() && + event.GetType() == WebInputEvent::Type::kPointerDown) { + touch_event_manager_->UpdateTouchAttributeMapsForPointerDown( + event, pointer_event_target); + } + WebInputEventResult result = DispatchTouchPointerEvent( event, coalesced_events, predicted_events, pointer_event_target);
diff --git a/third_party/blink/renderer/core/input/touch_event_manager.cc b/third_party/blink/renderer/core/input/touch_event_manager.cc index 856961e3..9b9ce13d 100644 --- a/third_party/blink/renderer/core/input/touch_event_manager.cc +++ b/third_party/blink/renderer/core/input/touch_event_manager.cc
@@ -624,9 +624,8 @@ return; } - // In touch event model only touch starts can set the target and after that - // the touch event always goes to that target. - if (event.GetType() == WebInputEvent::Type::kPointerDown) { + if (!RuntimeEnabledFeatures::TouchActionEffectiveAtPointerDownEnabled() && + event.GetType() == WebInputEvent::Type::kPointerDown) { UpdateTouchAttributeMapsForPointerDown(event, pointer_event_target); }
diff --git a/third_party/blink/renderer/core/input/touch_event_manager.h b/third_party/blink/renderer/core/input/touch_event_manager.h index 6075f79..8843365 100644 --- a/third_party/blink/renderer/core/input/touch_event_manager.h +++ b/third_party/blink/renderer/core/input/touch_event_manager.h
@@ -48,6 +48,14 @@ // Returns whether there is any touch on the screen. bool IsAnyTouchActive() const; + // Keeps track of attributes of the touch point in the + // |touch_points_attributes_| map and computes the effective touch-action + // value, after possibly performing a hit-test if the original hit test result + // was not inside capturing frame |touch_sequence_document_| for touch events. + void UpdateTouchAttributeMapsForPointerDown( + const WebPointerEvent&, + const event_handling_util::PointerEventTarget&); + private: // Class represending one touch point event with its coalesced events and // related attributes. @@ -75,14 +83,6 @@ Touch* CreateDomTouch(const TouchPointAttributes*, bool* known_target); void AllTouchesReleasedCleanup(); - // Keeps track of attributes of the touch point in the - // |touch_points_attributes_| map and does the hit-testing if the original hit - // test result was not inside capturing frame |touch_sequence_document_| for - // touch events. - void UpdateTouchAttributeMapsForPointerDown( - const WebPointerEvent&, - const event_handling_util::PointerEventTarget&); - // This is triggered either by VSync signal to send one touch event per frame // accumulating all move events or by discrete events pointerdown/up/cancel. WebInputEventResult DispatchTouchEventFromAccumulatdTouchPoints(); @@ -135,6 +135,9 @@ // action which is sent to the browser after handling each dispatched // 'touchstart' is the intersection of all the previously calculated effective // touch action values during the sequence. + // + // TODO(https://crbug.com/844493): This seems incomplete code, should be + // removed. absl::optional<TouchAction> delayed_effective_touch_action_; };
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc index b5adfd2b..27b7bf1 100644 --- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -2556,26 +2556,28 @@ } if (IsA<LocalFrame>(frame)) { - for (HTMLFencedFrameElement* ff : - DocumentFencedFrames::From(*(To<LocalFrame>(frame)->GetDocument())) - .GetFencedFrames()) { - Frame* ff_frame = ff->ContentFrame(); - if (ff_frame && IdentifiersFactory::FrameId(ff_frame) == frame_id) { - found_frame = ff_frame; - break; + if (auto* fenced_frames = DocumentFencedFrames::Get( + *To<LocalFrame>(frame)->GetDocument())) { + for (HTMLFencedFrameElement* ff : fenced_frames->GetFencedFrames()) { + Frame* ff_frame = ff->ContentFrame(); + if (ff_frame && IdentifiersFactory::FrameId(ff_frame) == frame_id) { + found_frame = ff_frame; + break; + } } } } } if (!found_frame) { - for (PortalContents* portal : - DocumentPortals::From(*inspected_frames_->Root()->GetDocument()) - .GetPortals()) { - Frame* portal_frame = portal->GetFrame(); - if (IdentifiersFactory::FrameId(portal_frame) == frame_id) { - found_frame = portal_frame; - break; + if (auto* portals = + DocumentPortals::Get(*inspected_frames_->Root()->GetDocument())) { + for (PortalContents* portal : portals->GetPortals()) { + Frame* portal_frame = portal->GetFrame(); + if (IdentifiersFactory::FrameId(portal_frame) == frame_id) { + found_frame = portal_frame; + break; + } } } }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index 3202c89..1fc575f7 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -240,8 +240,7 @@ return MakeGarbageCollected<NGPhysicalBoxFragment>( AdditionalBytes(byte_size), PassKey(), other, has_layout_overflow, - layout_overflow, - /* recalculate_layout_overflow */ updated_layout_overflow.has_value()); + layout_overflow); } // static @@ -370,9 +369,8 @@ PassKey key, const NGPhysicalBoxFragment& other, bool has_layout_overflow, - const PhysicalRect& layout_overflow, - bool recalculate_layout_overflow) - : NGPhysicalFragment(other, recalculate_layout_overflow), + const PhysicalRect& layout_overflow) + : NGPhysicalFragment(other), is_inline_formatting_context_(other.is_inline_formatting_context_), const_has_fragment_items_(other.const_has_fragment_items_), include_border_top_(other.include_border_top_),
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h index 81d38249..9e89f48 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h
@@ -55,8 +55,7 @@ NGPhysicalBoxFragment(PassKey, const NGPhysicalBoxFragment& other, bool has_layout_overflow, - const PhysicalRect& layout_overflow, - bool recalculate_layout_overflow); + const PhysicalRect& layout_overflow); ~NGPhysicalBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc index 2f59f0f..d748a04a 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -401,8 +401,7 @@ // Even though the other constructors don't initialize many of these fields // (instead set by their super-classes), the copy constructor does. -NGPhysicalFragment::NGPhysicalFragment(const NGPhysicalFragment& other, - bool recalculate_layout_overflow) +NGPhysicalFragment::NGPhysicalFragment(const NGPhysicalFragment& other) : layout_object_(other.layout_object_), size_(other.size_), has_floating_descendants_for_paint_(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h index 59f67c0..4a02fef 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -86,8 +86,7 @@ NGFragmentType type, unsigned sub_type); - NGPhysicalFragment(const NGPhysicalFragment& other, - bool recalculate_layout_overflow); + NGPhysicalFragment(const NGPhysicalFragment& other); ~NGPhysicalFragment();
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc index 634477f..d3278b5 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -971,6 +971,7 @@ const NGBlockBreakToken* child_break_token = entry.GetBreakToken(); const NGLayoutResult* child_result; LayoutUnit child_inline_offset; + absl::optional<TableBoxExtent> new_table_box_extent; if (child.IsTableCaption()) { if (!relayout_captions) continue; @@ -1026,7 +1027,7 @@ // in a previous fragment. if (entry.GetSectionIndex() > 0 || IsResumingLayout(child_break_token)) border_padding_sides_to_include.block_start = false; - table_box_extent = + new_table_box_extent = BeginTableBoxLayout(child_block_offset, TableBoxBorderPadding()); // Only include border-spacing if we're at the start of the section. if (!IsResumingLayout(child_break_token)) @@ -1084,6 +1085,12 @@ DCHECK_EQ(break_status, NGBreakStatus::kContinue); } + if (new_table_box_extent) { + // The first section was added successfully. We're officially inside the + // table box! + table_box_extent = new_table_box_extent; + } + const auto& physical_fragment = To<NGPhysicalBoxFragment>(child_result->PhysicalFragment()); NGBoxFragment fragment(table_writing_direction, physical_fragment);
diff --git a/third_party/blink/renderer/core/loader/cookie_jar.cc b/third_party/blink/renderer/core/loader/cookie_jar.cc index ddc73a1..b3644cb 100644 --- a/third_party/blink/renderer/core/loader/cookie_jar.cc +++ b/third_party/blink/renderer/core/loader/cookie_jar.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/strcat.h" #include "net/base/features.h" #include "net/cookies/parsed_cookie.h" @@ -18,10 +19,22 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h" +#include "third_party/blink/renderer/platform/wtf/hash_functions.h" +#include "third_party/blink/renderer/platform/wtf/text/string_hash.h" namespace blink { namespace { +enum class CookieCacheLookupResult { + kCacheMissFirstAccess = 0, + kCacheHitAfterGet = 1, + kCacheHitAfterSet = 2, + kCacheMissAfterGet = 3, + kCacheMissAfterSet = 4, + kMaxValue = kCacheMissAfterSet, +}; + void LogCookieHistogram(const char* prefix, bool cookie_manager_requested, base::TimeDelta elapsed) { @@ -86,6 +99,7 @@ value, RuntimeEnabledFeatures::PartitionedCookiesEnabled( document_->GetExecutionContext())); + last_operation_was_set_ = true; LogCookieHistogram("Blink.SetCookieTime.", requested, timer.Elapsed()); // TODO(crbug.com/1276520): Remove after truncating characters are fully @@ -108,7 +122,11 @@ RuntimeEnabledFeatures::PartitionedCookiesEnabled( document_->GetExecutionContext()), &value); + last_operation_was_set_ = false; LogCookieHistogram("Blink.CookiesTime.", requested, timer.Elapsed()); + + UpdateCacheAfterGetRequest(cookie_url, value); + return value; } @@ -160,4 +178,31 @@ } } +void CookieJar::UpdateCacheAfterGetRequest(const KURL& cookie_url, + const String& cookie_string) { + absl::optional<unsigned> new_hash = WTF::HashInts( + KURLHash::GetHash(cookie_url), + cookie_string.IsNull() ? 0 : StringHash::GetHash(cookie_string)); + + CookieCacheLookupResult result = + CookieCacheLookupResult::kCacheMissFirstAccess; + + if (last_cookies_hash_.has_value()) { + if (last_cookies_hash_ == new_hash) { + result = last_operation_was_set_ + ? CookieCacheLookupResult::kCacheHitAfterSet + : CookieCacheLookupResult::kCacheHitAfterGet; + } else { + result = last_operation_was_set_ + ? CookieCacheLookupResult::kCacheMissAfterSet + : CookieCacheLookupResult::kCacheMissAfterGet; + } + } + + UMA_HISTOGRAM_ENUMERATION("Blink.Experimental.Cookies.CacheLookupResult", + result); + + last_cookies_hash_ = new_hash; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/cookie_jar.h b/third_party/blink/renderer/core/loader/cookie_jar.h index ecaa64d..cf8ad3c 100644 --- a/third_party/blink/renderer/core/loader/cookie_jar.h +++ b/third_party/blink/renderer/core/loader/cookie_jar.h
@@ -7,9 +7,11 @@ #include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -41,8 +43,34 @@ private: bool RequestRestrictedCookieManagerIfNeeded(); + // Updates the fake cookie cache after a + // RestrictedCookieManager::GetCookiesString request returns. + // + // We want to evaluate the possible performance gain from having a cookie + // cache. There is no real cache right now and this class just stores a hash + // to determine if the current request could have been served from a real + // cache. + void UpdateCacheAfterGetRequest(const KURL& cookie_url, + const String& cookie_string); + HeapMojoRemote<network::mojom::blink::RestrictedCookieManager> backend_; Member<blink::Document> document_; + + // Hash used to determine if the value returned by a call to + // RestrictedCookieManager::GetCookiesString is the same as a previous one. + // Used to answer the question: "had we keep the last cookie_string around + // would it have been possible to return that instead of making a new IPC?". + // Combines hashes for the `cookie_string` returned by the call and the + // `cookie_url` used as a parameter to the call. + // + // ATTENTION: Just use hashes for now to keep space overhead low, but more + // importantly, because keeping cookies around is tricky from a security + // perspective. + absl::optional<unsigned> last_cookies_hash_; + // Whether the last operation performed on this jar was a set or get. Used + // along with `last_cookies_hash_` when updating the histogram that tracks + // cookie access results. + bool last_operation_was_set_{false}; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index e1db9ee..30cb674f 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -609,8 +609,9 @@ int actual_frame_count = 0; if (auto* local_frame = DynamicTo<LocalFrame>(frame)) { - actual_frame_count += static_cast<int>( - DocumentPortals::From(*local_frame->GetDocument()).GetPortals().size()); + if (auto* portals = DocumentPortals::Get(*local_frame->GetDocument())) { + actual_frame_count += static_cast<int>(portals->GetPortals().size()); + } } for (; frame; frame = frame->Tree().TraverseNext()) { @@ -620,10 +621,11 @@ // the ``frame`` to get an accurate count (i.e. if an iframe embeds // a fenced frame and creates a new ``DocumentFencedFrames`` object). if (auto* local_frame = DynamicTo<LocalFrame>(frame)) { - actual_frame_count += static_cast<int>( - DocumentFencedFrames::From(*local_frame->GetDocument()) - .GetFencedFrames() - .size()); + if (auto* fenced_frames = + DocumentFencedFrames::Get(*local_frame->GetDocument())) { + actual_frame_count += + static_cast<int>(fenced_frames->GetFencedFrames().size()); + } } }
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 5d2697d..c91e17b 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -378,8 +378,8 @@ return; } - // TODO(crbug.com/1099069): add a separate flag for keyboard event synthesis - if (!RuntimeEnabledFeatures::AccessibilityObjectModelEnabled()) + if (!RuntimeEnabledFeatures:: + SynthesizedKeyboardEventsForAccessibilityActionsEnabled()) return; // Otherwise, fire a keyboard event instead.
diff --git a/third_party/blink/renderer/modules/crypto/crypto_histograms.cc b/third_party/blink/renderer/modules/crypto/crypto_histograms.cc index c3fe37e..611c2b3b 100644 --- a/third_party/blink/renderer/modules/crypto/crypto_histograms.cc +++ b/third_party/blink/renderer/modules/crypto/crypto_histograms.cc
@@ -48,10 +48,6 @@ return WebFeature::kCryptoAlgorithmHkdf; case kWebCryptoAlgorithmIdPbkdf2: return WebFeature::kCryptoAlgorithmPbkdf2; - case kWebCryptoAlgorithmIdX25519: - return WebFeature::kCryptoAlgorithmX25519; - case kWebCryptoAlgorithmIdEd25519: - return WebFeature::kCryptoAlgorithmEd25519; } NOTREACHED(); @@ -104,8 +100,6 @@ case kWebCryptoAlgorithmParamsTypeEcKeyGenParams: case kWebCryptoAlgorithmParamsTypeEcKeyImportParams: case kWebCryptoAlgorithmParamsTypeAesDerivedKeyParams: - case kWebCryptoAlgorithmParamsTypeEd25519Params: - case kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams: break; } }
diff --git a/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc b/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc index 4dee45e..5cf45c0f 100644 --- a/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc +++ b/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
@@ -73,12 +73,10 @@ {"SHA-1", 5, kWebCryptoAlgorithmIdSha1}, {"ECDSA", 5, kWebCryptoAlgorithmIdEcdsa}, {"PBKDF2", 6, kWebCryptoAlgorithmIdPbkdf2}, - {"X25519", 6, kWebCryptoAlgorithmIdX25519}, {"AES-KW", 6, kWebCryptoAlgorithmIdAesKw}, {"SHA-512", 7, kWebCryptoAlgorithmIdSha512}, {"SHA-384", 7, kWebCryptoAlgorithmIdSha384}, {"SHA-256", 7, kWebCryptoAlgorithmIdSha256}, - {"ED25519", 7, kWebCryptoAlgorithmIdEd25519}, {"AES-CBC", 7, kWebCryptoAlgorithmIdAesCbc}, {"AES-GCM", 7, kWebCryptoAlgorithmIdAesGcm}, {"AES-CTR", 7, kWebCryptoAlgorithmIdAesCtr}, @@ -203,14 +201,6 @@ return false; id = it->algorithm_id; - // TODO(crbug.com/1032821): X25519 and Ed25519 are currently introduced behind - // a flag. - if (!RuntimeEnabledFeatures::WebCryptoCurve25519Enabled() && - (id == kWebCryptoAlgorithmIdEd25519 || - id == kWebCryptoAlgorithmIdX25519)) { - return false; - } - return true; } @@ -989,48 +979,6 @@ return true; } -// TODO(crbug.com/1032821): The implementation of Curve25519 algorithms is -// experimental. See also the status on -// https://chromestatus.com/feature/4913922408710144. -// -// Ed25519Params in the prototype assumes the same structure as EcdsaParams: -// -// dictionary Ed25519Params : Algorithm { -// required HashAlgorithmIdentifier hash; -// }; -bool ParseEd25519Params(v8::Isolate* isolate, - const Dictionary& raw, - std::unique_ptr<WebCryptoAlgorithmParams>& params, - const ErrorContext& context, - ExceptionState& exception_state) { - WebCryptoAlgorithm hash; - if (!ParseHash(isolate, raw, hash, context, exception_state)) - return false; - - params = std::make_unique<WebCryptoEd25519Params>(hash); - return true; -} - -// TODO(crbug.com/1032821): X25519KeyDeriveParams in the prototype assumes the -// same structure as EcdhKeyDeriveParams: -// -// dictionary X25519KeyDeriveParams : Algorithm { -// required CryptoKey public; -// }; -bool ParseX25519KeyDeriveParams( - const Dictionary& raw, - std::unique_ptr<WebCryptoAlgorithmParams>& params, - const ErrorContext& context, - ExceptionState& exception_state) { - WebCryptoKey peer_public_key; - if (!GetPeerPublicKey(raw, context, &peer_public_key, exception_state)) - return false; - - DCHECK(!peer_public_key.IsNull()); - params = std::make_unique<WebCryptoX25519KeyDeriveParams>(peer_public_key); - return true; -} - bool ParseAlgorithmParams(v8::Isolate* isolate, const Dictionary& raw, WebCryptoAlgorithmParamsType type, @@ -1095,12 +1043,6 @@ case kWebCryptoAlgorithmParamsTypePbkdf2Params: context.Add("Pbkdf2Params"); return ParsePbkdf2Params(isolate, raw, params, context, exception_state); - case kWebCryptoAlgorithmParamsTypeEd25519Params: - context.Add("Ed25519Params"); - return ParseEd25519Params(isolate, raw, params, context, exception_state); - case kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams: - context.Add("X25519KeyDeriveParams"); - return ParseX25519KeyDeriveParams(raw, params, context, exception_state); } NOTREACHED(); return false;
diff --git a/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc b/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc index e48be7ca..c85b44f6 100644 --- a/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc +++ b/third_party/blink/renderer/platform/exported/web_crypto_algorithm.cc
@@ -283,40 +283,6 @@ WebCryptoAlgorithmInfo::kUndefined, // WrapKey WebCryptoAlgorithmInfo::kUndefined // UnwrapKey }}, - {// Index 16 - // TODO(crbug.com/1032821): Ed25519 is experimental behind a flag. See - // https://chromestatus.com/feature/4913922408710144 for the status. - "ED25519", - { - WebCryptoAlgorithmInfo::kUndefined, // Encrypt - WebCryptoAlgorithmInfo::kUndefined, // Decrypt - kWebCryptoAlgorithmParamsTypeEd25519Params, // Sign - kWebCryptoAlgorithmParamsTypeEd25519Params, // Verify - WebCryptoAlgorithmInfo::kUndefined, // Digest - kWebCryptoAlgorithmParamsTypeNone, // GenerateKey - kWebCryptoAlgorithmParamsTypeNone, // ImportKey - WebCryptoAlgorithmInfo::kUndefined, // GetKeyLength - WebCryptoAlgorithmInfo::kUndefined, // DeriveBits - WebCryptoAlgorithmInfo::kUndefined, // WrapKey - WebCryptoAlgorithmInfo::kUndefined // UnwrapKey - }}, - {// Index 17 - // TODO(crbug.com/1032821): X25519 is experimental behind a flag. See - // https://chromestatus.com/feature/4913922408710144 for the status. - "X25519", - { - WebCryptoAlgorithmInfo::kUndefined, // Encrypt - WebCryptoAlgorithmInfo::kUndefined, // Decrypt - WebCryptoAlgorithmInfo::kUndefined, // Sign - WebCryptoAlgorithmInfo::kUndefined, // Verify - WebCryptoAlgorithmInfo::kUndefined, // Digest - kWebCryptoAlgorithmParamsTypeNone, // GenerateKey - kWebCryptoAlgorithmParamsTypeNone, // ImportKey - WebCryptoAlgorithmInfo::kUndefined, // GetKeyLength - kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams, // DeriveBits - WebCryptoAlgorithmInfo::kUndefined, // WrapKey - WebCryptoAlgorithmInfo::kUndefined // UnwrapKey - }}, }; // Initializing the algorithmIdToInfo table above depends on knowing the enum @@ -339,9 +305,7 @@ static_assert(kWebCryptoAlgorithmIdEcdh == 13, "ECDH id must match"); static_assert(kWebCryptoAlgorithmIdHkdf == 14, "HKDF id must match"); static_assert(kWebCryptoAlgorithmIdPbkdf2 == 15, "Pbkdf2 id must match"); -static_assert(kWebCryptoAlgorithmIdEd25519 == 16, "X25519 id must match"); -static_assert(kWebCryptoAlgorithmIdX25519 == 17, "Ed25519 id must match"); -static_assert(kWebCryptoAlgorithmIdLast == 17, "last id must match"); +static_assert(kWebCryptoAlgorithmIdLast == 15, "last id must match"); static_assert(10 == kWebCryptoOperationLast, "the parameter mapping needs to be updated"); @@ -522,21 +486,6 @@ return nullptr; } -const WebCryptoEd25519Params* WebCryptoAlgorithm::Ed25519Params() const { - DCHECK(!IsNull()); - if (ParamsType() == kWebCryptoAlgorithmParamsTypeEd25519Params) - return static_cast<WebCryptoEd25519Params*>(private_->params.get()); - return nullptr; -} - -const WebCryptoX25519KeyDeriveParams* -WebCryptoAlgorithm::X25519KeyDeriveParams() const { - DCHECK(!IsNull()); - if (ParamsType() == kWebCryptoAlgorithmParamsTypeX25519KeyDeriveParams) - return static_cast<WebCryptoX25519KeyDeriveParams*>(private_->params.get()); - return nullptr; -} - bool WebCryptoAlgorithm::IsHash(WebCryptoAlgorithmId id) { switch (id) { case kWebCryptoAlgorithmIdSha1: @@ -556,8 +505,6 @@ case kWebCryptoAlgorithmIdEcdh: case kWebCryptoAlgorithmIdHkdf: case kWebCryptoAlgorithmIdPbkdf2: - case kWebCryptoAlgorithmIdEd25519: - case kWebCryptoAlgorithmIdX25519: break; } return false; @@ -582,8 +529,6 @@ case kWebCryptoAlgorithmIdRsaPss: case kWebCryptoAlgorithmIdEcdsa: case kWebCryptoAlgorithmIdEcdh: - case kWebCryptoAlgorithmIdEd25519: - case kWebCryptoAlgorithmIdX25519: break; } return false;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 810de618..758ece2 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2277,6 +2277,10 @@ status: "stable" }, { + name: "SynthesizedKeyboardEventsForAccessibilityActions", + status: "experimental", + }, + { name: "SystemWakeLock", status: "experimental", }, @@ -2332,6 +2336,11 @@ origin_trial_feature_name: "PrivacySandboxAdsAPIs", origin_trial_allows_third_party: true, }, + // https://crbug.com/1314739 + { + name: "TouchActionEffectiveAtPointerDown", + status: "experimental", + }, // This feature allows touch dragging and a context menu to occur // simultaneously, with the assumption that the menu is non-modal. Without // this feature, a long-press touch gesture can start either a drag or a @@ -2634,10 +2643,6 @@ origin_trial_feature_name: "WebCodecs" }, { - name: "WebCryptoCurve25519", - status: "experimental", - }, - { name: "WebGLColorManagement", status: "stable", },
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 22a73d3..0063f07 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1573,6 +1573,7 @@ virtual/layout_ng_table_frag/external/wpt/css/css-break/table/break-before-expansion-002.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/break-before-table-cell.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/break-before-table-cell-child.html [ Pass ] +virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-border-005.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-cell-expansion-003.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-col-paint-htb-ltr.html [ Pass ] virtual/layout_ng_table_frag/external/wpt/css/css-break/table/table-collapsed-borders-paint-at-boundary.tentative.html [ Pass ] @@ -3911,6 +3912,7 @@ crbug.com/1078927 external/wpt/css/css-break/table/break-before-expansion-002.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/break-before-table-cell.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/break-before-table-cell-child.html [ Failure ] +crbug.com/1078927 external/wpt/css/css-break/table/table-border-005.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-cell-expansion-003.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-col-paint-htb-ltr.html [ Failure ] crbug.com/1078927 external/wpt/css/css-break/table/table-collapsed-borders-paint-at-boundary.tentative.html [ Failure ] @@ -5985,8 +5987,6 @@ crbug.com/1215949 external/wpt/pointerevents/pointerevent_iframe-touch-action-none_touch.html [ Pass Timeout ] crbug.com/1216139 http/tests/devtools/bfcache/bfcache-elements-update.js [ Failure Pass ] -crbug.com/1314739 external/wpt/pointerevents/pointerevent_touch-action-modified_touch.html [ Timeout ] - # Sheriff 2021-06-10 crbug.com/1177996 [ Mac10.15 ] storage/websql/database-lock-after-reload.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations index 63bb1962..00645f9d 100644 --- a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations +++ b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
@@ -573,7 +573,6 @@ crbug.com/1050754 external/wpt/css/css-backgrounds/inheritance.sub.html [ Failure ] crbug.com/1050754 external/wpt/css/css-cascade/all-prop-initial-xml.html [ Failure ] crbug.com/1050754 external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-system-colors.html [ Failure ] -crbug.com/1050754 external/wpt/css/css-color/system-color-compute.html [ Failure ] crbug.com/1050754 external/wpt/css/css-contain/contain-size-grid-003.html [ Failure ] crbug.com/1050754 external/wpt/css/css-contain/contain-size-grid-004.html [ Failure ] crbug.com/1050754 external/wpt/css/css-contain/content-visibility/content-visibility-068.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations index fa6ea5c..e8166521 100644 --- a/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations +++ b/third_party/blink/web_tests/android/WebLayerWPTOverrideExpectations
@@ -630,7 +630,6 @@ crbug.com/1050754 external/wpt/css/css-cascade/all-prop-initial-xml.html [ Failure ] crbug.com/1050754 external/wpt/css/css-color-adjust/print-color-adjust-parsing.html [ Failure ] crbug.com/1050754 external/wpt/css/css-color-adjust/rendering/dark-color-scheme/color-scheme-system-colors.html [ Failure Pass ] -crbug.com/1050754 external/wpt/css/css-color/system-color-compute.html [ Failure Pass ] crbug.com/1050754 external/wpt/css/css-contain/contain-size-grid-003.html [ Failure ] crbug.com/1050754 external/wpt/css/css-contain/contain-size-grid-004.html [ Failure ] crbug.com/1050754 external/wpt/css/css-contain/content-visibility/content-visibility-047.html [ Crash Failure Pass ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index 4886192..5a51b044 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: 0a72bfc95905c163a65401318b8914e18b8f764f +Version: 333c51b8d345b00b05854d9774b56bc95098f1c3
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index b59decc..b4c9ea9 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -295018,6 +295018,14 @@ [] ] }, + "tools": { + "_virtualenv": { + ".gitignore": [ + "ede80b85f0f30f7d19ce1a46d6b421fac3c1f82f", + [] + ] + } + }, "vendor-imports": { "mozilla": { "mozilla-central-reftests": { @@ -324123,7 +324131,7 @@ ] }, "idlharness-shadowrealm.js": [ - "631278db22d8fb34b73e5f2fddf723630ddb40d8", + "05c4a1affc8699b6cd2a1fe02aa0ac2085b04a8a", [] ], "idlharness.js": [ @@ -398021,6 +398029,13 @@ {} ] ], + "host-pseudo-class-in-has.html": [ + "a2c63d546355c33144d787d603c3c27a8f6e4e07", + [ + null, + {} + ] + ], "input-pseudo-classes-in-has.html": [ "67aeedf315e686133c444455255ed7bbdf3b20e0", [ @@ -398057,7 +398072,7 @@ ] ], "is-pseudo-containing-complex-in-has.html": [ - "4b0225eb428fa0d55816cd115c26feacaf8468c3", + "4e6d4c8832e31cad61d5ada85ce12b1024311887", [ null, {} @@ -398106,7 +398121,7 @@ ] ], "not-pseudo-containing-complex-in-has.html": [ - "b99b309efd9d0e6ec4ff9ef2f679d323da98b7e3", + "d24abf69f7348093d214e03d0845bccc23dc11a4", [ null, {} @@ -420231,7 +420246,7 @@ ] ], "scheme-about.any.js": [ - "4329bd070320ddf8e475de2b97a8859f201cebbd", + "9ef44183c1750a95594af11d166ea2d4879d307e", [ "fetch/api/basic/scheme-about.any.html", { @@ -429934,6 +429949,31 @@ ] }, "range": { + "data.any.js": [ + "22ef11e9317275cc70b9a23653b87f089afe4457", + [ + "fetch/range/data.any.html", + { + "script_metadata": [ + [ + "script", + "/common/utils.js" + ] + ] + } + ], + [ + "fetch/range/data.any.worker.html", + { + "script_metadata": [ + [ + "script", + "/common/utils.js" + ] + ] + } + ] + ], "general.any.js": [ "3c4669ad0bbc1c3f10bca384194cd75dd54aa171", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/table/table-border-005.html b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-border-005.html new file mode 100644 index 0000000..3f8efe9d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/table/table-border-005.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-break-3/#box-splitting"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="width:100px; height:100px; background:red;"> + <div style="columns:2; gap:0; column-fill:auto; height:150px;"> + <div style="display:table; border-top:30px solid red; width:100%;"> + <div style="display:table-caption;"> + <div style="height:100px; background:green;"></div> + </div> + <div style="contain:size; height:70px;"> + <div style="margin-top:-30px; height:100px; background:green;"></div> + </div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-about.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-about.any.js index 4329bd0..9ef4418 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-about.any.js +++ b/third_party/blink/web_tests/external/wpt/fetch/api/basic/scheme-about.any.js
@@ -16,3 +16,11 @@ checkNetworkError("about:invalid.com"); checkNetworkError("about:config"); checkNetworkError("about:unicorn"); + +promise_test(function(test) { + var promise = fetch("about:blank", { + "method": "GET", + "Range": "bytes=1-10" + }); + return promise_rejects_js(test, TypeError, promise); +}, "Fetching about:blank with range header does not affect behavior");
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/data.any.js b/third_party/blink/web_tests/external/wpt/fetch/range/data.any.js new file mode 100644 index 0000000..22ef11e9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/range/data.any.js
@@ -0,0 +1,29 @@ +// META: script=/common/utils.js + +promise_test(async () => { + return fetch("data:text/plain;charset=US-ASCII,paddingHello%2C%20World%21padding", { + "method": "GET", + "Range": "bytes=13-26" + }).then(function(resp) { + assert_equals(resp.status, 200, "HTTP status is 200"); + assert_equals(resp.type, "basic", "response type is basic"); + assert_equals(resp.headers.get("Content-Type"), "text/plain;charset=US-ASCII", "Content-Type is " + resp.headers.get("Content-Type")); + return resp.text(); + }).then(function(text) { + assert_equals(text, 'paddingHello, World!padding', "Response's body ignores range"); + }); +}, "data: URL and Range header"); + +promise_test(async () => { + return fetch("data:text/plain;charset=US-ASCII,paddingHello%2C%20paddingWorld%21padding", { + "method": "GET", + "Range": "bytes=7-14,21-27" + }).then(function(resp) { + assert_equals(resp.status, 200, "HTTP status is 200"); + assert_equals(resp.type, "basic", "response type is basic"); + assert_equals(resp.headers.get("Content-Type"), "text/plain;charset=US-ASCII", "Content-Type is " + resp.headers.get("Content-Type")); + return resp.text(); + }).then(function(text) { + assert_equals(text, 'paddingHello, paddingWorld!padding', "Response's body ignores range"); + }); +}, "data: URL and Range header with multiple ranges");
diff --git a/third_party/blink/web_tests/external/wpt/resources/idlharness-shadowrealm.js b/third_party/blink/web_tests/external/wpt/resources/idlharness-shadowrealm.js index 631278d..05c4a1a 100644 --- a/third_party/blink/web_tests/external/wpt/resources/idlharness-shadowrealm.js +++ b/third_party/blink/web_tests/external/wpt/resources/idlharness-shadowrealm.js
@@ -36,7 +36,7 @@ isWindow: function() { return false; }, isWorker: function() { return false; }, isShadowRealm: function() { return true; }, - }; + }; undefined; `); const ss = await Promise.all(script_urls.map(url => fetch_text(url)));
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/css/css-color/system-color-compute-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-color/system-color-compute-expected.txt new file mode 100644 index 0000000..d16956e --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/css/css-color/system-color-compute-expected.txt
@@ -0,0 +1,30 @@ +This is a testharness.js-based test. +PASS color-scheme property affects Menu system color keyword +FAIL System color doesn't compute to itself on color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on color assert_false: expected false got true +FAIL System color doesn't compute to itself on background-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on background-color assert_false: expected false got true +FAIL System color doesn't compute to itself on box-shadow assert_not_equals: got disallowed value "rgb(18, 18, 18) 2px 2px 0px 0px" +FAIL Inherited system color keyword is observable on box-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on text-shadow assert_not_equals: got disallowed value "menu 2px 2px 0px" +FAIL Inherited system color keyword is observable on text-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on border-left-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-left-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-top-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-top-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-right-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-right-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-bottom-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-bottom-color assert_false: expected false got true +FAIL System color doesn't compute to itself on column-rule-color assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on column-rule-color assert_false: expected false got true +FAIL System color doesn't compute to itself on outline-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on outline-color assert_false: expected false got true +FAIL System color doesn't compute to itself on caret-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on caret-color assert_false: expected false got true +FAIL System color doesn't compute to itself on fill assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on fill assert_false: expected false got true +FAIL System color doesn't compute to itself on stroke assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on stroke assert_false: expected false got true +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux/virtual/system-color-compute/external/wpt/css/css-color/system-color-compute-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/system-color-compute/external/wpt/css/css-color/system-color-compute-expected.txt new file mode 100644 index 0000000..d16956e --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/system-color-compute/external/wpt/css/css-color/system-color-compute-expected.txt
@@ -0,0 +1,30 @@ +This is a testharness.js-based test. +PASS color-scheme property affects Menu system color keyword +FAIL System color doesn't compute to itself on color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on color assert_false: expected false got true +FAIL System color doesn't compute to itself on background-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on background-color assert_false: expected false got true +FAIL System color doesn't compute to itself on box-shadow assert_not_equals: got disallowed value "rgb(18, 18, 18) 2px 2px 0px 0px" +FAIL Inherited system color keyword is observable on box-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on text-shadow assert_not_equals: got disallowed value "menu 2px 2px 0px" +FAIL Inherited system color keyword is observable on text-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on border-left-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-left-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-top-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-top-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-right-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-right-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-bottom-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-bottom-color assert_false: expected false got true +FAIL System color doesn't compute to itself on column-rule-color assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on column-rule-color assert_false: expected false got true +FAIL System color doesn't compute to itself on outline-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on outline-color assert_false: expected false got true +FAIL System color doesn't compute to itself on caret-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on caret-color assert_false: expected false got true +FAIL System color doesn't compute to itself on fill assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on fill assert_false: expected false got true +FAIL System color doesn't compute to itself on stroke assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on stroke assert_false: expected false got true +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/css/css-color/system-color-compute-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-color/system-color-compute-expected.txt new file mode 100644 index 0000000..d16956e --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-color/system-color-compute-expected.txt
@@ -0,0 +1,30 @@ +This is a testharness.js-based test. +PASS color-scheme property affects Menu system color keyword +FAIL System color doesn't compute to itself on color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on color assert_false: expected false got true +FAIL System color doesn't compute to itself on background-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on background-color assert_false: expected false got true +FAIL System color doesn't compute to itself on box-shadow assert_not_equals: got disallowed value "rgb(18, 18, 18) 2px 2px 0px 0px" +FAIL Inherited system color keyword is observable on box-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on text-shadow assert_not_equals: got disallowed value "menu 2px 2px 0px" +FAIL Inherited system color keyword is observable on text-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on border-left-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-left-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-top-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-top-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-right-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-right-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-bottom-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-bottom-color assert_false: expected false got true +FAIL System color doesn't compute to itself on column-rule-color assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on column-rule-color assert_false: expected false got true +FAIL System color doesn't compute to itself on outline-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on outline-color assert_false: expected false got true +FAIL System color doesn't compute to itself on caret-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on caret-color assert_false: expected false got true +FAIL System color doesn't compute to itself on fill assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on fill assert_false: expected false got true +FAIL System color doesn't compute to itself on stroke assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on stroke assert_false: expected false got true +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win10/external/wpt/css/css-color/system-color-compute-expected.txt b/third_party/blink/web_tests/platform/win10/external/wpt/css/css-color/system-color-compute-expected.txt new file mode 100644 index 0000000..d16956e --- /dev/null +++ b/third_party/blink/web_tests/platform/win10/external/wpt/css/css-color/system-color-compute-expected.txt
@@ -0,0 +1,30 @@ +This is a testharness.js-based test. +PASS color-scheme property affects Menu system color keyword +FAIL System color doesn't compute to itself on color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on color assert_false: expected false got true +FAIL System color doesn't compute to itself on background-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on background-color assert_false: expected false got true +FAIL System color doesn't compute to itself on box-shadow assert_not_equals: got disallowed value "rgb(18, 18, 18) 2px 2px 0px 0px" +FAIL Inherited system color keyword is observable on box-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on text-shadow assert_not_equals: got disallowed value "menu 2px 2px 0px" +FAIL Inherited system color keyword is observable on text-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on border-left-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-left-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-top-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-top-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-right-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-right-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-bottom-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-bottom-color assert_false: expected false got true +FAIL System color doesn't compute to itself on column-rule-color assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on column-rule-color assert_false: expected false got true +FAIL System color doesn't compute to itself on outline-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on outline-color assert_false: expected false got true +FAIL System color doesn't compute to itself on caret-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on caret-color assert_false: expected false got true +FAIL System color doesn't compute to itself on fill assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on fill assert_false: expected false got true +FAIL System color doesn't compute to itself on stroke assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on stroke assert_false: expected false got true +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win10/virtual/system-color-compute/external/wpt/css/css-color/system-color-compute-expected.txt b/third_party/blink/web_tests/platform/win10/virtual/system-color-compute/external/wpt/css/css-color/system-color-compute-expected.txt new file mode 100644 index 0000000..d16956e --- /dev/null +++ b/third_party/blink/web_tests/platform/win10/virtual/system-color-compute/external/wpt/css/css-color/system-color-compute-expected.txt
@@ -0,0 +1,30 @@ +This is a testharness.js-based test. +PASS color-scheme property affects Menu system color keyword +FAIL System color doesn't compute to itself on color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on color assert_false: expected false got true +FAIL System color doesn't compute to itself on background-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on background-color assert_false: expected false got true +FAIL System color doesn't compute to itself on box-shadow assert_not_equals: got disallowed value "rgb(18, 18, 18) 2px 2px 0px 0px" +FAIL Inherited system color keyword is observable on box-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on text-shadow assert_not_equals: got disallowed value "menu 2px 2px 0px" +FAIL Inherited system color keyword is observable on text-shadow assert_false: expected false got true +FAIL System color doesn't compute to itself on border-left-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-left-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-top-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-top-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-right-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-right-color assert_false: expected false got true +FAIL System color doesn't compute to itself on border-bottom-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on border-bottom-color assert_false: expected false got true +FAIL System color doesn't compute to itself on column-rule-color assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on column-rule-color assert_false: expected false got true +FAIL System color doesn't compute to itself on outline-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on outline-color assert_false: expected false got true +FAIL System color doesn't compute to itself on caret-color assert_not_equals: got disallowed value "rgb(18, 18, 18)" +FAIL Inherited system color keyword is observable on caret-color assert_false: expected false got true +FAIL System color doesn't compute to itself on fill assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on fill assert_false: expected false got true +FAIL System color doesn't compute to itself on stroke assert_not_equals: got disallowed value "menu" +FAIL Inherited system color keyword is observable on stroke assert_false: expected false got true +Harness: the test ran to completion. +
diff --git a/third_party/r8/3pp/patches/0001-Add-disassemble-command-to-keeps.patch b/third_party/r8/3pp/patches/0001-Add-disassemble-command-to-keeps.patch index a047ee4..e127e84 100644 --- a/third_party/r8/3pp/patches/0001-Add-disassemble-command-to-keeps.patch +++ b/third_party/r8/3pp/patches/0001-Add-disassemble-command-to-keeps.patch
@@ -20,5 +20,5 @@ -keep public class com.android.tools.r8.dexsplitter.DexSplitter { public static void main(java.lang.String[]); } -- -2.36.1.124.g0e6072fb45-goog +2.36.1.255.ge46751e96f-goog
diff --git a/third_party/r8/3pp/patches/0002-Disable-line-number-optimization.patch b/third_party/r8/3pp/patches/0002-Disable-line-number-optimization.patch index 42e04576..c774d6b1 100644 --- a/third_party/r8/3pp/patches/0002-Disable-line-number-optimization.patch +++ b/third_party/r8/3pp/patches/0002-Disable-line-number-optimization.patch
@@ -36,5 +36,5 @@ internal.featureSplitConfiguration = featureSplitConfiguration; -- -2.36.1.124.g0e6072fb45-goog +2.36.1.255.ge46751e96f-goog
diff --git a/third_party/r8/3pp/patches/0003-Add-SameFilePolicy.patch b/third_party/r8/3pp/patches/0003-Add-SameFilePolicy.patch index 2db1bec..50c92dc2 100644 --- a/third_party/r8/3pp/patches/0003-Add-SameFilePolicy.patch +++ b/third_party/r8/3pp/patches/0003-Add-SameFilePolicy.patch
@@ -65,5 +65,5 @@ + } +} -- -2.36.1.124.g0e6072fb45-goog +2.36.1.255.ge46751e96f-goog
diff --git a/third_party/r8/3pp/patches/0005-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch b/third_party/r8/3pp/patches/0004-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch similarity index 90% rename from third_party/r8/3pp/patches/0005-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch rename to third_party/r8/3pp/patches/0004-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch index 8d57ec74..9dadbc5 100644 --- a/third_party/r8/3pp/patches/0005-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch +++ b/third_party/r8/3pp/patches/0004-Add-a-way-to-enable-reportUnusedProguardConfiguratio.patch
@@ -1,7 +1,7 @@ -From f4848463c527b4ad13a5497e08a78a26200c059b Mon Sep 17 00:00:00 2001 +From bda472e3d7cb56d1b35e7ac25d1541a3789f747e Mon Sep 17 00:00:00 2001 From: Andrew Grieve <agrieve@chromium.org> Date: Thu, 26 May 2022 13:35:04 -0400 -Subject: [PATCH 5/5] Add a way to enable +Subject: [PATCH 4/5] Add a way to enable reportUnusedProguardConfigurationRules Bug: 1303951 @@ -23,5 +23,5 @@ public boolean alwaysUsePessimisticRegisterAllocation = false; public boolean enableCheckCastAndInstanceOfRemoval = true; -- -2.36.1.124.g0e6072fb45-goog +2.36.1.255.ge46751e96f-goog
diff --git a/third_party/r8/3pp/patches/0004-Disable-write-only-field-pruning.patch b/third_party/r8/3pp/patches/0004-Disable-write-only-field-pruning.patch deleted file mode 100644 index 1d19c3a..0000000 --- a/third_party/r8/3pp/patches/0004-Disable-write-only-field-pruning.patch +++ /dev/null
@@ -1,26 +0,0 @@ -From d9fa6e4f573601b60f4c512234e23403a5eaf37e Mon Sep 17 00:00:00 2001 -From: Andrew Grieve <agrieve@chromium.org> -Date: Wed, 25 May 2022 23:12:52 -0400 -Subject: [PATCH 4/5] Disable write-only field pruning. - -Bug: 1329389 ---- - .../android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java -index 85d14b91e..598ceff61 100644 ---- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java -+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java -@@ -139,7 +139,7 @@ public class EnqueuerDeferredTracingImpl extends EnqueuerDeferredTracing { - } - - private boolean isEligibleForPruning(ProgramField field) { -- if (enqueuer.isFieldLive(field)) { -+ if (true || enqueuer.isFieldLive(field)) { - return false; - } - --- -2.36.1.124.g0e6072fb45-goog -
diff --git a/third_party/r8/3pp/patches/0005-Disable-write-only-field-pruning.patch b/third_party/r8/3pp/patches/0005-Disable-write-only-field-pruning.patch new file mode 100644 index 0000000..fdce923 --- /dev/null +++ b/third_party/r8/3pp/patches/0005-Disable-write-only-field-pruning.patch
@@ -0,0 +1,2901 @@ +From 208592c4e7021c5ddbfcc49d53aa5298b73cdd54 Mon Sep 17 00:00:00 2001 +From: Andrew Grieve <agrieve@chromium.org> +Date: Wed, 25 May 2022 23:12:52 -0400 +Subject: [PATCH 5/5] Disable write-only field pruning. + +Bug: 1329389 +--- + src/main/java/com/android/tools/r8/R8.java | 9 +- + .../r8/graph/AbstractAccessContexts.java | 6 +- + .../tools/r8/graph/FieldAccessInfo.java | 16 +- + .../graph/FieldAccessInfoCollectionImpl.java | 4 - + .../tools/r8/graph/FieldAccessInfoImpl.java | 88 ++--- + .../analysis/proto/EnumLiteProtoShrinker.java | 11 +- + .../GeneratedExtensionRegistryShrinker.java | 17 +- + .../proto/schema/ProtoEnqueuerExtension.java | 30 +- + .../BasicBlockInstructionListIterator.java | 22 +- + .../android/tools/r8/ir/code/FieldGet.java | 5 - + .../code/IRCodeInstructionListIterator.java | 8 +- + .../r8/ir/code/InstructionListIterator.java | 5 +- + .../LinearFlowInstructionListIterator.java | 8 +- + .../tools/r8/ir/conversion/IRBuilder.java | 2 +- + .../tools/r8/ir/conversion/IRConverter.java | 6 +- + .../r8/ir/conversion/IRToDexFinalizer.java | 5 +- + .../conversion/MethodConversionOptions.java | 13 - + .../r8/ir/conversion/StringSwitchRemover.java | 4 + + .../tools/r8/ir/optimize/CodeRewriter.java | 11 +- + .../tools/r8/ir/optimize/DeadCodeRemover.java | 4 - + .../assume/AssumeInfoLookup.java | 7 +- + .../shaking/EmptyEnqueuerDeferredTracing.java | 41 --- + .../android/tools/r8/shaking/Enqueuer.java | 211 +++--------- + .../r8/shaking/EnqueuerDeferredTracing.java | 55 +--- + .../shaking/EnqueuerDeferredTracingImpl.java | 282 ---------------- + .../EnqueuerDeferredTracingRewriter.java | 228 ------------- + .../tools/r8/shaking/EnqueuerWorklist.java | 310 +----------------- + .../android/tools/r8/shaking/KeepInfo.java | 8 - + .../tools/r8/utils/InternalOptions.java | 3 - + .../utils/collections/ProgramMemberMap.java | 6 +- + .../internal/proto/Proto2ShrinkingTest.java | 1 - + .../tools/r8/ir/LinearFlowIteratorTest.java | 12 +- + .../staticizer/ClassStaticizerTest.java | 3 +- + .../regalloc/RegisterMoveSchedulerTest.java | 8 +- + ...lassReferencedFromFieldAnnotationTest.java | 22 +- + ...ationAssertionHandlerKotlinSimpleTest.java | 81 ----- + .../tools/r8/shaking/InvalidTypesTest.java | 54 +-- + .../r8/shaking/KeepClassMembersFieldTest.java | 37 ++- + ...FieldsAllowShrinkingCompatibilityTest.java | 8 +- + .../MergedFieldTypeTest.java | 6 +- + .../KeptSingletonIsNotCyclicTest.java | 4 +- + 41 files changed, 241 insertions(+), 1420 deletions(-) + delete mode 100644 src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java + delete mode 100644 src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java + delete mode 100644 src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingRewriter.java + delete mode 100644 src/test/java/com/android/tools/r8/rewrite/assertions/kotlinassertionhandlersimple/AssertionConfigurationAssertionHandlerKotlinSimpleTest.java + +diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java +index 5d07a1ca0..a20f6300b 100644 +--- a/src/main/java/com/android/tools/r8/R8.java ++++ b/src/main/java/com/android/tools/r8/R8.java +@@ -400,11 +400,6 @@ public class R8 { + GenericSignatureCorrectnessHelper.createForInitialCheck(appView, genericContextBuilder) + .run(appView.appInfo().classes()); + +- // TODO(b/226539525): Implement enum lite proto shrinking as deferred tracing. +- if (appView.options().protoShrinking().isEnumLiteProtoShrinkingEnabled()) { +- appView.protoShrinker().enumLiteProtoShrinker.clearDeadEnumLiteMaps(); +- } +- + TreePruner pruner = new TreePruner(appViewWithLiveness); + DirectMappedDexApplication prunedApp = pruner.run(executorService); + +@@ -421,6 +416,10 @@ public class R8 { + appViewWithLiveness, appViewWithLiveness.appInfo().computeSubtypingInfo()) + .run(); + ++ if (appView.options().protoShrinking().isEnumLiteProtoShrinkingEnabled()) { ++ appView.protoShrinker().enumLiteProtoShrinker.clearDeadEnumLiteMaps(); ++ } ++ + AnnotationRemover annotationRemover = + annotationRemoverBuilder + .build(appViewWithLiveness, removedClasses); +diff --git a/src/main/java/com/android/tools/r8/graph/AbstractAccessContexts.java b/src/main/java/com/android/tools/r8/graph/AbstractAccessContexts.java +index 3e180dfc9..616fcf5c6 100644 +--- a/src/main/java/com/android/tools/r8/graph/AbstractAccessContexts.java ++++ b/src/main/java/com/android/tools/r8/graph/AbstractAccessContexts.java +@@ -58,10 +58,6 @@ public abstract class AbstractAccessContexts { + + abstract int getNumberOfAccessContexts(); + +- public final boolean hasAccesses() { +- return !isEmpty(); +- } +- + public boolean isBottom() { + return false; + } +@@ -70,7 +66,7 @@ public abstract class AbstractAccessContexts { + return false; + } + +- public abstract boolean isEmpty(); ++ abstract boolean isEmpty(); + + public ConcreteAccessContexts asConcrete() { + return null; +diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java +index 34b3f2b80..2cd2be0be 100644 +--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java ++++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfo.java +@@ -20,32 +20,20 @@ public interface FieldAccessInfo { + + int getNumberOfWriteContexts(); + +- AbstractAccessContexts getReadsWithContexts(); +- +- AbstractAccessContexts getWritesWithContexts(); +- + ProgramMethod getUniqueReadContext(); + +- boolean hasKnownReadContexts(); +- + boolean hasKnownWriteContexts(); + + void forEachIndirectAccess(Consumer<DexField> consumer); + + void forEachIndirectAccessWithContexts(BiConsumer<DexField, ProgramMethodSet> consumer); + +- void forEachAccessContext(Consumer<ProgramMethod> consumer); +- + void forEachReadContext(Consumer<ProgramMethod> consumer); + + void forEachWriteContext(Consumer<ProgramMethod> consumer); + + boolean hasReflectiveAccess(); + +- boolean hasReflectiveRead(); +- +- boolean hasReflectiveWrite(); +- + default boolean isAccessedFromMethodHandle() { + return isReadFromMethodHandle() || isWrittenFromMethodHandle(); + } +@@ -58,8 +46,6 @@ public interface FieldAccessInfo { + + boolean isReadFromMethodHandle(); + +- boolean isReadOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate); +- + boolean isWritten(); + + boolean isWrittenFromMethodHandle(); +@@ -68,5 +54,7 @@ public interface FieldAccessInfo { + + boolean isWrittenOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate); + ++ boolean isReadOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate); ++ + boolean isWrittenOutside(DexEncodedMethod method); + } +diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java +index 8a8b9da47..439ef05ea 100644 +--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java ++++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoCollectionImpl.java +@@ -63,10 +63,6 @@ public class FieldAccessInfoCollectionImpl + infos.values().forEach(consumer); + } + +- public void remove(DexField field) { +- infos.remove(field); +- } +- + @Override + public void removeIf(BiPredicate<DexField, FieldAccessInfoImpl> predicate) { + infos.entrySet().removeIf(entry -> predicate.test(entry.getKey(), entry.getValue())); +diff --git a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java +index 8779817a4..0a7d218da 100644 +--- a/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java ++++ b/src/main/java/com/android/tools/r8/graph/FieldAccessInfoImpl.java +@@ -27,9 +27,8 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + public static int FLAG_IS_READ_FROM_ANNOTATION = 1 << 0; + public static int FLAG_IS_READ_FROM_METHOD_HANDLE = 1 << 1; + public static int FLAG_IS_WRITTEN_FROM_METHOD_HANDLE = 1 << 2; +- public static int FLAG_HAS_REFLECTIVE_READ = 1 << 3; +- public static int FLAG_HAS_REFLECTIVE_WRITE = 1 << 4; +- public static int FLAG_IS_READ_FROM_RECORD_INVOKE_DYNAMIC = 1 << 5; ++ public static int FLAG_HAS_REFLECTIVE_ACCESS = 1 << 3; ++ public static int FLAG_IS_READ_FROM_RECORD_INVOKE_DYNAMIC = 1 << 4; + + // A direct reference to the definition of the field. + private DexField field; +@@ -73,7 +72,6 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + return field; + } + +- @Override + public AbstractAccessContexts getReadsWithContexts() { + return readsWithContexts; + } +@@ -82,11 +80,6 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + this.readsWithContexts = readsWithContexts; + } + +- @Override +- public AbstractAccessContexts getWritesWithContexts() { +- return writesWithContexts; +- } +- + public void setWritesWithContexts(AbstractAccessContexts writesWithContexts) { + this.writesWithContexts = writesWithContexts; + } +@@ -108,11 +101,6 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + : null; + } + +- @Override +- public boolean hasKnownReadContexts() { +- return !readsWithContexts.isTop(); +- } +- + @Override + public boolean hasKnownWriteContexts() { + return !writesWithContexts.isTop(); +@@ -180,12 +168,6 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + }); + } + +- @Override +- public void forEachAccessContext(Consumer<ProgramMethod> consumer) { +- forEachReadContext(consumer); +- forEachWriteContext(consumer); +- } +- + @Override + public void forEachReadContext(Consumer<ProgramMethod> consumer) { + readsWithContexts.forEachAccessContext(consumer); +@@ -198,39 +180,17 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + + @Override + public boolean hasReflectiveAccess() { +- return hasReflectiveRead() || hasReflectiveWrite(); +- } +- +- @Override +- public boolean hasReflectiveRead() { +- return (flags & FLAG_HAS_REFLECTIVE_READ) != 0; +- } +- +- public void setHasReflectiveRead() { +- flags |= FLAG_HAS_REFLECTIVE_READ; +- } +- +- @Override +- public boolean hasReflectiveWrite() { +- return (flags & FLAG_HAS_REFLECTIVE_WRITE) != 0; ++ return (flags & FLAG_HAS_REFLECTIVE_ACCESS) != 0; + } + +- public void setHasReflectiveWrite() { +- flags |= FLAG_HAS_REFLECTIVE_WRITE; ++ public void setHasReflectiveAccess() { ++ flags |= FLAG_HAS_REFLECTIVE_ACCESS; + } + + /** Returns true if this field is read by the program. */ + @Override + public boolean isRead() { +- return isReadDirectly() || isReadIndirectly(); +- } +- +- private boolean isReadDirectly() { +- return !readsWithContexts.isEmpty(); +- } +- +- private boolean isReadIndirectly() { +- return hasReflectiveRead() ++ return !readsWithContexts.isEmpty() + || isReadFromAnnotation() + || isReadFromMethodHandle() + || isReadFromRecordInvokeDynamic(); +@@ -250,15 +210,15 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + return (flags & FLAG_IS_READ_FROM_METHOD_HANDLE) != 0; + } + +- public void setReadFromMethodHandle() { +- flags |= FLAG_IS_READ_FROM_METHOD_HANDLE; +- } +- + @Override + public boolean isReadFromRecordInvokeDynamic() { + return (flags & FLAG_IS_READ_FROM_RECORD_INVOKE_DYNAMIC) != 0; + } + ++ public void setReadFromMethodHandle() { ++ flags |= FLAG_IS_READ_FROM_METHOD_HANDLE; ++ } ++ + public void setReadFromRecordInvokeDynamic() { + flags |= FLAG_IS_READ_FROM_RECORD_INVOKE_DYNAMIC; + } +@@ -267,28 +227,12 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + flags &= ~FLAG_IS_READ_FROM_RECORD_INVOKE_DYNAMIC; + } + +- /** +- * Returns true if this field is only read by methods for which {@param predicate} returns true. +- */ +- @Override +- public boolean isReadOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) { +- return readsWithContexts.isAccessedOnlyInMethodSatisfying(predicate) && !isReadIndirectly(); +- } +- + /** Returns true if this field is written by the program. */ + @Override + public boolean isWritten() { +- return isWrittenDirectly() || isWrittenIndirectly(); +- } +- +- private boolean isWrittenDirectly() { + return !writesWithContexts.isEmpty(); + } + +- private boolean isWrittenIndirectly() { +- return hasReflectiveWrite() || isWrittenFromMethodHandle(); +- } +- + @Override + public boolean isWrittenFromMethodHandle() { + return (flags & FLAG_IS_WRITTEN_FROM_METHOD_HANDLE) != 0; +@@ -312,7 +256,15 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + */ + @Override + public boolean isWrittenOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) { +- return writesWithContexts.isAccessedOnlyInMethodSatisfying(predicate) && !isWrittenIndirectly(); ++ return writesWithContexts.isAccessedOnlyInMethodSatisfying(predicate); ++ } ++ ++ /** ++ * Returns true if this field is only read by methods for which {@param predicate} returns true. ++ */ ++ @Override ++ public boolean isReadOnlyInMethodSatisfying(Predicate<ProgramMethod> predicate) { ++ return readsWithContexts.isAccessedOnlyInMethodSatisfying(predicate); + } + + /** +@@ -320,7 +272,7 @@ public class FieldAccessInfoImpl implements FieldAccessInfo { + */ + @Override + public boolean isWrittenOutside(DexEncodedMethod method) { +- return writesWithContexts.isAccessedOutside(method) || isWrittenIndirectly(); ++ return writesWithContexts.isAccessedOutside(method); + } + + public boolean recordRead(DexField access, ProgramMethod context) { +diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java +index e5278324d..6accb73ab 100644 +--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java ++++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/EnumLiteProtoShrinker.java +@@ -86,14 +86,9 @@ public class EnumLiteProtoShrinker { + if (enumLite != null) { + DexEncodedField field = + enumLite.lookupField(createInternalValueMapField(enumLite.getType())); +- if (field == null) { +- return false; +- } +- if (appView.appInfo().isFieldRead(field)) { +- return false; +- } +- return !appView.appInfo().isFieldWritten(field) +- || appView.appInfo().isStaticFieldWrittenOnlyInEnclosingStaticInitializer(field); ++ return field != null ++ && appView.appInfo().isStaticFieldWrittenOnlyInEnclosingStaticInitializer(field) ++ && !appView.appInfo().isFieldRead(field); + } + } + return false; +diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java +index 66d04da00..88d1c4752 100644 +--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java ++++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedExtensionRegistryShrinker.java +@@ -14,7 +14,6 @@ import com.android.tools.r8.graph.DexProgramClass; + import com.android.tools.r8.graph.DexType; + import com.android.tools.r8.graph.FieldAccessInfo; + import com.android.tools.r8.graph.FieldAccessInfoCollection; +-import com.android.tools.r8.graph.FieldResolutionResult; + import com.android.tools.r8.graph.ProgramField; + import com.android.tools.r8.graph.ProgramMethod; + import com.android.tools.r8.ir.code.IRCode; +@@ -232,18 +231,10 @@ public class GeneratedExtensionRegistryShrinker { + + public boolean isDeadProtoExtensionField(DexField fieldReference) { + AppInfoWithLiveness appInfo = appView.appInfo(); +- return isDeadProtoExtensionField( +- appInfo.resolveField(fieldReference), +- appInfo.getFieldAccessInfoCollection(), +- appInfo.getKeepInfo()); +- } +- +- public boolean isDeadProtoExtensionField( +- FieldResolutionResult resolutionResult, +- FieldAccessInfoCollection<?> fieldAccessInfoCollection, +- KeepInfoCollection keepInfo) { +- ProgramField field = resolutionResult.getSingleProgramField(); +- return field != null && isDeadProtoExtensionField(field, fieldAccessInfoCollection, keepInfo); ++ ProgramField field = appInfo.resolveField(fieldReference).getSingleProgramField(); ++ return field != null ++ && isDeadProtoExtensionField( ++ field, appInfo.getFieldAccessInfoCollection(), appInfo.getKeepInfo()); + } + + public boolean isDeadProtoExtensionField( +diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java +index e84fc5a69..b3976c758 100644 +--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java ++++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java +@@ -384,7 +384,7 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + } + + boolean valueStorageIsLive; +- if (enqueuer.isFieldReferenced(valueStorage)) { ++ if (enqueuer.isFieldLive(valueStorage)) { + if (enqueuer.isFieldRead(valueStorage) + || enqueuer.isFieldWrittenOutsideDefaultConstructor(valueStorage) + || reachesMapOrRequiredField(protoFieldInfo)) { +@@ -392,13 +392,15 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + // (i) optimize field reads into loading the default value of the field or (ii) remove + // field writes to proto fields that could be read using reflection by the proto + // library. +- worklist.enqueueTraceReflectiveFieldAccessAction(valueStorage, dynamicMethod); ++ enqueuer.registerReflectiveFieldAccess(valueStorage.getReference(), dynamicMethod); + } + valueStorageIsLive = true; + } else if (reachesMapOrRequiredField(protoFieldInfo)) { + // Map/required fields cannot be removed. Therefore, we mark such fields as both read and + // written such that we cannot optimize any field reads or writes. +- worklist.enqueueTraceReflectiveFieldAccessAction(valueStorage, dynamicMethod); ++ enqueuer.registerReflectiveFieldAccess(valueStorage.getReference(), dynamicMethod); ++ worklist.enqueueMarkFieldAsReachableAction( ++ valueStorage, dynamicMethod, KeepReason.reflectiveUseIn(dynamicMethod)); + valueStorageIsLive = true; + } else { + valueStorageIsLive = false; +@@ -412,7 +414,7 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + newlyLiveField = protoFieldInfo.getOneOfCaseField(appView, protoMessageInfo); + } else if (protoFieldInfo.hasHazzerBitField(protoMessageInfo)) { + newlyLiveField = protoFieldInfo.getHazzerBitField(appView, protoMessageInfo); +- worklist.enqueueTraceReflectiveFieldAccessAction(valueStorage, dynamicMethod); ++ enqueuer.registerReflectiveFieldAccess(valueStorage.getReference(), dynamicMethod); + } + } else { + // For one-of fields, mark the one-of field as live if the one-of-case field is live, and +@@ -421,13 +423,13 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + if (protoFieldInfo.getType().isOneOf()) { + ProgramField oneOfCaseField = + protoFieldInfo.getOneOfCaseField(appView, protoMessageInfo); +- if (oneOfCaseField != null && enqueuer.isFieldReferenced(oneOfCaseField)) { ++ if (oneOfCaseField != null && enqueuer.isFieldLive(oneOfCaseField)) { + newlyLiveField = valueStorage; + } + } else if (protoFieldInfo.hasHazzerBitField(protoMessageInfo)) { + ProgramField hazzerBitField = + protoFieldInfo.getHazzerBitField(appView, protoMessageInfo); +- if (hazzerBitField == null || !enqueuer.isFieldReferenced(hazzerBitField)) { ++ if (hazzerBitField == null || !enqueuer.isFieldLive(hazzerBitField)) { + continue; + } + +@@ -456,12 +458,15 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + && !writer.isStructurallyEqualTo(dynamicMethod); + if (enqueuer.isFieldWrittenInMethodSatisfying( + newlyLiveField, neitherDefaultConstructorNorDynamicMethod)) { +- worklist.enqueueTraceReflectiveFieldReadAction(newlyLiveField, dynamicMethod); ++ enqueuer.registerReflectiveFieldRead(newlyLiveField.getReference(), dynamicMethod); + } + + // Unconditionally register the hazzer and one-of proto fields as written from + // dynamicMethod(). +- worklist.enqueueTraceReflectiveFieldWriteAction(newlyLiveField, dynamicMethod); ++ if (enqueuer.registerReflectiveFieldWrite(newlyLiveField.getReference(), dynamicMethod)) { ++ worklist.enqueueMarkFieldAsReachableAction( ++ newlyLiveField, dynamicMethod, KeepReason.reflectiveUseIn(dynamicMethod)); ++ } + } + } + +@@ -492,7 +497,7 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + // schema, and therefore we do need to trace the const-class instructions that will be + // emitted for it. + ProgramField valueStorage = protoFieldInfo.getValueStorage(appView, protoMessageInfo); +- if (valueStorage != null && enqueuer.isFieldReferenced(valueStorage)) { ++ if (valueStorage != null && enqueuer.isFieldLive(valueStorage)) { + for (ProtoObject object : objects) { + if (object.isProtoObjectFromStaticGet()) { + worklist.enqueueTraceStaticFieldRead( +@@ -549,7 +554,7 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + return; + } + +- if (!enqueuer.isFieldReferenced(oneOfCaseField)) { ++ if (!enqueuer.isFieldLive(oneOfCaseField)) { + return; + } + +@@ -573,7 +578,10 @@ public class ProtoEnqueuerExtension extends EnqueuerAnalysis { + return; + } + +- worklist.enqueueTraceReflectiveFieldWriteAction(oneOfField, dynamicMethod); ++ if (enqueuer.registerReflectiveFieldWrite(oneOfField.getReference(), dynamicMethod)) { ++ worklist.enqueueMarkFieldAsReachableAction( ++ oneOfField, dynamicMethod, KeepReason.reflectiveUseIn(dynamicMethod)); ++ } + } + + /** +diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java +index b9f07e33c..3525c5ff8 100644 +--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java ++++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionListIterator.java +@@ -9,6 +9,7 @@ import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNul + import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull; + import static com.android.tools.r8.ir.code.DominatorTree.Assumption.MAY_HAVE_UNREACHABLE_BLOCKS; + ++import com.android.tools.r8.graph.AppInfoWithClassHierarchy; + import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DebugLocalInfo; + import com.android.tools.r8.graph.DexField; +@@ -325,7 +326,8 @@ public class BasicBlockInstructionListIterator implements InstructionListIterato + removeOrReplaceByDebugLocalRead(); + return true; + } +- replaceCurrentInstructionWithNullCheck(appView, receiver); ++ DexMethod getClassMethod = appView.dexItemFactory().objectMembers.getClass; ++ replaceCurrentInstruction(new InvokeVirtual(getClassMethod, null, ImmutableList.of(receiver))); + return true; + } + +@@ -405,20 +407,6 @@ public class BasicBlockInstructionListIterator implements InstructionListIterato + replaceCurrentInstruction(constString); + } + +- @Override +- public void replaceCurrentInstructionWithNullCheck(AppView<?> appView, Value object) { +- if (current == null) { +- throw new IllegalStateException(); +- } +- +- assert current.hasUnusedOutValue(); +- assert !block.hasCatchHandlers() || current.instructionTypeCanThrow(); +- +- DexMethod getClassMethod = appView.dexItemFactory().objectMembers.getClass; +- replaceCurrentInstruction( +- InvokeVirtual.builder().setMethod(getClassMethod).setSingleArgument(object).build()); +- } +- + @Override + public void replaceCurrentInstructionWithStaticGet( + AppView<?> appView, IRCode code, DexField field, Set<Value> affectedValues) { +@@ -504,7 +492,7 @@ public class BasicBlockInstructionListIterator implements InstructionListIterato + + @Override + public void replaceCurrentInstructionWithThrowNull( +- AppView<?> appView, ++ AppView<? extends AppInfoWithClassHierarchy> appView, + IRCode code, + ListIterator<BasicBlock> blockIterator, + Set<BasicBlock> blocksToRemove, +@@ -586,7 +574,7 @@ public class BasicBlockInstructionListIterator implements InstructionListIterato + // target. + return; + } +- if (appView.isSubtype(appView.dexItemFactory().npeType, guard).isFalse()) { ++ if (!appView.appInfo().isSubtype(appView.dexItemFactory().npeType, guard)) { + // TODO(christofferqa): Consider updating previous dominator tree instead of + // rebuilding it from scratch. + DominatorTree dominatorTree = new DominatorTree(code, MAY_HAVE_UNREACHABLE_BLOCKS); +diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldGet.java b/src/main/java/com/android/tools/r8/ir/code/FieldGet.java +index ec663fb16..aecb3eb82 100644 +--- a/src/main/java/com/android/tools/r8/ir/code/FieldGet.java ++++ b/src/main/java/com/android/tools/r8/ir/code/FieldGet.java +@@ -5,15 +5,10 @@ + package com.android.tools.r8.ir.code; + + import com.android.tools.r8.graph.DexField; +-import com.android.tools.r8.ir.analysis.type.TypeElement; + + public interface FieldGet { + + DexField getField(); + +- TypeElement getOutType(); +- +- boolean hasUsedOutValue(); +- + Value outValue(); + } +diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java +index 912586942..21b9df5e0 100644 +--- a/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java ++++ b/src/main/java/com/android/tools/r8/ir/code/IRCodeInstructionListIterator.java +@@ -5,6 +5,7 @@ + package com.android.tools.r8.ir.code; + + import com.android.tools.r8.errors.Unimplemented; ++import com.android.tools.r8.graph.AppInfoWithClassHierarchy; + import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DebugLocalInfo; + import com.android.tools.r8.graph.DexField; +@@ -88,11 +89,6 @@ public class IRCodeInstructionListIterator implements InstructionListIterator { + instructionIterator.replaceCurrentInstructionWithConstString(appView, code, value); + } + +- @Override +- public void replaceCurrentInstructionWithNullCheck(AppView<?> appView, Value object) { +- instructionIterator.replaceCurrentInstructionWithNullCheck(appView, object); +- } +- + @Override + public void replaceCurrentInstructionWithStaticGet( + AppView<?> appView, IRCode code, DexField field, Set<Value> affectedValues) { +@@ -118,7 +114,7 @@ public class IRCodeInstructionListIterator implements InstructionListIterator { + + @Override + public void replaceCurrentInstructionWithThrowNull( +- AppView<?> appView, ++ AppView<? extends AppInfoWithClassHierarchy> appView, + IRCode code, + ListIterator<BasicBlock> blockIterator, + Set<BasicBlock> blocksToRemove, +diff --git a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java +index 505507201..f1eab8920 100644 +--- a/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java ++++ b/src/main/java/com/android/tools/r8/ir/code/InstructionListIterator.java +@@ -5,6 +5,7 @@ + package com.android.tools.r8.ir.code; + + import com.android.tools.r8.errors.Unimplemented; ++import com.android.tools.r8.graph.AppInfoWithClassHierarchy; + import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DebugLocalInfo; + import com.android.tools.r8.graph.DexField; +@@ -143,8 +144,6 @@ public interface InstructionListIterator + appView, code, appView.dexItemFactory().createString(value)); + } + +- void replaceCurrentInstructionWithNullCheck(AppView<?> appView, Value object); +- + void replaceCurrentInstructionWithStaticGet( + AppView<?> appView, IRCode code, DexField field, Set<Value> affectedValues); + +@@ -171,7 +170,7 @@ public interface InstructionListIterator + * @param affectedValues set passed where values depending on detached blocks will be added. + */ + void replaceCurrentInstructionWithThrowNull( +- AppView<?> appView, ++ AppView<? extends AppInfoWithClassHierarchy> appView, + IRCode code, + ListIterator<BasicBlock> blockIterator, + Set<BasicBlock> blocksToRemove, +diff --git a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java +index 093faf189..ffb5d2bf7 100644 +--- a/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java ++++ b/src/main/java/com/android/tools/r8/ir/code/LinearFlowInstructionListIterator.java +@@ -4,6 +4,7 @@ + + package com.android.tools.r8.ir.code; + ++import com.android.tools.r8.graph.AppInfoWithClassHierarchy; + import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DebugLocalInfo; + import com.android.tools.r8.graph.DexField; +@@ -112,11 +113,6 @@ public class LinearFlowInstructionListIterator implements InstructionListIterato + currentBlockIterator.replaceCurrentInstructionWithConstString(appView, code, value); + } + +- @Override +- public void replaceCurrentInstructionWithNullCheck(AppView<?> appView, Value object) { +- currentBlockIterator.replaceCurrentInstructionWithNullCheck(appView, object); +- } +- + @Override + public void replaceCurrentInstructionWithStaticGet( + AppView<?> appView, IRCode code, DexField field, Set<Value> affectedValues) { +@@ -138,7 +134,7 @@ public class LinearFlowInstructionListIterator implements InstructionListIterato + + @Override + public void replaceCurrentInstructionWithThrowNull( +- AppView<?> appView, ++ AppView<? extends AppInfoWithClassHierarchy> appView, + IRCode code, + ListIterator<BasicBlock> blockIterator, + Set<BasicBlock> blocksToRemove, +diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java +index 85ac399b3..142f70eea 100644 +--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java ++++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java +@@ -736,7 +736,7 @@ public class IRBuilder { + new TypeAnalysis(appView).narrowing(ir); + } + +- if (conversionOptions.isStringSwitchConversionEnabled()) { ++ if (appView.options().isStringSwitchConversionEnabled()) { + StringSwitchConverter.convertToStringSwitchInstructions(ir, appView.dexItemFactory()); + } + +diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java +index 0c255dad7..929c89a44 100644 +--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java ++++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java +@@ -906,7 +906,7 @@ public class IRConverter { + Timing timing = Timing.empty(); + deadCodeRemover.run(code, timing); + method.setCode( +- new IRToDexFinalizer(appView, deadCodeRemover) ++ new IRToDexFinalizer(appView, codeRewriter, deadCodeRemover) + .finalizeCode(code, BytecodeMetadataProvider.empty(), timing), + appView); + if (Log.ENABLED) { +@@ -1429,7 +1429,7 @@ public class IRConverter { + + previous = printMethod(code, "IR after outline handler (SSA)", previous); + +- if (code.getConversionOptions().isStringSwitchConversionEnabled()) { ++ if (stringSwitchRemover != null) { + // Remove string switches prior to canonicalization to ensure that the constants that are + // being introduced will be canonicalized if possible. + timing.begin("Remove string switch"); +@@ -1643,7 +1643,7 @@ public class IRConverter { + ProgramMethod method = code.context(); + DexEncodedMethod definition = method.getDefinition(); + method.setCode( +- new IRToDexFinalizer(appView, deadCodeRemover) ++ new IRToDexFinalizer(appView, codeRewriter, deadCodeRemover) + .finalizeCode(code, bytecodeMetadataProvider, timing), + appView); + markProcessed(code, feedback); +diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRToDexFinalizer.java b/src/main/java/com/android/tools/r8/ir/conversion/IRToDexFinalizer.java +index 4155003ec..70fd16a41 100644 +--- a/src/main/java/com/android/tools/r8/ir/conversion/IRToDexFinalizer.java ++++ b/src/main/java/com/android/tools/r8/ir/conversion/IRToDexFinalizer.java +@@ -26,9 +26,10 @@ public class IRToDexFinalizer extends IRFinalizer<DexCode> { + private final CodeRewriter codeRewriter; + private final InternalOptions options; + +- public IRToDexFinalizer(AppView<?> appView, DeadCodeRemover deadCodeRemover) { ++ public IRToDexFinalizer( ++ AppView<?> appView, CodeRewriter codeRewriter, DeadCodeRemover deadCodeRemover) { + super(appView, deadCodeRemover); +- this.codeRewriter = deadCodeRemover.getCodeRewriter(); ++ this.codeRewriter = codeRewriter; + this.options = appView.options(); + } + +diff --git a/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java b/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java +index 038a2771c..472f83882 100644 +--- a/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java ++++ b/src/main/java/com/android/tools/r8/ir/conversion/MethodConversionOptions.java +@@ -17,16 +17,12 @@ public abstract class MethodConversionOptions { + + public abstract boolean isPeepholeOptimizationsEnabled(); + +- public abstract boolean isStringSwitchConversionEnabled(); +- + public static class MutableMethodConversionOptions extends MethodConversionOptions { + + private boolean enablePeepholeOptimizations = true; +- private boolean enableStringSwitchConversion; + private boolean isGeneratingClassFiles; + + public MutableMethodConversionOptions(InternalOptions options) { +- this.enableStringSwitchConversion = options.isStringSwitchConversionEnabled(); + this.isGeneratingClassFiles = options.isGeneratingClassFiles(); + } + +@@ -35,10 +31,6 @@ public abstract class MethodConversionOptions { + enablePeepholeOptimizations = false; + } + +- public void disableStringSwitchConversion() { +- enableStringSwitchConversion = false; +- } +- + public MutableMethodConversionOptions setIsGeneratingClassFiles( + boolean isGeneratingClassFiles) { + this.isGeneratingClassFiles = isGeneratingClassFiles; +@@ -54,11 +46,6 @@ public abstract class MethodConversionOptions { + public boolean isPeepholeOptimizationsEnabled() { + return enablePeepholeOptimizations; + } +- +- @Override +- public boolean isStringSwitchConversionEnabled() { +- return enableStringSwitchConversion; +- } + } + + public static class ThrowingMethodConversionOptions extends MutableMethodConversionOptions { +diff --git a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java +index ab6e97d8c..ecaeac24b 100644 +--- a/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java ++++ b/src/main/java/com/android/tools/r8/ir/conversion/StringSwitchRemover.java +@@ -50,6 +50,10 @@ public class StringSwitchRemover { + private final IdentifierNameStringMarker identifierNameStringMarker; + private final ClassTypeElement stringType; + ++ public StringSwitchRemover(AppView<?> appView) { ++ this(appView, null); ++ } ++ + StringSwitchRemover(AppView<?> appView, IdentifierNameStringMarker identifierNameStringMarker) { + this.appView = appView; + this.identifierNameStringMarker = identifierNameStringMarker; +diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java +index afeb060e4..9c6521dfc 100644 +--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java ++++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java +@@ -14,6 +14,7 @@ import com.android.tools.r8.dex.Constants; + import com.android.tools.r8.errors.CompilationError; + import com.android.tools.r8.errors.Unreachable; + import com.android.tools.r8.graph.AccessControl; ++import com.android.tools.r8.graph.AppInfoWithClassHierarchy; + import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DebugLocalInfo; + import com.android.tools.r8.graph.DexClass; +@@ -3040,6 +3041,12 @@ public class CodeRewriter { + // it with a block throwing a null value (which should result in NPE). Note that this throw is not + // expected to be ever reached, but is intended to satisfy verifier. + public void optimizeAlwaysThrowingInstructions(IRCode code) { ++ if (!appView.appInfo().hasClassHierarchy()) { ++ return; ++ } ++ ++ AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy = ++ appView.withClassHierarchy(); + Set<Value> affectedValues = Sets.newIdentityHashSet(); + Set<BasicBlock> blocksToRemove = Sets.newIdentityHashSet(); + ListIterator<BasicBlock> blockIterator = code.listIterator(); +@@ -3089,7 +3096,7 @@ public class CodeRewriter { + } + } + instructionIterator.replaceCurrentInstructionWithThrowNull( +- appView, code, blockIterator, blocksToRemove, affectedValues); ++ appViewWithClassHierarchy, code, blockIterator, blocksToRemove, affectedValues); + continue; + } + } +@@ -3125,7 +3132,7 @@ public class CodeRewriter { + instructionIterator.setInsertionPosition(invoke.getPosition()); + instructionIterator.next(); + instructionIterator.replaceCurrentInstructionWithThrowNull( +- appView, code, blockIterator, blocksToRemove, affectedValues); ++ appViewWithClassHierarchy, code, blockIterator, blocksToRemove, affectedValues); + instructionIterator.unsetInsertionPosition(); + } + } +diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java +index 92e653d3e..caacb269f 100644 +--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java ++++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java +@@ -40,10 +40,6 @@ public class DeadCodeRemover { + this.codeRewriter = codeRewriter; + } + +- public CodeRewriter getCodeRewriter() { +- return codeRewriter; +- } +- + public void run(IRCode code, Timing timing) { + timing.begin("Remove dead code"); + +diff --git a/src/main/java/com/android/tools/r8/ir/optimize/membervaluepropagation/assume/AssumeInfoLookup.java b/src/main/java/com/android/tools/r8/ir/optimize/membervaluepropagation/assume/AssumeInfoLookup.java +index d207ac784..381ea11a4 100644 +--- a/src/main/java/com/android/tools/r8/ir/optimize/membervaluepropagation/assume/AssumeInfoLookup.java ++++ b/src/main/java/com/android/tools/r8/ir/optimize/membervaluepropagation/assume/AssumeInfoLookup.java +@@ -4,7 +4,6 @@ + + package com.android.tools.r8.ir.optimize.membervaluepropagation.assume; + +-import com.android.tools.r8.graph.AppInfoWithClassHierarchy; + import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DexClassAndMember; + import com.android.tools.r8.graph.DexClassAndMethod; +@@ -32,10 +31,10 @@ public class AssumeInfoLookup { + } + + public static AssumeInfo lookupAssumeInfo( +- AppView<? extends AppInfoWithClassHierarchy> appView, DexClassAndMember<?, ?> member) { ++ AppView<AppInfoWithLiveness> appView, DexClassAndMember<?, ?> member) { + DexMember<?, ?> reference = member.getReference(); +- ProguardMemberRule assumeNoSideEffectsRule = appView.rootSet().noSideEffects.get(reference); +- ProguardMemberRule assumeValuesRule = appView.rootSet().assumedValues.get(reference); ++ ProguardMemberRule assumeNoSideEffectsRule = appView.appInfo().noSideEffects.get(reference); ++ ProguardMemberRule assumeValuesRule = appView.appInfo().assumedValues.get(reference); + if (assumeNoSideEffectsRule == null && assumeValuesRule == null) { + return null; + } +diff --git a/src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java b/src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java +deleted file mode 100644 +index 2faf20b75..000000000 +--- a/src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java ++++ /dev/null +@@ -1,41 +0,0 @@ +-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file +-// for details. All rights reserved. Use of this source code is governed by a +-// BSD-style license that can be found in the LICENSE file. +- +-package com.android.tools.r8.shaking; +- +-import com.android.tools.r8.graph.DexField; +-import com.android.tools.r8.graph.FieldResolutionResult; +-import com.android.tools.r8.graph.ProgramField; +-import com.android.tools.r8.graph.ProgramMethod; +-import com.android.tools.r8.shaking.Enqueuer.FieldAccessKind; +-import com.android.tools.r8.shaking.Enqueuer.FieldAccessMetadata; +-import java.util.concurrent.ExecutorService; +- +-public class EmptyEnqueuerDeferredTracing extends EnqueuerDeferredTracing { +- +- @Override +- public boolean deferTracingOfFieldAccess( +- DexField fieldReference, +- FieldResolutionResult resolutionResult, +- ProgramMethod context, +- FieldAccessKind accessKind, +- FieldAccessMetadata metadata) { +- return false; +- } +- +- @Override +- public boolean enqueueWorklistActions(EnqueuerWorklist worklist) { +- return false; +- } +- +- @Override +- public void rewriteApplication(ExecutorService executorService) { +- // Intentionally empty. +- } +- +- @Override +- public void notifyReflectiveFieldAccess(ProgramField field, ProgramMethod context) { +- // Intentionally empty. +- } +-} +diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java +index f7d3e7422..10f971d76 100644 +--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java ++++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java +@@ -10,7 +10,6 @@ import static com.android.tools.r8.ir.desugar.LambdaDescriptor.isLambdaMetafacto + import static com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter.Flavor.ExcludeDexResources; + import static com.android.tools.r8.naming.IdentifierNameStringUtils.identifyIdentifier; + import static com.android.tools.r8.naming.IdentifierNameStringUtils.isReflectionMethod; +-import static com.android.tools.r8.shaking.KeepInfo.Joiner.asFieldJoinerOrNull; + import static com.android.tools.r8.utils.FunctionUtils.ignoreArgument; + import static com.android.tools.r8.utils.MapUtils.ignoreKey; + import static java.util.Collections.emptySet; +@@ -127,10 +126,6 @@ import com.android.tools.r8.shaking.EnqueuerEvent.InstantiatedClassEnqueuerEvent + import com.android.tools.r8.shaking.EnqueuerEvent.LiveClassEnqueuerEvent; + import com.android.tools.r8.shaking.EnqueuerEvent.UnconditionalKeepInfoEvent; + import com.android.tools.r8.shaking.EnqueuerWorklist.EnqueuerAction; +-import com.android.tools.r8.shaking.EnqueuerWorklist.TraceInstanceFieldReadAction; +-import com.android.tools.r8.shaking.EnqueuerWorklist.TraceInstanceFieldWriteAction; +-import com.android.tools.r8.shaking.EnqueuerWorklist.TraceStaticFieldReadAction; +-import com.android.tools.r8.shaking.EnqueuerWorklist.TraceStaticFieldWriteAction; + import com.android.tools.r8.shaking.GraphReporter.KeepReasonWitness; + import com.android.tools.r8.shaking.KeepInfoCollection.MutableKeepInfoCollection; + import com.android.tools.r8.shaking.RootSetUtils.ConsequentRootSet; +@@ -469,7 +464,7 @@ public class Enqueuer { + InternalOptions options = appView.options(); + this.appInfo = appView.appInfo(); + this.appView = appView.withClassHierarchy(); +- this.deferredTracing = EnqueuerDeferredTracing.create(appView, this, mode); ++ this.deferredTracing = new EnqueuerDeferredTracing(); + this.executorService = executorService; + this.subtypingInfo = subtypingInfo; + this.forceProguardCompatibility = options.forceProguardCompatibility; +@@ -705,10 +700,6 @@ public class Enqueuer { + return classResolutionResult; + } + +- public FieldAccessInfoCollectionImpl getFieldAccessInfoCollection() { +- return fieldAccessInfoCollection; +- } +- + public MutableKeepInfoCollection getKeepInfo() { + return keepInfo; + } +@@ -717,28 +708,6 @@ public class Enqueuer { + return keepInfo.getClassInfo(clazz); + } + +- public KeepFieldInfo getKeepInfo(ProgramField field) { +- return keepInfo.getFieldInfo(field); +- } +- +- public boolean hasMinimumKeepInfoThatMatches( +- ProgramField field, Predicate<KeepFieldInfo.Joiner> predicate) { +- MinimumKeepInfoCollection minimumKeepInfoCollection = +- dependentMinimumKeepInfo.getUnconditionalMinimumKeepInfoOrDefault( +- MinimumKeepInfoCollection.empty()); +- KeepFieldInfo.Joiner minimumKeepInfo = +- asFieldJoinerOrNull(minimumKeepInfoCollection.getOrDefault(field.getReference(), null)); +- return minimumKeepInfo != null && predicate.test(minimumKeepInfo); +- } +- +- public ObjectAllocationInfoCollectionImpl getObjectAllocationInfoCollection() { +- return objectAllocationInfoCollection; +- } +- +- public EnqueuerWorklist getWorklist() { +- return workList; +- } +- + private void addLiveNonProgramType( + ClasspathOrLibraryClass clazz, + // TODO(b/216576191): Remove when tracking live library members. +@@ -1010,39 +979,22 @@ public class Enqueuer { + return registerFieldAccess(field, context, true, false); + } + +- public boolean registerReflectiveFieldRead(ProgramField field, ProgramMethod context) { +- return registerFieldAccess(field.getReference(), context, true, true); ++ public boolean registerReflectiveFieldRead(DexField field, ProgramMethod context) { ++ return registerFieldAccess(field, context, true, true); + } + + public boolean registerFieldWrite(DexField field, ProgramMethod context) { + return registerFieldAccess(field, context, false, false); + } + +- public boolean registerReflectiveFieldWrite(ProgramField field, ProgramMethod context) { +- return registerFieldAccess(field.getReference(), context, false, true); +- } +- +- public void traceReflectiveFieldAccess(ProgramField field, ProgramMethod context) { +- deferredTracing.notifyReflectiveFieldAccess(field, context); +- boolean changed = registerReflectiveFieldRead(field, context); +- changed |= registerReflectiveFieldWrite(field, context); +- if (changed) { +- markFieldAsReachable(field, context, KeepReason.reflectiveUseIn(context)); +- } +- } +- +- public void traceReflectiveFieldRead(ProgramField field, ProgramMethod context) { +- deferredTracing.notifyReflectiveFieldAccess(field, context); +- if (registerReflectiveFieldRead(field, context)) { +- markFieldAsReachable(field, context, KeepReason.reflectiveUseIn(context)); +- } ++ public boolean registerReflectiveFieldWrite(DexField field, ProgramMethod context) { ++ return registerFieldAccess(field, context, false, true); + } + +- public void traceReflectiveFieldWrite(ProgramField field, ProgramMethod context) { +- deferredTracing.notifyReflectiveFieldAccess(field, context); +- if (registerReflectiveFieldWrite(field, context)) { +- markFieldAsReachable(field, context, KeepReason.reflectiveUseIn(context)); +- } ++ public boolean registerReflectiveFieldAccess(DexField field, ProgramMethod context) { ++ boolean changed = registerFieldAccess(field, context, true, true); ++ changed |= registerFieldAccess(field, context, false, true); ++ return changed; + } + + private boolean registerFieldAccess( +@@ -1076,18 +1028,7 @@ public class Enqueuer { + return false; + } + if (isReflective) { +- if (isRead) { +- if (!info.hasReflectiveRead()) { +- info.setHasReflectiveRead(); +- return true; +- } +- } else { +- if (!info.hasReflectiveWrite()) { +- info.setHasReflectiveWrite(); +- return true; +- } +- } +- return false; ++ info.setHasReflectiveAccess(); + } + return isRead ? info.recordRead(field, context) : info.recordWrite(field, context); + } +@@ -1275,7 +1216,7 @@ public class Enqueuer { + initClassReferences.put( + type, computeMinimumRequiredVisibilityForInitClassField(type, currentMethod.getHolder())); + +- markTypeAsLive(clazz, currentMethod); ++ markTypeAsLive(type, currentMethod); + markDirectAndIndirectClassInitializersAsLive(clazz); + return; + } +@@ -1574,29 +1515,12 @@ public class Enqueuer { + boolean isWrite() { + return !isRead(); + } +- +- EnqueuerAction toEnqueuerAction( +- DexField fieldReference, ProgramMethod context, FieldAccessMetadata metadata) { +- switch (this) { +- case INSTANCE_READ: +- return new TraceInstanceFieldReadAction(fieldReference, context, metadata); +- case INSTANCE_WRITE: +- return new TraceInstanceFieldWriteAction(fieldReference, context, metadata); +- case STATIC_READ: +- return new TraceStaticFieldReadAction(fieldReference, context, metadata); +- case STATIC_WRITE: +- return new TraceStaticFieldWriteAction(fieldReference, context, metadata); +- default: +- throw new Unreachable(); +- } +- } + } + + static class FieldAccessMetadata { + +- private static int DEFERRED_MASK = 1; +- private static int FROM_METHOD_HANDLE_MASK = 2; +- private static int FROM_RECORD_METHOD_HANDLE_MASK = 4; ++ private static int FROM_METHOD_HANDLE_MASK = 1; ++ private static int FROM_RECORD_METHOD_HANDLE_MASK = 2; + + static FieldAccessMetadata DEFAULT = new FieldAccessMetadata(0); + static FieldAccessMetadata FROM_METHOD_HANDLE = +@@ -1604,16 +1528,10 @@ public class Enqueuer { + static FieldAccessMetadata FROM_RECORD_METHOD_HANDLE = + new FieldAccessMetadata(FROM_RECORD_METHOD_HANDLE_MASK); + +- private final FieldAccessMetadata deferred; + private final int flags; + +- private FieldAccessMetadata(int flags) { ++ FieldAccessMetadata(int flags) { + this.flags = flags; +- this.deferred = isDeferred() ? this : new FieldAccessMetadata(flags | DEFERRED_MASK); +- } +- +- boolean isDeferred() { +- return (flags & DEFERRED_MASK) != 0; + } + + boolean isFromMethodHandle() { +@@ -1623,39 +1541,17 @@ public class Enqueuer { + boolean isFromRecordMethodHandle() { + return (flags & FROM_RECORD_METHOD_HANDLE_MASK) != 0; + } +- +- public FieldAccessMetadata toDeferred() { +- return deferred; +- } +- +- @Override +- public boolean equals(Object obj) { +- if (this == obj) { +- return true; +- } +- if (obj == null || getClass() != obj.getClass()) { +- return false; +- } +- FieldAccessMetadata metadata = (FieldAccessMetadata) obj; +- return flags == metadata.flags; +- } +- +- @Override +- public int hashCode() { +- return flags; +- } + } + +- void traceInstanceFieldRead( ++ private void traceInstanceFieldRead( + DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) { +- if (!metadata.isDeferred() && !registerFieldRead(fieldReference, currentMethod)) { ++ if (!registerFieldRead(fieldReference, currentMethod)) { + return; + } + + FieldResolutionResult resolutionResult = resolveField(fieldReference, currentMethod); + if (deferredTracing.deferTracingOfFieldAccess( + fieldReference, resolutionResult, currentMethod, FieldAccessKind.INSTANCE_READ, metadata)) { +- assert !metadata.isDeferred(); + return; + } + +@@ -1711,9 +1607,9 @@ public class Enqueuer { + traceInstanceFieldWrite(field, currentMethod, FieldAccessMetadata.FROM_METHOD_HANDLE); + } + +- void traceInstanceFieldWrite( ++ private void traceInstanceFieldWrite( + DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) { +- if (!metadata.isDeferred() && !registerFieldWrite(fieldReference, currentMethod)) { ++ if (!registerFieldWrite(fieldReference, currentMethod)) { + return; + } + +@@ -1724,7 +1620,6 @@ public class Enqueuer { + currentMethod, + FieldAccessKind.INSTANCE_WRITE, + metadata)) { +- assert !metadata.isDeferred(); + return; + } + +@@ -1778,31 +1673,15 @@ public class Enqueuer { + traceStaticFieldRead(field, currentMethod, FieldAccessMetadata.FROM_METHOD_HANDLE); + } + +- void traceStaticFieldRead( ++ private void traceStaticFieldRead( + DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) { +- if (!metadata.isDeferred() && !registerFieldRead(fieldReference, currentMethod)) { ++ if (!registerFieldRead(fieldReference, currentMethod)) { + return; + } + + FieldResolutionResult resolutionResult = resolveField(fieldReference, currentMethod); +- +- if (appView.options().protoShrinking().enableGeneratedExtensionRegistryShrinking) { +- // If it is a dead proto extension field, don't trace onwards. +- boolean skipTracing = +- appView.withGeneratedExtensionRegistryShrinker( +- shrinker -> +- shrinker.isDeadProtoExtensionField( +- resolutionResult, fieldAccessInfoCollection, keepInfo), +- false); +- if (skipTracing) { +- addDeadProtoTypeCandidate(resolutionResult.getSingleProgramField().getHolder()); +- return; +- } +- } +- + if (deferredTracing.deferTracingOfFieldAccess( + fieldReference, resolutionResult, currentMethod, FieldAccessKind.STATIC_READ, metadata)) { +- assert !metadata.isDeferred(); + return; + } + +@@ -1833,6 +1712,18 @@ public class Enqueuer { + Log.verbose(getClass(), "Register Sget `%s`.", fieldReference); + } + ++ // If it is a dead proto extension field, don't trace onwards. ++ boolean skipTracing = ++ appView.withGeneratedExtensionRegistryShrinker( ++ shrinker -> ++ shrinker.isDeadProtoExtensionField( ++ field, fieldAccessInfoCollection, keepInfo), ++ false); ++ if (skipTracing) { ++ addDeadProtoTypeCandidate(field.getHolder()); ++ return; ++ } ++ + if (field.getReference() != fieldReference) { + // Mark the initial resolution holder as live. Note that this should only be done if + // the field +@@ -1862,31 +1753,15 @@ public class Enqueuer { + traceStaticFieldWrite(field, currentMethod, FieldAccessMetadata.FROM_METHOD_HANDLE); + } + +- void traceStaticFieldWrite( ++ private void traceStaticFieldWrite( + DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) { +- if (!metadata.isDeferred() && !registerFieldWrite(fieldReference, currentMethod)) { ++ if (!registerFieldWrite(fieldReference, currentMethod)) { + return; + } + + FieldResolutionResult resolutionResult = resolveField(fieldReference, currentMethod); +- +- if (appView.options().protoShrinking().enableGeneratedExtensionRegistryShrinking) { +- // If it is a dead proto extension field, don't trace onwards. +- boolean skipTracing = +- appView.withGeneratedExtensionRegistryShrinker( +- shrinker -> +- shrinker.isDeadProtoExtensionField( +- resolutionResult, fieldAccessInfoCollection, keepInfo), +- false); +- if (skipTracing) { +- addDeadProtoTypeCandidate(resolutionResult.getSingleProgramField().getHolder()); +- return; +- } +- } +- + if (deferredTracing.deferTracingOfFieldAccess( + fieldReference, resolutionResult, currentMethod, FieldAccessKind.STATIC_WRITE, metadata)) { +- assert !metadata.isDeferred(); + return; + } + +@@ -1917,6 +1792,20 @@ public class Enqueuer { + Log.verbose(getClass(), "Register Sput `%s`.", fieldReference); + } + ++ if (appView.options().protoShrinking().enableGeneratedExtensionRegistryShrinking) { ++ // If it is a dead proto extension field, don't trace onwards. ++ boolean skipTracing = ++ appView.withGeneratedExtensionRegistryShrinker( ++ shrinker -> ++ shrinker.isDeadProtoExtensionField( ++ field, fieldAccessInfoCollection, keepInfo), ++ false); ++ if (skipTracing) { ++ addDeadProtoTypeCandidate(field.getHolder()); ++ return; ++ } ++ } ++ + if (field.getReference() != fieldReference) { + // Mark the initial resolution holder as live. Note that this should only be done if + // the field +@@ -2006,7 +1895,7 @@ public class Enqueuer { + markTypeAsLive(clazz, graphReporter.reportClassReferencedFrom(clazz, context)); + } + +- void markTypeAsLive(DexProgramClass clazz, KeepReason reason) { ++ private void markTypeAsLive(DexProgramClass clazz, KeepReason reason) { + assert clazz != null; + markTypeAsLive( + clazz, +@@ -2377,7 +2266,7 @@ public class Enqueuer { + }); + } + +- void markDirectAndIndirectClassInitializersAsLive(DexProgramClass clazz) { ++ private void markDirectAndIndirectClassInitializersAsLive(DexProgramClass clazz) { + if (clazz.isInterface()) { + // Accessing a static field or method on an interface does not trigger the class initializer + // of any parent interfaces. +diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java +index 78abb5014..a09a35814 100644 +--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java ++++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java +@@ -4,66 +4,45 @@ + + package com.android.tools.r8.shaking; + +-import com.android.tools.r8.graph.AppInfoWithClassHierarchy; +-import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DexField; + import com.android.tools.r8.graph.FieldResolutionResult; +-import com.android.tools.r8.graph.ProgramField; + import com.android.tools.r8.graph.ProgramMethod; + import com.android.tools.r8.shaking.Enqueuer.FieldAccessKind; + import com.android.tools.r8.shaking.Enqueuer.FieldAccessMetadata; +-import com.android.tools.r8.shaking.Enqueuer.Mode; +-import com.android.tools.r8.utils.InternalOptions; + import java.util.concurrent.ExecutionException; + import java.util.concurrent.ExecutorService; + +-public abstract class EnqueuerDeferredTracing { +- +- public static EnqueuerDeferredTracing create( +- AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer, Mode mode) { +- if (mode.isInitialTreeShaking()) { +- return empty(); +- } +- InternalOptions options = appView.options(); +- if (!options.isOptimizing() +- || !options.isShrinking() +- || !options.enableEnqueuerDeferredTracing) { +- return empty(); +- } +- return new EnqueuerDeferredTracingImpl(appView, enqueuer, mode); +- } +- +- public static EmptyEnqueuerDeferredTracing empty() { +- return new EmptyEnqueuerDeferredTracing(); +- } ++public class EnqueuerDeferredTracing { + + /** +- * @return true if the {@link Enqueuer} should not trace the given field reference. +- * <p>If for some reason the field reference should be traced after all, a worklist item will +- * be enqueued upon reaching a (preliminary) fixpoint in {@link +- * #enqueueWorklistActions(EnqueuerWorklist)}, which will cause tracing to continue. ++ * Returns true if the {@link Enqueuer} should not trace the given field reference. ++ * ++ * <p>If for some reason the field reference should be traced after all, a worklist item can be ++ * enqueued upon reaching a (preliminary) fixpoint in {@link ++ * #enqueueWorklistActions(EnqueuerWorklist)}, which will cause tracing to continue. + */ +- public abstract boolean deferTracingOfFieldAccess( ++ public boolean deferTracingOfFieldAccess( + DexField fieldReference, + FieldResolutionResult resolutionResult, + ProgramMethod context, +- FieldAccessKind accessKind, +- FieldAccessMetadata metadata); ++ FieldAccessKind kind, ++ FieldAccessMetadata metadata) { ++ return false; ++ } + + /** + * Called when the {@link EnqueuerWorklist} is empty, to allow additional tracing before ending + * tree shaking. +- * +- * @return true if any worklist items were enqueued. + */ +- public abstract boolean enqueueWorklistActions(EnqueuerWorklist worklist); ++ public boolean enqueueWorklistActions(EnqueuerWorklist worklist) { ++ return false; ++ } + + /** + * Called when tree shaking has ended, to allow rewriting the application according to the tracing + * that has not been performed (e.g., rewriting of dead field instructions). + */ +- public abstract void rewriteApplication(ExecutorService executorService) +- throws ExecutionException; +- +- public abstract void notifyReflectiveFieldAccess(ProgramField field, ProgramMethod context); ++ public void rewriteApplication(ExecutorService executorService) throws ExecutionException { ++ // Intentionally empty. ++ } + } +diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java +deleted file mode 100644 +index 85d14b91e..000000000 +--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java ++++ /dev/null +@@ -1,282 +0,0 @@ +-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file +-// for details. All rights reserved. Use of this source code is governed by a +-// BSD-style license that can be found in the LICENSE file. +- +-package com.android.tools.r8.shaking; +- +-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull; +-import static com.android.tools.r8.shaking.ObjectAllocationInfoCollectionUtils.mayHaveFinalizeMethodDirectlyOrIndirectly; +-import static com.android.tools.r8.utils.MapUtils.ignoreKey; +- +-import com.android.tools.r8.graph.AppInfoWithClassHierarchy; +-import com.android.tools.r8.graph.AppView; +-import com.android.tools.r8.graph.Code; +-import com.android.tools.r8.graph.DexField; +-import com.android.tools.r8.graph.DexProgramClass; +-import com.android.tools.r8.graph.DexType; +-import com.android.tools.r8.graph.FieldAccessInfo; +-import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl; +-import com.android.tools.r8.graph.FieldResolutionResult; +-import com.android.tools.r8.graph.ProgramField; +-import com.android.tools.r8.graph.ProgramMethod; +-import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadataProvider; +-import com.android.tools.r8.ir.code.IRCode; +-import com.android.tools.r8.ir.conversion.IRFinalizer; +-import com.android.tools.r8.ir.conversion.IRToCfFinalizer; +-import com.android.tools.r8.ir.conversion.IRToDexFinalizer; +-import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions; +-import com.android.tools.r8.ir.optimize.membervaluepropagation.assume.AssumeInfo; +-import com.android.tools.r8.ir.optimize.membervaluepropagation.assume.AssumeInfoLookup; +-import com.android.tools.r8.shaking.Enqueuer.FieldAccessKind; +-import com.android.tools.r8.shaking.Enqueuer.FieldAccessMetadata; +-import com.android.tools.r8.shaking.Enqueuer.Mode; +-import com.android.tools.r8.shaking.EnqueuerWorklist.EnqueuerAction; +-import com.android.tools.r8.utils.InternalOptions; +-import com.android.tools.r8.utils.ThreadUtils; +-import com.android.tools.r8.utils.Timing; +-import com.android.tools.r8.utils.collections.ProgramFieldMap; +-import com.android.tools.r8.utils.collections.ProgramFieldSet; +-import com.android.tools.r8.utils.collections.ProgramMethodSet; +-import java.util.IdentityHashMap; +-import java.util.LinkedHashSet; +-import java.util.Map; +-import java.util.Set; +-import java.util.concurrent.ConcurrentHashMap; +-import java.util.concurrent.ExecutionException; +-import java.util.concurrent.ExecutorService; +- +-public class EnqueuerDeferredTracingImpl extends EnqueuerDeferredTracing { +- +- private final AppView<? extends AppInfoWithClassHierarchy> appView; +- private final Enqueuer enqueuer; +- private final Mode mode; +- private final InternalOptions options; +- +- // Helper for rewriting code instances at the end of tree shaking. +- private final EnqueuerDeferredTracingRewriter rewriter; +- +- // Maps each field to the tracing actions that have been deferred for that field. This allows +- // enqueuing previously deferred tracing actions into the worklist if a given field cannot be +- // optimized after all. +- private final ProgramFieldMap<Set<EnqueuerAction>> deferredEnqueuerActions = +- ProgramFieldMap.create(); +- +- // A set of fields that are never eligible for pruning. +- private final ProgramFieldSet ineligibleForPruning = ProgramFieldSet.create(); +- +- EnqueuerDeferredTracingImpl( +- AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer, Mode mode) { +- this.appView = appView; +- this.enqueuer = enqueuer; +- this.mode = mode; +- this.options = appView.options(); +- this.rewriter = new EnqueuerDeferredTracingRewriter(appView); +- } +- +- @Override +- public boolean deferTracingOfFieldAccess( +- DexField fieldReference, +- FieldResolutionResult resolutionResult, +- ProgramMethod context, +- FieldAccessKind accessKind, +- FieldAccessMetadata metadata) { +- ProgramField field = resolutionResult.getSingleProgramField(); +- if (field == null) { +- return false; +- } +- +- // Check if field access is consistent with the field access flags. +- if (field.getAccessFlags().isStatic() != accessKind.isStatic()) { +- return enqueueDeferredEnqueuerActions(field); +- } +- +- // If the access is from a reachability sensitive method, then bail out. +- if (context.getHolder().getOrComputeReachabilitySensitive(appView)) { +- return enqueueDeferredEnqueuerActions(field); +- } +- +- if (accessKind.isRead()) { +- // If the value of the field is not guaranteed to be the default value, even if it is never +- // assigned, then give up. +- // TODO(b/205810841): Allow this by handling this in the corresponding IR rewriter. +- AssumeInfo assumeInfo = AssumeInfoLookup.lookupAssumeInfo(appView, field); +- if (assumeInfo != null && assumeInfo.hasReturnInfo()) { +- return enqueueDeferredEnqueuerActions(field); +- } +- if (field.getAccessFlags().isStatic() && field.getDefinition().hasExplicitStaticValue()) { +- return enqueueDeferredEnqueuerActions(field); +- } +- } +- +- if (!isEligibleForPruning(field)) { +- return enqueueDeferredEnqueuerActions(field); +- } +- +- // Field can be removed unless some other field access that has not yet been seen prohibits it. +- // Record an EnqueuerAction that must be traced if that should happen. +- EnqueuerAction deferredEnqueuerAction = +- accessKind.toEnqueuerAction(fieldReference, context, metadata.toDeferred()); +- deferredEnqueuerActions +- .computeIfAbsent(field, ignoreKey(LinkedHashSet::new)) +- .add(deferredEnqueuerAction); +- +- // If the field is static, then the field access will trigger the class initializer of the +- // field's holder. Therefore, we unconditionally trace the class initializer in this case. +- // The corresponding IR rewriter will rewrite the field access into an init-class instruction. +- if (accessKind.isStatic()) { +- KeepReason reason = +- enqueuer.getGraphReporter().reportClassReferencedFrom(field.getHolder(), context); +- enqueuer.getWorklist().enqueueTraceTypeReferenceAction(field.getHolder(), reason); +- enqueuer.getWorklist().enqueueTraceDirectAndIndirectClassInitializers(field.getHolder()); +- } +- +- return true; +- } +- +- @Override +- public void notifyReflectiveFieldAccess(ProgramField field, ProgramMethod context) { +- enqueueDeferredEnqueuerActions(field); +- } +- +- private boolean isEligibleForPruning(ProgramField field) { +- if (enqueuer.isFieldLive(field)) { +- return false; +- } +- +- assert enqueuer.getKeepInfo(field).isBottom(); +- assert !enqueuer.getKeepInfo(field).isPinned(options); +- +- FieldAccessInfo info = enqueuer.getFieldAccessInfoCollection().get(field.getReference()); +- if (info.hasReflectiveAccess() +- || info.isAccessedFromMethodHandle() +- || info.isReadFromAnnotation() +- || info.isReadFromRecordInvokeDynamic() +- || enqueuer.hasMinimumKeepInfoThatMatches( +- field, +- minimumKeepInfo -> +- !minimumKeepInfo.isOptimizationAllowed() +- || !minimumKeepInfo.isShrinkingAllowed())) { +- return false; +- } +- +- if (info.isWritten()) { +- // If the assigned value may have an override of Object#finalize() then give up. +- // Note that this check depends on the set of instantiated types, and must therefore be rerun +- // when the enqueuer's fixpoint is reached. +- if (field.getType().isReferenceType()) { +- DexType fieldBaseType = field.getType().toBaseType(appView.dexItemFactory()); +- if (fieldBaseType.isClassType() +- && mayHaveFinalizeMethodDirectlyOrIndirectly( +- appView, fieldBaseType, enqueuer.getObjectAllocationInfoCollection())) { +- return false; +- } +- } +- } +- +- // We always have precise knowledge of field accesses during tracing. +- assert info.hasKnownReadContexts(); +- assert info.hasKnownWriteContexts(); +- +- DexType fieldType = field.getType(); +- +- // If the field is now both read and written, then we cannot optimize the field unless the field +- // type is an uninstantiated class type. +- if (info.getReadsWithContexts().hasAccesses() && info.getWritesWithContexts().hasAccesses()) { +- if (!fieldType.isClassType()) { +- return false; +- } +- DexProgramClass fieldTypeDefinition = asProgramClassOrNull(appView.definitionFor(fieldType)); +- if (fieldTypeDefinition == null +- || enqueuer +- .getObjectAllocationInfoCollection() +- .isInstantiatedDirectlyOrHasInstantiatedSubtype(fieldTypeDefinition)) { +- return false; +- } +- } +- +- return !ineligibleForPruning.contains(field); +- } +- +- private boolean enqueueDeferredEnqueuerActions(ProgramField field) { +- Set<EnqueuerAction> actions = deferredEnqueuerActions.remove(field); +- if (actions != null) { +- enqueuer.getWorklist().enqueueAll(actions); +- } +- ineligibleForPruning.add(field); +- return false; +- } +- +- @Override +- public boolean enqueueWorklistActions(EnqueuerWorklist worklist) { +- return deferredEnqueuerActions.removeIf( +- (field, worklistActions) -> { +- if (isEligibleForPruning(field)) { +- return false; +- } +- worklist.enqueueAll(worklistActions); +- return true; +- }); +- } +- +- @Override +- public void rewriteApplication(ExecutorService executorService) throws ExecutionException { +- FieldAccessInfoCollectionImpl fieldAccessInfoCollection = +- enqueuer.getFieldAccessInfoCollection(); +- ProgramMethodSet methodsToProcess = ProgramMethodSet.create(); +- Map<DexField, ProgramField> prunedFields = new IdentityHashMap<>(); +- deferredEnqueuerActions.forEach( +- (field, ignore) -> { +- FieldAccessInfo accessInfo = fieldAccessInfoCollection.get(field.getReference()); +- prunedFields.put(field.getReference(), field); +- accessInfo.forEachAccessContext(methodsToProcess::add); +- accessInfo.forEachIndirectAccess(reference -> prunedFields.put(reference, field)); +- }); +- deferredEnqueuerActions.clear(); +- +- // Rewrite application. +- Map<DexProgramClass, ProgramMethodSet> initializedClassesWithContexts = +- new ConcurrentHashMap<>(); +- ThreadUtils.processItems( +- methodsToProcess, +- method -> rewriteMethod(method, initializedClassesWithContexts, prunedFields), +- executorService); +- +- // Register new InitClass instructions. +- initializedClassesWithContexts.forEach( +- (clazz, contexts) -> +- contexts.forEach(context -> enqueuer.traceInitClass(clazz.getType(), context))); +- assert enqueuer.getWorklist().isEmpty(); +- +- // Prune field access info collection. +- prunedFields.values().forEach(field -> fieldAccessInfoCollection.remove(field.getReference())); +- } +- +- private void rewriteMethod( +- ProgramMethod method, +- Map<DexProgramClass, ProgramMethodSet> initializedClassesWithContexts, +- Map<DexField, ProgramField> prunedFields) { +- // Build IR. +- MutableMethodConversionOptions conversionOptions = +- mode.isInitialTreeShaking() +- ? new MutableMethodConversionOptions(options).setIsGeneratingClassFiles(true) +- : new MutableMethodConversionOptions(options); +- conversionOptions.disableStringSwitchConversion(); +- +- IRCode ir = method.buildIR(appView, conversionOptions); +- +- // Rewrite the IR according to the tracing that has been deferred. +- rewriter.rewriteCode(ir, initializedClassesWithContexts, prunedFields); +- +- // Run dead code elimination. +- rewriter.getCodeRewriter().optimizeAlwaysThrowingInstructions(ir); +- rewriter.getDeadCodeRemover().run(ir, Timing.empty()); +- +- // Finalize to class files or dex. +- IRFinalizer<?> finalizer = +- conversionOptions.isGeneratingClassFiles() +- ? new IRToCfFinalizer(appView, rewriter.getDeadCodeRemover()) +- : new IRToDexFinalizer(appView, rewriter.getDeadCodeRemover()); +- Code newCode = finalizer.finalizeCode(ir, BytecodeMetadataProvider.empty(), Timing.empty()); +- method.setCode(newCode, appView); +- } +-} +diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingRewriter.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingRewriter.java +deleted file mode 100644 +index 79165d119..000000000 +--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingRewriter.java ++++ /dev/null +@@ -1,228 +0,0 @@ +-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file +-// for details. All rights reserved. Use of this source code is governed by a +-// BSD-style license that can be found in the LICENSE file. +- +-package com.android.tools.r8.shaking; +- +-import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_GET; +-import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_PUT; +-import static com.android.tools.r8.ir.code.Opcodes.STATIC_GET; +-import static com.android.tools.r8.ir.code.Opcodes.STATIC_PUT; +-import static com.android.tools.r8.utils.MapUtils.ignoreKey; +- +-import com.android.tools.r8.graph.AppInfoWithClassHierarchy; +-import com.android.tools.r8.graph.AppView; +-import com.android.tools.r8.graph.DexField; +-import com.android.tools.r8.graph.DexProgramClass; +-import com.android.tools.r8.graph.ProgramField; +-import com.android.tools.r8.graph.ProgramMethod; +-import com.android.tools.r8.ir.analysis.type.TypeAnalysis; +-import com.android.tools.r8.ir.analysis.type.TypeElement; +-import com.android.tools.r8.ir.code.BasicBlock; +-import com.android.tools.r8.ir.code.BasicBlockIterator; +-import com.android.tools.r8.ir.code.FieldGet; +-import com.android.tools.r8.ir.code.IRCode; +-import com.android.tools.r8.ir.code.InitClass; +-import com.android.tools.r8.ir.code.InstanceFieldInstruction; +-import com.android.tools.r8.ir.code.InstanceGet; +-import com.android.tools.r8.ir.code.InstancePut; +-import com.android.tools.r8.ir.code.Instruction; +-import com.android.tools.r8.ir.code.InstructionListIterator; +-import com.android.tools.r8.ir.code.StaticGet; +-import com.android.tools.r8.ir.code.StaticPut; +-import com.android.tools.r8.ir.code.Value; +-import com.android.tools.r8.ir.optimize.CodeRewriter; +-import com.android.tools.r8.ir.optimize.DeadCodeRemover; +-import com.android.tools.r8.utils.collections.ProgramMethodSet; +-import com.google.common.collect.Sets; +-import java.util.Map; +-import java.util.Set; +- +-public class EnqueuerDeferredTracingRewriter { +- +- private final AppView<? extends AppInfoWithClassHierarchy> appView; +- private final CodeRewriter codeRewriter; +- private final DeadCodeRemover deadCodeRemover; +- +- EnqueuerDeferredTracingRewriter(AppView<? extends AppInfoWithClassHierarchy> appView) { +- this.appView = appView; +- this.codeRewriter = new CodeRewriter(appView); +- this.deadCodeRemover = new DeadCodeRemover(appView, codeRewriter); +- } +- +- public CodeRewriter getCodeRewriter() { +- return codeRewriter; +- } +- +- public DeadCodeRemover getDeadCodeRemover() { +- return deadCodeRemover; +- } +- +- public void rewriteCode( +- IRCode code, +- Map<DexProgramClass, ProgramMethodSet> initializedClassesWithContexts, +- Map<DexField, ProgramField> prunedFields) { +- // TODO(b/205810841): Consider inserting assume instructions to reduce number of null checks. +- // TODO(b/205810841): Consider running constant canonicalizer. +- ProgramMethod context = code.context(); +- +- // Rewrite field instructions that reference a pruned field. +- Set<Value> affectedValues = Sets.newIdentityHashSet(); +- BasicBlockIterator blockIterator = code.listIterator(); +- while (blockIterator.hasNext()) { +- BasicBlock block = blockIterator.next(); +- InstructionListIterator instructionIterator = block.listIterator(code); +- while (instructionIterator.hasNext()) { +- Instruction instruction = instructionIterator.next(); +- switch (instruction.opcode()) { +- case INSTANCE_GET: +- rewriteInstanceGet( +- code, +- instructionIterator, +- instruction.asInstanceGet(), +- affectedValues, +- prunedFields); +- break; +- case INSTANCE_PUT: +- rewriteInstancePut(instructionIterator, instruction.asInstancePut(), prunedFields); +- break; +- case STATIC_GET: +- rewriteStaticGet( +- code, +- instructionIterator, +- instruction.asStaticGet(), +- affectedValues, +- context, +- initializedClassesWithContexts, +- prunedFields); +- break; +- case STATIC_PUT: +- rewriteStaticPut( +- code, +- instructionIterator, +- instruction.asStaticPut(), +- context, +- initializedClassesWithContexts, +- prunedFields); +- break; +- default: +- break; +- } +- } +- } +- if (!affectedValues.isEmpty()) { +- new TypeAnalysis(appView).narrowing(affectedValues); +- } +- } +- +- private void rewriteInstanceGet( +- IRCode code, +- InstructionListIterator instructionIterator, +- InstanceGet instanceGet, +- Set<Value> affectedValues, +- Map<DexField, ProgramField> prunedFields) { +- ProgramField prunedField = prunedFields.get(instanceGet.getField()); +- if (prunedField == null) { +- return; +- } +- +- insertDefaultValueForFieldGet( +- code, instructionIterator, instanceGet, affectedValues, prunedField); +- removeOrReplaceInstanceFieldInstructionWithNullCheck(instructionIterator, instanceGet); +- } +- +- private void rewriteInstancePut( +- InstructionListIterator instructionIterator, +- InstancePut instancePut, +- Map<DexField, ProgramField> prunedFields) { +- ProgramField prunedField = prunedFields.get(instancePut.getField()); +- if (prunedField == null) { +- return; +- } +- +- removeOrReplaceInstanceFieldInstructionWithNullCheck(instructionIterator, instancePut); +- } +- +- private void rewriteStaticGet( +- IRCode code, +- InstructionListIterator instructionIterator, +- StaticGet staticGet, +- Set<Value> affectedValues, +- ProgramMethod context, +- Map<DexProgramClass, ProgramMethodSet> initializedClassesWithContexts, +- Map<DexField, ProgramField> prunedFields) { +- ProgramField prunedField = prunedFields.get(staticGet.getField()); +- if (prunedField == null) { +- return; +- } +- +- insertDefaultValueForFieldGet( +- code, instructionIterator, staticGet, affectedValues, prunedField); +- removeOrReplaceStaticFieldInstructionByInitClass( +- code, instructionIterator, context, initializedClassesWithContexts, prunedField); +- } +- +- private void rewriteStaticPut( +- IRCode code, +- InstructionListIterator instructionIterator, +- StaticPut staticPut, +- ProgramMethod context, +- Map<DexProgramClass, ProgramMethodSet> initializedClassesWithContexts, +- Map<DexField, ProgramField> prunedFields) { +- ProgramField prunedField = prunedFields.get(staticPut.getField()); +- if (prunedField == null) { +- return; +- } +- +- removeOrReplaceStaticFieldInstructionByInitClass( +- code, instructionIterator, context, initializedClassesWithContexts, prunedField); +- } +- +- private void insertDefaultValueForFieldGet( +- IRCode code, +- InstructionListIterator instructionIterator, +- FieldGet fieldGet, +- Set<Value> affectedValues, +- ProgramField prunedField) { +- if (fieldGet.hasUsedOutValue()) { +- instructionIterator.previous(); +- Value replacement = +- prunedField.getType().isReferenceType() +- ? instructionIterator.insertConstNullInstruction(code, appView.options()) +- : instructionIterator.insertConstNumberInstruction( +- code, appView.options(), 0, fieldGet.getOutType()); +- fieldGet.outValue().replaceUsers(replacement, affectedValues); +- instructionIterator.next(); +- } +- } +- +- private void removeOrReplaceInstanceFieldInstructionWithNullCheck( +- InstructionListIterator instructionIterator, InstanceFieldInstruction fieldInstruction) { +- if (fieldInstruction.object().isMaybeNull()) { +- instructionIterator.replaceCurrentInstructionWithNullCheck( +- appView, fieldInstruction.object()); +- } else { +- instructionIterator.removeOrReplaceByDebugLocalRead(); +- } +- } +- +- private void removeOrReplaceStaticFieldInstructionByInitClass( +- IRCode code, +- InstructionListIterator instructionIterator, +- ProgramMethod context, +- Map<DexProgramClass, ProgramMethodSet> initializedClassesWithContexts, +- ProgramField prunedField) { +- if (prunedField.getHolder().classInitializationMayHaveSideEffectsInContext(appView, context)) { +- instructionIterator.replaceCurrentInstruction( +- InitClass.builder() +- .setFreshOutValue(code, TypeElement.getInt()) +- .setType(prunedField.getHolderType()) +- .build()); +- initializedClassesWithContexts +- .computeIfAbsent(prunedField.getHolder(), ignoreKey(ProgramMethodSet::createConcurrent)) +- .add(context); +- } else { +- instructionIterator.removeOrReplaceByDebugLocalRead(); +- } +- } +-} +diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java +index a09efe6ba..0efc4b58c 100644 +--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java ++++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java +@@ -11,17 +11,12 @@ import com.android.tools.r8.graph.DexField; + import com.android.tools.r8.graph.DexMethod; + import com.android.tools.r8.graph.DexProgramClass; + import com.android.tools.r8.graph.DexType; +-import com.android.tools.r8.graph.FieldAccessInfo; + import com.android.tools.r8.graph.ProgramDefinition; + import com.android.tools.r8.graph.ProgramField; + import com.android.tools.r8.graph.ProgramMethod; +-import com.android.tools.r8.shaking.Enqueuer.FieldAccessKind; +-import com.android.tools.r8.shaking.Enqueuer.FieldAccessMetadata; + import com.android.tools.r8.shaking.GraphReporter.KeepReasonWitness; + import com.android.tools.r8.utils.Action; + import com.android.tools.r8.utils.InternalOptions; +-import java.util.Collection; +-import java.util.Objects; + import java.util.Queue; + import java.util.concurrent.ConcurrentLinkedQueue; + +@@ -246,19 +241,6 @@ public abstract class EnqueuerWorklist { + } + } + +- static class TraceDirectAndIndirectClassInitializers extends EnqueuerAction { +- private final DexProgramClass clazz; +- +- TraceDirectAndIndirectClassInitializers(DexProgramClass clazz) { +- this.clazz = clazz; +- } +- +- @Override +- public void run(Enqueuer enqueuer) { +- enqueuer.markDirectAndIndirectClassInitializersAsLive(clazz); +- } +- } +- + static class TraceInvokeDirectAction extends EnqueuerAction { + private final DexMethod invokedMethod; + // TODO(b/175854431): Avoid pushing context on worklist. +@@ -320,199 +302,19 @@ public abstract class EnqueuerWorklist { + } + } + +- static class TraceReflectiveFieldAccessAction extends EnqueuerAction { +- private final ProgramField field; ++ static class TraceStaticFieldReadAction extends EnqueuerAction { ++ private final DexField field; ++ // TODO(b/175854431): Avoid pushing context on worklist. + private final ProgramMethod context; +- private final FieldAccessKind kind; + +- TraceReflectiveFieldAccessAction(ProgramField field, ProgramMethod context) { +- this(field, context, null); +- } +- +- TraceReflectiveFieldAccessAction( +- ProgramField field, ProgramMethod context, FieldAccessKind kind) { ++ TraceStaticFieldReadAction(DexField field, ProgramMethod context) { + this.field = field; + this.context = context; +- this.kind = kind; +- } +- +- @Override +- public void run(Enqueuer enqueuer) { +- if (kind != null) { +- if (kind.isRead()) { +- enqueuer.traceReflectiveFieldRead(field, context); +- } else { +- enqueuer.traceReflectiveFieldWrite(field, context); +- } +- } else { +- enqueuer.traceReflectiveFieldAccess(field, context); +- } +- } +- } +- +- static class TraceTypeReferenceAction extends EnqueuerAction { +- private final DexProgramClass clazz; +- private final KeepReason reason; +- +- TraceTypeReferenceAction(DexProgramClass clazz, KeepReason reason) { +- this.clazz = clazz; +- this.reason = reason; + } + + @Override + public void run(Enqueuer enqueuer) { +- enqueuer.markTypeAsLive(clazz, reason); +- } +- } +- +- abstract static class TraceFieldAccessAction extends EnqueuerAction { +- protected final DexField field; +- // TODO(b/175854431): Avoid pushing context on worklist. +- protected final ProgramMethod context; +- protected final FieldAccessMetadata metadata; +- +- TraceFieldAccessAction(DexField field, ProgramMethod context, FieldAccessMetadata metadata) { +- this.field = field; +- this.context = context; +- this.metadata = metadata; +- } +- +- protected boolean baseEquals(TraceFieldAccessAction action) { +- return field == action.field +- && context.isStructurallyEqualTo(action.context) +- && metadata.equals(action.metadata); +- } +- +- @Override +- public boolean equals(Object obj) { +- if (this == obj) { +- return true; +- } +- if (obj == null || getClass() != obj.getClass()) { +- return false; +- } +- TraceFieldAccessAction action = (TraceFieldAccessAction) obj; +- return baseEquals(action); +- } +- +- @Override +- public int hashCode() { +- return Objects.hash(field, context.getReference(), metadata); +- } +- } +- +- static class TraceInstanceFieldReadAction extends TraceFieldAccessAction { +- +- TraceInstanceFieldReadAction( +- DexField field, ProgramMethod context, FieldAccessMetadata metadata) { +- super(field, context, metadata); +- } +- +- @Override +- public void run(Enqueuer enqueuer) { +- enqueuer.traceInstanceFieldRead(field, context, metadata); +- } +- +- @Override +- public boolean equals(Object obj) { +- if (this == obj) { +- return true; +- } +- if (obj == null || getClass() != obj.getClass()) { +- return false; +- } +- TraceInstanceFieldReadAction action = (TraceInstanceFieldReadAction) obj; +- return baseEquals(action); +- } +- +- @Override +- public int hashCode() { +- return Objects.hash(field, context.getReference(), metadata); +- } +- } +- +- static class TraceInstanceFieldWriteAction extends TraceFieldAccessAction { +- +- TraceInstanceFieldWriteAction( +- DexField field, ProgramMethod context, FieldAccessMetadata metadata) { +- super(field, context, metadata); +- } +- +- @Override +- public void run(Enqueuer enqueuer) { +- enqueuer.traceInstanceFieldWrite(field, context, metadata); +- } +- +- @Override +- public boolean equals(Object obj) { +- if (this == obj) { +- return true; +- } +- if (obj == null || getClass() != obj.getClass()) { +- return false; +- } +- TraceInstanceFieldWriteAction action = (TraceInstanceFieldWriteAction) obj; +- return baseEquals(action); +- } +- +- @Override +- public int hashCode() { +- return Objects.hash(field, context.getReference(), metadata); +- } +- } +- +- static class TraceStaticFieldReadAction extends TraceFieldAccessAction { +- +- TraceStaticFieldReadAction( +- DexField field, ProgramMethod context, FieldAccessMetadata metadata) { +- super(field, context, metadata); +- } +- +- @Override +- public void run(Enqueuer enqueuer) { +- enqueuer.traceStaticFieldRead(field, context, metadata); +- } +- +- @Override +- public boolean equals(Object obj) { +- if (this == obj) { +- return true; +- } +- if (obj == null || getClass() != obj.getClass()) { +- return false; +- } +- TraceStaticFieldReadAction action = (TraceStaticFieldReadAction) obj; +- return baseEquals(action); +- } +- } +- +- static class TraceStaticFieldWriteAction extends TraceFieldAccessAction { +- +- TraceStaticFieldWriteAction( +- DexField field, ProgramMethod context, FieldAccessMetadata metadata) { +- super(field, context, metadata); +- } +- +- @Override +- public void run(Enqueuer enqueuer) { +- enqueuer.traceStaticFieldWrite(field, context, metadata); +- } +- +- @Override +- public boolean equals(Object obj) { +- if (this == obj) { +- return true; +- } +- if (obj == null || getClass() != obj.getClass()) { +- return false; +- } +- TraceStaticFieldWriteAction action = (TraceStaticFieldWriteAction) obj; +- return baseEquals(action); +- } +- +- @Override +- public int hashCode() { +- return Objects.hash(field, context.getReference(), metadata); ++ enqueuer.traceStaticFieldRead(field, context); + } + } + +@@ -538,12 +340,6 @@ public abstract class EnqueuerWorklist { + + abstract EnqueuerWorklist nonPushable(); + +- final void enqueueAll(Collection<? extends EnqueuerAction> actions) { +- actions.forEach(this::enqueue); +- } +- +- abstract void enqueue(EnqueuerAction action); +- + abstract boolean enqueueAssertAction(Action assertion); + + abstract void enqueueMarkReachableDirectAction( +@@ -581,8 +377,6 @@ public abstract class EnqueuerWorklist { + public abstract void enqueueTraceConstClassAction( + DexType type, ProgramMethod context, boolean ignoreCompatRules); + +- public abstract void enqueueTraceDirectAndIndirectClassInitializers(DexProgramClass clazz); +- + public abstract void enqueueTraceInvokeDirectAction( + DexMethod invokedMethod, ProgramMethod context); + +@@ -591,19 +385,8 @@ public abstract class EnqueuerWorklist { + + public abstract void enqueueTraceNewInstanceAction(DexType type, ProgramMethod context); + +- public abstract void enqueueTraceReflectiveFieldAccessAction( +- ProgramField field, ProgramMethod context); +- +- public abstract void enqueueTraceReflectiveFieldReadAction( +- ProgramField field, ProgramMethod context); +- +- public abstract void enqueueTraceReflectiveFieldWriteAction( +- ProgramField field, ProgramMethod context); +- + public abstract void enqueueTraceStaticFieldRead(DexField field, ProgramMethod context); + +- public abstract void enqueueTraceTypeReferenceAction(DexProgramClass clazz, KeepReason reason); +- + static class PushableEnqueuerWorkList extends EnqueuerWorklist { + + PushableEnqueuerWorkList(Enqueuer enqueuer) { +@@ -615,11 +398,6 @@ public abstract class EnqueuerWorklist { + return new NonPushableEnqueuerWorklist(this); + } + +- @Override +- void enqueue(EnqueuerAction action) { +- queue.add(action); +- } +- + @Override + boolean enqueueAssertAction(Action assertion) { + if (InternalOptions.assertionsEnabled()) { +@@ -713,11 +491,6 @@ public abstract class EnqueuerWorklist { + queue.add(new TraceConstClassAction(type, context, ignoreCompatRules)); + } + +- @Override +- public void enqueueTraceDirectAndIndirectClassInitializers(DexProgramClass clazz) { +- queue.add(new TraceDirectAndIndirectClassInitializers(clazz)); +- } +- + @Override + public void enqueueTraceInvokeDirectAction(DexMethod invokedMethod, ProgramMethod context) { + queue.add(new TraceInvokeDirectAction(invokedMethod, context)); +@@ -733,50 +506,9 @@ public abstract class EnqueuerWorklist { + queue.add(new TraceNewInstanceAction(type, context)); + } + +- @Override +- public void enqueueTraceReflectiveFieldAccessAction(ProgramField field, ProgramMethod context) { +- FieldAccessInfo info = enqueuer.getFieldAccessInfoCollection().get(field.getReference()); +- if (info == null || !info.hasReflectiveAccess()) { +- queue.add(new TraceReflectiveFieldAccessAction(field, context)); +- } +- } +- +- @Override +- public void enqueueTraceReflectiveFieldReadAction(ProgramField field, ProgramMethod context) { +- FieldAccessInfo info = enqueuer.getFieldAccessInfoCollection().get(field.getReference()); +- if (info == null || !info.hasReflectiveRead()) { +- queue.add( +- new TraceReflectiveFieldAccessAction( +- field, +- context, +- field.getAccessFlags().isStatic() +- ? FieldAccessKind.STATIC_READ +- : FieldAccessKind.INSTANCE_READ)); +- } +- } +- +- @Override +- public void enqueueTraceReflectiveFieldWriteAction(ProgramField field, ProgramMethod context) { +- FieldAccessInfo info = enqueuer.getFieldAccessInfoCollection().get(field.getReference()); +- if (info == null || !info.hasReflectiveWrite()) { +- queue.add( +- new TraceReflectiveFieldAccessAction( +- field, +- context, +- field.getAccessFlags().isStatic() +- ? FieldAccessKind.STATIC_WRITE +- : FieldAccessKind.INSTANCE_WRITE)); +- } +- } +- + @Override + public void enqueueTraceStaticFieldRead(DexField field, ProgramMethod context) { +- queue.add(new TraceStaticFieldReadAction(field, context, FieldAccessMetadata.DEFAULT)); +- } +- +- @Override +- public void enqueueTraceTypeReferenceAction(DexProgramClass clazz, KeepReason reason) { +- queue.add(new TraceTypeReferenceAction(clazz, reason)); ++ queue.add(new TraceStaticFieldReadAction(field, context)); + } + } + +@@ -791,11 +523,6 @@ public abstract class EnqueuerWorklist { + return this; + } + +- @Override +- void enqueue(EnqueuerAction action) { +- throw attemptToEnqueue(); +- } +- + private Unreachable attemptToEnqueue() { + throw new Unreachable("Attempt to enqueue an action in a non pushable enqueuer work list."); + } +@@ -886,11 +613,6 @@ public abstract class EnqueuerWorklist { + throw attemptToEnqueue(); + } + +- @Override +- public void enqueueTraceDirectAndIndirectClassInitializers(DexProgramClass clazz) { +- throw attemptToEnqueue(); +- } +- + @Override + public void enqueueTraceInvokeDirectAction(DexMethod invokedMethod, ProgramMethod context) { + throw attemptToEnqueue(); +@@ -906,29 +628,9 @@ public abstract class EnqueuerWorklist { + throw attemptToEnqueue(); + } + +- @Override +- public void enqueueTraceReflectiveFieldAccessAction(ProgramField field, ProgramMethod context) { +- throw attemptToEnqueue(); +- } +- +- @Override +- public void enqueueTraceReflectiveFieldReadAction(ProgramField field, ProgramMethod context) { +- throw attemptToEnqueue(); +- } +- +- @Override +- public void enqueueTraceReflectiveFieldWriteAction(ProgramField field, ProgramMethod context) { +- throw attemptToEnqueue(); +- } +- + @Override + public void enqueueTraceStaticFieldRead(DexField field, ProgramMethod context) { + throw attemptToEnqueue(); + } +- +- @Override +- public void enqueueTraceTypeReferenceAction(DexProgramClass clazz, KeepReason reason) { +- throw attemptToEnqueue(); +- } + } + } +diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java +index 9595b06a2..f48d65523 100644 +--- a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java ++++ b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java +@@ -511,10 +511,6 @@ public abstract class KeepInfo<B extends Builder<B, K>, K extends KeepInfo<B, K> + return null; + } + +- public static KeepFieldInfo.Joiner asFieldJoinerOrNull(Joiner<?, ?, ?> joiner) { +- return joiner != null ? joiner.asFieldJoiner() : null; +- } +- + public KeepMethodInfo.Joiner asMethodJoiner() { + return null; + } +@@ -535,10 +531,6 @@ public abstract class KeepInfo<B extends Builder<B, K>, K extends KeepInfo<B, K> + return builder.isCheckDiscardedEnabled(); + } + +- public boolean isOptimizationAllowed() { +- return builder.isOptimizationAllowed(); +- } +- + public boolean isShrinkingAllowed() { + return builder.isShrinkingAllowed(); + } +diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java +index 1d7f54c88..1e2a1ff9e 100644 +--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java ++++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java +@@ -611,9 +611,6 @@ public class InternalOptions implements GlobalKeepInfoConfiguration { + // public boolean lookupLibraryBeforeProgram = + // System.getProperty("com.android.tools.r8.lookupProgramBeforeLibrary") == null; + +- public boolean enableEnqueuerDeferredTracing = +- System.getProperty("com.android.tools.r8.disableEnqueuerDeferredTracing") == null; +- + public boolean loadAllClassDefinitions = false; + + // Whether or not to check for valid multi-dex builds. +diff --git a/src/main/java/com/android/tools/r8/utils/collections/ProgramMemberMap.java b/src/main/java/com/android/tools/r8/utils/collections/ProgramMemberMap.java +index 8292f1432..b14dd8606 100644 +--- a/src/main/java/com/android/tools/r8/utils/collections/ProgramMemberMap.java ++++ b/src/main/java/com/android/tools/r8/utils/collections/ProgramMemberMap.java +@@ -71,10 +71,8 @@ public abstract class ProgramMemberMap<K extends ProgramMember<?, ?>, V> { + return backing.remove(wrap(member)); + } + +- public boolean removeIf(BiPredicate<K, V> predicate) { +- return backing +- .entrySet() +- .removeIf(entry -> predicate.test(entry.getKey().get(), entry.getValue())); ++ public void removeIf(BiPredicate<K, V> predicate) { ++ backing.entrySet().removeIf(entry -> predicate.test(entry.getKey().get(), entry.getValue())); + } + + abstract Wrapper<K> wrap(K member); +diff --git a/src/test/java/com/android/tools/r8/internal/proto/Proto2ShrinkingTest.java b/src/test/java/com/android/tools/r8/internal/proto/Proto2ShrinkingTest.java +index 51acd6592..63dae9c99 100644 +--- a/src/test/java/com/android/tools/r8/internal/proto/Proto2ShrinkingTest.java ++++ b/src/test/java/com/android/tools/r8/internal/proto/Proto2ShrinkingTest.java +@@ -23,7 +23,6 @@ import com.google.common.collect.ImmutableList; + import com.google.common.collect.ImmutableSet; + import java.nio.file.Path; + import java.util.List; +-import org.junit.Ignore; + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runners.Parameterized; +diff --git a/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java b/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java +index 9d4d133e3..f191b3ba4 100644 +--- a/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java ++++ b/src/test/java/com/android/tools/r8/ir/LinearFlowIteratorTest.java +@@ -111,9 +111,10 @@ public class LinearFlowIteratorTest extends TestBase { + public void nextWillContinueThroughGotoBlocks() throws Exception { + IRCode code = simpleCode(); + InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.entryBlock()); +- assertTrue(it.next().isArgument()); +- assertTrue(it.next().isConstNumber()); +- assertTrue(it.next().isThrow()); ++ it.next(); // Argument ++ it.next(); // ConstNumber 0/NULL ++ it.next(); // ArrayGet ++ assert it.next().isReturn(); // Return + } + + @Test +@@ -153,8 +154,9 @@ public class LinearFlowIteratorTest extends TestBase { + InstructionListIterator it = new LinearFlowInstructionListIterator(code, code.blocks.get(1)); + Instruction current = it.previous(); + assertTrue(current.isConstNumber() && current.getOutType().isReferenceType()); +- assertTrue(it.next().isConstNumber()); +- assertTrue(it.next().isThrow()); ++ it.next(); ++ current = it.next(); ++ assertTrue(current.isArrayGet()); + } + + @Test +diff --git a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java +index 9cd0f5ff4..cb8c9f51c 100644 +--- a/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java ++++ b/src/test/java/com/android/tools/r8/ir/optimize/staticizer/ClassStaticizerTest.java +@@ -334,7 +334,8 @@ public class ClassStaticizerTest extends TestBase { + "DIRECT: void movetohost.HostConflictField.<init>()", + "STATIC: String movetohost.CandidateConflictField.bar(String)", + "STATIC: String movetohost.CandidateConflictField.foo()", +- "STATIC: String movetohost.MoveToHostTestClass.next()"), ++ "STATIC: String movetohost.MoveToHostTestClass.next()", ++ "String movetohost.CandidateConflictField.field"), + references(clazz, "testConflictField", "void")); + + assertThat(inspector.clazz(CandidateConflictMethod.class), isPresent()); +diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java +index 2100549ea..712953929 100644 +--- a/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java ++++ b/src/test/java/com/android/tools/r8/ir/regalloc/RegisterMoveSchedulerTest.java +@@ -7,6 +7,7 @@ import static org.junit.Assert.assertEquals; + + import com.android.tools.r8.errors.Unimplemented; + import com.android.tools.r8.graph.AppInfo; ++import com.android.tools.r8.graph.AppInfoWithClassHierarchy; + import com.android.tools.r8.graph.AppView; + import com.android.tools.r8.graph.DebugLocalInfo; + import com.android.tools.r8.graph.DexApplication; +@@ -111,11 +112,6 @@ public class RegisterMoveSchedulerTest { + throw new Unimplemented(); + } + +- @Override +- public void replaceCurrentInstructionWithNullCheck(AppView<?> appView, Value object) { +- throw new Unimplemented(); +- } +- + @Override + public void replaceCurrentInstructionWithStaticGet( + AppView<?> appView, IRCode code, DexField field, Set<Value> affectedValues) { +@@ -135,7 +131,7 @@ public class RegisterMoveSchedulerTest { + + @Override + public void replaceCurrentInstructionWithThrowNull( +- AppView<?> appView, ++ AppView<? extends AppInfoWithClassHierarchy> appView, + IRCode code, + ListIterator<BasicBlock> blockIterator, + Set<BasicBlock> blocksToRemove, +diff --git a/src/test/java/com/android/tools/r8/missingclasses/MissingClassReferencedFromFieldAnnotationTest.java b/src/test/java/com/android/tools/r8/missingclasses/MissingClassReferencedFromFieldAnnotationTest.java +index c0c9739b9..71e9638c5 100644 +--- a/src/test/java/com/android/tools/r8/missingclasses/MissingClassReferencedFromFieldAnnotationTest.java ++++ b/src/test/java/com/android/tools/r8/missingclasses/MissingClassReferencedFromFieldAnnotationTest.java +@@ -31,20 +31,13 @@ public class MissingClassReferencedFromFieldAnnotationTest extends MissingClasse + @Test(expected = CompilationFailedException.class) + public void testNoRules() throws Exception { + compileWithExpectedDiagnostics( +- Main.class, +- diagnostics -> inspectDiagnosticsWithNoRules(diagnostics, referencedFrom), +- builder -> builder.addKeepClassAndMembersRules(Main.class)); ++ Main.class, diagnostics -> inspectDiagnosticsWithNoRules(diagnostics, referencedFrom)); + } + + @Test + public void testDontWarnMainClass() throws Exception { + compileWithExpectedDiagnostics( +- Main.class, +- TestDiagnosticMessages::assertNoMessages, +- builder -> +- builder +- .addDontWarn(MissingRuntimeAnnotation.class) +- .addKeepClassAndMembersRules(Main.class)); ++ Main.class, TestDiagnosticMessages::assertNoMessages, addDontWarn(Main.class)); + } + + @Test +@@ -52,10 +45,7 @@ public class MissingClassReferencedFromFieldAnnotationTest extends MissingClasse + compileWithExpectedDiagnostics( + Main.class, + TestDiagnosticMessages::assertNoMessages, +- builder -> +- builder +- .addDontWarn(MissingRuntimeAnnotation.class) +- .addKeepClassAndMembersRules(Main.class)); ++ addDontWarn(MissingRuntimeAnnotation.class)); + } + + @Test +@@ -63,11 +53,7 @@ public class MissingClassReferencedFromFieldAnnotationTest extends MissingClasse + compileWithExpectedDiagnostics( + Main.class, + diagnostics -> inspectDiagnosticsWithIgnoreWarnings(diagnostics, referencedFrom), +- builder -> +- builder +- .addIgnoreWarnings() +- .addKeepClassAndMembersRules(Main.class) +- .allowDiagnosticWarningMessages()); ++ addIgnoreWarnings()); + } + + @Override +diff --git a/src/test/java/com/android/tools/r8/rewrite/assertions/kotlinassertionhandlersimple/AssertionConfigurationAssertionHandlerKotlinSimpleTest.java b/src/test/java/com/android/tools/r8/rewrite/assertions/kotlinassertionhandlersimple/AssertionConfigurationAssertionHandlerKotlinSimpleTest.java +deleted file mode 100644 +index aad753e5a..000000000 +--- a/src/test/java/com/android/tools/r8/rewrite/assertions/kotlinassertionhandlersimple/AssertionConfigurationAssertionHandlerKotlinSimpleTest.java ++++ /dev/null +@@ -1,81 +0,0 @@ +-// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file +-// for details. All rights reserved. Use of this source code is governed by a +-// BSD-style license that can be found in the LICENSE file. +- +-package com.android.tools.r8.rewrite.assertions.kotlinassertionhandlersimple; +- +-import static org.hamcrest.CoreMatchers.equalTo; +- +-import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion; +-import com.android.tools.r8.KotlinTestParameters; +-import com.android.tools.r8.R8FullTestBuilder; +-import com.android.tools.r8.R8TestCompileResult; +-import com.android.tools.r8.TestParameters; +-import com.android.tools.r8.references.MethodReference; +-import com.android.tools.r8.references.Reference; +-import com.android.tools.r8.rewrite.assertions.AssertionConfigurationAssertionHandlerKotlinTestBase; +-import com.android.tools.r8.rewrite.assertions.assertionhandler.AssertionHandlers; +-import com.android.tools.r8.utils.StringUtils; +-import java.io.IOException; +-import java.nio.file.Path; +-import java.util.List; +-import org.junit.runner.RunWith; +-import org.junit.runners.Parameterized; +- +-@RunWith(Parameterized.class) +-public class AssertionConfigurationAssertionHandlerKotlinSimpleTest +- extends AssertionConfigurationAssertionHandlerKotlinTestBase { +- +- public AssertionConfigurationAssertionHandlerKotlinSimpleTest( +- TestParameters parameters, +- KotlinTestParameters kotlinParameters, +- boolean kotlinStdlibAsClasspath, +- boolean useJvmAssertions) +- throws IOException { +- super(parameters, kotlinParameters, kotlinStdlibAsClasspath, useJvmAssertions); +- } +- +- @Override +- protected String getExpectedOutput() { +- return StringUtils.lines( +- "assertionHandler: simpleAssertion", +- "assertionHandler: multipleAssertions 1", +- "assertionHandler: multipleAssertions 2"); +- } +- +- @Override +- protected MethodReference getAssertionHandler() throws Exception { +- return Reference.methodFromMethod( +- AssertionHandlers.class.getMethod("assertionHandler", Throwable.class)); +- } +- +- @Override +- protected List<Path> getKotlinFiles() throws IOException { +- return getKotlinFilesInTestPackage(getClass().getPackage()); +- } +- +- @Override +- protected String getTestClassName() { +- return getClass().getPackage().getName() + ".AssertionSimpleKt"; +- } +- +- @Override +- protected void configureR8(R8FullTestBuilder builder) { +- boolean referencesNotNull = +- !kotlinParameters.is(KotlinCompilerVersion.KOTLINC_1_3_72) +- && !kotlinStdlibAsLibrary +- && !useJvmAssertions; +- builder +- .applyIf(referencesNotNull, b -> b.addDontWarn("org.jetbrains.annotations.NotNull")) +- .allowDiagnosticWarningMessages(!kotlinStdlibAsLibrary); +- } +- +- @Override +- protected void configureResultR8(R8TestCompileResult builder) { +- builder.applyIf( +- !kotlinStdlibAsLibrary, +- result -> +- result.assertAllWarningMessagesMatch( +- equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))); +- } +-} +diff --git a/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java b/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java +index bb63e6fc8..fda8843bd 100644 +--- a/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java ++++ b/src/test/java/com/android/tools/r8/shaking/InvalidTypesTest.java +@@ -8,6 +8,7 @@ import static org.hamcrest.CoreMatchers.allOf; + import static org.hamcrest.CoreMatchers.anyOf; + import static org.hamcrest.CoreMatchers.containsString; + import static org.hamcrest.CoreMatchers.equalTo; ++import static org.hamcrest.core.IsNot.not; + + import com.android.tools.r8.D8TestRunResult; + import com.android.tools.r8.DXTestRunResult; +@@ -70,6 +71,11 @@ public class InvalidTypesTest extends JasminTestBase { + + case DX: + case D8: ++ case R8: ++ if (parameters.isCfRuntime()) { ++ assert compiler == Compiler.R8; ++ return StringUtils.joinLines("Hello!", "Goodbye!", ""); ++ } + switch (parameters.getDexRuntimeVersion()) { + case V4_0_4: + case V4_4_4: +@@ -98,14 +104,6 @@ public class InvalidTypesTest extends JasminTestBase { + throw new Unreachable(); + } + +- case R8: +- return StringUtils.joinLines( +- "Hello!", +- "Unexpected outcome of getstatic", +- "Unexpected outcome of checkcast", +- "Goodbye!", +- ""); +- + case PROGUARD: + return StringUtils.joinLines( + "Hello!", "Unexpected outcome of checkcast", "Goodbye!", ""); +@@ -125,6 +123,10 @@ public class InvalidTypesTest extends JasminTestBase { + @Override + public String getExpectedOutput( + Compiler compiler, TestParameters parameters, boolean useInterface) { ++ if (useInterface) { ++ return StringUtils.joinLines("Hello!", "In verifiable method!", "Goodbye!", ""); ++ } ++ + switch (compiler) { + case R8: + case PROGUARD: +@@ -133,9 +135,6 @@ public class InvalidTypesTest extends JasminTestBase { + return StringUtils.joinLines("Hello!", "In verifiable method!", "Goodbye!", ""); + + default: +- if (useInterface) { +- return StringUtils.joinLines("Hello!", "In verifiable method!", "Goodbye!", ""); +- } + // The code fails with a verification error because the verifiableMethod() is being + // called on UnverifiableClass, which does not verify due to unverifiableMethod(). + return StringUtils.joinLines("Hello!", ""); +@@ -330,12 +329,17 @@ public class InvalidTypesTest extends JasminTestBase { + break; + + case INVOKE_VERIFIABLE_METHOD_ON_UNVERIFIABLE_CLASS: +- if (useInterface || compiler == Compiler.R8 || compiler == Compiler.PROGUARD) { ++ if (useInterface) { + result.assertSuccessWithOutput(getExpectedOutput(compiler)); + } else { +- result +- .assertFailureWithOutput(getExpectedOutput(compiler)) +- .assertFailureWithErrorThatMatches(getMatcherForExpectedError(compiler)); ++ if (compiler == Compiler.R8 ++ || compiler == Compiler.PROGUARD) { ++ result.assertSuccessWithOutput(getExpectedOutput(compiler)); ++ } else { ++ result ++ .assertFailureWithOutput(getExpectedOutput(compiler)) ++ .assertFailureWithErrorThatMatches(getMatcherForExpectedError()); ++ } + } + break; + +@@ -343,9 +347,18 @@ public class InvalidTypesTest extends JasminTestBase { + if (useInterface) { + result.assertSuccessWithOutput(getExpectedOutput(compiler)); + } else { +- result +- .assertFailureWithOutput(getExpectedOutput(compiler)) +- .assertFailureWithErrorThatMatches(getMatcherForExpectedError(compiler)); ++ if (compiler == Compiler.R8) { ++ result ++ .assertFailureWithOutput(getExpectedOutput(compiler)) ++ .assertFailureWithErrorThatMatches( ++ allOf( ++ containsString("java.lang.NullPointerException"), ++ not(containsString("java.lang.VerifyError")))); ++ } else { ++ result ++ .assertFailureWithOutput(getExpectedOutput(compiler)) ++ .assertFailureWithErrorThatMatches(getMatcherForExpectedError()); ++ } + } + break; + +@@ -358,10 +371,7 @@ public class InvalidTypesTest extends JasminTestBase { + return mode.getExpectedOutput(compiler, parameters, useInterface); + } + +- private Matcher<String> getMatcherForExpectedError(Compiler compiler) { +- if (compiler == Compiler.R8 && mode == Mode.INVOKE_UNVERIFIABLE_METHOD) { +- return containsString("java.lang.NullPointerException"); +- } ++ private Matcher<String> getMatcherForExpectedError() { + if (parameters.isCfRuntime()) { + return allOf( + containsString("java.lang.VerifyError"), +diff --git a/src/test/java/com/android/tools/r8/shaking/KeepClassMembersFieldTest.java b/src/test/java/com/android/tools/r8/shaking/KeepClassMembersFieldTest.java +index 05cec263b..ff09c75a5 100644 +--- a/src/test/java/com/android/tools/r8/shaking/KeepClassMembersFieldTest.java ++++ b/src/test/java/com/android/tools/r8/shaking/KeepClassMembersFieldTest.java +@@ -4,13 +4,14 @@ + + package com.android.tools.r8.shaking; + +-import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; +-import static org.hamcrest.MatcherAssert.assertThat; ++import static org.junit.Assert.assertFalse; + + import com.android.tools.r8.TestBase; + import com.android.tools.r8.TestParameters; + import com.android.tools.r8.TestParametersCollection; + import com.android.tools.r8.utils.StringUtils; ++import com.android.tools.r8.utils.codeinspector.FoundFieldSubject; ++import java.util.List; + import org.junit.Test; + import org.junit.runner.RunWith; + import org.junit.runners.Parameterized; +@@ -20,10 +21,11 @@ import org.junit.runners.Parameterized.Parameters; + public class KeepClassMembersFieldTest extends TestBase { + + private static final String KEEP_RULE = +- StringUtils.lines( +- "-keepclassmembers,allowshrinking class " + Foo.class.getTypeName() + " {", +- " <fields>;", +- "}"); ++ "-keepclassmembers,allowshrinking class" ++ + " com.android.tools.r8.shaking.KeepClassMembersFieldTest$Foo {" ++ + " <fields>; " ++ + "}"; ++ private static final String EXPECTED_RESULT = StringUtils.lines("42"); + + private final TestParameters parameters; + +@@ -39,23 +41,32 @@ public class KeepClassMembersFieldTest extends TestBase { + @Test + public void testR8() throws Throwable { + testForR8(parameters.getBackend()) +- .addInnerClasses(getClass()) ++ .addProgramClasses(Foo.class, Bar.class) + .addKeepMainRule(Foo.class) + .addKeepRules(KEEP_RULE) + .setMinApi(parameters.getApiLevel()) + .compile() +- .inspect( +- inspector -> +- assertThat(inspector.clazz(Foo.class).uniqueFieldWithName("value"), isPresent())) + .run(parameters.getRuntime(), Foo.class) +- .assertSuccessWithEmptyOutput(); ++ .inspect( ++ inspector -> { ++ List<FoundFieldSubject> foundFieldSubjects = inspector.clazz(Foo.class).allFields(); ++ // TODO(b/231555675): This should present ++ assertFalse(inspector.clazz(Foo.class).uniqueFieldWithName("value").isPresent()); ++ }) ++ .assertSuccess(); + } + +- static class Bar {} ++ static class Bar { ++ @Override ++ public String toString() { ++ return "42"; ++ } ++ } + + static class Foo { ++ public Bar value = new Bar(); + +- Bar value = new Bar(); ++ Foo() {} + + public static void main(String[] args) { + new Foo(); +diff --git a/src/test/java/com/android/tools/r8/shaking/allowshrinking/KeepClassFieldsAllowShrinkingCompatibilityTest.java b/src/test/java/com/android/tools/r8/shaking/allowshrinking/KeepClassFieldsAllowShrinkingCompatibilityTest.java +index e0e151aa4..314ea33e9 100644 +--- a/src/test/java/com/android/tools/r8/shaking/allowshrinking/KeepClassFieldsAllowShrinkingCompatibilityTest.java ++++ b/src/test/java/com/android/tools/r8/shaking/allowshrinking/KeepClassFieldsAllowShrinkingCompatibilityTest.java +@@ -103,9 +103,11 @@ public class KeepClassFieldsAllowShrinkingCompatibilityTest extends TestBase { + assertThat(bBar, not(isPresent())); + } else { + assertThat(aFoo, isPresentAndRenamed(allowObfuscation)); +- assertThat( +- aBar, /*shrinker.isR8() ? isAbsent() : */ +- isPresentAndRenamed(allowObfuscation)); ++ // TODO(b/171459868) It is inconsistent that the unused field A.bar is retained. ++ // This does not match the R8 behavior for an unused method, so there may be an ++ // optimization opportunity here. ++ // (See KeepClassMethodsAllowShrinkingCompatibilityTest regarding methods). ++ assertThat(aBar, isPresentAndRenamed(allowObfuscation)); + assertThat(inspector.clazz(TestClass.class).mainMethod(), accessesField(aFoo)); + if (shrinker.isR8()) { + assertThat(bFoo, not(isPresent())); +diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedFieldTypeTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedFieldTypeTest.java +index 8e4f9f43c..12c064356 100644 +--- a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedFieldTypeTest.java ++++ b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/MergedFieldTypeTest.java +@@ -65,16 +65,12 @@ public class MergedFieldTypeTest extends MergedTypeBaseTest { + + public static void main(String[] args) { + TestClass obj = new TestClass(); +- if (alwaysFalse()) { ++ if (false) { + obj.field = new B(); + System.out.println(obj.field); + } + System.out.print(obj.get().getClass().getName()); + } +- +- static boolean alwaysFalse() { +- return false; +- } + } + + public MergedFieldTypeWithCollisionTest( +diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptSingletonIsNotCyclicTest.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptSingletonIsNotCyclicTest.java +index f6f59ddcc..e65f24001 100644 +--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptSingletonIsNotCyclicTest.java ++++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptSingletonIsNotCyclicTest.java +@@ -100,13 +100,13 @@ public class KeptSingletonIsNotCyclicTest extends TestBase { + // TestClass.foo is kept by TestClass.<init>. + QueryNode testFooFieldNode = + inspector.field(testFooFieldRef).assertPresent().assertKeptBy(testInit); +- // The type Foo is kept by TestClass.<init> and TestClass.foo. ++ // The type Foo is not kept by TestClass.<init>, but TestClass.foo. + QueryNode fooClassNode = + inspector + .clazz(fooClassRef) + .assertRenamed() + .assertKeptBy(testFooFieldNode) +- .assertKeptBy(testInit); ++ .assertNotKeptBy(testInit); + // Foo.<clinit> is kept by Foo + QueryNode fooClInit = inspector.method(fooClInitRef).assertPresent().assertKeptBy(fooClassNode); + // The type Foo is also kept by Foo.<clinit> +-- +2.36.1.255.ge46751e96f-goog +
diff --git a/third_party/r8/README.chromium b/third_party/r8/README.chromium index 98a74e3..934151a 100644 --- a/third_party/r8/README.chromium +++ b/third_party/r8/README.chromium
@@ -53,7 +53,9 @@ * Find the version tag at this url https://chrome-infra-packages.appspot.com/p/chromium/third_party/r8/+/<instance id> * Or, run `cipd describe chromium/third_party/r8 -version <instance id>` and look at the version tag. - * The commit hash that R8 was built at appears after the @ symbol in the version tag. + * The commit hash that R8 was built at appears after the "@" symbol in the version tag and + before the "-". Eg. version:2@33ae86d80351efc4d632452331d06cb97e42f2a7-72dd46fd5c gives the + commit hash of 33ae86d80351efc4d632452331d06cb97e42f2a7. * New instances are uploaded by the packager bot: https://ci.chromium.org/p/chromium/builders/ci/3pp-linux-amd64-packager * The bot autoruns every 6 hours. Ping a trooper or a clank build core dev to @@ -76,6 +78,7 @@ git am $CHROMIUM_SRC/third_party/r8/3pp/patches/*.patch * Fix patch conflicts. * Save new patches. Change number if expecting more or fewer patches: +rm $CHROMIUM_SRC/third_party/r8/3pp/patches/* git format-patch origin/main..HEAD -o $CHROMIUM_SRC/third_party/r8/3pp/patches * Submit these fixed patches and the bot will automatically retry.
diff --git a/tools/binary_size/libsupersize/viewer/caspian/model.h b/tools/binary_size/libsupersize/viewer/caspian/model.h index c81913b..e6d2d4d 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/model.h +++ b/tools/binary_size/libsupersize/viewer/caspian/model.h
@@ -27,7 +27,7 @@ enum class ArtifactType : char { kSymbol = '\0', kDirectory = 'D', - kComponent = 'C', + kGroup = 'G', kFile = 'F', kJavaClass = 'J', };
diff --git a/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc b/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc index 35ae4d8..2d7b09e8 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc
@@ -72,8 +72,7 @@ // Sort nodes with same size in alphabetically ascending order. float l_size = abs(l->size); float r_size = abs(r->size); - return (l_size != r_size) ? abs(l->size) > abs(r->size) - : l->id_path < r->id_path; + return (l_size != r_size) ? l_size > r_size : l->id_path < r->id_path; } bool CompareCount(const TreeNode* const& l, const TreeNode* const& r) { @@ -238,7 +237,7 @@ // '/' separators for the file tree - e.g. Blink>third_party/blink/common... // We know that Blink is a component because its children have the form // Blink>third_party rather than Blink/third_party. - return child_path.IsTopLevelPath() ? ArtifactType::kComponent + return child_path.IsTopLevelPath() ? ArtifactType::kGroup : ArtifactType::kDirectory; }
diff --git a/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch b/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch index 036e5a3e..42993fc6 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch +++ b/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch
@@ -1,5 +1,5 @@ diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn -index d960648941d8b..fc8e041d2bc66 100644 +index c737e53c2ce72..963a095d14a19 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -301,10 +301,11 @@ is_ios = current_os == "ios" @@ -16,7 +16,7 @@ # ============================================================================= # TARGET DEFAULTS diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn -index 719de1f28fb64..da8adfa8e52c7 100644 +index c3ae8f2250358..9a756be9b3c51 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn @@ -635,6 +635,20 @@ config("compiler") { @@ -40,7 +40,7 @@ # Add flags for link-time optimization. These flags enable # optimizations/transformations that require whole-program visibility at link # time, so they need to be applied to all translation units, and we may end up -@@ -749,9 +763,7 @@ config("compiler") { +@@ -751,9 +765,7 @@ config("compiler") { if (use_lld && !enable_call_graph_profile_sort) { if (is_win) { ldflags += [ "/call-graph-profile-sort:no" ] @@ -51,16 +51,16 @@ ldflags += [ "-Wl,--no-call-graph-profile-sort" ] } } -@@ -1537,7 +1549,7 @@ config("default_warnings") { - cflags += [ "-Wno-deprecated-non-prototype" ] +@@ -1536,7 +1548,7 @@ config("default_warnings") { + cflags += [ "-Wno-unqualified-std-cast-call" ] } - if (!is_nacl && !(is_chromeos || + if (!is_wasm && !is_nacl && !(is_chromeos || default_toolchain == "//build/toolchain/cros:target")) { - # TODO(https://crbug.com/1316298): Re-enable once test failure is figured out + # TODO(https://crbug.com/1322823): Remove flags once potential miscompile is investigated. cflags += [ -@@ -2307,6 +2319,9 @@ config("symbols") { +@@ -2305,6 +2317,9 @@ config("symbols") { # All configs using /DEBUG should include this: configs = [ ":win_pdbaltpath" ]
diff --git a/tools/binary_size/libsupersize/viewer/static/infocard-ui.js b/tools/binary_size/libsupersize/viewer/static/infocard-ui.js index 6502d718..205eb94 100644 --- a/tools/binary_size/libsupersize/viewer/static/infocard-ui.js +++ b/tools/binary_size/libsupersize/viewer/static/infocard-ui.js
@@ -143,17 +143,25 @@ } /** - * Updates the icon and type text. The type label is pulled from the - * title of the icon supplied. - * @param {SVGSVGElement} icon Icon to display + * Returns the type label of a node. By default this is pulled from the + * title of the associated icon. + * @param {TreeNode} node + * @param {!SVGSVGElement} icon */ - _setTypeContent(icon) { - const typeDescription = icon.querySelector('title').textContent; - icon.setAttribute('fill', '#fff'); + _getTypeDescription(node, icon) { + return icon.querySelector('title').textContent; + } - this._typeInfo.textContent = typeDescription; - this._iconInfo.removeChild(this._iconInfo.lastElementChild); - this._iconInfo.appendChild(icon); + /** + * @param {TreeNode} node + * @return {!SVGSVGElement} The created icon. + */ + _setTypeContent(node) { + const icon = getIconTemplate(node.type[0]); + icon.setAttribute('fill', '#fff'); + this._typeInfo.textContent = this._getTypeDescription(node, icon); + this._iconInfo.replaceChild(icon, this._iconInfo.lastElementChild); + return icon; } /** @@ -194,10 +202,9 @@ // Update DOM this._updateSize(node); this._updateDetails(node); - if (type !== this._lastType) { - // No need to create a new icon if it is identical. - const icon = getIconTemplate(type); - this._setTypeContent(icon); + // If possible, skip making new type content. + if (type !== this._lastType || type === _ARTIFACT_TYPES.GROUP) { + this._setTypeContent(node); this._lastType = type; } this._flagsInfo.textContent = this._flagsString(node); @@ -219,12 +226,13 @@ class SymbolInfocard extends Infocard { /** - * @param {SVGSVGElement} icon Icon to display + * @param {TreeNode} node + * @return {!SVGSVGElement} The created icon. */ - _setTypeContent(icon) { - const color = icon.getAttribute('fill'); - super._setTypeContent(icon); - this._iconInfo.style.backgroundColor = color; + _setTypeContent(node) { + const icon = super._setTypeContent(node); + this._iconInfo.style.backgroundColor = getIconStyle(node.type[0]).color; + return icon; } } @@ -266,11 +274,29 @@ } /** - * @param {SVGSVGElement} icon Icon to display + * @param {TreeNode} node + * @param {!SVGSVGElement} icon */ - _setTypeContent(icon) { - super._setTypeContent(icon); + _getTypeDescription(node, icon) { + const depth = node.idPath.replace(/[^/]/g, '').length; + if (depth === 0) { + const t = state.get('group_by'); + if (t) { + // Format, e.g., "generated_type" to "Generated type". + return (t[0].toUpperCase() + t.slice(1)).replace(/_/g, ' '); + } + } + return super._getTypeDescription(node, icon); + } + + /** + * @param {TreeNode} node + * @return {!SVGSVGElement} The created icon. + */ + _setTypeContent(node) { + const icon = super._setTypeContent(node); icon.classList.add('canvas-overlay'); + return icon; } _flagsString(artifactNode) {
diff --git a/tools/binary_size/libsupersize/viewer/static/shared.js b/tools/binary_size/libsupersize/viewer/static/shared.js index 40a01b76..c5277923 100644 --- a/tools/binary_size/libsupersize/viewer/static/shared.js +++ b/tools/binary_size/libsupersize/viewer/static/shared.js
@@ -136,7 +136,7 @@ */ const _ARTIFACT_TYPES = { DIRECTORY: 'D', - COMPONENT: 'C', + GROUP: 'G', FILE: 'F', JAVA_CLASS: 'J', };
diff --git a/tools/binary_size/libsupersize/viewer/static/state.js b/tools/binary_size/libsupersize/viewer/static/state.js index 62b7100..8ae4bef1 100644 --- a/tools/binary_size/libsupersize/viewer/static/state.js +++ b/tools/binary_size/libsupersize/viewer/static/state.js
@@ -278,7 +278,7 @@ */ const symbolIcons = { D: _icons.querySelector('.foldericon'), - C: _icons.querySelector('.componenticon'), + G: _icons.querySelector('.groupicon'), J: _icons.querySelector('.javaclassicon'), F: _icons.querySelector('.fileicon'), b: _icons.querySelector('.bssicon'), @@ -291,7 +291,7 @@ m: _icons.querySelector('.dexmethodicon'), p: _icons.querySelector('.localpakicon'), P: _icons.querySelector('.nonlocalpakicon'), - o: _icons.querySelector('.othericon'), // used as default icon + o: _icons.querySelector('.othericon'), // used as default icon }; const _statuses = document.getElementById('symbol-diff-status-icons');
diff --git a/tools/binary_size/libsupersize/viewer/static/tree-ui.js b/tools/binary_size/libsupersize/viewer/static/tree-ui.js index d38766e..20107c6 100644 --- a/tools/binary_size/libsupersize/viewer/static/tree-ui.js +++ b/tools/binary_size/libsupersize/viewer/static/tree-ui.js
@@ -314,29 +314,29 @@ * The element will represent a tree or a leaf, depending on if the tree node * object has any children. Trees use a slightly different template and have * click event listeners attached. - * @param {TreeNode} data Data to use for the UI. + * @param {TreeNode} node Data to use for the UI. * @returns {DocumentFragment} */ - function makeTreeElement(data) { - const isLeaf = data.children && data.children.length === 0; + function makeTreeElement(node) { + const isLeaf = node.children && node.children.length === 0; const template = isLeaf ? _leafTemplate : _treeTemplate; const element = document.importNode(template.content, true); const listItemEl = element.firstElementChild; const link = /** @type {HTMLElement} */ (listItemEl.firstElementChild); // Associate clickable node & tree data. - _uiNodeData.set(link, Object.freeze(data)); + _uiNodeData.set(link, Object.freeze(node)); // Icons are predefined in the HTML through hidden SVG elements. - const type = data.type[0]; + const type = node.type[0]; const icon = getIconTemplate(type); if (!isLeaf) { - const symbolStyle = getIconStyle(data.type[1]); + const symbolStyle = getIconStyle(node.type[1]); icon.setAttribute('fill', symbolStyle.color); } // Insert an SVG icon at the start of the link to represent adds/removals. - const diffStatusIcon = getDiffStatusTemplate(data); + const diffStatusIcon = getDiffStatusTemplate(node); if (diffStatusIcon) { listItemEl.insertBefore(diffStatusIcon, listItemEl.firstElementChild); } @@ -347,14 +347,12 @@ // Set the symbol name and hover text. /** @type {HTMLSpanElement} */ const symbolName = element.querySelector('.symbol-name'); - symbolName.textContent = shortName(data).replace( - _SPECIAL_CHAR_REGEX, - _ZERO_WIDTH_SPACE - ); - symbolName.title = data.idPath; + symbolName.textContent = + shortName(node).replace(_SPECIAL_CHAR_REGEX, _ZERO_WIDTH_SPACE); + symbolName.title = node.idPath; // Set the byte size and hover text. - _setSize(element.querySelector('.size'), data); + _setSize(element.querySelector('.size'), node); link.addEventListener('mouseover', _handleMouseOver); if (!isLeaf) {
diff --git a/tools/binary_size/libsupersize/viewer/static/viewer.html b/tools/binary_size/libsupersize/viewer/static/viewer.html index 616194d..ce47821 100644 --- a/tools/binary_size/libsupersize/viewer/static/viewer.html +++ b/tools/binary_size/libsupersize/viewer/static/viewer.html
@@ -295,8 +295,8 @@ <path d="M9.17,6l2,2H20v10L4,18V6H9.17 M10,4H4C2.9,4,2.01,4.9,2.01,6L2,18c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8c0-1.1-0.9-2-2-2 h-8L10,4L10,4z" /> </svg> - <svg class="icon componenticon" height="24" width="24" fill="#5f6368"> - <title>Component</title> + <svg class="icon groupicon" height="24" width="24" fill="#5f6368"> + <title>(Group)</title> <path d="M9,13.75c-2.34,0-7,1.17-7,3.5V19h14v-1.75C16,14.92,11.34,13.75,9,13.75z M4.34,17c0.84-0.58,2.87-1.25,4.66-1.25 s3.82,0.67,4.66,1.25H4.34z" /> <path d="M9,12c1.93,0,3.5-1.57,3.5-3.5C12.5,6.57,10.93,5,9,5S5.5,6.57,5.5,8.5C5.5,10.43,7.07,12,9,12z M9,7
diff --git a/tools/mac/power/driver.py b/tools/mac/power/driver.py index d4c91e8..2d13e3b 100644 --- a/tools/mac/power/driver.py +++ b/tools/mac/power/driver.py
@@ -249,7 +249,7 @@ self.WriteScenarioSummary(scenario_driver) dtraces_output_dir = os.path.join(self._output_dir, scenario_driver.name, - f"dtraces_{profile_mode}") + "dtraces_stacks") os.makedirs(dtraces_output_dir, exist_ok=True) scenario_driver.Launch() browser_process = scenario_driver.browser.browser_process @@ -263,24 +263,18 @@ os.path.join(self._output_dir, scenario_driver.name, f'dtrace_{profile_mode}_log.txt'), "w") as dtrace_log: - # Comments regarding the DTrace probes below. - # pid == {pid} to capture the browser process. - # ppid == {pid} to capture all child processes. - # ustack(64) to capture stacks user space. - + scripts_dir = os.path.join(os.path.dirname(__file__), "dtrace_scripts") if profile_mode == "wakeups": - probe = "mach_kernel::wakeup" + script = os.path.join(scripts_dir, "iwakeups.d") else: - probe = "profile-1001" + script = os.path.join(scripts_dir, "profile.d") pid = browser_process.pid - probe_def = \ - f"{probe}/pid=={pid} || ppid=={pid}/ {{@[ustack(128)] = count();}}" - output_filename = os.path.join(dtraces_output_dir, f"{pid}.txt") + dtrace_args = [ - 'sudo', 'dtrace', '-p', f"{pid}", "-o", output_filename, '-n', - probe_def + 'sudo', 'dtrace', '-p', f"{pid}", "-o", output_filename, '-s', + script, f"{pid}" ] # No need to add |dtrace_process| to |self._started_processeds| as it's
diff --git a/tools/memory/mac/parse_vmmap.py b/tools/memory/mac/parse_vmmap.py index 43ef7e2..4357ec9 100755 --- a/tools/memory/mac/parse_vmmap.py +++ b/tools/memory/mac/parse_vmmap.py
@@ -19,7 +19,7 @@ ]) -def _ExecuteVmmap(pid: int) -> str: +def ExecuteVmmap(pid: int) -> str: """Runs vmmap PID and returns its output.""" ret = subprocess.run(['vmmap', str(pid)], capture_output=True) ret.check_returncode() @@ -51,7 +51,7 @@ return str(size) -def _ParseIOSurface(contents: str) -> list: +def ParseIOSurface(contents: str, quiet=False) -> list: """From the content of a vmmap file, returns a list of IOSurfaces.""" io_surfaces = [] for line in contents.split('\n'): @@ -83,7 +83,8 @@ matches = regexp.match(line) if matches: - print(line) + if not quiet: + print(line) start = int(matches.group('start'), 16) end = int(matches.group('end'), 16) virtual = _ParseSize(matches.group('virtual')) @@ -92,7 +93,6 @@ swapped = _ParseSize(matches.group('swapped')) width = int(matches.group('width')) height = int(matches.group('height')) - print(matches.group('size')) size = _ParseSize(matches.group('size')) io_surface = IOSurface(start, end, virtual, resident, dirty, swapped, @@ -113,13 +113,13 @@ contents = None if args.pid: - contents = _ExecuteVmmap(args.pid) + contents = ExecuteVmmap(args.pid) else: assert args.filename with open(args.filename, 'r') as f: contents = f.read() - io_surfaces = _ParseIOSurface(contents) + io_surfaces = ParseIOSurface(contents) io_surfaces.sort(key=operator.attrgetter('virtual')) print('\nIOSurfaces sorted by virtual size:') for io_surface in io_surfaces:
diff --git a/tools/memory/mac/plot_iosurface.py b/tools/memory/mac/plot_iosurface.py new file mode 100755 index 0000000..7b9eaa6 --- /dev/null +++ b/tools/memory/mac/plot_iosurface.py
@@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# Copyright 2022 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. +"""Visualizes the amount of IOSurface memory used over time. +""" + +import argparse +import time + +import matplotlib +from matplotlib import pylab as plt +import matplotlib.animation as animation +import numpy as np + +import parse_vmmap + + +def _PlotData(pid: int): + times = [] + virtual = [] + dirty = [] + swapped = [] + + fig = plt.figure(figsize=(16, 8)) + ax = fig.add_subplot(1, 1, 1) + first_time = time.time() + + def _Animate(i): + contents = parse_vmmap.ExecuteVmmap(pid) + io_surfaces = parse_vmmap.ParseIOSurface(contents, quiet=True) + total_virtual_size = sum(io_surface.size for io_surface in io_surfaces) + total_dirty_size = sum(io_surface.dirty for io_surface in io_surfaces) + total_swapped_size = sum(io_surface.swapped for io_surface in io_surfaces) + + print('SIZE = %d\tDIRTY = %d\tSWAPPED = %d' % + (total_virtual_size, total_dirty_size, total_swapped_size)) + now = time.time() + + times.append(now - first_time) + _MIB = 1 << 20 + virtual.append(total_virtual_size / _MIB) + dirty.append(total_dirty_size / _MIB) + swapped.append(total_swapped_size / _MIB) + bucket_sizes = [] + + ax.clear() + bottom = np.zeros(len(times)) + + top = np.array(swapped) + ax.plot(times, top, label='Swapped') + plt.fill_between(times, top, bottom) + bottom += swapped + + top += dirty + ax.plot(times, top, label='Dirty') + plt.fill_between(times, top, bottom) + bottom += dirty + + top = virtual + ax.plot(times, top, label='Virtual') + plt.fill_between(times, top, bottom) + + plt.ylim(bottom=0) + plt.xlim(left=times[0], right=times[-1]) + + plt.xlabel('Time (s)') + plt.ylabel('Memory (MiB)') + plt.title('IOSurface memory usage vs time - PID = %d' % pid) + + plt.legend() + + ani = animation.FuncAnimation(fig, _Animate, interval=1000) + plt.show() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--pid', + help='PID of the GPU process', + type=int, + required=True) + args = parser.parse_args() + + _PlotData(args.pid) + + +if __name__ == '__main__': + main()
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 696805f..11279e1 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -18819,6 +18819,14 @@ <int value="4" label="Flushed"/> </enum> +<enum name="CookieCacheLookupResult"> + <int value="0" label="kCacheMissFirstAccess"/> + <int value="1" label="kCacheHitAfterGet"/> + <int value="2" label="kCacheHitAfterSet"/> + <int value="3" label="kCacheMissAfterGet"/> + <int value="4" label="kCacheMissAfterSet"/> +</enum> + <enum name="CookieCommitProblem"> <int value="0" label="Entry encryption failed"/> <int value="1" label="Adding cookie to DB failed."/> @@ -40217,6 +40225,10 @@ <int value="4247" label="V8MathMLElement_Focusgroup_AttributeSetter"/> <int value="4248" label="V8SVGElement_Focusgroup_AttributeGetter"/> <int value="4249" label="V8SVGElement_Focusgroup_AttributeSetter"/> + <int value="4250" label="CSSLegacyPerspectiveOrigin"/> + <int value="4251" label="CSSLegacyTransformOrigin"/> + <int value="4252" label="CSSLegacyBorderImage"/> + <int value="4253" label="CSSLegacyBorderImageWidth"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -57118,6 +57130,8 @@ <int value="-503601144" label="UserDataSnapshot:disabled"/> <int value="-503430431" label="XRSandbox:enabled"/> <int value="-502004335" label="OobeHidDetectionRevamp:enabled"/> + <int value="-501821181" + label="ContextualPageActionsWithPriceTracking:disabled"/> <int value="-499723386" label="EnableFilesAppCopyImage:disabled"/> <int value="-499186481" label="OmniboxGroupSuggestionsBySearchVsUrl:disabled"/> @@ -57922,6 +57936,7 @@ <int value="46334141" label="FeatureNotificationGuideSkipCheckForLowEngagedUsers:enabled"/> <int value="48159177" label="reduced-referrer-granularity"/> + <int value="48334820" label="ContextualPageActionsWithPriceTracking:enabled"/> <int value="50643563" label="MBIMode:enabled"/> <int value="51793504" label="protect-sync-credential-on-reauth:disabled"/> <int value="52150780" label="OsSettingsPolymer3:disabled"/> @@ -89950,7 +89965,10 @@ <int value="0" label="Main frame"/> <int value="1" label="Iframe with the same url as main frame"/> <int value="2" label="Iframe with different url and the same signon realm"/> - <int value="3" label="Iframe with different signon realm"/> + <int value="3" label="(obsolete) Iframe with different signon realm"/> + <int value="4" label="Iframe with PSL matched signon realm"/> + <int value="5" + label="Iframe with different and not PSL matched signon realm"/> </enum> <enum name="SubprocessType">
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index 97dd6596..f689025 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -791,6 +791,20 @@ </summary> </histogram> +<histogram name="Blink.Experimental.Cookies.CacheLookupResult" + enum="CookieCacheLookupResult" expires_after="2023-01-01"> + <owner>carlscab@google.com</owner> + <owner>woa-performance@google</owner> + <summary> + Whether a GetCookiesString request for a document returned the same result + as the previous one. This is an experiment to determine the usefulness of a + cookie cache in the Renderer. + + A sample is recorded for every GetCookiesString request sent from the + Document owned CookieJar. + </summary> +</histogram> + <histogram name="Blink.FedCm.ApprovedClientsExistence" enum="Boolean" expires_after="M110"> <owner>yigu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml index 93fac495..7c27725 100644 --- a/tools/metrics/histograms/metadata/enterprise/histograms.xml +++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -1680,9 +1680,9 @@ <histogram name="Enterprise.MachineLevelUserCloudPolicyEnrollment.RequestSuccessTime" - units="ms" expires_after="2022-06-01"> - <owner>rogerta@chromium.org</owner> + units="ms" expires_after="2023-06-01"> <owner>zmin@chromium.org</owner> + <owner>rogerta@chromium.org</owner> <summary> Time since the enrollment request was made until a successful enrollment response is returned from the server. @@ -1691,18 +1691,18 @@ <histogram name="Enterprise.MachineLevelUserCloudPolicyEnrollment.Result" enum="MachineLevelUserCloudPolicyEnrollmentResult" - expires_after="2022-07-31"> - <owner>rogerta@chromium.org</owner> + expires_after="2023-07-31"> <owner>zmin@chromium.org</owner> + <owner>rogerta@chromium.org</owner> <summary>The result of machine level user cloud policy enrollment.</summary> </histogram> <histogram name="Enterprise.MachineLevelUserCloudPolicyEnrollment.StartupDialog" enum="MachineLevelUserCloudPolicyEnrollmentStartupDialog" - expires_after="2022-06-01"> - <owner>rogerta@chromium.org</owner> + expires_after="2023-06-01"> <owner>zmin@chromium.org</owner> + <owner>rogerta@chromium.org</owner> <summary> Records whether the machine level user cloud policy enrollment dialog is shown to the user and the action they took. @@ -1711,9 +1711,9 @@ <histogram name="Enterprise.MachineLevelUserCloudPolicyEnrollment.StartupDialogTime" - units="ms" expires_after="2022-06-01"> - <owner>rogerta@chromium.org</owner> + units="ms" expires_after="2023-06-01"> <owner>zmin@chromium.org</owner> + <owner>rogerta@chromium.org</owner> <summary> The length of time the machine level user cloud policy enrollment dialog was visible to the user. @@ -1722,9 +1722,9 @@ <histogram name="Enterprise.MachineLevelUserCloudPolicyEnrollment.UnenrollSuccess" - enum="BooleanSuccess" expires_after="2022-06-01"> - <owner>domfc@chromium.org</owner> + enum="BooleanSuccess" expires_after="2023-06-01"> <owner>zmin@chromium.org</owner> + <owner>domfc@chromium.org</owner> <summary> Records whether a browser unenrollment was completed succcessfully by writing an invalid DM token to storage or not.
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index b6dfc2528..aed9775 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -2751,11 +2751,26 @@ <histogram name="PasswordManager.SubmittedFormFrame" enum="SubmittedPasswordFormFrame" expires_after="2022-10-30"> + <obsolete> + Removed in M104. Replaced with PasswordManager.SubmittedFormFrame2. + </obsolete> <owner>kazinova@google.com</owner> <owner>vasilii@chromium.org</owner> <summary> Records a frame type (eg. main frame, iframe with the same url as the main - frame) of a submitted password form. + frame) of a submitted password form. Logged at every provisional save (i.e. + on every user keystroke). + </summary> +</histogram> + +<histogram name="PasswordManager.SubmittedFormFrame2" + enum="SubmittedPasswordFormFrame" expires_after="2022-10-30"> + <owner>kazinova@google.com</owner> + <owner>vasilii@chromium.org</owner> + <summary> + Records a frame type (eg. main frame, iframe with the same url as the main + frame, etc) of a submitted password form. Logged only once per submitted + form. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml index f5f54fe..330e9e0 100644 --- a/tools/metrics/histograms/metadata/stability/histograms.xml +++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -75,10 +75,9 @@ </histogram> <histogram name="Stability.Android.ProcessedRealMinidumps" - enum="AndroidProcessedMinidumps" expires_after="2022-10-16"> - <owner>mheikal@chromium.org</owner> - <owner>smaier@chromium.org</owner> + enum="AndroidProcessedMinidumps" expires_after="2023-05-24"> <owner>wnwen@chromium.org</owner> + <owner>src/components/minidump_uploader/OWNERS</owner> <summary> Records the number of non-simulated minidumps processed by Crashpad, split by process type. This metric is similar to one that could be computed @@ -87,19 +86,6 @@ </summary> </histogram> -<histogram name="Stability.Android.ProcessedSimulatedMinidumps" - enum="AndroidProcessedMinidumps" expires_after="2022-07-03"> - <owner>mheikal@chromium.org</owner> - <owner>smaier@chromium.org</owner> - <owner>wnwen@chromium.org</owner> - <summary> - Records the number of simulated minidumps processed by Crashpad, split by - process type. This metric is similar to one that could be computed - server-side based on received crash uploads; but the client-side metric also - includes any minidumps that were not successfully uploaded. - </summary> -</histogram> - <histogram name="Stability.Android.RendererCrash" enum="Boolean" expires_after="2022-10-30"> <owner>wnwen@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index c34933a..dc84c80 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "b63f94357b0f34298abd3a9b83112bde117301d9", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/23339a6fac0aeb6c2289af885ee4d1df0a9aaf90/trace_processor_shell.exe" + "hash": "362305e5177cc8f1a2938840b6ddcc86544ff0fb", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/feeb5c1043fc9fe022b6c720aae568fbac7b0f1a/trace_processor_shell.exe" }, "linux_arm": { "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893", "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "mac": { - "hash": "264c11ffef682d8a1f737bec52098694092919a4", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/23339a6fac0aeb6c2289af885ee4d1df0a9aaf90/trace_processor_shell" + "hash": "c596583f38124f15f97db8fef7b9a71dded377b5", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/992efc532f462258cc68585423ee612621f96754/trace_processor_shell" }, "mac_arm64": { "hash": "e1ad4861384b06d911a65f035317914b8cc975c6", "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "2706843ca63f4105b3660df895afbafde6ca4ec7", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/6214d0c954d720a3c87cf7673903d679d2ae7413/trace_processor_shell" + "hash": "ec0b651002a120069aead56ce8729e63ed0a0b27", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/feeb5c1043fc9fe022b6c720aae568fbac7b0f1a/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn index 1de6f384..da5d0c7b 100644 --- a/ui/display/manager/BUILD.gn +++ b/ui/display/manager/BUILD.gn
@@ -41,6 +41,8 @@ "apply_content_protection_task.h", "configure_displays_task.cc", "configure_displays_task.h", + "content_protection_key_manager.cc", + "content_protection_key_manager.h", "content_protection_manager.cc", "content_protection_manager.h", "default_touch_transform_setter.cc",
diff --git a/ui/display/manager/content_protection_key_manager.cc b/ui/display/manager/content_protection_key_manager.cc new file mode 100644 index 0000000..e13f88a --- /dev/null +++ b/ui/display/manager/content_protection_key_manager.cc
@@ -0,0 +1,70 @@ +// Copyright (c) 2022 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 "ui/display/manager/content_protection_key_manager.h" + +#include "ui/display/display_features.h" +#include "ui/display/manager/display_manager_util.h" + +namespace { +std::vector<display::DisplaySnapshot*> GetHdcpCapableDisplays( + const std::vector<display::DisplaySnapshot*>& displays_states) { + std::vector<display::DisplaySnapshot*> hdcp_capable_displays; + for (display::DisplaySnapshot* display : displays_states) { + uint32_t protection_mask; + if (GetContentProtectionMethods(display->type(), &protection_mask) && + protection_mask & display::kContentProtectionMethodHdcpAll) { + hdcp_capable_displays.push_back(display); + } + } + return hdcp_capable_displays; +} +} // namespace + +namespace display { + +ContentProtectionKeyManager::ContentProtectionKeyManager() = default; +ContentProtectionKeyManager::~ContentProtectionKeyManager() = default; + +void ContentProtectionKeyManager::SetKeyIfRequired( + const std::vector<DisplaySnapshot*>& displays_states, + NativeDisplayDelegate* native_display_delegate, + KeySetCallback on_key_set) { + // TODO(markyacoub): Query the hdcp key and inject it if needed to + // replace the feature flag. + if (!features::IsHdcpKeyProvisioningRequired()) { + std::move(on_key_set).Run(); + return; + } + + if (key_fetching_status_ == KeyFetchingStatus::kFetchingNotRequired || + provisioned_key_request_.is_null()) { + std::move(on_key_set).Run(); + return; + } + + // Check if any of the displays support HDCP. + std::vector<DisplaySnapshot*> hdcp_capable_displays = + GetHdcpCapableDisplays(displays_states); + pending_displays_to_configure_ = hdcp_capable_displays.size(); + if (hdcp_capable_displays.empty()) { + std::move(on_key_set).Run(); + return; + } + + // If we already learnt that we need a key and already fetched the key, go + // ahead and inject it into the kernel. + if (!cached_provisioned_key_.empty()) { + for (DisplaySnapshot* display : hdcp_capable_displays) { + // TODO(markyacoub): inject key to kernel. + (void)display; + } + return; + } + + // TODO(markyacoub): Implement querying and injecting. + std::move(on_key_set).Run(); +} + +}; // namespace display
diff --git a/ui/display/manager/content_protection_key_manager.h b/ui/display/manager/content_protection_key_manager.h new file mode 100644 index 0000000..e30e7c7 --- /dev/null +++ b/ui/display/manager/content_protection_key_manager.h
@@ -0,0 +1,77 @@ +// Copyright (c) 2022 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 UI_DISPLAY_MANAGER_CONTENT_PROTECTION_KEY_MANAGER_H_ +#define UI_DISPLAY_MANAGER_CONTENT_PROTECTION_KEY_MANAGER_H_ + +#include "ui/display/manager/display_manager_export.h" +#include "ui/display/types/display_snapshot.h" +#include "ui/display/types/native_display_delegate.h" + +namespace display { + +// ContentProtectionKeyManager is responsible for managing the provisioned HDCP +// key for the displays. +// Some drivers such as msm expose "Content Protection Key" connector prop that +// needs a key to enable HDCP. The key is typically provisioned from a server. + +// The Workflow when a key is required: +// 1. Check for a valid key request function. +// 2. Query the "Content Protection Key" connector property to verify if the +// key is required. +// 3. Check for keys that are cached for the HDCP capable displays, if they +// don't exist get the provisioned key from the server. +// 4. Inject the key into the kernel by writing the key into the +// "Content Protection Key" connector property of each HDCP capable display. +class DISPLAY_MANAGER_EXPORT ContentProtectionKeyManager { + public: + using ProvisionedKeyRequest = base::RepeatingCallback<void( + base::OnceCallback<void(const std::string&)>)>; + using KeySetCallback = base::OnceCallback<void()>; + + ContentProtectionKeyManager(); + + ContentProtectionKeyManager(const ContentProtectionKeyManager&) = delete; + ContentProtectionKeyManager& operator=(const ContentProtectionKeyManager&) = + delete; + + ~ContentProtectionKeyManager(); + + void set_provisioned_key_request( + ContentProtectionKeyManager::ProvisionedKeyRequest request) { + provisioned_key_request_ = std::move(request); + } + + // Querying the key prop through |native_display_delegate|, requests the key + // by calling |request| and injects the key into the kernel if required by + // the |displays_states|. + // When the displays config is done, whether it was needed or not, on both + // success and failure, |on_key_set| is called. + void SetKeyIfRequired(const std::vector<DisplaySnapshot*>& displays_states, + NativeDisplayDelegate* native_display_delegate, + KeySetCallback on_key_set); + + private: + enum class KeyFetchingStatus { + kFetchingNotStarted, + kFetchingInProgress, + kFetchingSucceeded, + kFetchingFailed, + kFetchingNotRequired + }; + + KeyFetchingStatus key_fetching_status_ = + KeyFetchingStatus::kFetchingNotStarted; + + // Function to request the provisioned key from the server. + ProvisionedKeyRequest provisioned_key_request_; + // It is assumed that the key is the same for all the displays and doesn't + // change throughout the life of the process. + std::string cached_provisioned_key_; + + int pending_displays_to_configure_ = 0; +}; +} // namespace display + +#endif // UI_DISPLAY_MANAGER_CONTENT_PROTECTION_KEY_MANAGER_H_
diff --git a/ui/display/manager/content_protection_manager.cc b/ui/display/manager/content_protection_manager.cc index d6b5098..d1dc255 100644 --- a/ui/display/manager/content_protection_manager.cc +++ b/ui/display/manager/content_protection_manager.cc
@@ -10,7 +10,6 @@ #include "base/check.h" #include "base/containers/cxx20_erase.h" #include "base/observer_list.h" -#include "ui/display/display_features.h" #include "ui/display/manager/apply_content_protection_task.h" #include "ui/display/manager/display_layout_manager.h" #include "ui/display/manager/query_content_protection_task.h" @@ -107,18 +106,12 @@ protections->insert_or_assign(display_id, protection_mask); - // If the device requires a provisioned HDCP key, we need to get the key and - // inject it into the kernel, then apply content protection when all is ready. - bool should_get_provisioned_key = features::IsHdcpKeyProvisioningRequired() && - cached_hdcp_provisioned_key_.empty() && - ShouldPollDisplaySecurity() && - !hdcp_key_request_.is_null(); - - if (should_get_provisioned_key) { - DVLOG(1) << "Device requires provisioned HDCP key"; - hdcp_key_request_.Run(base::BindOnce( - &ContentProtectionManager::OnGetHdcpKey, weak_ptr_factory_.GetWeakPtr(), - std::move(callback), client_id)); + if (ShouldPollDisplaySecurity()) { + hdcp_key_manager_.SetKeyIfRequired( + layout_manager_->GetDisplayStates(), native_display_delegate_, + base::BindOnce(&ContentProtectionManager::QueueContentProtectionTask, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + client_id)); } else { QueueContentProtectionTask(std::move(callback), client_id); } @@ -136,20 +129,6 @@ ToggleDisplaySecurityPolling(); } -void ContentProtectionManager::OnGetHdcpKey( - ApplyContentProtectionCallback callback, - ClientId client_id, - const std::string& key) { - // Cache the key to avoid making calls every time the HDCP state changes. - cached_hdcp_provisioned_key_ = key; - if (key.empty()) { - LOG(ERROR) << "OnGetHdcpKey: Failed to get HDCP key - Empty String"; - } - - // TODO(b/112172923): Pass the key to the kernel to enable HDCP. - QueueContentProtectionTask(std::move(callback), client_id); -} - const DisplaySnapshot* ContentProtectionManager::GetDisplay( int64_t display_id) const { for (const DisplaySnapshot* display : layout_manager_->GetDisplayStates())
diff --git a/ui/display/manager/content_protection_manager.h b/ui/display/manager/content_protection_manager.h index 7cefdd2..9eb8332 100644 --- a/ui/display/manager/content_protection_manager.h +++ b/ui/display/manager/content_protection_manager.h
@@ -15,6 +15,7 @@ #include "base/observer_list.h" #include "base/timer/timer.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/display/manager/content_protection_key_manager.h" #include "ui/display/manager/display_configurator.h" #include "ui/display/manager/display_manager_export.h" @@ -46,9 +47,6 @@ using ContentProtections = base::flat_map<int64_t /* display_id */, uint32_t /* protection_mask */>; - using GetHdcpKeyRequest = base::RepeatingCallback<void( - base::OnceCallback<void(const std::string&)>)>; - // Though only run once, a task must outlive its asynchronous operations, so // cannot be a OnceCallback. struct Task { @@ -82,10 +80,6 @@ native_display_delegate_ = delegate; } - void set_hdcp_key_request(GetHdcpKeyRequest callback) { - hdcp_key_request_ = std::move(callback); - } - using ClientId = absl::optional<uint64_t>; // On display reconfiguration, pending requests are cancelled, i.e. clients @@ -117,6 +111,11 @@ uint32_t protection_mask, ApplyContentProtectionCallback callback); + void SetProvisionedKeyRequest( + ContentProtectionKeyManager::ProvisionedKeyRequest request) { + hdcp_key_manager_.set_provisioned_key_request(request); + } + private: friend class test::ContentProtectionManagerTest; @@ -172,9 +171,6 @@ void QueueContentProtectionTask(ApplyContentProtectionCallback callback, ClientId client_id); - void OnGetHdcpKey(ApplyContentProtectionCallback callback, - ClientId client_id, - const std::string& key); DisplayLayoutManager* const layout_manager_; // Not owned. NativeDisplayDelegate* native_display_delegate_ = nullptr; // Not owned. @@ -194,8 +190,7 @@ // Used for periodic queries to notify observers of display security changes. base::RepeatingTimer security_timer_; - GetHdcpKeyRequest hdcp_key_request_; - std::string cached_hdcp_provisioned_key_; + ContentProtectionKeyManager hdcp_key_manager_; base::WeakPtrFactory<ContentProtectionManager> weak_ptr_factory_{this}; };