diff --git a/AUTHORS b/AUTHORS index 0ba5dd0..9e15934a 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -392,6 +392,7 @@ Hyungwook Lee <withlhw@gmail.com> HyunJi Kim <hjkim3323@gmail.com> Hyunjun Shin <hyunjun.shin2@navercorp.com> +Hyunjun Shin <shjj1504@gmail.com> Hyunjune Kim <hyunjune.kim@samsung.com> Hyunki Baik <hyunki.baik@samsung.com> Ian Cullinan <cullinan@amazon.com> @@ -897,6 +898,7 @@ Sebastian Krzyszkowiak <dos@dosowisko.net> Seo Sanghyeon <sanxiyn@gmail.com> Seokju Kwon <seokju.kwon@gmail.com> +Seokho Song <0xdevssh@gmail.com> SeongTae Jeong <ferendevelop.gl@gmail.com> Sergey Kipet <sergey.kipet@gmail.com> Sergey Putilin <p.sergey@samsung.com>
diff --git a/DEPS b/DEPS index bcdb903..db8d2e1 100644 --- a/DEPS +++ b/DEPS
@@ -195,11 +195,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '109ff207de7d7846ec9ddcd4230dac47814b2aea', + 'skia_revision': '49983ef4e7deb15a8023223c24eca5685fec972a', # 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': 'dd1a9165f9be726553620f7c810dadd8f5660db1', + 'v8_revision': '347e854b713ba7e4d782ae008fa116ceb8ba3687', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -207,11 +207,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'de914d018068be8866e697116c0ffa6e9f2b5754', + 'angle_revision': '9385eb35f507a9c13e93e35c300ea15176b46b2c', # 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': '59b4828f293eb16f8983ae9ea0a8a0a84cf8174c', + 'swiftshader_revision': '72ea2ee4650f3f8ac7e70aaa72a38f8ea0e09e6c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -250,7 +250,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. - 'harfbuzz_revision': 'cdb7d2b9bc0d5928ae4f6ba16fe905f603583688', + 'harfbuzz_revision': 'd03eecb4d63e1cdac77a08d081179c28440b2d18', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Emoji Segmenter # and whatever else without interference from each other. @@ -266,7 +266,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': '7e3e7bb35184b4be3834a864d8d3059ae1d9079e', + 'devtools_frontend_revision': 'd2454323cb6eb157830d277e27e059e21183e135', # 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. @@ -322,7 +322,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. - 'quiche_revision': '13ebfa60c3f2970e5d7f05e85ccf29ce3c1304ba', + 'quiche_revision': '07b2e8df6cc8aeda04e989102f4c97a11297ffb2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -342,7 +342,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavif # and whatever else without interference from each other. - 'libavif_revision': '50c5bbd8f04ae9d8dc98556745b44476c3ce3223', + 'libavif_revision': '4cfee6282b97533e6c99183ddf7a897173755c69', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. @@ -875,7 +875,7 @@ # Build tools for Chrome OS. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a1d5ae72b241aea42dc26e65be8061b68981ce9d', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5245bcfaf6a900bad9c74f4b59b02d3281c32cb5', 'condition': 'checkout_chromeos', }, @@ -1248,7 +1248,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'dc4568899168e48a2721fa971994386eda1f7e63', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '0376edf14e5896af79fc71552f9579cbbd12f381', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1326,7 +1326,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': 'f3U-txC3MEm9VvlQ4pywd_v8j7679EBLg7b-jCVWqhQC' + 'version': 'NDFbDVf-nlMof_IApfrnOXCEZ6m0bLKR9ag5pittXqwC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1470,7 +1470,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '64a60835a190ec41dcb1e63a6cd081b366b7b30b', + Var('webrtc_git') + '/src.git' + '@' + '5401bad7015d510be212efa1e3d3bc1c149bc77c', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1542,7 +1542,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ea4f2acc63991e04989c6cf5c54a41abd258d027', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0b969adbdff12a835045cf33f640d91c64ee0d11', 'condition': 'checkout_src_internal', }, @@ -1550,7 +1550,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'IVemt3pOQOKoaDEDMgqmUBfRju4WJsHWYff7SymNScAC', + 'version': 'qm8oRNi8gU7naD1qdw0-8dq2k2YWuPswsrYsoz6u_n8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 1a60f44..be1c69e 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -7,17 +7,6 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into depot_tools. """ -# Run this function to enable ALL Check... functions will serve as entry -# points into our code, and we will individually time and report their results -# to ResultDB -class VersionError(Exception): pass -if __name__ == '__builtin__': - try: - REQUIRE_PRESUBMIT_VERSION(1) - except NameError: - raise VersionError("Your depot_tools is out of date, and doesn't define the" - " function REQUIRE_PRESUBMIT_VERSION needed to enable" - " the new version of presubmit checks.") _EXCLUDED_PATHS = ( @@ -1469,7 +1458,7 @@ def _IsProtoFile(input_api, file_path): return input_api.os_path.splitext(file_path)[1] == ".proto" -def CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api): +def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api): """Attempts to prevent use of functions intended only for testing in non-testing code. For now this is just a best-effort implementation that ignores header files and may have some false positives. A @@ -1512,7 +1501,7 @@ return [] -def CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api): +def _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api): """This is a simplified version of _CheckNoProductionCodeUsingTestOnlyFunctions for Java files. """ @@ -1558,7 +1547,7 @@ return [] -def CheckNoIOStreamInHeaders(input_api, output_api): +def _CheckNoIOStreamInHeaders(input_api, output_api): """Checks to make sure no .h files include <iostream>.""" files = [] pattern = input_api.re.compile(r'^#include\s*<iostream>', @@ -1601,7 +1590,7 @@ return [] -def CheckNoUNIT_TESTInSourceFiles(input_api, output_api): +def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api): """Checks to make sure no source files use UNIT_TEST.""" problems = [] for f in input_api.AffectedFiles(): @@ -1617,7 +1606,7 @@ return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' + '\n'.join(problems))] -def CheckNoDISABLETypoInTests(input_api, output_api): +def _CheckNoDISABLETypoInTests(input_api, output_api): """Checks to prevent attempts to disable tests with DISABLE_ prefix. This test warns if somebody tries to disable a test with the DISABLE_ prefix @@ -1671,7 +1660,7 @@ ] -def CheckDCHECK_IS_ONHasBraces(input_api, output_api): +def _CheckDCHECK_IS_ONHasBraces(input_api, output_api): """Checks to make sure DCHECK_IS_ON() does not skip the parentheses.""" errors = [] pattern = input_api.re.compile(r'DCHECK_IS_ON\b(?!\(\))', @@ -1709,7 +1698,7 @@ return histogram_name in chunk -def CheckUmaHistogramChangesOnUpload(input_api, output_api): +def _CheckUmaHistogramChanges(input_api, output_api): """Check that UMA histogram names in touched lines can still be found in other lines of the patch or in histograms.xml. Note that this check would not catch the reverse: changes in histograms.xml not matched in the code itself.""" @@ -1795,7 +1784,7 @@ '%s or the modifications of it:' % (histograms_xml_path), problems)] -def CheckFlakyTestUsage(input_api, output_api): +def _CheckFlakyTestUsage(input_api, output_api): """Check that FlakyTest annotation is our own instead of the android one""" pattern = input_api.re.compile(r'import android.test.FlakyTest;') files = [] @@ -1811,7 +1800,7 @@ return [] -def CheckNoNewWStrings(input_api, output_api): +def _CheckNoNewWStrings(input_api, output_api): """Checks to make sure we don't introduce use of wstrings.""" problems = [] for f in input_api.AffectedFiles(): @@ -1840,7 +1829,7 @@ '\n'.join(problems))] -def CheckNoDEPSGIT(input_api, output_api): +def _CheckNoDEPSGIT(input_api, output_api): """Make sure .DEPS.git is never modified manually.""" if any(f.LocalPath().endswith('.DEPS.git') for f in input_api.AffectedFiles()): @@ -1854,7 +1843,7 @@ return [] -def CheckValidHostsInDEPSOnUpload(input_api, output_api): +def _CheckValidHostsInDEPS(input_api, output_api): """Checks that DEPS file deps are from allowed_hosts.""" # Run only if DEPS file has been modified to annoy fewer bystanders. if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()): @@ -1903,7 +1892,7 @@ return result -def CheckNoBannedFunctions(input_api, output_api): +def _CheckNoBannedFunctions(input_api, output_api): """Make sure that banned functions are not used.""" warnings = [] errors = [] @@ -2004,7 +1993,7 @@ return result -def CheckNoDeprecatedMojoTypes(input_api, output_api): +def _CheckNoDeprecatedMojoTypes(input_api, output_api): """Make sure that old Mojo types are not used.""" warnings = [] errors = [] @@ -2042,7 +2031,7 @@ return result -def CheckNoPragmaOnce(input_api, output_api): +def _CheckNoPragmaOnce(input_api, output_api): """Make sure that banned functions are not used.""" files = [] pattern = input_api.re.compile(r'^#pragma\s+once', @@ -2062,7 +2051,7 @@ return [] -def CheckNoTrinaryTrueFalse(input_api, output_api): +def _CheckNoTrinaryTrueFalse(input_api, output_api): """Checks to make sure we don't introduce use of foo ? true : false.""" problems = [] pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)') @@ -2081,7 +2070,7 @@ '\n'.join(problems))] -def CheckUnwantedDependencies(input_api, output_api): +def _CheckUnwantedDependencies(input_api, output_api): """Runs checkdeps on #include and import statements added in this change. Breaking - rules is an error, breaking ! rules is a warning. @@ -2120,7 +2109,6 @@ warning_descriptions = [] error_subjects = set() warning_subjects = set() - for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes( added_includes): path = input_api.os_path.relpath(path, input_api.PresubmitLocalPath()) @@ -2170,7 +2158,7 @@ return results -def CheckFilePermissions(input_api, output_api): +def _CheckFilePermissions(input_api, output_api): """Check that all files have their permissions properly set.""" if input_api.platform == 'win32': return [] @@ -2195,7 +2183,7 @@ long_text=error.output)] -def CheckNoAuraWindowPropertyHInHeaders(input_api, output_api): +def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api): """Makes sure we don't include ui/aura/window_property.h in header files. """ @@ -2228,7 +2216,7 @@ return errors -def CheckForVersionControlConflicts(input_api, output_api): +def _CheckForVersionControlConflicts(input_api, output_api): """Usually this is not intentional and will cause a compile failure.""" errors = [] for f in input_api.AffectedFiles(): @@ -2241,7 +2229,7 @@ return results -def CheckGoogleSupportAnswerUrlOnUpload(input_api, output_api): +def _CheckGoogleSupportAnswerUrl(input_api, output_api): pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer') errors = [] for f in input_api.AffectedFiles(): @@ -2257,7 +2245,7 @@ return results -def CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api): +def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api): def FilterFile(affected_file): """Filter function for use with input_api.AffectedSourceFiles, below. This filters out everything except non-test files from @@ -2291,7 +2279,7 @@ return [] -def CheckChromeOsSyncedPrefRegistration(input_api, output_api): +def _CheckChromeOsSyncedPrefRegistration(input_api, output_api): """Warns if Chrome OS C++ files register syncable prefs as browser prefs.""" def FileFilter(affected_file): """Includes directories known to be Chrome OS only.""" @@ -2332,7 +2320,7 @@ # TODO: add unit tests. -def CheckNoAbbreviationInPngFileName(input_api, output_api): +def _CheckNoAbbreviationInPngFileName(input_api, output_api): """Makes sure there are no abbreviations in the name of PNG files. The native_client_sdk directory is excluded because it has auto-generated PNG files for documentation. @@ -2426,7 +2414,7 @@ return results -def CheckAddedDepsHaveTargetApprovals(input_api, output_api): +def _CheckAddedDepsHaveTargetApprovals(input_api, output_api): """When a dependency prefixed with + is added to a DEPS file, we want to make sure that the change is reviewed by an OWNER of the target file or directory, to avoid layering violations from being @@ -2505,7 +2493,7 @@ # TODO: add unit tests. -def CheckSpamLogging(input_api, output_api): +def _CheckSpamLogging(input_api, output_api): file_inclusion_pattern = [r'.+%s' % _IMPLEMENTATION_EXTENSIONS] files_to_skip = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS + @@ -2584,7 +2572,7 @@ return [] -def CheckForAnonymousVariables(input_api, output_api): +def _CheckForAnonymousVariables(input_api, output_api): """These types are all expected to hold locks while in scope and so should never be anonymous (which causes them to be immediately destroyed).""" @@ -2640,7 +2628,7 @@ return [] -def CheckUniquePtrOnUpload(input_api, output_api): +def _CheckUniquePtr(input_api, output_api): # Returns whether |template_str| is of the form <T, U...> for some types T # and U. Assumes that |template_str| is already in the form <...>. def HasMoreThanOneArg(template_str): @@ -2738,7 +2726,7 @@ return errors -def CheckUserActionUpdate(input_api, output_api): +def _CheckUserActionUpdate(input_api, output_api): """Checks if any new user action has been added.""" if any('actions.xml' == input_api.os_path.basename(f) for f in input_api.LocalPaths()): @@ -2810,7 +2798,7 @@ return e -def CheckParseErrors(input_api, output_api): +def _CheckParseErrors(input_api, output_api): """Check that IDL and JSON files do not contain syntax errors.""" actions = { '.idl': _GetIDLParseError, @@ -2864,7 +2852,7 @@ return results -def CheckJavaStyle(input_api, output_api): +def _CheckJavaStyle(input_api, output_api): """Runs checkstyle on changed java files and returns errors if any exist.""" import sys original_sys_path = sys.path @@ -2881,7 +2869,7 @@ files_to_skip=_EXCLUDED_PATHS + input_api.DEFAULT_FILES_TO_SKIP) -def CheckPythonDevilInit(input_api, output_api): +def _CheckPythonDevilInit(input_api, output_api): """Checks to make sure devil is initialized correctly in python scripts.""" script_common_initialize_pattern = input_api.re.compile( r'script_common\.InitializeEnvironment\(') @@ -3080,7 +3068,7 @@ return to_check -def CheckSecurityOwners(input_api, output_api): +def _CheckSecurityOwners(input_api, output_api): """Checks that affected files involving IPC have an IPC OWNERS rule.""" to_check = _GetOwnersFilesToCheckForIpcOwners(input_api) _AddOwnersFilesToCheckForFuchsiaSecurityOwners(input_api, to_check) @@ -3170,7 +3158,7 @@ return files_to_functions -def CheckSecurityChanges(input_api, output_api): +def _CheckSecurityChanges(input_api, output_api): """Checks that changes involving security-critical functions are reviewed by the security team. """ @@ -3206,7 +3194,7 @@ return [] -def CheckSetNoParent(input_api, output_api): +def _CheckSetNoParent(input_api, output_api): """Checks that set noparent is only used together with an OWNERS file in //build/OWNERS.setnoparent (see also //docs/code_reviews.md#owners-files-details) @@ -3271,7 +3259,7 @@ return results -def CheckUselessForwardDeclarations(input_api, output_api): +def _CheckUselessForwardDeclarations(input_api, output_api): """Checks that added or removed lines in non third party affected header files do not lead to new useless class or struct forward declaration. @@ -3742,7 +3730,7 @@ return args -def CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None): +def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None): """Checks if a .pydeps file needs to be regenerated.""" # This check is for Python dependency lists (.pydeps files), and involves # paths not only in the PRESUBMIT.py, but also in the .pydeps files. It @@ -3804,7 +3792,7 @@ return results -def CheckSingletonInHeaders(input_api, output_api): +def _CheckSingletonInHeaders(input_api, output_api): """Checks to make sure no header files have |Singleton<|.""" def FileFilter(affected_file): # It's ok for base/memory/singleton.h to have |Singleton<|. @@ -3864,7 +3852,7 @@ # TODO: add unit tests -def CheckNoDeprecatedCss(input_api, output_api): +def _CheckNoDeprecatedCss(input_api, output_api): """ Make sure that we don't use deprecated CSS properties, functions or values. Our external documentation and iOS CSS for dom distiller @@ -3892,7 +3880,7 @@ return results -def CheckForRelativeIncludes(input_api, output_api): +def _CheckForRelativeIncludes(input_api, output_api): bad_files = {} for f in input_api.AffectedFiles(include_deletes=False): if (f.LocalPath().startswith('third_party') and @@ -3930,7 +3918,7 @@ return results -def CheckForCcIncludes(input_api, output_api): +def _CheckForCcIncludes(input_api, output_api): """Check that nobody tries to include a cc file. It's a relatively common error which results in duplicate symbols in object files. This may not always break the build until someone later gets @@ -4070,7 +4058,7 @@ return _CheckWATCHLISTSEntries(first_value, second_value, input_api) -def CheckWATCHLISTS(input_api, output_api): +def _CheckWATCHLISTS(input_api, output_api): for f in input_api.AffectedFiles(include_deletes=False): if f.LocalPath() == 'WATCHLISTS': contents = input_api.ReadFile(f, 'r') @@ -4099,7 +4087,7 @@ return [] -def CheckNewHeaderWithoutGnChangeOnUpload(input_api, output_api): +def _CheckNewHeaderWithoutGnChange(input_api, output_api): """Checks that newly added header files have corresponding GN changes. Note that this is only a heuristic. To be precise, run script: build/check_gn_headers.py. @@ -4139,7 +4127,7 @@ return [] -def CheckCorrectProductNameInMessages(input_api, output_api): +def _CheckCorrectProductNameInMessages(input_api, output_api): """Check that Chromium-branded strings don't include "Chrome" or vice versa. This assumes we won't intentionally reference one product from the other @@ -4183,7 +4171,7 @@ return all_problems -def CheckBuildtoolsRevisionsAreInSync(input_api, output_api): +def _CheckBuildtoolsRevisionsAreInSync(input_api, output_api): # TODO(crbug.com/941824): We need to make sure the entries in # //buildtools/DEPS are kept in sync with the entries in //DEPS # so that users of //buildtools in other projects get the same tooling @@ -4223,7 +4211,7 @@ return [] -def CheckForTooLargeFiles(input_api, output_api): +def _CheckForTooLargeFiles(input_api, output_api): """Avoid large files, especially binary files, in the repository since git doesn't scale well for those. They will be in everyone's repo clones forever, forever making Chromium slower to clone and work @@ -4255,7 +4243,7 @@ return [] -def CheckFuzzTargetsOnUpload(input_api, output_api): +def _CheckFuzzTargets(input_api, output_api): """Checks specific for fuzz target sources.""" EXPORTED_SYMBOLS = [ 'LLVMFuzzerInitialize', @@ -4336,7 +4324,7 @@ return errors -def ChecksAndroidSpecificOnUpload(input_api, output_api): +def _AndroidSpecificOnUploadChecks(input_api, output_api): """Groups upload checks that target android code.""" results = [] results.extend(_CheckAndroidCrLogUsage(input_api, output_api)) @@ -4352,7 +4340,7 @@ results.extend(_CheckAndroidNoBannedImports(input_api, output_api)) return results -def ChecksAndroidSpecificOnCommit(input_api, output_api): +def _AndroidSpecificOnCommitChecks(input_api, output_api): """Groups commit checks that target android code.""" results = [] results.extend(_CheckAndroidXmlStyle(input_api, output_api, False)) @@ -4373,7 +4361,7 @@ r"^ui[\\/]views[\\/]accessibility[\\/]", ) -def CheckAccessibilityRelnotesField(input_api, output_api): +def _CheckAccessibilityRelnotesField(input_api, output_api): """Checks that commits to accessibility code contain an AX-Relnotes field in their commit message.""" def FileFilter(affected_file): @@ -4407,7 +4395,7 @@ return [output_api.PresubmitNotifyResult(message)] -def ChecksCommon(input_api, output_api): +def _CommonChecks(input_api, output_api): """Checks common to both upload and commit.""" results = [] results.extend(input_api.canned_checks.PanProjectChecks( @@ -4419,13 +4407,67 @@ results.extend( input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api)) + results.extend(_CheckAccessibilityRelnotesField(input_api, output_api)) + results.extend( + _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api)) + results.extend( + _CheckNoProductionCodeUsingTestOnlyFunctionsJava(input_api, output_api)) + results.extend(_CheckNoIOStreamInHeaders(input_api, output_api)) + results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api)) + results.extend(_CheckNoDISABLETypoInTests(input_api, output_api)) + results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api)) + results.extend(_CheckNoNewWStrings(input_api, output_api)) + results.extend(_CheckNoDEPSGIT(input_api, output_api)) + results.extend(_CheckNoBannedFunctions(input_api, output_api)) + results.extend(_CheckNoDeprecatedMojoTypes(input_api, output_api)) + results.extend(_CheckNoPragmaOnce(input_api, output_api)) + results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api)) + results.extend(_CheckUnwantedDependencies(input_api, output_api)) + results.extend(_CheckFilePermissions(input_api, output_api)) + results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api)) + results.extend(_CheckForVersionControlConflicts(input_api, output_api)) + results.extend(_CheckPatchFiles(input_api, output_api)) + results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api)) + results.extend(_CheckChromeOsSyncedPrefRegistration(input_api, output_api)) + results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api)) + results.extend(_CheckBuildConfigMacrosWithoutInclude(input_api, output_api)) + results.extend(_CheckForInvalidOSMacros(input_api, output_api)) + results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api)) + results.extend(_CheckFlakyTestUsage(input_api, output_api)) + results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api)) results.extend( input_api.canned_checks.CheckChangeHasNoTabs( input_api, output_api, source_file_filter=lambda x: x.LocalPath().endswith('.grd'))) + results.extend(_CheckSpamLogging(input_api, output_api)) + results.extend(_CheckForAnonymousVariables(input_api, output_api)) + results.extend(_CheckUserActionUpdate(input_api, output_api)) + results.extend(_CheckNoDeprecatedCss(input_api, output_api)) + results.extend(_CheckParseErrors(input_api, output_api)) + results.extend(_CheckForIPCRules(input_api, output_api)) + results.extend(_CheckForLongPathnames(input_api, output_api)) + results.extend(_CheckForIncludeGuards(input_api, output_api)) + results.extend(_CheckForWindowsLineEndings(input_api, output_api)) + results.extend(_CheckSingletonInHeaders(input_api, output_api)) + results.extend(_CheckPydepsNeedsUpdating(input_api, output_api)) + results.extend(_CheckJavaStyle(input_api, output_api)) + results.extend(_CheckSecurityOwners(input_api, output_api)) + results.extend(_CheckSecurityChanges(input_api, output_api)) + results.extend(_CheckSetNoParent(input_api, output_api)) + results.extend(_CheckUselessForwardDeclarations(input_api, output_api)) + results.extend(_CheckForRelativeIncludes(input_api, output_api)) + results.extend(_CheckForCcIncludes(input_api, output_api)) + results.extend(_CheckWATCHLISTS(input_api, output_api)) results.extend(input_api.RunTests( input_api.canned_checks.CheckVPythonSpec(input_api, output_api))) + results.extend(_CheckStrings(input_api, output_api)) + results.extend(_CheckTranslationExpectations(input_api, output_api)) + results.extend(_CheckCorrectProductNameInMessages(input_api, output_api)) + results.extend(_CheckBuildtoolsRevisionsAreInSync(input_api, output_api)) + results.extend(_CheckForTooLargeFiles(input_api, output_api)) + results.extend(_CheckPythonDevilInit(input_api, output_api)) + results.extend(_CheckStableMojomChanges(input_api, output_api)) dirmd_bin = input_api.os_path.join( input_api.PresubmitLocalPath(), 'third_party', 'depot_tools', 'dirmd') @@ -4451,7 +4493,7 @@ return results -def CheckPatchFiles(input_api, output_api): +def _CheckPatchFiles(input_api, output_api): problems = [f.LocalPath() for f in input_api.AffectedFiles() if f.LocalPath().endswith(('.orig', '.rej'))] if problems: @@ -4461,7 +4503,7 @@ return [] -def CheckBuildConfigMacrosWithoutInclude(input_api, output_api): +def _CheckBuildConfigMacrosWithoutInclude(input_api, output_api): # Excludes OS_CHROMEOS, which is not defined in build_config.h. macro_re = input_api.re.compile(r'^\s*#(el)?if.*\bdefined\(((OS_(?!CHROMEOS)|' 'COMPILER_|ARCH_CPU_|WCHAR_T_IS_)[^)]*)') @@ -4543,7 +4585,7 @@ return results -def CheckForInvalidOSMacros(input_api, output_api): +def _CheckForInvalidOSMacros(input_api, output_api): """Check all affected files for invalid OS macros.""" bad_macros = [] for f in input_api.AffectedSourceFiles(None): @@ -4590,7 +4632,7 @@ return results -def CheckForInvalidIfDefinedMacros(input_api, output_api): +def _CheckForInvalidIfDefinedMacros(input_api, output_api): """Check all affected files for invalid "if defined" macros.""" bad_macros = [] skipped_paths = ['third_party/sqlite/', 'third_party/abseil-cpp/'] @@ -4609,7 +4651,7 @@ bad_macros)] -def CheckForIPCRules(input_api, output_api): +def _CheckForIPCRules(input_api, output_api): """Check for same IPC rules described in http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc """ @@ -4634,7 +4676,7 @@ return [] -def CheckForLongPathnames(input_api, output_api): +def _CheckForLongPathnames(input_api, output_api): """Check to make sure no files being submitted have long paths. This causes issues on Windows. """ @@ -4652,7 +4694,7 @@ return [] -def CheckForIncludeGuards(input_api, output_api): +def _CheckForIncludeGuards(input_api, output_api): """Check that header files have proper guards against multiple inclusion. If a file should not have such guards (and it probably should) then it should include the string "no-include-guard-because-multiply-included". @@ -4764,7 +4806,7 @@ return errors -def CheckForWindowsLineEndings(input_api, output_api): +def _CheckForWindowsLineEndings(input_api, output_api): """Check source code and known ascii text files for Windows style line endings. """ @@ -4794,10 +4836,10 @@ return [] -def CheckSyslogUseWarningOnUpload(input_api, output_api, src_file_filter=None): +def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None): """Checks that all source files use SYSLOG properly.""" syslog_files = [] - for f in input_api.AffectedSourceFiles(src_file_filter): + for f in input_api.AffectedSourceFiles(source_file_filter): for line_number, line in f.ChangedContents(): if 'SYSLOG' in line: syslog_files.append(f.LocalPath() + ':' + str(line_number)) @@ -4811,8 +4853,17 @@ def CheckChangeOnUpload(input_api, output_api): results = [] + results.extend(_CommonChecks(input_api, output_api)) + results.extend(_CheckValidHostsInDEPS(input_api, output_api)) results.extend( input_api.canned_checks.CheckPatchFormatted(input_api, output_api)) + results.extend(_CheckUmaHistogramChanges(input_api, output_api)) + results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api)) + results.extend(_CheckSyslogUseWarning(input_api, output_api)) + results.extend(_CheckGoogleSupportAnswerUrl(input_api, output_api)) + results.extend(_CheckUniquePtr(input_api, output_api)) + results.extend(_CheckNewHeaderWithoutGnChange(input_api, output_api)) + results.extend(_CheckFuzzTargets(input_api, output_api)) return results @@ -4842,6 +4893,8 @@ def CheckChangeOnCommit(input_api, output_api): results = [] + results.extend(_CommonChecks(input_api, output_api)) + results.extend(_AndroidSpecificOnCommitChecks(input_api, output_api)) # Make sure the tree is 'open'. results.extend(input_api.canned_checks.CheckTreeIsOpen( input_api, @@ -4859,7 +4912,7 @@ return results -def CheckStrings(input_api, output_api): +def _CheckStrings(input_api, output_api): """Check string ICU syntax validity and if translation screenshots exist.""" # Skip translation screenshots check if a SkipTranslationScreenshotsCheck # footer is set to true. @@ -5170,7 +5223,7 @@ return results -def CheckTranslationExpectations(input_api, output_api, +def _CheckTranslationExpectations(input_api, output_api, repo_root=None, translation_expectations_path=None, grd_files=None): @@ -5215,7 +5268,7 @@ return [] -def CheckStableMojomChanges(input_api, output_api): +def _CheckStableMojomChanges(input_api, output_api): """Changes to [Stable] mojom types must preserve backward-compatibility.""" changed_mojoms = input_api.AffectedFiles( include_deletes=True,
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py index cb9461d..111f2b2 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py
@@ -8,7 +8,6 @@ import unittest import PRESUBMIT - from PRESUBMIT_test_mocks import MockFile, MockAffectedFile from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi @@ -53,7 +52,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -66,7 +65,7 @@ MockFile('some/path/foo.cc', diff_cc), MockFile('some/path/foo.java', diff_java), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('warning', warnings[0].type) @@ -87,7 +86,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('warning', warnings[0].type) @@ -108,7 +107,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -125,7 +124,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -147,7 +146,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -165,7 +164,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -178,7 +177,7 @@ MockFile('some/path/foo.cc', diff_cc), MockFile('some/path/foo.java', diff_java), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -195,7 +194,7 @@ MockFile('some/path/foo2.cc', diff_cc2), MockFile('some/path/foo.java', diff_java), ] - warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, + warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('warning', warnings[0].type) @@ -212,7 +211,7 @@ MockFile('some/path2/bar.h.rej', ''), ] - results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi()) + results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertEqual(2, len(results[0].items)) self.assertTrue('foo.cc.rej' in results[0].items[0]) @@ -226,7 +225,7 @@ MockFile('other/path/qux.cc', ''), ] - results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi()) + results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertEqual(1, len(results[0].items)) self.assertTrue('qux.h.orig' in results[0].items[0]) @@ -237,7 +236,7 @@ MockFile('other/path/qux.h', ''), MockFile('other/path/qux.cc', ''), ] - results = PRESUBMIT.CheckPatchFiles(mock_input_api, MockOutputApi()) + results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) @@ -255,7 +254,7 @@ MockAffectedFile('foo.h', diff_foo_h), MockAffectedFile('foo2.h', diff_foo2_h), MockAffectedFile('bad.h', diff_bad_h)] - warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api, + warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual(1, len(warnings[0].items)) @@ -266,7 +265,7 @@ diff_cc = ['Foo* foo = base::Singleton<Foo>::get();'] mock_input_api = MockInputApi() mock_input_api.files = [MockAffectedFile('some/path/foo.cc', diff_cc)] - warnings = PRESUBMIT.CheckSingletonInHeaders(mock_input_api, + warnings = PRESUBMIT._CheckSingletonInHeaders(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -688,7 +687,7 @@ contents_with_user_action)] self.assertEqual( - [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())) + [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())) def testUserMetricsActionNotAddedToActions(self): input_api = MockInputApi() @@ -700,7 +699,7 @@ input_api.files = [MockFile(file_with_user_action, contents_with_user_action)] - output = PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi()) + output = PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi()) self.assertEqual( ('File %s line %d: %s is missing in ' 'tools/metrics/actions/actions.xml. Please run ' @@ -744,12 +743,12 @@ PRESUBMIT._ParseGclientArgs = self.old_ParseGclientArgs def _RunCheck(self): - return PRESUBMIT.CheckPydepsNeedsUpdating(self.mock_input_api, + return PRESUBMIT._CheckPydepsNeedsUpdating(self.mock_input_api, self.mock_output_api, checker_for_tests=self.checker) def testAddedPydep(self): - # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux. + # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux. if self.mock_input_api.platform != 'linux2': return [] @@ -773,7 +772,7 @@ self.assertEqual(0, len(results)) def testRemovedPydep(self): - # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux. + # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux. if self.mock_input_api.platform != 'linux2': return [] @@ -788,7 +787,7 @@ self.assertTrue('PYDEPS_FILES' in str(results[0])) def testRandomPyIgnored(self): - # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux. + # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux. if self.mock_input_api.platform != 'linux2': return [] @@ -800,7 +799,7 @@ self.assertEqual(0, len(results), 'Unexpected results: %r' % results) def testRelevantPyNoChange(self): - # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux. + # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux. if self.mock_input_api.platform != 'linux2': return [] @@ -818,7 +817,7 @@ self.assertEqual(0, len(results), 'Unexpected results: %r' % results) def testRelevantPyOneChange(self): - # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux. + # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux. if self.mock_input_api.platform != 'linux2': return [] @@ -837,7 +836,7 @@ self.assertTrue('File is stale' in str(results[0])) def testRelevantPyTwoChanges(self): - # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux. + # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux. if self.mock_input_api.platform != 'linux2': return [] @@ -856,7 +855,7 @@ self.assertTrue('File is stale' in str(results[1])) def testRelevantAndroidPyInNonAndroidCheckout(self): - # PRESUBMIT.CheckPydepsNeedsUpdating is only implemented for Linux. + # PRESUBMIT._CheckPydepsNeedsUpdating is only implemented for Linux. if self.mock_input_api.platform != 'linux2': return [] @@ -1013,7 +1012,7 @@ '#endif', ]), ] - msgs = PRESUBMIT.CheckForIncludeGuards( + msgs = PRESUBMIT._CheckForIncludeGuards( mock_input_api, mock_output_api) expected_fail_count = 8 self.assertEqual(expected_fail_count, len(msgs), @@ -1067,7 +1066,7 @@ mock_input_api.change.footers['AX-Relnotes'] = [ 'Important user facing change'] - msgs = PRESUBMIT.CheckAccessibilityRelnotesField( + msgs = PRESUBMIT._CheckAccessibilityRelnotesField( mock_input_api, mock_output_api) self.assertEqual(0, len(msgs), 'Expected %d messages, found %d: %s' @@ -1084,7 +1083,7 @@ ] mock_input_api.change.DescriptionText = lambda : 'Commit description' - msgs = PRESUBMIT.CheckAccessibilityRelnotesField( + msgs = PRESUBMIT._CheckAccessibilityRelnotesField( mock_input_api, mock_output_api) self.assertEqual(1, len(msgs), 'Expected %d messages, found %d: %s' @@ -1104,7 +1103,7 @@ ] mock_input_api.change.DescriptionText = lambda : 'Commit description' - msgs = PRESUBMIT.CheckAccessibilityRelnotesField( + msgs = PRESUBMIT._CheckAccessibilityRelnotesField( mock_input_api, mock_output_api) self.assertEqual(0, len(msgs), 'Expected %d messages, found %d: %s' @@ -1137,7 +1136,7 @@ ] mock_input_api.change.DescriptionText = lambda : 'Commit description' - msgs = PRESUBMIT.CheckAccessibilityRelnotesField( + msgs = PRESUBMIT._CheckAccessibilityRelnotesField( mock_input_api, mock_output_api) self.assertEqual(1, len(msgs), 'Expected %d messages, found %d: %s, for file %s' @@ -1158,7 +1157,7 @@ mock_input_api.change.DescriptionText = lambda : ('Description:\n' + 'AX-Relnotes: solves all accessibility issues forever') - msgs = PRESUBMIT.CheckAccessibilityRelnotesField( + msgs = PRESUBMIT._CheckAccessibilityRelnotesField( mock_input_api, mock_output_api) self.assertEqual(0, len(msgs), 'Expected %d messages, found %d: %s' @@ -1175,7 +1174,7 @@ mock_input_api.change.DescriptionText = lambda : ('Description:\n' + 'This change has no AX-Relnotes: we should print a warning') - msgs = PRESUBMIT.CheckAccessibilityRelnotesField( + msgs = PRESUBMIT._CheckAccessibilityRelnotesField( mock_input_api, mock_output_api) self.assertTrue("Missing 'AX-Relnotes:' field" in msgs[0].message, 'Missing AX-Relnotes field message not found in errors') @@ -1192,7 +1191,7 @@ mock_input_api.change.DescriptionText = lambda : ('Description:\n' + 'ax-relnotes= this is a valid format for accessibiliy relnotes') - msgs = PRESUBMIT.CheckAccessibilityRelnotesField( + msgs = PRESUBMIT._CheckAccessibilityRelnotesField( mock_input_api, mock_output_api) self.assertEqual(0, len(msgs), 'Expected %d messages, found %d: %s' @@ -1548,7 +1547,7 @@ ' "https://support.google.com/chrome/a/answer/123456";']), ] - warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload( + warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl( input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual(2, len(warnings[0].items)) @@ -1561,7 +1560,7 @@ ' "https://support.google.com/chrome/?p=cpn_crash_reports";']), ] - warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload( + warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1579,7 +1578,7 @@ ['char* host = "https://clients1.google.com";']), ] - warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers( + warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers( input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual(3, len(warnings[0].items)) @@ -1591,7 +1590,7 @@ ['char* host = "https://www.aol.com"; // google.com']) ] - warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers( + warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1612,7 +1611,7 @@ MockFile('components/exo/file.cc', ['PrefRegistrySyncable::SYNCABLE_PREF']), ] - warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) @@ -1622,7 +1621,7 @@ MockFile('chromeos/file.cc', ['PrefRegistrySyncable::SYNCABLE_OS_PREF']), ] - warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1636,7 +1635,7 @@ MockFile('content/browser/file.cc', ['PrefRegistrySyncable::SYNCABLE_PREF']), ] - warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1647,7 +1646,7 @@ ['PrefRegistrySyncable::SYNCABLE_PREF', 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']), ] - warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) @@ -1663,7 +1662,7 @@ 'class DummyClass;' ]) ] - warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1677,7 +1676,7 @@ '};' ]) ] - warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1691,7 +1690,7 @@ 'SomeStructPtr *p2;' ]) ] - warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) @@ -1705,7 +1704,7 @@ 'std::unique_ptr<UsefulClass> p;' ]) ] - warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) @@ -1721,7 +1720,7 @@ 'struct DummyStruct;', ]) ] - warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(4, len(warnings)) @@ -1736,7 +1735,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForRelativeIncludes( + errors = PRESUBMIT._CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1748,7 +1747,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForRelativeIncludes( + errors = PRESUBMIT._CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1761,7 +1760,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForRelativeIncludes( + errors = PRESUBMIT._CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1773,7 +1772,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForRelativeIncludes( + errors = PRESUBMIT._CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1786,7 +1785,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForRelativeIncludes( + errors = PRESUBMIT._CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1800,7 +1799,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForCcIncludes( + errors = PRESUBMIT._CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1812,7 +1811,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForCcIncludes( + errors = PRESUBMIT._CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1824,7 +1823,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForCcIncludes( + errors = PRESUBMIT._CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1837,7 +1836,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForCcIncludes( + errors = PRESUBMIT._CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1849,7 +1848,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForCcIncludes( + errors = PRESUBMIT._CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1862,7 +1861,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckForCcIncludes( + errors = PRESUBMIT._CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1873,7 +1872,7 @@ mock_input_api.files = [ MockAffectedFile('base/stuff.h', ''), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue('base/stuff.h' in warnings[0].items) @@ -1883,7 +1882,7 @@ mock_input_api.files = [ MockAffectedFile('base/stuff.h', '', action='M'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1892,7 +1891,7 @@ mock_input_api.files = [ MockAffectedFile('base/stuff.h', '', action='D'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1902,7 +1901,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/BUILD.gn', 'stuff.h'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1912,7 +1911,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/files.gni', 'stuff.h'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1922,7 +1921,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/stuff.cc', 'stuff.h'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) @@ -1932,7 +1931,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/BUILD.gn', 'stuff_h'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) @@ -1943,7 +1942,7 @@ MockAffectedFile('base/another.h', ''), MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1954,7 +1953,7 @@ MockAffectedFile('base/another.h', ''), MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertFalse('base/stuff.h' in warnings[0].items) @@ -1967,7 +1966,7 @@ MockAffectedFile('base/another.h', ''), MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'), ] - warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( + warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue('base/stuff.h' in warnings[0].items) @@ -1989,7 +1988,7 @@ '</message>', ]), ] - warnings = PRESUBMIT.CheckCorrectProductNameInMessages( + warnings = PRESUBMIT._CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -2007,7 +2006,7 @@ '</message>', ]), ] - warnings = PRESUBMIT.CheckCorrectProductNameInMessages( + warnings = PRESUBMIT._CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue('chrome/app/chromium_strings.grd' in warnings[0].items[0]) @@ -2026,7 +2025,7 @@ '</message>', ]), ] - warnings = PRESUBMIT.CheckCorrectProductNameInMessages( + warnings = PRESUBMIT._CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue( @@ -2047,7 +2046,7 @@ '</message>', ]), ] - warnings = PRESUBMIT.CheckCorrectProductNameInMessages( + warnings = PRESUBMIT._CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue( @@ -2081,7 +2080,7 @@ '</message>', ]), ] - warnings = PRESUBMIT.CheckCorrectProductNameInMessages( + warnings = PRESUBMIT._CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) self.assertTrue( @@ -2103,7 +2102,7 @@ 'const service_manager::Manifest& GetManifest() {}', ])] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSecurityOwners( + errors = PRESUBMIT._CheckSecurityOwners( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) self.assertEqual( @@ -2118,7 +2117,7 @@ 'const char kNoEnforcement[] = "not a manifest!";', ])] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSecurityOwners( + errors = PRESUBMIT._CheckSecurityOwners( mock_input_api, mock_output_api) self.assertEqual([], errors) @@ -2132,7 +2131,7 @@ 'library test.fidl' ])] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSecurityOwners( + errors = PRESUBMIT._CheckSecurityOwners( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) self.assertEqual( @@ -2147,7 +2146,7 @@ '{ "that is no": "manifest!" }' ])] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSecurityOwners( + errors = PRESUBMIT._CheckSecurityOwners( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) self.assertEqual( @@ -2162,7 +2161,7 @@ '{ "that is no": "manifest!" }' ])] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSecurityOwners( + errors = PRESUBMIT._CheckSecurityOwners( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) self.assertEqual( @@ -2177,7 +2176,7 @@ 'const char kNoEnforcement[] = "Security?!? Pah!";', ])] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSecurityOwners( + errors = PRESUBMIT._CheckSecurityOwners( mock_input_api, mock_output_api) self.assertEqual([], errors) @@ -2253,7 +2252,7 @@ mock_output_api = MockOutputApi() self._mockChangeOwnerAndReviewers( mock_input_api, 'owner@chromium.org', ['banana@chromium.org']) - result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api) + result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api) self.assertEquals(1, len(result)) self.assertEquals(result[0].type, 'notify') self.assertEquals(result[0].message, @@ -2272,7 +2271,7 @@ mock_output_api = MockOutputApi() self._mockChangeOwnerAndReviewers( mock_input_api, 'owner@chromium.org', ['banana@chromium.org']) - result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api) + result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api) self.assertEquals(1, len(result)) self.assertEquals(result[0].type, 'error') self.assertEquals(result[0].message, @@ -2291,7 +2290,7 @@ self._mockChangeOwnerAndReviewers( mock_input_api, 'owner@chromium.org', ['apple@chromium.org', 'banana@chromium.org']) - result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api) + result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api) self.assertEquals(0, len(result)) def testChangeOwnerIsSecurityOwner(self): @@ -2303,7 +2302,7 @@ mock_output_api = MockOutputApi() self._mockChangeOwnerAndReviewers( mock_input_api, 'orange@chromium.org', ['pear@chromium.org']) - result = PRESUBMIT.CheckSecurityChanges(mock_input_api, mock_output_api) + result = PRESUBMIT._CheckSecurityChanges(mock_input_api, mock_output_api) self.assertEquals(1, len(result)) @@ -2322,7 +2321,7 @@ ['set_owned_by_client()']), ] - results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi()) + results = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi()) # warnings are results[0], errors are results[1] self.assertEqual(2, len(results)) @@ -2354,7 +2353,7 @@ ] # warnings are errors[0], errors are errors[1] - errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi()) + errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi()) self.assertEqual(2, len(errors)) self.assertTrue('some/cpp/problematic/file1.cc' in errors[1].message) self.assertTrue('some/cpp/problematic/file2.cc' in errors[0].message) @@ -2381,7 +2380,7 @@ ['TEST_F(SomeTest, TestThis) { EXPECT_OCMOCK_VERIFY(aMock); }']), ] - errors = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi()) + errors = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi()) self.assertEqual(1, len(errors)) self.assertTrue('some/ios/file.mm' in errors[0].message) self.assertTrue('another/ios_file.mm' in errors[0].message) @@ -2406,7 +2405,7 @@ ['mojo::ConvertTo<>']), ] - results = PRESUBMIT.CheckNoBannedFunctions(input_api, MockOutputApi()) + results = PRESUBMIT._CheckNoBannedFunctions(input_api, MockOutputApi()) # warnings are results[0], errors are results[1] self.assertEqual(2, len(results)) @@ -2511,7 +2510,7 @@ input_api.files.append(MockFile(os.path.join(path, test_case['file']), [test_case['type']])) - results = PRESUBMIT.CheckNoDeprecatedMojoTypes(input_api, MockOutputApi()) + results = PRESUBMIT._CheckNoDeprecatedMojoTypes(input_api, MockOutputApi()) # warnings are results[0], errors are results[1] self.assertEqual(2, len(results)) @@ -2543,7 +2542,7 @@ MockFile('some/path/foo.cpp', ['foo_for_test();']), ] - results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions( + results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions( mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertEqual(4, len(results[0].items)) @@ -2561,7 +2560,7 @@ MockFile('some/path/foo.cpp', ['// foo_for_test();']), ] - results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions( + results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions( mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) @@ -2579,7 +2578,7 @@ ]) ] - results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava( + results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava( mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertEqual(4, len(results[0].items)) @@ -2608,7 +2607,7 @@ ]), ] - results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava( + results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava( mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) @@ -2653,7 +2652,7 @@ MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']), ] - results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi()) + results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertTrue('nullptr' in results[0].message) self.assertEqual(2, len(results[0].items)) @@ -2681,7 +2680,7 @@ 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']), ] - results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi()) + results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertTrue('std::make_unique' in results[0].message) self.assertEqual(6, len(results[0].items)) @@ -2713,7 +2712,7 @@ 'auto p = std::unique_ptr<T, D>(new T(), D());']), ] - results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi()) + results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase): @@ -2937,7 +2936,7 @@ self.NEW_GRD_CONTENTS1, action='M'), MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS1, self.NEW_GRDP_CONTENTS1, action='M')]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -2947,7 +2946,7 @@ self.NEW_GRD_CONTENTS1, action='M'), MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2, self.NEW_GRDP_CONTENTS1, action='M')]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual(self.GENERATE_SIGNATURES_MESSAGE, warnings[0].message) @@ -2963,7 +2962,7 @@ self.OLD_GRD_CONTENTS, action='M'), MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS2, self.OLD_GRDP_CONTENTS, action='M')]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('error', warnings[0].type) @@ -2991,7 +2990,7 @@ MockAffectedFile( os.path.join('test_grd', 'IDS_TEST1.png'), 'binary', action='A') ]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) self.assertEqual('error', warnings[0].type) @@ -3028,7 +3027,7 @@ os.path.join('part_grdp', 'IDS_PART_TEST1.png'), 'binary', action='A') ]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) self.assertEqual('error', warnings[0].type) @@ -3075,7 +3074,7 @@ 'binary', action='A'), ]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual([], warnings) @@ -3103,7 +3102,7 @@ MockFile(os.path.join('part_grdp', 'IDS_PART_TEST2.png.sha1'), 'binary', '') ]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('error', warnings[0].type) @@ -3144,7 +3143,7 @@ 'old_contents', action='D') ]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('error', warnings[0].type) @@ -3184,7 +3183,7 @@ 'binary', action='D') ]) - warnings = PRESUBMIT.CheckStrings(input_api, + warnings = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) self.assertEqual([], warnings) @@ -3195,7 +3194,7 @@ self.NEW_GRD_CONTENTS1, action='M'), MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2, self.NEW_GRDP_CONTENTS1, action='M')]) - results = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) + results = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) # We expect no ICU syntax errors. icu_errors = [e for e in results if e.message == self.ICU_SYNTAX_ERROR_MESSAGE] @@ -3207,7 +3206,7 @@ self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'), MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK2, self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')]) - results = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) + results = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) # We expect no ICU syntax errors. icu_errors = [e for e in results if e.message == self.ICU_SYNTAX_ERROR_MESSAGE] @@ -3219,7 +3218,7 @@ self.NEW_GRD_CONTENTS1, action='M'), MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR, self.NEW_GRD_CONTENTS1, action='M')]) - results = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) + results = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) # We expect 2 ICU syntax errors. icu_errors = [e for e in results if e.message == self.ICU_SYNTAX_ERROR_MESSAGE] @@ -3236,7 +3235,7 @@ self.NEW_GRD_CONTENTS_ICU_SYNTAX_OK1, action='M'), MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS_ICU_SYNTAX_ERROR, self.NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1, action='M')]) - results = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) + results = PRESUBMIT._CheckStrings(input_api, MockOutputApi()) # We expect 2 ICU syntax errors. icu_errors = [e for e in results if e.message == self.ICU_SYNTAX_ERROR_MESSAGE] @@ -3275,7 +3274,7 @@ # under tools/translation/testdata. This is OK because the presubmit won't # run in the first place since there are no modified grd/grps in input_api. grd_files = ['doesnt_exist_doesnt_matter.grd'] - warnings = PRESUBMIT.CheckTranslationExpectations( + warnings = PRESUBMIT._CheckTranslationExpectations( input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS, grd_files) self.assertEqual(0, len(warnings)) @@ -3293,7 +3292,7 @@ # List of all grd files in the repo. grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd', 'internal.grd'] - warnings = PRESUBMIT.CheckTranslationExpectations( + warnings = PRESUBMIT._CheckTranslationExpectations( input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS, grd_files) self.assertEqual(0, len(warnings)) @@ -3310,7 +3309,7 @@ # unlisted.grd is listed under tools/translation/testdata but is not # included in translation expectations. grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd'] - warnings = PRESUBMIT.CheckTranslationExpectations( + warnings = PRESUBMIT._CheckTranslationExpectations( input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS, grd_files) self.assertEqual(1, len(warnings)) @@ -3334,7 +3333,7 @@ # included in translation expectations. grd_files = ['test.grd', 'unlisted.grd', 'not_translated.grd', 'internal.grd'] - warnings = PRESUBMIT.CheckTranslationExpectations( + warnings = PRESUBMIT._CheckTranslationExpectations( input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files) self.assertEqual(1, len(warnings)) @@ -3361,7 +3360,7 @@ # test.grd is not listed under tools/translation/testdata but is included # in translation expectations. grd_files = ['unlisted.grd', 'not_translated.grd', 'internal.grd'] - warnings = PRESUBMIT.CheckTranslationExpectations( + warnings = PRESUBMIT._CheckTranslationExpectations( input_api, MockOutputApi(), self.REPO_ROOT, self.EXPECTATIONS_WITHOUT_UNLISTED_FILE, grd_files) self.assertEqual(1, len(warnings)) @@ -3409,7 +3408,7 @@ MockFile('some/path/foo_unittest.cc', test.splitlines()), ] - results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api, + results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api, MockOutputApi()) self.assertEqual( 1, @@ -3427,7 +3426,7 @@ MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, DISABLE_Foo)'), ] - results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api, + results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) @@ -3437,7 +3436,7 @@ MockFile('some/path/foo.cc', 'TEST_F(FoobarTest, Foo)', action='D'), ] - results = PRESUBMIT.CheckNoDISABLETypoInTests(mock_input_api, + results = PRESUBMIT._CheckNoDISABLETypoInTests(mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) @@ -3455,7 +3454,7 @@ mock_input_api.files = [] for fname, contents in files.items(): mock_input_api.files.append(MockFile(fname, contents.splitlines())) - return PRESUBMIT.CheckBuildtoolsRevisionsAreInSync(mock_input_api, + return PRESUBMIT._CheckBuildtoolsRevisionsAreInSync(mock_input_api, MockOutputApi()) def testOneFileChangedButNotTheOther(self): @@ -3492,7 +3491,7 @@ mock_input_api.files = [] for fname, contents in files.items(): mock_input_api.files.append(MockFile(fname, contents.splitlines())) - return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi()) + return PRESUBMIT._CheckFuzzTargets(mock_input_api, MockOutputApi()) def testLibFuzzerSourcesIgnored(self): results = self._check({ @@ -3536,7 +3535,7 @@ ]) ] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api) + errors = PRESUBMIT._CheckSetNoParent(mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) self.assertTrue('goat/OWNERS:1' in errors[0].long_text) self.assertTrue('goat/OWNERS:3' in errors[0].long_text) @@ -3554,7 +3553,7 @@ ]) ] mock_output_api = MockOutputApi() - errors = PRESUBMIT.CheckSetNoParent(mock_input_api, mock_output_api) + errors = PRESUBMIT._CheckSetNoParent(mock_input_api, mock_output_api) self.assertEqual([], errors) @@ -3563,7 +3562,7 @@ mock_input_api = MockInputApi() mock_input_api.files = affected_files mock_output_api = MockOutputApi() - return PRESUBMIT.CheckStableMojomChanges( + return PRESUBMIT._CheckStableMojomChanges( mock_input_api, mock_output_api) def testSafeChangePasses(self):
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 7926047..3f791586 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -198,6 +198,8 @@ "ambient/ui/assistant_response_container_view.h", "ambient/ui/glanceable_info_view.cc", "ambient/ui/glanceable_info_view.h", + "ambient/ui/media_string_view.cc", + "ambient/ui/media_string_view.h", "ambient/ui/photo_view.cc", "ambient/ui/photo_view.h", "ambient/util/ambient_util.cc", @@ -1763,6 +1765,7 @@ "ambient/autotest_ambient_api_unittest.cc", "ambient/model/ambient_backend_model_unittest.cc", "ambient/ui/ambient_container_view_unittest.cc", + "ambient/ui/media_string_view_unittest.cc", "ambient/ui/photo_view_unittest.cc", "app_list/app_list_controller_impl_unittest.cc", "app_list/app_list_metrics_unittest.cc",
diff --git a/ash/ambient/test/ambient_ash_test_base.cc b/ash/ambient/test/ambient_ash_test_base.cc index f0df732..985855e 100644 --- a/ash/ambient/test/ambient_ash_test_base.cc +++ b/ash/ambient/test/ambient_ash_test_base.cc
@@ -12,6 +12,7 @@ #include "ash/ambient/ambient_photo_controller.h" #include "ash/ambient/ui/ambient_background_image_view.h" #include "ash/ambient/ui/ambient_container_view.h" +#include "ash/ambient/ui/media_string_view.h" #include "ash/ambient/ui/photo_view.h" #include "ash/assistant/ui/assistant_view_ids.h" #include "ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h" @@ -167,6 +168,22 @@ base::RunLoop().RunUntilIdle(); } +void AmbientAshTestBase::SimulateMediaMetadataChanged( + media_session::MediaMetadata metadata) { + GetMediaStringView()->MediaSessionMetadataChanged(metadata); +} + +void AmbientAshTestBase::SimulateMediaPlaybackStateChanged( + media_session::mojom::MediaPlaybackState state) { + // Creates media session info. + media_session::mojom::MediaSessionInfoPtr session_info( + media_session::mojom::MediaSessionInfo::New()); + session_info->playback_state = state; + + // Simulate media session info changed. + GetMediaStringView()->MediaSessionInfoChanged(std::move(session_info)); +} + void AmbientAshTestBase::SetPhotoViewImageSize(int width, int height) { auto* image_decoder = static_cast<TestAmbientImageDecoderImpl*>( ambient_controller() @@ -182,6 +199,11 @@ AssistantViewID::kAmbientBackgroundImageView)); } +MediaStringView* AmbientAshTestBase::GetMediaStringView() { + return static_cast<MediaStringView*>( + container_view()->GetViewByID(AssistantViewID::kAmbientMediaStringView)); +} + void AmbientAshTestBase::FastForwardToInactivity() { task_environment()->FastForwardBy( 2 * AmbientController::kAutoShowWaitTimeInterval);
diff --git a/ash/ambient/test/ambient_ash_test_base.h b/ash/ambient/test/ambient_ash_test_base.h index 0fb03483..d3ac14b 100644 --- a/ash/ambient/test/ambient_ash_test_base.h +++ b/ash/ambient/test/ambient_ash_test_base.h
@@ -15,12 +15,14 @@ #include "ash/test/ash_test_base.h" #include "base/test/scoped_feature_list.h" #include "services/device/public/cpp/test/test_wake_lock_provider.h" +#include "services/media_session/public/mojom/media_session.mojom.h" #include "ui/views/widget/widget.h" namespace ash { class AmbientContainerView; class AmbientPhotoController; +class MediaStringView; // The base class to test the Ambient Mode in Ash. class AmbientAshTestBase : public AshTestBase { @@ -66,6 +68,11 @@ // Simulates a screen brightness changed event. void SetScreenBrightnessAndWait(double percent); + void SimulateMediaMetadataChanged(media_session::MediaMetadata metadata); + + void SimulateMediaPlaybackStateChanged( + media_session::mojom::MediaPlaybackState state); + // Set the size of the next image that will be loaded. void SetPhotoViewImageSize(int width, int height); @@ -86,6 +93,9 @@ AmbientBackgroundImageView* GetAmbientBackgroundImageView(); + // Returns the media string view for displaying ongoing media info. + MediaStringView* GetMediaStringView(); + AmbientController* ambient_controller(); AmbientPhotoController* photo_controller();
diff --git a/ash/ambient/ui/ambient_container_view.cc b/ash/ambient/ui/ambient_container_view.cc index 525a79a..40570dd 100644 --- a/ash/ambient/ui/ambient_container_view.cc +++ b/ash/ambient/ui/ambient_container_view.cc
@@ -10,6 +10,7 @@ #include "ash/ambient/ui/ambient_assistant_container_view.h" #include "ash/ambient/ui/ambient_view_delegate.h" #include "ash/ambient/ui/glanceable_info_view.h" +#include "ash/ambient/ui/media_string_view.h" #include "ash/ambient/ui/photo_view.h" #include "ash/ambient/util/ambient_util.h" #include "ash/assistant/ui/assistant_view_ids.h" @@ -40,6 +41,7 @@ constexpr int kHorizontalMarginDip = 16; constexpr int kVerticalMarginDip = 64; constexpr int kAssistantPreferredHeightDip = 128; +constexpr int kMediaStringTopMarginDip = 25; // A tolerance threshold used to ignore spurious mouse move. constexpr int kMouseMoveErrorTolerancePx = 3; @@ -132,6 +134,7 @@ // Layout child views first to have proper bounds set for children. LayoutPhotoView(); LayoutGlanceableInfoView(); + LayoutMediaStringView(); // The assistant view may not exist if |kAmbientAssistant| feature is // disabled. if (ambient_assistant_container_view_) @@ -155,6 +158,9 @@ glanceable_info_view_ = AddChildView(std::make_unique<GlanceableInfoView>(delegate_)); + media_string_view_ = AddChildView(std::make_unique<MediaStringView>()); + media_string_view_->SetVisible(false); + if (IsAmbientAssistantEnabled()) { ambient_assistant_container_view_ = AddChildView(std::make_unique<AmbientAssistantContainerView>()); @@ -187,6 +193,22 @@ gfx::Rect(0, 0, preferred_width, preferred_height)); } +void AmbientContainerView::LayoutMediaStringView() { + const gfx::Size container_size = GetLocalBounds().size(); + const gfx::Size preferred_size = media_string_view_->GetPreferredSize(); + + // The media string view is positioned on the right-top corner of the + // container. + // TODO(meilinw): without a maximum width limit, media string can grow too + // long or even overflow the screen. Revisit here to polish the UI once the + // spec is available. See b/163398805. + int x = + container_size.width() - kHorizontalMarginDip - preferred_size.width(); + int y = kMediaStringTopMarginDip; + media_string_view_->SetBoundsRect( + gfx::Rect(x, y, preferred_size.width(), preferred_size.height())); +} + void AmbientContainerView::HandleEvent() { delegate_->OnBackgroundPhotoEvents(); }
diff --git a/ash/ambient/ui/ambient_container_view.h b/ash/ambient/ui/ambient_container_view.h index 78f815e..6e5dbce 100644 --- a/ash/ambient/ui/ambient_container_view.h +++ b/ash/ambient/ui/ambient_container_view.h
@@ -17,6 +17,7 @@ class AmbientViewDelegate; class GlanceableInfoView; class PhotoView; +class MediaStringView; // Container view to display all Ambient Mode related views, i.e. photo frame, // weather info. @@ -38,9 +39,12 @@ void Init(); // Layouts its child views. + // TODO(meilinw): Use LayoutManagers to lay out children instead of overriding + // Layout(). See b/163170162. void LayoutPhotoView(); void LayoutGlanceableInfoView(); void LayoutAssistantView(); + void LayoutMediaStringView(); // Invoked on specific types of events. void HandleEvent(); @@ -51,6 +55,7 @@ PhotoView* photo_view_ = nullptr; AmbientAssistantContainerView* ambient_assistant_container_view_ = nullptr; GlanceableInfoView* glanceable_info_view_ = nullptr; + MediaStringView* media_string_view_ = nullptr; // Observes events from its host widget. std::unique_ptr<HostWidgetEventObserver> event_observer_;
diff --git a/ash/ambient/ui/media_string_view.cc b/ash/ambient/ui/media_string_view.cc new file mode 100644 index 0000000..26b79bd --- /dev/null +++ b/ash/ambient/ui/media_string_view.cc
@@ -0,0 +1,118 @@ +// 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 "ash/ambient/ui/media_string_view.h" + +#include <memory> +#include <string> + +#include "ash/ambient/util/ambient_util.h" +#include "ash/assistant/ui/assistant_view_ids.h" +#include "ash/shell.h" +#include "ash/shell_delegate.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "services/media_session/public/mojom/media_session.mojom.h" +#include "services/media_session/public/mojom/media_session_service.mojom.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/box_layout.h" + +namespace ash { + +namespace { + +// Typography. +constexpr SkColor kTextColor = SK_ColorWHITE; +constexpr char kMiddleDotSeparator[] = " \u00B7 "; +constexpr char kPreceedingEighthNoteSymbol[] = "\u266A "; +constexpr int kDefaultFontSizeDip = 64; +constexpr int kMediaStringFontSizeDip = 16; + +} // namespace + +MediaStringView::MediaStringView() { + SetID(AssistantViewID::kAmbientMediaStringView); + InitLayout(); +} + +MediaStringView::~MediaStringView() = default; + +const char* MediaStringView::GetClassName() const { + return "MediaStringView"; +} + +void MediaStringView::MediaSessionInfoChanged( + media_session::mojom::MediaSessionInfoPtr session_info) { + // Don't show the media string if session info is unavailable, or the active + // session is marked as sensitive. + if (!session_info || session_info->is_sensitive) { + SetVisible(false); + return; + } + + bool is_paused = session_info->playback_state == + media_session::mojom::MediaPlaybackState::kPaused; + + // Don't show the media string if paused. + SetVisible(!is_paused); +} + +void MediaStringView::MediaSessionMetadataChanged( + const base::Optional<media_session::MediaMetadata>& metadata) { + media_session::MediaMetadata session_metadata = + metadata.value_or(media_session::MediaMetadata()); + + base::string16 media_string; + if (!session_metadata.title.empty() && !session_metadata.artist.empty()) { + media_string = session_metadata.title + + base::UTF8ToUTF16(kMiddleDotSeparator) + + session_metadata.artist; + } else if (!session_metadata.title.empty()) { + media_string = session_metadata.title; + } else { + media_string = session_metadata.artist; + } + + // Formats the media string with a preceding music eighth note. + SetText(base::UTF8ToUTF16(kPreceedingEighthNoteSymbol) + media_string); +} + +void MediaStringView::InitLayout() { + // This view will be drawn on its own layer instead of the layer of + // |PhotoView| which has a solid black background. + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + + // Defines the appearance. + SetAutoColorReadabilityEnabled(false); + SetEnabledColor(kTextColor); + SetFontList(ambient::util::GetDefaultFontlist().DeriveWithSizeDelta( + kMediaStringFontSizeDip - kDefaultFontSizeDip)); + + BindMediaControllerObserver(); +} + +void MediaStringView::BindMediaControllerObserver() { + media_session::mojom::MediaSessionService* service = + Shell::Get()->shell_delegate()->GetMediaSessionService(); + // Service might be unavailable under some test environments. + if (!service) + return; + + // Binds to the MediaControllerManager and create a MediaController for the + // current active media session so that we can observe it. + mojo::Remote<media_session::mojom::MediaControllerManager> + controller_manager_remote; + service->BindMediaControllerManager( + controller_manager_remote.BindNewPipeAndPassReceiver()); + controller_manager_remote->CreateActiveMediaController( + media_controller_remote_.BindNewPipeAndPassReceiver()); + + // Observe the active media controller for changes. + media_controller_remote_->AddObserver( + observer_receiver_.BindNewPipeAndPassRemote()); +} + +} // namespace ash
diff --git a/ash/ambient/ui/media_string_view.h b/ash/ambient/ui/media_string_view.h new file mode 100644 index 0000000..7e7aa5b --- /dev/null +++ b/ash/ambient/ui/media_string_view.h
@@ -0,0 +1,59 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_AMBIENT_UI_MEDIA_STRING_VIEW_H_ +#define ASH_AMBIENT_UI_MEDIA_STRING_VIEW_H_ + +#include <string> +#include "ash/app_menu/notification_item_view.h" +#include "ash/public/cpp/ambient/ambient_ui_model.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/media_session/public/mojom/media_controller.mojom.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/controls/label.h" + +namespace ash { + +// Container for displaying ongoing media information, including the name of the +// media and the artist, formatted with a proceding music note symbol and a +// middle dot separator. +class MediaStringView : public views::Label, + public media_session::mojom::MediaControllerObserver { + public: + MediaStringView(); + MediaStringView(const MediaStringView&) = delete; + MediaStringView& operator=(const MediaStringView&) = delete; + ~MediaStringView() override; + + // views::Label: + const char* GetClassName() const override; + + // media_session::mojom::MediaControllerObserver: + void MediaSessionInfoChanged( + media_session::mojom::MediaSessionInfoPtr session_info) override; + void MediaSessionMetadataChanged( + const base::Optional<media_session::MediaMetadata>& metadata) override; + void MediaSessionActionsChanged( + const std::vector<media_session::mojom::MediaSessionAction>& actions) + override {} + void MediaSessionChanged( + const base::Optional<base::UnguessableToken>& request_id) override {} + void MediaSessionPositionChanged( + const base::Optional<media_session::MediaPosition>& position) override {} + + private: + void InitLayout(); + + void BindMediaControllerObserver(); + + // Used to receive updates to the active media controller. + mojo::Remote<media_session::mojom::MediaController> media_controller_remote_; + mojo::Receiver<media_session::mojom::MediaControllerObserver> + observer_receiver_{this}; +}; + +} // namespace ash + +#endif // ASH_AMBIENT_UI_MEDIA_STRING_VIEW_H_
diff --git a/ash/ambient/ui/media_string_view_unittest.cc b/ash/ambient/ui/media_string_view_unittest.cc new file mode 100644 index 0000000..e4fa9af --- /dev/null +++ b/ash/ambient/ui/media_string_view_unittest.cc
@@ -0,0 +1,56 @@ +// 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 "ash/ambient/ui/media_string_view.h" + +#include "ash/ambient/test/ambient_ash_test_base.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "services/media_session/public/mojom/media_session.mojom.h" + +namespace ash { + +using MediaStringViewTest = AmbientAshTestBase; + +TEST_F(MediaStringViewTest, ShowMediaTitleAndArtist) { + ShowAmbientScreen(); + + // Sets metadata for current session. + media_session::MediaMetadata metadata; + metadata.title = base::ASCIIToUTF16("title"); + metadata.artist = base::ASCIIToUTF16("artist"); + + SimulateMediaMetadataChanged(metadata); + + const base::string16 expected_text = + base::UTF8ToUTF16("\u266A title \u00B7 artist"); + EXPECT_EQ(GetMediaStringView()->GetText(), expected_text); +} + +TEST_F(MediaStringViewTest, ShowWhenMediaIsPlaying) { + ShowAmbientScreen(); + EXPECT_FALSE(GetMediaStringView()->GetVisible()); + + // Sets media playstate for the current session. + SimulateMediaPlaybackStateChanged( + media_session::mojom::MediaPlaybackState::kPlaying); + EXPECT_TRUE(GetMediaStringView()->GetVisible()); +} + +TEST_F(MediaStringViewTest, DoNotShowWhenMediaIsPaused) { + ShowAmbientScreen(); + EXPECT_FALSE(GetMediaStringView()->GetVisible()); + + // Sets media playstate for the current session. + SimulateMediaPlaybackStateChanged( + media_session::mojom::MediaPlaybackState::kPlaying); + EXPECT_TRUE(GetMediaStringView()->GetVisible()); + + // Simulates the ongoing media paused. + SimulateMediaPlaybackStateChanged( + media_session::mojom::MediaPlaybackState::kPaused); + EXPECT_FALSE(GetMediaStringView()->GetVisible()); +} + +} // namespace ash
diff --git a/ash/assistant/ui/assistant_view_ids.h b/ash/assistant/ui/assistant_view_ids.h index 9f1fab4..a9e9eee 100644 --- a/ash/assistant/ui/assistant_view_ids.h +++ b/ash/assistant/ui/assistant_view_ids.h
@@ -43,6 +43,7 @@ kAmbientBackgroundImageView, kAmbientGlanceableInfoView, kAmbientAssistantDialogPlate, + kAmbientMediaStringView, }; } // namespace ash
diff --git a/ash/quick_answers/quick_answers_controller_impl.cc b/ash/quick_answers/quick_answers_controller_impl.cc index 7b36b46..6239dc2 100644 --- a/ash/quick_answers/quick_answers_controller_impl.cc +++ b/ash/quick_answers/quick_answers_controller_impl.cc
@@ -70,6 +70,8 @@ if (!is_eligible_) return; + is_session_active_ = true; + // Cache anchor-bounds and query. anchor_bounds_ = anchor_bounds; // Initially, title is same as query. Title and query can be overridden based @@ -94,6 +96,7 @@ } void QuickAnswersControllerImpl::DismissQuickAnswers(bool is_active) { + is_session_active_ = false; MaybeDismissQuickAnswersConsent(); bool closed = quick_answers_ui_controller_->CloseQuickAnswersView(); quick_answers_client_->OnQuickAnswersDismissed( @@ -153,6 +156,9 @@ return; } + if (!is_session_active_) + return; + query_ = processed_request.preprocessed_output.query; title_ = processed_request.preprocessed_output.intent_text; @@ -194,7 +200,8 @@ chromeos::quick_answers::ConsentInteractionType::kAccept); // Display Quick-Answer for the cached query when user consents. - MaybeShowQuickAnswers(anchor_bounds_, title_, context_); + if (is_session_active_) + MaybeShowQuickAnswers(anchor_bounds_, title_, context_); } void QuickAnswersControllerImpl::OnConsentSettingsRequestedByUser() {
diff --git a/ash/quick_answers/quick_answers_controller_impl.h b/ash/quick_answers/quick_answers_controller_impl.h index fc2c852..c276392d 100644 --- a/ash/quick_answers/quick_answers_controller_impl.h +++ b/ash/quick_answers/quick_answers_controller_impl.h
@@ -118,6 +118,9 @@ // The last received QuickAnswer from client. std::unique_ptr<chromeos::quick_answers::QuickAnswer> quick_answer_; + + // If currently there is an active quick answers session. + bool is_session_active_ = false; }; } // namespace ash
diff --git a/ash/shelf/contextual_nudge_status_tracker.cc b/ash/shelf/contextual_nudge_status_tracker.cc index 8728ea2..a12193d2 100644 --- a/ash/shelf/contextual_nudge_status_tracker.cc +++ b/ash/shelf/contextual_nudge_status_tracker.cc
@@ -53,7 +53,7 @@ base::TimeTicks shown_time) { nudge_shown_time_ = shown_time; gesture_time_recorded_ = false; - dismissal_reason_recorded_ = false; + can_record_dismiss_metrics_ = true; } void ContextualNudgeStatusTracker::HandleGesturePerformed( @@ -61,7 +61,7 @@ if (gesture_time_recorded_) return; - if (!dismissal_reason_recorded_) { + if (can_record_dismiss_metrics_) { MaybeLogNudgeDismissedMetrics( contextual_tooltip::DismissNudgeReason::kPerformedGesture); } @@ -76,10 +76,10 @@ void ContextualNudgeStatusTracker::MaybeLogNudgeDismissedMetrics( contextual_tooltip::DismissNudgeReason reason) { - if (dismissal_reason_recorded_) + if (!can_record_dismiss_metrics_) return; base::UmaHistogramEnumeration(GetEnumHistogramName(type_), reason); - dismissal_reason_recorded_ = true; + can_record_dismiss_metrics_ = false; } } // namespace ash
diff --git a/ash/shelf/contextual_nudge_status_tracker.h b/ash/shelf/contextual_nudge_status_tracker.h index 656da023d..fbe279a 100644 --- a/ash/shelf/contextual_nudge_status_tracker.h +++ b/ash/shelf/contextual_nudge_status_tracker.h
@@ -36,10 +36,8 @@ bool gesture_time_recorded() const { return gesture_time_recorded_; } - bool dismissal_reason_recorded() const { return dismissal_reason_recorded_; } - bool can_record_dismiss_metrics() const { - return !gesture_time_recorded_ && !dismissal_reason_recorded_; + return can_record_dismiss_metrics_; } private: @@ -49,13 +47,16 @@ // The tooltip type tracked by this object. const ash::contextual_tooltip::TooltipType type_; - // Tracks whether the tooltip dismiss time has been recorded. - // Set when the tooltip is shown. Resets after gesture is performed. + // Tracks whether the tooltip dismiss time has been recorded because of the + // gesture is performed. Sets after gesture is performed. Resets when the + // tooltip is shown. bool gesture_time_recorded_ = false; - // Tracks whether the tooltip dismiss time has been recorded. - // Set when the tooltip is shown. Resets after tooltip is hidden. - bool dismissal_reason_recorded_ = false; + // Tracks whether the nudge dismiss metrics can be recorded. Only after the + // tooltip is shown, the tooltip can be dismissed and the dismiss reason + // metrics can be logged. Otherwise, calling MaybeLogNudgeDismissedMetrics() + // is a no-op. + bool can_record_dismiss_metrics_ = false; }; } // namespace ash
diff --git a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc index 3862ce6..f7e92de 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc +++ b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.cc
@@ -5,6 +5,8 @@ #include "ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.h" #include "ash/public/cpp/shell_window_ids.h" +#include "ash/session/session_controller_impl.h" +#include "ash/shelf/contextual_tooltip.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "base/callback.h" @@ -124,7 +126,7 @@ : public views::View, public ui::ImplicitAnimationObserver { public: - explicit ContextualNudgeView(base::OnceClosure callback) + explicit ContextualNudgeView(base::OnceCallback<void(bool)> callback) : callback_(std::move(callback)) { SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); @@ -151,7 +153,7 @@ animation_stage_ = AnimationStage::kWaitingCancelled; DCHECK(show_timer_.IsRunning()); show_timer_.AbandonAndStop(); - std::move(callback_).Run(); + std::move(callback_).Run(/*animation_completed=*/false); } else if (animation_stage_ == AnimationStage::kSlidingIn || animation_stage_ == AnimationStage::kBouncing || animation_stage_ == AnimationStage::kSlidingOut) { @@ -164,6 +166,8 @@ } } + void SetNudgeShownForTesting() { SetNudgeCountsAsShown(); } + bool count_as_shown() const { return count_as_shown_; } private: @@ -330,6 +334,14 @@ layer()->SetTransform(transform); } + void SetNudgeCountsAsShown() { + count_as_shown_ = true; + // Log nudge metrics right after it's shown. + contextual_tooltip::HandleNudgeShown( + Shell::Get()->session_controller()->GetActivePrefService(), + contextual_tooltip::TooltipType::kBackGesture); + } + // views::View: void Layout() override { suggestion_view_->SetBoundsRect(GetLocalBounds()); } @@ -339,13 +351,16 @@ (animation_stage_ == AnimationStage::kSlidingOut && !WasAnimationAbortedForProperty( ui::LayerAnimationElement::TRANSFORM))) { - std::move(callback_).Run(); + std::move(callback_).Run(/*animation_completed=*/animation_stage_ == + AnimationStage::kSlidingOut); return; } if (animation_stage_ == AnimationStage::kSlidingIn && !WasAnimationAbortedForProperty(ui::LayerAnimationElement::TRANSFORM)) { - count_as_shown_ = true; + // Only after the back nudge finishes sliding in animation, it counts as + // a successful shown. + SetNudgeCountsAsShown(); animation_stage_ = AnimationStage::kBouncing; suggestion_view_->ScheduleBounceAnimation(); } @@ -366,12 +381,12 @@ bool count_as_shown_ = false; // Callback function to be called after animation is cancelled or completed. - // Count the nudge as shown successfully if |success| is true. - base::OnceClosure callback_; + // Count the nudge as shown successfully if |count_as_shown_| is true. + base::OnceCallback<void(bool)> callback_; }; BackGestureContextualNudge::BackGestureContextualNudge( - base::OnceClosure callback) { + base::OnceCallback<void(bool)> callback) { widget_ = CreateWidget(); nudge_view_ = new ContextualNudgeView(std::move(callback)); widget_->SetContentsView(nudge_view_); @@ -388,4 +403,8 @@ return nudge_view_->count_as_shown(); } +void BackGestureContextualNudge::SetNudgeShownForTesting() { + nudge_view_->SetNudgeShownForTesting(); +} + } // namespace ash
diff --git a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.h b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.h index 29d79259..45eff82 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.h +++ b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.h
@@ -8,7 +8,7 @@ #include <memory> #include "ash/ash_export.h" -#include "base/callback_forward.h" +#include "base/callback.h" #include "ui/views/widget/widget.h" namespace ash { @@ -19,7 +19,7 @@ public: // Constructor to create a BackGestureContextualNudge with |callback| to be // called after the animation is completed or cancelled. - explicit BackGestureContextualNudge(base::OnceClosure callback); + explicit BackGestureContextualNudge(base::OnceCallback<void(bool)> callback); BackGestureContextualNudge(const BackGestureContextualNudge&) = delete; BackGestureContextualNudge& operator=(const BackGestureContextualNudge&) = delete; @@ -35,6 +35,11 @@ // not. bool ShouldNudgeCountAsShown() const; + // Set nudge as shown for testing. Only after nudge is counted as shown, + // the nudge dismiss metrics can be correctly logged. This is to simulate + // something happens in the middle of a nudge animation. + void SetNudgeShownForTesting(); + views::Widget* widget() { return widget_.get(); } private:
diff --git a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.cc b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.cc index c43f3a37..1759a3e 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.cc +++ b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.cc
@@ -123,6 +123,9 @@ shelf_control_visible_ = updated_shelf_control_visibility; + if (!nudge_ || !shelf_control_visible_) + return; + // Metrics for hiding nudge when exiting tablet mode is handled by // OnTabletModeEnded. if (tablet_mode && shelf_control_visible_) { @@ -130,9 +133,6 @@ contextual_tooltip::TooltipType::kBackGesture, contextual_tooltip::DismissNudgeReason::kOther); } - - if (!nudge_ || !shelf_control_visible_) - return; nudge_->CancelAnimationOrFadeOutToHide(); } @@ -218,19 +218,23 @@ } } -void BackGestureContextualNudgeControllerImpl::OnNudgeAnimationFinished() { - // TODO(crbug/1101105) Reimplement kTimeout metric for back gesture nudge. +void BackGestureContextualNudgeControllerImpl::OnNudgeAnimationFinished( + bool animation_completed) { const bool count_as_shown = nudge_->ShouldNudgeCountAsShown(); // UpdateWindowMonitoring() might attempt to cancel any in-progress nudge, // which would switch the nudge into an invalid state. Reset the nudge before // window monitoring is updated. nudge_.reset(); + if (animation_completed) { + DCHECK(count_as_shown); + contextual_tooltip::MaybeLogNudgeDismissedMetrics( + contextual_tooltip::TooltipType::kBackGesture, + contextual_tooltip::DismissNudgeReason::kTimeout); + } contextual_tooltip::SetBackGestureNudgeShowing(false); if (count_as_shown) { - contextual_tooltip::HandleNudgeShown( - GetActivePrefService(), contextual_tooltip::TooltipType::kBackGesture); UpdateWindowMonitoring(/*can_show_nudge_immediately=*/false); // Set a timer to monitoring windows and show nudge ui again.
diff --git a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.h b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.h index 7c6ffba..803d5a0 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.h +++ b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl.h
@@ -96,8 +96,10 @@ void UpdateWindowMonitoring(bool can_show_nudge_immediately); // Callback function to be called after nudge animation is cancelled or - // completed. - void OnNudgeAnimationFinished(); + // completed. |animation_completed| is true when the nudge animation has + // completed (i.e., finishes the entire animation sequence, which includes + // sliding in, bouncing and sliding out animation.) + void OnNudgeAnimationFinished(bool animation_completed); // Do necessary cleanup when |this| is destroyed or system is shutdown. void DoCleanUp();
diff --git a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl_unittest.cc b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl_unittest.cc index 4dbca59..6a03132 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl_unittest.cc +++ b/ash/wm/gestures/back_gesture/back_gesture_contextual_nudge_controller_impl_unittest.cc
@@ -12,6 +12,7 @@ #include "ash/test/ash_test_base.h" #include "ash/test_shell_delegate.h" #include "ash/wm/gestures/back_gesture/back_gesture_contextual_nudge.h" +#include "ash/wm/gestures/back_gesture/back_gesture_event_handler.h" #include "ash/wm/gestures/back_gesture/test_back_gesture_contextual_nudge_delegate.h" #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" #include "base/test/metrics/histogram_tester.h" @@ -51,8 +52,6 @@ scoped_feature_list_.InitWithFeatures( {features::kContextualNudges, features::kHideShelfControlsInTabletMode}, {}); - nudge_controller_ = - std::make_unique<BackGestureContextualNudgeControllerImpl>(); GetSessionControllerClient()->AddUserSession(kUser1Email); GetSessionControllerClient()->AddUserSession(kUser2Email); @@ -78,7 +77,6 @@ } void TearDown() override { - nudge_controller_.reset(); contextual_tooltip::ClearClockOverrideForTesting(); NoSessionAshTestBase::TearDown(); } @@ -98,6 +96,14 @@ } } + // Set nudge as shown for testing. Only after nudge is counted as shown, + // the nudge dismiss metrics can be correctly logged. This is to simulate + // something happens in the middle of nudge animation to dismiss the nudge. + void SetNudgeShownForTesting() { + if (nudge()) + nudge()->SetNudgeShownForTesting(); + } + PrefService* user1_pref_service() { return Shell::Get()->session_controller()->GetUserPrefServiceForUser( AccountId::FromUserEmail(kUser1Email)); @@ -109,7 +115,9 @@ } BackGestureContextualNudgeControllerImpl* nudge_controller() { - return nudge_controller_.get(); + return Shell::Get() + ->back_gesture_event_handler() + ->nudge_controller_for_testing(); } BackGestureContextualNudge* nudge() { return nudge_controller()->nudge(); } @@ -127,8 +135,6 @@ bool can_go_back_; base::SimpleTestClock test_clock_; base::test::ScopedFeatureList scoped_feature_list_; - - std::unique_ptr<BackGestureContextualNudgeControllerImpl> nudge_controller_; }; class BackGestureContextualNudgeControllerTestCantGoBack @@ -320,10 +326,10 @@ ui::ScopedAnimationDurationScaleMode non_zero( ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); - // Verify the nudge is shown and wait until nudge animation is finished. + // Verify the nudge is created and wait until nudge animation is shown. std::unique_ptr<aura::Window> window = CreateTestWindow(); EXPECT_TRUE(nudge()); - WaitNudgeAnimationDone(); + SetNudgeShownForTesting(); EXPECT_FALSE(contextual_tooltip::ShouldShowNudge( user1_pref_service(), contextual_tooltip::TooltipType::kBackGesture, @@ -354,10 +360,12 @@ // Back gesture metrics should be recorded after performing gesture. TEST_F(BackGestureContextualNudgeControllerTest, GesturePerformedMetricTest) { base::HistogramTester histogram_tester; - // Verify the nudge is shown and wait until nudge animation is finished. + ui::ScopedAnimationDurationScaleMode non_zero( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + // Verify the nudge is created and wait until nudge animation is shown. std::unique_ptr<aura::Window> window = CreateTestWindow(); EXPECT_TRUE(nudge()); - WaitNudgeAnimationDone(); + SetNudgeShownForTesting(); GenerateBackSequence(); @@ -369,6 +377,55 @@ base::TimeDelta::FromSeconds(0), 1); } +TEST_P(BackGestureContextualNudgeControllerTestA11yPrefs, TimeoutMetricsTest) { + base::HistogramTester histogram_tester; + ui::ScopedAnimationDurationScaleMode non_zero( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + std::unique_ptr<aura::Window> window = CreateTestWindow(); + EXPECT_TRUE(nudge()); + WaitNudgeAnimationDone(); + EXPECT_FALSE(nudge()); + + histogram_tester.ExpectBucketCount( + "Ash.ContextualNudgeDismissContext.BackGesture", + contextual_tooltip::DismissNudgeReason::kTimeout, 1); +} + +TEST_P(BackGestureContextualNudgeControllerTestA11yPrefs, + LogDismissMetricsAfterNudgeShown) { + base::HistogramTester histogram_tester; + ui::ScopedAnimationDurationScaleMode non_zero( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + std::unique_ptr<aura::Window> window = CreateTestWindow(); + EXPECT_TRUE(nudge()); + // Before nudge is still waiting to be shown, exit tablet mode. The nudge will + // be dismissed immediately. + TabletModeControllerTestApi tablet_mode_api; + tablet_mode_api.LeaveTabletMode(); + EXPECT_FALSE(nudge()); + + // Because the nudge hasn't shown yet, the dismissal metrics should not be + // logged. + histogram_tester.ExpectBucketCount( + "Ash.ContextualNudgeDismissContext.BackGesture", + contextual_tooltip::DismissNudgeReason::kSwitchToClamshell, 0); + + tablet_mode_api.EnterTabletMode(); + std::unique_ptr<aura::Window> window2 = CreateTestWindow(); + EXPECT_TRUE(nudge()); + SetNudgeShownForTesting(); + + // Exit tablet mode in the middle of the animation, test the dismissmal + // metrics should be correctly logged. + tablet_mode_api.LeaveTabletMode(); + WaitNudgeAnimationDone(); + histogram_tester.ExpectBucketCount( + "Ash.ContextualNudgeDismissContext.BackGesture", + contextual_tooltip::DismissNudgeReason::kSwitchToClamshell, 1); + histogram_tester.ExpectTotalCount( + "Ash.ContextualNudgeDismissContext.BackGesture", 1); +} + // Back Gesture Nudge should be hidden when shelf controls are enabled. TEST_P(BackGestureContextualNudgeControllerTestA11yPrefs, HideNudgesForShelfControls) { @@ -376,8 +433,7 @@ SCOPED_TRACE(testing::Message() << "Pref=" << GetParam()); std::unique_ptr<aura::Window> window = CreateTestWindow(); EXPECT_TRUE(nudge()); - - WaitNudgeAnimationDone(); + SetNudgeShownForTesting(); // Turn on accessibility settings to enable shelf controls. Shell::Get()
diff --git a/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc b/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc index e1c642c..a6e1936 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc +++ b/ash/wm/gestures/back_gesture/back_gesture_event_handler.cc
@@ -314,6 +314,9 @@ if (features::AreContextualNudgesEnabled()) { // Cancel the in-waiting or in-progress back nudge animation. nudge_controller_->OnBackGestureStarted(); + contextual_tooltip::HandleGesturePerformed( + Shell::Get()->session_controller()->GetActivePrefService(), + contextual_tooltip::TooltipType::kBackGesture); } return true; case ui::ET_GESTURE_SCROLL_BEGIN: @@ -393,11 +396,6 @@ } } back_gesture_affordance_->Complete(); - if (features::AreContextualNudgesEnabled()) { - contextual_tooltip::HandleGesturePerformed( - Shell::Get()->session_controller()->GetActivePrefService(), - contextual_tooltip::TooltipType::kBackGesture); - } } else { back_gesture_affordance_->Abort(); RecordEndScenarioType(GetEndScenarioType(
diff --git a/ash/wm/gestures/back_gesture/back_gesture_event_handler.h b/ash/wm/gestures/back_gesture/back_gesture_event_handler.h index b0777a5..c8b03330 100644 --- a/ash/wm/gestures/back_gesture/back_gesture_event_handler.h +++ b/ash/wm/gestures/back_gesture/back_gesture_event_handler.h
@@ -46,6 +46,10 @@ void OnGestureEvent(GestureConsumer* consumer, ui::GestureEvent* event) override; + BackGestureContextualNudgeControllerImpl* nudge_controller_for_testing() { + return nudge_controller_.get(); + } + private: // Returns true if |event| was handled as a go-back gesture. |event| is // generated by |gesture_provider_| from touch event, |screen_location| is
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h index 31f563dd..58f3fa1d 100644 --- a/base/trace_event/builtin_categories.h +++ b/base/trace_event/builtin_categories.h
@@ -82,6 +82,7 @@ X("fonts") \ X("GAMEPAD") \ X("gpu") \ + X("gpu.angle") \ X("gpu.capture") \ X("gpu.memory") \ X("headless") \
diff --git a/build/toolchain/concurrent_links.gni b/build/toolchain/concurrent_links.gni index c4637454..1f427ee6 100644 --- a/build/toolchain/concurrent_links.gni +++ b/build/toolchain/concurrent_links.gni
@@ -45,30 +45,21 @@ } else { _args = [ "--mem_per_link_gb=4" ] } - } else if (is_android) { + } else if (is_android && !is_component_build && symbol_level == 2) { + # Full debug symbols require large memory for link. + _args = [ "--mem_per_link_gb=25" ] + } else if (is_android && !is_debug && !using_sanitizer && is_java_debug && + disable_android_lint && symbol_level < 2) { # The link pool is also shared with: - # * R8 - # * 10gb per run for 72-core machine MonochromePublic.apk, Aug 2020. - # * 4.5gb per run for 8-core machine MonochromePublic.apk, Aug 2020. + # * ProGuard / R8 # * Android Lint - # * 2gb per run for MonochromePublic.apk, Aug 2020. - if (!is_component_build && symbol_level == 2) { - # Full debug symbols require large memory for link. - _args = [ "--mem_per_link_gb=25" ] - } else if (!is_java_debug) { - # R8 requires more ram than linker. - # TODO(crbug.com/1098333): Do not decrease on bots with low CPU counts. - _args = [ "--mem_per_link_gb=10" ] - } else if (!is_debug && !using_sanitizer && symbol_level < 2) { - # Increase the number of concurrent links for release bots that have - # ProGuard and sanitizers disabled (which use a lot of RAM). - if (symbol_level == 1) { - _args = [ "--mem_per_link_gb=6" ] - } else { - _args = [ "--mem_per_link_gb=4" ] - } + # Increase the number of concurrent links for release bots that have + # ProGuard and Lint disabled, and that do not enable sanitizers (which use a + # lot of RAM). + if (symbol_level == 1) { + _args = [ "--mem_per_link_gb=6" ] } else { - _args = [] + _args = [ "--mem_per_link_gb=4" ] } } else if (is_linux && !is_chromeos && symbol_level == 0) { # Memory consumption on link without debug symbols is low on linux.
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 8359a47d..acad3418 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1234,11 +1234,9 @@ "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordEntryViewer.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordManagerHandler.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordManagerHandlerProvider.java", - "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragment.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordUIView.java", "java/src/org/chromium/chrome/browser/password_manager/settings/ProgressBarDialogFragment.java", - "java/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManager.java", "java/src/org/chromium/chrome/browser/password_manager/settings/SavedPasswordEntry.java", "java/src/org/chromium/chrome/browser/password_manager/settings/SingleThreadBarrierClosure.java", "java/src/org/chromium/chrome/browser/password_manager/settings/TimedCallbackDelayer.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 68df3bac..e5258754 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -189,8 +189,6 @@ "junit/src/org/chromium/chrome/browser/password_manager/settings/DialogManagerTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/EnsureAsyncPostingRule.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragmentTest.java", - "junit/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragmentTest.java", - "junit/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManagerTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/SingleThreadBarrierClosureTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/TimedCallbackDelayerTest.java", "junit/src/org/chromium/chrome/browser/payments/AutofillContactTest.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksView.java index 86b3dd1..e8d2111 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/TasksView.java
@@ -26,8 +26,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.browser.feed.shared.FeedFeatures; -import org.chromium.chrome.browser.flags.CachedFeatureFlags; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.ntp.IncognitoDescriptionView; import org.chromium.chrome.browser.ntp.search.SearchBoxCoordinator; @@ -110,13 +108,11 @@ private void setTabCarouselTitleStyle() { // Match the tab carousel title style with the feed header. - // TODO(crbug.com/1016952): Migrate feature flag checks to use cached flags for instant - // start. There are many places checking FeedFeatures.isReportingUserActions, like in + // There are many places checking FeedFeatures.isReportingUserActions, like in // ExploreSurfaceCoordinator. TextView titleDescription = (TextView) findViewById(R.id.tab_switcher_title_description); TextView moreTabs = (TextView) findViewById(R.id.more_tabs); - if (!CachedFeatureFlags.isEnabled(ChromeFeatureList.INSTANT_START) - && FeedFeatures.isReportingUserActions()) { + if (FeedFeatures.cachedIsReportingUserActions()) { ApiCompatibilityUtils.setTextAppearance( titleDescription, R.style.TextAppearance_TextSmall_Secondary); ApiCompatibilityUtils.setTextAppearance(
diff --git a/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml b/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml index a30cc10..33f8628 100644 --- a/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml +++ b/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml
@@ -47,6 +47,7 @@ app:leading="@dimen/text_size_medium_leading" /> <View + android:id="@+id/account_picker_horizontal_divider" style="@style/HorizontalDivider" /> <androidx.recyclerview.widget.RecyclerView @@ -81,4 +82,13 @@ android:ellipsize="end" android:singleLine="true" android:text="@string/signin_promo_continue_as" /> + + <ProgressBar + android:id="@+id/account_picker_signin_spinner_view" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="center" + android:layout_marginTop="32dp" + android:layout_marginBottom="132dp" + android:visibility="gone" /> </LinearLayout> \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java index da8ab6e..6b0515c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/QualityEnforcer.java
@@ -58,9 +58,12 @@ private final CustomTabsConnection mConnection; private final CustomTabsSessionToken mSessionToken; private final ClientPackageNameProvider mClientPackageNameProvider; + private final TrustedWebActivityUmaRecorder mUmaRecorder; private boolean mOriginVerified; + // Do not modify or reuse existing entries, they are used in a UMA histogram. Please also edit + // TrustedWebActivityQualityEnforcementViolationType in enums.xml if new value added. @IntDef({ViolationType.ERROR_404, ViolationType.ERROR_5XX, ViolationType.UNAVAILABLE_OFFLINE, ViolationType.DIGITAL_ASSERTLINKS}) @Retention(RetentionPolicy.SOURCE) @@ -103,18 +106,21 @@ @Inject public QualityEnforcer(ChromeActivity<?> activity, TabObserverRegistrar tabObserverRegistrar, BrowserServicesIntentDataProvider intentDataProvider, CustomTabsConnection connection, - Verifier verifier, ClientPackageNameProvider clientPackageNameProvider) { + Verifier verifier, ClientPackageNameProvider clientPackageNameProvider, + TrustedWebActivityUmaRecorder umaRecorder) { mActivity = activity; mVerifier = verifier; mConnection = connection; mSessionToken = intentDataProvider.getSession(); mClientPackageNameProvider = clientPackageNameProvider; + mUmaRecorder = umaRecorder; // Initialize the value to true before the first navigation. mOriginVerified = true; tabObserverRegistrar.registerActivityTabObserver(mTabObserver); } private void trigger(@ViolationType int type, String url, int httpStatusCode) { + mUmaRecorder.recordQualityEnforcementViolation(type); showErrorToast(getToastMessage(type, url, httpStatusCode)); // Notify the client app.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java index 3550ce0..1e1bb01 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityUmaRecorder.java
@@ -212,4 +212,9 @@ RecordHistogram.recordEnumeratedHistogram("TrustedWebActivity.LocationUpdateErrorCode", error, LocationUpdateError.MAX_VALUE + 1); } + + public void recordQualityEnforcementViolation(@QualityEnforcer.ViolationType int type) { + RecordHistogram.recordEnumeratedHistogram("TrustedWebActivity.QualityEnforcementViolation", + type, QualityEnforcer.ViolationType.NUM_ENTRIES); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/content_capture/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/OWNERS index 2d0a24b..b48766c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/content_capture/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/content_capture/OWNERS
@@ -1,4 +1,4 @@ tedchoc@chromium.org -wylieb@chomium.org +wylieb@chromium.org file://components/content_capture/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java index 2a483667..cca17ec 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java
@@ -7,12 +7,14 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.metrics.PageLoadMetrics; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.paint_preview.services.PaintPreviewTabServiceFactory; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; +import org.chromium.content_public.browser.WebContents; /** * Handles initialization of the Paint Preview tab observers. @@ -69,6 +71,25 @@ } sHasAttemptedToShowOnRestore = true; - return TabbedPaintPreviewPlayer.get(tab).maybeShow(onShown, onDismissed); + + TabbedPaintPreviewPlayer player = TabbedPaintPreviewPlayer.get(tab); + PageLoadMetrics.Observer observer = new PageLoadMetrics.Observer() { + @Override + public void onFirstMeaningfulPaint(WebContents webContents, long navigationId, + long navigationStartTick, long firstMeaningfulPaintMs) { + player.onFirstMeaningfulPaint(webContents); + } + }; + + if (!player.maybeShow(onShown, () -> { + onDismissed.run(); + PageLoadMetrics.removeObserver(observer); + })) { + return false; + } + + PageLoadMetrics.addObserver(observer); + + return true; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index 6e4b639..958a326 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -84,11 +84,9 @@ import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsStatics; -import org.chromium.payments.mojom.AddressErrors; import org.chromium.payments.mojom.CanMakePaymentQueryResult; import org.chromium.payments.mojom.HasEnrolledInstrumentQueryResult; import org.chromium.payments.mojom.PayerDetail; -import org.chromium.payments.mojom.PayerErrors; import org.chromium.payments.mojom.PaymentAddress; import org.chromium.payments.mojom.PaymentComplete; import org.chromium.payments.mojom.PaymentDetails; @@ -1580,69 +1578,7 @@ mWasRetryCalled = true; - // Remove all payment apps except the selected one. - assert mPaymentUIsManager.getPaymentMethodsSection() != null; - PaymentApp selectedApp = - (PaymentApp) mPaymentUIsManager.getPaymentMethodsSection().getSelectedItem(); - assert selectedApp != null; - mPaymentUIsManager.setPaymentMethodsSection( - new SectionInformation(PaymentRequestUI.DataType.PAYMENT_METHODS, - /* selection = */ 0, new ArrayList<>(Arrays.asList(selectedApp)))); - mPaymentUIsManager.getPaymentRequestUI().updateSection( - PaymentRequestUI.DataType.PAYMENT_METHODS, - mPaymentUIsManager.getPaymentMethodsSection()); - mPaymentUIsManager.getPaymentRequestUI().disableAddingNewCardsDuringRetry(); - - // Go back to the payment sheet - mPaymentUIsManager.getPaymentRequestUI().onPayButtonProcessingCancelled(); - PaymentDetailsUpdateServiceHelper.getInstance().reset(); - if (!TextUtils.isEmpty(errors.error)) { - mPaymentUIsManager.getPaymentRequestUI().setRetryErrorMessage(errors.error); - } else { - ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents); - mPaymentUIsManager.getPaymentRequestUI().setRetryErrorMessage( - activity.getResources().getString(R.string.payments_error_message)); - } - - if (shouldShowShippingSection() && hasShippingAddressError(errors.shippingAddress)) { - mPaymentUIsManager.getRetryQueue().add(() -> { - mPaymentUIsManager.getAddressEditor().setAddressErrors(errors.shippingAddress); - AutofillAddress selectedAddress = - (AutofillAddress) mPaymentUIsManager.getShippingAddressesSection() - .getSelectedItem(); - // Log the edit of a shipping address. - mJourneyLogger.incrementSelectionEdits(Section.SHIPPING_ADDRESS); - mPaymentUIsManager.editAddress(selectedAddress); - }); - } - - if (shouldShowContactSection() && hasPayerError(errors.payer)) { - mPaymentUIsManager.getRetryQueue().add(() -> { - mPaymentUIsManager.getContactEditor().setPayerErrors(errors.payer); - AutofillContact selectedContact = - (AutofillContact) mPaymentUIsManager.getContactSection().getSelectedItem(); - mJourneyLogger.incrementSelectionEdits(Section.CONTACT_INFO); - mPaymentUIsManager.editContactOnPaymentRequestUI(selectedContact); - }); - } - - if (!mPaymentUIsManager.getRetryQueue().isEmpty()) { - mHandler.post(mPaymentUIsManager.getRetryQueue().remove()); - } - } - - private boolean hasShippingAddressError(AddressErrors errors) { - return !TextUtils.isEmpty(errors.addressLine) || !TextUtils.isEmpty(errors.city) - || !TextUtils.isEmpty(errors.country) - || !TextUtils.isEmpty(errors.dependentLocality) - || !TextUtils.isEmpty(errors.organization) || !TextUtils.isEmpty(errors.phone) - || !TextUtils.isEmpty(errors.postalCode) || !TextUtils.isEmpty(errors.recipient) - || !TextUtils.isEmpty(errors.region) || !TextUtils.isEmpty(errors.sortingCode); - } - - private boolean hasPayerError(PayerErrors errors) { - return !TextUtils.isEmpty(errors.name) || !TextUtils.isEmpty(errors.phone) - || !TextUtils.isEmpty(errors.email); + mComponentPaymentRequestImpl.getPaymentRequestLifecycleObserver().onRetry(errors); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java index 12867c4..4eb99391 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUIsManager.java
@@ -13,6 +13,7 @@ import org.chromium.base.Callback; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; @@ -37,19 +38,23 @@ import org.chromium.components.payments.JourneyLogger; import org.chromium.components.payments.PaymentApp; import org.chromium.components.payments.PaymentAppType; +import org.chromium.components.payments.PaymentDetailsUpdateServiceHelper; import org.chromium.components.payments.PaymentFeatureList; import org.chromium.components.payments.PaymentOptionsUtils; import org.chromium.components.payments.PaymentRequestLifecycleObserver; import org.chromium.components.payments.PaymentRequestParams; import org.chromium.components.payments.Section; import org.chromium.content_public.browser.WebContents; +import org.chromium.payments.mojom.AddressErrors; import org.chromium.payments.mojom.PayerDetail; +import org.chromium.payments.mojom.PayerErrors; import org.chromium.payments.mojom.PaymentCurrencyAmount; import org.chromium.payments.mojom.PaymentDetails; import org.chromium.payments.mojom.PaymentDetailsModifier; import org.chromium.payments.mojom.PaymentItem; import org.chromium.payments.mojom.PaymentOptions; import org.chromium.payments.mojom.PaymentShippingOption; +import org.chromium.payments.mojom.PaymentValidationErrors; import org.chromium.url.GURL; import java.util.ArrayList; @@ -88,6 +93,7 @@ private Callback<PaymentInformation> mPaymentInformationCallback; private SectionInformation mUiShippingOptions; private final Delegate mDelegate; + private final WebContents mWebContents; private final Map<String, CurrencyFormatter> mCurrencyFormatterMap; private final AddressEditor mAddressEditor; private final CardEditor mCardEditor; @@ -191,6 +197,7 @@ // billing address labels. mCardEditor = new CardEditor(webContents, mAddressEditor, /*includeOrgLabel=*/false); mJourneyLogger = journeyLogger; + mWebContents = webContents; mPaymentUisShowStateReconciler = new PaymentUisShowStateReconciler(); mCurrencyFormatterMap = new HashMap<>(); @@ -460,6 +467,68 @@ } } + // Implement PaymentRequestLifecycleObserver: + @Override + public void onRetry(PaymentValidationErrors errors) { + // Remove all payment apps except the selected one. + assert mPaymentMethodsSection != null; + PaymentApp selectedApp = (PaymentApp) mPaymentMethodsSection.getSelectedItem(); + assert selectedApp != null; + mPaymentMethodsSection = new SectionInformation(PaymentRequestUI.DataType.PAYMENT_METHODS, + /* selection = */ 0, new ArrayList<>(Arrays.asList(selectedApp))); + mPaymentRequestUI.updateSection( + PaymentRequestUI.DataType.PAYMENT_METHODS, mPaymentMethodsSection); + mPaymentRequestUI.disableAddingNewCardsDuringRetry(); + + // Go back to the payment sheet + mPaymentRequestUI.onPayButtonProcessingCancelled(); + PaymentDetailsUpdateServiceHelper.getInstance().reset(); + if (!TextUtils.isEmpty(errors.error)) { + mPaymentRequestUI.setRetryErrorMessage(errors.error); + } else { + ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents); + mPaymentRequestUI.setRetryErrorMessage( + activity.getResources().getString(R.string.payments_error_message)); + } + + if (shouldShowShippingSection() && hasShippingAddressError(errors.shippingAddress)) { + mRetryQueue.add(() -> { + mAddressEditor.setAddressErrors(errors.shippingAddress); + AutofillAddress selectedAddress = + (AutofillAddress) mShippingAddressesSection.getSelectedItem(); + // Log the edit of a shipping address. + mJourneyLogger.incrementSelectionEdits(Section.SHIPPING_ADDRESS); + editAddress(selectedAddress); + }); + } + + if (shouldShowContactSection() && hasPayerError(errors.payer)) { + mRetryQueue.add(() -> { + mContactEditor.setPayerErrors(errors.payer); + AutofillContact selectedContact = + (AutofillContact) mContactSection.getSelectedItem(); + mJourneyLogger.incrementSelectionEdits(Section.CONTACT_INFO); + editContactOnPaymentRequestUI(selectedContact); + }); + } + + if (!mRetryQueue.isEmpty()) mHandler.post(mRetryQueue.remove()); + } + + private boolean hasShippingAddressError(AddressErrors errors) { + return !TextUtils.isEmpty(errors.addressLine) || !TextUtils.isEmpty(errors.city) + || !TextUtils.isEmpty(errors.country) + || !TextUtils.isEmpty(errors.dependentLocality) + || !TextUtils.isEmpty(errors.organization) || !TextUtils.isEmpty(errors.phone) + || !TextUtils.isEmpty(errors.postalCode) || !TextUtils.isEmpty(errors.recipient) + || !TextUtils.isEmpty(errors.region) || !TextUtils.isEmpty(errors.sortingCode); + } + + private boolean hasPayerError(PayerErrors errors) { + return !TextUtils.isEmpty(errors.name) || !TextUtils.isEmpty(errors.phone) + || !TextUtils.isEmpty(errors.email); + } + /** @return The selected payment app type. */ public @PaymentAppType int getSelectedPaymentAppType() { return mPaymentMethodsSection != null && mPaymentMethodsSection.getSelectedItem() != null
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java index e22630d..0c172e7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java
@@ -119,8 +119,11 @@ mAccountPickerTitle.setText(R.string.signin_account_picker_bottom_sheet_signin_title); mContentView.findViewById(R.id.account_picker_bottom_sheet_subtitle) .setVisibility(View.GONE); + mContentView.findViewById(R.id.account_picker_horizontal_divider).setVisibility(View.GONE); mSelectedAccountView.setVisibility(View.GONE); mContinueAsButton.setVisibility(View.GONE); + mContentView.findViewById(R.id.account_picker_signin_spinner_view) + .setVisibility(View.VISIBLE); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java index 5a8c44c..9af5fab 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -568,7 +568,6 @@ @SmallTest @Feature({"Browser", "ContextMenu"}) @DisableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS}) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE}) public void testContextMenuRetrievesImageOptions() throws TimeoutException { Tab tab = mDownloadTestRule.getActivity().getActivityTab(); ContextMenu menu = ContextMenuUtils.openContextMenu(tab, "testImage"); @@ -586,10 +585,9 @@ @SmallTest @Feature({"Browser", "ContextMenu"}) @DisableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS}) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE, - ChromeFeatureList.CONTEXT_MENU_ENABLE_LENS_SHOPPING_ALLOWLIST}) - public void - testContextMenuRetrievesImageOptionsWithLensShoppingAllowlist() throws TimeoutException { + @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_ENABLE_LENS_SHOPPING_ALLOWLIST}) + public void testContextMenuRetrievesImageOptionsWithLensShoppingAllowlist() + throws TimeoutException { Tab tab = mDownloadTestRule.getActivity().getActivityTab(); ContextMenu menu = ContextMenuUtils.openContextMenu(tab, "testImage"); @@ -605,10 +603,8 @@ @Test @SmallTest @Feature({"Browser", "ContextMenu"}) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS, - ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE}) - public void - testContextMenuRetrievesImageOptionsLensEnabled() throws TimeoutException { + @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS}) + public void testContextMenuRetrievesImageOptionsLensEnabled() throws TimeoutException { LensUtils.setFakePassableLensEnvironmentForTesting(true); Tab tab = mDownloadTestRule.getActivity().getActivityTab(); @@ -642,7 +638,7 @@ Integer[] expectedItems = {R.id.contextmenu_save_image, R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image, - R.id.contextmenu_shop_similar_products}; + R.id.contextmenu_shop_similar_products, R.id.contextmenu_copy_image}; Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab}; expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems); @@ -668,7 +664,7 @@ Integer[] expectedItems = {R.id.contextmenu_save_image, R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image, - R.id.contextmenu_shop_image_with_google_lens}; + R.id.contextmenu_shop_image_with_google_lens, R.id.contextmenu_copy_image}; Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab}; expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems); @@ -694,7 +690,7 @@ Integer[] expectedItems = {R.id.contextmenu_save_image, R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image, - R.id.contextmenu_search_similar_products}; + R.id.contextmenu_search_similar_products, R.id.contextmenu_copy_image}; Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab}; expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems); @@ -719,7 +715,7 @@ Integer[] expectedItems = {R.id.contextmenu_save_image, R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_with_google_lens, - R.id.contextmenu_share_image}; + R.id.contextmenu_share_image, R.id.contextmenu_copy_image}; Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab}; expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems); @@ -745,7 +741,8 @@ Integer[] expectedItems = {R.id.contextmenu_save_image, R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_with_google_lens, - R.id.contextmenu_share_image, R.id.contextmenu_shop_similar_products}; + R.id.contextmenu_share_image, R.id.contextmenu_shop_similar_products, + R.id.contextmenu_copy_image}; Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab}; expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems); @@ -766,7 +763,7 @@ Integer[] expectedItems = {R.id.contextmenu_save_image, R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_by_image, - R.id.contextmenu_share_image}; + R.id.contextmenu_share_image, R.id.contextmenu_copy_image}; Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab}; expectedItems = addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems); @@ -778,7 +775,6 @@ @Feature({"Browser", "ContextMenu"}) @Policies.Add({ @Policies.Item(key = "DefaultSearchProviderEnabled", string = "false") }) @DisableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS}) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE}) public void testContextMenuRetrievesImageOptions_NoDefaultSearchEngine() throws TimeoutException { Tab tab = mDownloadTestRule.getActivity().getActivityTab(); @@ -797,10 +793,8 @@ @SmallTest @Feature({"Browser", "ContextMenu"}) @Policies.Add({ @Policies.Item(key = "DefaultSearchProviderEnabled", string = "false") }) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS, - ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE}) - public void - testContextMenuRetrievesImageOptions_NoDefaultSearchEngineLensEnabled() + @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS}) + public void testContextMenuRetrievesImageOptions_NoDefaultSearchEngineLensEnabled() throws TimeoutException { LensUtils.setFakePassableLensEnvironmentForTesting(true); @@ -821,7 +815,6 @@ @SmallTest @Feature({"Browser", "ContextMenu"}) @DisableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS}) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE}) public void testContextMenuRetrievesImageLinkOptions() throws TimeoutException { Tab tab = mDownloadTestRule.getActivity().getActivityTab(); ContextMenu menu = ContextMenuUtils.openContextMenu(tab, "testImageLink"); @@ -842,10 +835,9 @@ @Test @SmallTest @Feature({"Browser", "ContextMenu"}) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS, - ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE}) - public void - testContextMenuRetrievesImageLinkOptionsSearchLensEnabled() throws TimeoutException { + @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS}) + public void testContextMenuRetrievesImageLinkOptionsSearchLensEnabled() + throws TimeoutException { LensUtils.setFakePassableLensEnvironmentForTesting(true); Tab tab = mDownloadTestRule.getActivity().getActivityTab(); @@ -883,7 +875,8 @@ R.id.contextmenu_open_in_incognito_tab, R.id.contextmenu_copy_link_address, R.id.contextmenu_save_link_as, R.id.contextmenu_save_image, R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_by_image, - R.id.contextmenu_share_image, R.id.contextmenu_share_link}; + R.id.contextmenu_share_image, R.id.contextmenu_share_link, + R.id.contextmenu_copy_image}; Integer[] featureItems = {R.id.contextmenu_open_in_ephemeral_tab, R.id.contextmenu_open_image_in_ephemeral_tab}; expectedItems = @@ -908,7 +901,6 @@ @Test @SmallTest @Feature({"Browser", "ContextMenu"}) - @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE}) public void testCopyImage() throws Throwable { // Clear the clipboard. Clipboard.getInstance().setText("");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java index 8bf90d8..c53c12f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -29,6 +29,7 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.RuleChain; @@ -59,6 +60,7 @@ import org.chromium.components.signin.test.util.FakeProfileDataSource; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.test.util.DisableAnimationsTestRule; import java.io.IOException; @@ -84,6 +86,11 @@ /* accountName= */ "test.account2@gmail.com", /* avatar= */ null, /* fullName= */ null, /* givenName= */ null); + // Disable animations to reduce flakiness. + @ClassRule + public static final DisableAnimationsTestRule sNoAnimationsRule = + new DisableAnimationsTestRule(); + @Rule public final ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(0).build(); @@ -293,10 +300,22 @@ return !bottomSheetView.findViewById(R.id.account_picker_continue_as_button).isShown(); }); verify(mAccountPickerDelegateMock).signIn(PROFILE_DATA1.getAccountName()); + Assert.assertTrue( + bottomSheetView.findViewById(R.id.account_picker_signin_spinner_view).isShown()); + // Currently the ProgressBar animation cannot be disabled on android-marshmallow-arm64-rel + // bot with DisableAnimationsTestRule, we hide the ProgressBar manually here to enable + // checks of other elements on the screen. + // TODO(https://crbug.com/1115067): Delete this line once DisableAnimationsTestRule is + // fixed. + ThreadUtils.runOnUiThread(() -> { + bottomSheetView.findViewById(R.id.account_picker_signin_spinner_view) + .setVisibility(View.GONE); + }); onView(withText(R.string.signin_account_picker_bottom_sheet_signin_title)) .check(matches(isDisplayed())); onView(withId(R.id.account_picker_bottom_sheet_subtitle)) .check(matches(not(isDisplayed()))); + onView(withId(R.id.account_picker_horizontal_divider)).check(matches(not(isDisplayed()))); onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed()))); onView(withId(R.id.account_picker_selected_account)).check(matches(not(isDisplayed()))); onView(withId(R.id.account_picker_continue_as_button)).check(matches(not(isDisplayed())));
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java index 12aa5ad7..c02f286 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/QualityEnforcerUnitTest.java
@@ -76,6 +76,8 @@ private ArgumentCaptor<CustomTabTabObserver> mTabObserverCaptor; @Mock private Tab mTab; + @Mock + public TrustedWebActivityUmaRecorder mUmaRecorder; private ShadowPackageManager mShadowPackageManager; @@ -91,8 +93,9 @@ when(mVerifier.verify(TRUSTED_ORIGIN_PAGE)).thenReturn(Promise.fulfilled(true)); when(mVerifier.verify(UNTRUSTED_PAGE)).thenReturn(Promise.fulfilled(false)); - mQualityEnforcer = new QualityEnforcer(mActivity, mTabObserverRegistrar, - mIntentDataProvider, mCustomTabsConnection, mVerifier, mClientPackageNameProvider); + mQualityEnforcer = + new QualityEnforcer(mActivity, mTabObserverRegistrar, mIntentDataProvider, + mCustomTabsConnection, mVerifier, mClientPackageNameProvider, mUmaRecorder); } @Test
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index f86df9d..0d05402 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -703,8 +703,20 @@ <!-- Dice Web Signin Interception Bubble--> <if expr="not chromeos and not is_android"> - <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC" desc="Body of the web signin interception bubble"> - You signed in with a work account. Would you like to create a new Chromium Profile for Work to keep your data separate? + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE" desc="Title of the web signin interception bubble"> + Create new Chromium space for <ph name="NEW_USER">$1<ex>Bob</ex></ph>? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC" desc="Body of the web signin interception bubble when the new account is a personal account and the existing account is a managed account"> + You signed-in with a work account. Would you like to create a new Chromium space for <ph name="NEW_USER">$1<ex>Bob</ex></ph> to keep your personal data separate? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC" desc="Body of the web signin interception bubble"> + You signed-in with a new account in <ph name="EXISTING_USER">$1<ex>Elisa</ex></ph>’s space. Would you like to create a new Chromium space for <ph name="NEW_USER">$2<ex>Bob</ex></ph> to keep your data separate? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC" desc="Body of the web signin interception bubble when the new account is managed"> + You signed-in with a Work account in <ph name="EXISTING_USER">$1<ex>Elisa</ex></ph>’s space. Would you like to create a new Chromium space for <ph name="WORK_DOMAIN">$2<ex>example.com</ex></ph> to keep your data separate? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE" desc="Title of the web signin interception bubble"> + Create new Chromium Work space? </message> </if>
diff --git a/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC.png.sha1 b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC.png.sha1 new file mode 100644 index 0000000..4f849f1 --- /dev/null +++ b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC.png.sha1
@@ -0,0 +1 @@ +68fd06a2f928c5d491eed19fc44d4f2b88bf9c8a \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE.png.sha1 b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE.png.sha1 new file mode 100644 index 0000000..4f849f1 --- /dev/null +++ b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE.png.sha1
@@ -0,0 +1 @@ +68fd06a2f928c5d491eed19fc44d4f2b88bf9c8a \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 index dc2f9af32..b1d6480 100644 --- a/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 +++ b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1
@@ -1 +1 @@ -5b9b6af71c9cb4fced7472e927c8a4e695a34e62 \ No newline at end of file +5b5fdde82e956fd3f78a7ee780f6c3563c8dcf07 \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 new file mode 100644 index 0000000..b1d6480 --- /dev/null +++ b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1
@@ -0,0 +1 @@ +5b5fdde82e956fd3f78a7ee780f6c3563c8dcf07 \ No newline at end of file
diff --git a/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC.png.sha1 b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC.png.sha1 new file mode 100644 index 0000000..3781f5b --- /dev/null +++ b/chrome/app/chromium_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC.png.sha1
@@ -0,0 +1 @@ +3182482996d3d091632f1115027ef24a29b6b28a \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index c53b8b51..4f2e51c2 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -7767,9 +7767,6 @@ <!-- Dice Web Signin Interception Bubble--> <if expr="not chromeos and not is_android"> - <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE" desc="Title of the web signin interception bubble"> - Create Work Profile? - </message> <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL" desc="Label of the confirmation button in the web signin interception bubble"> New Profile </message>
diff --git a/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 deleted file mode 100644 index dc2f9af32..0000000 --- a/chrome/app/generated_resources_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -5b9b6af71c9cb4fced7472e927c8a4e695a34e62 \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index d86661db..f795a20d 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -710,8 +710,20 @@ <!-- Dice Web Signin Interception Bubble--> <if expr="not chromeos and not is_android"> - <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC" desc="Body of the web signin interception bubble"> - You signed in with a work account. Would you like to create a new Chrome Profile for Work to keep your data separate? + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE" desc="Title of the web signin interception bubble"> + Create new Chrome space for <ph name="NEW_USER">$1<ex>Bob</ex></ph>? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC" desc="Body of the web signin interception bubble when the new account is a personal account and the existing account is a managed account"> + You signed-in with a work account. Would you like to create a new Chrome space for <ph name="NEW_USER">$1<ex>Bob</ex></ph> to keep your personal data separate? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC" desc="Body of the web signin interception bubble"> + You signed-in with a new account in <ph name="EXISTING_USER">$1<ex>Elisa</ex></ph>’s space. Would you like to create a new Chrome space for <ph name="NEW_USER">$2<ex>Bob</ex></ph> to keep your data separate? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC" desc="Body of the web signin interception bubble when the new account is managed"> + You signed-in with a Work account in <ph name="EXISTING_USER">$1<ex>Elisa</ex></ph>’s space. Would you like to create a new Chrome space for <ph name="WORK_DOMAIN">$2<ex>example.com</ex></ph> to keep your data separate? + </message> + <message name="IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE" desc="Title of the web signin interception bubble"> + Create new Chrome Work space? </message> </if>
diff --git a/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC.png.sha1 new file mode 100644 index 0000000..4f849f1 --- /dev/null +++ b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC.png.sha1
@@ -0,0 +1 @@ +68fd06a2f928c5d491eed19fc44d4f2b88bf9c8a \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE.png.sha1 new file mode 100644 index 0000000..4f849f1 --- /dev/null +++ b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE.png.sha1
@@ -0,0 +1 @@ +68fd06a2f928c5d491eed19fc44d4f2b88bf9c8a \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 index dc2f9af32..b1d6480 100644 --- a/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1 +++ b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC.png.sha1
@@ -1 +1 @@ -5b9b6af71c9cb4fced7472e927c8a4e695a34e62 \ No newline at end of file +5b5fdde82e956fd3f78a7ee780f6c3563c8dcf07 \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1 new file mode 100644 index 0000000..b1d6480 --- /dev/null +++ b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE.png.sha1
@@ -0,0 +1 @@ +5b5fdde82e956fd3f78a7ee780f6c3563c8dcf07 \ No newline at end of file
diff --git a/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC.png.sha1 b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC.png.sha1 new file mode 100644 index 0000000..3781f5b --- /dev/null +++ b/chrome/app/google_chrome_strings_grd/IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC.png.sha1
@@ -0,0 +1 @@ +3182482996d3d091632f1115027ef24a29b6b28a \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 2836062..81948a7 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2927,7 +2927,7 @@ "//chrome/browser/notifications/scheduler/public", "//chrome/browser/offline_pages/prefetch/notifications", "//chrome/browser/optimization_guide/android:jni_headers", - "//chrome/browser/password_check/android/internal:jni_headers", + "//chrome/browser/password_check/android:jni_headers", "//chrome/browser/payments/android:jni_headers", "//chrome/browser/policy/android:jni_headers", "//chrome/browser/privacy:jni_headers",
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 7d06f9c..c29fa2e 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -1346,7 +1346,16 @@ TestHelper("testDisplayNoneWebviewLoad", "web_view/shim", NO_TEST_SERVER); } -IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestDisplayNoneWebviewRemoveChild) { +#if defined(OS_WIN) || defined(OS_LINUX) +#define MAYBE_Shim_TestDisplayNoneWebviewRemoveChild \ + DISABLED_Shim_TestDisplayNoneWebviewRemoveChild +#else +#define MAYBE_Shim_TestDisplayNoneWebviewRemoveChild \ + Shim_TestDisplayNoneWebviewRemoveChild +#endif +// Flaky on Windows & Linux: https://crbug.com/1115106. +IN_PROC_BROWSER_TEST_F(WebViewTest, + MAYBE_Shim_TestDisplayNoneWebviewRemoveChild) { TestHelper("testDisplayNoneWebviewRemoveChild", "web_view/shim", NO_TEST_SERVER); }
diff --git a/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc index 62a0c79..d498242 100644 --- a/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc +++ b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc
@@ -81,14 +81,13 @@ void SetPolicy(policy::PolicyMap* policies, const char* key, - std::unique_ptr<base::Value> value) { + base::Value value) { policies->Set(key, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_PLATFORM, std::move(value), nullptr); } void EnableBrowserSwitcher(policy::PolicyMap* policies) { - SetPolicy(policies, policy::key::kBrowserSwitcherEnabled, - std::make_unique<base::Value>(true)); + SetPolicy(policies, policy::key::kBrowserSwitcherEnabled, base::Value(true)); } } // namespace @@ -128,7 +127,7 @@ policy::PolicyMap policies; EnableBrowserSwitcher(&policies); SetPolicy(&policies, policy::key::kBrowserSwitcherUseIeSitelist, - std::make_unique<base::Value>(use_ie_sitelist)); + base::Value(use_ie_sitelist)); provider_.UpdateChromePolicy(policies); base::RunLoop().RunUntilIdle(); } @@ -137,7 +136,7 @@ policy::PolicyMap policies; EnableBrowserSwitcher(&policies); SetPolicy(&policies, policy::key::kBrowserSwitcherExternalSitelistUrl, - std::make_unique<base::Value>(url)); + base::Value(url)); provider_.UpdateChromePolicy(policies); base::RunLoop().RunUntilIdle(); } @@ -368,12 +367,12 @@ ExternalGreylistFetchAndParseAfterStartup) { policy::PolicyMap policies; EnableBrowserSwitcher(&policies); - auto url_list = std::make_unique<base::ListValue>(); - url_list->Append("*"); + base::Value url_list(base::Value::Type::LIST); + url_list.Append("*"); SetPolicy(&policies, policy::key::kBrowserSwitcherUrlList, std::move(url_list)); SetPolicy(&policies, policy::key::kBrowserSwitcherExternalGreylistUrl, - std::make_unique<base::Value>(kAValidUrl)); + base::Value(kAValidUrl)); policy_provider().UpdateChromePolicy(policies); base::RunLoop().RunUntilIdle(); @@ -513,23 +512,23 @@ policy::PolicyMap policies; EnableBrowserSwitcher(&policies); SetPolicy(&policies, policy::key::kAlternativeBrowserPath, - std::make_unique<base::Value>("IExplore.exe")); - auto alt_params = std::make_unique<base::ListValue>(); - alt_params->Append(base::Value("--bogus-flag")); + base::Value("IExplore.exe")); + base::Value alt_params(base::Value::Type::LIST); + alt_params.Append("--bogus-flag"); SetPolicy(&policies, policy::key::kAlternativeBrowserParameters, std::move(alt_params)); SetPolicy(&policies, policy::key::kBrowserSwitcherChromePath, - std::make_unique<base::Value>("chrome.exe")); - auto chrome_params = std::make_unique<base::ListValue>(); - chrome_params->Append(base::Value("--force-dark-mode")); + base::Value("chrome.exe")); + base::Value chrome_params(base::Value::Type::LIST); + chrome_params.Append("--force-dark-mode"); SetPolicy(&policies, policy::key::kBrowserSwitcherChromeParameters, std::move(chrome_params)); - auto url_list = std::make_unique<base::ListValue>(); - url_list->Append(base::Value("example.com")); + base::Value url_list(base::Value::Type::LIST); + url_list.Append("example.com"); SetPolicy(&policies, policy::key::kBrowserSwitcherUrlList, std::move(url_list)); - auto greylist = std::make_unique<base::ListValue>(); - greylist->Append(base::Value("foo.example.com")); + base::Value greylist(base::Value::Type::LIST); + greylist.Append("foo.example.com"); SetPolicy(&policies, policy::key::kBrowserSwitcherUrlGreylist, std::move(greylist)); policy_provider().UpdateChromePolicy(policies); @@ -580,13 +579,11 @@ policy::PolicyMap policies; EnableBrowserSwitcher(&policies); SetPolicy(&policies, policy::key::kBrowserSwitcherExternalSitelistUrl, - std::make_unique<base::Value>( - net::FilePathToFileURL(external_sitelist_path).spec())); + base::Value(net::FilePathToFileURL(external_sitelist_path).spec())); SetPolicy(&policies, policy::key::kBrowserSwitcherExternalGreylistUrl, - std::make_unique<base::Value>( - net::FilePathToFileURL(external_greylist_path).spec())); + base::Value(net::FilePathToFileURL(external_greylist_path).spec())); SetPolicy(&policies, policy::key::kBrowserSwitcherUseIeSitelist, - std::make_unique<base::Value>(true)); + base::Value(true)); policy_provider().UpdateChromePolicy(policies); base::RunLoop().RunUntilIdle(); BrowserSwitcherServiceWin::SetIeemSitelistUrlForTesting(
diff --git a/chrome/browser/chromeos/crosapi/DEPS b/chrome/browser/chromeos/crosapi/DEPS index 34c9a59..abdbca61 100644 --- a/chrome/browser/chromeos/crosapi/DEPS +++ b/chrome/browser/chromeos/crosapi/DEPS
@@ -1,8 +1,4 @@ specific_include_rules = { - "browser_manager\.cc": [ - # To show error notification to developers. - "+ui/message_center/message_center.h", - ], "screen_manager_crosapi\.cc": [ # For window parenting. "+ash/shell.h",
diff --git a/chrome/browser/chromeos/crosapi/browser_manager.cc b/chrome/browser/chromeos/crosapi/browser_manager.cc index 4216491..870b182d 100644 --- a/chrome/browser/chromeos/crosapi/browser_manager.cc +++ b/chrome/browser/chromeos/crosapi/browser_manager.cc
@@ -4,13 +4,10 @@ #include "chrome/browser/chromeos/crosapi/browser_manager.h" -#include <sys/statvfs.h> - #include <string> #include <utility> #include <vector> -#include "ash/public/cpp/notification_utils.h" #include "base/bind.h" #include "base/command_line.h" #include "base/environment.h" @@ -22,11 +19,9 @@ #include "base/process/process_handle.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" -#include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" -#include "base/threading/scoped_blocking_call.h" #include "chrome/browser/chromeos/crosapi/ash_chrome_service_impl.h" #include "chrome/browser/chromeos/crosapi/browser_loader.h" #include "chrome/browser/chromeos/crosapi/browser_util.h" @@ -41,7 +36,6 @@ #include "mojo/public/cpp/platform/platform_channel.h" #include "mojo/public/cpp/system/invitation.h" #include "mojo/public/mojom/base/binder.mojom.h" -#include "ui/message_center/message_center.h" // TODO(crbug.com/1101667): Currently, this source has log spamming // by LOG(WARNING) for non critical errors to make it easy @@ -97,39 +91,6 @@ browser_util::kLaunchOnLoginPref); } -// Checks that the stateful parition is executable. Returns true if it is. -// Otherwise presents a warning dialog for the developer. -bool VerifyStatefulPartitionIsExecutable() { - struct statvfs buf; - { - base::ScopedBlockingCall scoped_blocking_call( - FROM_HERE, base::BlockingType::MAY_BLOCK); - if (statvfs("/mnt/stateful_partition", &buf) < 0) { - PLOG(ERROR) << "statvfs() failed"; - return false; - } - } - const bool is_executable = !(buf.f_flag & ST_NOEXEC); - if (is_executable) - return true; - - message_center::MessageCenter* message_center = - message_center::MessageCenter::Get(); - std::string notification_id = "stateful_noexec"; - message_center->AddNotification(ash::CreateSystemNotification( - message_center::NOTIFICATION_TYPE_SIMPLE, notification_id, - base::ASCIIToUTF16("Cannot launch lacros-chrome"), - base::ASCIIToUTF16("/mnt/stateful_partition is marked as noexec."), - base::string16(), // display_source - GURL(), - message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT, - notification_id), - message_center::RichNotificationData(), - /*delegate=*/nullptr, gfx::VectorIcon(), - message_center::SystemNotificationWarningLevel::NORMAL)); - return false; -} - } // namespace // static @@ -250,16 +211,6 @@ if (custom_chrome_path) { argv.push_back("--enable-logging"); argv.push_back("--log-file=" + LacrosLogPath().value()); - - // If this is a developer, we also want to check that the partition is - // executable. This allows us to present an obvious warning dialog for the - // common case where the device has been restarted and the partition is no - // longer executable. We cannot simply check the return value of - // base::LaunchProcess as that actually returns success. - if (base::SysInfo::IsRunningOnChromeOS() && - !VerifyStatefulPartitionIsExecutable()) { - return false; - } } // Set up Mojo channel.
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc index db9d2af..2c4bbac8 100644 --- a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc +++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -766,7 +766,7 @@ } INSTANTIATE_TEST_SUITE_P( - OobeInteractiveUITestImpl, + All, OobeInteractiveUITest, testing::Combine(testing::Bool(), testing::Bool(), @@ -844,7 +844,7 @@ } INSTANTIATE_TEST_SUITE_P( - OobeZeroTouchInteractiveUITestImpl, + All, OobeZeroTouchInteractiveUITest, testing::Combine(testing::Bool(), testing::Bool(), @@ -938,7 +938,7 @@ } INSTANTIATE_TEST_SUITE_P( - PublicSessionOobeTestImpl, + All, PublicSessionOobeTest, testing::Combine(testing::Bool(), testing::Bool(), @@ -972,7 +972,7 @@ } INSTANTIATE_TEST_SUITE_P( - PublicSessionWithTermsOfServiceOobeTestImpl, + All, PublicSessionWithTermsOfServiceOobeTest, testing::Combine(testing::Bool(), testing::Bool(), @@ -1078,7 +1078,7 @@ } INSTANTIATE_TEST_SUITE_P( - EphemeralUserOobeTestImpl, + All, EphemeralUserOobeTest, testing::Combine(testing::Bool(), testing::Bool(),
diff --git a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc index 60509f23..427c6ceb 100644 --- a/chrome/browser/chromeos/login/oobe_localization_browsertest.cc +++ b/chrome/browser/chromeos/login/oobe_localization_browsertest.cc
@@ -379,7 +379,7 @@ } INSTANTIATE_TEST_SUITE_P( - StructSequence, + All, OobeLocalizationTest, testing::Range(&oobe_localization_test_parameters[0], &oobe_localization_test_parameters[base::size(
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index cbb8f7f4..75ff8423 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -1852,9 +1852,7 @@ EXPECT_FALSE(attrs.has_password_change_url()); } -INSTANTIATE_TEST_SUITE_P(SAMLPasswordAttributesSuite, - SAMLPasswordAttributesTest, - testing::Bool()); +INSTANTIATE_TEST_SUITE_P(All, SAMLPasswordAttributesTest, testing::Bool()); void FakeGetCertificateCallbackTrue( attestation::AttestationFlow::CertificateCallback callback) {
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc index 7452b2a..3310746 100644 --- a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
@@ -356,7 +356,7 @@ } // "es" tests language switching, "en-GB" checks switching to language varants. -INSTANTIATE_TEST_SUITE_P(SyncConsentTestWithParamsImpl, +INSTANTIATE_TEST_SUITE_P(All, SyncConsentTestWithParams, testing::Values("es", "en-GB"));
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc index 1fd75fc1..acd5e27 100644 --- a/chrome/browser/chromeos/login/webview_login_browsertest.cc +++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -650,7 +650,7 @@ EXPECT_FALSE(error_screen_watcher.has_error_screen_been_shown()); } -INSTANTIATE_TEST_SUITE_P(WebviewLoginWithIframe, +INSTANTIATE_TEST_SUITE_P(All, WebviewLoginWithIframeTest, testing::Values(FrameUrlOrigin::kSameOrigin, FrameUrlOrigin::kDifferentOrigin));
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc index 5bd0f415..b541e95 100644 --- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -1052,7 +1052,7 @@ } INSTANTIATE_TEST_SUITE_P( - WizardControllerUpdateAfterCompletedOobe, + All, WizardControllerUpdateAfterCompletedOobeTest, testing::Values(UpdateScreen::Result::UPDATE_NOT_REQUIRED, UpdateScreen::Result::UPDATE_ERROR)); @@ -1469,7 +1469,7 @@ } } -INSTANTIATE_TEST_SUITE_P(WizardControllerDeviceStateExplicitRequirement, +INSTANTIATE_TEST_SUITE_P(All, WizardControllerDeviceStateExplicitRequirementTest, testing::Values(false, true));
diff --git a/chrome/browser/extensions/api/declarative_content/content_action.cc b/chrome/browser/extensions/api/declarative_content/content_action.cc index 94112a93..29cd54f00 100644 --- a/chrome/browser/extensions/api/declarative_content/content_action.cc +++ b/chrome/browser/extensions/api/declarative_content/content_action.cc
@@ -28,6 +28,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_messages.h" #include "extensions/common/image_util.h" +#include "extensions/common/script_constants.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" @@ -336,7 +337,10 @@ script_.set_host_id(host_id); script_.set_run_location(UserScript::BROWSER_DRIVEN); script_.set_match_all_frames(script_data.all_frames); - script_.set_match_about_blank(script_data.match_about_blank); + script_.set_match_origin_as_fallback( + script_data.match_about_blank + ? MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree + : MatchOriginAsFallbackBehavior::kNever); for (auto it = script_data.css_file_names.cbegin(); it != script_data.css_file_names.cend(); ++it) { GURL url = extension->GetResourceURL(*it);
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc index 83e2f4f..a1a76c0 100644 --- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc +++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -640,7 +640,14 @@ << "a specific tab id."; } -IN_PROC_BROWSER_TEST_P(BrowserActionApiLazyTest, IncognitoBasic) { +#if defined(OS_WIN) || defined(OS_LINUX) +// Flaky: https://crbug.com/1113904 +#define MAYBE_IncognitoBasic DISABLED_IncognitoBasic +#else +#define MAYBE_IncognitoBasic IncognitoBasic +#endif + +IN_PROC_BROWSER_TEST_P(BrowserActionApiLazyTest, MAYBE_IncognitoBasic) { ExtensionTestMessageListener ready_listener("ready", false); ASSERT_TRUE(embedded_test_server()->Start()); scoped_refptr<const Extension> extension = LoadExtensionWithParamFlags(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index bc9e1cd..11b7846 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -3901,7 +3901,7 @@ { "name": "scanning-ui", "owners": [ "jschettler", "bmgordon" ], - "expiry_milestone": 85 + "expiry_milestone": 90 }, { "name": "scheduler-configuration",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 9d2c4b71..d585e0c 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -170,7 +170,8 @@ const char kAppCacheDescription[] = "When disabled, turns off all AppCache code so that developers " "can test that their code works properly in the future when AppCache " - "has been removed."; + "has been removed. If disabled, this will also delete any AppCache data " + "from profile directories."; const char kDnsHttpssvcName[] = "Support for HTTPSSVC records in DNS."; const char kDnsHttpssvcDescription[] =
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index e4774ad..790e0a9 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -408,7 +408,7 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kContextMenuCopyImage{"ContextMenuCopyImage", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kContextMenuSearchWithGoogleLens{ "ContextMenuSearchWithGoogleLens", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/google/google_update_policy_fetcher_win.cc b/chrome/browser/google/google_update_policy_fetcher_win.cc index fbcf1942..8b887ab 100644 --- a/chrome/browser/google/google_update_policy_fetcher_win.cc +++ b/chrome/browser/google/google_update_policy_fetcher_win.cc
@@ -31,7 +31,7 @@ // Adds the |value| of |policy_name| to |policies| using a "Mandatory" level, // "Machine" scope and "Platform" source. void AddPolicy(const char* policy_name, - std::unique_ptr<base::Value> value, + base::Value value, policy::PolicyMap* policies) { DCHECK(policies); policies->Set(policy_name, policy::POLICY_LEVEL_MANDATORY, @@ -83,7 +83,7 @@ &auto_update_check_period_minutes); if (SUCCEEDED(last_com_res)) { AddPolicy(kAutoUpdateCheckPeriodMinutes, - std::make_unique<base::Value>( + base::Value( base::saturated_cast<int>(auto_update_check_period_minutes)), policies.get()); } @@ -93,10 +93,9 @@ download_preference_group_policy.Receive()); if (SUCCEEDED(last_com_res) && download_preference_group_policy.Length() > 0) { - AddPolicy( - kDownloadPreference, - std::make_unique<base::Value>(download_preference_group_policy.Get()), - policies.get()); + AddPolicy(kDownloadPreference, + base::Value(download_preference_group_policy.Get()), + policies.get()); } DWORD effective_policy_for_app_installs; @@ -104,7 +103,7 @@ app_id.Get(), &effective_policy_for_app_installs); if (SUCCEEDED(last_com_res)) { AddPolicy(kInstallPolicy, - std::make_unique<base::Value>( + base::Value( base::saturated_cast<int>(effective_policy_for_app_installs)), policies.get()); } @@ -114,7 +113,7 @@ app_id.Get(), &effective_policy_for_app_updates); if (SUCCEEDED(last_com_res)) { AddPolicy(kUpdatePolicy, - std::make_unique<base::Value>( + base::Value( base::saturated_cast<int>(effective_policy_for_app_updates)), policies.get()); } @@ -127,36 +126,35 @@ &updates_suppressed_start_hour, &updates_suppressed_start_minute, &updates_suppressed_duration, &are_updates_suppressed); if (SUCCEEDED(last_com_res)) { - AddPolicy(kUpdatesSuppressedDurationMin, - std::make_unique<base::Value>( - base::saturated_cast<int>(updates_suppressed_duration)), - policies.get()); - AddPolicy(kUpdatesSuppressedStartHour, - std::make_unique<base::Value>( - base::saturated_cast<int>(updates_suppressed_start_hour)), - policies.get()); - AddPolicy(kUpdatesSuppressedStartMinute, - std::make_unique<base::Value>( - base::saturated_cast<int>(updates_suppressed_start_minute)), - policies.get()); + AddPolicy( + kUpdatesSuppressedDurationMin, + base::Value(base::saturated_cast<int>(updates_suppressed_duration)), + policies.get()); + AddPolicy( + kUpdatesSuppressedStartHour, + base::Value(base::saturated_cast<int>(updates_suppressed_start_hour)), + policies.get()); + AddPolicy( + kUpdatesSuppressedStartMinute, + base::Value(base::saturated_cast<int>(updates_suppressed_start_minute)), + policies.get()); } VARIANT_BOOL is_rollback_to_target_version_allowed; last_com_res = policy_status->get_isRollbackToTargetVersionAllowed( app_id.Get(), &is_rollback_to_target_version_allowed); if (SUCCEEDED(last_com_res)) { - AddPolicy(kRollbackToTargetVersion, - std::make_unique<base::Value>( - is_rollback_to_target_version_allowed == VARIANT_TRUE), - policies.get()); + AddPolicy( + kRollbackToTargetVersion, + base::Value(is_rollback_to_target_version_allowed == VARIANT_TRUE), + policies.get()); } base::win::ScopedBstr target_version_prefix; last_com_res = policy_status->get_targetVersionPrefix( app_id.Get(), target_version_prefix.Receive()); if (SUCCEEDED(last_com_res) && target_version_prefix.Length() > 0) { - AddPolicy(kTargetVersionPrefix, - std::make_unique<base::Value>(target_version_prefix.Get()), + AddPolicy(kTargetVersionPrefix, base::Value(target_version_prefix.Get()), policies.get()); }
diff --git a/chrome/browser/installable/installable_logging.cc b/chrome/browser/installable/installable_logging.cc index e4faec9..de902bf 100644 --- a/chrome/browser/installable/installable_logging.cc +++ b/chrome/browser/installable/installable_logging.cc
@@ -64,6 +64,9 @@ "channels on Android."; static const char kManifestLocationChanged[] = "Manifest location changed during fetch"; +static const char kManifestDisplayOverrideNotSupportedMessage[] = + "Manifest contains 'display_override' field, and the first supported " + "display mode must be one of 'standalone', 'fullscreen', or 'minimal-ui'"; static const char kNotInMainFrameId[] = "not-in-main-frame"; static const char kNotFromSecureOriginId[] = "not-from-secure-origin"; @@ -96,6 +99,8 @@ static const char kPreferRelatedApplicationsSupportedOnlyBetaStableId[] = "prefer-related-applications-only-beta-stable"; static const char kManifestLocationChangedId[] = "manifest-location-changed"; +static const char kManifestDisplayOverrideNotSupportedId[] = + "manifest-display-override-not-supported"; const std::string& GetMessagePrefix() { static base::NoDestructor<std::string> message_prefix( @@ -200,6 +205,9 @@ case MANIFEST_URL_CHANGED: message = kManifestLocationChanged; break; + case MANIFEST_DISPLAY_OVERRIDE_NOT_SUPPORTED: + message = kManifestDisplayOverrideNotSupportedMessage; + break; } return message; @@ -305,6 +313,9 @@ case MANIFEST_URL_CHANGED: error_id = kManifestLocationChangedId; break; + case MANIFEST_DISPLAY_OVERRIDE_NOT_SUPPORTED: + error_id = kManifestDisplayOverrideNotSupportedId; + break; } error.error_id = error_id; error.installability_error_arguments = error_arguments;
diff --git a/chrome/browser/installable/installable_logging.h b/chrome/browser/installable/installable_logging.h index 8921779..b25c88e6 100644 --- a/chrome/browser/installable/installable_logging.h +++ b/chrome/browser/installable/installable_logging.h
@@ -57,6 +57,7 @@ PREFER_RELATED_APPLICATIONS = 36, PREFER_RELATED_APPLICATIONS_SUPPORTED_ONLY_BETA_STABLE = 37, MANIFEST_URL_CHANGED = 38, + MANIFEST_DISPLAY_OVERRIDE_NOT_SUPPORTED = 39, MAX_ERROR_CODE, };
diff --git a/chrome/browser/installable/installable_manager.cc b/chrome/browser/installable/installable_manager.cc index a6a057c4..e9cefc6 100644 --- a/chrome/browser/installable/installable_manager.cc +++ b/chrome/browser/installable/installable_manager.cc
@@ -24,6 +24,7 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/storage_partition.h" +#include "content/public/common/content_features.h" #include "content/public/common/origin_util.h" #include "content/public/common/url_constants.h" #include "net/base/url_util.h" @@ -179,6 +180,12 @@ return false; } +bool ShouldRejectDisplayMode(blink::mojom::DisplayMode display_mode) { + return !(display_mode == blink::mojom::DisplayMode::kStandalone || + display_mode == blink::mojom::DisplayMode::kFullscreen || + display_mode == blink::mojom::DisplayMode::kMinimalUi); +} + // Returns true if |params| specifies a full PWA check. bool IsParamsForPwaCheck(const InstallableParams& params) { return params.valid_manifest && params.has_worker && @@ -656,12 +663,26 @@ is_valid = false; } - if (check_webapp_manifest_display && - manifest.display != blink::mojom::DisplayMode::kStandalone && - manifest.display != blink::mojom::DisplayMode::kFullscreen && - manifest.display != blink::mojom::DisplayMode::kMinimalUi) { - valid_manifest_->errors.push_back(MANIFEST_DISPLAY_NOT_SUPPORTED); - is_valid = false; + if (check_webapp_manifest_display) { + blink::mojom::DisplayMode display_mode_to_evaluate = manifest.display; + InstallableStatusCode manifest_error = MANIFEST_DISPLAY_NOT_SUPPORTED; + + if (base::FeatureList::IsEnabled( + features::kWebAppManifestDisplayOverride)) { + // Unsupported values are ignored when we parse the manifest, and + // consequently aren't in the manifest.display_override array. + // If this array is not empty, the first value will "win", so validate + // this value is installable. + if (!manifest.display_override.empty()) { + display_mode_to_evaluate = manifest.display_override[0]; + manifest_error = MANIFEST_DISPLAY_OVERRIDE_NOT_SUPPORTED; + } + } + + if (ShouldRejectDisplayMode(display_mode_to_evaluate)) { + valid_manifest_->errors.push_back(manifest_error); + is_valid = false; + } } if (!DoesManifestContainRequiredIcon(manifest, prefer_maskable_icon)) {
diff --git a/chrome/browser/installable/installable_manager_browsertest.cc b/chrome/browser/installable/installable_manager_browsertest.cc index aa61baf..6da94b7 100644 --- a/chrome/browser/installable/installable_manager_browsertest.cc +++ b/chrome/browser/installable/installable_manager_browsertest.cc
@@ -12,6 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/banners/app_banner_manager_desktop.h" #include "chrome/browser/installable/installable_logging.h" @@ -24,6 +25,7 @@ #include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -211,6 +213,7 @@ EXPECT_EQ(manifest_.display, data.manifest->display); EXPECT_EQ(manifest_.name, data.manifest->name); EXPECT_EQ(manifest_.short_name, data.manifest->short_name); + EXPECT_EQ(manifest_.display_override, data.manifest->display_override); quit_closure_.Run(); } @@ -1836,3 +1839,103 @@ ASSERT_EQ(tester->errors().size(), 1u); EXPECT_EQ(tester->errors()[0], MANIFEST_URL_CHANGED); } + +// A dedicated test fixture for DisplayOverride, which is supported +// only for the new web apps mode, and requires a command line switch +// to enable manifest parsing. +class InstallableManagerBrowserTest_DisplayOverride + : public InstallableManagerBrowserTest { + public: + InstallableManagerBrowserTest_DisplayOverride() { + scoped_feature_list_.InitAndEnableFeature( + features::kWebAppManifestDisplayOverride); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(InstallableManagerBrowserTest_DisplayOverride, + CheckManifestOnly) { + base::RunLoop run_loop; + std::unique_ptr<CallbackTester> tester( + new CallbackTester(run_loop.QuitClosure())); + + NavigateAndRunInstallableManager( + browser(), tester.get(), GetManifestParams(), + GetURLOfPageWithServiceWorkerAndManifest( + "/banners/manifest_display_override.json")); + run_loop.Run(); + + EXPECT_FALSE(tester->manifest().IsEmpty()); + EXPECT_FALSE(tester->manifest_url().is_empty()); + ASSERT_EQ(2u, tester->manifest().display_override.size()); + EXPECT_EQ(blink::mojom::DisplayMode::kMinimalUi, + tester->manifest().display_override[0]); + EXPECT_EQ(blink::mojom::DisplayMode::kStandalone, + tester->manifest().display_override[1]); + + EXPECT_TRUE(tester->primary_icon_url().is_empty()); + EXPECT_EQ(nullptr, tester->primary_icon()); + EXPECT_FALSE(tester->has_maskable_primary_icon()); + EXPECT_FALSE(tester->valid_manifest()); + EXPECT_FALSE(tester->has_worker()); + EXPECT_TRUE(tester->splash_icon_url().is_empty()); + EXPECT_EQ(nullptr, tester->splash_icon()); + EXPECT_EQ(std::vector<InstallableStatusCode>{}, tester->errors()); +} + +IN_PROC_BROWSER_TEST_F(InstallableManagerBrowserTest_DisplayOverride, + ManifestDisplayOverrideReportsError) { + base::RunLoop run_loop; + std::unique_ptr<CallbackTester> tester( + new CallbackTester(run_loop.QuitClosure())); + + NavigateAndRunInstallableManager( + browser(), tester.get(), GetWebAppParams(), + GetURLOfPageWithServiceWorkerAndManifest( + "/banners/manifest_display_override_contains_browser.json")); + run_loop.Run(); + + EXPECT_FALSE(tester->manifest().IsEmpty()); + EXPECT_FALSE(tester->manifest_url().is_empty()); + ASSERT_EQ(3u, tester->manifest().display_override.size()); + EXPECT_EQ(blink::mojom::DisplayMode::kBrowser, + tester->manifest().display_override[0]); + EXPECT_EQ(blink::mojom::DisplayMode::kMinimalUi, + tester->manifest().display_override[1]); + EXPECT_EQ(blink::mojom::DisplayMode::kStandalone, + tester->manifest().display_override[2]); + EXPECT_EQ( + std::vector<InstallableStatusCode>{ + MANIFEST_DISPLAY_OVERRIDE_NOT_SUPPORTED}, + tester->errors()); +} + +IN_PROC_BROWSER_TEST_F(InstallableManagerBrowserTest_DisplayOverride, + FallbackToDisplayBrowser) { + base::RunLoop run_loop; + std::unique_ptr<CallbackTester> tester( + new CallbackTester(run_loop.QuitClosure())); + + NavigateAndRunInstallableManager( + browser(), tester.get(), GetWebAppParams(), + GetURLOfPageWithServiceWorkerAndManifest( + "/banners/manifest_display_override_display_is_browser.json")); + run_loop.Run(); + + EXPECT_FALSE(tester->manifest().IsEmpty()); + EXPECT_FALSE(tester->manifest_url().is_empty()); + ASSERT_EQ(1u, tester->manifest().display_override.size()); + EXPECT_EQ(blink::mojom::DisplayMode::kStandalone, + tester->manifest().display_override[0]); + + EXPECT_FALSE(tester->primary_icon_url().is_empty()); + EXPECT_NE(nullptr, tester->primary_icon()); + EXPECT_EQ(144, tester->primary_icon()->width()); + EXPECT_TRUE(tester->valid_manifest()); + EXPECT_TRUE(tester->has_worker()); + EXPECT_TRUE(tester->splash_icon_url().is_empty()); + EXPECT_EQ(nullptr, tester->splash_icon()); + EXPECT_EQ(std::vector<InstallableStatusCode>{}, tester->errors()); +}
diff --git a/chrome/browser/installable/installable_manager_unittest.cc b/chrome/browser/installable/installable_manager_unittest.cc index 6f40789b..803b8df 100644 --- a/chrome/browser/installable/installable_manager_unittest.cc +++ b/chrome/browser/installable/installable_manager_unittest.cc
@@ -5,7 +5,9 @@ #include "chrome/browser/installable/installable_manager.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" +#include "content/public/common/content_features.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h" @@ -327,3 +329,53 @@ EXPECT_TRUE(IsManifestValid(manifest)); EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); } + +class InstallableManagerUnitTest_DisplayOverride + : public InstallableManagerUnitTest { + public: + InstallableManagerUnitTest_DisplayOverride() { + scoped_feature_list_.InitAndEnableFeature( + features::kWebAppManifestDisplayOverride); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(InstallableManagerUnitTest_DisplayOverride, ManifestDisplayOverride) { + blink::Manifest manifest = GetValidManifest(); + + manifest.display_override.push_back(blink::mojom::DisplayMode::kMinimalUi); + EXPECT_TRUE(IsManifestValid(manifest)); + EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); + + manifest.display_override.push_back(blink::mojom::DisplayMode::kBrowser); + EXPECT_TRUE(IsManifestValid(manifest)); + EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); + + manifest.display_override.insert(manifest.display_override.begin(), + blink::mojom::DisplayMode::kStandalone); + EXPECT_TRUE(IsManifestValid(manifest)); + EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); + + manifest.display_override.insert(manifest.display_override.begin(), + blink::mojom::DisplayMode::kStandalone); + EXPECT_TRUE(IsManifestValid(manifest)); + EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); + + manifest.display_override.insert(manifest.display_override.begin(), + blink::mojom::DisplayMode::kBrowser); + EXPECT_TRUE( + IsManifestValid(manifest, false /* check_webapp_manifest_display */)); + EXPECT_FALSE(IsManifestValid(manifest)); + EXPECT_EQ(MANIFEST_DISPLAY_OVERRIDE_NOT_SUPPORTED, GetErrorCode()); +} + +TEST_F(InstallableManagerUnitTest_DisplayOverride, FallbackToBrowser) { + blink::Manifest manifest = GetValidManifest(); + + manifest.display = blink::mojom::DisplayMode::kBrowser; + manifest.display_override.push_back(blink::mojom::DisplayMode::kMinimalUi); + EXPECT_TRUE(IsManifestValid(manifest)); + EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); +}
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc index 0965aaf1..3bddb4d 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager.cc
@@ -13,6 +13,7 @@ #include "base/json/json_reader.h" #include "base/metrics/histogram_functions.h" #include "base/optional.h" +#include "base/strings/strcat.h" #include "chrome/browser/media/router/data_decoder_util.h" #include "chrome/browser/media/router/logger_impl.h" #include "chrome/browser/media/router/providers/cast/app_activity.h" @@ -116,9 +117,10 @@ mojom::MediaRouteProvider::CreateRouteCallback callback, data_decoder::DataDecoder::ValueOrError result) { if (!cast_source.app_params().empty() && result.error) { - logger_->LogError(mojom::LogCategory::kRoute, kLoggerComponent, - "Error parsing JSON data in appParams" + *result.error, - sink.id(), cast_source.source_id(), presentation_id); + logger_->LogError( + mojom::LogCategory::kRoute, kLoggerComponent, + base::StrCat({"Error parsing JSON data in appParams: ", *result.error}), + sink.id(), cast_source.source_id(), presentation_id); std::move(callback).Run( base::nullopt, nullptr, std::string("Invalid JSON Format of appParams"), RouteRequestResult::ResultCode::NO_SUPPORTED_PROVIDER); @@ -191,7 +193,7 @@ ? AddMirroringActivity(route, app_id, tab_id, sink.cast_data()) : AddAppActivity(route, app_id); const std::string& client_id = cast_source.client_id(); - if (!client_id.empty()) { + if (MediaSource(cast_source.source_id()).IsCastPresentationUrl()) { presentation_connection = activity_ptr->AddClient(cast_source, params.origin, tab_id); activity_ptr->SendMessageToClient( @@ -772,9 +774,18 @@ } if (response.result != cast_channel::LaunchSessionResponse::Result::kOk) { - logger_->LogError(mojom::LogCategory::kRoute, kLoggerComponent, - "Failed to launch session.", sink.id(), - cast_source.source_id(), + std::string message; + switch (response.result) { + case cast_channel::LaunchSessionResponse::Result::kTimedOut: + message = "Failed to launch session due to timeout."; + break; + default: + message = + base::StrCat({"Failed to launch session. ", response.error_msg}); + break; + } + logger_->LogError(mojom::LogCategory::kRoute, kLoggerComponent, message, + sink.id(), cast_source.source_id(), MediaRoute::GetPresentationIdFromMediaRouteId(route_id)); RemoveActivity(activity_it, PresentationConnectionState::CLOSED, PresentationConnectionCloseReason::CONNECTION_ERROR);
diff --git a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc index 828b195..430f2ee 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc +++ b/chrome/browser/media/router/providers/cast/cast_activity_manager_unittest.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/media/router/test/mock_logger.h" #include "chrome/browser/media/router/test/mock_mojo_media_router.h" #include "chrome/browser/media/router/test/test_helper.h" +#include "chrome/common/media_router/media_source.h" #include "chrome/common/media_router/test/test_helper.h" #include "components/cast_channel/cast_test_util.h" #include "content/public/browser/browser_task_traits.h" @@ -56,6 +57,7 @@ namespace { constexpr int kChannelId = 42; constexpr int kChannelId2 = 43; +constexpr char kClientId[] = "theClientId"; constexpr char kOrigin[] = "https://google.com"; constexpr int kTabId = 1; constexpr int kTabId2 = 2; @@ -76,9 +78,10 @@ constexpr char kPresentationId2[] = "presentationId2"; std::string MakeSourceId(const std::string& app_id = kAppId1, - const std::string& app_params = "") { + const std::string& app_params = "", + const std::string& client_id = kClientId) { return base::StrCat( - {"cast:", app_id, "?clientId=theClientId&appParams=", app_params}); + {"cast:", app_id, "?clientId=", client_id, "&appParams=", app_params}); } base::Value MakeReceiverStatus(const std::string& app_id, @@ -207,6 +210,7 @@ media_router::RouteRequestResult::ResultCode) { ASSERT_TRUE(route); route_ = std::make_unique<MediaRoute>(*route); + presentation_connections_ = std::move(presentation_connections); } void ExpectLaunchSessionFailure( @@ -219,7 +223,8 @@ } void CallLaunchSession(const std::string& app_id = kAppId1, - const std::string& app_params = "") { + const std::string& app_params = "", + const std::string& client_id = kClientId) { // MediaRouter is notified of new route. ExpectSingleRouteUpdate(); @@ -234,8 +239,8 @@ launch_session_callback_ = std::move(callback); })); - auto source = - CastMediaSource::FromMediaSourceId(MakeSourceId(app_id, app_params)); + auto source = CastMediaSource::FromMediaSourceId( + MakeSourceId(app_id, app_params, client_id)); ASSERT_TRUE(source); cast_activity_callback_ = @@ -403,6 +408,7 @@ base::Optional<MediaRoute> updated_route_; cast_channel::ResultCallback stop_session_callback_; MockLogger logger_; + mojom::RoutePresentationConnectionPtr presentation_connections_; }; TEST_F(CastActivityManagerTest, LaunchCastAppSession) { @@ -420,6 +426,14 @@ EXPECT_EQ(RouteControllerType::kMirroring, route_->controller_type()); } +TEST_F(CastActivityManagerTest, LaunchSiteInitiatedMirroringSession) { + // For a session initiated by a website with the mirroring source we should be + // establishing a presentation connection, even if the client ID isn't set. + CallLaunchSession(kCastStreamingAppId, /*app_params*/ "", /*client_id*/ ""); + EXPECT_FALSE(presentation_connections_.is_null()); + EXPECT_EQ(RouteControllerType::kMirroring, route_->controller_type()); +} + TEST_F(CastActivityManagerTest, MirroringSessionStopped) { CallLaunchSession(kCastStreamingAppId); auto response = GetSuccessLaunchResponse();
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity.cc b/chrome/browser/media/router/providers/cast/mirroring_activity.cc index 43669b1..f1d4ad1 100644 --- a/chrome/browser/media/router/providers/cast/mirroring_activity.cc +++ b/chrome/browser/media/router/providers/cast/mirroring_activity.cc
@@ -209,6 +209,16 @@ weak_ptr_factory_.GetWeakPtr(), route().media_route_id())); } +void MirroringActivity::SendMessageToClient( + const std::string& client_id, + blink::mojom::PresentationConnectionMessagePtr message) { + // A client exists if this is a site-initiated mirroring session. Given client + // ID is a Cast SDK concept, the client may not have an ID if it joined by + // directly using the Presentation API, and we wouldn't be able to distinguish + // them. We also do not expect the mirroring receiver to send any messages, so + // we drop them. +} + void MirroringActivity::OnAppMessage( const cast::channel::CastMessage& message) { if (!route_.is_local())
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity.h b/chrome/browser/media/router/providers/cast/mirroring_activity.h index 086c0e6..a6e7caa 100644 --- a/chrome/browser/media/router/providers/cast/mirroring_activity.h +++ b/chrome/browser/media/router/providers/cast/mirroring_activity.h
@@ -62,6 +62,9 @@ void Send(mirroring::mojom::CastMessagePtr message) override; // CastActivity implementation + void SendMessageToClient( + const std::string& client_id, + blink::mojom::PresentationConnectionMessagePtr message) override; void OnAppMessage(const cast::channel::CastMessage& message) override; void OnInternalMessage(const cast_channel::InternalMessage& message) override;
diff --git a/chrome/browser/nearby_sharing/BUILD.gn b/chrome/browser/nearby_sharing/BUILD.gn index 2dc5a81..e2e9d48 100644 --- a/chrome/browser/nearby_sharing/BUILD.gn +++ b/chrome/browser/nearby_sharing/BUILD.gn
@@ -4,6 +4,7 @@ source_set("share_target") { sources = [ + "attachment.cc", "attachment.h", "file_attachment.cc", "file_attachment.h",
diff --git a/chrome/browser/nearby_sharing/attachment.cc b/chrome/browser/nearby_sharing/attachment.cc new file mode 100644 index 0000000..e75814e --- /dev/null +++ b/chrome/browser/nearby_sharing/attachment.cc
@@ -0,0 +1,28 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/nearby_sharing/attachment.h" +#include "crypto/random.h" + +namespace { + +int64_t CreateRandomId() { + int64_t id; + crypto::RandBytes(&id, sizeof(id)); + return id; +} + +} // namespace + +Attachment::Attachment(Family family, int64_t size) + : id_(CreateRandomId()), family_(family), size_(size) {} + +Attachment::Attachment(int64_t id, Family family, int64_t size) + : id_(id), family_(family), size_(size) {} + +Attachment::Attachment(const Attachment&) = default; + +Attachment& Attachment::operator=(const Attachment&) = default; + +Attachment::~Attachment() = default;
diff --git a/chrome/browser/nearby_sharing/attachment.h b/chrome/browser/nearby_sharing/attachment.h index 007a496..eeec23ec 100644 --- a/chrome/browser/nearby_sharing/attachment.h +++ b/chrome/browser/nearby_sharing/attachment.h
@@ -7,23 +7,26 @@ #include <stdint.h> -#include "base/unguessable_token.h" - // A single attachment to be sent by / received from a ShareTarget, can be // either a file or text. class Attachment { public: enum class Family { kFile, kText, kMaxValue = kText }; - virtual ~Attachment() = default; + Attachment(Family family, int64_t size); + Attachment(int64_t id, Family family, int64_t size); + Attachment(const Attachment&); + Attachment& operator=(const Attachment&); + virtual ~Attachment(); - virtual int64_t size() const = 0; - virtual Family family() const = 0; - - const base::UnguessableToken& id() const { return id_; } + int64_t id() const { return id_; } + Family family() const { return family_; } + int64_t size() const { return size_; } private: - base::UnguessableToken id_ = base::UnguessableToken::Create(); + int64_t id_; + Family family_; + int64_t size_; }; #endif // CHROME_BROWSER_NEARBY_SHARING_ATTACHMENT_H_
diff --git a/chrome/browser/nearby_sharing/file_attachment.cc b/chrome/browser/nearby_sharing/file_attachment.cc index 1119145..996a52c 100644 --- a/chrome/browser/nearby_sharing/file_attachment.cc +++ b/chrome/browser/nearby_sharing/file_attachment.cc
@@ -11,20 +11,24 @@ int64_t size, base::Optional<base::FilePath> file_path, std::string mime_type) - : file_name_(std::move(file_name)), + : Attachment(Attachment::Family::kFile, size), + file_name_(std::move(file_name)), type_(type), - size_(size), file_path_(std::move(file_path)), mime_type_(std::move(mime_type)) {} -FileAttachment::~FileAttachment() = default; +FileAttachment::FileAttachment(int64_t id, + std::string file_name, + Type type, + int64_t size, + std::string mime_type) + : Attachment(id, Attachment::Family::kFile, size), + file_name_(std::move(file_name)), + type_(type), + mime_type_(std::move(mime_type)) {} + FileAttachment::FileAttachment(const FileAttachment&) = default; + FileAttachment& FileAttachment::operator=(const FileAttachment&) = default; -int64_t FileAttachment::size() const { - return size_; -} - -Attachment::Family FileAttachment::family() const { - return Attachment::Family::kFile; -} +FileAttachment::~FileAttachment() = default;
diff --git a/chrome/browser/nearby_sharing/file_attachment.h b/chrome/browser/nearby_sharing/file_attachment.h index 19590c7..8e18c84 100644 --- a/chrome/browser/nearby_sharing/file_attachment.h +++ b/chrome/browser/nearby_sharing/file_attachment.h
@@ -23,13 +23,14 @@ int64_t size, base::Optional<base::FilePath> file_path, std::string mime_type); - ~FileAttachment() override; + FileAttachment(int64_t id, + std::string file_name, + Type type, + int64_t size, + std::string mime_type); FileAttachment(const FileAttachment&); FileAttachment& operator=(const FileAttachment&); - - // Attachment: - int64_t size() const override; - Attachment::Family family() const override; + ~FileAttachment() override; const std::string& file_name() const { return file_name_; } Type type() const { return type_; } @@ -39,7 +40,6 @@ private: std::string file_name_; Type type_; - int64_t size_; base::Optional<base::FilePath> file_path_; std::string mime_type_; };
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc index 9c5f45047..6cb86b0 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc
@@ -38,7 +38,7 @@ } TextAttachment CreateTextAttachment(TextAttachment::Type type) { - return TextAttachment("text body", type, /*size=*/9); + return TextAttachment(type, "text body"); } FileAttachment CreateFileAttachment(FileAttachment::Type type) {
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 0bbd047..83cde104 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -1158,7 +1158,7 @@ // TODO(himanshujaju) - Implement payload tracker. - for (const auto& attachment_id : share_target.GetAttachmentIds()) { + for (int64_t attachment_id : share_target.GetAttachmentIds()) { base::Optional<int64_t> payload_id = GetAttachmentPayloadId(attachment_id); if (!payload_id) { NS_LOG(WARNING) << __func__ @@ -1386,8 +1386,8 @@ NS_LOG(VERBOSE) << __func__ << "Found file attachment " << file->name << " of type " << file->type << " with mimeType " << file->mime_type; - FileAttachment attachment(file->name, file->type, file->size, - /*file_path=*/base::nullopt, file->mime_type); + FileAttachment attachment(file->id, file->name, file->type, file->size, + file->mime_type); SetAttachmentPayloadId(attachment, file->payload_id); share_target.file_attachments.push_back(std::move(attachment)); } @@ -1403,7 +1403,8 @@ NS_LOG(VERBOSE) << __func__ << "Found text attachment " << text->text_title << " of type " << text->type; - TextAttachment attachment(text->text_title, text->type, text->size); + TextAttachment attachment(text->id, text->type, text->text_title, + text->size); SetAttachmentPayloadId(attachment, text->payload_id); share_target.text_attachments.push_back(std::move(attachment)); } @@ -1657,7 +1658,7 @@ } base::Optional<int64_t> NearbySharingServiceImpl::GetAttachmentPayloadId( - const base::UnguessableToken& attachment_id) { + int64_t attachment_id) { auto it = attachment_info_map_.find(attachment_id); if (it == attachment_info_map_.end()) return base::nullopt;
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h index 00063704..8274ee51 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_ #define CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_ +#include <stdint.h> #include <memory> #include <string> #include <utility> @@ -206,8 +207,7 @@ const std::string& endpoint_id); void ClearOutgoingShareTargetInfoMap(); void SetAttachmentPayloadId(const Attachment& attachment, int64_t payload_id); - base::Optional<int64_t> GetAttachmentPayloadId( - const base::UnguessableToken& attachment_id); + base::Optional<int64_t> GetAttachmentPayloadId(int64_t attachment_id); void UnregisterShareTarget(const ShareTarget& share_target); Profile* profile_; @@ -269,7 +269,7 @@ // A mapping of Attachment Id to additional AttachmentInfo related to the // Attachment. - base::flat_map<base::UnguessableToken, AttachmentInfo> attachment_info_map_; + base::flat_map<int64_t, AttachmentInfo> attachment_info_map_; // This alarm is used to disconnect the sharing connection if both sides do // not press accept within the timeout.
diff --git a/chrome/browser/nearby_sharing/share_target.cc b/chrome/browser/nearby_sharing/share_target.cc index b50cf26..2172cb7b 100644 --- a/chrome/browser/nearby_sharing/share_target.cc +++ b/chrome/browser/nearby_sharing/share_target.cc
@@ -37,14 +37,14 @@ ShareTarget::~ShareTarget() = default; -std::vector<base::UnguessableToken> ShareTarget::GetAttachmentIds() const { - std::vector<base::UnguessableToken> attachments; +std::vector<int64_t> ShareTarget::GetAttachmentIds() const { + std::vector<int64_t> attachment_ids; for (const auto& file : file_attachments) - attachments.push_back(file.id()); + attachment_ids.push_back(file.id()); for (const auto& text : text_attachments) - attachments.push_back(text.id()); + attachment_ids.push_back(text.id()); - return attachments; + return attachment_ids; }
diff --git a/chrome/browser/nearby_sharing/share_target.h b/chrome/browser/nearby_sharing/share_target.h index 8e3096c2..9945996 100644 --- a/chrome/browser/nearby_sharing/share_target.h +++ b/chrome/browser/nearby_sharing/share_target.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_NEARBY_SHARING_SHARE_TARGET_H_ #define CHROME_BROWSER_NEARBY_SHARING_SHARE_TARGET_H_ +#include <stdint.h> #include <string> #include <vector> @@ -38,7 +39,7 @@ return !text_attachments.empty() || !file_attachments.empty(); } - std::vector<base::UnguessableToken> GetAttachmentIds() const; + std::vector<int64_t> GetAttachmentIds() const; base::UnguessableToken id = base::UnguessableToken::Create(); std::string device_name;
diff --git a/chrome/browser/nearby_sharing/text_attachment.cc b/chrome/browser/nearby_sharing/text_attachment.cc index ab210fab..32988bd 100644 --- a/chrome/browser/nearby_sharing/text_attachment.cc +++ b/chrome/browser/nearby_sharing/text_attachment.cc
@@ -4,21 +4,40 @@ #include <utility> +#include "base/strings/strcat.h" #include "chrome/browser/nearby_sharing/text_attachment.h" -TextAttachment::TextAttachment(std::string text_body, Type type, int64_t size) - : text_body_(std::move(text_body)), type_(type), size_(size) {} +namespace { -TextAttachment::~TextAttachment() = default; +constexpr size_t kMaxPreviewTextLength = 32; + +std::string GetTextTitle(const std::string& text_body, + TextAttachment::Type type) { + // TODO(crbug.com/1085067): Improve title based on |type|. + if (text_body.size() > kMaxPreviewTextLength) + return base::StrCat({text_body.substr(0, kMaxPreviewTextLength), "…"}); + + return text_body; +} + +} // namespace + +TextAttachment::TextAttachment(Type type, std::string text_body) + : Attachment(Attachment::Family::kText, text_body.size()), + type_(type), + text_title_(GetTextTitle(text_body, type)), + text_body_(std::move(text_body)) {} + +TextAttachment::TextAttachment(int64_t id, + Type type, + std::string text_title, + int64_t size) + : Attachment(id, Attachment::Family::kText, size), + type_(type), + text_title_(std::move(text_title)) {} TextAttachment::TextAttachment(const TextAttachment&) = default; TextAttachment& TextAttachment::operator=(const TextAttachment&) = default; -int64_t TextAttachment::size() const { - return size_; -} - -Attachment::Family TextAttachment::family() const { - return Attachment::Family::kText; -} +TextAttachment::~TextAttachment() = default;
diff --git a/chrome/browser/nearby_sharing/text_attachment.h b/chrome/browser/nearby_sharing/text_attachment.h index 78ddacf..c5f7bf9b 100644 --- a/chrome/browser/nearby_sharing/text_attachment.h +++ b/chrome/browser/nearby_sharing/text_attachment.h
@@ -16,22 +16,20 @@ public: using Type = sharing::mojom::TextMetadata::Type; - TextAttachment(std::string text_body, Type type, int64_t size); - ~TextAttachment() override; + TextAttachment(Type type, std::string text_body); + TextAttachment(int64_t id, Type type, std::string text_title, int64_t size); TextAttachment(const TextAttachment&); TextAttachment& operator=(const TextAttachment&); - - // Attachment: - int64_t size() const override; - Attachment::Family family() const override; + ~TextAttachment() override; const std::string& text_body() const { return text_body_; } + const std::string& text_title() const { return text_title_; } Type type() const { return type_; } private: - std::string text_body_; Type type_; - int64_t size_; + std::string text_title_; + std::string text_body_; }; #endif // CHROME_BROWSER_NEARBY_SHARING_TEXT_ATTACHMENT_H_
diff --git a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java index 7beceeb..b630ffda 100644 --- a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java +++ b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java
@@ -27,6 +27,7 @@ import org.chromium.components.paintpreview.player.PlayerManager; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationHandle; +import org.chromium.content_public.browser.WebContents; import org.chromium.url.GURL; /** @@ -53,7 +54,7 @@ TabbedPaintPreviewPlayer.class; private static final int SNACKBAR_DURATION_MS = 8 * 1000; - private static final int DEFAULT_INITIAL_REMOVE_DELAY_MS = 400; + private static final int DEFAULT_INITIAL_REMOVE_DELAY_MS = 0; private static final String INITIAL_REMOVE_DELAY_PARAM = "initial_remove_delay_ms"; private Tab mTab; @@ -62,7 +63,7 @@ private Runnable mOnDismissed; private Boolean mInitializing; private boolean mHasUserInteraction; - private EmptyTabObserver mTabObserver; + private TabbedPaintPreviewObserver mObserver; private long mLastShownSnackBarTime; private boolean mDidStartRestore; private long mShownTime; @@ -75,70 +76,71 @@ return tab.getUserDataHost().getUserData(USER_DATA_KEY); } + class TabbedPaintPreviewObserver extends EmptyTabObserver { + public void onFirstMeaningfulPaint() { + if (!isShowingAndNeedsBadge()) return; + + long delayMs = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( + ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP, INITIAL_REMOVE_DELAY_PARAM, + DEFAULT_INITIAL_REMOVE_DELAY_MS); + // Delay removing paint preview after didFirstVisuallyNonEmptyPaint and no user + // interaction by |delayMs|. This is to account for 'heavy' pages that take a while + // to finish painting and avoid having flickers when switching from paint preview + // to the live page. + new Handler().postDelayed(() -> { + if (!isShowingAndNeedsBadge()) return; + + if (!mHasUserInteraction) { + removePaintPreview(ExitCause.TAB_FINISHED_LOADING); + return; + } + + showSnackbar(); + }, delayMs); + } + + @Override + public void onRestoreStarted(Tab tab) { + mDidStartRestore = true; + } + + @Override + public void onDidStartNavigation(Tab tab, NavigationHandle navigationHandle) { + if (mPlayerManager == null || !isShowingAndNeedsBadge()) return; + + // Ignore navigations from subframes. We should only remove the paint preview + // player when the user navigates to a new page. + if (!navigationHandle.isInMainFrame()) return; + + // If we haven't started to restore, this is the navigation call to start the + // restoration. We shouldn't remove the paint preview player. + if (!mDidStartRestore) return; + + removePaintPreview(ExitCause.NAVIGATION_STARTED); + } + } + private TabbedPaintPreviewPlayer(Tab tab) { mTab = tab; mPaintPreviewTabService = PaintPreviewTabServiceFactory.getServiceInstance(); - mTabObserver = new EmptyTabObserver() { - private boolean mFirstPaintHappened; - private boolean mPageLoadFinished; - @Override - public void didFirstVisuallyNonEmptyPaint(Tab tab) { - mFirstPaintHappened = true; - maybeRemovePaintPreview(); - } + mObserver = new TabbedPaintPreviewObserver(); + mTab.addObserver(mObserver); + } - @Override - public void onPageLoadFinished(Tab tab, String url) { - mPageLoadFinished = true; - maybeRemovePaintPreview(); - } + /** + * Triggered via {@link PageLoadMetrics.Observer} when First Meaningful Paint happens. + * @param webContents the webContents that triggered the event. + * @return Whether the event was handled for the provided webContents. + */ + public void onFirstMeaningfulPaint(WebContents webContents) { + // If there is no observer or tab this will never handle the event so it should be + // treated as a success. + if (mObserver == null || mTab == null) return; - private void maybeRemovePaintPreview() { - if (!isShowingAndNeedsBadge() || !mFirstPaintHappened || !mPageLoadFinished) return; + if (mTab.getWebContents() != webContents) return; - mFirstPaintHappened = false; - mPageLoadFinished = false; - long delayMs = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( - ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP, INITIAL_REMOVE_DELAY_PARAM, - DEFAULT_INITIAL_REMOVE_DELAY_MS); - // Delay removing paint preview after didFirstVisuallyNonEmptyPaint and no user - // interaction by |delayMs|. This is to account for 'heavy' pages that take a while - // to finish painting and avoid having flickers when switching from paint preview - // to the live page. - new Handler().postDelayed(() -> { - if (!isShowingAndNeedsBadge()) return; - - if (!mHasUserInteraction) { - removePaintPreview(ExitCause.TAB_FINISHED_LOADING); - return; - } - - showSnackbar(); - }, delayMs); - } - - @Override - public void onRestoreStarted(Tab tab) { - mDidStartRestore = true; - } - - @Override - public void onDidStartNavigation(Tab tab, NavigationHandle navigationHandle) { - if (mPlayerManager == null || !isShowingAndNeedsBadge()) return; - - // Ignore navigations from subframes. We should only remove the paint preview - // player when the user navigates to a new page. - if (!navigationHandle.isInMainFrame()) return; - - // If we haven't started to restore, this is the navigation call to start the - // restoration. We shouldn't remove the paint preview player. - if (!mDidStartRestore) return; - - removePaintPreview(ExitCause.NAVIGATION_STARTED); - } - }; - mTab.addObserver(mTabObserver); + mObserver.onFirstMeaningfulPaint(); } /** @@ -254,7 +256,7 @@ @Override public void destroy() { removePaintPreview(ExitCause.TAB_DESTROYED); - mTab.removeObserver(mTabObserver); + mTab.removeObserver(mObserver); mTab = null; } }
diff --git a/chrome/browser/password_check/android/BUILD.gn b/chrome/browser/password_check/android/BUILD.gn index 6a6b66a..4833287e 100644 --- a/chrome/browser/password_check/android/BUILD.gn +++ b/chrome/browser/password_check/android/BUILD.gn
@@ -55,7 +55,10 @@ } android_library("public_ui_java") { - deps = [] + deps = [ + "//base:base_java", + "//url:gurl_java", + ] sources = [ "java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java", "java/src/org/chromium/chrome/browser/password_check/PasswordCheckComponentUi.java", @@ -82,6 +85,7 @@ "//third_party/hamcrest:hamcrest_java", "//third_party/junit", "//ui/android:ui_full_java", + "//url:gurl_java", ] } @@ -123,6 +127,15 @@ "//third_party/mockito:mockito_java", "//ui/android:ui_full_java", "//ui/android:ui_utils_java", + "//url:gurl_java", + ] +} + +generate_jni("jni_headers") { + visibility = [ "//chrome/browser" ] + sources = [ + "internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java", + "java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java", ] }
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn index 05df26b..82b53e7 100644 --- a/chrome/browser/password_check/android/internal/BUILD.gn +++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -90,11 +90,6 @@ resources_package = "org.chromium.chrome.browser.password_check.internal" } -generate_jni("jni_headers") { - visibility = [ "//chrome/browser" ] - sources = [ "java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java" ] -} - android_resources("java_resources") { deps = [ ":java_strings_grd",
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java index be71c982..3ff351d 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckBridge.java
@@ -6,6 +6,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.NativeMethods; +import org.chromium.url.GURL; /** * Class handling the communication with the C++ part of the password check feature. It forwards @@ -21,13 +22,9 @@ interface PasswordCheckObserver { /** * Called when a new compromised credential is found by the password check - * @param originUrl Origin of the compromised credential. - * @param username Username for the compromised credential. - * @param password Password of the compromised credential. - * @param hasScript True iff a script can be applied to the compromised credential. + * @param credential The newly found compromised credential. */ - void onCompromisedCredentialFound( - String originUrl, String username, String password, boolean hasScript); + void onCompromisedCredentialFound(CompromisedCredential credential); /** * Called when the compromised credentials found in a previous check are read from disk. @@ -56,10 +53,14 @@ } // TODO(crbug.com/1102025): Add call from native. - void onCompromisedCredentialFound( - String originUrl, String username, String password, boolean hasScript) { - mPasswordCheckObserver.onCompromisedCredentialFound( - originUrl, username, password, hasScript); + void onCompromisedCredentialFound(String signonRealm, GURL origin, String username, + String displayOrigin, String displayUsername, String password, boolean hasScript) { + assert signonRealm != null; + assert displayOrigin != null; + assert username != null; + assert password != null; + mPasswordCheckObserver.onCompromisedCredentialFound(new CompromisedCredential(signonRealm, + origin, username, displayOrigin, displayUsername, password, false, hasScript)); } @CalledByNative @@ -79,10 +80,10 @@ @CalledByNative private static void insertCredential(CompromisedCredential[] credentials, int index, - String displayOrigin, String displayUsername, String password, boolean phished, - boolean hasScript) { - credentials[index] = new CompromisedCredential( - displayOrigin, displayUsername, password, phished, hasScript); + String signonRealm, GURL origin, String username, String displayOrigin, + String displayUsername, String password, boolean phished, boolean hasScript) { + credentials[index] = new CompromisedCredential(signonRealm, origin, username, displayOrigin, + displayUsername, password, phished, hasScript); } /**
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java index 1830a1b6..bd025f27 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java
@@ -86,7 +86,8 @@ if (mModel == null) { mModel = PasswordCheckProperties.createDefaultModel(); PasswordCheckCoordinator.setUpModelChangeProcessors(mModel, mFragmentView); - mMediator.initialize(mModel, PasswordCheckFactory.getOrCreate()); + mMediator.initialize( + mModel, PasswordCheckFactory.getOrCreate(), mFragmentView.getReferrer()); } } @@ -142,7 +143,7 @@ * @param credential A {@link CompromisedCredential} to be changed with a script. */ private void launchCctWithScript(CompromisedCredential credential) { - Intent intent = buildIntent(credential.getOriginUrl()); + Intent intent = buildIntent(credential.getOrigin().getSpec()); populateAutofillAssistantExtras(intent, credential.getUsername()); IntentUtils.safeStartActivity(mFragmentView.getActivity(), intent); }
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java index 1131862f..b5a576e 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java
@@ -21,6 +21,7 @@ private boolean mCompromisedCredentialsFetched; private boolean mSavedPasswordsFetched; + private @PasswordCheckUIStatus int mStatus = PasswordCheckUIStatus.IDLE; PasswordCheckImpl() { mCompromisedCredentialsFetched = false; @@ -36,7 +37,6 @@ fragmentArgs.putInt( PasswordCheckFragmentView.PASSWORD_CHECK_REFERRER, passwordCheckReferrer); launcher.launchSettingsActivity(context, PasswordCheckFragmentView.class, fragmentArgs); - if (passwordCheckReferrer != PasswordCheckReferrer.SAFETY_CHECK) startCheck(); } @Override @@ -45,11 +45,8 @@ } @Override - public void onCompromisedCredentialFound( - String originUrl, String username, String password, boolean hasScript) { - for (Observer obs : mObserverList) { - obs.onCompromisedCredentialFound(originUrl, username, password, hasScript); - } + public void onCompromisedCredentialFound(CompromisedCredential credential) { + for (Observer obs : mObserverList) obs.onCompromisedCredentialFound(credential); } @Override @@ -69,7 +66,8 @@ } @Override - public void onPasswordCheckStatusChanged(int status) { + public void onPasswordCheckStatusChanged(@PasswordCheckUIStatus int status) { + mStatus = status; for (Observer obs : mObserverList) { obs.onPasswordCheckStatusChanged(status); } @@ -102,6 +100,11 @@ } @Override + public @PasswordCheckUIStatus int getCheckStatus() { + return mStatus; + } + + @Override public int getCompromisedCredentialsCount() { return mPasswordCheckBridge.getCompromisedCredentialsCount(); }
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java index 13a68b4..245506b 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java
@@ -43,21 +43,18 @@ this.mLaunchCctWithScript = launchCctWithScript; } - void initialize(PropertyModel model, PasswordCheckComponentUi.Delegate delegate) { + void initialize(PropertyModel model, PasswordCheckComponentUi.Delegate delegate, + @PasswordCheckReferrer int passwordCheckReferrer) { mModel = model; mDelegate = delegate; - ListModel<ListItem> items = mModel.get(ITEMS); - assert items.size() == 0; - items.add(new ListItem(PasswordCheckProperties.ItemType.HEADER, - new PropertyModel.Builder(PasswordCheckProperties.HeaderProperties.ALL_KEYS) - .with(CHECK_PROGRESS, UNKNOWN_PROGRESS) - .with(CHECK_STATUS, PasswordCheckUIStatus.RUNNING) - .with(CHECK_TIMESTAMP, null) - .with(COMPROMISED_CREDENTIALS_COUNT, null) - .with(RESTART_BUTTON_ACTION, this::runCheck) - .build())); + // If a run is scheduled to happen soon, initialize the UI as running to prevent flickering. + // Otherwise, initialize the UI with last known state (defaults to IDLE before first run). + boolean shouldRunCheck = passwordCheckReferrer != PasswordCheckReferrer.SAFETY_CHECK; + onPasswordCheckStatusChanged(shouldRunCheck ? PasswordCheckUIStatus.RUNNING + : getPasswordCheck().getCheckStatus()); getPasswordCheck().addObserver(this, true); + if (shouldRunCheck) getPasswordCheck().startCheck(); } void destroy() { @@ -76,6 +73,7 @@ .with(RESTART_BUTTON_ACTION, this::runCheck) .build())); } + if (items.size() > 1) items.removeRange(1, items.size() - 1); for (CompromisedCredential credential : credentials) { items.add(new ListItem(credential.hasScript() @@ -96,9 +94,18 @@ @Override public void onPasswordCheckStatusChanged(@PasswordCheckUIStatus int status) { ListModel<ListItem> items = mModel.get(ITEMS); - assert items.size() >= 1; - - PropertyModel header = items.get(0).model; + PropertyModel header; + if (items.size() == 0) { + header = new PropertyModel.Builder(PasswordCheckProperties.HeaderProperties.ALL_KEYS) + .with(CHECK_PROGRESS, UNKNOWN_PROGRESS) + .with(CHECK_STATUS, PasswordCheckUIStatus.RUNNING) + .with(CHECK_TIMESTAMP, null) + .with(COMPROMISED_CREDENTIALS_COUNT, null) + .with(RESTART_BUTTON_ACTION, this::runCheck) + .build(); + } else { + header = items.get(0).model; + } header.set(CHECK_STATUS, status); header.set( CHECK_PROGRESS, status == PasswordCheckUIStatus.RUNNING ? UNKNOWN_PROGRESS : null); @@ -110,6 +117,10 @@ } header.set(CHECK_TIMESTAMP, checkTimestamp); header.set(COMPROMISED_CREDENTIALS_COUNT, compromisedCredentialCount); + + if (items.size() == 0) { + items.add(new ListItem(PasswordCheckProperties.ItemType.HEADER, header)); + } } void onPasswordCheckProgressChanged(Pair<Integer, Integer> progress) { @@ -126,22 +137,16 @@ } @Override - public void onCompromisedCredentialFound( - String originUrl, String username, String password, boolean hasScript) { - assert originUrl != null; - assert username != null; - assert password != null; + public void onCompromisedCredentialFound(CompromisedCredential leakedCredential) { + assert leakedCredential != null; ListModel<ListItem> items = mModel.get(ITEMS); assert items.size() >= 1 : "Needs to initialize list with header before adding items!"; - - CompromisedCredential credential = - new CompromisedCredential(originUrl, username, password, false, hasScript); - items.add(new ListItem(credential.hasScript() + items.add(new ListItem(leakedCredential.hasScript() ? PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL_WITH_SCRIPT : PasswordCheckProperties.ItemType.COMPROMISED_CREDENTIAL, new PropertyModel .Builder(PasswordCheckProperties.CompromisedCredentialProperties.ALL_KEYS) - .with(COMPROMISED_CREDENTIAL, credential) + .with(COMPROMISED_CREDENTIAL, leakedCredential) .with(CREDENTIAL_HANDLER, this) .build())); } @@ -153,7 +158,7 @@ @Override public void onRemove(CompromisedCredential credential) { - mModel.set(DELETION_ORIGIN, credential.getOriginUrl()); + mModel.set(DELETION_ORIGIN, credential.getDisplayOrigin()); mModel.set( DELETION_CONFIRMATION_HANDLER, new PasswordCheckDeletionDialogFragment.Handler() { @Override @@ -173,7 +178,7 @@ @Override public void onChangePasswordButtonClick(CompromisedCredential credential) { - mLaunchCctWithChangePasswordUrl.accept(credential.getOriginUrl()); + mLaunchCctWithChangePasswordUrl.accept(credential.getSignonRealm()); } @Override
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java index 39691e4..176ca85 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java
@@ -15,7 +15,6 @@ import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.RESTART_BUTTON_ACTION; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.HeaderProperties.UNKNOWN_PROGRESS; import static org.chromium.chrome.browser.password_check.PasswordCheckProperties.ITEMS; -import static org.chromium.components.embedder_support.util.UrlUtilities.stripScheme; import android.content.Context; import android.content.res.Resources; @@ -64,6 +63,7 @@ PasswordCheckViewBinder::connectPropertyModel), PasswordCheckViewBinder::createViewHolder)); } else if (propertyKey == DELETION_CONFIRMATION_HANDLER) { + if (model.get(DELETION_CONFIRMATION_HANDLER) == null) return; // Initial or onDismiss. view.showDialogFragment(new PasswordCheckDeletionDialogFragment( model.get(DELETION_CONFIRMATION_HANDLER), model.get(DELETION_ORIGIN))); } else if (propertyKey == DELETION_ORIGIN) { @@ -122,14 +122,11 @@ PropertyModel model, View view, PropertyKey propertyKey) { CompromisedCredential credential = model.get(COMPROMISED_CREDENTIAL); if (propertyKey == COMPROMISED_CREDENTIAL) { - TextView pslOriginText = view.findViewById(R.id.credential_origin); - String formattedOrigin = stripScheme(credential.getOriginUrl()); - formattedOrigin = - formattedOrigin.replaceFirst("/$", ""); // Strip possibly trailing slash. - pslOriginText.setText(formattedOrigin); + TextView originText = view.findViewById(R.id.credential_origin); + originText.setText(credential.getDisplayOrigin()); TextView username = view.findViewById(R.id.compromised_username); - username.setText(credential.getUsername()); + username.setText(credential.getDisplayUsername()); TextView reason = view.findViewById(R.id.compromised_reason); reason.setText(credential.isPhished()
diff --git a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java index 0b0e060..8ae10f3 100644 --- a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java +++ b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/CompromisedCredential.java
@@ -4,6 +4,9 @@ package org.chromium.chrome.browser.password_check; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.url.GURL; + import java.util.Objects; /** @@ -11,35 +14,63 @@ * settings screen. */ public class CompromisedCredential { + private final String mSignonRealm; + private final GURL mOrigin; private final String mUsername; + private final String mDisplayOrigin; + private final String mDisplayUsername; private final String mPassword; - private final String mOriginUrl; private final boolean mPhished; private final boolean mHasScript; /** - * @param username Username shown to the user. - * @param originUrl Origin URL shown to the user in case this credential is a PSL match. + * @param signonRealm The URL leading to the sign-on page. + * @param origin The origin used to identify this credential (may be empty). + * @param username The name used to identify this credential (may be empty). + * @param displayOrigin The origin displayed to the user. Not necessarily a valid URL (e.g. + * missing scheme). + * @param displayUsername The username displayed to the user (substituted if empty). + * @param password The compromised password. + * @param phished True iff the credential was entered on an unsafe site. + * @param hasScript True iff the credential can be automatically fixed. */ - public CompromisedCredential(String originUrl, String username, String password, - boolean phished, boolean hasScript) { - assert originUrl != null : "Credential origin is null! Pass an empty one instead."; - mOriginUrl = originUrl; + public CompromisedCredential(String signonRealm, GURL origin, String username, + String displayOrigin, String displayUsername, String password, boolean phished, + boolean hasScript) { + assert origin != null : "Credential origin is null! Pass an empty one instead."; + assert signonRealm != null; + mSignonRealm = signonRealm; + mOrigin = origin; mUsername = username; + mDisplayOrigin = displayOrigin; + mDisplayUsername = displayUsername; mPassword = password; mPhished = phished; mHasScript = hasScript; } - public String getOriginUrl() { - return mOriginUrl; + @CalledByNative + public String getSignonRealm() { + return mSignonRealm; } + @CalledByNative public String getUsername() { return mUsername; } + @CalledByNative + public GURL getOrigin() { + return mOrigin; + } + @CalledByNative public String getPassword() { return mPassword; } + public String getDisplayUsername() { + return mDisplayUsername; + } + public String getDisplayOrigin() { + return mDisplayOrigin; + } public boolean isPhished() { return mPhished; } @@ -52,21 +83,25 @@ if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CompromisedCredential that = (CompromisedCredential) o; - return mPhished == that.mPhished && mHasScript == that.mHasScript - && mUsername.equals(that.mUsername) && mPassword.equals(that.mPassword) - && mOriginUrl.equals(that.mOriginUrl); + return mSignonRealm.equals(that.mSignonRealm) && mOrigin.equals(that.mOrigin) + && mUsername.equals(that.mUsername) && mDisplayOrigin.equals(that.mDisplayOrigin) + && mDisplayUsername.equals(that.mDisplayUsername) + && mPassword.equals(that.mPassword) && mPhished == that.mPhished + && mHasScript == that.mHasScript; } @Override public String toString() { return "CompromisedCredential{" - + "username='" + mUsername + '\'' + ", password='" + mPassword + '\'' - + ", originUrl='" + mOriginUrl + '\'' + ", phished=" + mPhished - + ", hasScript=" + mHasScript + '}'; + + "signonRealm='" + mSignonRealm + ", origin='" + mOrigin + '\'' + '\'' + + ", username='" + mUsername + '\'' + ", displayOrigin='" + mDisplayOrigin + '\'' + + ", displayUsername='" + mDisplayUsername + '\'' + ", password='" + mPassword + + '\'' + ", phished=" + mPhished + ", hasScript=" + mHasScript + '}'; } @Override public int hashCode() { - return Objects.hash(mUsername, mPassword, mOriginUrl, mPhished, mHasScript); + return Objects.hash(mSignonRealm, mOrigin, mUsername, mDisplayOrigin, mDisplayUsername, + mPassword, mPhished, mHasScript); } }
diff --git a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java index 62c346c6..b209868 100644 --- a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java +++ b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheck.java
@@ -33,14 +33,10 @@ void onPasswordCheckStatusChanged(@PasswordCheckUIStatus int status); /** - * Invoked whenever a running check finds another compromised credential. - * @param originUrl The origin of the newly found compromised credential. - * @param username The username of the newly found compromised credential. - * @param password The password of the newly found compromised credential. - * @param hasScript True iff a script can be applied to the newly found credential. + * Invoked whenever a running check finds another leaked credential. + * @param leakedCredential The newly found leaked credential. */ - void onCompromisedCredentialFound( - String originUrl, String username, String password, boolean hasScript); + void onCompromisedCredentialFound(CompromisedCredential leakedCredential); } /** @@ -76,6 +72,12 @@ long getCheckTimestamp(); /** + * @return The last known status of the check. + */ + @PasswordCheckUIStatus + int getCheckStatus(); + + /** * @return The latest available number of compromised passwords. If this is invoked before * {@link Observer#onCompromisedCredentialsFetchCompleted}, the returned value is likely * invalid.
diff --git a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java index 616855f..0efc013c 100644 --- a/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java +++ b/chrome/browser/password_check/android/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFragmentView.java
@@ -80,4 +80,9 @@ if (passwordCheckDeletionDialogFragment == null) return; passwordCheckDeletionDialogFragment.show(getParentFragmentManager(), null); } + + @PasswordCheckReferrer + int getReferrer() { + return mPasswordCheckReferrer; + } }
diff --git a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java index 0291d75..3558f14d 100644 --- a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java +++ b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckViewTest.java
@@ -83,6 +83,7 @@ import org.chromium.ui.modelutil.MVCListAdapter; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.widget.ButtonCompat; +import org.chromium.url.GURL; /** * View tests for the Password Check component ensure model changes are reflected in the check UI. @@ -90,14 +91,18 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class PasswordCheckViewTest { - private static final CompromisedCredential ANA = - new CompromisedCredential("some-url.com", "Ana", "password", false, false); + private static final CompromisedCredential ANA = new CompromisedCredential( + "https://some-url.com/signin", new GURL("https://some-url.com/"), "Ana", "some-url.com", + "Ana", "password", false, false); private static final CompromisedCredential PHISHED = - new CompromisedCredential("example.com", "Baub", "DoSomething", true, false); - private static final CompromisedCredential LEAKED = - new CompromisedCredential("some-other-url.com", "AZiegler", "N0M3rcy", false, false); + new CompromisedCredential("http://example.com/signin", new GURL("http://example.com/"), + "", "http://example.com", "(No username)", "DoSomething", true, false); + private static final CompromisedCredential LEAKED = new CompromisedCredential( + "https://some-other-url.com/signin", new GURL("https://some-other-url.com/"), + "AZiegler", "some-other-url.com", "AZiegler", "N0M3rcy", false, false); private static final CompromisedCredential SCRIPTED = - new CompromisedCredential("script.com", "Charlie", "secret", false, true); + new CompromisedCredential("https://script.com/signin", new GURL("https://script.com/"), + "Charlie", "script.com", "Charlie", "secret", false, true); private static final int LEAKS_COUNT = 2; @@ -393,14 +398,14 @@ waitForListViewToHaveLength(2); // The phished credential is rendered first: - assertThat(getCredentialOriginAt(0).getText(), is(PHISHED.getOriginUrl())); - assertThat(getCredentialUserAt(0).getText(), is(PHISHED.getUsername())); + assertThat(getCredentialOriginAt(0).getText(), is(PHISHED.getDisplayOrigin())); + assertThat(getCredentialUserAt(0).getText(), is(PHISHED.getDisplayUsername())); assertThat(getCredentialReasonAt(0).getText(), is(getString(R.string.password_check_credential_row_reason_phished))); // The leaked credential is rendered second: - assertThat(getCredentialOriginAt(1).getText(), is(LEAKED.getOriginUrl())); - assertThat(getCredentialUserAt(1).getText(), is(LEAKED.getUsername())); + assertThat(getCredentialOriginAt(1).getText(), is(LEAKED.getDisplayOrigin())); + assertThat(getCredentialUserAt(1).getText(), is(LEAKED.getDisplayUsername())); assertThat(getCredentialReasonAt(1).getText(), is(getString(R.string.password_check_credential_row_reason_leaked))); } @@ -412,8 +417,8 @@ pollUiThread(() -> Criteria.checkThat(getPasswordCheckViewList().getChildCount(), is(1))); // Origin and username. - assertThat(getCredentialOriginAt(0).getText(), is(SCRIPTED.getOriginUrl())); - assertThat(getCredentialUserAt(0).getText(), is(SCRIPTED.getUsername())); + assertThat(getCredentialOriginAt(0).getText(), is(SCRIPTED.getDisplayOrigin())); + assertThat(getCredentialUserAt(0).getText(), is(SCRIPTED.getDisplayUsername())); // Reason to show credential. assertThat(getCredentialReasonAt(0).getText(), @@ -509,7 +514,7 @@ public void testConfirmingDeletionDialogTriggersHandler() { PasswordCheckDeletionDialogFragment.Handler mockHandler = mock(PasswordCheckDeletionDialogFragment.Handler.class); - mModel.set(DELETION_ORIGIN, ANA.getOriginUrl()); + mModel.set(DELETION_ORIGIN, ANA.getDisplayOrigin()); runOnUiThreadBlocking(() -> mModel.set(DELETION_CONFIRMATION_HANDLER, mockHandler)); onView(withText(R.string.password_check_delete_credential_dialog_confirm))
diff --git a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java index 79f305b..683f5b6 100644 --- a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java +++ b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
@@ -10,7 +10,9 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -50,6 +52,7 @@ import org.chromium.ui.modelutil.ListModel; import org.chromium.ui.modelutil.MVCListAdapter; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.url.GURL; /** * Controller tests verify that the PasswordCheck controller modifies the model if the API is used @@ -59,9 +62,11 @@ @EnableFeatures(ChromeFeatureList.PASSWORD_CHECK) public class PasswordCheckControllerTest { private static final CompromisedCredential ANA = - new CompromisedCredential("https://m.a.xyz/", "Ana", "password", false, false); + new CompromisedCredential("https://m.a.xyz/signin", mock(GURL.class), "Ana", "m.a.xyz", + "Ana", "password", false, false); private static final CompromisedCredential BOB = - new CompromisedCredential("https://www.b.ch/", "Baub", "DoneSth", false, true); + new CompromisedCredential("http://www.b.ch/signin", mock(GURL.class), "", + "http://www.b.ch", "(No username)", "DoneSth", false, true); @Rule public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); @@ -88,7 +93,7 @@ mMediator = new PasswordCheckMediator( mLaunchCctWithChangePasswordUrlConsumer, mLaunchCctWithScriptConsumer); PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck); - mMediator.initialize(mModel, mDelegate); + mMediator.initialize(mModel, mDelegate, PasswordCheckReferrer.PASSWORD_SETTINGS); } @Test @@ -104,8 +109,18 @@ } @Test - public void testInitializeRunningHeader() { + public void testInitializeRunningHeaderAndTriggerRunAsSoonAsPossible() { assertRunningHeader(mModel.get(ITEMS).get(0), UNKNOWN_PROGRESS); + verify(mPasswordCheck).startCheck(); + } + + @Test + public void testInitializeHeaderWithLastStatusWhenComingFromSafetyCheck() { + clearInvocations(mPasswordCheck); // Clear invocations from setup code. + when(mPasswordCheck.getCheckStatus()).thenReturn(PasswordCheckUIStatus.IDLE); + mMediator.initialize(mModel, mDelegate, PasswordCheckReferrer.SAFETY_CHECK); + assertIdleHeader(mModel.get(ITEMS).get(0)); + verify(mPasswordCheck, never()).startCheck(); } @Test @@ -167,8 +182,7 @@ mMediator.onCompromisedCredentialsFetchCompleted(); assertThat(mModel.get(ITEMS).size(), is(2)); // Header + existing credentials. - mMediator.onCompromisedCredentialFound( - BOB.getOriginUrl(), BOB.getUsername(), BOB.getPassword(), BOB.hasScript()); + mMediator.onCompromisedCredentialFound(BOB); assertThat(mModel.get(ITEMS).get(2).type, is(ItemType.COMPROMISED_CREDENTIAL_WITH_SCRIPT)); assertThat(mModel.get(ITEMS).get(2).model.get(COMPROMISED_CREDENTIAL), equalTo(BOB)); @@ -176,6 +190,26 @@ } @Test + public void testReplacesEntriesForUpdateOfEntireList() { + mMediator.onPasswordCheckStatusChanged(IDLE); + + // First call adds only ANA. + when(mPasswordCheck.getCompromisedCredentials()) + .thenReturn(new CompromisedCredential[] {ANA}); + mMediator.onCompromisedCredentialsFetchCompleted(); + assertThat(mModel.get(ITEMS).size(), is(2)); // Header + existing credentials. + + // Second call adds BOB and removes ANA. + when(mPasswordCheck.getCompromisedCredentials()) + .thenReturn(new CompromisedCredential[] {BOB}); + mMediator.onCompromisedCredentialsFetchCompleted(); + assertThat(mModel.get(ITEMS).size(), is(2)); + assertThat(mModel.get(ITEMS).get(1).type, is(ItemType.COMPROMISED_CREDENTIAL_WITH_SCRIPT)); + assertThat(mModel.get(ITEMS).get(1).model.get(COMPROMISED_CREDENTIAL), equalTo(BOB)); + assertThat(mModel.get(ITEMS).get(1).model.get(CREDENTIAL_HANDLER), is(mMediator)); + } + + @Test public void testRemovingElementTriggersDelegate() { // Removing sets a valid handler: mMediator.onRemove(ANA); @@ -191,7 +225,7 @@ @Test public void testOnChangePasswordButtonClick() { mMediator.onChangePasswordButtonClick(ANA); - verify(mLaunchCctWithChangePasswordUrlConsumer).accept(eq(ANA.getOriginUrl())); + verify(mLaunchCctWithChangePasswordUrlConsumer).accept(eq(ANA.getSignonRealm())); } @Test
diff --git a/chrome/browser/password_check/android/password_check_bridge.cc b/chrome/browser/password_check/android/password_check_bridge.cc index 1d3e7c0..4bcbd54 100644 --- a/chrome/browser/password_check/android/password_check_bridge.cc +++ b/chrome/browser/password_check/android/password_check_bridge.cc
@@ -7,10 +7,30 @@ #include <jni.h> #include "base/android/jni_string.h" -#include "chrome/browser/password_check/android/internal/jni_headers/PasswordCheckBridge_jni.h" +#include "chrome/browser/password_check/android/jni_headers/CompromisedCredential_jni.h" +#include "chrome/browser/password_check/android/jni_headers/PasswordCheckBridge_jni.h" +#include "chrome/browser/profiles/profile_manager.h" #include "components/password_manager/core/browser/ui/compromised_credentials_manager.h" #include "url/android/gurl_android.h" +namespace { + +password_manager::CredentialView ConvertJavaObjectToCredentialView( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& credential) { + return password_manager::CredentialView( + ConvertJavaStringToUTF8( + env, Java_CompromisedCredential_getSignonRealm(env, credential)), + *url::GURLAndroid::ToNativeGURL( + env, Java_CompromisedCredential_getOrigin(env, credential)), + ConvertJavaStringToUTF16( + env, Java_CompromisedCredential_getUsername(env, credential)), + ConvertJavaStringToUTF16( + env, Java_CompromisedCredential_getPassword(env, credential))); +} + +} // namespace + static jlong JNI_PasswordCheckBridge_Create( JNIEnv* env, const base::android::JavaParamRef<jobject>& java_bridge) { @@ -49,6 +69,9 @@ const auto& credential = credentials[i]; Java_PasswordCheckBridge_insertCredential( env, java_credentials, i, + base::android::ConvertUTF8ToJavaString(env, credential.signon_realm), + url::GURLAndroid::FromNativeGURL(env, credential.url), + base::android::ConvertUTF16ToJavaString(env, credential.username), base::android::ConvertUTF16ToJavaString(env, credential.display_origin), base::android::ConvertUTF16ToJavaString(env, credential.display_username), @@ -62,7 +85,8 @@ void PasswordCheckBridge::RemoveCredential( JNIEnv* env, const base::android::JavaParamRef<jobject>& credential) { - // TODO(crbug.com/1108358): implement this. + check_manager_.RemoveCredential( + ConvertJavaObjectToCredentialView(env, credential)); } void PasswordCheckBridge::Destroy(JNIEnv* env) {
diff --git a/chrome/browser/password_check/android/password_check_manager.cc b/chrome/browser/password_check/android/password_check_manager.cc index 53dd234..29e1e01 100644 --- a/chrome/browser/password_check/android/password_check_manager.cc +++ b/chrome/browser/password_check/android/password_check_manager.cc
@@ -106,6 +106,11 @@ return ui_credentials; } +void PasswordCheckManager::RemoveCredential( + const password_manager::CredentialView& credential) { + compromised_credentials_manager_.RemoveCompromisedCredential(credential); +} + void PasswordCheckManager::OnSavedPasswordsChanged( password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords) { if (!is_initialized_) {
diff --git a/chrome/browser/password_check/android/password_check_manager.h b/chrome/browser/password_check/android/password_check_manager.h index 2ec6e95..cc3e7bf 100644 --- a/chrome/browser/password_check/android/password_check_manager.h +++ b/chrome/browser/password_check/android/password_check_manager.h
@@ -70,6 +70,10 @@ // Called by java to retrieve the compromised credentials. std::vector<CompromisedCredentialForUI> GetCompromisedCredentials() const; + // Called by java to remove the given compromised |credential| and trigger a + // UI update on completion. + void RemoveCredential(const password_manager::CredentialView& credential); + // Not copyable or movable PasswordCheckManager(const PasswordCheckManager&) = delete; PasswordCheckManager& operator=(const PasswordCheckManager&) = delete;
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index 8abe1e4..48075506 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -9,6 +9,29 @@ "//base:base_java", "//chrome/browser/settings:java", "//components/password_manager/core/browser:password_manager_java_enums", + "//third_party/android_deps:androidx_annotation_annotation_java", + "//third_party/android_deps:androidx_fragment_fragment_java", ] - sources = [ "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java" ] + sources = [ + "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java", + "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragment.java", + "java/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManager.java", + ] +} + +junit_binary("password_manager_junit_tests") { + testonly = true + + sources = [ + "junit/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragmentTest.java", + "junit/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManagerTest.java", + ] + + deps = [ + ":java", + "//base:base_junit_test_support", + "//chrome/test/android:chrome_java_test_support", + "//third_party/android_deps:androidx_fragment_fragment_java", + "//third_party/junit", + ] }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragment.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragment.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragment.java rename to chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragment.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManager.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManager.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManager.java rename to chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManager.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragmentTest.java b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragmentTest.java similarity index 100% rename from chrome/android/junit/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragmentTest.java rename to chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragmentTest.java
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManagerTest.java b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManagerTest.java similarity index 100% rename from chrome/android/junit/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManagerTest.java rename to chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManagerTest.java
diff --git a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc index 8a1423d..8f898f6 100644 --- a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc +++ b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc
@@ -535,6 +535,7 @@ #define MAYBE_Test Test #endif IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementEnrollmentTest, MAYBE_Test) { +#undef MAYBE_Test // Test body is run only if enrollment is succeeded or failed without error // message. EXPECT_TRUE(is_enrollment_token_valid() || !should_display_error_message()); @@ -789,7 +790,13 @@ network::TestURLLoaderFactory test_url_loader_factory_; }; // namespace policy -IN_PROC_BROWSER_TEST_F(MachineLevelUserCloudPolicyRobotAuthTest, Test) { +// Flaky on linux & win: https://crbug.com/1105167 +#if defined(OS_WIN) || defined(OS_LINUX) +#define MAYBE_Test DISABLED_Test +#else +#define MAYBE_Test Test +#endif +IN_PROC_BROWSER_TEST_F(MachineLevelUserCloudPolicyRobotAuthTest, MAYBE_Test) { MachineLevelUserCloudPolicyManager* manager = g_browser_process->browser_policy_connector() ->machine_level_user_cloud_policy_manager();
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc index d5f43f6..45e73e6 100644 --- a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc +++ b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.cc
@@ -134,6 +134,8 @@ void QuickAnswersMenuObserver::OnContextMenuShown( const content::ContextMenuParams& params, const gfx::Rect& bounds_in_screen) { + is_context_menu_showing_ = true; + if (!IsRichUiEnabled()) return; @@ -163,12 +165,14 @@ void QuickAnswersMenuObserver::OnContextMenuViewBoundsChanged( const gfx::Rect& bounds_in_screen) { bounds_in_screen_ = bounds_in_screen; - if (!quick_answers_controller_) + if (!quick_answers_controller_ || !is_context_menu_showing_) return; quick_answers_controller_->UpdateQuickAnswersAnchorBounds(bounds_in_screen); } void QuickAnswersMenuObserver::OnMenuClosed() { + is_context_menu_showing_ = false; + if (!IsRichUiEnabled()) return; @@ -268,6 +272,9 @@ const base::string16& surrounding_text, uint32_t start_offset, uint32_t end_offset) { + if (!is_context_menu_showing_) + return; + Context context; context.surrounding_text = base::UTF16ToUTF8(surrounding_text); context.device_properties.language = GetDeviceLanguage();
diff --git a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h index 1009fc2..45592f9ee 100644 --- a/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h +++ b/chrome/browser/renderer_context_menu/quick_answers_menu_observer.h
@@ -84,6 +84,11 @@ // Whether commands other than quick answers is executed. bool is_other_command_executed_ = false; + // Whether the context menu is currently showing. + // TODO(updowndota): Instead of adding flags to check the callback, add a + // global quick answers state in the client to guard the sequence. + bool is_context_menu_showing_ = false; + base::WeakPtrFactory<QuickAnswersMenuObserver> weak_factory_{this}; };
diff --git a/chrome/browser/reputation/safety_tip_test_utils.cc b/chrome/browser/reputation/safety_tip_test_utils.cc index 4a1061b..83837e3 100644 --- a/chrome/browser/reputation/safety_tip_test_utils.cc +++ b/chrome/browser/reputation/safety_tip_test_utils.cc
@@ -74,3 +74,7 @@ } SetSafetyTipsRemoteConfigProto(std::move(config_proto)); } + +void InitializeBlankLookalikeAllowlistForTesting() { + SetSafetyTipAllowlistPatterns({}, {}); +}
diff --git a/chrome/browser/reputation/safety_tip_test_utils.h b/chrome/browser/reputation/safety_tip_test_utils.h index cc7179b..7077950 100644 --- a/chrome/browser/reputation/safety_tip_test_utils.h +++ b/chrome/browser/reputation/safety_tip_test_utils.h
@@ -32,4 +32,10 @@ void SetSafetyTipAllowlistPatterns(std::vector<std::string> patterns, std::vector<std::string> target_patterns); +// Ensure that the allowlist has been initialized. This is important as some +// code (e.g. the elision policy) is fail-open (i.e. it won't elide without an +// initialized allowlist). This is convenience wrapper around +// SetSafetyTipAllowlistPatterns(). +void InitializeBlankLookalikeAllowlistForTesting(); + #endif // CHROME_BROWSER_REPUTATION_SAFETY_TIP_TEST_UTILS_H_
diff --git a/chrome/browser/reputation/url_elision_policy.cc b/chrome/browser/reputation/url_elision_policy.cc index d55fdd6..dfdc066 100644 --- a/chrome/browser/reputation/url_elision_policy.cc +++ b/chrome/browser/reputation/url_elision_policy.cc
@@ -6,6 +6,8 @@ #include "base/feature_list.h" #include "chrome/browser/reputation/local_heuristics.h" +#include "chrome/browser/reputation/safety_tip_test_utils.h" +#include "chrome/browser/reputation/safety_tips_config.h" #include "components/lookalikes/core/lookalike_url_util.h" #include "components/omnibox/common/omnibox_features.h" #include "components/url_formatter/spoof_checks/top_domains/top500_domains.h" @@ -25,9 +27,14 @@ return false; } - auto host = url.host(); - // TODO(jdeblasio): Check allowlist + auto* proto = GetSafetyTipsRemoteConfigProto(); + if (!proto || IsUrlAllowlistedBySafetyTipsComponent(proto, url)) { + // Not having a proto happens when the component hasn't downloaded yet. This + // should only happen for a short window following initial Chrome install. + return false; + } + auto host = url.host(); if (static_cast<int>(host.length()) > kMaximumUnelidedHostnameLength.Get()) { return true; }
diff --git a/chrome/browser/reputation/url_elision_policy_unittest.cc b/chrome/browser/reputation/url_elision_policy_unittest.cc index 693ae2c2..a8da934 100644 --- a/chrome/browser/reputation/url_elision_policy_unittest.cc +++ b/chrome/browser/reputation/url_elision_policy_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/reputation/url_elision_policy.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/reputation/safety_tip_test_utils.h" #include "components/omnibox/common/omnibox_features.h" #include "components/url_formatter/spoof_checks/common_words/common_words_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,6 +26,9 @@ {}); url_formatter::common_words::SetCommonWordDAFSAForTesting( test::kDafsa, sizeof(test::kDafsa)); + + // Ensure that the allowlist exists (as otherwise we'll never elide). + InitializeBlankLookalikeAllowlistForTesting(); } ~UrlElisionPolicyTest() override = default; @@ -51,6 +55,18 @@ EXPECT_FALSE(ShouldElideToRegistrableDomain(kUrl)); } +// Ensure that domains are allowlisted are not elided. +TEST_F(UrlElisionPolicyTest, DoesntElideAllowlistedDomains) { + GURL kUrl = GURL("http://alongbutstillallowlisteddomain.com/xyz"); + + // This domain should be elided normally... + EXPECT_TRUE(ShouldElideToRegistrableDomain(kUrl)); + + // ...but not when allowlisted. + SetSafetyTipAllowlistPatterns({"alongbutstillallowlisteddomain.com/"}, {}); + EXPECT_FALSE(ShouldElideToRegistrableDomain(kUrl)); +} + // Ensure that sensitive keywords cause elision when expected and not otherwise. // Note further tests in SafetyTipHeuristicsTest.SensitiveKeywordsTest. TEST_F(UrlElisionPolicyTest, ElidesKeywordedDomainsAppropriately) {
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index 5f238c1d..b446e9c 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -225,7 +225,11 @@ /* A settings-box is a horizontal row of text or controls within a * setting section (page or subpage). */ .settings-box { - @apply --cr-section; + align-items: center; + border-top: var(--cr-separator-line); + display: flex; + min-height: var(--cr-section-min-height); + padding: 0 var(--cr-section-padding); } .settings-box.no-padding {
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html index 451a1c7..d58105fa 100644 --- a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html +++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.html
@@ -7,13 +7,15 @@ #header { --avatar-position: 84px; - border-radius: 8px; + background-color: var(--header-background-color); + border-radius: 4px; + color: var(--header-text-color); margin: 8px 8px 16px; min-height: 128px; position: relative; } - #accountName { + #headerText { font-size: 15px; font-weight: bold; line-height: 18px; @@ -24,36 +26,61 @@ white-space: nowrap; } - .avatar { - --avatar-size: 60px; - border: 2px solid var(--md-background-color); - border-radius: 50%; + .avatar-container { + --avatar-image-width: 60px; + --avatar-border: 2px; + --avatar-size: calc(var(--avatar-image-width) + 2 * var(--avatar-border)); + --avatar-radius: calc(var(--avatar-image-width)/2 + var(--avatar-border)); + --avatar-overlap: 27px; height: var(--avatar-size); position: absolute; - top: 43px; width: var(--avatar-size); } - #workBadge { - background-color: var(--signin-work-badge-background-color); - display: flex; - left: var(--avatar-position); - /** Ensure the work badge is on top */ - z-index: 1; + .avatar { + /** The user avatar may be transparent, add a background */ + background-color: var(--md-background-color); + border: var(--avatar-border) solid var(--md-background-color); + border-radius: 50%; + height: var(--avatar-image-width); + top: 43px; + width: var(--avatar-image-width); } - #workBadge > iron-icon { - --work-icon-size: 36px; + .work-badge { + --badge-width: 20px; + --badge-offset: -4px; + background-color: var(--signin-work-badge-background-color); + border: 2px solid var(--header-background-color); + border-radius: 50%; + bottom: var(--badge-offset); + height: var(--badge-width); + position: absolute; + right: var(--badge-offset); + width: var(--badge-width); + } + + .work-badge > iron-icon { + --work-icon-size: 16px; + bottom: 0; color: white; height: var(--work-icon-size); + left: 0; margin: auto; + position: absolute; + right: 0; + top: 0; width: var(--work-icon-size); } - #userAvatar { - /** The user avatar may be transparent, add a background */ - background-color: var(--md-background-color); - right: var(--avatar-position); + #interceptedAvatar { + left: calc(50% - var(--avatar-radius) - var(--avatar-overlap)); + /** Ensure the intercepted avatar is on top of the primary avatar */ + z-index: 1; + } + + #primaryAvatar { + left: calc(50% - var(--avatar-radius) + var(--avatar-overlap)); } #body { @@ -72,22 +99,38 @@ margin: 0 0 8px; } + .action-container { + padding: 0 16px 16px; + } + cr-button { font-size: 12px; } </style> -<div id="header" style$="[[headerStyle_]]"> - <div id="accountName">[[accountInfo_.name]]</div> - <div class="avatar" id="workBadge"> - <iron-icon class="icon" icon="signin:work"></iron-icon> +<div id="header"> + <div id="headerText">[[interceptionParameters_.headerText]]</div> + <div class="avatar-container" id="interceptedAvatar"> + <img class="avatar" id="interceptedAvatarImg" + src="[[interceptionParameters_.interceptedAccount.pictureUrl]]"> + <div class="work-badge" id="interceptedBadge" + hidden="[[!interceptionParameters_.interceptedAccount.isManaged]]"> + <iron-icon class="icon" icon="signin:work"></iron-icon> + </div> </div> - <img class="avatar" id="userAvatar" src="[[accountInfo_.pictureUrl]]"> + <div class="avatar-container" id="primaryAvatar"> + <img class="avatar" id="primaryAvatarImg" + src="[[interceptionParameters_.primaryAccount.pictureUrl]]"> + <div class="work-badge" id="primaryBadge" + hidden="[[!interceptionParameters_.primaryAccount.isManaged]]"> + <iron-icon class="icon" icon="signin:work"></iron-icon> + </div> + </div> </div> <div id="body"> - <div id="title">$i18n{diceWebSigninInterceptTitle}</div> - <div>$i18n{diceWebSigninInterceptDesc}</div> + <div id="title">[[interceptionParameters_.bodyTitle]]</div> + <div id="contents">[[interceptionParameters_.bodyText]]</div> </div> <div class="action-container">
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js index 860732b..1889ca3 100644 --- a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js +++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_app.js
@@ -13,7 +13,7 @@ import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {AccountInfo, DiceWebSigninInterceptBrowserProxy, DiceWebSigninInterceptBrowserProxyImpl} from './dice_web_signin_intercept_browser_proxy.js'; +import {AccountInfo, DiceWebSigninInterceptBrowserProxy, DiceWebSigninInterceptBrowserProxyImpl, InterceptionParameters} from './dice_web_signin_intercept_browser_proxy.js'; Polymer({ is: 'dice-web-signin-intercept-app', @@ -25,17 +25,8 @@ ], properties: { - /** @private {AccountInfo} */ - accountInfo_: Object, - /** @private */ - headerStyle_: { - type: String, - value() { - return 'background-color: ' + - loadTimeData.getString('headerBackgroundColor') + - '; color: ' + loadTimeData.getString('headerTextColor'); - }, - }, + /** @private {InterceptionParameters} */ + InterceptionParameters_: Object, }, /** @private {?DiceWebSigninInterceptBrowserProxy} */ @@ -43,12 +34,14 @@ /** @override */ attached() { + this.setColors_(); this.diceWebSigninInterceptBrowserProxy_ = DiceWebSigninInterceptBrowserProxyImpl.getInstance(); - this.diceWebSigninInterceptBrowserProxy_.pageLoaded().then( - info => this.handleAccountInfoChanged_(info)); this.addWebUIListener( - 'account-info-changed', this.handleAccountInfoChanged_.bind(this)); + 'interception-parameters-changed', + this.handleParametersChanged_.bind(this)); + this.diceWebSigninInterceptBrowserProxy_.pageLoaded().then( + parameters => this.handleParametersChanged_(parameters)); }, /** @private */ @@ -61,12 +54,23 @@ this.diceWebSigninInterceptBrowserProxy_.cancel(); }, + /** @private */ + setColors_() { + this.style.setProperty( + '--header-background-color', + loadTimeData.getString('headerBackgroundColor')); + this.style.setProperty( + '--header-text-color', loadTimeData.getString('headerTextColor')); + }, + /** - * Called when the account image changes. - * @param {!AccountInfo} info + * Called when the interception parameters are updated. + * @param {!InterceptionParameters} parameters * @private */ - handleAccountInfoChanged_(info) { - this.accountInfo_ = info; + handleParametersChanged_(parameters) { + this.interceptionParameters_ = parameters; + this.notifyPath('interceptionParameters_.interceptedAccount.isManaged'); + this.notifyPath('interceptionParameters_.primaryAccount.isManaged'); }, });
diff --git a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js index b200200..26a9e692 100644 --- a/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js +++ b/chrome/browser/resources/signin/dice_web_signin_intercept/dice_web_signin_intercept_browser_proxy.js
@@ -11,12 +11,23 @@ /** * Account information sent from C++. * @typedef {{ - * name: string, + * isManaged: boolean, * pictureUrl: string, * }} */ export let AccountInfo; +/** + * @typedef {{ + * headerText: string, + * bodyTitle: string, + * bodyText: string, + * interceptedAccount: AccountInfo, + * primaryAccount: AccountInfo, + * }} + */ +export let InterceptionParameters; + /** @interface */ export class DiceWebSigninInterceptBrowserProxy { /** Called when the user accepts the interception bubble. */ @@ -27,7 +38,7 @@ /** * Called when the page is loaded. - * @return {!Promise<!AccountInfo>} + * @return {!Promise<!InterceptionParameters>} * */ pageLoaded() {} }
diff --git a/chrome/browser/resources/sync_file_system_internals/OWNERS b/chrome/browser/resources/sync_file_system_internals/OWNERS index a69fb9b7..0d7e100e 100644 --- a/chrome/browser/resources/sync_file_system_internals/OWNERS +++ b/chrome/browser/resources/sync_file_system_internals/OWNERS
@@ -1,7 +1,7 @@ calvinlo@chromium.org kinuko@chromium.org nhiroki@chromium.org -pwnall@chomium.org +pwnall@chromium.org # TEAM: storage-dev@chromium.org # COMPONENT: Blink>Storage>FileSystem
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckElementPreference.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckElementPreference.java index 76639d4..ffbae5ef 100644 --- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckElementPreference.java +++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckElementPreference.java
@@ -12,6 +12,7 @@ import androidx.annotation.DrawableRes; import androidx.preference.PreferenceViewHolder; +import org.chromium.base.Callback; import org.chromium.components.browser_ui.settings.ChromeBasePreference; /** @@ -24,11 +25,20 @@ private ImageView mStatusView; /** + * Represents an action to take once the view elements are available. + * This is needed because |SafetyCheckMediator::setInitialState()| is invoked before all the + * nested views are available, so setting icons should be delayed. + */ + private Callback<Void> mDelayedAction; + + /** * Creates a new object and sets the widget layout. */ public SafetyCheckElementPreference(Context context, AttributeSet attrs) { super(context, attrs); setWidgetLayoutResource(R.layout.safety_check_status); + // No delayed action to take. + mDelayedAction = null; } /** @@ -39,14 +49,21 @@ super.onBindViewHolder(holder); mProgressBar = holder.findViewById(R.id.progress); mStatusView = (ImageView) holder.findViewById(R.id.status_view); + // If there is a delayed action - take it. + if (mDelayedAction != null) { + mDelayedAction.onResult(null); + } + // Reset the delayed action. + mDelayedAction = null; } /** * Displays the progress bar. */ void showProgressBar() { - // Ignore if this gets invoked before onBindViewHolder. + // Delay if this gets invoked before onBindViewHolder. if (mStatusView == null || mProgressBar == null) { + mDelayedAction = (ignored) -> showProgressBar(); return; } mStatusView.setVisibility(View.GONE); @@ -58,8 +75,9 @@ * @param icon An icon to display. */ void showStatusIcon(@DrawableRes int icon) { - // Ignore if this gets invoked before onBindViewHolder. + // Delay if this gets invoked before onBindViewHolder. if (mStatusView == null || mProgressBar == null) { + mDelayedAction = (ignored) -> showStatusIcon(icon); return; } mStatusView.setImageResource(icon); @@ -71,8 +89,9 @@ * Hides anything in the status area. */ void clearStatusIndicator() { - // Ignore if this gets invoked before onBindViewHolder. + // Delay if this gets invoked before onBindViewHolder. if (mStatusView == null || mProgressBar == null) { + mDelayedAction = (ignored) -> clearStatusIndicator(); return; } mStatusView.setVisibility(View.GONE);
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java index 0d9bbc2..18d1f668 100644 --- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java +++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
@@ -19,6 +19,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.password_check.CompromisedCredential; import org.chromium.chrome.browser.password_check.PasswordCheck; import org.chromium.chrome.browser.password_check.PasswordCheckFactory; import org.chromium.chrome.browser.password_check.PasswordCheckUIStatus; @@ -114,8 +115,6 @@ this(model, client, settingsLauncher, null, new Handler()); // Have to initialize this after the constructor call, since a "this" instance is needed. mSafetyCheckBridge = new SafetyCheckBridge(SafetyCheckMediator.this); - // Determine and set the initial state. - setInitialState(); } @VisibleForTesting @@ -126,8 +125,6 @@ mSafetyCheckBridge = bridge; mHandler = handler; mPreferenceManager = SharedPreferencesManager.getInstance(); - mPasswordsLoaded = false; - mLeaksLoaded = false; // Set the listener for clicking the updates element. mModel.set(SafetyCheckProperties.UPDATES_CLICK_LISTENER, (Preference.OnPreferenceClickListener) (p) -> { @@ -175,10 +172,6 @@ mModel.set(SafetyCheckProperties.LAST_RUN_TIMESTAMP, mPreferenceManager.readLong( ChromePreferenceKeys.SETTINGS_SAFETY_CHECK_LAST_RUN_TIMESTAMP, 0)); - if (mSafetyCheckBridge != null) { - // Determine and set the initial state. - setInitialState(); - } } /** @@ -203,6 +196,10 @@ } mModel.set(SafetyCheckProperties.PASSWORDS_STATE, PasswordsState.CHECKING); mLoadStage = PasswordCheckLoadStage.INITIAL_WAIT_FOR_LOAD; + // Reset the status of the password disk loads. If it's loaded, PasswordCheck will invoke + // the callbacks again (the |callImmediatelyIfReady| argument to |addObserver| is true). + mPasswordsLoaded = false; + mLeaksLoaded = false; // Refresh the PasswordCheck instance, since it's not guaranteed to be the same. mPasswordCheck = PasswordCheckFactory.getOrCreate(); mPasswordCheck.addObserver(this, true); @@ -310,8 +307,7 @@ } @Override - public void onCompromisedCredentialFound( - String originUrl, String username, String password, boolean hasScript) {} + public void onCompromisedCredentialFound(CompromisedCredential leakedCredential) {} /** Cancels any pending callbacks and registered observers. */ public void destroy() {
diff --git a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java index 26d7c32c..38780b0 100644 --- a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java +++ b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
@@ -381,7 +381,7 @@ @Test public void testPasswordsInitialLoadDuringInitialState() { // Order: initial state -> load completed -> done. - // setInitialState was invoked on Mediator creation. + mMediator.setInitialState(); assertEquals(PasswordsState.CHECKING, mModel.get(PASSWORDS_STATE)); mMediator.onCompromisedCredentialsFetchCompleted(); @@ -398,7 +398,7 @@ @Test public void testPasswordsInitialLoadDuringRunningCheck() { // Order: initial state -> safety check triggered -> load completed -> check done. - // setInitialState was invoked on Mediator creation. + mMediator.setInitialState(); assertEquals(PasswordsState.CHECKING, mModel.get(PASSWORDS_STATE)); mMediator.performSafetyCheck(); @@ -419,7 +419,7 @@ @Test public void testPasswordsInitialLoadAfterRunningCheck() { // Order: initial state -> safety check triggered -> check done -> load completed. - // setInitialState was invoked on Mediator creation. + mMediator.setInitialState(); assertEquals(PasswordsState.CHECKING, mModel.get(PASSWORDS_STATE)); mMediator.performSafetyCheck(); @@ -440,7 +440,7 @@ @Test public void testPasswordsInitialLoadCheckReturnsError() { // Order: initial state -> safety check triggered -> check error -> load ignored. - // setInitialState was invoked on Mediator creation. + mMediator.setInitialState(); assertEquals(PasswordsState.CHECKING, mModel.get(PASSWORDS_STATE)); mMediator.performSafetyCheck();
diff --git a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java index db20cb1f..3eb0696 100644 --- a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java +++ b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragmentTest.java
@@ -7,6 +7,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; import android.content.Context; import android.support.test.InstrumentationRegistry; @@ -69,6 +73,18 @@ public void setUp() { MockitoAnnotations.initMocks(this); PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck); + // Make the passwords initial status return immediately to avoid spinning animation. + when(mPasswordCheck.getSavedPasswordsCount()).thenReturn(0); + when(mPasswordCheck.getCompromisedCredentialsCount()).thenReturn(0); + doAnswer(invocation -> { + PasswordCheck.Observer observer = + (PasswordCheck.Observer) (invocation.getArguments()[0]); + observer.onCompromisedCredentialsFetchCompleted(); + observer.onSavedPasswordsFetchCompleted(); + return null; + }) + .when(mPasswordCheck) + .addObserver(any(SafetyCheckMediator.class), eq(true)); } @Test
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index 780ea02..9236238 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -2494,6 +2494,11 @@ EXPECT_EQ(c_url, subframe->GetLastCommittedURL()); EXPECT_EQ(c_origin, subframe->GetLastCommittedOrigin()); + // Check that main frame and subframe are in the same BrowsingInstance. + content::SiteInstance* subframe_instance_c = subframe->GetSiteInstance(); + EXPECT_TRUE(new_tab->GetMainFrame()->GetSiteInstance()->IsRelatedSiteInstance( + subframe_instance_c)); + // Go back - this should reach: a.com(a.com-blank). { content::TestNavigationObserver nav_observer(new_tab); @@ -2503,10 +2508,13 @@ ASSERT_EQ(2u, new_tab->GetAllFrames().size()); subframe = new_tab->GetAllFrames()[1]; EXPECT_EQ(GURL(url::kAboutBlankURL), subframe->GetLastCommittedURL()); - // TODO(lukasza): https://crbug.com/888079: The browser process should tell - // the renderer which (initiator-based) origin to commit. Right now, Blink - // just falls back to an opaque origin. - EXPECT_TRUE(subframe->GetLastCommittedOrigin().opaque()); + EXPECT_EQ(a_origin, subframe->GetLastCommittedOrigin()); + + // Check that we're still in the same BrowsingInstance. + EXPECT_TRUE(new_tab->GetMainFrame()->GetSiteInstance()->IsRelatedSiteInstance( + subframe->GetSiteInstance())); + EXPECT_TRUE( + subframe_instance_c->IsRelatedSiteInstance(subframe->GetSiteInstance())); } // Check that TabManager.TimeSinceTabClosedUntilRestored histogram is not
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc index ffa9cc6..6272dacc 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -33,8 +33,39 @@ return service->GetBoolean(prefs::kBrowserAddPersonEnabled); } +// Helper function to return the primary account info. The returned info is +// empty if there is no primary account, and non-empty otherwise. Extended +// fields may be missing if they are not available. +AccountInfo GetPrimaryAccountInfo(signin::IdentityManager* manager) { + CoreAccountInfo primary_core_account_info = + manager->GetPrimaryAccountInfo(signin::ConsentLevel::kNotRequired); + if (primary_core_account_info.IsEmpty()) + return AccountInfo(); + + base::Optional<AccountInfo> primary_account_info = + manager->FindExtendedAccountInfoForAccountWithRefreshToken( + primary_core_account_info); + + if (primary_account_info) + return *primary_account_info; + + // Return an AccountInfo without extended fields, based on the core info. + AccountInfo account_info; + account_info.gaia = primary_core_account_info.gaia; + account_info.email = primary_core_account_info.email; + account_info.account_id = primary_core_account_info.account_id; + return account_info; +} + } // namespace +bool DiceWebSigninInterceptor::Delegate::BubbleParameters::operator==( + const DiceWebSigninInterceptor::Delegate::BubbleParameters& rhs) const { + return interception_type == rhs.interception_type && + intercepted_account == rhs.intercepted_account && + primary_account == rhs.primary_account; +} + DiceWebSigninInterceptor::DiceWebSigninInterceptor( Profile* profile, std::unique_ptr<Delegate> delegate) @@ -80,8 +111,11 @@ if (ShouldShowProfileSwitchBubble(*account_info, &g_browser_process->profile_manager() ->GetProfileAttributesStorage())) { + Delegate::BubbleParameters bubble_parameters{ + SigninInterceptionType::kProfileSwitch, *account_info, + GetPrimaryAccountInfo(identity_manager_)}; delegate_->ShowSigninInterceptionBubble( - SigninInterceptionType::kProfileSwitch, web_contents, *account_info, + web_contents, bubble_parameters, base::BindOnce(&DiceWebSigninInterceptor::OnProfileSwitchChoice, base::Unretained(this))); @@ -217,8 +251,10 @@ return; } + Delegate::BubbleParameters bubble_parameters{ + *interception_type, info, GetPrimaryAccountInfo(identity_manager_)}; delegate_->ShowSigninInterceptionBubble( - *interception_type, web_contents(), info, + web_contents(), bubble_parameters, base::BindOnce(&DiceWebSigninInterceptor::OnProfileCreationChoice, base::Unretained(this))); }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.h b/chrome/browser/signin/dice_web_signin_interceptor.h index 0d69a2c..c587a40d 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.h +++ b/chrome/browser/signin/dice_web_signin_interceptor.h
@@ -49,6 +49,15 @@ // Delegate class responsible for showing the various interception UIs. class Delegate { public: + // Parameters for interception bubble UIs. + struct BubbleParameters { + bool operator==(const BubbleParameters& rhs) const; + + SigninInterceptionType interception_type; + AccountInfo intercepted_account; + AccountInfo primary_account; + }; + virtual ~Delegate() = default; // Shows the signin interception bubble and calls |callback| to indicate @@ -56,9 +65,8 @@ // The callback is never called if the delegate is deleted before it // completes. virtual void ShowSigninInterceptionBubble( - SigninInterceptionType signin_interception_type, content::WebContents* web_contents, - const AccountInfo& account_info, + const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback) = 0; };
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc index 1827bcd..aeca348 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc
@@ -33,12 +33,11 @@ : public DiceWebSigninInterceptor::Delegate { public: void ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType signin_interception_type, content::WebContents* web_contents, - const AccountInfo& account_info, + const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback) override { bool should_intercept = - signin_interception_type == + bubble_parameters.interception_type == DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser; std::move(callback).Run(should_intercept); }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc index 1626fe9..fc4d1c6 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
@@ -36,10 +36,8 @@ public: MOCK_METHOD(void, ShowSigninInterceptionBubble, - (DiceWebSigninInterceptor::SigninInterceptionType - signin_interception_type, - content::WebContents* web_contents, - const AccountInfo& account_info, + (content::WebContents * web_contents, + const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback), (override)); }; @@ -324,11 +322,12 @@ testing::Mock::VerifyAndClearExpectations(mock_delegate()); // Check that interception works otherwise, as a sanity check. - EXPECT_CALL( - *mock_delegate(), - ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch, - web_contents(), account_info, testing::_)); + DiceWebSigninInterceptor::Delegate::BubbleParameters expected_parameters = { + DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch, + account_info, AccountInfo()}; + EXPECT_CALL(*mock_delegate(), + ShowSigninInterceptionBubble(web_contents(), expected_parameters, + testing::_)); interceptor()->MaybeInterceptWebSignin(web_contents(), account_info.account_id, /*is_new_account=*/true, @@ -347,13 +346,14 @@ /*is_consented_primary_account=*/false); // Start an interception. + DiceWebSigninInterceptor::Delegate::BubbleParameters expected_parameters = { + DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch, + account_info, AccountInfo()}; base::OnceCallback<void(bool)> delegate_callback; - EXPECT_CALL( - *mock_delegate(), - ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch, - web_contents(), account_info, testing::_)) - .WillOnce(testing::WithArg<3>(testing::Invoke( + EXPECT_CALL(*mock_delegate(), + ShowSigninInterceptionBubble(web_contents(), expected_parameters, + testing::_)) + .WillOnce(testing::WithArg<2>(testing::Invoke( [&delegate_callback](base::OnceCallback<void(bool)> callback) { delegate_callback = std::move(callback); }))); @@ -370,11 +370,9 @@ EXPECT_FALSE(interceptor()->is_interception_in_progress_); // A new interception can now start. - EXPECT_CALL( - *mock_delegate(), - ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch, - web_contents(), account_info, testing::_)); + EXPECT_CALL(*mock_delegate(), + ShowSigninInterceptionBubble(web_contents(), expected_parameters, + testing::_)); MaybeIntercept(account_info.account_id); } @@ -415,17 +413,19 @@ EXPECT_FALSE(interceptor()->is_interception_in_progress_); // Profile switch interception still works. - EXPECT_CALL( - *mock_delegate(), - ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch, - web_contents(), account_info, testing::_)); + DiceWebSigninInterceptor::Delegate::BubbleParameters expected_parameters = { + DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch, + account_info, AccountInfo()}; + EXPECT_CALL(*mock_delegate(), + ShowSigninInterceptionBubble(web_contents(), expected_parameters, + testing::_)); MaybeIntercept(account_info.account_id); } TEST_F(DiceWebSigninInterceptorTest, WaitForAccountInfoAvailable) { - identity_test_env()->MakeUnconsentedPrimaryAccountAvailable( - "bob@example.com"); + AccountInfo primary_account_info = + identity_test_env()->MakeUnconsentedPrimaryAccountAvailable( + "bob@example.com"); AccountInfo account_info = identity_test_env()->MakeAccountAvailable("alice@example.com"); MaybeIntercept(account_info.account_id); @@ -433,18 +433,21 @@ testing::Mock::VerifyAndClearExpectations(mock_delegate()); // Account info becomes available, interception happens. + DiceWebSigninInterceptor::Delegate::BubbleParameters expected_parameters = { + DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise, + account_info, primary_account_info}; EXPECT_CALL(*mock_delegate(), - ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise, - web_contents(), account_info, testing::_)); + ShowSigninInterceptionBubble(web_contents(), expected_parameters, + testing::_)); MakeValidAccountInfo(&account_info); account_info.hosted_domain = "example.com"; identity_test_env()->UpdateAccountInfoForAccount(account_info); } TEST_F(DiceWebSigninInterceptorTest, AccountInfoAlreadyAvailable) { - identity_test_env()->MakeUnconsentedPrimaryAccountAvailable( - "bob@example.com"); + AccountInfo primary_account_info = + identity_test_env()->MakeUnconsentedPrimaryAccountAvailable( + "bob@example.com"); AccountInfo account_info = identity_test_env()->MakeAccountAvailable("alice@example.com"); MakeValidAccountInfo(&account_info); @@ -452,25 +455,30 @@ identity_test_env()->UpdateAccountInfoForAccount(account_info); // Account info is already available, interception happens immediately. + DiceWebSigninInterceptor::Delegate::BubbleParameters expected_parameters = { + DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise, + account_info, primary_account_info}; EXPECT_CALL(*mock_delegate(), - ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise, - web_contents(), account_info, testing::_)); + ShowSigninInterceptionBubble(web_contents(), expected_parameters, + testing::_)); MaybeIntercept(account_info.account_id); } TEST_F(DiceWebSigninInterceptorTest, MultiUserInterception) { - identity_test_env()->MakeUnconsentedPrimaryAccountAvailable( - "bob@example.com"); + AccountInfo primary_account_info = + identity_test_env()->MakeUnconsentedPrimaryAccountAvailable( + "bob@example.com"); AccountInfo account_info = identity_test_env()->MakeAccountAvailable("alice@example.com"); MakeValidAccountInfo(&account_info); identity_test_env()->UpdateAccountInfoForAccount(account_info); // Account info is already available, interception happens immediately. + DiceWebSigninInterceptor::Delegate::BubbleParameters expected_parameters = { + DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser, + account_info, primary_account_info}; EXPECT_CALL(*mock_delegate(), - ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser, - web_contents(), account_info, testing::_)); + ShowSigninInterceptionBubble(web_contents(), expected_parameters, + testing::_)); MaybeIntercept(account_info.account_id); }
diff --git a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc index 97a83032..7f35c77 100644 --- a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc +++ b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
@@ -8,6 +8,12 @@ #include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_process_platform_part.h" +#include "chromeos/components/account_manager/account_manager_factory.h" +#endif + // static std::unique_ptr<TestingProfile> IdentityTestEnvironmentProfileAdaptor:: CreateProfileForIdentityTestEnvironment() { @@ -71,10 +77,16 @@ IdentityTestEnvironmentProfileAdaptor::BuildIdentityManagerForTests( content::BrowserContext* context) { Profile* profile = Profile::FromBrowserContext(context); - +#if defined(OS_CHROMEOS) + return signin::IdentityTestEnvironment::BuildIdentityManagerForTests( + ChromeSigninClientFactory::GetForProfile(profile), profile->GetPrefs(), + profile->GetPath(), + g_browser_process->platform_part()->GetAccountManagerFactory()); +#else return signin::IdentityTestEnvironment::BuildIdentityManagerForTests( ChromeSigninClientFactory::GetForProfile(profile), profile->GetPrefs(), profile->GetPath()); +#endif } IdentityTestEnvironmentProfileAdaptor::IdentityTestEnvironmentProfileAdaptor(
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc index 3f27e18..a2372e8 100644 --- a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc +++ b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
@@ -41,9 +41,8 @@ public: ~TestDiceWebSigninInterceptorDelegate() override = default; void ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType signin_interception_type, content::WebContents* web_contents, - const AccountInfo& account_info, + const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback) override { std::move(callback).Run(false); }
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index fcde182..84f62f4 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -6278,8 +6278,7 @@ policy::PolicyMap policies; policies.Set(policy::key::kInsecureFormsWarningsEnabled, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, - policy::POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>(false), nullptr); + policy::POLICY_SOURCE_CLOUD, base::Value(false), nullptr); UpdateProviderPolicy(policies); // Pref should now be set to false. EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean(
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_observer.cc b/chrome/browser/supervised_user/supervised_user_navigation_observer.cc index 7995c78..f9789673 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_observer.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_observer.cc
@@ -86,7 +86,7 @@ } void SupervisedUserNavigationObserver::DidFinishNavigation( - content::NavigationHandle* navigation_handle) { + content::NavigationHandle* navigation_handle) { if (!navigation_handle->HasCommitted()) return; @@ -108,13 +108,15 @@ auto* render_frame_host = web_contents()->GetMainFrame(); int process_id = render_frame_host->GetProcess()->GetID(); int routing_id = render_frame_host->GetRoutingID(); - + bool skip_manual_parent_filter = + url_filter_->ShouldSkipParentManualAllowlistFiltering(web_contents()); url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( web_contents()->GetLastCommittedURL(), base::BindOnce( &SupervisedUserNavigationObserver::URLFilterCheckCallback, weak_ptr_factory_.GetWeakPtr(), navigation_handle->GetURL(), - process_id, routing_id)); + process_id, routing_id), + skip_manual_parent_filter); } } @@ -149,13 +151,15 @@ auto* main_frame = web_contents()->GetMainFrame(); int main_frame_process_id = main_frame->GetProcess()->GetID(); int routing_id = main_frame->GetRoutingID(); - + bool skip_manual_parent_filter = + url_filter_->ShouldSkipParentManualAllowlistFiltering(web_contents()); url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( web_contents()->GetLastCommittedURL(), base::BindOnce(&SupervisedUserNavigationObserver::URLFilterCheckCallback, weak_ptr_factory_.GetWeakPtr(), web_contents()->GetLastCommittedURL(), - main_frame_process_id, routing_id)); + main_frame_process_id, routing_id), + skip_manual_parent_filter); MaybeUpdateRequestedHosts(); @@ -287,13 +291,15 @@ return; const GURL& last_committed_url = render_frame_host->GetLastCommittedURL(); - + bool skip_manual_parent_filter = + url_filter_->ShouldSkipParentManualAllowlistFiltering(web_contents()); url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( web_contents()->GetLastCommittedURL(), base::BindOnce(&SupervisedUserNavigationObserver::URLFilterCheckCallback, weak_ptr_factory_.GetWeakPtr(), last_committed_url, render_frame_host->GetProcess()->GetID(), - render_frame_host->GetRoutingID())); + render_frame_host->GetRoutingID()), + skip_manual_parent_filter); } void SupervisedUserNavigationObserver::GoBack() {
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc index f053afec..f81ae72 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
@@ -158,9 +158,15 @@ deferred_ = false; DCHECK_EQ(SupervisedUserURLFilter::INVALID, behavior_); GURL url = navigation_handle()->GetURL(); + + bool skip_manual_parent_filter = + url_filter_->ShouldSkipParentManualAllowlistFiltering( + navigation_handle()->GetWebContents()->GetOutermostWebContents()); bool got_result = url_filter_->GetFilteringBehaviorForURLWithAsyncChecks( - url, base::BindOnce(&SupervisedUserNavigationThrottle::OnCheckDone, - weak_ptr_factory_.GetWeakPtr(), url)); + url, + base::BindOnce(&SupervisedUserNavigationThrottle::OnCheckDone, + weak_ptr_factory_.GetWeakPtr(), url), + skip_manual_parent_filter); DCHECK_EQ(got_result, behavior_ != SupervisedUserURLFilter::INVALID); // If we got a "not blocked" result synchronously, don't defer. deferred_ = !got_result || (behavior_ == SupervisedUserURLFilter::BLOCK);
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc index 6561fc0..6359b4e 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -26,7 +26,9 @@ #include "chrome/browser/supervised_user/supervised_user_url_filter.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/webui_url_constants.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" @@ -83,6 +85,40 @@ render_frame_hosts_.erase(host->GetFrameTreeNodeId()); } +class InnerWebContentsAttachedWaiter : public content::WebContentsObserver { + public: + explicit InnerWebContentsAttachedWaiter(content::WebContents* contents) + : content::WebContentsObserver(contents) {} + InnerWebContentsAttachedWaiter(const InnerWebContentsAttachedWaiter&) = + delete; + InnerWebContentsAttachedWaiter& operator=( + const InnerWebContentsAttachedWaiter&) = delete; + ~InnerWebContentsAttachedWaiter() override = default; + + // content::WebContentsObserver: + void InnerWebContentsAttached(content::WebContents* inner_web_contents, + content::RenderFrameHost* render_frame_host, + bool is_full_page) override; + + void WaitForInnerWebContentsAttached(); + + private: + base::RunLoop run_loop_{base::RunLoop::Type::kNestableTasksAllowed}; +}; + +void InnerWebContentsAttachedWaiter::InnerWebContentsAttached( + content::WebContents* inner_web_contents, + content::RenderFrameHost* render_frame_host, + bool is_full_page) { + run_loop_.Quit(); +} + +void InnerWebContentsAttachedWaiter::WaitForInnerWebContentsAttached() { + if (web_contents()->GetInnerWebContents().size() > 0u) + return; + run_loop_.Run(); +} + } // namespace class SupervisedUserNavigationThrottleTest @@ -233,6 +269,42 @@ EXPECT_TRUE(loaded2); } +IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationThrottleTest, + AllowEDUCoexistenceInnerWebContents) { + BlockHost(kExampleHost2); + GURL manually_blocked_url = embedded_test_server()->GetURL( + kExampleHost2, "/supervised_user/with_iframes.html"); + + ui_test_utils::NavigateToURL(browser(), + GURL(chrome::kChromeUIEDUCoexistenceLoginURL)); + // Get the top level WebContents. + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_EQ(contents->GetURL(), GURL(chrome::kChromeUIEDUCoexistenceLoginURL)); + + InnerWebContentsAttachedWaiter web_contents_attached_waiter( + browser()->tab_strip_model()->GetActiveWebContents()); + web_contents_attached_waiter.WaitForInnerWebContentsAttached(); + + // Get the inner WebContents. + std::vector<content::WebContents*> inner_web_contents = + contents->GetInnerWebContents(); + + // There is only one inner web content in EDUCoexistence flow. + EXPECT_EQ(inner_web_contents.size(), 1u); + + content::WebContents* webview_element = inner_web_contents[0]; + NavigationFinishedWaiter waiter(webview_element, manually_blocked_url); + webview_element->GetController().LoadURLWithParams( + NavigationController::LoadURLParams(manually_blocked_url)); + waiter.Wait(); + + // Make sure that there is no error page in the inner web content. + EXPECT_NE( + webview_element->GetController().GetLastCommittedEntry()->GetPageType(), + content::PAGE_TYPE_ERROR); +} + class SupervisedUserIframeFilterTest : public SupervisedUserNavigationThrottleTest { protected:
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc index 544f0b2..7cb7b09d 100644 --- a/chrome/browser/supervised_user/supervised_user_service.cc +++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -583,6 +583,7 @@ SupervisedUserURLFilter::FilteringBehavior behavior = SupervisedUserURLFilter::BehaviorFromInt(behavior_value); url_filter_.SetDefaultFilteringBehavior(behavior); + UpdateAsyncUrlChecker(); for (SupervisedUserServiceObserver& observer : observer_list_) observer.OnURLFilterChanged(); @@ -603,8 +604,19 @@ // Do nothing - we'll check the setting again when the load finishes. } + UpdateAsyncUrlChecker(); +} + +void SupervisedUserService::UpdateAsyncUrlChecker() { + int behavior_value = profile_->GetPrefs()->GetInteger( + prefs::kDefaultSupervisedUserFilteringBehavior); + SupervisedUserURLFilter::FilteringBehavior behavior = + SupervisedUserURLFilter::BehaviorFromInt(behavior_value); + bool use_online_check = - supervised_users::IsSafeSitesOnlineCheckEnabled(profile_); + supervised_users::IsSafeSitesOnlineCheckEnabled(profile_) || + behavior == SupervisedUserURLFilter::FilteringBehavior::BLOCK; + if (use_online_check != url_filter_.HasAsyncURLChecker()) { if (use_online_check) { url_filter_.InitAsyncURLChecker(
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h index 8bae30f5..f1cb977 100644 --- a/chrome/browser/supervised_user/supervised_user_service.h +++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -333,6 +333,8 @@ void OnSafeSitesSettingChanged(); + void UpdateAsyncUrlChecker(); + void OnSiteListsChanged( const std::vector<scoped_refptr<SupervisedUserSiteList>>& site_lists);
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.cc b/chrome/browser/supervised_user/supervised_user_url_filter.cc index eb3e4417..34708684 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter.cc +++ b/chrome/browser/supervised_user/supervised_user_url_filter.cc
@@ -18,6 +18,7 @@ #include "base/macros.h" #include "base/no_destructor.h" #include "base/stl_util.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -28,11 +29,13 @@ #include "chrome/browser/supervised_user/kids_management_url_checker_client.h" #include "chrome/browser/supervised_user/supervised_user_blacklist.h" #include "chrome/common/chrome_features.h" +#include "chrome/common/webui_url_constants.h" #include "components/policy/core/browser/url_util.h" #include "components/url_formatter/url_formatter.h" #include "components/url_matcher/url_matcher.h" #include "components/variations/service/variations_service.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" #include "extensions/buildflags/buildflags.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -108,6 +111,9 @@ const char kPlayStoreHost[] = "play.google.com"; const char kPlayTermsPath[] = "/about/play-terms"; +// accounts.google.com used for login: +const char kAccountsGoogleUrl[] = "https://accounts.google.com"; + // This class encapsulates all the state that is required during construction of // a new SupervisedUserURLFilter::Contents. class FilterBuilder { @@ -225,6 +231,18 @@ } // static +bool SupervisedUserURLFilter::ShouldSkipParentManualAllowlistFiltering( + content::WebContents* contents) { + // Note that |contents| can be an inner WebContents. Get the outer most + // WebContents and check if it belongs to the EDUCoexistence login flow. + content::WebContents* outer_most_content = + contents->GetOutermostWebContents(); + + return outer_most_content->GetURL() == + GURL(chrome::kChromeUIEDUCoexistenceLoginURL); +} + +// static SupervisedUserURLFilter::FilteringBehavior SupervisedUserURLFilter::BehaviorFromInt(int behavior_value) { DCHECK_GE(behavior_value, ALLOW); @@ -344,10 +362,12 @@ } #endif - // Allow navigations to whitelisted origins (currently families.google.com). + // Allow navigations to whitelisted origins (currently families.google.com and + // accounts.google.com). static const base::NoDestructor<base::flat_set<GURL>> kWhitelistedOrigins( base::flat_set<GURL>({GURL(kFamiliesUrl).GetOrigin(), - GURL(kFamiliesSecureUrl).GetOrigin()})); + GURL(kFamiliesSecureUrl).GetOrigin(), + GURL(kAccountsGoogleUrl).GetOrigin()})); if (base::Contains(*kWhitelistedOrigins, effective_url.GetOrigin())) return ALLOW; @@ -445,17 +465,27 @@ bool SupervisedUserURLFilter::GetFilteringBehaviorForURLWithAsyncChecks( const GURL& url, - FilteringBehaviorCallback callback) const { - supervised_user_error_page::FilteringBehaviorReason reason = - supervised_user_error_page::DEFAULT; - FilteringBehavior behavior = GetFilteringBehaviorForURL(url, false, &reason); - // Any non-default reason trumps the async checker. - // Also, if we're blocking anyway, then there's no need to check it. - if (reason != supervised_user_error_page::DEFAULT || behavior == BLOCK || - !async_url_checker_) { - std::move(callback).Run(behavior, reason, false); - for (Observer& observer : observers_) - observer.OnURLChecked(url, behavior, reason, false); + FilteringBehaviorCallback callback, + bool skip_manual_parent_filter) const { + if (!skip_manual_parent_filter) { + supervised_user_error_page::FilteringBehaviorReason reason = + supervised_user_error_page::DEFAULT; + FilteringBehavior behavior = + GetFilteringBehaviorForURL(url, false, &reason); + // Any non-default reason trumps the async checker. + // Also, if we're blocking anyway, then there's no need to check it. + if (reason != supervised_user_error_page::DEFAULT || behavior == BLOCK || + !async_url_checker_) { + std::move(callback).Run(behavior, reason, false); + for (Observer& observer : observers_) + observer.OnURLChecked(url, behavior, reason, false); + return true; + } + } + + if (!async_url_checker_) { + std::move(callback).Run(FilteringBehavior::ALLOW, + supervised_user_error_page::DEFAULT, false); return true; } @@ -611,11 +641,8 @@ const GURL& url, safe_search_api::Classification classification, bool uncertain) const { - DCHECK(default_behavior_ != BLOCK); - FilteringBehavior behavior = GetBehaviorFromSafeSearchClassification(classification); - std::move(callback).Run(behavior, supervised_user_error_page::ASYNC_CHECKER, uncertain); for (Observer& observer : observers_) {
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.h b/chrome/browser/supervised_user/supervised_user_url_filter.h index f14ead53..2871f7d 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter.h +++ b/chrome/browser/supervised_user/supervised_user_url_filter.h
@@ -27,6 +27,10 @@ class TaskRunner; } +namespace content { +class WebContents; +} // namespace content + namespace network { class SharedURLLoaderFactory; } // namespace network @@ -75,6 +79,11 @@ SupervisedUserURLFilter(); ~SupervisedUserURLFilter(); + // Returns true if the parental allowlist/blocklist should be skipped in + // |contents|. SafeSearch filtering is still applied to |contents|. + static bool ShouldSkipParentManualAllowlistFiltering( + content::WebContents* contents); + static FilteringBehavior BehaviorFromInt(int behavior_value); static bool ReasonIsAutomatic( @@ -115,10 +124,13 @@ // Like |GetFilteringBehaviorForURL|, but also includes asynchronous checks // against a remote service. If the result is already determined by the // synchronous checks, then |callback| will be called synchronously. - // Returns true if |callback| was called synchronously. + // Returns true if |callback| was called synchronously. If + // |skip_manual_parent_filter| is set to true, it only uses the asynchronous + // safe search checks. bool GetFilteringBehaviorForURLWithAsyncChecks( const GURL& url, - FilteringBehaviorCallback callback) const; + FilteringBehaviorCallback callback, + bool skip_manual_parent_filter = false) const; // Gets all the whitelists that the url is part of. Returns id->name of each // whitelist.
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc b/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc index df9ca707..72533e1 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_url_filter_unittest.cc
@@ -73,10 +73,11 @@ void ExpectURLCheckMatches( const std::string& url, SupervisedUserURLFilter::FilteringBehavior expected_behavior, - supervised_user_error_page::FilteringBehaviorReason expected_reason) { + supervised_user_error_page::FilteringBehaviorReason expected_reason, + bool skip_manual_parent_filter = false) { bool called_synchronously = - filter_.GetFilteringBehaviorForURLWithAsyncChecks(GURL(url), - base::DoNothing()); + filter_.GetFilteringBehaviorForURLWithAsyncChecks( + GURL(url), base::DoNothing(), skip_manual_parent_filter); ASSERT_TRUE(called_synchronously); EXPECT_EQ(behavior_, expected_behavior);
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc index 979291ba..d7777aa 100644 --- a/chrome/browser/sync/test/integration/enable_disable_test.cc +++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -442,10 +442,14 @@ SetupTest(/*all_types_enabled=*/true); SyncPrefs prefs(GetProfile(0)->GetPrefs()); - ASSERT_NE("", prefs.GetCacheGuid()); + const std::string initial_cache_guid = prefs.GetCacheGuid(); + ASSERT_NE("", initial_cache_guid); GetClient(0)->StopSyncServiceAndClearData(); - EXPECT_EQ("", prefs.GetCacheGuid()); + // After "stop and clear", the SyncService may immediately start up again in + // transport-only mode, creating a new cache GUID. So the cache GUID may be + // non-empty now, but it must be different from the previous one. + EXPECT_NE(initial_cache_guid, prefs.GetCacheGuid()); } IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 4adf0f9..eacb3a8 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3486,6 +3486,8 @@ "views/in_product_help/feature_promo_colors.h", "views/in_product_help/feature_promo_controller.cc", "views/in_product_help/feature_promo_controller.h", + "views/in_product_help/feature_promo_controller_views.cc", + "views/in_product_help/feature_promo_controller_views.h", "views/in_product_help/global_media_controls_promo_controller.cc", "views/in_product_help/global_media_controls_promo_controller.h", "views/in_product_help/reopen_tab_promo_controller.cc",
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc index 5413ec3..eae60fb 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
@@ -50,12 +50,12 @@ apps::ArcRawIconPngDataToImageSkia( std::move(data_->icon), icon_dimension, base::BindOnce(&ArcAppShortcutSearchResult::SetIcon, - base::Unretained(this))); + weak_ptr_factory_.GetWeakPtr())); } else if (data_->icon && data_->icon->icon_png_data && !data_->icon->icon_png_data->empty()) { icon_decode_request_ = std::make_unique<arc::IconDecodeRequest>( base::BindOnce(&ArcAppShortcutSearchResult::SetIcon, - base::Unretained(this)), + weak_ptr_factory_.GetWeakPtr()), icon_dimension); icon_decode_request_->StartWithOptions(data_->icon->icon_png_data.value()); } else { @@ -63,7 +63,7 @@ // OS. icon_decode_request_ = std::make_unique<arc::IconDecodeRequest>( base::BindOnce(&ArcAppShortcutSearchResult::SetIcon, - base::Unretained(this)), + weak_ptr_factory_.GetWeakPtr()), icon_dimension); icon_decode_request_->StartWithOptions(data_->icon_png); }
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h index 44bac2ee..32163629 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
@@ -59,6 +59,8 @@ Profile* const profile_; // Owned by ProfileInfo. AppListControllerDelegate* const list_controller_; // Owned by AppListClient. + base::WeakPtrFactory<ArcAppShortcutSearchResult> weak_ptr_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(ArcAppShortcutSearchResult); };
diff --git a/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc index 00df4ea..c0a65c94 100644 --- a/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/tab_under_blocker_browsertest.cc
@@ -65,8 +65,7 @@ policy::PolicyMap policy; policy.Set(policy::key::kDefaultPopupsSetting, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, - policy::POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>(popup_setting), + policy::POLICY_SOURCE_CLOUD, base::Value(popup_setting), nullptr /* external_data_fetcher */); provider_.UpdateChromePolicy(policy); }
diff --git a/chrome/browser/ui/managed_ui_browsertest.cc b/chrome/browser/ui/managed_ui_browsertest.cc index 0982201..5b2a80b5 100644 --- a/chrome/browser/ui/managed_ui_browsertest.cc +++ b/chrome/browser/ui/managed_ui_browsertest.cc
@@ -43,7 +43,7 @@ policy::PolicyMap policy_map; policy_map.Set("test-policy", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM, - std::make_unique<base::Value>("hello world"), nullptr); + base::Value("hello world"), nullptr); provider()->UpdateChromePolicy(policy_map); #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc index e1623447..73eb5ccc 100644 --- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc +++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -887,7 +887,7 @@ policy::PolicyMap policies; policies.Set("DefaultSearchProviderEnabled", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_PLATFORM, - std::make_unique<base::Value>(false), nullptr); + base::Value(false), nullptr); policy_provider()->UpdateChromePolicy(policies); base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc index 8123907..f120248 100644 --- a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc +++ b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc
@@ -14,11 +14,10 @@ DiceWebSigninInterceptorDelegate::~DiceWebSigninInterceptorDelegate() = default; void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType signin_interception_type, content::WebContents* web_contents, - const AccountInfo& account_info, + const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback) { - if (signin_interception_type != + if (bubble_parameters.interception_type != DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise) { // Only the enterprise interception is currently implemented. std::move(callback).Run(false); @@ -31,6 +30,6 @@ } ShowSigninInterceptionBubbleInternal( - chrome::FindBrowserWithWebContents(web_contents), account_info, + chrome::FindBrowserWithWebContents(web_contents), bubble_parameters, std::move(callback)); }
diff --git a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h index 76fdb46..45295d1 100644 --- a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h +++ b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h
@@ -13,7 +13,6 @@ class WebContents; } -struct AccountInfo; class Browser; class DiceWebSigninInterceptorDelegate @@ -24,16 +23,15 @@ // DiceWebSigninInterceptor::Delegate void ShowSigninInterceptionBubble( - DiceWebSigninInterceptor::SigninInterceptionType signin_interception_type, content::WebContents* web_contents, - const AccountInfo& account_info, + const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback) override; private: // Implemented in dice_web_signin_interception_bubble_view.cc void ShowSigninInterceptionBubbleInternal( Browser* browser, - const AccountInfo& account_info, + const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback); };
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index d09a67a..4e9553003 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -1528,9 +1528,8 @@ policy_map_.Set(policy::key::kRestoreOnStartup, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD, base::Value(4), nullptr); - auto url_list = std::make_unique<base::Value>(base::Value::Type::LIST); - url_list->Append( - base::Value(embedded_test_server()->GetURL("/title1.html").spec())); + base::Value url_list(base::Value::Type::LIST); + url_list.Append(embedded_test_server()->GetURL("/title1.html").spec()); policy_map_.Set(policy::key::kRestoreOnStartupURLs, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD, std::move(url_list), nullptr);
diff --git a/chrome/browser/ui/startup/startup_browser_policy_unittest.cc b/chrome/browser/ui/startup/startup_browser_policy_unittest.cc index e5d3393..7540cfd9 100644 --- a/chrome/browser/ui/startup/startup_browser_policy_unittest.cc +++ b/chrome/browser/ui/startup/startup_browser_policy_unittest.cc
@@ -99,7 +99,7 @@ Args... args) { policy_map.Set(policy, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>(args...), nullptr); + base::Value(args...), nullptr); } template <typename... Args>
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index c86a605..2a92095 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -103,7 +103,7 @@ #include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.h" #include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h" #include "chrome/browser/ui/views/hats/hats_bubble_view.h" -#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h" #include "chrome/browser/ui/views/infobars/infobar_container_view.h" #include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" @@ -546,7 +546,7 @@ std::make_unique<TabStripRegionView>(std::move(tabstrip))); feature_promo_controller_ = - std::make_unique<FeaturePromoController>(browser_->profile()); + std::make_unique<FeaturePromoControllerViews>(browser_->profile()); // Must be destroyed before the tab strip and |feature_promo_controller_|. tab_groups_iph_controller_ = std::make_unique<TabGroupsIPHController>(
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 96c8f80..4a810dd 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -60,7 +60,7 @@ class ContentsLayoutManager; class DownloadShelfView; class ExclusiveAccessBubbleViews; -class FeaturePromoController; +class FeaturePromoControllerViews; class FullscreenControlHost; class InfoBarContainerView; class LocationBarView; @@ -294,7 +294,7 @@ return tab_groups_iph_controller_.get(); } - FeaturePromoController* feature_promo_controller() { + FeaturePromoControllerViews* feature_promo_controller() { return feature_promo_controller_.get(); } @@ -903,7 +903,7 @@ std::unique_ptr<AccessibilityFocusHighlight> accessibility_focus_highlight_; std::unique_ptr<TabGroupsIPHController> tab_groups_iph_controller_; - std::unique_ptr<FeaturePromoController> feature_promo_controller_; + std::unique_ptr<FeaturePromoControllerViews> feature_promo_controller_; mutable base::WeakPtrFactory<BrowserView> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc index 3a835ea..9772193e8 100644 --- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc +++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
@@ -41,7 +41,7 @@ #include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_params.h" #include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_view.h" #include "chrome/browser/ui/views/in_product_help/feature_promo_colors.h" -#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h" #include "chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_button.h" #include "chrome/browser/ui/views/toolbar/webui_tab_counter_button.h" @@ -343,7 +343,7 @@ class WebUITabStripContainerView::IPHController : public TabStripModelObserver { public: explicit IPHController(Browser* browser, - FeaturePromoController* promo_controller) + FeaturePromoControllerViews* promo_controller) : browser_(browser), promo_controller_(promo_controller), iph_tracker_(feature_engagement::TrackerFactory::GetForBrowserContext( @@ -404,7 +404,7 @@ private: Browser* const browser_; - FeaturePromoController* const promo_controller_; + FeaturePromoControllerViews* const promo_controller_; feature_engagement::Tracker* const iph_tracker_; views::ViewTracker anchor_; };
diff --git a/chrome/browser/ui/views/in_product_help/feature_promo_controller.cc b/chrome/browser/ui/views/in_product_help/feature_promo_controller.cc index d9a9213..d29bba4 100644 --- a/chrome/browser/ui/views/in_product_help/feature_promo_controller.cc +++ b/chrome/browser/ui/views/in_product_help/feature_promo_controller.cc
@@ -4,118 +4,6 @@ #include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h" -#include <utility> - -#include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "chrome/browser/feature_engagement/tracker_factory.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/views/chrome_view_class_properties.h" -#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_params.h" -#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_view.h" -#include "components/feature_engagement/public/tracker.h" - -FeaturePromoController::FeaturePromoController(Profile* profile) - : tracker_( - feature_engagement::TrackerFactory::GetForBrowserContext(profile)) { - DCHECK(tracker_); -} - -FeaturePromoController::~FeaturePromoController() { - if (!promo_bubble_) { - DCHECK_EQ(current_iph_feature_, nullptr); - return; - } - - DCHECK(current_iph_feature_); - - promo_bubble_->GetWidget()->Close(); -} - -bool FeaturePromoController::MaybeShowPromo(const base::Feature& iph_feature, - FeaturePromoBubbleParams params) { - if (!tracker_->ShouldTriggerHelpUI(iph_feature)) - return false; - - // If the tracker says we should trigger, but we have a promo - // currently showing, there is a bug somewhere in here. - DCHECK(!current_iph_feature_); - - params.anchor_view->SetProperty(kHasInProductHelpPromoKey, true); - anchor_view_tracker_.SetView(params.anchor_view); - - current_iph_feature_ = &iph_feature; - promo_bubble_ = FeaturePromoBubbleView::Create(std::move(params)); - widget_observer_.Add(promo_bubble_->GetWidget()); - - return true; -} - -bool FeaturePromoController::BubbleIsShowing( - const base::Feature& iph_feature) const { - return promo_bubble_ && current_iph_feature_ == &iph_feature; -} - -void FeaturePromoController::CloseBubble(const base::Feature& iph_feature) { - DCHECK_EQ(&iph_feature, current_iph_feature_); - DCHECK(promo_bubble_); - promo_bubble_->GetWidget()->Close(); -} - -void FeaturePromoController::UpdateBubbleForAnchorBoundsChange() { - if (!promo_bubble_) - return; - promo_bubble_->OnAnchorBoundsChanged(); -} - -FeaturePromoController::PromoHandle -FeaturePromoController::CloseBubbleAndContinuePromo( - const base::Feature& iph_feature) { - DCHECK_EQ(&iph_feature, current_iph_feature_); - DCHECK(promo_bubble_); - - widget_observer_.Remove(promo_bubble_->GetWidget()); - promo_bubble_->GetWidget()->Close(); - promo_bubble_ = nullptr; - - if (anchor_view_tracker_.view()) - anchor_view_tracker_.view()->SetProperty(kHasInProductHelpPromoKey, false); - - return PromoHandle(weak_ptr_factory_.GetWeakPtr()); -} - -void FeaturePromoController::OnWidgetClosing(views::Widget* widget) { - DCHECK(promo_bubble_); - DCHECK_EQ(widget, promo_bubble_->GetWidget()); - HandleBubbleClosed(); -} - -void FeaturePromoController::OnWidgetDestroying(views::Widget* widget) { - DCHECK(promo_bubble_); - DCHECK_EQ(widget, promo_bubble_->GetWidget()); - HandleBubbleClosed(); -} - -void FeaturePromoController::FinishContinuedPromo() { - DCHECK(current_iph_feature_); - DCHECK(!promo_bubble_); - tracker_->Dismissed(*current_iph_feature_); - current_iph_feature_ = nullptr; -} - -void FeaturePromoController::HandleBubbleClosed() { - DCHECK(current_iph_feature_); - - tracker_->Dismissed(*current_iph_feature_); - widget_observer_.Remove(promo_bubble_->GetWidget()); - - current_iph_feature_ = nullptr; - promo_bubble_ = nullptr; - - if (anchor_view_tracker_.view()) - anchor_view_tracker_.view()->SetProperty(kHasInProductHelpPromoKey, false); -} - FeaturePromoController::PromoHandle::PromoHandle( base::WeakPtr<FeaturePromoController> controller) : controller_(std::move(controller)) {}
diff --git a/chrome/browser/ui/views/in_product_help/feature_promo_controller.h b/chrome/browser/ui/views/in_product_help/feature_promo_controller.h index e8f99ae..81629bb 100644 --- a/chrome/browser/ui/views/in_product_help/feature_promo_controller.h +++ b/chrome/browser/ui/views/in_product_help/feature_promo_controller.h
@@ -6,59 +6,45 @@ #define CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_FEATURE_PROMO_CONTROLLER_H_ #include "base/memory/weak_ptr.h" -#include "base/scoped_observer.h" -#include "ui/views/view_tracker.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_observer.h" -class FeaturePromoBubbleView; struct FeaturePromoBubbleParams; -class Profile; namespace base { struct Feature; } -namespace feature_engagement { -class Tracker; -} - // Manages display of in-product help promos. All IPH displays in Top // Chrome should go through here. -class FeaturePromoController : public views::WidgetObserver { +class FeaturePromoController { public: - explicit FeaturePromoController(Profile* profile); - ~FeaturePromoController() override; + FeaturePromoController() = default; + virtual ~FeaturePromoController() = default; // Starts the promo if possible. Returns whether it started. // |iph_feature| must be an IPH feature defined in // components/feature_engagement/public/feature_list.cc. Note that // this is different than the feature that the IPH is for. - bool MaybeShowPromo(const base::Feature& iph_feature, - FeaturePromoBubbleParams params); + virtual bool MaybeShowPromo(const base::Feature& iph_feature, + FeaturePromoBubbleParams params) = 0; // Returns whether a bubble is showing for the given IPH. Note that if // this is false, a promo might still be in progress; for example, a // promo may have continued into a menu in which case the bubble is no // longer showing. - bool BubbleIsShowing(const base::Feature& iph_feature) const; + virtual bool BubbleIsShowing(const base::Feature& iph_feature) const = 0; // Close the bubble for |iph_feature| and end the promo. If no promo // is showing for |iph_feature|, or the promo has continued past the // bubble, calling this is an error. - void CloseBubble(const base::Feature& iph_feature); + virtual void CloseBubble(const base::Feature& iph_feature) = 0; class PromoHandle; // Like CloseBubble() but does not end the promo yet. The caller takes // ownership of the promo (e.g. to show a highlight in a menu or on a // button). The returned PromoHandle represents this ownership. - PromoHandle CloseBubbleAndContinuePromo(const base::Feature& iph_feature); - - // Repositions the bubble (if showing) relative to the anchor view. - // This should be called whenever the anchor view is potentially - // moved. It is safe to call this if a bubble is not showing. - void UpdateBubbleForAnchorBoundsChange(); + virtual PromoHandle CloseBubbleAndContinuePromo( + const base::Feature& iph_feature) = 0; // When a caller wants to take ownership of the promo after a bubble // is closed, this handle is given. It must be dropped in a timely @@ -77,39 +63,9 @@ base::WeakPtr<FeaturePromoController> controller_; }; - // views::WidgetObserver: - void OnWidgetClosing(views::Widget* widget) override; - void OnWidgetDestroying(views::Widget* widget) override; - - FeaturePromoBubbleView* promo_bubble_for_testing() { return promo_bubble_; } - const FeaturePromoBubbleView* promo_bubble_for_testing() const { - return promo_bubble_; - } - - private: + protected: // Called when PromoHandle is destroyed to finish the promo. - void FinishContinuedPromo(); - - void HandleBubbleClosed(); - - // IPH backend that is notified of user events and decides whether to - // trigger IPH. - feature_engagement::Tracker* const tracker_; - - // Non-null as long as a promo is showing. Corresponds to an IPH - // feature registered with |tracker_|. - const base::Feature* current_iph_feature_ = nullptr; - - // The bubble currently showing, if any. - FeaturePromoBubbleView* promo_bubble_ = nullptr; - - // Stores the bubble anchor view so we can set/unset a highlight on - // it. - views::ViewTracker anchor_view_tracker_; - - ScopedObserver<views::Widget, views::WidgetObserver> widget_observer_{this}; - - base::WeakPtrFactory<FeaturePromoController> weak_ptr_factory_{this}; + virtual void FinishContinuedPromo() = 0; }; #endif // CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_FEATURE_PROMO_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/in_product_help/feature_promo_controller_views.cc b/chrome/browser/ui/views/in_product_help/feature_promo_controller_views.cc new file mode 100644 index 0000000..553a0490 --- /dev/null +++ b/chrome/browser/ui/views/in_product_help/feature_promo_controller_views.cc
@@ -0,0 +1,119 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h" + +#include <utility> + +#include "base/logging.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/views/chrome_view_class_properties.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_params.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_view.h" +#include "components/feature_engagement/public/tracker.h" + +FeaturePromoControllerViews::FeaturePromoControllerViews(Profile* profile) + : tracker_( + feature_engagement::TrackerFactory::GetForBrowserContext(profile)) { + DCHECK(tracker_); +} + +FeaturePromoControllerViews::~FeaturePromoControllerViews() { + if (!promo_bubble_) { + DCHECK_EQ(current_iph_feature_, nullptr); + return; + } + + DCHECK(current_iph_feature_); + + promo_bubble_->GetWidget()->Close(); +} + +bool FeaturePromoControllerViews::MaybeShowPromo( + const base::Feature& iph_feature, + FeaturePromoBubbleParams params) { + if (!tracker_->ShouldTriggerHelpUI(iph_feature)) + return false; + + // If the tracker says we should trigger, but we have a promo + // currently showing, there is a bug somewhere in here. + DCHECK(!current_iph_feature_); + + params.anchor_view->SetProperty(kHasInProductHelpPromoKey, true); + anchor_view_tracker_.SetView(params.anchor_view); + + current_iph_feature_ = &iph_feature; + promo_bubble_ = FeaturePromoBubbleView::Create(std::move(params)); + widget_observer_.Add(promo_bubble_->GetWidget()); + + return true; +} + +bool FeaturePromoControllerViews::BubbleIsShowing( + const base::Feature& iph_feature) const { + return promo_bubble_ && current_iph_feature_ == &iph_feature; +} + +void FeaturePromoControllerViews::CloseBubble( + const base::Feature& iph_feature) { + DCHECK_EQ(&iph_feature, current_iph_feature_); + DCHECK(promo_bubble_); + promo_bubble_->GetWidget()->Close(); +} + +void FeaturePromoControllerViews::UpdateBubbleForAnchorBoundsChange() { + if (!promo_bubble_) + return; + promo_bubble_->OnAnchorBoundsChanged(); +} + +FeaturePromoController::PromoHandle +FeaturePromoControllerViews::CloseBubbleAndContinuePromo( + const base::Feature& iph_feature) { + DCHECK_EQ(&iph_feature, current_iph_feature_); + DCHECK(promo_bubble_); + + widget_observer_.Remove(promo_bubble_->GetWidget()); + promo_bubble_->GetWidget()->Close(); + promo_bubble_ = nullptr; + + if (anchor_view_tracker_.view()) + anchor_view_tracker_.view()->SetProperty(kHasInProductHelpPromoKey, false); + + return PromoHandle(weak_ptr_factory_.GetWeakPtr()); +} + +void FeaturePromoControllerViews::OnWidgetClosing(views::Widget* widget) { + DCHECK(promo_bubble_); + DCHECK_EQ(widget, promo_bubble_->GetWidget()); + HandleBubbleClosed(); +} + +void FeaturePromoControllerViews::OnWidgetDestroying(views::Widget* widget) { + DCHECK(promo_bubble_); + DCHECK_EQ(widget, promo_bubble_->GetWidget()); + HandleBubbleClosed(); +} + +void FeaturePromoControllerViews::FinishContinuedPromo() { + DCHECK(current_iph_feature_); + DCHECK(!promo_bubble_); + tracker_->Dismissed(*current_iph_feature_); + current_iph_feature_ = nullptr; +} + +void FeaturePromoControllerViews::HandleBubbleClosed() { + DCHECK(current_iph_feature_); + + tracker_->Dismissed(*current_iph_feature_); + widget_observer_.Remove(promo_bubble_->GetWidget()); + + current_iph_feature_ = nullptr; + promo_bubble_ = nullptr; + + if (anchor_view_tracker_.view()) + anchor_view_tracker_.view()->SetProperty(kHasInProductHelpPromoKey, false); +}
diff --git a/chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h b/chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h new file mode 100644 index 0000000..03c0552 --- /dev/null +++ b/chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h
@@ -0,0 +1,82 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_FEATURE_PROMO_CONTROLLER_VIEWS_H_ +#define CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_FEATURE_PROMO_CONTROLLER_VIEWS_H_ + +#include "base/memory/weak_ptr.h" +#include "base/scoped_observer.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h" +#include "ui/views/view_tracker.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_observer.h" + +class FeaturePromoBubbleView; +struct FeaturePromoBubbleParams; +class Profile; + +namespace base { +struct Feature; +} + +namespace feature_engagement { +class Tracker; +} + +// Views implementation of FeaturePromoController. +class FeaturePromoControllerViews : public FeaturePromoController, + public views::WidgetObserver { + public: + explicit FeaturePromoControllerViews(Profile* profile); + ~FeaturePromoControllerViews() override; + + // Repositions the bubble (if showing) relative to the anchor view. + // This should be called whenever the anchor view is potentially + // moved. It is safe to call this if a bubble is not showing. + void UpdateBubbleForAnchorBoundsChange(); + + // FeaturePromoController: + bool MaybeShowPromo(const base::Feature& iph_feature, + FeaturePromoBubbleParams params) override; + bool BubbleIsShowing(const base::Feature& iph_feature) const override; + void CloseBubble(const base::Feature& iph_feature) override; + PromoHandle CloseBubbleAndContinuePromo( + const base::Feature& iph_feature) override; + + // views::WidgetObserver: + void OnWidgetClosing(views::Widget* widget) override; + void OnWidgetDestroying(views::Widget* widget) override; + + FeaturePromoBubbleView* promo_bubble_for_testing() { return promo_bubble_; } + const FeaturePromoBubbleView* promo_bubble_for_testing() const { + return promo_bubble_; + } + + private: + // Called when PromoHandle is destroyed to finish the promo. + void FinishContinuedPromo() override; + + void HandleBubbleClosed(); + + // IPH backend that is notified of user events and decides whether to + // trigger IPH. + feature_engagement::Tracker* const tracker_; + + // Non-null as long as a promo is showing. Corresponds to an IPH + // feature registered with |tracker_|. + const base::Feature* current_iph_feature_ = nullptr; + + // The bubble currently showing, if any. + FeaturePromoBubbleView* promo_bubble_ = nullptr; + + // Stores the bubble anchor view so we can set/unset a highlight on + // it. + views::ViewTracker anchor_view_tracker_; + + ScopedObserver<views::Widget, views::WidgetObserver> widget_observer_{this}; + + base::WeakPtrFactory<FeaturePromoController> weak_ptr_factory_{this}; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_FEATURE_PROMO_CONTROLLER_VIEWS_H_
diff --git a/chrome/browser/ui/views/in_product_help/feature_promo_controller_unittest.cc b/chrome/browser/ui/views/in_product_help/feature_promo_controller_views_unittest.cc similarity index 91% rename from chrome/browser/ui/views/in_product_help/feature_promo_controller_unittest.cc rename to chrome/browser/ui/views/in_product_help/feature_promo_controller_views_unittest.cc index b00f5e79..f2178b8 100644 --- a/chrome/browser/ui/views/in_product_help/feature_promo_controller_unittest.cc +++ b/chrome/browser/ui/views/in_product_help/feature_promo_controller_views_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h" #include "base/bind.h" #include "base/feature_list.h" @@ -34,7 +34,7 @@ base::FEATURE_ENABLED_BY_DEFAULT}; } // namespace -class FeaturePromoControllerTest : public TestWithBrowserView { +class FeaturePromoControllerViewsTest : public TestWithBrowserView { public: void SetUp() override { TestWithBrowserView::SetUp(); @@ -51,7 +51,7 @@ TestWithBrowserView::GetTestingFactories(); factories.emplace_back( feature_engagement::TrackerFactory::GetInstance(), - base::BindRepeating(FeaturePromoControllerTest::MakeTestTracker)); + base::BindRepeating(FeaturePromoControllerViewsTest::MakeTestTracker)); return factories; } @@ -68,7 +68,7 @@ return params; } - FeaturePromoController* controller_; + FeaturePromoControllerViews* controller_; NiceMock<feature_engagement::test::MockTracker>* mock_tracker_; private: @@ -87,7 +87,7 @@ } }; -TEST_F(FeaturePromoControllerTest, AsksBackendToShowPromo) { +TEST_F(FeaturePromoControllerViewsTest, AsksBackendToShowPromo) { EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature))) .Times(1) .WillOnce(Return(false)); @@ -97,7 +97,7 @@ EXPECT_FALSE(controller_->promo_bubble_for_testing()); } -TEST_F(FeaturePromoControllerTest, ShowsBubble) { +TEST_F(FeaturePromoControllerViewsTest, ShowsBubble) { EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature))) .Times(1) .WillOnce(Return(true)); @@ -107,7 +107,7 @@ EXPECT_TRUE(controller_->promo_bubble_for_testing()); } -TEST_F(FeaturePromoControllerTest, PromoEndsWhenRequested) { +TEST_F(FeaturePromoControllerViewsTest, PromoEndsWhenRequested) { EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature))) .Times(1) .WillOnce(Return(true)); @@ -132,7 +132,7 @@ widget_observer.Wait(); } -TEST_F(FeaturePromoControllerTest, PromoEndsOnBubbleClosure) { +TEST_F(FeaturePromoControllerViewsTest, PromoEndsOnBubbleClosure) { EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature))) .Times(1) .WillOnce(Return(true)); @@ -156,7 +156,7 @@ EXPECT_FALSE(controller_->promo_bubble_for_testing()); } -TEST_F(FeaturePromoControllerTest, ContinuedPromoDefersBackendDismissed) { +TEST_F(FeaturePromoControllerViewsTest, ContinuedPromoDefersBackendDismissed) { EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature))) .Times(1) .WillOnce(Return(true)); @@ -189,7 +189,8 @@ promo_handle.reset(); } -TEST_F(FeaturePromoControllerTest, PropertySetOnAnchorViewWhileBubbleOpen) { +TEST_F(FeaturePromoControllerViewsTest, + PropertySetOnAnchorViewWhileBubbleOpen) { EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature))) .Times(1) .WillOnce(Return(true));
diff --git a/chrome/browser/ui/views/in_product_help/mock_feature_promo_controller.cc b/chrome/browser/ui/views/in_product_help/mock_feature_promo_controller.cc new file mode 100644 index 0000000..febbb67 --- /dev/null +++ b/chrome/browser/ui/views/in_product_help/mock_feature_promo_controller.cc
@@ -0,0 +1,8 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/in_product_help/mock_feature_promo_controller.h" + +MockFeaturePromoController::MockFeaturePromoController() = default; +MockFeaturePromoController::~MockFeaturePromoController() = default;
diff --git a/chrome/browser/ui/views/in_product_help/mock_feature_promo_controller.h b/chrome/browser/ui/views/in_product_help/mock_feature_promo_controller.h new file mode 100644 index 0000000..4c258a01 --- /dev/null +++ b/chrome/browser/ui/views/in_product_help/mock_feature_promo_controller.h
@@ -0,0 +1,32 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_MOCK_FEATURE_PROMO_CONTROLLER_H_ +#define CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_MOCK_FEATURE_PROMO_CONTROLLER_H_ + +#include "base/feature_list.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_params.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h" +#include "testing/gmock/include/gmock/gmock.h" + +class MockFeaturePromoController : public FeaturePromoController { + public: + MockFeaturePromoController(); + ~MockFeaturePromoController() override; + + // FeaturePromoController: + MOCK_METHOD(bool, + MaybeShowPromo, + (const base::Feature&, FeaturePromoBubbleParams), + (override)); + MOCK_METHOD(bool, BubbleIsShowing, (const base::Feature&), (const, override)); + MOCK_METHOD(void, CloseBubble, (const base::Feature&), (override)); + MOCK_METHOD(PromoHandle, + CloseBubbleAndContinuePromo, + (const base::Feature&), + (override)); + MOCK_METHOD(void, FinishContinuedPromo, (), (override)); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_MOCK_FEATURE_PROMO_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index ecfd0e4..c60f26c 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/command_updater_impl.h" +#include "chrome/browser/reputation/safety_tip_test_utils.h" #include "chrome/browser/search_engines/template_url_service_factory_test_util.h" #include "chrome/browser/ui/omnibox/chrome_omnibox_client.h" #include "chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.h" @@ -1624,7 +1625,10 @@ {{omnibox::kRevealSteadyStateUrlPathQueryAndRefOnHover, {}}}), {}, - GetParam().second) {} + GetParam().second) { + // The lookalike allowlist is used by the registrable-domain-elision code. + InitializeBlankLookalikeAllowlistForTesting(); + } OmniboxViewViewsRevealOnHoverTest(const OmniboxViewViewsRevealOnHoverTest&) = delete; @@ -1734,7 +1738,10 @@ kHideSteadyStateUrlPathQueryAndRefOnInteraction, {}}}), {}, - GetParam().second) {} + GetParam().second) { + // The lookalike allowlist is used by the registrable-domain-elision code. + InitializeBlankLookalikeAllowlistForTesting(); + } OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest( const OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest&) = delete; @@ -2098,7 +2105,11 @@ kHideSteadyStateUrlPathQueryAndRefOnInteraction, {}}}), {}, - GetParam().second) {} + GetParam().second) { + // The lookalike allowlist is used by the registrable-domain-elision code. + InitializeBlankLookalikeAllowlistForTesting(); + } + OmniboxViewViewsHideOnInteractionTest( const OmniboxViewViewsHideOnInteractionTest&) = delete; OmniboxViewViewsHideOnInteractionTest& operator=(
diff --git a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc index 31866fb4..5cfa825 100644 --- a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc +++ b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc
@@ -39,12 +39,14 @@ void DiceWebSigninInterceptionBubbleView::CreateBubble( content::BrowserContext* browser_context, views::View* anchor_view, - const AccountInfo& account_info, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, base::OnceCallback<void(bool)> callback) { // The widget is owned by the views system. views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble( - new DiceWebSigninInterceptionBubbleView( - browser_context, anchor_view, account_info, std::move(callback))); + new DiceWebSigninInterceptionBubbleView(browser_context, anchor_view, + bubble_parameters, + std::move(callback))); // TODO(droger): Delay showing the bubble until the web view is loaded. widget->Show(); } @@ -52,7 +54,8 @@ DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView( content::BrowserContext* browser_context, views::View* anchor_view, - const AccountInfo& account_info, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, base::OnceCallback<void(bool)> callback) : views::BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), @@ -72,7 +75,7 @@ DCHECK(web_ui); // Unretained is fine because this outlives the inner web UI. web_ui->Initialize( - account_info, + bubble_parameters, base::BindOnce(&DiceWebSigninInterceptionBubbleView::OnWebUIUserChoice, base::Unretained(this))); AddChildView(std::move(web_view)); @@ -93,7 +96,8 @@ void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal( Browser* browser, - const AccountInfo& account_info, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, base::OnceCallback<void(bool)> callback) { DCHECK(browser); views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser) @@ -101,5 +105,5 @@ ->GetAvatarToolbarButton(); DCHECK(anchor_view); DiceWebSigninInterceptionBubbleView::CreateBubble( - browser->profile(), anchor_view, account_info, std::move(callback)); + browser->profile(), anchor_view, bubble_parameters, std::move(callback)); }
diff --git a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h index f556ac9..c99d36a 100644 --- a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h +++ b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/gtest_prod_util.h" +#include "chrome/browser/signin/dice_web_signin_interceptor.h" namespace content { class BrowserContext; @@ -18,7 +19,6 @@ class View; } // namespace views -struct AccountInfo; // Bubble shown as part of Dice web signin interception. This bubble is // implemented as a WebUI page rendered inside a native bubble. @@ -32,19 +32,23 @@ DiceWebSigninInterceptionBubbleView& operator=( const DiceWebSigninInterceptionBubbleView& other) = delete; - static void CreateBubble(content::BrowserContext* browser_context, - views::View* anchor_view, - const AccountInfo& account_info, - base::OnceCallback<void(bool)> callback); + static void CreateBubble( + content::BrowserContext* browser_context, + views::View* anchor_view, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, + base::OnceCallback<void(bool)> callback); private: FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptionBubbleBrowserTest, BubbleClosed); - DiceWebSigninInterceptionBubbleView(content::BrowserContext* browser_context, - views::View* anchor_view, - const AccountInfo& account_info, - base::OnceCallback<void(bool)> callback); + DiceWebSigninInterceptionBubbleView( + content::BrowserContext* browser_context, + views::View* anchor_view, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, + base::OnceCallback<void(bool)> callback); // This bubble has no native buttons. The user accepts or cancels through this // method, which is called by the inner web UI.
diff --git a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc index 1a5ad151..1a70fefc 100644 --- a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc
@@ -25,7 +25,7 @@ // DialogBrowserTest: void ShowUi(const std::string& name) override { DiceWebSigninInterceptionBubbleView::CreateBubble( - browser()->profile(), GetAvatarButton(), AccountInfo(), + browser()->profile(), GetAvatarButton(), GetTestBubbleParameters(), base::OnceCallback<void(bool)>()); } @@ -46,6 +46,17 @@ callback_result_ = accept; } + // Returns dummy bubble parameters for testing. + DiceWebSigninInterceptor::Delegate::BubbleParameters + GetTestBubbleParameters() { + AccountInfo account; + account.account_id = CoreAccountId::FromGaiaId("ID1"); + AccountInfo primary_account; + primary_account.account_id = CoreAccountId::FromGaiaId("ID2"); + return {DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser, + account, primary_account}; + } + base::Optional<bool> callback_result_; }; @@ -59,7 +70,7 @@ BubbleClosed) { views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble( new DiceWebSigninInterceptionBubbleView( - browser()->profile(), GetAvatarButton(), AccountInfo(), + browser()->profile(), GetAvatarButton(), GetTestBubbleParameters(), base::BindOnce(&DiceWebSigninInterceptionBubbleBrowserTest:: OnInterceptionComplete, base::Unretained(this))));
diff --git a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc index 8c98940..2f060a1 100644 --- a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc +++ b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
@@ -509,7 +509,7 @@ policies.Set(policy::key::kClickToCallEnabled, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_ENTERPRISE_DEFAULT, - std::make_unique<base::Value>(policy_bool), nullptr); + base::Value(policy_bool), nullptr); } provider_.UpdateChromePolicy(policies);
diff --git a/chrome/browser/ui/views/tabs/tab_groups_iph_controller.h b/chrome/browser/ui/views/tabs/tab_groups_iph_controller.h index 860be9f..f5fcf6c 100644 --- a/chrome/browser/ui/views/tabs/tab_groups_iph_controller.h +++ b/chrome/browser/ui/views/tabs/tab_groups_iph_controller.h
@@ -36,7 +36,7 @@ // |browser| is the browser window that this instance will track and // will show IPH in if needed. |promo_controller| is the window's - // FeaturePromoController, used to start promos. |get_tab_view| should + // FeaturePromoControllerViews, used to start promos. |get_tab_view| should // get an appropriate tab to anchor the bubble in |browser|. TabGroupsIPHController(Browser* browser, FeaturePromoController* promo_controller,
diff --git a/chrome/browser/ui/views/tabs/tab_groups_iph_controller_unittest.cc b/chrome/browser/ui/views/tabs/tab_groups_iph_controller_unittest.cc index fdccb35..9ef08b5 100644 --- a/chrome/browser/ui/views/tabs/tab_groups_iph_controller_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_groups_iph_controller_unittest.cc
@@ -10,7 +10,7 @@ #include "base/bind.h" #include "chrome/browser/feature_engagement/tracker_factory.h" #include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h" +#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/views/chrome_test_widget.h" @@ -57,7 +57,7 @@ .WillRepeatedly(Return(false)); promo_controller_ = - std::make_unique<FeaturePromoController>(browser()->profile()); + std::make_unique<FeaturePromoControllerViews>(browser()->profile()); iph_controller_ = std::make_unique<TabGroupsIPHController>( browser(), promo_controller_.get(),
diff --git a/chrome/browser/ui/webui/managed_ui_handler_unittest.cc b/chrome/browser/ui/webui/managed_ui_handler_unittest.cc index c165d33a..cc1126a 100644 --- a/chrome/browser/ui/webui/managed_ui_handler_unittest.cc +++ b/chrome/browser/ui/webui/managed_ui_handler_unittest.cc
@@ -104,7 +104,7 @@ policy::PolicyMap non_empty_map; non_empty_map.Set("FakePolicyName", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>("fake"), nullptr); + base::Value("fake"), nullptr); policy_provider()->UpdateChromePolicy(non_empty_map); // Source should auto-update.
diff --git a/chrome/browser/ui/webui/management_ui_browsertest.cc b/chrome/browser/ui/webui/management_ui_browsertest.cc index 961468b..806e9c1 100644 --- a/chrome/browser/ui/webui/management_ui_browsertest.cc +++ b/chrome/browser/ui/webui/management_ui_browsertest.cc
@@ -92,7 +92,7 @@ policy::PolicyMap policy_map; policy_map.Set("test-policy", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM, - std::make_unique<base::Value>("hello world"), nullptr); + base::Value("hello world"), nullptr); provider()->UpdateExtensionPolicy(policy_map, kOnPremReportingExtensionBetaId);
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc index d301f7a91..36aee62 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
@@ -176,7 +176,7 @@ // Sets a policy update which will cause power pref managed change. void SetPolicyForPolicyKey(policy::PolicyMap* policy_map, const std::string& policy_key, - std::unique_ptr<base::Value> value) { + base::Value value) { policy_map->Set(policy_key, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, std::move(value), nullptr); @@ -224,21 +224,20 @@ // Making an arbitrary AC delay pref managed should result in the AC idle // setting being reported as managed. SetPolicyForPolicyKey(&policy_map, policy::key::kScreenDimDelayAC, - std::make_unique<base::Value>(10000)); + base::Value(10000)); DevicePowerSettings settings; settings.ac_idle_managed = true; EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage()); // Ditto for battery delay pref managed. SetPolicyForPolicyKey(&policy_map, policy::key::kScreenDimDelayBattery, - std::make_unique<base::Value>(10000)); + base::Value(10000)); settings.battery_idle_managed = true; EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage()); // Ditto for making the lid action pref managed. - SetPolicyForPolicyKey( - &policy_map, policy::key::kLidCloseAction, - std::make_unique<base::Value>(PowerPolicyController::ACTION_SUSPEND)); + SetPolicyForPolicyKey(&policy_map, policy::key::kLidCloseAction, + base::Value(PowerPolicyController::ACTION_SUSPEND)); settings.lid_closed_controlled = true; EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage()); } @@ -288,9 +287,9 @@ // Set Enterpise policy that forces AC idle action to suspend. Only possible // AC idle option visible to the user should be DISPLAY_OFF_SLEEP and the // current should also be set to same. - SetPolicyForPolicyKey(&policy_map, policy::key::kIdleActionAC, - std::make_unique<base::Value>( - chromeos::PowerPolicyController::ACTION_SUSPEND)); + SetPolicyForPolicyKey( + &policy_map, policy::key::kIdleActionAC, + base::Value(chromeos::PowerPolicyController::ACTION_SUSPEND)); DevicePowerSettings settings; std::set<PowerHandler::IdleBehavior> behaviors; behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP); @@ -301,9 +300,9 @@ // Set Enterpise policy that forces battery idle action to Shutdown. Only // possible battery idle option visible to the user then should be OTHER and // the default should also be set to same. - SetPolicyForPolicyKey(&policy_map, policy::key::kIdleActionBattery, - std::make_unique<base::Value>( - chromeos::PowerPolicyController::ACTION_SHUT_DOWN)); + SetPolicyForPolicyKey( + &policy_map, policy::key::kIdleActionBattery, + base::Value(chromeos::PowerPolicyController::ACTION_SHUT_DOWN)); behaviors.clear(); behaviors.insert(PowerHandler::IdleBehavior::OTHER); settings.possible_battery_behaviors = behaviors; @@ -317,8 +316,7 @@ // should not see DISPLAY_OFF_SLEEP in available options. SetPolicyForPolicyKey( &policy_map, policy::key::kIdleActionBattery, - std::make_unique<base::Value>( - chromeos::PowerPolicyController::ACTION_DO_NOTHING)); + base::Value(chromeos::PowerPolicyController::ACTION_DO_NOTHING)); behaviors.clear(); behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF); behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_ON); @@ -330,7 +328,7 @@ // action. The user should see only see DISPLAY_OFF as the possible battery // idle action. SetPolicyForPolicyKey(&policy_map, policy::key::kScreenOffDelayBattery, - std::make_unique<base::Value>(10000)); + base::Value(10000)); behaviors.clear(); behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF); settings.possible_battery_behaviors = behaviors;
diff --git a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc index c33bd5da..189c2a8 100644 --- a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc
@@ -107,8 +107,7 @@ // Change the policy, check that the page was notified. map()->Set(policy::key::kMetricsReportingEnabled, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, - policy::POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), - nullptr); + policy::POLICY_SOURCE_CLOUD, base::Value(true), nullptr); provider()->UpdateChromePolicy(*map()); EXPECT_EQ(1u, test_web_ui()->call_data().size()); @@ -118,8 +117,7 @@ // Policies changing while JavaScript is disabled shouldn't notify the page. map()->Set(policy::key::kMetricsReportingEnabled, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, - policy::POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false), - nullptr); + policy::POLICY_SOURCE_CLOUD, base::Value(false), nullptr); provider()->UpdateChromePolicy(*map()); EXPECT_TRUE(test_web_ui()->call_data().empty()); }
diff --git a/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc b/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc index 81aa102..378b66e 100644 --- a/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc +++ b/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc
@@ -174,7 +174,7 @@ // Sets a policy update which will cause power pref managed change. void SetPolicyForPolicyKey(policy::PolicyMap* policy_map, const std::string& policy_key, - std::unique_ptr<base::Value> value) { + base::Value value) { policy_map->Set(policy_key, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, std::move(value), nullptr); @@ -225,9 +225,8 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsPolicy) { policy::PolicyMap policy_map; - SetPolicyForPolicyKey( - &policy_map, policy::key::kDnsOverHttpsMode, - std::make_unique<base::Value>(SecureDnsConfig::kModeAutomatic)); + SetPolicyForPolicyKey(&policy_map, policy::key::kDnsOverHttpsMode, + base::Value(SecureDnsConfig::kModeAutomatic)); PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kDnsOverHttpsMode, @@ -245,9 +244,8 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsPolicyChange) { policy::PolicyMap policy_map; - SetPolicyForPolicyKey( - &policy_map, policy::key::kDnsOverHttpsMode, - std::make_unique<base::Value>(SecureDnsConfig::kModeAutomatic)); + SetPolicyForPolicyKey(&policy_map, policy::key::kDnsOverHttpsMode, + base::Value(SecureDnsConfig::kModeAutomatic)); std::string secure_dns_mode; std::vector<std::string> secure_dns_templates; @@ -258,9 +256,8 @@ EXPECT_EQ(static_cast<int>(SecureDnsConfig::ManagementMode::kNoOverride), management_mode); - SetPolicyForPolicyKey( - &policy_map, policy::key::kDnsOverHttpsMode, - std::make_unique<base::Value>(SecureDnsConfig::kModeOff)); + SetPolicyForPolicyKey(&policy_map, policy::key::kDnsOverHttpsMode, + base::Value(SecureDnsConfig::kModeOff)); EXPECT_TRUE(GetLastSettingsChangedMessage( &secure_dns_mode, &secure_dns_templates, &management_mode)); EXPECT_EQ(SecureDnsConfig::kModeOff, secure_dns_mode); @@ -274,7 +271,7 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, OtherPoliciesSet) { policy::PolicyMap policy_map; SetPolicyForPolicyKey(&policy_map, policy::key::kIncognitoModeAvailability, - std::make_unique<base::Value>(1)); + base::Value(1)); PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kDnsOverHttpsMode,
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc index 4fdb750d..ec87bde 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.cc
@@ -5,19 +5,37 @@ #include "chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h" #include "base/bind.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_attributes_entry.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/grit/chromium_strings.h" #include "content/public/browser/web_ui.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" #include "ui/gfx/image/image.h" #include "url/gurl.h" +namespace { + +// Returns true if the account is managed (aka Enterprise, or Dasher). +bool IsManaged(const AccountInfo& info) { + return info.hosted_domain != kNoHostedDomainFound; +} + +} // namespace + DiceWebSigninInterceptHandler::DiceWebSigninInterceptHandler( - const AccountInfo& account_info, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, base::OnceCallback<void(bool)> callback) - : account_info_(account_info), callback_(std::move(callback)) { + : bubble_parameters_(bubble_parameters), callback_(std::move(callback)) { DCHECK(callback_); + DCHECK_NE(intercepted_account().account_id, primary_account().account_id); } DiceWebSigninInterceptHandler::~DiceWebSigninInterceptHandler() = default; @@ -49,10 +67,30 @@ void DiceWebSigninInterceptHandler::OnExtendedAccountInfoUpdated( const AccountInfo& info) { - if (info.account_id == account_info_.account_id) { - account_info_ = info; - FireWebUIListener("account-info-changed", GetAccountInfoValue()); + if (!info.IsValid()) + return; + + bool should_fire_event = false; + if (info.account_id == intercepted_account().account_id) { + should_fire_event = true; + bubble_parameters_.intercepted_account = info; + } else if (info.account_id == primary_account().account_id) { + should_fire_event = true; + bubble_parameters_.primary_account = info; } + + if (should_fire_event) { + FireWebUIListener("interception-parameters-changed", + GetInterceptionParametersValue()); + } +} + +const AccountInfo& DiceWebSigninInterceptHandler::primary_account() { + return bubble_parameters_.primary_account; +} + +const AccountInfo& DiceWebSigninInterceptHandler::intercepted_account() { + return bubble_parameters_.intercepted_account; } void DiceWebSigninInterceptHandler::HandleAccept(const base::ListValue* args) { @@ -69,26 +107,117 @@ const base::ListValue* args) { AllowJavascript(); - // Update the account info and the image. + // Update the account info and the images. + Profile* profile = Profile::FromWebUI(web_ui()); signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui())); - base::Optional<AccountInfo> info = + IdentityManagerFactory::GetForProfile(profile); + base::Optional<AccountInfo> updated_info = identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken( - account_info_); - if (info) - account_info_ = info.value(); + intercepted_account()); + if (updated_info) + bubble_parameters_.intercepted_account = updated_info.value(); + updated_info = + identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken( + primary_account()); + if (updated_info) + bubble_parameters_.primary_account = updated_info.value(); + + // If there is no extended info for the primary account, populate with + // reasonable defaults. + if (primary_account().hosted_domain.empty()) + bubble_parameters_.primary_account.hosted_domain = kNoHostedDomainFound; + if (primary_account().given_name.empty()) { + ProfileAttributesEntry* entry = nullptr; + g_browser_process->profile_manager() + ->GetProfileAttributesStorage() + .GetProfileAttributesWithPath(profile->GetPath(), &entry); + bubble_parameters_.primary_account.given_name = + base::UTF16ToUTF8(entry->GetName()); + } const base::Value& callback_id = args->GetList()[0]; - ResolveJavascriptCallback(callback_id, GetAccountInfoValue()); + ResolveJavascriptCallback(callback_id, GetInterceptionParametersValue()); } -base::Value DiceWebSigninInterceptHandler::GetAccountInfoValue() { +base::Value DiceWebSigninInterceptHandler::GetAccountInfoValue( + const AccountInfo& info) { std::string picture_url_to_load = - account_info_.account_image.IsEmpty() + info.account_image.IsEmpty() ? profiles::GetPlaceholderAvatarIconUrl() - : webui::GetBitmapDataUrl(account_info_.account_image.AsBitmap()); + : webui::GetBitmapDataUrl(info.account_image.AsBitmap()); base::Value account_info_value(base::Value::Type::DICTIONARY); + account_info_value.SetBoolKey("isManaged", IsManaged(info)); account_info_value.SetStringKey("pictureUrl", picture_url_to_load); - account_info_value.SetStringKey("name", account_info_.given_name); return account_info_value; } + +base::Value DiceWebSigninInterceptHandler::GetInterceptionParametersValue() { + base::Value parameters(base::Value::Type::DICTIONARY); + parameters.SetStringKey("headerText", GetHeaderText()); + parameters.SetStringKey("bodyTitle", GetBodyTitle()); + parameters.SetStringKey("bodyText", GetBodyText()); + parameters.SetKey("interceptedAccount", + GetAccountInfoValue(intercepted_account())); + parameters.SetKey("primaryAccount", GetAccountInfoValue(primary_account())); + return parameters; +} + +std::string DiceWebSigninInterceptHandler::GetHeaderText() { + switch (bubble_parameters_.interception_type) { + case DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise: + return IsManaged(intercepted_account()) + ? intercepted_account().hosted_domain + : intercepted_account().given_name; + case DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser: + return primary_account().given_name; + case DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch: + return intercepted_account().given_name; + } +} + +std::string DiceWebSigninInterceptHandler::GetBodyTitle() { + switch (bubble_parameters_.interception_type) { + case DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise: + case DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser: + return IsManaged(intercepted_account()) + ? l10n_util::GetStringUTF8( + IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE) + : l10n_util::GetStringFUTF8( + IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_TITLE, + base::UTF8ToUTF16(intercepted_account().given_name)); + case DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch: + // This interception bubble is not implemented yet. + NOTREACHED(); + return ""; + } +} + +std::string DiceWebSigninInterceptHandler::GetBodyText() { + if (bubble_parameters_.interception_type == + DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch) { + // This interception bubble is not implemented yet. + NOTREACHED(); + return ""; + } + + if (IsManaged(intercepted_account())) { + DCHECK_EQ(bubble_parameters_.interception_type, + DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise); + return l10n_util::GetStringFUTF8( + IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC, + base::UTF8ToUTF16(primary_account().given_name), + base::UTF8ToUTF16(intercepted_account().hosted_domain)); + } else if (bubble_parameters_.interception_type == + DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise) { + return l10n_util::GetStringFUTF8( + IDS_SIGNIN_DICE_WEB_INTERCEPT_MIXED_BUBBLE_DESC, + base::UTF8ToUTF16(intercepted_account().given_name)); + } else { + DCHECK_EQ(bubble_parameters_.interception_type, + DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser); + return l10n_util::GetStringFUTF8( + IDS_SIGNIN_DICE_WEB_INTERCEPT_CONSUMER_BUBBLE_DESC, + base::UTF8ToUTF16(primary_account().given_name), + base::UTF8ToUTF16(intercepted_account().given_name)); + } +}
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h index 091c0d4..57a3214 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_handler.h
@@ -7,9 +7,12 @@ #include "content/public/browser/web_ui_message_handler.h" +#include <string> + #include "base/callback.h" #include "base/scoped_observer.h" #include "base/values.h" +#include "chrome/browser/signin/dice_web_signin_interceptor.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -21,8 +24,10 @@ class DiceWebSigninInterceptHandler : public content::WebUIMessageHandler, public signin::IdentityManager::Observer { public: - DiceWebSigninInterceptHandler(const AccountInfo& account_info, - base::OnceCallback<void(bool)> callback); + DiceWebSigninInterceptHandler( + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, + base::OnceCallback<void(bool)> callback); ~DiceWebSigninInterceptHandler() override; DiceWebSigninInterceptHandler(const DiceWebSigninInterceptHandler&) = delete; @@ -38,17 +43,25 @@ void OnExtendedAccountInfoUpdated(const AccountInfo& info) override; private: + const AccountInfo& primary_account(); + const AccountInfo& intercepted_account(); + void HandleAccept(const base::ListValue* args); void HandleCancel(const base::ListValue* args); void HandlePageLoaded(const base::ListValue* args); - // Gets the AccountInfo javascript value. - base::Value GetAccountInfoValue(); + // Gets the values sent to javascript. + base::Value GetAccountInfoValue(const AccountInfo& info); + base::Value GetInterceptionParametersValue(); + + std::string GetHeaderText(); + std::string GetBodyTitle(); + std::string GetBodyText(); ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer> identity_observer_{this}; + DiceWebSigninInterceptor::Delegate::BubbleParameters bubble_parameters_; - AccountInfo account_info_; base::OnceCallback<void(bool)> callback_; };
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc index b083ed04..6091f29 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.cc
@@ -12,7 +12,6 @@ #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" -#include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" @@ -48,10 +47,6 @@ source->UseStringsJs(); source->EnableReplaceI18nInJS(); static constexpr webui::LocalizedString kLocalizedStrings[] = { - {"diceWebSigninInterceptTitle", - IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_TITLE}, - {"diceWebSigninInterceptDesc", - IDS_SIGNIN_DICE_WEB_INTERCEPT_ENTERPRISE_BUBBLE_DESC}, {"diceWebSigninInterceptAcceptLabel", IDS_SIGNIN_DICE_WEB_INTERCEPT_BUBBLE_NEW_PROFILE_BUTTON_LABEL}, {"diceWebSigninInterceptCancelLabel", @@ -72,10 +67,11 @@ DiceWebSigninInterceptUI::~DiceWebSigninInterceptUI() = default; void DiceWebSigninInterceptUI::Initialize( - const AccountInfo& account_info, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, base::OnceCallback<void(bool)> callback) { web_ui()->AddMessageHandler(std::make_unique<DiceWebSigninInterceptHandler>( - account_info, std::move(callback))); + bubble_parameters, std::move(callback))); } WEB_UI_CONTROLLER_TYPE_IMPL(DiceWebSigninInterceptUI)
diff --git a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h index e2f1add..7f0793bb 100644 --- a/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h +++ b/chrome/browser/ui/webui/signin/dice_web_signin_intercept_ui.h
@@ -8,13 +8,12 @@ #include "content/public/browser/web_ui_controller.h" #include "base/callback.h" +#include "chrome/browser/signin/dice_web_signin_interceptor.h" namespace content { class WebUI; } -struct AccountInfo; - class DiceWebSigninInterceptUI : public content::WebUIController { public: explicit DiceWebSigninInterceptUI(content::WebUI* web_ui); @@ -24,7 +23,8 @@ DiceWebSigninInterceptUI& operator=(const DiceWebSigninInterceptUI&) = delete; // Initializes the DiceWebSigninInterceptUI. - void Initialize(const AccountInfo& account_info, + void Initialize(const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, base::OnceCallback<void(bool)> callback); private:
diff --git a/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.cc index 32ae905..b6f8cc8 100644 --- a/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.cc +++ b/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.cc
@@ -86,11 +86,7 @@ source == InlineLoginDialogChromeOS::Source::kArc) { return GURL(chrome::kChromeUIAccountManagerErrorURL); } - DCHECK_EQ(std::string(chrome::kChromeUIChromeSigninURL).back(), '/'); - // chrome://chrome-signin/edu - const std::string kEduAccountLoginURL = - std::string(chrome::kChromeUIChromeSigninURL) + "edu"; - return GetUrlWithEmailParam(kEduAccountLoginURL, email); + return GetUrlWithEmailParam(chrome::kChromeUIEDUCoexistenceLoginURL, email); } } // namespace
diff --git a/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc b/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc index 93201ca6..6e182ae 100644 --- a/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc +++ b/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc
@@ -28,6 +28,7 @@ #include "components/url_formatter/url_fixer.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" using content::BrowserThread; @@ -181,12 +182,22 @@ return; SupervisedUserURLFilter* filter = GetSupervisedUserService()->GetURLFilter(); + content::WebContents* web_contents = + web_ui() ? web_ui()->GetWebContents() : nullptr; + bool skip_manual_parent_filter = false; + if (web_contents) { + skip_manual_parent_filter = + filter->ShouldSkipParentManualAllowlistFiltering( + web_contents->GetOutermostWebContents()); + } + std::map<std::string, base::string16> allowlists = filter->GetMatchingWhitelistTitles(url); filter->GetFilteringBehaviorForURLWithAsyncChecks( url, base::BindOnce(&SupervisedUserInternalsMessageHandler::OnTryURLResult, - weak_factory_.GetWeakPtr(), allowlists)); + weak_factory_.GetWeakPtr(), allowlists), + skip_manual_parent_filter); } void SupervisedUserInternalsMessageHandler::SendBasicInfo() {
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc index ef97221..9707f63 100644 --- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc +++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -826,11 +826,11 @@ )"; OverrideManifest(kManifestTemplate, - {R"([ "browser", "standalone" ])", kInstallableIconList}); + {R"([ "fullscreen", "standalone" ])", kInstallableIconList}); AppId app_id = InstallWebApp(); OverrideManifest(kManifestTemplate, - {R"([ "browser", "minimal-ui" ])", kInstallableIconList}); + {R"([ "fullscreen", "minimal-ui" ])", kInstallableIconList}); EXPECT_EQ(GetResultAfterPageLoad(GetAppURL(), &app_id), ManifestUpdateResult::kAppUpdated); histogram_tester_.ExpectBucketCount(kUpdateHistogramName, @@ -841,7 +841,7 @@ GetProvider().registrar().GetAppDisplayModeOverride(app_id); ASSERT_EQ(2u, app_display_mode_override.size()); - EXPECT_EQ(DisplayMode::kBrowser, app_display_mode_override[0]); + EXPECT_EQ(DisplayMode::kFullscreen, app_display_mode_override[0]); EXPECT_EQ(DisplayMode::kMinimalUi, app_display_mode_override[1]); } @@ -989,13 +989,13 @@ )"; OverrideManifest(kManifestTemplate, - {R"([ "browser", "fullscreen" ])", kInstallableIconList}); + {R"([ "standard", "fullscreen" ])", kInstallableIconList}); AppId app_id = InstallWebApp(); // display_override contains an additional invalid value OverrideManifest( kManifestTemplate, - {R"([ "invalid", "browser", "fullscreen" ])", kInstallableIconList}); + {R"([ "invalid", "standard", "fullscreen" ])", kInstallableIconList}); EXPECT_EQ(GetResultAfterPageLoad(GetAppURL(), &app_id), ManifestUpdateResult::kAppUpToDate); histogram_tester_.ExpectBucketCount(kUpdateHistogramName,
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 76faac2..45a2ec81 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1597125357-adec03df0679051d9df22e43cd9f58968dde96e7.profdata +chrome-mac-master-1597147084-8c4cc9658838494b8781316d2fe64028822c8b91.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index c181519..d3820fac 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -575,7 +575,7 @@ // Enables usage of Parent Access Code in the login flow for reauth and add // user. Requires |kParentAccessCode| to be enabled. const base::Feature kParentAccessCodeForOnlineLogin{ - "ParentAccessCodeForOnlineLogin", base::FEATURE_DISABLED_BY_DEFAULT}; + "ParentAccessCodeForOnlineLogin", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables usage of Parent Access Code to authorize change of time actions on // child user device. Requires |kParentAccessCode| to be enabled.
diff --git a/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc b/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc index 226fb9c2..50154a5a 100644 --- a/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc +++ b/chrome/common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc
@@ -17,6 +17,7 @@ #include "extensions/common/file_util.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/content_scripts_handler.h" +#include "extensions/common/script_constants.h" #include "extensions/common/switches.h" #include "testing/gtest/include/gtest/gtest.h" @@ -114,15 +115,31 @@ ASSERT_TRUE(extension); const UserScriptList& user_scripts = ContentScriptsInfo::GetContentScripts(extension.get()); - ASSERT_EQ(3u, user_scripts.size()); + ASSERT_EQ(7u, user_scripts.size()); // The first script specifies `"match_origin_as_fallback": true`. - EXPECT_TRUE(user_scripts[0]->match_origin_as_fallback()); + EXPECT_EQ(MatchOriginAsFallbackBehavior::kAlways, + user_scripts[0]->match_origin_as_fallback()); // The second specifies `"match_origin_as_fallback": false`. - EXPECT_FALSE(user_scripts[1]->match_origin_as_fallback()); - // The third doesn't specify a value for "match_origin_as_fallback"; it - // should default to false. - EXPECT_FALSE(user_scripts[2]->match_origin_as_fallback()); + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[1]->match_origin_as_fallback()); + // The third specifies `"match_about_blank": true`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree, + user_scripts[2]->match_origin_as_fallback()); + // The fourth specifies `"match_about_blank": false`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[3]->match_origin_as_fallback()); + // The fifth specifies `"match_origin_as_fallback": false` *and* + // `"match_about_blank": true`. "match_origin_as_fallback" takes precedence. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[4]->match_origin_as_fallback()); + // The sixth specifies `"match_origin_as_fallback": true` *and* + // `"match_about_blank": false`. "match_origin_as_fallback" takes precedence. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kAlways, + user_scripts[5]->match_origin_as_fallback()); + // The seventh and final does not specify a value for either. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[6]->match_origin_as_fallback()); } TEST_F(ContentScriptsManifestTest, MatchOriginAsFallback_FeatureDisabled) { @@ -135,13 +152,33 @@ ASSERT_TRUE(extension); const UserScriptList& user_scripts = ContentScriptsInfo::GetContentScripts(extension.get()); - ASSERT_EQ(3u, user_scripts.size()); + ASSERT_EQ(7u, user_scripts.size()); - // Without the feature enabled, match_origin_as_fallback should always be - // false. - EXPECT_FALSE(user_scripts[0]->match_origin_as_fallback()); - EXPECT_FALSE(user_scripts[1]->match_origin_as_fallback()); - EXPECT_FALSE(user_scripts[2]->match_origin_as_fallback()); + // With the feature disabled, match_origin_as_fallback should be ignored. + + // The first script specifies `"match_origin_as_fallback": true`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[0]->match_origin_as_fallback()); + // The second specifies `"match_origin_as_fallback": false`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[1]->match_origin_as_fallback()); + // The third specifies `"match_about_blank": true`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree, + user_scripts[2]->match_origin_as_fallback()); + // The fourth specifies `"match_about_blank": false`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[3]->match_origin_as_fallback()); + // The fifth specifies `"match_origin_as_fallback": false` *and* + // `"match_about_blank": true`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree, + user_scripts[4]->match_origin_as_fallback()); + // The sixth specifies `"match_origin_as_fallback": true` *and* + // `"match_about_blank": false`. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[5]->match_origin_as_fallback()); + // The seventh and final does not specify a value for either. + EXPECT_EQ(MatchOriginAsFallbackBehavior::kNever, + user_scripts[6]->match_origin_as_fallback()); } } // namespace extensions
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 0e7cfe6e..52ae00f 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -68,6 +68,7 @@ const char kChromeUIDownloadsHost[] = "downloads"; const char kChromeUIDownloadsURL[] = "chrome://downloads/"; const char kChromeUIDriveInternalsHost[] = "drive-internals"; +const char kChromeUIEDUCoexistenceLoginURL[] = "chrome://chrome-signin/edu"; const char kChromeUIExtensionIconHost[] = "extension-icon"; const char kChromeUIExtensionIconURL[] = "chrome://extension-icon/"; const char kChromeUIExtensionsHost[] = "extensions";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index be1a6f0..1bddc3e 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -71,6 +71,7 @@ extern const char kChromeUIDownloadsHost[]; extern const char kChromeUIDownloadsURL[]; extern const char kChromeUIDriveInternalsHost[]; +extern const char kChromeUIEDUCoexistenceLoginURL[]; extern const char kChromeUIExtensionIconHost[]; extern const char kChromeUIExtensionIconURL[]; extern const char kChromeUIExtensionsHost[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index d79e61f..cd073087 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -359,6 +359,8 @@ "../browser/autofill/autofill_uitest_util.h", "../browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.cc", "../browser/ui/views/desktop_capture/desktop_media_picker_views_test_api.h", + "../browser/ui/views/in_product_help/mock_feature_promo_controller.cc", + "../browser/ui/views/in_product_help/mock_feature_promo_controller.h", "../browser/ui/views/media_router/app_menu_test_api.h", "../browser/ui/views/media_router/app_menu_test_api_views.cc", "../browser/ui/views/web_apps/web_app_frame_toolbar_test_mixin.cc", @@ -5557,7 +5559,7 @@ "../browser/ui/views/global_media_controls/media_notification_list_view_unittest.cc", "../browser/ui/views/global_media_controls/overlay_media_notification_view_unittest.cc", "../browser/ui/views/hover_button_unittest.cc", - "../browser/ui/views/in_product_help/feature_promo_controller_unittest.cc", + "../browser/ui/views/in_product_help/feature_promo_controller_views_unittest.cc", "../browser/ui/views/infobars/infobar_view_unittest.cc", "../browser/ui/views/intent_picker_bubble_view_unittest.cc", "../browser/ui/views/layout/interpolating_layout_manager_unittest.cc",
diff --git a/chrome/test/data/banners/manifest_display_override_contains_browser.json b/chrome/test/data/banners/manifest_display_override_contains_browser.json new file mode 100644 index 0000000..938fac0d --- /dev/null +++ b/chrome/test/data/banners/manifest_display_override_contains_browser.json
@@ -0,0 +1,13 @@ +{ + "name": "Manifest test app", + "icons": [ + { + "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQAQMAAADdiHD7AAAABlBMVEUAAAAAAAClZ7nPAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAGklEQVRIie3BMQEAAADCoPVPbQ0PoAAA4NcACrAAAcLJlncAAAAASUVORK5CYII=", + "type": "image/png", + "sizes": "192x192" + } + ], + "start_url": "manifest_test_page.html", + "display": "fullscreen", + "display_override": [ "browser", "minimal-ui", "standalone" ] +}
diff --git a/chrome/test/data/banners/manifest_display_override_display_is_browser.json b/chrome/test/data/banners/manifest_display_override_display_is_browser.json new file mode 100644 index 0000000..ffa7ec8 --- /dev/null +++ b/chrome/test/data/banners/manifest_display_override_display_is_browser.json
@@ -0,0 +1,13 @@ +{ + "name": "Manifest test app", + "icons": [ + { + "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQAQMAAADdiHD7AAAABlBMVEUAAAAAAAClZ7nPAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAGklEQVRIie3BMQEAAADCoPVPbQ0PoAAA4NcACrAAAcLJlncAAAAASUVORK5CYII=", + "type": "image/png", + "sizes": "192x192" + } + ], + "start_url": "manifest_test_page.html", + "display": "browser", + "display_override": [ "standalone" ] +}
diff --git a/chrome/test/data/extensions/manifest_tests/content_script_match_origin_as_fallback.json b/chrome/test/data/extensions/manifest_tests/content_script_match_origin_as_fallback.json index 9804cc3..29a9ccd 100644 --- a/chrome/test/data/extensions/manifest_tests/content_script_match_origin_as_fallback.json +++ b/chrome/test/data/extensions/manifest_tests/content_script_match_origin_as_fallback.json
@@ -12,7 +12,25 @@ "match_origin_as_fallback": false, "js": ["file.js"] }, { + "matches": ["https://and.example/*"], + "match_about_blank": true, + "js": ["file.js"] + }, { + "matches": ["https://another.example/*"], + "match_about_blank": false, + "js": ["file.js"] + }, { "matches": ["https://bar.example/*"], + "match_origin_as_fallback": false, + "match_about_blank": true, + "js": ["file.js"] + }, { + "matches": ["https://baz.example/*"], + "match_origin_as_fallback": true, + "match_about_blank": false, + "js": ["file.js"] + }, { + "matches": ["https://example.example/*"], "js": ["file.js"] }] }
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js index d0e8f39..5d556073 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -37,7 +37,7 @@ } }; -[['AmbientModePpage', 'ambient_mode_page_test.m.js'], +[['AmbientModePage', 'ambient_mode_page_test.m.js'], ['BluetoothPage', 'bluetooth_page_tests.m.js'], ['DateTimePage', 'date_time_page_tests.m.js'], ['InputMethodOptionPage', 'input_method_options_page_test.m.js'],
diff --git a/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js b/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js index 89a0082..b9a68b1 100644 --- a/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js +++ b/chrome/test/data/webui/signin/dice_web_signin_intercept_test.js
@@ -5,16 +5,16 @@ import 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_app.js'; import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; -import {AccountInfo, DiceWebSigninInterceptBrowserProxyImpl} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js'; +import {AccountInfo, DiceWebSigninInterceptBrowserProxyImpl, InterceptionParameters} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js'; import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js'; import {isChildVisible} from '../test_util.m.js'; import {TestDiceWebSigninInterceptBrowserProxy} from './test_dice_web_signin_intercept_browser_proxy.js'; -/** @param {!AccountInfo} account_info */ -function fireAccountInfoChanged(account_info) { - webUIListenerCallback('account-info-changed', account_info); +/** @param {!InterceptionParameters} parameters */ +function fireParametersChanged(parameters) { + webUIListenerCallback('interception-parameters-changed', parameters); } suite('DiceWebSigninInterceptTest', function() { @@ -25,12 +25,23 @@ let browserProxy; /** @type {string} */ - const PLACEHOLDER_AVATAR = - 'chrome://theme/IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE'; + const AVATAR_URL_1 = 'chrome://theme/IDR_PROFILE_AVATAR_1'; + /** @type {string} */ + const AVATAR_URL_2 = 'chrome://theme/IDR_PROFILE_AVATAR_2'; + /** @type {string} */ + const AVATAR_URL_3 = 'chrome://theme/IDR_PROFILE_AVATAR_3'; + /** @type {string} */ + const AVATAR_URL_4 = 'chrome://theme/IDR_PROFILE_AVATAR_4'; setup(function() { browserProxy = new TestDiceWebSigninInterceptBrowserProxy(); - browserProxy.setAccountInfo({pictureUrl: PLACEHOLDER_AVATAR, name: ''}); + browserProxy.setInterceptionParameters({ + headerText: 'header_text', + bodyTitle: 'body_title', + bodyText: 'body_text', + interceptedAccount: {isManaged: false, pictureUrl: AVATAR_URL_1}, + primaryAccount: {isManaged: false, pictureUrl: AVATAR_URL_2} + }); DiceWebSigninInterceptBrowserProxyImpl.instance_ = browserProxy; document.body.innerHTML = ''; app = /** @type {!DiceWebSigninInterceptAppElement} */ ( @@ -39,6 +50,28 @@ return browserProxy.whenCalled('pageLoaded'); }); + /** + * Checks that the text from the interception parameters is displayed. + * @param {string} expectedHeaderText + * @param {string} expectedBodyTitle + * @param {string} expectedBodyText + */ + function checkTextValues( + expectedHeaderText, expectedBodyTitle, expectedBodyText) { + const headerTextElement = app.$$('#headerText'); + assertEquals(expectedHeaderText, headerTextElement.textContent); + const titleElement = app.$$('#title'); + assertEquals(expectedBodyTitle, titleElement.textContent); + const contentsElement = app.$$('#contents'); + assertEquals(expectedBodyText, contentsElement.textContent); + } + + function checkImageUrl(elementId, expectedUrl) { + assertTrue(isChildVisible(app, elementId)); + const img = app.$$(elementId); + assertEquals(expectedUrl, img.src); + } + test('ClickAccept', function() { assertTrue(isChildVisible(app, '#acceptButton')); app.$$('#acceptButton').click(); @@ -51,17 +84,53 @@ return browserProxy.whenCalled('cancel'); }); - test('AccountInfo', function() { - assertTrue(isChildVisible(app, '#userAvatar')); - assertFalse(isChildVisible(app, '#accountName')); - const userImg = app.$$('#userAvatar'); - const accountNameElement = app.$$('#accountName'); - assertEquals(PLACEHOLDER_AVATAR, userImg.src); - const avatarUrl = 'chrome://theme/IDR_PROFILE_AVATAR_0'; - const accountName = 'Foo'; - fireAccountInfoChanged({pictureUrl: avatarUrl, name: accountName}); - assertEquals(avatarUrl, userImg.src); - assertEquals(accountName, accountNameElement.textContent); - assertTrue(isChildVisible(app, '#accountName')); + test('TextValues', function() { + // Initial values. + checkTextValues('header_text', 'body_title', 'body_text'); + + // Update the values. + fireParametersChanged({ + headerText: 'new_header_text', + bodyTitle: 'new_body_title', + bodyText: 'new_body_text', + interceptedAccount: {isManaged: false, pictureUrl: AVATAR_URL_1}, + primaryAccount: {isManaged: false, pictureUrl: AVATAR_URL_2} + }); + checkTextValues('new_header_text', 'new_body_title', 'new_body_text'); }); + + test('Avatars', function() { + // Consumer avatars. + checkImageUrl('#interceptedAvatarImg', AVATAR_URL_1); + checkImageUrl('#primaryAvatarImg', AVATAR_URL_2); + assertFalse(isChildVisible(app, '#interceptedBadge')); + assertFalse(isChildVisible(app, '#primaryBadge')); + + const parameters = { + headerText: 'header_text', + bodyTitle: 'body_title', + bodyText: 'body_text', + interceptedAccount: {isManaged: false, pictureUrl: AVATAR_URL_3}, + primaryAccount: {isManaged: false, pictureUrl: AVATAR_URL_4} + }; + + // Update urls. + fireParametersChanged(parameters); + checkImageUrl('#interceptedAvatarImg', AVATAR_URL_3); + checkImageUrl('#primaryAvatarImg', AVATAR_URL_4); + + // Update isManaged for intercepted account. + parameters.interceptedAccount.isManaged = true; + fireParametersChanged(parameters); + assertTrue(isChildVisible(app, '#interceptedBadge')); + assertFalse(isChildVisible(app, '#primaryBadge')); + + // Update isManaged for primary account. + parameters.interceptedAccount.isManaged = false; + parameters.primaryAccount.isManaged = true; + fireParametersChanged(parameters); + assertFalse(isChildVisible(app, '#interceptedBadge')); + assertTrue(isChildVisible(app, '#primaryBadge')); + }); + });
diff --git a/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js b/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js index dc8f88e0..9e349500 100644 --- a/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js +++ b/chrome/test/data/webui/signin/test_dice_web_signin_intercept_browser_proxy.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {AccountInfo, DiceWebSigninInterceptBrowserProxy} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js'; +import {AccountInfo, DiceWebSigninInterceptBrowserProxy, InterceptionParameters} from 'chrome://signin-dice-web-intercept/dice_web_signin_intercept_browser_proxy.js'; import {TestBrowserProxy} from '../test_browser_proxy.m.js'; @@ -10,13 +10,19 @@ export class TestDiceWebSigninInterceptBrowserProxy extends TestBrowserProxy { constructor() { super(['accept', 'cancel', 'pageLoaded']); - /** @private {!AccountInfo} */ - this.accountInfo_ = {pictureUrl: '', name: ''}; + /** @private {!InterceptionParameters} */ + this.interceptionParameters_ = { + headerText: '', + bodyTitle: '', + bodyText: '', + interceptedAccount: {isManaged: false, pictureUrl: ''}, + primaryAccount: {isManaged: false, pictureUrl: ''} + }; } - /** @param {!AccountInfo} info */ - setAccountInfo(info) { - this.accountInfo_ = info; + /** @param {!InterceptionParameters} parameters */ + setInterceptionParameters(parameters) { + this.interceptionParameters_ = parameters; } /** @override */ @@ -32,6 +38,6 @@ /** @override */ pageLoaded() { this.methodCalled('pageLoaded'); - return Promise.resolve(this.accountInfo_); + return Promise.resolve(this.interceptionParameters_); } }
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc index 22269fe..bd254f65 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.cc +++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -389,7 +389,7 @@ policy::PolicyMap policy; policy.Set(policy::key::kEnableMediaRouter, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>(enable), nullptr); + base::Value(enable), nullptr); provider_.UpdateChromePolicy(policy); base::RunLoop().RunUntilIdle(); }
diff --git a/chrome/updater/persisted_data.cc b/chrome/updater/persisted_data.cc index e3a8a0d..360ef2b 100644 --- a/chrome/updater/persisted_data.cc +++ b/chrome/updater/persisted_data.cc
@@ -125,31 +125,52 @@ return app_ids; } -std::string PersistedData::GetString(const std::string& id, - const std::string& key) const { +const base::Value* PersistedData::GetAppKey(const std::string& id) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!base::Contains(id, '.')); // Assume the id does not contain '.'. - + if (!pref_service_) + return nullptr; const base::DictionaryValue* dict = pref_service_->GetDictionary(kPersistedDataPreference); if (!dict) + return nullptr; + const base::Value* apps = dict->FindDictKey("apps"); + if (!apps) + return nullptr; + return apps->FindDictKey(id); +} + +std::string PersistedData::GetString(const std::string& id, + const std::string& key) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + const base::Value* app_key = GetAppKey(id); + if (!app_key) return {}; - std::string result; - return dict->GetString( - base::StringPrintf("apps.%s.%s", id.c_str(), key.c_str()), &result) - ? result - : std::string(); + const std::string* value = app_key->FindStringKey(key); + if (!value) + return {}; + return *value; +} + +base::Value* PersistedData::GetOrCreateAppKey(const std::string& id, + base::Value* root) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::Value* apps = root->FindDictKey("apps"); + if (!apps) + apps = root->SetKey("apps", base::Value(base::Value::Type::DICTIONARY)); + base::Value* app = apps->FindDictKey(id); + if (!app) + app = apps->SetKey(id, base::Value(base::Value::Type::DICTIONARY)); + return app; } void PersistedData::SetString(const std::string& id, const std::string& key, const std::string& value) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!base::Contains(id, '.')); // Assume the id does not contain '.'. - + if (!pref_service_) + return; DictionaryPrefUpdate update(pref_service_, kPersistedDataPreference); - update->SetString(base::StringPrintf("apps.%s.%s", id.c_str(), key.c_str()), - value); + GetOrCreateAppKey(id, update.Get())->SetStringKey(key, value); } } // namespace updater
diff --git a/chrome/updater/persisted_data.h b/chrome/updater/persisted_data.h index ca5d0f1..f0078e7 100644 --- a/chrome/updater/persisted_data.h +++ b/chrome/updater/persisted_data.h
@@ -15,6 +15,7 @@ namespace base { class FilePath; +class Value; class Version; } // namespace base @@ -72,6 +73,12 @@ friend class base::RefCountedThreadSafe<PersistedData>; ~PersistedData(); + // Returns nullptr if the app key does not exist. + const base::Value* GetAppKey(const std::string& id) const; + + // Returns an existing or newly created app key under a root pref. + base::Value* GetOrCreateAppKey(const std::string& id, base::Value* root); + std::string GetString(const std::string& id, const std::string& key) const; void SetString(const std::string& id, const std::string& key,
diff --git a/chromecast/browser/cast_web_contents.h b/chromecast/browser/cast_web_contents.h index b921830d..171cddf 100644 --- a/chromecast/browser/cast_web_contents.h +++ b/chromecast/browser/cast_web_contents.h
@@ -269,6 +269,10 @@ // same tab ID at any given time. virtual int tab_id() const = 0; + // An identifier for the WebContents, mainly used by platform views service. + // IDs may be re-used but are unique among all live CastWebContents. + virtual int id() const = 0; + // TODO(seantopping): Hide this, clients shouldn't use WebContents directly. virtual content::WebContents* web_contents() const = 0; virtual PageState page_state() const = 0;
diff --git a/chromecast/browser/cast_web_contents_impl.cc b/chromecast/browser/cast_web_contents_impl.cc index 00fd4cd..e9288081 100644 --- a/chromecast/browser/cast_web_contents_impl.cc +++ b/chromecast/browser/cast_web_contents_impl.cc
@@ -53,6 +53,9 @@ // IDs start at 1, since 0 is reserved for the root content window. size_t next_tab_id = 1; +// Next id for id() +size_t next_id = 0; + // Remove the given CastWebContents pointer from the global instance vector. void RemoveCastWebContents(CastWebContents* instance) { auto& all_cast_web_contents = CastWebContents::GetAll(); @@ -129,6 +132,7 @@ activity_url_filter_(std::move(init_params.url_filters)), main_process_host_(nullptr), tab_id_(init_params.is_root_window ? 0 : next_tab_id++), + id_(next_id++), is_websql_enabled_(init_params.enable_websql), is_mixer_audio_enabled_(init_params.enable_mixer_audio), main_frame_loaded_(false), @@ -185,6 +189,10 @@ return tab_id_; } +int CastWebContentsImpl::id() const { + return id_; +} + content::WebContents* CastWebContentsImpl::web_contents() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return web_contents_;
diff --git a/chromecast/browser/cast_web_contents_impl.h b/chromecast/browser/cast_web_contents_impl.h index 696f53c..247872f2 100644 --- a/chromecast/browser/cast_web_contents_impl.h +++ b/chromecast/browser/cast_web_contents_impl.h
@@ -56,6 +56,7 @@ // CastWebContents implementation: int tab_id() const override; + int id() const override; void AddRendererFeatures(std::vector<RendererFeature> features) override; void AllowWebAndMojoWebUiBindings() override; void ClearRenderWidgetHostView() override; @@ -166,6 +167,7 @@ std::vector<RendererFeature> renderer_features_; const int tab_id_; + const int id_; bool is_websql_enabled_; bool is_mixer_audio_enabled_; base::TimeTicks start_loading_ticks_;
diff --git a/chromecast/browser/test/mock_cast_web_view.h b/chromecast/browser/test/mock_cast_web_view.h index c3df3b2..e1cc121 100644 --- a/chromecast/browser/test/mock_cast_web_view.h +++ b/chromecast/browser/test/mock_cast_web_view.h
@@ -17,6 +17,7 @@ // CastWebContents implementation MOCK_METHOD(int, tab_id, (), (const, override)); + MOCK_METHOD(int, id, (), (const, override)); MOCK_METHOD(content::WebContents*, web_contents, (), (const, override)); MOCK_METHOD(PageState, page_state, (), (const, override)); MOCK_METHOD(QueryableDataHost*, queryable_data_host, (), (const, override));
diff --git a/chromecast/browser/webview/webview_controller.cc b/chromecast/browser/webview/webview_controller.cc index 2964975..aea2d5b1 100644 --- a/chromecast/browser/webview/webview_controller.cc +++ b/chromecast/browser/webview/webview_controller.cc
@@ -76,12 +76,12 @@ std::unique_ptr<webview::WebviewResponse> response = std::make_unique<webview::WebviewResponse>(); - // For webviews, set the ax_id to be the cast_web_contents' tab id rather than - // the ax tree id for the main frame. The main frame can be replaced after - // we've set this from navigation. Prefix the string with "T:" to tell the ax - // bridge to find the cast_web_contents by tab id. Then it can find the - // current ax tree id from that. - std::string ax_id = "T:" + base::NumberToString(cast_web_contents_->tab_id()); + // For webviews, set the ax_id to be the cast_web_contents' id + // rather than the ax tree id for the main frame. The main frame can be + // replaced after we've set this from navigation. Prefix the string with + // "T:" to tell the ax bridge to find the cast_web_contents by id. + // Then it can find the current ax tree id from that. + std::string ax_id = "T:" + base::NumberToString(cast_web_contents_->id()); response->mutable_create_response() ->mutable_accessibility_info() ->set_ax_tree_id(ax_id);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 540a706..840b9d3 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13398.0.0 \ No newline at end of file +13399.0.0 \ No newline at end of file
diff --git a/chromeos/components/BUILD.gn b/chromeos/components/BUILD.gn index 1efd27c..8b56d3e 100644 --- a/chromeos/components/BUILD.gn +++ b/chromeos/components/BUILD.gn
@@ -22,6 +22,7 @@ "//chromeos/components/local_search_service/mojom:unit_tests", "//chromeos/components/mojo_bootstrap:unit_tests", "//chromeos/components/multidevice:unit_tests", + "//chromeos/components/phonehub:unit_tests", "//chromeos/components/power:unit_tests", "//chromeos/components/proximity_auth:unit_tests", "//chromeos/components/quick_answers:unit_tests",
diff --git a/chromeos/components/phonehub/BUILD.gn b/chromeos/components/phonehub/BUILD.gn new file mode 100644 index 0000000..308be82 --- /dev/null +++ b/chromeos/components/phonehub/BUILD.gn
@@ -0,0 +1,61 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//testing/test.gni") + +assert(is_chromeos, "Phone Hub is Chrome OS only") + +static_library("phonehub") { + sources = [ + "feature_status.cc", + "feature_status.h", + "feature_status_provider.cc", + "feature_status_provider.h", + "feature_status_provider_impl.cc", + "feature_status_provider_impl.h", + ] + + deps = [ + "//base", + "//chromeos/components/multidevice", + "//chromeos/components/multidevice/logging", + "//chromeos/services/device_sync/public/cpp", + "//chromeos/services/multidevice_setup/public/cpp", + "//device/bluetooth", + ] +} + +static_library("test_support") { + testonly = true + + sources = [ + "fake_feature_status_provider.cc", + "fake_feature_status_provider.h", + ] + + public_deps = [ ":phonehub" ] + + deps = [ "//base" ] +} + +source_set("unit_tests") { + testonly = true + + sources = [ "feature_status_provider_impl_unittest.cc" ] + + deps = [ + ":phonehub", + ":test_support", + "//base", + "//base/test:test_support", + "//chromeos/components/multidevice", + "//chromeos/components/multidevice:test_support", + "//chromeos/services/device_sync/public/cpp", + "//chromeos/services/device_sync/public/cpp:test_support", + "//chromeos/services/multidevice_setup/public/cpp", + "//chromeos/services/multidevice_setup/public/cpp:test_support", + "//device/bluetooth:mocks", + "//testing/gtest", + ] +}
diff --git a/chromeos/components/phonehub/DEPS b/chromeos/components/phonehub/DEPS new file mode 100644 index 0000000..8145cd9 --- /dev/null +++ b/chromeos/components/phonehub/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+chromeos/components/multidevice", + "+chromeos/services/device_sync/public/cpp", + "+chromeos/services/multidevice_setup/public/cpp", + "+device/bluetooth", +]
diff --git a/chromeos/components/phonehub/fake_feature_status_provider.cc b/chromeos/components/phonehub/fake_feature_status_provider.cc new file mode 100644 index 0000000..ed90a083 --- /dev/null +++ b/chromeos/components/phonehub/fake_feature_status_provider.cc
@@ -0,0 +1,32 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/phonehub/fake_feature_status_provider.h" + +namespace chromeos { +namespace phonehub { + +FakeFeatureStatusProvider::FakeFeatureStatusProvider() + : FakeFeatureStatusProvider(FeatureStatus::kEnabledAndConnected) {} + +FakeFeatureStatusProvider::FakeFeatureStatusProvider( + FeatureStatus initial_status) + : status_(initial_status) {} + +FakeFeatureStatusProvider::~FakeFeatureStatusProvider() = default; + +void FakeFeatureStatusProvider::SetStatus(FeatureStatus status) { + if (status == status_) + return; + + status_ = status; + NotifyStatusChanged(); +} + +FeatureStatus FakeFeatureStatusProvider::GetStatus() const { + return status_; +} + +} // namespace phonehub +} // namespace chromeos
diff --git a/chromeos/components/phonehub/fake_feature_status_provider.h b/chromeos/components/phonehub/fake_feature_status_provider.h new file mode 100644 index 0000000..964e742 --- /dev/null +++ b/chromeos/components/phonehub/fake_feature_status_provider.h
@@ -0,0 +1,32 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_COMPONENTS_PHONEHUB_FAKE_FEATURE_STATUS_PROVIDER_H_ +#define CHROMEOS_COMPONENTS_PHONEHUB_FAKE_FEATURE_STATUS_PROVIDER_H_ + +#include "chromeos/components/phonehub/feature_status_provider.h" + +namespace chromeos { +namespace phonehub { + +class FakeFeatureStatusProvider : public FeatureStatusProvider { + public: + // Defaults initial status to kEnabledAndConnected. + FakeFeatureStatusProvider(); + FakeFeatureStatusProvider(FeatureStatus initial_status); + ~FakeFeatureStatusProvider() override; + + void SetStatus(FeatureStatus status); + + // FeatureStatusProvider: + FeatureStatus GetStatus() const override; + + private: + FeatureStatus status_; +}; + +} // namespace phonehub +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_PHONEHUB_FAKE_FEATURE_STATUS_PROVIDER_H_
diff --git a/chromeos/components/phonehub/feature_status.cc b/chromeos/components/phonehub/feature_status.cc new file mode 100644 index 0000000..d4917f1 --- /dev/null +++ b/chromeos/components/phonehub/feature_status.cc
@@ -0,0 +1,45 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/phonehub/feature_status.h" + +namespace chromeos { +namespace phonehub { + +std::ostream& operator<<(std::ostream& stream, FeatureStatus status) { + switch (status) { + case FeatureStatus::kNotEligibleForFeature: + stream << "[Not eligible for feature]"; + break; + case FeatureStatus::kEligiblePhoneButNotSetUp: + stream << "[Eligible phone but not set up]"; + break; + case FeatureStatus::kPhoneSelectedAndPendingSetup: + stream << "[Phone selected and pending setup]"; + break; + case FeatureStatus::kProhibitedByPolicy: + stream << "[Prohibited by policy]"; + break; + case FeatureStatus::kDisabled: + stream << "[Disabled]"; + break; + case FeatureStatus::kUnavailableBluetoothOff: + stream << "[Unavailable; Bluetooth off]"; + break; + case FeatureStatus::kEnabledButDisconnected: + stream << "[Enabled; disconnected]"; + break; + case FeatureStatus::kEnabledAndConnecting: + stream << "[Enabled; connecting]"; + break; + case FeatureStatus::kEnabledAndConnected: + stream << "[Enabled; connected]"; + break; + } + + return stream; +} + +} // namespace phonehub +} // namespace chromeos
diff --git a/chromeos/components/phonehub/feature_status.h b/chromeos/components/phonehub/feature_status.h new file mode 100644 index 0000000..c37917b --- /dev/null +++ b/chromeos/components/phonehub/feature_status.h
@@ -0,0 +1,56 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_H_ +#define CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_H_ + +#include <ostream> + +namespace chromeos { +namespace phonehub { + +// Enum representing potential status values for the Phone Hub feature. +enum class FeatureStatus { + // The user's devices are not eligible for the feature. This means that either + // the Chrome OS device or the user's phone (or both) have not enrolled with + // the requisite feature enum values. + kNotEligibleForFeature = 0, + + // The user has a phone eligible for the feature, but they have not yet + // started the opt-in flow. + kEligiblePhoneButNotSetUp = 1, + + // The user has selected a phone in the opt-in flow, but setup is not yet + // complete. Note that setting up the feature requires interaction with a + // server and with the phone itself. + kPhoneSelectedAndPendingSetup = 2, + + // An enterprise policy has prohibited this feature from running. + kProhibitedByPolicy = 3, + + // The feature is disabled, but the user could enable it via settings. + kDisabled = 4, + + // The feature is enabled, but it is currently unavailable because Bluetooth + // is disabled (the feature cannot run without Bluetooth). + kUnavailableBluetoothOff = 5, + + // The feature is enabled, but currently there is no active connection to + // the phone. + kEnabledButDisconnected = 6, + + // The feature is enabled, and there is an active attempt to connect to the + // phone. + kEnabledAndConnecting = 7, + + // The feature is enabled, and there is an active connection with the phone. + kEnabledAndConnected = 8 +}; + +std::ostream& operator<<(std::ostream& stream, FeatureStatus status); + +} // namespace phonehub +} // namespace chromeos + +#endif // CHROMEOS_CO MPONENTS_PHONEHUB_FEATURE_STATUS_H_
diff --git a/chromeos/components/phonehub/feature_status_provider.cc b/chromeos/components/phonehub/feature_status_provider.cc new file mode 100644 index 0000000..19525a7 --- /dev/null +++ b/chromeos/components/phonehub/feature_status_provider.cc
@@ -0,0 +1,28 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/phonehub/feature_status_provider.h" + +namespace chromeos { +namespace phonehub { + +FeatureStatusProvider::FeatureStatusProvider() = default; + +FeatureStatusProvider::~FeatureStatusProvider() = default; + +void FeatureStatusProvider::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void FeatureStatusProvider::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +void FeatureStatusProvider::NotifyStatusChanged() { + for (auto& observer : observer_list_) + observer.OnStatusChanged(); +} + +} // namespace phonehub +} // namespace chromeos
diff --git a/chromeos/components/phonehub/feature_status_provider.h b/chromeos/components/phonehub/feature_status_provider.h new file mode 100644 index 0000000..83bfa8d5 --- /dev/null +++ b/chromeos/components/phonehub/feature_status_provider.h
@@ -0,0 +1,48 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_H_ +#define CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_H_ + +#include "base/observer_list.h" +#include "base/observer_list_types.h" +#include "chromeos/components/phonehub/feature_status.h" + +namespace chromeos { +namespace phonehub { + +// Provides the current status of Phone Hub and notifies observers when the +// status changes. +class FeatureStatusProvider { + public: + class Observer : public base::CheckedObserver { + public: + ~Observer() override = default; + + // Called when the status has changed; use GetStatus() for the new status. + virtual void OnStatusChanged() = 0; + }; + + FeatureStatusProvider(const FeatureStatusProvider&) = delete; + FeatureStatusProvider& operator=(const FeatureStatusProvider&) = delete; + virtual ~FeatureStatusProvider(); + + virtual FeatureStatus GetStatus() const = 0; + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + protected: + FeatureStatusProvider(); + + void NotifyStatusChanged(); + + private: + base::ObserverList<Observer> observer_list_; +}; + +} // namespace phonehub +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_H_
diff --git a/chromeos/components/phonehub/feature_status_provider_impl.cc b/chromeos/components/phonehub/feature_status_provider_impl.cc new file mode 100644 index 0000000..fea23f5 --- /dev/null +++ b/chromeos/components/phonehub/feature_status_provider_impl.cc
@@ -0,0 +1,226 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/phonehub/feature_status_provider_impl.h" + +#include <utility> + +#include "base/bind.h" +#include "chromeos/components/multidevice/logging/logging.h" +#include "chromeos/components/multidevice/remote_device_ref.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" + +namespace chromeos { +namespace phonehub { +namespace { + +using multidevice::RemoteDeviceRef; +using multidevice::RemoteDeviceRefList; +using multidevice::SoftwareFeature; +using multidevice::SoftwareFeatureState; + +using multidevice_setup::mojom::Feature; +using multidevice_setup::mojom::FeatureState; +using multidevice_setup::mojom::HostStatus; + +bool IsEligibleForFeature( + const base::Optional<multidevice::RemoteDeviceRef>& local_device, + const RemoteDeviceRefList& remote_devices) { + // If the local device has not yet been enrolled, no phone can serve as its + // Phone Hub host. + if (!local_device) + return false; + + // If the local device does not support being a Phone Hub client, no phone can + // serve as its host. + if (local_device->GetSoftwareFeatureState(SoftwareFeature::kPhoneHubClient) == + SoftwareFeatureState::kNotSupported) { + return false; + } + + // If the local device does not have an enrolled Bluetooth address, no phone + // can serve as its host. + if (local_device->bluetooth_public_address().empty()) + return false; + + for (const RemoteDeviceRef& device : remote_devices) { + // Device must be capable of being a multi-device host. + if (device.GetSoftwareFeatureState(SoftwareFeature::kBetterTogetherHost) == + SoftwareFeatureState::kNotSupported) { + continue; + } + + // Device must be capable of being a Phone Hub host. + if (device.GetSoftwareFeatureState(SoftwareFeature::kPhoneHubHost) == + SoftwareFeatureState::kNotSupported) { + continue; + } + + // Device must have a synced Bluetooth public address, which is used to + // bootstrap Phone Hub connections. + if (device.bluetooth_public_address().empty()) + continue; + + return true; + }; + + // If none of the devices return true above, there are no phones capable of + // Phone Hub connections on the account. + return false; +} + +bool IsPhonePendingSetup(HostStatus host_status, FeatureState feature_state) { + // The user has completed the opt-in flow, but we have not yet notified the + // back-end of this selection. One common cause of this state is when the user + // completes setup while offline. + if (host_status == + HostStatus::kHostSetLocallyButWaitingForBackendConfirmation) { + return true; + } + + // The device has been set up with the back-end, but the phone has not yet + // enabled itself. + if (host_status == HostStatus::kHostSetButNotYetVerified) + return true; + + // The phone has enabled itself for the multi-device suite but has not yet + // enabled itself for Phone Hub. Note that kNotSupportedByPhone is a bit of a + // misnomer here; this value means that the phone has advertised support for + // the feature but has not yet enabled it. + return host_status == HostStatus::kHostVerified && + feature_state == FeatureState::kNotSupportedByPhone; +} + +bool IsFeatureDisabledByUser(FeatureState feature_state) { + return feature_state == FeatureState::kDisabledByUser || + feature_state == FeatureState::kUnavailableSuiteDisabled || + feature_state == FeatureState::kUnavailableTopLevelFeatureDisabled; +} + +} // namespace + +FeatureStatusProviderImpl::FeatureStatusProviderImpl( + device_sync::DeviceSyncClient* device_sync_client, + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client) + : device_sync_client_(device_sync_client), + multidevice_setup_client_(multidevice_setup_client) { + device_sync_client_->AddObserver(this); + multidevice_setup_client_->AddObserver(this); + + device::BluetoothAdapterFactory::Get()->GetAdapter( + base::BindOnce(&FeatureStatusProviderImpl::OnBluetoothAdapterReceived, + weak_ptr_factory_.GetWeakPtr())); + + status_ = ComputeStatus(); +} + +FeatureStatusProviderImpl::~FeatureStatusProviderImpl() { + device_sync_client_->RemoveObserver(this); + multidevice_setup_client_->RemoveObserver(this); + if (bluetooth_adapter_) + bluetooth_adapter_->RemoveObserver(this); +} + +FeatureStatus FeatureStatusProviderImpl::GetStatus() const { + return *status_; +} + +void FeatureStatusProviderImpl::OnReady() { + UpdateStatus(); +} + +void FeatureStatusProviderImpl::OnNewDevicesSynced() { + UpdateStatus(); +} + +void FeatureStatusProviderImpl::OnHostStatusChanged( + const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice& + host_device_with_status) { + UpdateStatus(); +} + +void FeatureStatusProviderImpl::OnFeatureStatesChanged( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + UpdateStatus(); +} + +void FeatureStatusProviderImpl::AdapterPresentChanged( + device::BluetoothAdapter* adapter, + bool present) { + UpdateStatus(); +} + +void FeatureStatusProviderImpl::AdapterPoweredChanged( + device::BluetoothAdapter* adapter, + bool powered) { + UpdateStatus(); +} + +void FeatureStatusProviderImpl::OnBluetoothAdapterReceived( + scoped_refptr<device::BluetoothAdapter> bluetooth_adapter) { + bluetooth_adapter_ = std::move(bluetooth_adapter); + bluetooth_adapter_->AddObserver(this); + + // If |status_| has not yet been set, this call occurred synchronously in the + // constructor, so status_ has not yet been initialized. + if (status_.has_value()) + UpdateStatus(); +} + +void FeatureStatusProviderImpl::UpdateStatus() { + DCHECK(status_.has_value()); + + FeatureStatus computed_status = ComputeStatus(); + if (computed_status == *status_) + return; + + PA_LOG(INFO) << "Phone Hub feature status: " << *status_ << " => " + << computed_status; + *status_ = computed_status; + NotifyStatusChanged(); +} + +FeatureStatus FeatureStatusProviderImpl::ComputeStatus() { + if (!IsEligibleForFeature(device_sync_client_->GetLocalDeviceMetadata(), + device_sync_client_->GetSyncedDevices())) { + return FeatureStatus::kNotEligibleForFeature; + } + + HostStatus host_status = multidevice_setup_client_->GetHostStatus().first; + + if (host_status == HostStatus::kEligibleHostExistsButNoHostSet) + return FeatureStatus::kEligiblePhoneButNotSetUp; + + FeatureState feature_state = + multidevice_setup_client_->GetFeatureState(Feature::kPhoneHub); + + if (IsPhonePendingSetup(host_status, feature_state)) + return FeatureStatus::kPhoneSelectedAndPendingSetup; + + if (feature_state == FeatureState::kProhibitedByPolicy) + return FeatureStatus::kProhibitedByPolicy; + + if (IsFeatureDisabledByUser(feature_state)) + return FeatureStatus::kDisabled; + + if (!IsBluetoothOn()) + return FeatureStatus::kUnavailableBluetoothOff; + + // TODO(khorimoto): Return different statuses based on whether we have an + // active connection. + return FeatureStatus::kEnabledButDisconnected; +} + +bool FeatureStatusProviderImpl::IsBluetoothOn() const { + if (!bluetooth_adapter_) + return false; + + return bluetooth_adapter_->IsPresent() && bluetooth_adapter_->IsPowered(); +} + +} // namespace phonehub +} // namespace chromeos
diff --git a/chromeos/components/phonehub/feature_status_provider_impl.h b/chromeos/components/phonehub/feature_status_provider_impl.h new file mode 100644 index 0000000..be40382 --- /dev/null +++ b/chromeos/components/phonehub/feature_status_provider_impl.h
@@ -0,0 +1,75 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_IMPL_H_ +#define CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_IMPL_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "chromeos/components/phonehub/feature_status_provider.h" +#include "chromeos/services/device_sync/public/cpp/device_sync_client.h" +#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h" +#include "device/bluetooth/bluetooth_adapter.h" + +namespace chromeos { + +namespace phonehub { + +// FeatureStatusProvider implementation which utilizes DeviceSyncClient, +// MultiDeviceSetupClient and BluetoothAdapter to determine the current status. +// TODO(khorimoto): Add metrics for initial status and status changes. +class FeatureStatusProviderImpl + : public FeatureStatusProvider, + public device_sync::DeviceSyncClient::Observer, + public multidevice_setup::MultiDeviceSetupClient::Observer, + public device::BluetoothAdapter::Observer { + public: + FeatureStatusProviderImpl( + device_sync::DeviceSyncClient* device_sync_client, + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client); + ~FeatureStatusProviderImpl() override; + + private: + friend class FeatureStatusProviderImplTest; + + // FeatureStatusProvider: + FeatureStatus GetStatus() const override; + + // device_sync::DeviceSyncClient::Observer: + void OnReady() override; + void OnNewDevicesSynced() override; + + // multidevice_setup::MultiDeviceSetupClient::Observer: + void OnHostStatusChanged( + const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice& + host_device_with_status) override; + void OnFeatureStatesChanged( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) override; + + void OnBluetoothAdapterReceived( + scoped_refptr<device::BluetoothAdapter> bluetooth_adapter); + void UpdateStatus(); + FeatureStatus ComputeStatus(); + bool IsBluetoothOn() const; + + // device::BluetoothAdapter::Observer: + void AdapterPresentChanged(device::BluetoothAdapter* adapter, + bool present) override; + void AdapterPoweredChanged(device::BluetoothAdapter* adapter, + bool powered) override; + + device_sync::DeviceSyncClient* device_sync_client_; + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_; + + scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; + base::Optional<FeatureStatus> status_; + + base::WeakPtrFactory<FeatureStatusProviderImpl> weak_ptr_factory_{this}; +}; + +} // namespace phonehub +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_PHONEHUB_FEATURE_STATUS_PROVIDER_IMPL_H_
diff --git a/chromeos/components/phonehub/feature_status_provider_impl_unittest.cc b/chromeos/components/phonehub/feature_status_provider_impl_unittest.cc new file mode 100644 index 0000000..1aab330 --- /dev/null +++ b/chromeos/components/phonehub/feature_status_provider_impl_unittest.cc
@@ -0,0 +1,369 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/components/phonehub/feature_status_provider_impl.h" + +#include <memory> + +#include "base/test/task_environment.h" +#include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" +#include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace phonehub { +namespace { + +using multidevice_setup::mojom::Feature; +using multidevice_setup::mojom::FeatureState; +using multidevice_setup::mojom::HostStatus; + +const char kLocalDeviceBluetoothAddress[] = "01:23:45:67:89:AB"; +const char kPhoneBluetoothAddress[] = "23:45:67:89:AB:CD"; + +multidevice::RemoteDeviceRef CreateLocalDevice(bool supports_phone_hub_client, + bool has_bluetooth_address) { + multidevice::RemoteDeviceRefBuilder builder; + + builder.SetSoftwareFeatureState( + multidevice::SoftwareFeature::kPhoneHubClient, + supports_phone_hub_client + ? multidevice::SoftwareFeatureState::kSupported + : multidevice::SoftwareFeatureState::kNotSupported); + builder.SetBluetoothPublicAddress( + has_bluetooth_address ? kLocalDeviceBluetoothAddress : std::string()); + + return builder.Build(); +} + +multidevice::RemoteDeviceRef CreatePhoneDevice( + bool supports_better_together_host, + bool supports_phone_hub_host, + bool has_bluetooth_address) { + multidevice::RemoteDeviceRefBuilder builder; + + builder.SetSoftwareFeatureState( + multidevice::SoftwareFeature::kBetterTogetherHost, + supports_better_together_host + ? multidevice::SoftwareFeatureState::kSupported + : multidevice::SoftwareFeatureState::kNotSupported); + builder.SetSoftwareFeatureState( + multidevice::SoftwareFeature::kPhoneHubHost, + supports_phone_hub_host + ? multidevice::SoftwareFeatureState::kSupported + : multidevice::SoftwareFeatureState::kNotSupported); + builder.SetBluetoothPublicAddress( + has_bluetooth_address ? kPhoneBluetoothAddress : std::string()); + + return builder.Build(); +} + +class FakeObserver : public FeatureStatusProvider::Observer { + public: + FakeObserver() = default; + ~FakeObserver() override = default; + + size_t num_calls() const { return num_calls_; } + + // FeatureStatusProvider::Observer: + void OnStatusChanged() override { ++num_calls_; } + + private: + size_t num_calls_ = 0; +}; + +} // namespace + +class FeatureStatusProviderImplTest : public testing::Test { + protected: + FeatureStatusProviderImplTest() = default; + FeatureStatusProviderImplTest(const FeatureStatusProviderImplTest&) = delete; + FeatureStatusProviderImplTest& operator=( + const FeatureStatusProviderImplTest&) = delete; + ~FeatureStatusProviderImplTest() override = default; + + // testing::Test: + void SetUp() override { + mock_adapter_ = + base::MakeRefCounted<testing::NiceMock<device::MockBluetoothAdapter>>(); + is_adapter_present_ = true; + ON_CALL(*mock_adapter_, IsPresent()) + .WillByDefault( + Invoke(this, &FeatureStatusProviderImplTest::is_adapter_present)); + ON_CALL(*mock_adapter_, IsPowered()) + .WillByDefault( + Invoke(this, &FeatureStatusProviderImplTest::is_adapter_powered)); + device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_); + + provider_ = std::make_unique<FeatureStatusProviderImpl>( + &fake_device_sync_client_, &fake_multidevice_setup_client_); + provider_->AddObserver(&fake_observer_); + } + + void SetSyncedDevices( + const base::Optional<multidevice::RemoteDeviceRef>& local_device, + const base::Optional<multidevice::RemoteDeviceRef>& phone_device) { + fake_device_sync_client_.set_local_device_metadata(local_device); + + multidevice::RemoteDeviceRefList synced_devices; + if (local_device) + synced_devices.push_back(*local_device); + if (phone_device) + synced_devices.push_back(*phone_device); + fake_device_sync_client_.set_synced_devices(synced_devices); + + fake_device_sync_client_.NotifyNewDevicesSynced(); + } + + void SetEligibleSyncedDevices() { + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/true, + /*supports_phone_hub_host=*/true, + /*has_bluetooth_address=*/true)); + } + + void SetMultiDeviceState(HostStatus host_status, FeatureState feature_state) { + fake_multidevice_setup_client_.SetHostStatusWithDevice(std::make_pair( + host_status, CreatePhoneDevice(/*supports_better_together_host=*/true, + /*supports_phone_hub_host=*/true, + /*has_bluetooth_address=*/true))); + fake_multidevice_setup_client_.SetFeatureState(Feature::kPhoneHub, + feature_state); + } + + void SetAdapterPresentState(bool present) { + if (is_adapter_present_ == present) + return; + + is_adapter_present_ = present; + + FeatureStatusProviderImpl* impl = + static_cast<FeatureStatusProviderImpl*>(provider_.get()); + impl->AdapterPresentChanged(mock_adapter_.get(), present); + } + + void SetAdapterPoweredState(bool powered) { + if (is_adapter_powered_ == powered) + return; + + is_adapter_powered_ = powered; + + FeatureStatusProviderImpl* impl = + static_cast<FeatureStatusProviderImpl*>(provider_.get()); + impl->AdapterPoweredChanged(mock_adapter_.get(), powered); + } + + FeatureStatus GetStatus() const { return provider_->GetStatus(); } + + size_t GetNumObserverCalls() const { return fake_observer_.num_calls(); } + + private: + bool is_adapter_present() { return is_adapter_present_; } + bool is_adapter_powered() { return is_adapter_powered_; } + + base::test::TaskEnvironment task_environment_; + + device_sync::FakeDeviceSyncClient fake_device_sync_client_; + multidevice_setup::FakeMultiDeviceSetupClient fake_multidevice_setup_client_; + + scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_; + + bool is_adapter_present_ = true; + bool is_adapter_powered_ = true; + + FakeObserver fake_observer_; + std::unique_ptr<FeatureStatusProvider> provider_; +}; + +// Tests conditions for kNotEligibleForFeature status, including missing local +// device and/or phone and various missing properties of these devices. +TEST_F(FeatureStatusProviderImplTest, NotEligibleForFeature) { + SetSyncedDevices(/*local_device=*/base::nullopt, + /*phone_device=*/base::nullopt); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/false, + /*has_bluetooth_address=*/false), + /*phone_device=*/base::nullopt); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/false), + /*phone_device=*/base::nullopt); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/false, + /*has_bluetooth_address=*/true), + /*phone_device=*/base::nullopt); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + /*phone_device=*/base::nullopt); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/false, + /*supports_phone_hub_host=*/false, + /*has_bluetooth_address=*/false)); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/true, + /*supports_phone_hub_host=*/false, + /*has_bluetooth_address=*/false)); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/true, + /*supports_phone_hub_host=*/true, + /*has_bluetooth_address=*/false)); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/true, + /*supports_phone_hub_host=*/false, + /*has_bluetooth_address=*/true)); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/false, + /*supports_phone_hub_host=*/true, + /*has_bluetooth_address=*/false)); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/false, + /*supports_phone_hub_host=*/true, + /*has_bluetooth_address=*/true)); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/false, + /*supports_phone_hub_host=*/false, + /*has_bluetooth_address=*/true)); + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + // Set all properties to true so that there is an eligible phone. Since + // |fake_multidevice_setup_client_| defaults to kProhibitedByPolicy, the + // status should change to this default. + SetSyncedDevices(CreateLocalDevice(/*supports_phone_hub_client=*/true, + /*has_bluetooth_address=*/true), + CreatePhoneDevice(/*supports_better_together_host=*/true, + /*supports_phone_hub_host=*/true, + /*has_bluetooth_address=*/true)); + EXPECT_EQ(FeatureStatus::kProhibitedByPolicy, GetStatus()); +} + +TEST_F(FeatureStatusProviderImplTest, EligiblePhoneButNotSetUp) { + SetEligibleSyncedDevices(); + SetMultiDeviceState(HostStatus::kEligibleHostExistsButNoHostSet, + FeatureState::kUnavailableNoVerifiedHost); + EXPECT_EQ(FeatureStatus::kEligiblePhoneButNotSetUp, GetStatus()); +} + +TEST_F(FeatureStatusProviderImplTest, PhoneSelectedAndPendingSetup) { + SetEligibleSyncedDevices(); + + SetMultiDeviceState( + HostStatus::kHostSetLocallyButWaitingForBackendConfirmation, + FeatureState::kUnavailableNoVerifiedHost); + EXPECT_EQ(FeatureStatus::kPhoneSelectedAndPendingSetup, GetStatus()); + + SetMultiDeviceState(HostStatus::kHostSetButNotYetVerified, + FeatureState::kUnavailableNoVerifiedHost); + EXPECT_EQ(FeatureStatus::kPhoneSelectedAndPendingSetup, GetStatus()); + + SetMultiDeviceState(HostStatus::kHostVerified, + FeatureState::kNotSupportedByPhone); + EXPECT_EQ(FeatureStatus::kPhoneSelectedAndPendingSetup, GetStatus()); +} + +TEST_F(FeatureStatusProviderImplTest, ProhibitedByPolicy) { + SetEligibleSyncedDevices(); + + SetMultiDeviceState(HostStatus::kHostVerified, + FeatureState::kProhibitedByPolicy); + EXPECT_EQ(FeatureStatus::kProhibitedByPolicy, GetStatus()); +} + +TEST_F(FeatureStatusProviderImplTest, Disabled) { + SetEligibleSyncedDevices(); + + SetMultiDeviceState(HostStatus::kHostVerified, FeatureState::kDisabledByUser); + EXPECT_EQ(FeatureStatus::kDisabled, GetStatus()); + + SetMultiDeviceState(HostStatus::kHostVerified, + FeatureState::kUnavailableSuiteDisabled); + EXPECT_EQ(FeatureStatus::kDisabled, GetStatus()); + + SetMultiDeviceState(HostStatus::kHostVerified, + FeatureState::kUnavailableTopLevelFeatureDisabled); + EXPECT_EQ(FeatureStatus::kDisabled, GetStatus()); +} + +TEST_F(FeatureStatusProviderImplTest, UnavailableBluetoothOff) { + SetEligibleSyncedDevices(); + SetMultiDeviceState(HostStatus::kHostVerified, FeatureState::kEnabledByUser); + + SetAdapterPoweredState(false); + SetAdapterPresentState(false); + EXPECT_EQ(FeatureStatus::kUnavailableBluetoothOff, GetStatus()); + + SetAdapterPoweredState(true); + SetAdapterPresentState(false); + EXPECT_EQ(FeatureStatus::kUnavailableBluetoothOff, GetStatus()); + + SetAdapterPoweredState(false); + SetAdapterPresentState(true); + EXPECT_EQ(FeatureStatus::kUnavailableBluetoothOff, GetStatus()); +} + +TEST_F(FeatureStatusProviderImplTest, TransitionBetweenStatuses) { + EXPECT_EQ(FeatureStatus::kNotEligibleForFeature, GetStatus()); + + SetMultiDeviceState(HostStatus::kEligibleHostExistsButNoHostSet, + FeatureState::kUnavailableNoVerifiedHost); + SetEligibleSyncedDevices(); + EXPECT_EQ(FeatureStatus::kEligiblePhoneButNotSetUp, GetStatus()); + EXPECT_EQ(1u, GetNumObserverCalls()); + + SetMultiDeviceState(HostStatus::kHostSetButNotYetVerified, + FeatureState::kNotSupportedByPhone); + EXPECT_EQ(FeatureStatus::kPhoneSelectedAndPendingSetup, GetStatus()); + EXPECT_EQ(2u, GetNumObserverCalls()); + + SetMultiDeviceState(HostStatus::kHostVerified, + FeatureState::kProhibitedByPolicy); + EXPECT_EQ(FeatureStatus::kProhibitedByPolicy, GetStatus()); + EXPECT_EQ(3u, GetNumObserverCalls()); + + SetMultiDeviceState(HostStatus::kHostVerified, FeatureState::kDisabledByUser); + EXPECT_EQ(FeatureStatus::kDisabled, GetStatus()); + EXPECT_EQ(4u, GetNumObserverCalls()); + + SetAdapterPoweredState(false); + SetMultiDeviceState(HostStatus::kHostVerified, FeatureState::kEnabledByUser); + EXPECT_EQ(FeatureStatus::kUnavailableBluetoothOff, GetStatus()); + EXPECT_EQ(5u, GetNumObserverCalls()); + + SetAdapterPoweredState(true); + EXPECT_EQ(FeatureStatus::kEnabledButDisconnected, GetStatus()); + EXPECT_EQ(6u, GetNumObserverCalls()); +} + +} // namespace phonehub +} // namespace chromeos
diff --git a/chromeos/components/sync_wifi/OWNERS b/chromeos/components/sync_wifi/OWNERS index 6100d11..016e07a 100644 --- a/chromeos/components/sync_wifi/OWNERS +++ b/chromeos/components/sync_wifi/OWNERS
@@ -1,5 +1,5 @@ jonmann@chromium.org khorimoto@chromium.org -vecore@google.org +vecore@google.com # COMPONENT: OS>Systems>Network>WiFi
diff --git a/components/arc/session/arc_property_util_unittest.cc b/components/arc/session/arc_property_util_unittest.cc index ba65c4e..4c74314d 100644 --- a/components/arc/session/arc_property_util_unittest.cc +++ b/components/arc/session/arc_property_util_unittest.cc
@@ -304,7 +304,9 @@ // Add default.prop to the source, but not build.prop. base::FilePath default_prop = source_dir.Append("default.prop"); - constexpr const char kDefaultProp[] = "ro.foo=bar\n"; + // Add a non-ro property to make sure that the property is NOT filetered out + // when not in the "append" mode. + constexpr const char kDefaultProp[] = "dalvik.a=b\nro.foo=bar\n"; base::WriteFile(default_prop, kDefaultProp, strlen(kDefaultProp)); EXPECT_FALSE(ExpandPropertyFiles(source_dir, dest_dir, false, false)); @@ -380,8 +382,12 @@ // Add default.prop to the source, but not build.prop. const base::FilePath default_prop = source_dir.Append("default.prop"); + // Add a non-ro property to make sure that the property is filetered out when + // in the "append" mode. + constexpr const char kDefaultPropNonRo[] = "dalvik.a=b\n"; constexpr const char kDefaultProp[] = "ro.foo=bar\n"; - base::WriteFile(default_prop, kDefaultProp, strlen(kDefaultProp)); + base::WriteFile(default_prop, + base::StringPrintf("%s%s", kDefaultPropNonRo, kDefaultProp)); EXPECT_FALSE(ExpandPropertyFiles(source_dir, dest_prop_file, true, false)); // Add build.prop too. The call should not succeed still. @@ -435,6 +441,7 @@ // Verify the content. std::string content; EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content)); + // Don't include kDefaultPropNonRo since that one should be filtered out. EXPECT_EQ(base::StringPrintf("%s%s%s%s%s%s", kDefaultProp, kBuildProp, kSystemExtBuildProp, kVendorBuildProp, kOdmBuildProp, kProductBuildProp),
diff --git a/components/cast_channel/cast_message_handler.cc b/components/cast_channel/cast_message_handler.cc index 5bff7f1..ac8bcd0 100644 --- a/components/cast_channel/cast_message_handler.cc +++ b/components/cast_channel/cast_message_handler.cc
@@ -209,8 +209,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CastSocket* socket = socket_service_->GetSocket(channel_id); if (!socket) { - DVLOG(2) << __func__ << ": socket not found: " << channel_id; - std::move(callback).Run(LaunchSessionResponse()); + std::move(callback).Run(GetLaunchSessionResponseError( + base::StringPrintf("Socket not found: %d.", channel_id))); return; } @@ -223,9 +223,8 @@ CastMessage message = CreateLaunchRequest( sender_id_, request_id, app_id, locale_, supported_app_types, app_params); if (message.ByteSizeLong() > kMaxCastMessagePayload) { - LaunchSessionResponse response; - response.result = LaunchSessionResponse::kError; - std::move(callback).Run(std::move(response)); + std::move(callback).Run(GetLaunchSessionResponseError( + "Message size exceeds maximum cast channel message payload.")); return; } if (requests->AddLaunchRequest(std::make_unique<LaunchSessionRequest>(
diff --git a/components/cast_channel/cast_message_util.cc b/components/cast_channel/cast_message_util.cc index 80d8da2..afed9c2 100644 --- a/components/cast_channel/cast_message_util.cc +++ b/components/cast_channel/cast_message_util.cc
@@ -561,11 +561,20 @@ .value_or(GetAppAvailabilityResult::kUnknown); } -LaunchSessionResponse::LaunchSessionResponse() {} +LaunchSessionResponse::LaunchSessionResponse() = default; LaunchSessionResponse::LaunchSessionResponse(LaunchSessionResponse&& other) = default; +LaunchSessionResponse& LaunchSessionResponse::operator=( + LaunchSessionResponse&& other) = default; LaunchSessionResponse::~LaunchSessionResponse() = default; +LaunchSessionResponse GetLaunchSessionResponseError(std::string error_msg) { + LaunchSessionResponse response; + response.result = LaunchSessionResponse::Result::kError; + response.error_msg = std::move(error_msg); + return response; +} + LaunchSessionResponse GetLaunchSessionResponse(const base::Value& payload) { const Value* type_value = payload.FindKeyOfType("type", Value::Type::STRING); if (!type_value)
diff --git a/components/cast_channel/cast_message_util.h b/components/cast_channel/cast_message_util.h index d32b77c1..feb03b1 100644 --- a/components/cast_channel/cast_message_util.h +++ b/components/cast_channel/cast_message_util.h
@@ -307,12 +307,17 @@ enum Result { kOk, kError, kTimedOut, kUnknown, kMaxValue = kUnknown }; LaunchSessionResponse(); + LaunchSessionResponse(const LaunchSessionResponse& other) = delete; LaunchSessionResponse(LaunchSessionResponse&& other); + LaunchSessionResponse& operator=(const LaunchSessionResponse& other) = delete; + LaunchSessionResponse& operator=(LaunchSessionResponse&& other); ~LaunchSessionResponse(); Result result = Result::kUnknown; // Populated if |result| is |kOk|. base::Optional<base::Value> receiver_status; + // Populated if |result| is |kError|. + std::string error_msg; }; // Parses |payload| into a LaunchSessionResponse. Returns an empty @@ -321,6 +326,8 @@ // CastMessage. LaunchSessionResponse GetLaunchSessionResponse(const base::Value& payload); +LaunchSessionResponse GetLaunchSessionResponseError(std::string error_msg); + } // namespace cast_channel #endif // COMPONENTS_CAST_CHANNEL_CAST_MESSAGE_UTIL_H_
diff --git a/components/download/database/download_db_conversions.cc b/components/download/database/download_db_conversions.cc index d9c2ef3..2e62916 100644 --- a/components/download/database/download_db_conversions.cc +++ b/components/download/database/download_db_conversions.cc
@@ -5,8 +5,10 @@ #include "components/download/database/download_db_conversions.h" #include <utility> + #include "base/notreached.h" #include "base/pickle.h" +#include "components/download/public/common/download_features.h" namespace download { namespace { @@ -207,7 +209,8 @@ proto.set_metered(in_progress_info.metered); proto.set_bytes_wasted(in_progress_info.bytes_wasted); proto.set_auto_resume_count(in_progress_info.auto_resume_count); - if (in_progress_info.download_schedule.has_value()) { + if (base::FeatureList::IsEnabled(download::features::kDownloadLater) && + in_progress_info.download_schedule.has_value()) { DCHECK_NE(in_progress_info.download_schedule->only_on_wifi(), in_progress_info.metered); auto download_schedule_proto = @@ -266,7 +269,8 @@ info.metered = proto.metered(); info.bytes_wasted = proto.bytes_wasted(); info.auto_resume_count = proto.auto_resume_count(); - if (proto.has_download_schedule()) { + if (base::FeatureList::IsEnabled(download::features::kDownloadLater) && + proto.has_download_schedule()) { info.download_schedule = DownloadScheduleFromProto( proto.download_schedule(), !proto.metered() /*only_on_wifi*/); DCHECK_NE(info.download_schedule->only_on_wifi(), info.metered);
diff --git a/components/download/database/download_db_conversions_unittest.cc b/components/download/database/download_db_conversions_unittest.cc index c89f8cb..a2b8087 100644 --- a/components/download/database/download_db_conversions_unittest.cc +++ b/components/download/database/download_db_conversions_unittest.cc
@@ -5,6 +5,8 @@ #include "components/download/database/download_db_conversions.h" #include "base/optional.h" +#include "base/test/scoped_feature_list.h" +#include "components/download/public/common/download_features.h" #include "components/download/public/common/download_schedule.h" #include "components/download/public/common/download_url_parameters.h" #include "testing/gtest/include/gtest/gtest.h" @@ -67,7 +69,19 @@ class DownloadDBConversionsTest : public testing::Test, public DownloadDBConversions { public: - ~DownloadDBConversionsTest() override {} + ~DownloadDBConversionsTest() override = default; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature(features::kDownloadLater); + } + + protected: + base::test::ScopedFeatureList* scoped_feature_list() { + return &scoped_feature_list_; + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; TEST_F(DownloadDBConversionsTest, DownloadEntry) { @@ -185,4 +199,20 @@ EXPECT_EQ(persisted_download_schedule, download_schedule); } +// Test to verify that when download later feature is disabled, download +// schedule will not be loaded. +TEST_F(DownloadDBConversionsTest, DownloadLaterDisabled) { + scoped_feature_list()->Reset(); + scoped_feature_list()->InitAndDisableFeature(features::kDownloadLater); + + DownloadDBEntry entry; + entry.download_info = CreateDownloadInfo(); + EXPECT_TRUE( + entry.download_info->in_progress_info->download_schedule.has_value()); + + auto new_entry = DownloadDBEntryFromProto(DownloadDBEntryToProto(entry)); + EXPECT_FALSE( + new_entry.download_info->in_progress_info->download_schedule.has_value()); +} + } // namespace download
diff --git a/components/favicon/content/content_favicon_driver.cc b/components/favicon/content/content_favicon_driver.cc index 63f2187..e1ae023 100644 --- a/components/favicon/content/content_favicon_driver.cc +++ b/components/favicon/content/content_favicon_driver.cc
@@ -19,21 +19,6 @@ #include "ui/gfx/image/image.h" namespace favicon { -namespace { - -void ExtractManifestIcons( - ContentFaviconDriver::ManifestDownloadCallback callback, - const GURL& manifest_url, - const blink::Manifest& manifest) { - std::vector<FaviconURL> candidates; - for (const auto& icon : manifest.icons) { - candidates.emplace_back(icon.src, favicon_base::IconType::kWebManifestIcon, - icon.sizes); - } - std::move(callback).Run(candidates); -} - -} // namespace // static void ContentFaviconDriver::CreateForWebContents( @@ -80,7 +65,25 @@ FaviconDriverImpl(favicon_service), document_on_load_completed_(false) {} -ContentFaviconDriver::~ContentFaviconDriver() { +ContentFaviconDriver::~ContentFaviconDriver() = default; + +void ContentFaviconDriver::OnDidDownloadManifest( + ManifestDownloadCallback callback, + const GURL& manifest_url, + const blink::Manifest& manifest) { + // ~WebContentsImpl triggers running any pending callbacks for manifests. + // As we're about to be destroyed ignore the request. To do otherwise may + // result in calling back to this and attempting to use the WebContents, which + // will crash. + if (!web_contents()) + return; + + std::vector<FaviconURL> candidates; + for (const auto& icon : manifest.icons) { + candidates.emplace_back(icon.src, favicon_base::IconType::kWebManifestIcon, + icon.sizes); + } + std::move(callback).Run(candidates); } int ContentFaviconDriver::DownloadImage(const GURL& url, @@ -97,7 +100,8 @@ void ContentFaviconDriver::DownloadManifest(const GURL& url, ManifestDownloadCallback callback) { web_contents()->GetManifest( - base::BindOnce(&ExtractManifestIcons, std::move(callback))); + base::BindOnce(&ContentFaviconDriver::OnDidDownloadManifest, + base::Unretained(this), std::move(callback))); } bool ContentFaviconDriver::IsOffTheRecord() {
diff --git a/components/favicon/content/content_favicon_driver.h b/components/favicon/content/content_favicon_driver.h index bae413e..8226afb 100644 --- a/components/favicon/content/content_favicon_driver.h +++ b/components/favicon/content/content_favicon_driver.h
@@ -51,6 +51,11 @@ private: friend class content::WebContentsUserData<ContentFaviconDriver>; + // Callback when a manifest is downloaded. + void OnDidDownloadManifest(ManifestDownloadCallback callback, + const GURL& manifest_url, + const blink::Manifest& manifest); + // FaviconHandler::Delegate implementation. int DownloadImage(const GURL& url, int max_image_size,
diff --git a/components/favicon/content/content_favicon_driver_unittest.cc b/components/favicon/content/content_favicon_driver_unittest.cc index fc6f18a..d8ded21 100644 --- a/components/favicon/content/content_favicon_driver_unittest.cc +++ b/components/favicon/content/content_favicon_driver_unittest.cc
@@ -9,9 +9,11 @@ #include "base/macros.h" #include "base/run_loop.h" +#include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" #include "components/favicon/core/favicon_client.h" #include "components/favicon/core/favicon_handler.h" +#include "components/favicon/core/test/favicon_driver_impl_test_helper.h" #include "components/favicon/core/test/mock_favicon_service.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/navigation_simulator.h" @@ -38,15 +40,16 @@ const GURL kIconURL = GURL("http://www.google.com/favicon.ico"); ContentFaviconDriverTest() { + ContentFaviconDriverTest* t = this; ON_CALL(favicon_service_, UpdateFaviconMappingsAndFetch(_, _, _, _, _, _)) - .WillByDefault([](auto, auto, auto, auto, - favicon_base::FaviconResultsCallback callback, - base::CancelableTaskTracker* tracker) { + .WillByDefault([t](auto, auto, auto, auto, + favicon_base::FaviconResultsCallback callback, + base::CancelableTaskTracker* tracker) { return tracker->PostTask( base::ThreadTaskRunnerHandle::Get().get(), FROM_HERE, - base::BindOnce( - std::move(callback), - std::vector<favicon_base::FaviconRawBitmapResult>())); + base::BindOnce(&ContentFaviconDriverTest:: + OnCallUpdateFaviconMappingsAndFetch, + base::Unretained(t), std::move(callback))); }); ON_CALL(favicon_service_, GetFaviconForPageURL(_, _, _, _, _)) .WillByDefault([](auto, auto, auto, @@ -60,7 +63,7 @@ }); } - ~ContentFaviconDriverTest() override {} + ~ContentFaviconDriverTest() override = default; // content::RenderViewHostTestHarness: void SetUp() override { @@ -85,7 +88,21 @@ base::RunLoop().RunUntilIdle(); } + // This is run *after* the callback posted by way of + // UpdateFaviconMappingsAndFetch() is run. It allows hooking processing + // immediately after it. + base::OnceClosure on_did_update_favicon_mappings_and_fetch_; + testing::NiceMock<MockFaviconService> favicon_service_; + + private: + // Callback from UpdateFaviconMappingsAndFetch(). + void OnCallUpdateFaviconMappingsAndFetch( + favicon_base::FaviconResultsCallback callback) { + std::move(callback).Run({}); + if (on_did_update_favicon_mappings_and_fetch_) + std::move(on_did_update_favicon_mappings_and_fetch_).Run(); + } }; // Test that a download is initiated when there isn't a favicon in the database @@ -171,5 +188,39 @@ EXPECT_TRUE(driver->favicon_urls().empty()); } +// This test verifies a crash doesn't happen during deletion of the +// WebContents. The crash occurred because ~WebContentsImpl would trigger +// running callbacks for manifests. This mean FaviconHandler would be called +// while ContentFaviconDriver::web_contents() was null, which is unexpected and +// crashed. See https://crbug.com/1114237 for more. +TEST_F(ContentFaviconDriverTest, + WebContentsDeletedWithInProgressManifestRequest) { + // Manifests are only downloaded with TOUCH_LARGEST. Force creating this + // handler so code path is exercised on all platforms. + favicon::ContentFaviconDriver* driver = + favicon::ContentFaviconDriver::FromWebContents(web_contents()); + FaviconDriverImplTestHelper::RecreateHandlerForType( + driver, FaviconDriverObserver::TOUCH_LARGEST); + + // Mimic a page load. + std::vector<blink::mojom::FaviconURLPtr> favicon_urls; + favicon_urls.push_back(blink::mojom::FaviconURL::New( + kIconURL, blink::mojom::FaviconIconType::kTouchIcon, kEmptyIconSizes)); + TestFetchFaviconForPage(kPageURL, favicon_urls); + + // Trigger downloading a manifest. + base::RunLoop run_loop; + on_did_update_favicon_mappings_and_fetch_ = + base::BindLambdaForTesting([&] { run_loop.Quit(); }); + static_cast<content::WebContentsObserver*>(driver)->DidUpdateWebManifestURL( + web_contents()->GetMainFrame(), GURL("http://bad.manifest.com")); + run_loop.Run(); + + // The request for the manifest is still pending, delete the WebContents, + // which should trigger notifying the callback for the manifest and *not* + // crash. + DeleteContents(); +} + } // namespace } // namespace favicon
diff --git a/components/favicon/core/favicon_driver_impl.cc b/components/favicon/core/favicon_driver_impl.cc index 730121a..5c48be4 100644 --- a/components/favicon/core/favicon_driver_impl.cc +++ b/components/favicon/core/favicon_driver_impl.cc
@@ -6,7 +6,6 @@ #include <memory> -#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "build/build_config.h" #include "components/favicon/core/core_favicon_service.h" @@ -38,8 +37,7 @@ } } -FaviconDriverImpl::~FaviconDriverImpl() { -} +FaviconDriverImpl::~FaviconDriverImpl() = default; void FaviconDriverImpl::FetchFavicon(const GURL& page_url, bool is_same_document) {
diff --git a/components/favicon/core/favicon_driver_impl.h b/components/favicon/core/favicon_driver_impl.h index c985be4..79e9eac4 100644 --- a/components/favicon/core/favicon_driver_impl.h +++ b/components/favicon/core/favicon_driver_impl.h
@@ -51,12 +51,13 @@ const std::vector<FaviconURL>& candidates, const GURL& manifest_url); - protected: CoreFaviconService* favicon_service() { return favicon_service_; } private: - // KeyedService used by FaviconDriverImpl. It may be null, if non-null, it - // must outlive FaviconDriverImpl. + friend class FaviconDriverImplTestHelper; + + // KeyedService used by FaviconDriverImpl. It may be null during testing, + // but if it is defined, it must outlive the FaviconDriverImpl. CoreFaviconService* favicon_service_; // FaviconHandlers used to download the different kind of favicons.
diff --git a/components/favicon/core/test/BUILD.gn b/components/favicon/core/test/BUILD.gn index d87927d..f301372 100644 --- a/components/favicon/core/test/BUILD.gn +++ b/components/favicon/core/test/BUILD.gn
@@ -6,6 +6,8 @@ testonly = true sources = [ + "favicon_driver_impl_test_helper.cc", + "favicon_driver_impl_test_helper.h", "mock_favicon_service.cc", "mock_favicon_service.h", ]
diff --git a/components/favicon/core/test/favicon_driver_impl_test_helper.cc b/components/favicon/core/test/favicon_driver_impl_test_helper.cc new file mode 100644 index 0000000..dd1eb27f --- /dev/null +++ b/components/favicon/core/test/favicon_driver_impl_test_helper.cc
@@ -0,0 +1,22 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/favicon/core/test/favicon_driver_impl_test_helper.h" + +#include <memory> + +#include "components/favicon/core/favicon_driver_impl.h" + +namespace favicon { + +// static +void FaviconDriverImplTestHelper::RecreateHandlerForType( + FaviconDriverImpl* driver, + FaviconDriverObserver::NotificationIconType type) { + driver->handlers_.clear(); + driver->handlers_.push_back( + std::make_unique<FaviconHandler>(driver->favicon_service_, driver, type)); +} + +} // namespace favicon
diff --git a/components/favicon/core/test/favicon_driver_impl_test_helper.h b/components/favicon/core/test/favicon_driver_impl_test_helper.h new file mode 100644 index 0000000..a98b920 --- /dev/null +++ b/components/favicon/core/test/favicon_driver_impl_test_helper.h
@@ -0,0 +1,31 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_FAVICON_CORE_TEST_FAVICON_DRIVER_IMPL_TEST_HELPER_H_ +#define COMPONENTS_FAVICON_CORE_TEST_FAVICON_DRIVER_IMPL_TEST_HELPER_H_ + +#include "components/favicon/core/favicon_driver_observer.h" + +namespace favicon { + +class FaviconDriverImpl; + +// Test helper for reaching into the internals of FaviconDriverImpl. +class FaviconDriverImplTestHelper { + public: + FaviconDriverImplTestHelper(const FaviconDriverImplTestHelper&) = delete; + FaviconDriverImplTestHelper& operator=(const FaviconDriverImplTestHelper&) = + delete; + FaviconDriverImplTestHelper() = delete; + + // Resets |driver->handler_| to a FaviconHandler of type |type|. This should + // be called at a time when there are no outstanding requests. + static void RecreateHandlerForType( + FaviconDriverImpl* driver, + FaviconDriverObserver::NotificationIconType type); +}; + +} // namespace favicon + +#endif // COMPONENTS_FAVICON_CORE_TEST_FAVICON_DRIVER_IMPL_TEST_HELPER_H_
diff --git a/components/feature_engagement/public/feature_list.h b/components/feature_engagement/public/feature_list.h index a2e4233..a239ee3f 100644 --- a/components/feature_engagement/public/feature_list.h +++ b/components/feature_engagement/public/feature_list.h
@@ -191,6 +191,7 @@ VARIATION_ENTRY(kIPHDesktopTabGroupsNewGroupFeature), VARIATION_ENTRY(kIPHFocusModeFeature), VARIATION_ENTRY(kIPHGlobalMediaControls), + VARIATION_ENTRY(kIPHPasswordsAccountStorageFeature), VARIATION_ENTRY(kIPHReopenTabFeature), VARIATION_ENTRY(kIPHWebUITabStripFeature), #endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
diff --git a/components/metal_util/OWNERS b/components/metal_util/OWNERS index f82eef2..6d0eed7 100644 --- a/components/metal_util/OWNERS +++ b/components/metal_util/OWNERS
@@ -1,5 +1,5 @@ ccameron@chromium.org -jvanverth@google.org +jvanverth@google.com # TEAM: graphics-dev@chromium.org # COMPONENT: Internals>Compositing
diff --git a/components/omnibox/browser/omnibox_pedal.cc b/components/omnibox/browser/omnibox_pedal.cc index fe6ef83..daaba444 100644 --- a/components/omnibox/browser/omnibox_pedal.cc +++ b/components/omnibox/browser/omnibox_pedal.cc
@@ -44,10 +44,18 @@ OmniboxPedal::LabelStrings::LabelStrings(int id_hint, int id_hint_short, - int id_suggestion_contents) + int id_suggestion_contents, + int id_accessibility_suffix, + int id_accessibility_hint) : hint(l10n_util::GetStringUTF16(id_hint)), hint_short(l10n_util::GetStringUTF16(id_hint_short)), - suggestion_contents(l10n_util::GetStringUTF16(id_suggestion_contents)) {} + suggestion_contents(l10n_util::GetStringUTF16(id_suggestion_contents)), + id_accessibility_suffix(id_accessibility_suffix), + accessibility_hint(l10n_util::GetStringUTF16(id_accessibility_hint)) {} + +OmniboxPedal::LabelStrings::LabelStrings(const LabelStrings&) = default; + +OmniboxPedal::LabelStrings::~LabelStrings() = default; // =============================================================================
diff --git a/components/omnibox/browser/omnibox_pedal.h b/components/omnibox/browser/omnibox_pedal.h index 8c7d2ea..d91a9386 100644 --- a/components/omnibox/browser/omnibox_pedal.h +++ b/components/omnibox/browser/omnibox_pedal.h
@@ -37,10 +37,18 @@ typedef std::vector<int> Tokens; struct LabelStrings { - LabelStrings(int id_hint, int id_hint_short, int id_suggestion_contents); + LabelStrings(int id_hint, + int id_hint_short, + int id_suggestion_contents, + int id_accessibility_suffix, + int id_accessibility_hint); + LabelStrings(const LabelStrings&); + ~LabelStrings(); const base::string16 hint; const base::string16 hint_short; const base::string16 suggestion_contents; + const int id_accessibility_suffix; + const base::string16 accessibility_hint; }; class SynonymGroup {
diff --git a/components/omnibox/browser/omnibox_pedal_implementations.cc b/components/omnibox/browser/omnibox_pedal_implementations.cc index bf91ef5..32091c61 100644 --- a/components/omnibox/browser/omnibox_pedal_implementations.cc +++ b/components/omnibox/browser/omnibox_pedal_implementations.cc
@@ -25,7 +25,9 @@ LabelStrings( IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_HINT, IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_HINT_SHORT, - IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUGGESTION_CONTENTS), + IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUGGESTION_CONTENTS, + IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUFFIX, + IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA), GURL("chrome://settings/clearBrowserData")) {} }; @@ -35,10 +37,11 @@ public: OmniboxPedalManagePasswords() : OmniboxPedal( - LabelStrings( - IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_HINT, - IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_HINT_SHORT, - IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUGGESTION_CONTENTS), + LabelStrings(IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_HINT, + IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_HINT_SHORT, + IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUGGESTION_CONTENTS, + IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUFFIX, + IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS), GURL("chrome://settings/passwords")) {} }; @@ -51,7 +54,9 @@ OmniboxPedal::LabelStrings( IDS_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_HINT, IDS_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_HINT_SHORT, - IDS_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUGGESTION_CONTENTS), + IDS_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUGGESTION_CONTENTS, + IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUFFIX, + IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD), GURL("chrome://settings/payments")) {} }; @@ -61,10 +66,11 @@ public: OmniboxPedalLaunchIncognito() : OmniboxPedal( - LabelStrings( - IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_HINT, - IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_HINT_SHORT, - IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUGGESTION_CONTENTS), + LabelStrings(IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_HINT, + IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_HINT_SHORT, + IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUGGESTION_CONTENTS, + IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUFFIX, + IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO), // Fake URL to distinguish matches. GURL("chrome://newtab?incognito=true")) {} @@ -81,7 +87,9 @@ : OmniboxPedal( LabelStrings(IDS_OMNIBOX_PEDAL_TRANSLATE_HINT, IDS_OMNIBOX_PEDAL_TRANSLATE_HINT_SHORT, - IDS_OMNIBOX_PEDAL_TRANSLATE_SUGGESTION_CONTENTS), + IDS_OMNIBOX_PEDAL_TRANSLATE_SUGGESTION_CONTENTS, + IDS_ACC_OMNIBOX_PEDAL_TRANSLATE_SUFFIX, + IDS_ACC_OMNIBOX_PEDAL_TRANSLATE), // Fake URL to distinguish matches. GURL("chrome://translate/pedals")) {} @@ -98,7 +106,9 @@ : OmniboxPedal( LabelStrings(IDS_OMNIBOX_PEDAL_UPDATE_CHROME_HINT, IDS_OMNIBOX_PEDAL_UPDATE_CHROME_HINT_SHORT, - IDS_OMNIBOX_PEDAL_UPDATE_CHROME_SUGGESTION_CONTENTS), + IDS_OMNIBOX_PEDAL_UPDATE_CHROME_SUGGESTION_CONTENTS, + IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME_SUFFIX, + IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME), GURL("chrome://settings/help")) {} };
diff --git a/components/omnibox/browser/omnibox_pedal_unittest.cc b/components/omnibox/browser/omnibox_pedal_unittest.cc index 354b5d4..27131c4 100644 --- a/components/omnibox/browser/omnibox_pedal_unittest.cc +++ b/components/omnibox/browser/omnibox_pedal_unittest.cc
@@ -52,7 +52,9 @@ OmniboxPedal::LabelStrings( IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_HINT, IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_HINT_SHORT, - IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUGGESTION_CONTENTS), + IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUGGESTION_CONTENTS, + IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUFFIX, + IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA), GURL()); const auto add_group = [&](bool required, int token) { OmniboxPedal::SynonymGroup group(required, true, 1);
diff --git a/components/omnibox/browser/omnibox_popup_model.cc b/components/omnibox/browser/omnibox_popup_model.cc index 4f5745f..100902f 100644 --- a/components/omnibox/browser/omnibox_popup_model.cc +++ b/components/omnibox/browser/omnibox_popup_model.cc
@@ -15,6 +15,7 @@ #include "components/omnibox/browser/omnibox_client.h" #include "components/omnibox/browser/omnibox_edit_controller.h" #include "components/omnibox/browser/omnibox_field_trial.h" +#include "components/omnibox/browser/omnibox_pedal.h" #include "components/omnibox/browser/omnibox_popup_view.h" #include "components/omnibox/browser/omnibox_prefs.h" #include "components/strings/grit/components_strings.h" @@ -608,28 +609,43 @@ message_id, result().GetHeaderForGroupId(match.suggestion_group_id.value())); } - case NORMAL: + case NORMAL: { + int available_actions_count = 0; if (IsControlPresentOnMatch(Selection(line, FOCUSED_BUTTON_TAB_SWITCH))) { additional_message_id = IDS_ACC_TAB_SWITCH_SUFFIX; + available_actions_count++; } + if (IsControlPresentOnMatch(Selection(line, FOCUSED_BUTTON_KEYWORD))) { + additional_message_id = IDS_ACC_KEYWORD_SUFFIX; + available_actions_count++; + } + if (IsControlPresentOnMatch(Selection(line, FOCUSED_BUTTON_PEDAL))) { + additional_message_id = + match.pedal->GetLabelStrings().id_accessibility_suffix; + available_actions_count++; + } + DCHECK_EQ(LINE_STATE_MAX_VALUE, 7); + if (available_actions_count > 1) + additional_message_id = IDS_ACC_MULTIPLE_ACTIONS_SUFFIX; + // Don't add an additional message for removable suggestions without // button focus, since they are relatively common. break; + } case KEYWORD_MODE: // TODO(tommycli): Investigate whether the accessibility messaging for // Keyword mode belongs here. break; case FOCUSED_BUTTON_KEYWORD: - // TODO(yoangela): Add an accessibility message for the Keyword button - // in the button-row UI configuration. + additional_message_id = IDS_ACC_KEYWORD_BUTTON; break; case FOCUSED_BUTTON_TAB_SWITCH: additional_message_id = IDS_ACC_TAB_SWITCH_BUTTON_FOCUSED_PREFIX; break; case FOCUSED_BUTTON_PEDAL: - // TODO(orinj): Add an accessibility message for the Pedal button - // in the button-row UI configuration. - break; + // When pedal button is focused, the autocomplete suggestion isn't + // read because it's not relevant to the button's action. + return match.pedal->GetLabelStrings().accessibility_hint; case FOCUSED_BUTTON_REMOVE_SUGGESTION: additional_message_id = IDS_ACC_REMOVE_SUGGESTION_FOCUSED_PREFIX; break;
diff --git a/components/omnibox/browser/omnibox_popup_model.h b/components/omnibox/browser/omnibox_popup_model.h index 9d1f4f7d..153a0cf 100644 --- a/components/omnibox/browser/omnibox_popup_model.h +++ b/components/omnibox/browser/omnibox_popup_model.h
@@ -81,6 +81,11 @@ // FOCUSED_BUTTON_REMOVE_SUGGESTION state means the Remove Suggestion (X) // button is focused. Pressing enter will attempt to remove this suggestion. FOCUSED_BUTTON_REMOVE_SUGGESTION = 6, + + // Whenever new line state is added, accessibility label for current + // selection should be revisited + // (OmniboxPopupModel::GetAccessibilityLabelForCurrentSelection). + LINE_STATE_MAX_VALUE }; struct Selection {
diff --git a/components/omnibox_strings.grdp b/components/omnibox_strings.grdp index 1d921f2..d080efd 100644 --- a/components/omnibox_strings.grdp +++ b/components/omnibox_strings.grdp
@@ -109,6 +109,12 @@ <message name="IDS_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, clear browsing data."> Clear your browsing history, cookies, cache, and more in Chrome settings </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUFFIX" desc="Suffix for spoken suggestion description with clear data pedal action to explain keystroke used to clear browsing data."> + <ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to clear Chrome's browsing history data + </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA" desc="Announcement when clear browsing data pedal button is focused."> + Clear Data button, press Enter to clear Chrome's browsing history data + </message> <message name="IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_HINT" desc="The button text contents to suggest pedal action, manage passwords."> Manage passwords @@ -119,6 +125,12 @@ <message name="IDS_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, change language."> View and manage your passwords in Chrome settings </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUFFIX" desc="Suffix for spoken suggestion description with manage passwords pedal action to explain keystroke used to manage passwords."> + <ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to manage passwords in Chrome settings + </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS" desc="Announcement when manage passwords pedal button is focused."> + Manage Passwords button, press Enter to manage passwords in Chrome settings + </message> <message name="IDS_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_HINT" desc="The button text contents to suggest pedal action, update credit card."> Manage payment methods @@ -129,6 +141,12 @@ <message name="IDS_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, update credit card."> Manage your payments and credit card info in Chrome settings </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUFFIX" desc="Suffix for spoken suggestion description with update credit card pedal action to explain keystroke used to manage passwords."> + <ph name="UPDATE_CREDIT_CARD_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to update credit card autofill info in Chrome settings + </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD" desc="Announcement when update credit card pedal button is focused."> + Update Credit Card button, press Enter to update credit card autofill info in Chrome settings + </message> <message name="IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_HINT" desc="The button text contents to suggest pedal action, launch incognito."> Open Incognito window @@ -139,6 +157,12 @@ <message name="IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, launch incognito."> Open a new Incognito window to browse privately </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUFFIX" desc="Suffix for spoken suggestion description with launch incognito pedal action to explain keystroke used to manage passwords."> + <ph name="LAUNCH_INCOGNITO_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to open new Chrome incognito window + </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO" desc="Announcement when launch incognito pedal button is focused."> + Open Incognito Window button, press Enter to open new Chrome incognito window + </message> <message name="IDS_OMNIBOX_PEDAL_TRANSLATE_HINT" desc="The button text contents to suggest pedal action, translate."> Translate page @@ -149,6 +173,12 @@ <message name="IDS_OMNIBOX_PEDAL_TRANSLATE_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, translate."> Translate this page with Google Translate </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_TRANSLATE_SUFFIX" desc="Suffix for spoken suggestion description with translate pedal action to explain keystroke used to manage passwords."> + <ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to translate this page + </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_TRANSLATE" desc="Announcement when translate pedal button is focused."> + Translate Page button, press Enter to translate this page + </message> <message name="IDS_OMNIBOX_PEDAL_UPDATE_CHROME_HINT" desc="The button text contents to suggest pedal action, update chrome."> Update Chrome @@ -159,6 +189,12 @@ <message name="IDS_OMNIBOX_PEDAL_UPDATE_CHROME_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, update chrome."> Update Chrome from your Chrome settings </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME_SUFFIX" desc="Suffix for spoken suggestion description with update chrome pedal action to explain keystroke used to manage passwords."> + <ph name="UPDATE_CHROME_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to update Chrome + </message> + <message name="IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME" desc="Announcement when update chrome pedal button is focused."> + Relaunch to Update button, press Enter to update Chrome + </message> <!-- Accessibility labels for autocomplete match types. These are parameterized on the text being completed into the omnibox. @@ -211,6 +247,17 @@ <message name="IDS_ACC_TAB_SWITCH_BUTTON" desc="Announcement when tab switch button focused."> Tab switch button, press Enter to switch to this tab </message> + + <message name="IDS_ACC_MULTIPLE_ACTIONS_SUFFIX" desc="Suffix for spoken suggestion description with multiple actions available (pedals, switch tab, keyword search) to indicate that this suggestion has multiple actions available."> + <ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, multiple actions are available, press Tab to cycle through them + </message> + <message name="IDS_ACC_KEYWORD_SUFFIX" desc="Suffix for spoken keyword suggestion description to explain keystroke used to search."> + <ph name="KEYWORD_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to search + </message> + <message name="IDS_ACC_KEYWORD_BUTTON" desc="Announcement when keyword search button focused."> + Search button, press Enter to search <ph name="KEYWORD_SUFFIX">$1<ex>Search Youtube</ex></ph> + </message> + <!-- Accessibility suffix for suggestions when the remove button is focused. --> <message name="IDS_ACC_REMOVE_SUGGESTION_FOCUSED_PREFIX" desc="Announcement when remove suggestion button is focused."> Remove Suggestion button, press Enter to remove, <ph name="REMOVE_BUTTON_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>
diff --git a/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_BUTTON.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_BUTTON.png.sha1 new file mode 100644 index 0000000..285a1fdb --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_BUTTON.png.sha1
@@ -0,0 +1 @@ +006b4c3d0255628f837e20c319c10676cef37109 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_SUFFIX.png.sha1 new file mode 100644 index 0000000..1d534ca9 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_KEYWORD_SUFFIX.png.sha1
@@ -0,0 +1 @@ +167e3431478cbfd40c8ac92b77b246b5c9202358 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_MULTIPLE_ACTIONS_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_MULTIPLE_ACTIONS_SUFFIX.png.sha1 new file mode 100644 index 0000000..5b5c1933 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_MULTIPLE_ACTIONS_SUFFIX.png.sha1
@@ -0,0 +1 @@ +e17c4ab73d17f200fae391851dc4f98ce5817ef2 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA.png.sha1 new file mode 100644 index 0000000..3894515 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA.png.sha1
@@ -0,0 +1 @@ +4361ca28e97038007846b05a11ff6b4f669f6c20 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUFFIX.png.sha1 new file mode 100644 index 0000000..1506c99 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_CLEAR_BROWSING_DATA_SUFFIX.png.sha1
@@ -0,0 +1 @@ +1de3f2f59c873f339459f3144c42a51fa61df8af \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO.png.sha1 new file mode 100644 index 0000000..32458ee5 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO.png.sha1
@@ -0,0 +1 @@ +9271ad409aabe1ff88f4038500a0122a1d3b9920 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUFFIX.png.sha1 new file mode 100644 index 0000000..cfbc87fa --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUFFIX.png.sha1
@@ -0,0 +1 @@ +1643cbffd07497fd70b09c01493aafdef0ec5ac0 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS.png.sha1 new file mode 100644 index 0000000..554b981 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS.png.sha1
@@ -0,0 +1 @@ +02dc80bf06286f288fe3afcd62ed6e470936946a \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUFFIX.png.sha1 new file mode 100644 index 0000000..23cfb844 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_MANAGE_PASSWORDS_SUFFIX.png.sha1
@@ -0,0 +1 @@ +e39177ad8f4c1195f2f8397d62394110b77d62c1 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_TRANSLATE.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_TRANSLATE.png.sha1 new file mode 100644 index 0000000..08038db --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_TRANSLATE.png.sha1
@@ -0,0 +1 @@ +d35a775dc904ac5bb6c5de015eb8f824c8532616 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_TRANSLATE_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_TRANSLATE_SUFFIX.png.sha1 new file mode 100644 index 0000000..ebb997f --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_TRANSLATE_SUFFIX.png.sha1
@@ -0,0 +1 @@ +80917d536b163b57c1111331cdcfdb982167639c \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME.png.sha1 new file mode 100644 index 0000000..b0fa2fe --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME.png.sha1
@@ -0,0 +1 @@ +1d06b2efdb6b0314f979665c025ce1c1577d327c \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME_SUFFIX.png.sha1 new file mode 100644 index 0000000..d8a3101 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CHROME_SUFFIX.png.sha1
@@ -0,0 +1 @@ +be0b21c471c6a17df3d466b7136f73796c77b4c4 \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD.png.sha1 new file mode 100644 index 0000000..14d7ca28 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD.png.sha1
@@ -0,0 +1 @@ +f17c75e5b016def05c96fad398d44921f5d2242e \ No newline at end of file
diff --git a/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUFFIX.png.sha1 b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUFFIX.png.sha1 new file mode 100644 index 0000000..a02f872 --- /dev/null +++ b/components/omnibox_strings_grdp/IDS_ACC_OMNIBOX_PEDAL_UPDATE_CREDIT_CARD_SUFFIX.png.sha1
@@ -0,0 +1 @@ +d8eefdbdef87e96900e627d107e8ca910dabb8eb \ No newline at end of file
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameBitmapPainter.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameBitmapPainter.java index 1c89c39..293e6c8 100644 --- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameBitmapPainter.java +++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameBitmapPainter.java
@@ -57,7 +57,7 @@ int colEnd = (int) Math.ceil((double) mViewPort.right / mTileSize.getWidth()); rowEnd = Math.min(rowEnd, mBitmapMatrix.length); - colEnd = Math.min(colEnd, rowEnd > 1 ? mBitmapMatrix[rowEnd - 1].length : 0); + colEnd = Math.min(colEnd, rowEnd >= 1 ? mBitmapMatrix[rowEnd - 1].length : 0); for (int row = rowStart; row < rowEnd; row++) { for (int col = colStart; col < colEnd; col++) {
diff --git a/components/password_manager/core/browser/mock_password_feature_manager.h b/components/password_manager/core/browser/mock_password_feature_manager.h index c92fc2e..6e8a721 100644 --- a/components/password_manager/core/browser/mock_password_feature_manager.h +++ b/components/password_manager/core/browser/mock_password_feature_manager.h
@@ -31,6 +31,9 @@ MOCK_CONST_METHOD0(ComputePasswordAccountStorageUsageLevel, metrics_util::PasswordAccountStorageUsageLevel()); + + MOCK_METHOD0(IncrementMoveToAccountRefusedCount, void()); + MOCK_CONST_METHOD0(GetMoveToAccountRefusedCount, int()); }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_feature_manager.h b/components/password_manager/core/browser/password_feature_manager.h index f2cd4b1..01fdfe1 100644 --- a/components/password_manager/core/browser/password_feature_manager.h +++ b/components/password_manager/core/browser/password_feature_manager.h
@@ -71,6 +71,18 @@ virtual metrics_util::PasswordAccountStorageUsageLevel ComputePasswordAccountStorageUsageLevel() const = 0; + // Increases the count of how many times Chrome automatically offered to move + // a password to the account and the user refused this, e.g. by ignoring the + // bubble that's shown after successful sign-in with a device password. Should + // only be called if the user is signed-in and not opted-in. + virtual void IncrementMoveToAccountRefusedCount() = 0; + + // Gets the count of how many times Chrome automatically offered to move a + // password to the account and the user refused this, e.g. by ignoring the + // bubble that's shown after successful sign-in with a device password. Should + // only be called if the user is signed-in and not opted-in. + virtual int GetMoveToAccountRefusedCount() const = 0; + private: DISALLOW_COPY_AND_ASSIGN(PasswordFeatureManager); };
diff --git a/components/password_manager/core/browser/password_feature_manager_impl.cc b/components/password_manager/core/browser/password_feature_manager_impl.cc index 7ceb1a0..5535d354 100644 --- a/components/password_manager/core/browser/password_feature_manager_impl.cc +++ b/components/password_manager/core/browser/password_feature_manager_impl.cc
@@ -77,4 +77,14 @@ sync_service_); } +void PasswordFeatureManagerImpl::IncrementMoveToAccountRefusedCount() { + features_util::IncrementMoveToAccountRefusedCount(pref_service_, + sync_service_); +} + +int PasswordFeatureManagerImpl::GetMoveToAccountRefusedCount() const { + return features_util::GetMoveToAccountRefusedCount(pref_service_, + sync_service_); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_feature_manager_impl.h b/components/password_manager/core/browser/password_feature_manager_impl.h index e49d484..e7d2801 100644 --- a/components/password_manager/core/browser/password_feature_manager_impl.h +++ b/components/password_manager/core/browser/password_feature_manager_impl.h
@@ -41,6 +41,9 @@ metrics_util::PasswordAccountStorageUsageLevel ComputePasswordAccountStorageUsageLevel() const override; + void IncrementMoveToAccountRefusedCount() override; + int GetMoveToAccountRefusedCount() const override; + private: PrefService* const pref_service_; const syncer::SyncService* const sync_service_;
diff --git a/components/password_manager/core/browser/password_manager_client_helper.cc b/components/password_manager/core/browser/password_manager_client_helper.cc index 8de7a05a..2a8bdb9 100644 --- a/components/password_manager/core/browser/password_manager_client_helper.cc +++ b/components/password_manager/core/browser/password_manager_client_helper.cc
@@ -4,6 +4,7 @@ #include "components/password_manager/core/browser/password_manager_client_helper.h" +#include "base/metrics/field_trial_params.h" #include "base/strings/utf_string_conversions.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_feature_manager.h" @@ -105,11 +106,11 @@ bool PasswordManagerClientHelper::ShouldPromptToMovePasswordToAccount( const PasswordFormManagerForUI& submitted_manager) const { - if (!delegate_->GetPasswordFeatureManager() - ->ShouldShowAccountStorageBubbleUi()) { + PasswordFeatureManager* feature_manager = + delegate_->GetPasswordFeatureManager(); + if (!feature_manager->ShouldShowAccountStorageBubbleUi()) return false; - } - if (delegate_->GetPasswordFeatureManager()->GetDefaultPasswordStore() == + if (feature_manager->GetDefaultPasswordStore() == autofill::PasswordForm::Store::kProfileStore) { return false; } @@ -125,7 +126,14 @@ submitted_manager.GetPendingCredentials().signon_realm)) { return false; } - return true; + int max_move_to_account_offers_for_non_opted_in_user = + base::GetFieldTrialParamByFeatureAsInt( + features::kEnablePasswordsAccountStorage, + features::kMaxMoveToAccountOffersForNonOptedInUser, + features::kMaxMoveToAccountOffersForNonOptedInUserDefaultValue); + return feature_manager->IsOptedInForAccountStorage() || + feature_manager->GetMoveToAccountRefusedCount() < + max_move_to_account_offers_for_non_opted_in_user; } } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_client_helper_unittest.cc b/components/password_manager/core/browser/password_manager_client_helper_unittest.cc index 4c3ec13..1a7d1ba 100644 --- a/components/password_manager/core/browser/password_manager_client_helper_unittest.cc +++ b/components/password_manager/core/browser/password_manager_client_helper_unittest.cc
@@ -172,7 +172,7 @@ TEST_F(PasswordManagerClientHelperTest, NoPromptToMoveWithoutFeature) { base::test::ScopedFeatureList account_storage_feature; account_storage_feature.InitAndDisableFeature( - password_manager::features::kEnablePasswordsAccountStorage); + features::kEnablePasswordsAccountStorage); EXPECT_CALL(*client(), PromptUserToMovePasswordToAccount).Times(0); EXPECT_CALL(*client(), PromptUserToEnableAutosignin).Times(0); @@ -186,7 +186,7 @@ TEST_F(PasswordManagerClientHelperTest, NoPromptToMoveForUnmovableForm) { base::test::ScopedFeatureList account_storage_feature; account_storage_feature.InitAndEnableFeature( - password_manager::features::kEnablePasswordsAccountStorage); + features::kEnablePasswordsAccountStorage); EXPECT_CALL(*client(), PromptUserToMovePasswordToAccount).Times(0); EXPECT_CALL(*client(), PromptUserToEnableAutosignin).Times(0); @@ -200,7 +200,7 @@ TEST_F(PasswordManagerClientHelperTest, NoPromptToMoveForGaiaAccountForm) { base::test::ScopedFeatureList account_storage_feature; account_storage_feature.InitAndEnableFeature( - password_manager::features::kEnablePasswordsAccountStorage); + features::kEnablePasswordsAccountStorage); EXPECT_CALL(*client()->GetPasswordFeatureManager(), ShouldShowAccountStorageBubbleUi) .WillOnce(Return(true)); @@ -215,4 +215,35 @@ CreateFormManager(&gaia_account_form, /*is_movable=*/true)); } +TEST_F(PasswordManagerClientHelperTest, + NoPromptToMoveForNonOptedInUserIfRefusedTooManyTimes) { + base::test::ScopedFeatureList account_storage_feature; + account_storage_feature.InitAndEnableFeatureWithParameters( + features::kEnablePasswordsAccountStorage, + {{features::kMaxMoveToAccountOffersForNonOptedInUser, "1"}}); + ON_CALL(*client()->GetPasswordFeatureManager(), + ShouldShowAccountStorageBubbleUi) + .WillByDefault(Return(true)); + ON_CALL(*client()->GetPasswordFeatureManager(), GetDefaultPasswordStore) + .WillByDefault(Return(autofill::PasswordForm::Store::kAccountStore)); + + // Simulate that no refusals happened so far. Moving should be offered. + EXPECT_CALL(*client()->GetPasswordFeatureManager(), + GetMoveToAccountRefusedCount) + .WillOnce(Return(0)); + EXPECT_CALL(*client(), PromptUserToMovePasswordToAccount); + const PasswordForm form = + CreateForm(kTestUsername, kTestPassword, GURL(kTestOrigin)); + helper()->NotifySuccessfulLoginWithExistingPassword( + CreateFormManager(&form, /*is_movable=*/true)); + + // If the previous move was refused and the max is 1, shouldn't offer anymore. + EXPECT_CALL(*client()->GetPasswordFeatureManager(), + GetMoveToAccountRefusedCount) + .WillOnce(Return(1)); + EXPECT_CALL(*client(), PromptUserToMovePasswordToAccount).Times(0); + helper()->NotifySuccessfulLoginWithExistingPassword( + CreateFormManager(&form, /*is_movable=*/true)); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_features_util.h b/components/password_manager/core/browser/password_manager_features_util.h index b2612fc..7b262ae 100644 --- a/components/password_manager/core/browser/password_manager_features_util.h +++ b/components/password_manager/core/browser/password_manager_features_util.h
@@ -132,7 +132,8 @@ // password to the account and the user refused this, e.g. by ignoring the // bubble that's shown after successful sign-in with a device password. Should // only be called if the user is signed-in and not opted-in. |pref_service| and -// |sync_service| should be non-null. +// |sync_service| must be non-null. +// See PasswordFeatureManager::IncrementMoveToAccountRefusedCount(). void IncrementMoveToAccountRefusedCount( PrefService* pref_service, const syncer::SyncService* sync_service); @@ -141,7 +142,8 @@ // password to the account and the user refused this, e.g. by ignoring the // bubble that's shown after successful sign-in with a device password. Should // only be called if the user is signed-in and not opted-in. |pref_service| and -// |sync_service| should be non-null. +// |sync_service| must be non-null. +// See PasswordFeatureManager::GetMoveToAccountRefusedCount(). int GetMoveToAccountRefusedCount(const PrefService* pref_service, const syncer::SyncService* sync_service);
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index eceeaa3..cce676d 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -133,6 +133,14 @@ const char kPasswordChangeInSettingsWithForcedWarningForEverySite[] = "should_force_warning_for_every_site_in_settings"; +// Number of times the user can refuse an offer to move a password to the +// account before Chrome stops offering this flow. Only applies to users who +// haven't gone through the opt-in flow for passwords account storage. +const char kMaxMoveToAccountOffersForNonOptedInUser[] = + "max_move_to_account_offers_for_non_opted_in_user"; + +const int kMaxMoveToAccountOffersForNonOptedInUserDefaultValue = 5; + } // namespace features } // namespace password_manager
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h index 039b6af..e16fa911 100644 --- a/components/password_manager/core/common/password_manager_features.h +++ b/components/password_manager/core/common/password_manager_features.h
@@ -54,6 +54,10 @@ kPasswordChangeWithForcedDialogAfterEverySuccessfulSubmission[]; extern const char kPasswordChangeInSettingsWithForcedWarningForEverySite[]; +// |kEnablePasswordAccountStorage| variations. +extern const char kMaxMoveToAccountOffersForNonOptedInUser[]; +extern const int kMaxMoveToAccountOffersForNonOptedInUserDefaultValue; + } // namespace features } // namespace password_manager
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestLifecycleObserver.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestLifecycleObserver.java index 00065bb..5b8a18d 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestLifecycleObserver.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestLifecycleObserver.java
@@ -4,6 +4,9 @@ package org.chromium.components.payments; +import org.chromium.payments.mojom.PaymentRequest; +import org.chromium.payments.mojom.PaymentValidationErrors; + /** Observe the lifecycle of the PaymentRequest. */ public interface PaymentRequestLifecycleObserver { /** @@ -11,4 +14,10 @@ * @param params The parameters. */ void onPaymentRequestParamsInitiated(PaymentRequestParams params); + + /** + * Called after {@link PaymentRequest#retry} is invoked. + * @param errors The payment validation errors. + */ + void onRetry(PaymentValidationErrors errors); }
diff --git a/components/policy/core/browser/policy_pref_mapping_test.cc b/components/policy/core/browser/policy_pref_mapping_test.cc index 7dcdf70..14a5aa5a 100644 --- a/components/policy/core/browser/policy_pref_mapping_test.cc +++ b/components/policy/core/browser/policy_pref_mapping_test.cc
@@ -359,7 +359,7 @@ ASSERT_TRUE(policy_details); policy_map.Set( it.first, level, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, - it.second.CreateDeepCopy(), + it.second.Clone(), policy_details->max_external_data_size ? std::make_unique<ExternalDataFetcher>(nullptr, it.first) : nullptr);
diff --git a/components/policy/core/common/async_policy_provider_unittest.cc b/components/policy/core/common/async_policy_provider_unittest.cc index a9d618e2..7594fd225 100644 --- a/components/policy/core/common/async_policy_provider_unittest.cc +++ b/components/policy/core/common/async_policy_provider_unittest.cc
@@ -34,8 +34,7 @@ const std::string& value) { bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) .Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>(value), - nullptr); + POLICY_SOURCE_PLATFORM, base::Value(value), nullptr); } class MockPolicyLoader : public AsyncPolicyLoader {
diff --git a/components/policy/core/common/cloud/component_cloud_policy_store.cc b/components/policy/core/common/cloud/component_cloud_policy_store.cc index 1c39b22..4800bfbd 100644 --- a/components/policy/core/common/cloud/component_cloud_policy_store.cc +++ b/components/policy/core/common/cloud/component_cloud_policy_store.cc
@@ -435,8 +435,7 @@ level = POLICY_LEVEL_RECOMMENDED; policy->Set(policy_name, level, domain_constants_->scope, policy_source_, - base::Value::ToUniquePtrValue(std::move(value.value())), - nullptr); + std::move(value.value()), nullptr); } return true;
diff --git a/components/policy/core/common/cloud/user_cloud_policy_manager.cc b/components/policy/core/common/cloud/user_cloud_policy_manager.cc index 9384f98..4201a729 100644 --- a/components/policy/core/common/cloud/user_cloud_policy_manager.cc +++ b/components/policy/core/common/cloud/user_cloud_policy_manager.cc
@@ -114,8 +114,7 @@ !policy_map->Get(key::kNTPContentSuggestionsEnabled)) { policy_map->Set(key::kNTPContentSuggestionsEnabled, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_ENTERPRISE_DEFAULT, - std::make_unique<base::Value>(false), - nullptr /* external_data_fetcher */); + base::Value(false), nullptr /* external_data_fetcher */); } #endif }
diff --git a/components/policy/core/common/generate_policy_source_unittest.cc b/components/policy/core/common/generate_policy_source_unittest.cc index 59de129..d7c75da 100644 --- a/components/policy/core/common/generate_policy_source_unittest.cc +++ b/components/policy/core/common/generate_policy_source_unittest.cc
@@ -221,7 +221,7 @@ // If policy already configured, it's not changed to enterprise defaults. policy_map.Set(key::kChromeOsMultiProfileUserBehavior, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>("test_value"), nullptr); + base::Value("test_value"), nullptr); SetEnterpriseUsersDefaults(&policy_map); multiprof_behavior = policy_map.GetValue(key::kChromeOsMultiProfileUserBehavior);
diff --git a/components/policy/core/common/legacy_chrome_policy_migrator_unittest.cc b/components/policy/core/common/legacy_chrome_policy_migrator_unittest.cc index 2577ad0..f9cac88c 100644 --- a/components/policy/core/common/legacy_chrome_policy_migrator_unittest.cc +++ b/components/policy/core/common/legacy_chrome_policy_migrator_unittest.cc
@@ -28,9 +28,7 @@ *val = base::Value(val->GetInt() * 3); } -void SetPolicy(PolicyMap* policy, - const char* policy_name, - std::unique_ptr<base::Value> value) { +void SetPolicy(PolicyMap* policy, const char* policy_name, base::Value value) { policy->Set(policy_name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, std::move(value), nullptr); } @@ -42,9 +40,8 @@ PolicyMap& chrome_map = bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); - SetPolicy(&chrome_map, kOldPolicy, std::make_unique<base::Value>(kOldValue)); - SetPolicy(&chrome_map, kOtherPolicy, - std::make_unique<base::Value>(kOtherValue)); + SetPolicy(&chrome_map, kOldPolicy, base::Value(kOldValue)); + SetPolicy(&chrome_map, kOtherPolicy, base::Value(kOtherValue)); LegacyChromePolicyMigrator migrator(kOldPolicy, kNewPolicy); @@ -71,7 +68,7 @@ PolicyMap& chrome_map = bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); - SetPolicy(&chrome_map, kOldPolicy, std::make_unique<base::Value>(kOldValue)); + SetPolicy(&chrome_map, kOldPolicy, base::Value(kOldValue)); LegacyChromePolicyMigrator migrator(kOldPolicy, kNewPolicy, base::BindRepeating(&MultiplyByThree)); @@ -88,8 +85,8 @@ PolicyMap& chrome_map = bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); - SetPolicy(&chrome_map, kOldPolicy, std::make_unique<base::Value>(kOldValue)); - SetPolicy(&chrome_map, kNewPolicy, std::make_unique<base::Value>(kNewValue)); + SetPolicy(&chrome_map, kOldPolicy, base::Value(kOldValue)); + SetPolicy(&chrome_map, kNewPolicy, base::Value(kNewValue)); LegacyChromePolicyMigrator migrator(kOldPolicy, kNewPolicy);
diff --git a/components/policy/core/common/policy_bundle_unittest.cc b/components/policy/core/common/policy_bundle_unittest.cc index 6625447e..09104ea 100644 --- a/components/policy/core/common/policy_bundle_unittest.cc +++ b/components/policy/core/common/policy_bundle_unittest.cc
@@ -37,10 +37,10 @@ POLICY_SOURCE_CLOUD, base::Value("omg"), nullptr); policy->Set("recommended-user", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(true), nullptr); - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetBoolean("false", false); - dict->SetInteger("int", 456); - dict->SetString("str", "bbq"); + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetBoolKey("false", false); + dict.SetIntKey("int", 456); + dict.SetStringKey("str", "bbq"); policy->Set("recommended-machine", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, std::move(dict), nullptr);
diff --git a/components/policy/core/common/policy_loader_ios.h b/components/policy/core/common/policy_loader_ios.h index c04a579..ca4682c 100644 --- a/components/policy/core/common/policy_loader_ios.h +++ b/components/policy/core/common/policy_loader_ios.h
@@ -40,9 +40,8 @@ // Validates the given policy data against the stored |schema_|, converting // data to the expected type if necessary. The returned value is suitable for // adding to a PolicyMap. - std::unique_ptr<base::Value> ConvertPolicyDataIfNecessary( - const std::string& key, - const base::Value& value); + base::Value ConvertPolicyDataIfNecessary(const std::string& key, + const base::Value& value); // The schema used by |ValidatePolicyData()|. const Schema* policy_schema_;
diff --git a/components/policy/core/common/policy_loader_ios.mm b/components/policy/core/common/policy_loader_ios.mm index 36b57d8..8e58ebf 100644 --- a/components/policy/core/common/policy_loader_ios.mm +++ b/components/policy/core/common/policy_loader_ios.mm
@@ -149,13 +149,13 @@ } } -std::unique_ptr<base::Value> PolicyLoaderIOS::ConvertPolicyDataIfNecessary( +base::Value PolicyLoaderIOS::ConvertPolicyDataIfNecessary( const std::string& key, const base::Value& value) { const Schema schema = policy_schema_->GetKnownProperty(key); if (!schema.valid()) { - return value.CreateDeepCopy(); + return value.Clone(); } // Handle the case of a JSON-encoded string for a dict policy. @@ -163,12 +163,12 @@ base::Optional<base::Value> decoded_value = base::JSONReader::Read( value.GetString(), base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS); if (decoded_value.has_value()) { - return base::Value::ToUniquePtrValue(std::move(decoded_value.value())); + return std::move(decoded_value.value()); } } // Otherwise return an unchanged value. - return value.CreateDeepCopy(); + return value.Clone(); } } // namespace policy
diff --git a/components/policy/core/common/policy_loader_mac.mm b/components/policy/core/common/policy_loader_mac.mm index bb19a66..7bbe6c5 100644 --- a/components/policy/core/common/policy_loader_mac.mm +++ b/components/policy/core/common/policy_loader_mac.mm
@@ -134,7 +134,7 @@ std::unique_ptr<base::Value> policy = PropertyToValue(value); if (policy) { chrome_policy.Set(it.key(), level, POLICY_SCOPE_MACHINE, - POLICY_SOURCE_PLATFORM, std::move(policy), nullptr); + POLICY_SOURCE_PLATFORM, std::move(*policy), nullptr); } else { status.Add(POLICY_LOAD_STATUS_PARSE_ERROR); } @@ -234,7 +234,7 @@ std::unique_ptr<base::Value> policy_value = PropertyToValue(value); if (policy_value) { policy->Set(it.key(), level, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM, - std::move(policy_value), nullptr); + std::move(*policy_value), nullptr); } } }
diff --git a/components/policy/core/common/policy_loader_mac_unittest.cc b/components/policy/core/common/policy_loader_mac_unittest.cc index 846af796..1e5ea05 100644 --- a/components/policy/core/common/policy_loader_mac_unittest.cc +++ b/components/policy/core/common/policy_loader_mac_unittest.cc
@@ -197,7 +197,7 @@ expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) .Set(test_keys::kKeyString, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM, - std::make_unique<base::Value>("string value"), nullptr); + base::Value("string value"), nullptr); EXPECT_TRUE(provider_->policies().Equals(expected_bundle)); }
diff --git a/components/policy/core/common/policy_service_impl.cc b/components/policy/core/common/policy_service_impl.cc index a73b9cd4..d607651 100644 --- a/components/policy/core/common/policy_service_impl.cc +++ b/components/policy/core/common/policy_service_impl.cc
@@ -51,21 +51,19 @@ // first, and then only policies with those exact attributes are merged. PolicyMap::Entry current_priority; // Defaults to the lowest priority. PolicySource inherited_source = POLICY_SOURCE_ENTERPRISE_DEFAULT; - std::unique_ptr<base::DictionaryValue> proxy_settings( - new base::DictionaryValue); + base::Value proxy_settings(base::Value::Type::DICTIONARY); for (size_t i = 0; i < base::size(kProxyPolicies); ++i) { const PolicyMap::Entry* entry = policies->Get(kProxyPolicies[i]); if (entry) { if (entry->has_higher_priority_than(current_priority)) { - proxy_settings->Clear(); + proxy_settings = base::Value(base::Value::Type::DICTIONARY); current_priority = entry->DeepCopy(); if (entry->source > inherited_source) // Higher priority? inherited_source = entry->source; } if (!entry->has_higher_priority_than(current_priority) && !current_priority.has_higher_priority_than(*entry)) { - proxy_settings->Set(kProxyPolicies[i], - entry->value()->CreateDeepCopy()); + proxy_settings.SetKey(kProxyPolicies[i], entry->value()->Clone()); } policies->Erase(kProxyPolicies[i]); } @@ -73,7 +71,7 @@ // Sets the new |proxy_settings| if kProxySettings isn't set yet, or if the // new priority is higher. const PolicyMap::Entry* existing = policies->Get(key::kProxySettings); - if (!proxy_settings->empty() && + if (!proxy_settings.DictEmpty() && (!existing || current_priority.has_higher_priority_than(*existing))) { policies->Set(key::kProxySettings, current_priority.level, current_priority.scope, inherited_source,
diff --git a/components/policy/core/common/policy_statistics_collector_unittest.cc b/components/policy/core/common/policy_statistics_collector_unittest.cc index 2d01549..d6fdb11 100644 --- a/components/policy/core/common/policy_statistics_collector_unittest.cc +++ b/components/policy/core/common/policy_statistics_collector_unittest.cc
@@ -116,8 +116,7 @@ void SetPolicy(const std::string& name) { policy_map_.Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, - POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), - nullptr); + POLICY_SOURCE_CLOUD, base::Value(true), nullptr); } void SetPolicyIgnoredByAtomicGroup(const std::string& name) {
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 1a4ef7a..ebda116 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -3657,7 +3657,7 @@ If this policy isn't set, only file types that a user has already specified to automatically be opened will do so when downloaded. - This policy is available only on Windows instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain. or Windows 10 Pro or Enterprise instances that enrolled for device management and macOS instances that are that are managed via MDM or joined to a domain via MCX.''', + On <ph name="MS_WIN_NAME">Microsoft® Windows®</ph>, this functionality is only available on instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, running on Windows 10 Pro, or enrolled in Chrome Browser Cloud Management. On <ph name="MAC_OS_NAME">macOS</ph>, this functionality is only available on instances that are managed via MDM, or joined to a domain via MCX.''', }, { 'name': 'AutoOpenAllowedForURLs', @@ -4452,7 +4452,9 @@ This policy superseeds <ph name="EXTENSION_INSTALL_BLOCKLIST_POLICY_NAME">ExtensionInstallBlocklist</ph> policy. If a previously force-installed app or extension is removed from this list, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> automatically uninstalls it. - For Windows® instances not joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, forced installation is limited to apps and extensions in the Chrome Web Store. + On <ph name="MS_WIN_NAME">Microsoft® Windows®</ph> instances, apps and extensions from outside the Chrome Web Store can only be forced installed if the instance is joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, running on Windows 10 Pro, or enrolled in Chrome Browser Cloud Management. + + On <ph name="MAC_OS_NAME">macOS</ph> instances, apps and extensions from outside the Chrome Web Store can only can only be force installed if the instance is managed via MDM, or joined to a domain via MCX. The source code of any extension may be altered by users through developer tools, potentially rendering the extension dysfunctional. If this is a concern, set the <ph name="DEVELOPER_TOOLS_DISABLED_POLICY_NAME">DeveloperToolsDisabled</ph> policy. @@ -4958,7 +4960,7 @@ If you set the policy, users can't change it in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>. If not set, the default search provider is on, and users can set the search provider list. - Note: This policy is only on Windows® instances that are joined to a <ph name="MS_AD_NAME">Microsoft®ActiveDirectory®</ph> domain, Windows 10 Pro, or Chrome Enterprise Upgrade and macOS instances that are that are managed via MDM or joined to a domain via MCX.''', + On <ph name="MS_WIN_NAME">Microsoft® Windows®</ph>, this functionality is only available on instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, running on Windows 10 Pro, or enrolled in Chrome Browser Cloud Management. On <ph name="MAC_OS_NAME">macOS</ph>, this functionality is only available on instances that are managed via MDM, or joined to a domain via MCX.''', }, { 'name': 'DefaultSearchProviderContextMenuAccessAllowed', @@ -17257,7 +17259,7 @@ If this setting is enabled, then Safe Browsing will trust these domains. If this setting is disabled or not set, then default Safe Browsing protection is applied to all resources. - This policy is available only on Windows instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain. or Windows 10 Pro or Enterprise instances that enrolled for device management and macOS instances that are that are managed via MDM or joined to a domain via MCX.''', + On <ph name="MS_WIN_NAME">Microsoft® Windows®</ph>, this functionality is only available on instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, running on Windows 10 Pro, or enrolled in Chrome Browser Cloud Management. On <ph name="MAC_OS_NAME">macOS</ph>, this functionality is only available on instances that are managed via MDM, or joined to a domain via MCX.''', }, { 'name': 'PasswordProtectionLoginURLs', @@ -17579,7 +17581,7 @@ If enabled or unset, Chrome Cleanup periodically scans the system for unwanted software and should any be found, will ask the user if they wish to remove it. Manually triggering Chrome Cleanup from chrome://settings is enabled. - This policy is available only on Windows instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain. or Windows 10 Pro or Enterprise instances that enrolled for device management.''', + On <ph name="MS_WIN_NAME">Microsoft® Windows®</ph>, this functionality is only available on instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, running on Windows 10 Pro, or enrolled in Chrome Browser Cloud Management.''', }, { 'name': 'ChromeCleanupReportingEnabled', @@ -17601,7 +17603,7 @@ If enabled, should Chrome Cleanup detect unwanted software, it may report metadata about the scan to Google in accordance with policy set by SafeBrowsingExtendedReportingEnabled. Chrome Cleanup will ask the user if they wish to clean up the unwanted software. Results of the cleanup will be reported to Google and the user will not have the option to prevent it. - This policy is available only on Windows instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain. or Windows 10 Pro or Enterprise instances that enrolled for device management.''', + On <ph name="MS_WIN_NAME">Microsoft® Windows®</ph>, this functionality is only available on instances that are joined to a <ph name="MS_AD_NAME">Microsoft® Active Directory®</ph> domain, running on Windows 10 Pro, or enrolled in Chrome Browser Cloud Management.''', }, { 'name': 'AllowedLanguages',
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py index 6d6c9ea..0fed66a 100755 --- a/components/policy/tools/generate_policy_source.py +++ b/components/policy/tools/generate_policy_source.py
@@ -1009,17 +1009,17 @@ |value|: The deserialized value to convert to base::Value.""" if type(value) == bool or type(value) == int: - return [], 'std::make_unique<base::Value>(%s)' % json.dumps(value) + return [], 'base::Value(%s)' % json.dumps(value) elif type(value) == str: - return [], 'std::make_unique<base::Value>("%s")' % value + return [], 'base::Value("%s")' % value elif type(value) == list: - setup = ['auto default_value = std::make_unique<base::ListValue>();'] + setup = ['base::Value default_value(base::Value::Type::LIST);'] for entry in value: decl, fetch = _GenerateDefaultValue(entry) # Nested lists are not supported. if decl: return [], None - setup.append('default_value->Append(%s);' % fetch) + setup.append('default_value.Append(%s);' % fetch) return setup, 'std::move(default_value)' return [], None
diff --git a/components/signin/internal/identity_manager/BUILD.gn b/components/signin/internal/identity_manager/BUILD.gn index e7d0cce..bbd18b4 100644 --- a/components/signin/internal/identity_manager/BUILD.gn +++ b/components/signin/internal/identity_manager/BUILD.gn
@@ -197,6 +197,13 @@ "fake_profile_oauth2_token_service_delegate.h", ] + if (is_chromeos) { + sources += [ + "test_profile_oauth2_token_service_delegate_chromeos.cc", + "test_profile_oauth2_token_service_delegate_chromeos.h", + ] + } + public_deps = [ ":identity_manager", "//base",
diff --git a/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc b/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc index f3aa3e0..6c7e3d0 100644 --- a/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc +++ b/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.cc
@@ -5,20 +5,26 @@ #include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h" #include <memory> +#include <utility> #include "components/signin/internal/identity_manager/fake_profile_oauth2_token_service_delegate.h" FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService( PrefService* user_prefs) - : ProfileOAuth2TokenService( + : FakeProfileOAuth2TokenService( user_prefs, - std::make_unique<FakeProfileOAuth2TokenServiceDelegate>()) { + std::make_unique<FakeProfileOAuth2TokenServiceDelegate>()) {} + +FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService( + PrefService* user_prefs, + std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate) + : ProfileOAuth2TokenService(user_prefs, std::move(delegate)) { OverrideAccessTokenManagerForTesting( std::make_unique<FakeOAuth2AccessTokenManager>( this /* OAuth2AccessTokenManager::Delegate* */)); } -FakeProfileOAuth2TokenService::~FakeProfileOAuth2TokenService() {} +FakeProfileOAuth2TokenService::~FakeProfileOAuth2TokenService() = default; void FakeProfileOAuth2TokenService::IssueAllTokensForAccount( const CoreAccountId& account_id,
diff --git a/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h b/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h index dc8f4ba..2a09d3c 100644 --- a/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h +++ b/components/signin/internal/identity_manager/fake_profile_oauth2_token_service.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_ #define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_H_ +#include <memory> #include <string> #include <vector> @@ -36,6 +37,9 @@ class FakeProfileOAuth2TokenService : public ProfileOAuth2TokenService { public: explicit FakeProfileOAuth2TokenService(PrefService* user_prefs); + FakeProfileOAuth2TokenService( + PrefService* user_prefs, + std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate); ~FakeProfileOAuth2TokenService() override; // Gets a list of active requests (can be used by tests to validate that the
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc index 1a36cc3..2cd93ec 100644 --- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc +++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.cc
@@ -60,11 +60,15 @@ --batch_change_depth_; DCHECK_LE(0, batch_change_depth_); if (batch_change_depth_ == 0) { - for (auto& observer : observer_list_) - observer.OnEndBatchChanges(); + FireEndBatchChanges(); } } +void ProfileOAuth2TokenServiceDelegate::FireEndBatchChanges() { + for (auto& observer : observer_list_) + observer.OnEndBatchChanges(); +} + void ProfileOAuth2TokenServiceDelegate::FireRefreshTokenAvailable( const CoreAccountId& account_id) { DCHECK(!account_id.empty());
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h index 5cc8236..6107e14d 100644 --- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h +++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h
@@ -156,6 +156,7 @@ } // Called by subclasses to notify observers. + void FireEndBatchChanges(); void FireRefreshTokenAvailable(const CoreAccountId& account_id); void FireRefreshTokenRevoked(const CoreAccountId& account_id); // FireRefreshTokensLoaded is virtual and overridden in android implementation
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc index 559be84..9e5c2a3 100644 --- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc +++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc
@@ -246,53 +246,9 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateCredentials( const CoreAccountId& account_id, const std::string& refresh_token) { - // This API could have been called for upserting the Device/Primary - // |account_id| or a Secondary |account_id|. - - // Account insertion: - // Device Account insertion on Chrome OS happens as a 2 step process: - // 1. The account is inserted into PrimaryAccountManager / - // AccountTrackerService, via IdentityManager, with a valid Gaia id and email - // but an invalid refresh token. - // 2. This API is called to update the aforementioned account with a valid - // refresh token. - // Secondary Account insertion on Chrome OS happens atomically in - // |InlineLoginHandlerChromeOS::<anon>::SigninHelper::OnClientOAuthSuccess|. - // In both of the aforementioned cases, we can be sure that when this API is - // called, |account_id| is guaranteed to be present in - // |AccountTrackerService|. This guarantee is important because - // |ProfileOAuth2TokenServiceDelegateChromeOS| relies on - // |AccountTrackerService| to convert |account_id| to an email id. - - // Account update: - // If an account is being updated, it must be present in - // |AccountTrackerService|. - - // Hence for all cases (insertion and updates for Device and Secondary - // Accounts) we can be sure that |account_id| is present in - // |AccountTrackerService|. - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK_EQ( - signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS, - load_credentials_state()); - DCHECK(!account_id.empty()); - DCHECK(!refresh_token.empty()); - - ValidateAccountId(account_id); - - const AccountInfo& account_info = - account_tracker_service_->GetAccountInfo(account_id); - LOG_IF(FATAL, account_info.gaia.empty()) - << "account_id must be present in AccountTrackerService before " - "UpdateCredentials is called"; - - // Will result in chromeos::AccountManager calling - // |ProfileOAuth2TokenServiceDelegateChromeOS::OnTokenUpserted|. - account_manager_->UpsertAccount( - chromeos::AccountManager::AccountKey{ - account_info.gaia, chromeos::account_manager::AccountType:: - ACCOUNT_TYPE_GAIA} /* account_key */, - account_info.email /* email */, refresh_token); + // UpdateCredentials should not be called on Chrome OS. Credentials should be + // updated through Chrome OS Account Manager. + NOTREACHED(); } scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc index d9965a6f..f2e92878 100644 --- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc +++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos_unittest.cc
@@ -208,6 +208,18 @@ GetValidTokenResponse("token", 3600)); } + void UpdateCredentials(const std::string& gaia_id, + const std::string& email, + const std::string& refresh_token) { + // Will result in chromeos::AccountManager calling + // |ProfileOAuth2TokenServiceDelegateChromeOS::OnTokenUpserted|. + account_manager_.UpsertAccount( + chromeos::AccountManager::AccountKey{ + gaia_id, chromeos::account_manager::AccountType:: + ACCOUNT_TYPE_GAIA} /* account_key */, + email /* email */, refresh_token); + } + base::test::TaskEnvironment task_environment_; base::ScopedTempDir tmp_dir_; @@ -325,7 +337,7 @@ TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, ObserversAreNotifiedOnCredentialsInsertion) { TestOAuth2TokenServiceObserver observer(delegate_.get()); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); EXPECT_EQ(1UL, observer.account_ids_.size()); EXPECT_EQ(account_info_.account_id, *observer.account_ids_.begin()); @@ -338,19 +350,19 @@ TestOAuth2TokenServiceObserver observer(delegate_.get()); auto error = GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); // Deliberately add an error. delegate_->UpdateAuthError(account_info_.account_id, error); // Update credentials. The delegate will check if see cached errors. - delegate_->UpdateCredentials(account_info_.account_id, "new-token"); + UpdateCredentials(account_info_.gaia, account_info_.email, "new-token"); } TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, ObserversDoNotSeeCachedErrorsOnAccountRemoval) { auto error = GoogleServiceAuthError(GoogleServiceAuthError::State::SERVICE_ERROR); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); // Deliberately add an error. delegate_->UpdateAuthError(account_info_.account_id, error); account_manager_.RemoveAccount(chromeos::AccountManager::AccountKey{ @@ -363,8 +375,8 @@ TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, DummyTokensArePreEmptivelyRejected) { TestOAuth2TokenServiceObserver observer(delegate_.get()); - delegate_->UpdateCredentials(account_info_.account_id, - chromeos::AccountManager::kInvalidToken); + UpdateCredentials(account_info_.gaia, account_info_.email, + chromeos::AccountManager::kInvalidToken); const GoogleServiceAuthError error = delegate_->GetAuthError(account_info_.account_id); @@ -382,7 +394,7 @@ TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, ObserversAreNotifiedOnCredentialsUpdate) { TestOAuth2TokenServiceObserver observer(delegate_.get()); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); EXPECT_EQ(1UL, observer.account_ids_.size()); EXPECT_EQ(account_info_.account_id, *observer.account_ids_.begin()); @@ -394,10 +406,10 @@ ObserversAreNotNotifiedIfCredentialsAreNotUpdated) { TestOAuth2TokenServiceObserver observer(delegate_.get()); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); observer.account_ids_.clear(); observer.last_err_account_id_ = CoreAccountId(); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); EXPECT_TRUE(observer.account_ids_.empty()); EXPECT_TRUE(observer.last_err_account_id_.empty()); @@ -406,7 +418,7 @@ TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, BatchChangeObserversAreNotifiedOnCredentialsUpdate) { TestOAuth2TokenServiceObserver observer(delegate_.get()); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); EXPECT_EQ(1UL, observer.batch_change_records_.size()); EXPECT_EQ(1UL, observer.batch_change_records_[0].size()); @@ -545,7 +557,7 @@ UpdateCredentialsSucceeds) { EXPECT_TRUE(delegate_->GetAccounts().empty()); - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); std::vector<CoreAccountId> accounts = delegate_->GetAccounts(); EXPECT_EQ(1UL, accounts.size()); @@ -554,7 +566,7 @@ TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, ObserversAreNotifiedOnAccountRemoval) { - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); TestOAuth2TokenServiceObserver observer(delegate_.get()); account_manager_.RemoveAccount(gaia_account_key_); @@ -590,7 +602,7 @@ TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, BackOffIsTriggerredForTransientErrors) { - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); auto transient_error = GoogleServiceAuthError( GoogleServiceAuthError::State::SERVICE_UNAVAILABLE); delegate_->UpdateAuthError(account_info_.account_id, transient_error); @@ -628,7 +640,7 @@ TEST_F(ProfileOAuth2TokenServiceDelegateChromeOSTest, BackOffIsResetOnNetworkChange) { - delegate_->UpdateCredentials(account_info_.account_id, kGaiaToken); + UpdateCredentials(account_info_.gaia, account_info_.email, kGaiaToken); auto transient_error = GoogleServiceAuthError( GoogleServiceAuthError::State::SERVICE_UNAVAILABLE); delegate_->UpdateAuthError(account_info_.account_id, transient_error);
diff --git a/components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.cc b/components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.cc new file mode 100644 index 0000000..212ff2d4 --- /dev/null +++ b/components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.cc
@@ -0,0 +1,135 @@ +// 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/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.h" + +#include "google_apis/gaia/oauth2_access_token_fetcher.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" + +namespace signin { + +TestProfileOAuth2TokenServiceDelegateChromeOS:: + TestProfileOAuth2TokenServiceDelegateChromeOS( + AccountTrackerService* account_tracker_service, + chromeos::AccountManager* account_manager, + bool is_regular_profile) { + if (!network::TestNetworkConnectionTracker::HasInstance()) { + owned_tracker_ = network::TestNetworkConnectionTracker::CreateInstance(); + } + + delegate_ = std::make_unique<ProfileOAuth2TokenServiceDelegateChromeOS>( + account_tracker_service, + network::TestNetworkConnectionTracker::GetInstance(), account_manager, + is_regular_profile); + delegate_->AddObserver(this); +} + +TestProfileOAuth2TokenServiceDelegateChromeOS:: + ~TestProfileOAuth2TokenServiceDelegateChromeOS() { + delegate_->RemoveObserver(this); +} + +std::unique_ptr<OAuth2AccessTokenFetcher> +TestProfileOAuth2TokenServiceDelegateChromeOS::CreateAccessTokenFetcher( + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + OAuth2AccessTokenConsumer* consumer) { + return delegate_->CreateAccessTokenFetcher(account_id, url_loader_factory, + consumer); +} + +bool TestProfileOAuth2TokenServiceDelegateChromeOS::RefreshTokenIsAvailable( + const CoreAccountId& account_id) const { + return delegate_->RefreshTokenIsAvailable(account_id); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::UpdateAuthError( + const CoreAccountId& account_id, + const GoogleServiceAuthError& error) { + delegate_->UpdateAuthError(account_id, error); +} + +GoogleServiceAuthError +TestProfileOAuth2TokenServiceDelegateChromeOS::GetAuthError( + const CoreAccountId& account_id) const { + return delegate_->GetAuthError(account_id); +} + +std::vector<CoreAccountId> +TestProfileOAuth2TokenServiceDelegateChromeOS::GetAccounts() const { + return delegate_->GetAccounts(); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::LoadCredentials( + const CoreAccountId& primary_account_id) { + // In tests |LoadCredentials| may be called twice, in this case we call + // |FireRefreshTokensLoaded| again to notify that credentials are loaded. + if (load_credentials_state() == + signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS) { + FireRefreshTokensLoaded(); + return; + } + + if (load_credentials_state() != + signin::LoadCredentialsState::LOAD_CREDENTIALS_NOT_STARTED) { + return; + } + + set_load_credentials_state( + signin::LoadCredentialsState::LOAD_CREDENTIALS_IN_PROGRESS); + delegate_->LoadCredentials(primary_account_id); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::UpdateCredentials( + const CoreAccountId& account_id, + const std::string& refresh_token) { + delegate_->UpdateCredentials(account_id, refresh_token); +} + +scoped_refptr<network::SharedURLLoaderFactory> +TestProfileOAuth2TokenServiceDelegateChromeOS::GetURLLoaderFactory() const { + return delegate_->GetURLLoaderFactory(); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::RevokeCredentials( + const CoreAccountId& account_id) { + delegate_->RevokeCredentials(account_id); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::RevokeAllCredentials() { + delegate_->RevokeAllCredentials(); +} + +const net::BackoffEntry* +TestProfileOAuth2TokenServiceDelegateChromeOS::BackoffEntry() const { + return delegate_->BackoffEntry(); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::OnRefreshTokenAvailable( + const CoreAccountId& account_id) { + FireRefreshTokenAvailable(account_id); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::OnRefreshTokenRevoked( + const CoreAccountId& account_id) { + FireRefreshTokenRevoked(account_id); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::OnEndBatchChanges() { + FireEndBatchChanges(); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::OnRefreshTokensLoaded() { + set_load_credentials_state( + signin::LoadCredentialsState::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS); + FireRefreshTokensLoaded(); +} + +void TestProfileOAuth2TokenServiceDelegateChromeOS::OnAuthErrorChanged( + const CoreAccountId& account_id, + const GoogleServiceAuthError& auth_error) { + FireAuthErrorChanged(account_id, auth_error); +} + +} // namespace signin
diff --git a/components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.h b/components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.h new file mode 100644 index 0000000..e94f87b --- /dev/null +++ b/components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.h
@@ -0,0 +1,75 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_TEST_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_ +#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_TEST_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_ + +#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h" +#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h" +#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h" +#include "services/network/test/test_network_connection_tracker.h" + +class AccountTrackerService; +namespace chromeos { +class AccountManager; +} + +namespace signin { + +// Creates and owns instance of TestNetworkConnectionTracker, if it wasn't +// created yet. This is a wrapper around +// ProfileOAuth2TokenServiceDelegateChromeOS that can be used for testing. It +// lazily instantiates a TestNetworkConnectionTracker if it wasn't created yet. +class TestProfileOAuth2TokenServiceDelegateChromeOS + : public ProfileOAuth2TokenServiceDelegate, + public ProfileOAuth2TokenServiceObserver { + public: + TestProfileOAuth2TokenServiceDelegateChromeOS( + AccountTrackerService* account_tracker_service, + chromeos::AccountManager* account_manager, + bool is_regular_profile); + ~TestProfileOAuth2TokenServiceDelegateChromeOS() override; + TestProfileOAuth2TokenServiceDelegateChromeOS( + const TestProfileOAuth2TokenServiceDelegateChromeOS&) = delete; + TestProfileOAuth2TokenServiceDelegateChromeOS& operator=( + const TestProfileOAuth2TokenServiceDelegateChromeOS&) = delete; + + // ProfileOAuth2TokenServiceDelegate overrides. + std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher( + const CoreAccountId& account_id, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + OAuth2AccessTokenConsumer* consumer) override; + bool RefreshTokenIsAvailable(const CoreAccountId& account_id) const override; + void UpdateAuthError(const CoreAccountId& account_id, + const GoogleServiceAuthError& error) override; + GoogleServiceAuthError GetAuthError( + const CoreAccountId& account_id) const override; + std::vector<CoreAccountId> GetAccounts() const override; + void LoadCredentials(const CoreAccountId& primary_account_id) override; + void UpdateCredentials(const CoreAccountId& account_id, + const std::string& refresh_token) override; + scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() + const override; + void RevokeCredentials(const CoreAccountId& account_id) override; + void RevokeAllCredentials() override; + const net::BackoffEntry* BackoffEntry() const override; + + // |ProfileOAuth2TokenServiceObserver| implementation. + void OnRefreshTokenAvailable(const CoreAccountId& account_id) override; + void OnRefreshTokenRevoked(const CoreAccountId& account_id) override; + void OnEndBatchChanges() override; + void OnRefreshTokensLoaded() override; + void OnAuthErrorChanged(const CoreAccountId& account_id, + const GoogleServiceAuthError& auth_error) override; + + private: + // Owning pointer to TestNetworkConnectionTracker. Set only if it wasn't + // created before initialization of this class. + std::unique_ptr<network::TestNetworkConnectionTracker> owned_tracker_; + std::unique_ptr<ProfileOAuth2TokenServiceDelegateChromeOS> delegate_; +}; + +} // namespace signin + +#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_TEST_PROFILE_OAUTH2_TOKEN_SERVICE_DELEGATE_CHROMEOS_H_
diff --git a/components/signin/public/identity_manager/identity_manager_unittest.cc b/components/signin/public/identity_manager/identity_manager_unittest.cc index fcd4119..85b0cf2 100644 --- a/components/signin/public/identity_manager/identity_manager_unittest.cc +++ b/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -61,6 +61,7 @@ #if defined(OS_CHROMEOS) #include "chromeos/components/account_manager/account_manager.h" #include "chromeos/components/account_manager/account_manager_factory.h" +#include "components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.h" #endif namespace signin { @@ -134,13 +135,22 @@ class CustomFakeProfileOAuth2TokenService : public FakeProfileOAuth2TokenService { public: - CustomFakeProfileOAuth2TokenService(PrefService* user_prefs) + explicit CustomFakeProfileOAuth2TokenService(PrefService* user_prefs) : FakeProfileOAuth2TokenService(user_prefs) { OverrideAccessTokenManagerForTesting( std::make_unique<CustomFakeOAuth2AccessTokenManager>( this /* OAuth2AccessTokenManager::Delegate* */)); } + CustomFakeProfileOAuth2TokenService( + PrefService* user_prefs, + std::unique_ptr<ProfileOAuth2TokenServiceDelegate> delegate) + : FakeProfileOAuth2TokenService(user_prefs, std::move(delegate)) { + OverrideAccessTokenManagerForTesting( + std::make_unique<CustomFakeOAuth2AccessTokenManager>( + this /* OAuth2AccessTokenManager::Delegate* */)); + } + void set_on_access_token_invalidated_info( CoreAccountId expected_account_id_to_invalidate, std::set<std::string> expected_scopes_to_invalidate, @@ -291,6 +301,31 @@ identity_manager()->GetTokenService()); } + void UpdateCredentials(const CoreAccountId& account_id, + std::string gaia_id, + std::string email, + std::string token) { +#if defined(OS_CHROMEOS) + identity_manager()->GetChromeOSAccountManager()->UpsertAccount( + chromeos::AccountManager::AccountKey{ + gaia_id, chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA}, + email, token); +#else + token_service()->UpdateCredentials(account_id, "refresh_token"); +#endif + } + + void RevokeCredentials(const CoreAccountId& account_id, std::string gaia_id) { +#if defined(OS_CHROMEOS) + identity_manager()->GetChromeOSAccountManager()->RemoveAccount( + chromeos::AccountManager::AccountKey{ + gaia_id, + chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA}); +#else + token_service()->RevokeCredentials(account_id); +#endif + } + // See RecreateIdentityManager. enum class PrimaryAccountManagerSetup { kWithAuthenticatedAccout, @@ -321,17 +356,33 @@ ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir()); + auto account_tracker_service = std::make_unique<AccountTrackerService>(); + account_tracker_service->Initialize(&pref_service_, + temp_profile_dir_.GetPath()); + +#if defined(OS_CHROMEOS) + chromeos::AccountManager::RegisterPrefs(pref_service_.registry()); + chromeos::AccountManager* chromeos_account_manager = + GetAccountManagerFactory()->GetAccountManager( + temp_profile_dir_.GetPath().value()); + chromeos_account_manager->InitializeInEphemeralMode( + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + &test_url_loader_factory_)); + chromeos_account_manager->SetPrefService(&pref_service_); + auto token_service = std::make_unique<CustomFakeProfileOAuth2TokenService>( + &pref_service_, + std::make_unique<TestProfileOAuth2TokenServiceDelegateChromeOS>( + account_tracker_service.get(), chromeos_account_manager, + /*is_regular_profile=*/true)); +#else auto token_service = std::make_unique<CustomFakeProfileOAuth2TokenService>(&pref_service_); +#endif auto gaia_cookie_manager_service = std::make_unique<GaiaCookieManagerService>(token_service.get(), &signin_client_); - auto account_tracker_service = std::make_unique<AccountTrackerService>(); - account_tracker_service->Initialize(&pref_service_, - temp_profile_dir_.GetPath()); - auto account_fetcher_service = std::make_unique<AccountFetcherService>(); account_fetcher_service->Initialize( &signin_client_, token_service.get(), account_tracker_service.get(), @@ -388,9 +439,7 @@ primary_account_manager.get(), &pref_service_); #endif #if defined(OS_CHROMEOS) - init_params.chromeos_account_manager = - GetAccountManagerFactory()->GetAccountManager( - temp_profile_dir_.GetPath().value()); + init_params.chromeos_account_manager = chromeos_account_manager; #endif init_params.account_fetcher_service = std::move(account_fetcher_service); @@ -449,6 +498,9 @@ private: base::ScopedTempDir temp_profile_dir_; base::test::TaskEnvironment task_environment_; +#if defined(OS_CHROMEOS) + chromeos::AccountManagerFactory account_manager_factory_; +#endif sync_preferences::TestingPrefServiceSyncable pref_service_; network::TestURLLoaderFactory test_url_loader_factory_; TestSigninClient signin_client_; @@ -457,9 +509,6 @@ std::unique_ptr<TestIdentityManagerDiagnosticsObserver> identity_manager_diagnostics_observer_; CoreAccountId primary_account_id_; -#if defined(OS_CHROMEOS) - chromeos::AccountManagerFactory account_manager_factory_; -#endif DISALLOW_COPY_AND_ASSIGN(IdentityManagerTest); }; @@ -1170,7 +1219,8 @@ identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId, kTestEmail); identity_manager()->GetPrimaryAccountManager()->SignIn(kTestEmail); - token_service()->UpdateCredentials(primary_account_id(), "refresh_token"); + UpdateCredentials(primary_account_id(), kTestGaiaId, kTestEmail, + "refresh_token"); base::RunLoop run_loop; token_service()->set_on_access_token_invalidated_info( @@ -1210,7 +1260,8 @@ identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId, kTestEmail); identity_manager()->GetPrimaryAccountManager()->SignIn(kTestEmail); - token_service()->UpdateCredentials(primary_account_id(), "refresh_token"); + UpdateCredentials(primary_account_id(), kTestGaiaId, kTestEmail, + "refresh_token"); std::set<std::string> scopes{"scope"}; AccessTokenFetcher::TokenCallback callback = base::BindOnce( @@ -1260,7 +1311,7 @@ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2); CoreAccountId account_id2 = account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id; - token_service()->UpdateCredentials(account_id2, "refresh_token"); + UpdateCredentials(account_id2, kTestGaiaId2, kTestEmail2, "refresh_token"); // No changes to the declared scopes and callback, we can reuse them. std::unique_ptr<AccessTokenFetcher> token_fetcher2 = @@ -1299,7 +1350,8 @@ identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId, kTestEmail); identity_manager()->GetPrimaryAccountManager()->SignIn(kTestEmail); - token_service()->UpdateCredentials(primary_account_id(), "refresh_token"); + UpdateCredentials(primary_account_id(), kTestGaiaId, kTestEmail, + "refresh_token"); std::set<std::string> scopes{"scope"}; AccessTokenFetcher::TokenCallback callback = base::BindOnce( @@ -1353,7 +1405,8 @@ identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId, kTestEmail); identity_manager()->GetPrimaryAccountManager()->SignIn(kTestEmail); - token_service()->UpdateCredentials(primary_account_id(), "refresh_token"); + UpdateCredentials(primary_account_id(), kTestGaiaId, kTestEmail, + "refresh_token"); token_service()->set_auto_post_fetch_response_on_message_loop(true); std::set<std::string> scopes{"scope"}; @@ -1390,7 +1443,7 @@ account_tracker()->SeedAccountInfo(kTestGaiaId2, kTestEmail2); CoreAccountId account_id2 = account_tracker()->FindAccountInfoByGaiaId(kTestGaiaId2).account_id; - token_service()->UpdateCredentials(account_id2, "refresh_token"); + UpdateCredentials(account_id2, kTestGaiaId2, kTestEmail2, "refresh_token"); std::set<std::string> scopes{"scope"}; AccessTokenFetcher::TokenCallback callback = base::BindOnce( @@ -1402,7 +1455,7 @@ AccessTokenFetcher::Mode::kImmediate); // Revoke the refresh token result cancelling access token request. - token_service()->RevokeCredentials(account_id2); + RevokeCredentials(account_id2, kTestGaiaId2); run_loop.Run(); @@ -1575,7 +1628,6 @@ expected_account_info.account_id, identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback()); } -#endif TEST_F(IdentityManagerTest, CallbackSentOnRefreshTokenRemovalOfUnknownAccount) { // When the token service is still loading credentials, it may send token @@ -1595,6 +1647,7 @@ dummy_account_id, identity_manager_observer()->AccountIdFromRefreshTokenRemovedCallback()); } +#endif TEST_F(IdentityManagerTest, IdentityManagerGetsTokensLoadedEvent) { base::RunLoop run_loop; @@ -2042,7 +2095,8 @@ identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId, kTestEmail); identity_manager()->GetPrimaryAccountManager()->SignIn(kTestEmail); - token_service()->UpdateCredentials(primary_account_id(), "refresh_token"); + UpdateCredentials(primary_account_id(), kTestGaiaId, kTestEmail, + "refresh_token"); EXPECT_EQ(1ul, identity_manager_observer()->BatchChangeRecords().size()); EXPECT_EQ(1ul,
diff --git a/components/signin/public/identity_manager/identity_test_environment.cc b/components/signin/public/identity_manager/identity_test_environment.cc index 3fa0c7e1..37e0c91 100644 --- a/components/signin/public/identity_manager/identity_test_environment.cc +++ b/components/signin/public/identity_manager/identity_test_environment.cc
@@ -35,6 +35,12 @@ #include "google_apis/gaia/oauth2_access_token_consumer.h" #include "services/network/test/test_url_loader_factory.h" +#if defined(OS_CHROMEOS) +#include "chromeos/components/account_manager/account_manager.h" +#include "chromeos/components/account_manager/account_manager_factory.h" +#include "components/signin/internal/identity_manager/test_profile_oauth2_token_service_delegate_chromeos.h" +#endif + #if defined(OS_IOS) #include "components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h" #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h" @@ -54,16 +60,20 @@ ~IdentityManagerDependenciesOwner(); sync_preferences::TestingPrefServiceSyncable* pref_service(); - +#if defined(OS_CHROMEOS) + chromeos::AccountManagerFactory* account_manager_factory(); +#endif TestSigninClient* signin_client(); private: +#if defined(OS_CHROMEOS) + std::unique_ptr<chromeos::AccountManagerFactory> account_manager_factory_; +#endif // Depending on whether a |pref_service| instance is passed in // the constructor, exactly one of these will be non-null. std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> owned_pref_service_; sync_preferences::TestingPrefServiceSyncable* raw_pref_service_ = nullptr; - std::unique_ptr<TestSigninClient> owned_signin_client_; TestSigninClient* raw_signin_client_ = nullptr; @@ -73,7 +83,12 @@ IdentityManagerDependenciesOwner::IdentityManagerDependenciesOwner( sync_preferences::TestingPrefServiceSyncable* pref_service_param, TestSigninClient* signin_client_param) - : owned_pref_service_( + : +#if defined(OS_CHROMEOS) + account_manager_factory_( + std::make_unique<chromeos::AccountManagerFactory>()), +#endif + owned_pref_service_( pref_service_param ? nullptr : std::make_unique< @@ -83,7 +98,8 @@ signin_client_param ? nullptr : std::make_unique<TestSigninClient>(pref_service())), - raw_signin_client_(signin_client_param) {} + raw_signin_client_(signin_client_param) { +} IdentityManagerDependenciesOwner::~IdentityManagerDependenciesOwner() = default; @@ -95,6 +111,14 @@ return raw_pref_service_ ? raw_pref_service_ : owned_pref_service_.get(); } +#if defined(OS_CHROMEOS) +chromeos::AccountManagerFactory* +IdentityManagerDependenciesOwner::account_manager_factory() { + DCHECK(account_manager_factory_); + return account_manager_factory_.get(); +} +#endif + TestSigninClient* IdentityManagerDependenciesOwner::signin_client() { DCHECK(raw_signin_client_ || owned_signin_client_); DCHECK(!(raw_signin_client_ && owned_signin_client_)); @@ -157,14 +181,67 @@ IdentityManager::RegisterProfilePrefs(test_pref_service->registry()); IdentityManager::RegisterLocalStatePrefs(test_pref_service->registry()); +#if defined(OS_CHROMEOS) + chromeos::AccountManager::RegisterPrefs(test_pref_service->registry()); + owned_identity_manager_ = BuildIdentityManagerForTests( + test_signin_client, test_pref_service, base::FilePath(), + dependencies_owner_->account_manager_factory(), account_consistency); +#else owned_identity_manager_ = BuildIdentityManagerForTests(test_signin_client, test_pref_service, base::FilePath(), account_consistency); +#endif // defined(OS_CHROMEOS) Initialize(); } +#if defined(OS_CHROMEOS) +// static +std::unique_ptr<IdentityManager> +IdentityTestEnvironment::BuildIdentityManagerForTests( + SigninClient* signin_client, + PrefService* pref_service, + base::FilePath user_data_dir, + chromeos::AccountManagerFactory* chromeos_account_manager_factory, + AccountConsistencyMethod account_consistency) { + auto account_tracker_service = std::make_unique<AccountTrackerService>(); + account_tracker_service->Initialize(pref_service, user_data_dir); + + IdentityManager::InitParameters init_params; + chromeos::AccountManager* account_manager = + chromeos_account_manager_factory->GetAccountManager( + user_data_dir.value()); + + if (user_data_dir.empty()) { + account_manager->InitializeInEphemeralMode( + signin_client->GetURLLoaderFactory()); + } else { + chromeos::AccountManager::DelayNetworkCallRunner immediate_callback_runner = + base::BindRepeating([](base::OnceClosure closure) -> void { + std::move(closure).Run(); + }); + account_manager->Initialize(user_data_dir, + signin_client->GetURLLoaderFactory(), + immediate_callback_runner, base::DoNothing()); + } + account_manager->SetPrefService(pref_service); + account_manager->SetUrlLoaderFactoryForTests( + signin_client->GetURLLoaderFactory()); + init_params.chromeos_account_manager = account_manager; + + auto token_service = std::make_unique<FakeProfileOAuth2TokenService>( + pref_service, + std::make_unique<TestProfileOAuth2TokenServiceDelegateChromeOS>( + account_tracker_service.get(), account_manager, + /*is_regular_profile=*/true)); + + return FinishBuildIdentityManagerForTests( + std::move(init_params), std::move(account_tracker_service), + std::move(token_service), signin_client, pref_service, user_data_dir, + account_consistency); +} +#else // static std::unique_ptr<IdentityManager> IdentityTestEnvironment::BuildIdentityManagerForTests( @@ -174,10 +251,25 @@ AccountConsistencyMethod account_consistency) { auto account_tracker_service = std::make_unique<AccountTrackerService>(); account_tracker_service->Initialize(pref_service, user_data_dir); - auto token_service = std::make_unique<FakeProfileOAuth2TokenService>(pref_service); + return FinishBuildIdentityManagerForTests( + IdentityManager::InitParameters(), std::move(account_tracker_service), + std::move(token_service), signin_client, pref_service, user_data_dir, + account_consistency); +} +#endif // defined(OS_CHROMEOS) +// static +std::unique_ptr<IdentityManager> +IdentityTestEnvironment::FinishBuildIdentityManagerForTests( + IdentityManager::InitParameters&& init_params, + std::unique_ptr<AccountTrackerService> account_tracker_service, + std::unique_ptr<ProfileOAuth2TokenService> token_service, + SigninClient* signin_client, + PrefService* pref_service, + base::FilePath user_data_dir, + AccountConsistencyMethod account_consistency) { auto account_fetcher_service = std::make_unique<AccountFetcherService>(); account_fetcher_service->Initialize( signin_client, token_service.get(), account_tracker_service.get(), @@ -198,8 +290,6 @@ std::make_unique<GaiaCookieManagerService>(token_service.get(), signin_client); - IdentityManager::InitParameters init_params; - init_params.primary_account_mutator = std::make_unique<PrimaryAccountMutatorImpl>(account_tracker_service.get(), primary_account_manager.get(),
diff --git a/components/signin/public/identity_manager/identity_test_environment.h b/components/signin/public/identity_manager/identity_test_environment.h index c1630c2..900311a 100644 --- a/components/signin/public/identity_manager/identity_test_environment.h +++ b/components/signin/public/identity_manager/identity_test_environment.h
@@ -6,6 +6,8 @@ #define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_IDENTITY_TEST_ENVIRONMENT_H_ #include <memory> +#include <string> +#include <vector> #include "base/callback.h" #include "base/optional.h" @@ -21,6 +23,10 @@ class PrefService; class TestSigninClient; +namespace chromeos { +class AccountManagerFactory; +} + namespace sync_preferences { class TestingPrefServiceSyncable; } @@ -340,6 +346,37 @@ IdentityTestEnvironment(IdentityManager* identity_manager, SigninClient* signin_client); + // Shared constructor initialization logic. + void Initialize(); + + // Create an IdentityManager instance for tests. +#if defined(OS_CHROMEOS) + static std::unique_ptr<IdentityManager> BuildIdentityManagerForTests( + SigninClient* signin_client, + PrefService* pref_service, + base::FilePath user_data_dir, + chromeos::AccountManagerFactory* chromeos_account_manager_factory, + AccountConsistencyMethod account_consistency = + AccountConsistencyMethod::kDisabled); +#else + static std::unique_ptr<IdentityManager> BuildIdentityManagerForTests( + SigninClient* signin_client, + PrefService* pref_service, + base::FilePath user_data_dir, + AccountConsistencyMethod account_consistency = + AccountConsistencyMethod::kDisabled); +#endif + + static std::unique_ptr<IdentityManager> FinishBuildIdentityManagerForTests( + IdentityManager::InitParameters&& init_params, + std::unique_ptr<AccountTrackerService> account_tracker_service, + std::unique_ptr<ProfileOAuth2TokenService> token_service, + SigninClient* signin_client, + PrefService* pref_service, + base::FilePath user_data_dir, + AccountConsistencyMethod account_consistency = + AccountConsistencyMethod::kDisabled); + // IdentityManager::DiagnosticsObserver: void OnAccessTokenRequested(const CoreAccountId& account_id, const std::string& consumer_id, @@ -387,17 +424,6 @@ base::OnceClosure on_access_token_requested_callback_; std::vector<AccessTokenRequestState> requesters_; - // Create an IdentityManager instance for tests. - static std::unique_ptr<IdentityManager> BuildIdentityManagerForTests( - SigninClient* signin_client, - PrefService* pref_service, - base::FilePath user_data_dir, - AccountConsistencyMethod account_consistency = - AccountConsistencyMethod::kDisabled); - - // Shared constructor initialization logic. - void Initialize(); - base::WeakPtrFactory<IdentityTestEnvironment> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(IdentityTestEnvironment);
diff --git a/components/signin/public/identity_manager/identity_test_utils.cc b/components/signin/public/identity_manager/identity_test_utils.cc index 41329ad..f179eea 100644 --- a/components/signin/public/identity_manager/identity_test_utils.cc +++ b/components/signin/public/identity_manager/identity_test_utils.cc
@@ -6,6 +6,7 @@ #include <vector> +#include "base/guid.h" #include "base/run_loop.h" #include "build/build_config.h" #include "components/signin/internal/identity_manager/account_tracker_service.h" @@ -20,6 +21,10 @@ #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_constants.h" +#if defined(OS_CHROMEOS) +#include "chromeos/components/account_manager/account_manager.h" +#endif + #if defined(OS_ANDROID) #include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h" #endif @@ -51,6 +56,9 @@ void UpdateRefreshTokenForAccount( ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker_service, +#if defined(OS_CHROMEOS) + chromeos::AccountManager* account_manager, +#endif IdentityManager* identity_manager, const CoreAccountId& account_id, const std::string& new_token) { @@ -70,7 +78,19 @@ token_updated_observer.SetOnRefreshTokenUpdatedCallback( run_loop.QuitClosure()); +#if defined(OS_CHROMEOS) + const AccountInfo& account_info = + account_tracker_service->GetAccountInfo(account_id); + + DCHECK(account_manager); + account_manager->UpsertAccount( + chromeos::AccountManager::AccountKey{ + account_info.gaia, + chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA}, + account_info.email, new_token); +#else token_service->UpdateCredentials(account_id, new_token); +#endif run_loop.Run(); } @@ -279,9 +299,16 @@ const std::string& token_value) { UpdateRefreshTokenForAccount( identity_manager->GetTokenService(), - identity_manager->GetAccountTrackerService(), identity_manager, - account_id, + identity_manager->GetAccountTrackerService(), +#if defined(OS_CHROMEOS) + identity_manager->GetChromeOSAccountManager(), +#endif + identity_manager, account_id, + // TODO(crbug.com/1115075): set the same token_value on all platforms. token_value.empty() ? "refresh_token_for_" + account_id.ToString() +#if defined(OS_CHROMEOS) + + "_" + base::GenerateGUID() +#endif : token_value); } @@ -290,6 +317,9 @@ UpdateRefreshTokenForAccount(identity_manager->GetTokenService(), identity_manager->GetAccountTrackerService(), +#if defined(OS_CHROMEOS) + identity_manager->GetChromeOSAccountManager(), +#endif identity_manager, account_id, GaiaConstants::kInvalidRefreshToken); } @@ -304,7 +334,17 @@ token_updated_observer.SetOnRefreshTokenRemovedCallback( run_loop.QuitClosure()); +#if defined(OS_CHROMEOS) + const AccountInfo& account_info = + identity_manager->GetAccountTrackerService()->GetAccountInfo(account_id); + + identity_manager->GetChromeOSAccountManager()->RemoveAccount( + chromeos::AccountManager::AccountKey{ + account_info.gaia, + chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA}); +#else identity_manager->GetTokenService()->RevokeCredentials(account_id); +#endif run_loop.Run(); }
diff --git a/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc b/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc index d76c826..bc188f3 100644 --- a/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc +++ b/components/subresource_filter/tools/ruleset_converter/rule_stream_unittest.cc
@@ -46,7 +46,7 @@ std::vector<std::string> GetSomeChromeUnfriendlyRules() { return std::vector<std::string>{ "/a[0-9].com/$image", - "a.com$image,popup" + "a.com$image,popup", "a.com$popup", "a.com$~image", "a.com$~popup",
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index 813f086..5d9b845 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -1567,12 +1567,7 @@ } // Try to start up again (in transport-only mode). - // TODO(crbug.com/1035874): There's no real need to delay the startup here, - // i.e. it should be fine to set force_immediate to true. However currently - // some tests depend on the startup *not* happening immediately (because - // they want to check that Sync (the feature) got disabled, which is hard to - // do if the engine starts up again immediately). - startup_controller_->TryStart(/*force_immediate=*/false); + startup_controller_->TryStart(/*force_immediate=*/true); } }
diff --git a/components/sync/model_impl/client_tag_based_remote_update_handler.cc b/components/sync/model_impl/client_tag_based_remote_update_handler.cc index c4790a0..60c2934 100644 --- a/components/sync/model_impl/client_tag_based_remote_update_handler.cc +++ b/components/sync/model_impl/client_tag_based_remote_update_handler.cc
@@ -105,17 +105,18 @@ DCHECK(storage_key_to_clear.empty()); + if (got_new_encryption_requirements) { + already_updated.insert(entity->storage_key()); + } + if (entity->CanClearMetadata()) { metadata_changes->ClearMetadata(entity->storage_key()); + // The line below frees |entity| and it shouldn't be used afterwards. entity_tracker_->RemoveEntityForStorageKey(entity->storage_key()); } else { metadata_changes->UpdateMetadata(entity->storage_key(), entity->metadata()); } - - if (got_new_encryption_requirements) { - already_updated.insert(entity->storage_key()); - } } if (got_new_encryption_requirements) {
diff --git a/components/sync/model_impl/client_tag_based_remote_update_handler_unittest.cc b/components/sync/model_impl/client_tag_based_remote_update_handler_unittest.cc index be4fbc85..6c6b0a1 100644 --- a/components/sync/model_impl/client_tag_based_remote_update_handler_unittest.cc +++ b/components/sync/model_impl/client_tag_based_remote_update_handler_unittest.cc
@@ -14,11 +14,9 @@ #include "components/sync/test/engine/mock_model_type_worker.h" #include "testing/gtest/include/gtest/gtest.h" -namespace { +namespace syncer { -using syncer::FakeModelTypeSyncBridge; -using syncer::UpdateResponseData; -using syncer::UpdateResponseDataList; +namespace { const char kKey1[] = "key1"; const char kKey2[] = "key2"; @@ -34,42 +32,46 @@ public: ClientTagBasedRemoteUpdateHandlerTest() : processor_entity_tracker_(GenerateModelTypeState(), - syncer::EntityMetadataMap()), + EntityMetadataMap()), model_type_sync_bridge_(change_processor_.CreateForwardingProcessor()), - remote_update_handler_(syncer::PREFERENCES, + remote_update_handler_(PREFERENCES, &model_type_sync_bridge_, &processor_entity_tracker_), worker_(GenerateModelTypeState(), &model_type_processor_) {} ~ClientTagBasedRemoteUpdateHandlerTest() override = default; - void ProcessSingleUpdate(UpdateResponseData update) { + void ProcessSingleUpdate(const sync_pb::ModelTypeState& model_type_state, + UpdateResponseData update) { UpdateResponseDataList updates; updates.push_back(std::move(update)); - remote_update_handler_.ProcessIncrementalUpdate(GenerateModelTypeState(), + remote_update_handler_.ProcessIncrementalUpdate(model_type_state, std::move(updates)); } - syncer::UpdateResponseData GenerateUpdate(const std::string& key, - const std::string& value) { - const syncer::ClientTagHash client_tag_hash = + void ProcessSingleUpdate(UpdateResponseData update) { + ProcessSingleUpdate(GenerateModelTypeState(), std::move(update)); + } + + UpdateResponseData GenerateUpdate(const std::string& key, + const std::string& value) { + const ClientTagHash client_tag_hash = FakeModelTypeSyncBridge::TagHashFromKey(key); return GenerateUpdate(client_tag_hash, key, value); } - syncer::UpdateResponseData GenerateUpdate( - const syncer::ClientTagHash& client_tag_hash, - const std::string& key, - const std::string& value) { + UpdateResponseData GenerateUpdate(const ClientTagHash& client_tag_hash, + const std::string& key, + const std::string& value) { return worker()->GenerateUpdateData( client_tag_hash, FakeModelTypeSyncBridge::GenerateSpecifics(key, value)); } - syncer::UpdateResponseData GenerateUpdate(const std::string& key, - const std::string& value, - int64_t version_offset) { - const syncer::ClientTagHash client_tag_hash = + UpdateResponseData GenerateUpdate(const std::string& key, + const std::string& value, + int64_t version_offset) { + const ClientTagHash client_tag_hash = FakeModelTypeSyncBridge::TagHashFromKey(key); const sync_pb::ModelTypeState model_type_state = GenerateModelTypeState(); const sync_pb::EntitySpecifics specifics = @@ -84,25 +86,25 @@ } FakeModelTypeSyncBridge* bridge() { return &model_type_sync_bridge_; } - syncer::ClientTagBasedRemoteUpdateHandler* remote_update_handler() { + ClientTagBasedRemoteUpdateHandler* remote_update_handler() { return &remote_update_handler_; } FakeModelTypeSyncBridge::Store* db() { return bridge()->mutable_db(); } - syncer::ProcessorEntityTracker* entity_tracker() { + ProcessorEntityTracker* entity_tracker() { return &processor_entity_tracker_; } - testing::NiceMock<syncer::MockModelTypeChangeProcessor>* change_processor() { + testing::NiceMock<MockModelTypeChangeProcessor>* change_processor() { return &change_processor_; } - syncer::MockModelTypeWorker* worker() { return &worker_; } + MockModelTypeWorker* worker() { return &worker_; } private: - testing::NiceMock<syncer::MockModelTypeChangeProcessor> change_processor_; - syncer::ProcessorEntityTracker processor_entity_tracker_; + testing::NiceMock<MockModelTypeChangeProcessor> change_processor_; + ProcessorEntityTracker processor_entity_tracker_; FakeModelTypeSyncBridge model_type_sync_bridge_; - syncer::ClientTagBasedRemoteUpdateHandler remote_update_handler_; - testing::NiceMock<syncer::MockModelTypeProcessor> model_type_processor_; - syncer::MockModelTypeWorker worker_; + ClientTagBasedRemoteUpdateHandler remote_update_handler_; + testing::NiceMock<MockModelTypeProcessor> model_type_processor_; + MockModelTypeWorker worker_; }; // Thoroughly tests the data generated by a server item creation. @@ -111,7 +113,7 @@ EXPECT_EQ(1u, db()->data_count()); EXPECT_EQ(1u, db()->metadata_count()); - const syncer::EntityData& data = db()->GetData(kKey1); + const EntityData& data = db()->GetData(kKey1); EXPECT_FALSE(data.id.empty()); EXPECT_EQ(kKey1, data.specifics.preference().name()); EXPECT_EQ(kValue1, data.specifics.preference().value()); @@ -136,7 +138,7 @@ ShouldIgnoreRemoteUpdatesForRootNodes) { ASSERT_EQ(0U, ProcessorEntityCount()); ProcessSingleUpdate( - worker()->GenerateTypeRootUpdateData(syncer::ModelType::SESSIONS)); + worker()->GenerateTypeRootUpdateData(ModelType::SESSIONS)); // Root node update should be filtered out. EXPECT_EQ(0U, db()->data_count()); EXPECT_EQ(0U, db()->metadata_count()); @@ -222,4 +224,28 @@ EXPECT_FALSE(entity_tracker()->HasLocalChanges()); } +// Test for the case from crbug.com/1046309. Tests that there is no redundant +// deletion when processing remote deletion with different encryption key. +TEST_F(ClientTagBasedRemoteUpdateHandlerTest, + ShouldNotIssueDeletionUponRemoteDeletion) { + const std::string kTestEncryptionKeyName = "TestEncryptionKey"; + const std::string kDifferentEncryptionKeyName = "DifferentEncryptionKey"; + const ClientTagHash kClientTagHash = + FakeModelTypeSyncBridge::TagHashFromKey(kKey1); + + sync_pb::ModelTypeState model_type_state = GenerateModelTypeState(); + model_type_state.set_encryption_key_name(kTestEncryptionKeyName); + + ProcessSingleUpdate(GenerateUpdate(kClientTagHash, kKey1, kValue1)); + + // Generate a remote deletion with a different encryption key. + model_type_state.set_encryption_key_name(kDifferentEncryptionKeyName); + ProcessSingleUpdate(model_type_state, + worker()->GenerateTombstoneUpdateData(kClientTagHash)); + + EXPECT_EQ(0u, ProcessorEntityCount()); +} + } // namespace + +} // namespace syncer
diff --git a/components/viz/service/display/output_surface.h b/components/viz/service/display/output_surface.h index a680e373..af8563c3 100644 --- a/components/viz/service/display/output_surface.h +++ b/components/viz/service/display/output_surface.h
@@ -51,6 +51,12 @@ kOpenGL = 1, kVulkan = 2, }; + + enum class OrientationMode { + kLogic, // The orientation same to logical screen orientation as seen by + // the user. + kHardware, // The orientation same to the hardware. + }; struct Capabilities { Capabilities(); Capabilities(const Capabilities& capabilities); @@ -75,12 +81,8 @@ bool supports_commit_overlay_planes = false; // Whether this OutputSurface supports gpu vsync callbacks. bool supports_gpu_vsync = false; - // Whether this OutputSurface supports pre transform. If it is supported, - // the chrome will set the output surface size in hardware natural - // orientation, and will render transformed content on back buffers based - // on the current system transform. So the OS presentation engine can - // present buffers onto the screen directly. - bool supports_pre_transform = false; + // OutputSurface's orientation mode. + OrientationMode orientation_mode = OrientationMode::kLogic; // Whether this OutputSurface supports direct composition layers. bool supports_dc_layers = false; // Whether this OutputSurface should skip DrawAndSwap(). This is true for
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 179388ea..5a22a89d 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -2218,14 +2218,31 @@ NOTREACHED(); return; } + // Only Wayland uses this code path. + DCHECK(output_surface_->capabilities().supports_surfaceless); + auto& locks = pending_overlay_locks_.back(); + std::vector<gpu::SyncToken> sync_tokens; + for (auto& overlay : current_frame()->overlay_list) { + // Resources will be unlocked after the next SwapBuffers() is completed. + locks.emplace_back(resource_provider_, overlay.resource_id); + auto& lock = locks.back(); - NOTIMPLEMENTED_LOG_ONCE(); -#else + // Sync tokens ensure the texture to be overlaid is available before + // scheduling it for display. + if (lock.sync_token().HasData()) + sync_tokens.push_back(lock.sync_token()); + + overlay.mailbox = lock.mailbox(); + DCHECK(!overlay.mailbox.IsZero()); + } + skia_output_surface_->ScheduleOverlays( + std::move(current_frame()->overlay_list), std::move(sync_tokens)); +#else // defined(OS_ANDROID) // For platforms that don't support overlays, the // current_frame()->overlay_list should be empty, and this code should not be // reached. NOTREACHED(); -#endif +#endif // defined(OS_ANDROID) } sk_sp<SkColorFilter> SkiaRenderer::GetColorSpaceConversionFilter(
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc index 1d4f6ae..d0e262d 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.cc +++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -347,7 +347,7 @@ std::vector<OutputPresenter::OverlayData> OutputPresenterGL::ScheduleOverlays( SkiaOutputSurface::OverlayList overlays) { std::vector<OverlayData> pending_overlays; -#if defined(OS_ANDROID) || defined(OS_APPLE) || defined(OS_CHROMEOS) +#if defined(OS_ANDROID) || defined(OS_APPLE) || defined(USE_OZONE) // Note while reading through this for-loop that |overlay| has different // types on different platforms. On Android and Ozone it is an // OverlayCandidate, on Windows it is a DCLayerOverlay, and on macOS it is @@ -380,7 +380,7 @@ std::move(shared_image_access)); } -#if defined(OS_ANDROID) || defined(OS_CHROMEOS) +#if defined(OS_ANDROID) || defined(USE_OZONE) if (gl_image) { DCHECK(!overlay.gpu_fence_id); gl_surface_->ScheduleOverlayPlane( @@ -400,7 +400,7 @@ overlay.shared_state->opacity, overlay.filter)); #endif } -#endif // defined(OS_ANDROID) || defined(OS_APPLE) || defined(OS_CHROMEOS) +#endif // defined(OS_ANDROID) || defined(OS_APPLE) || defined(USE_OZONE) return pending_overlays; }
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc index ef7546353..d5eea0f4 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -9,6 +9,8 @@ #include <vector> #include "base/command_line.h" +#include "base/feature_list.h" +#include "build/build_config.h" #include "components/viz/common/switches.h" #include "components/viz/service/display_embedder/skia_output_surface_dependency.h" #include "gpu/command_buffer/common/capabilities.h" @@ -34,14 +36,19 @@ capabilities_.preserve_buffer_content = true; capabilities_.only_invalidates_damage_rect = false; capabilities_.number_of_buffers = 3; - -// TODO(crbug.com/1110443): This ifdef was added to unblock SkiaRenderer GL on -// Chrome OS, but theoretically, this should be true across all buffer queue -// platforms. Remove this ifdef once we verify that supports_pre_transform -// does not cause any regressions on Android. -#if defined(OS_CHROMEOS) - capabilities_.supports_pre_transform = true; -#endif // defined(OS_CHROMEOS) +#if defined(OS_ANDROID) + capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware; + // With vulkan and android surface control, if the chrome is launched in + // landscape mode, the chrome is always blank until chrome window is rotated + // once. Workaround this problem by using logic rotation mode. + // TODO(https://crbug.com/1115065): use hardware orientation mode for vulkan, + if (dependency_->GetSharedContextState()->GrContextIsVulkan() && + base::FeatureList::GetFieldTrial(features::kVulkan)) { + capabilities_.orientation_mode = OutputSurface::OrientationMode::kLogic; + } +#else + capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware; +#endif // Force the number of max pending frames to one when the switch // "double-buffer-compositing" is passed.
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc index 657d564..57154ac 100644 --- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -291,7 +291,7 @@ capabilities_.preserve_buffer_content = true; capabilities_.output_surface_origin = gfx::SurfaceOrigin::kTopLeft; capabilities_.supports_post_sub_buffer = true; - capabilities_.supports_pre_transform = true; + capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware; // We don't know the number of buffers until the VulkanSwapChain is // initialized, so set it to 0. Since |damage_area_from_skia_output_device| is // assigned to true, so |number_of_buffers| will not be used for tracking
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index ecbeb3b3..11c1162 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -230,7 +230,7 @@ auto task = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::Reshape, base::Unretained(impl_on_gpu_.get()), size, device_scale_factor, color_space, format, - use_stencil, pre_transform_); + use_stencil, GetDisplayTransform()); ScheduleGpuTask(std::move(task), {}); color_space_ = color_space; @@ -259,12 +259,18 @@ void SkiaOutputSurfaceImpl::SetDisplayTransformHint( gfx::OverlayTransform transform) { - if (capabilities_.supports_pre_transform) - pre_transform_ = transform; + display_transform_ = transform; } gfx::OverlayTransform SkiaOutputSurfaceImpl::GetDisplayTransform() { - return pre_transform_; + switch (capabilities_.orientation_mode) { + case OutputSurface::OrientationMode::kLogic: + return gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE; + case OutputSurface::OrientationMode::kHardware: + return display_transform_; + default: + NOTREACHED(); + } } SkCanvas* SkiaOutputSurfaceImpl::BeginPaintCurrentFrame() {
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index 2d96b1d2..919a954 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -254,7 +254,7 @@ // The display transform relative to the hardware natural orientation, // applied to the frame content. The transform can be rotations in 90 degree // increments or flips. - gfx::OverlayTransform pre_transform_ = gfx::OVERLAY_TRANSFORM_NONE; + gfx::OverlayTransform display_transform_ = gfx::OVERLAY_TRANSFORM_NONE; // |gpu_task_scheduler_| holds a gpu::SingleTaskSequence, and helps schedule // tasks on GPU as a single sequence. It is shared with OverlayProcessor so
diff --git a/content/browser/find_request_manager_browsertest.cc b/content/browser/find_request_manager_browsertest.cc index 623a7dd..0a281e7 100644 --- a/content/browser/find_request_manager_browsertest.cc +++ b/content/browser/find_request_manager_browsertest.cc
@@ -863,7 +863,8 @@ // Test basic find-in-page functionality after going back and forth to the same // page. In particular, find-in-page should continue to work after going back to // a page using the back-forward cache. -IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, HistoryBackAndForth) { +// Flaky everywhere: https://crbug.com/1115102 +IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, DISABLED_HistoryBackAndForth) { GURL url_a = embedded_test_server()->GetURL("a.com", "/find_in_page.html"); GURL url_b = embedded_test_server()->GetURL("b.com", "/find_in_page.html");
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index f346d5a..2ca0e52 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -193,24 +193,8 @@ // Check that the entry has been already populated with required information. DCHECK(frame_entry->page_state().IsValid()); - // For about:blank and data: URLs create a SiteInstance based on the initiator - // origin. See also https://crbug.com/1026474. - if (frame_entry->url().IsAboutBlank() || - frame_entry->url().SchemeIs(url::kDataScheme)) { - // TODO(lukasza): We should consider also creating a SiteInstance if there - // is no initiator origin. Doing this would allow us to - // 1) remove special-casing of data URLs in - // SiteInstanceImpl::GetSiteForURLInternal where sometimes we use the - // whole data URL as a site URL to avoid session restore trouble. - // 2) start asserting that an initialized FrameNavigationEntry should always - // have a non-null SiteInstance. - if (frame_entry->initiator_origin().has_value()) { - url::SchemeHostPort initiator_tuple = - frame_entry->initiator_origin()->GetTupleOrPrecursorTupleIfOpaque(); - frame_entry->set_site_instance(SiteInstanceImpl::CreateForURL( - browser_context, initiator_tuple.GetURL())); - } - } + // TODO(lukasza): Finish reverting r719801 and remove this empty function and + // its callers. } void RecursivelyInitRestoredTreeNode(BrowserContext* browser_context,
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index e215b975..1027ee1 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -1161,13 +1161,24 @@ dest_site_instance_ = frame_entry->site_instance(); bindings_ = frame_entry->bindings(); - // Handle history subframe navigations that require a source_site_instance - // but do not have one set yet. This can happen when navigation entries - // are restored from PageState objects. The serialized state does not - // contain a SiteInstance so we need to use the initiator_origin to - // get an appropriate source SiteInstance. - if (common_params_->is_history_navigation_in_new_child_frame) + // Handle history subframe and restore navigations that require a + // |source_site_instance| but do not have one set yet. This can happen + // when navigation entries are restored from PageState objects, because + // the serialized state does not contain a SiteInstance so we need to use + // the |initiator_origin| to get an appropriate source SiteInstance. + // + // History subframe and restore navigations are the only cases where + // SetSourceSiteInstanceToInitiatorIfNeeded needs to be called (i.e. the + // only cases that may have no |source_site_instance_| even though + // RequiresInitiatorBasedSourceSiteInstance returns true). We verify that + // other cases which require a |source_site_instance_| indeed have one + // with a DCHECK below. + if (common_params_->is_history_navigation_in_new_child_frame || + common_params_->navigation_type == mojom::NavigationType::RESTORE || + common_params_->navigation_type == + mojom::NavigationType::RESTORE_WITH_POST) { SetSourceSiteInstanceToInitiatorIfNeeded(); + } } isolation_info_ = entry->isolation_info(); is_view_source_ = entry->IsViewSourceMode(); @@ -1179,7 +1190,8 @@ // TODO(acolwell): Move this below so it can be enforced on all paths. // This requires auditing same-document and other navigations that don't // have |from_begin_navigation_| or |entry| set. - DCHECK(!RequiresSourceSiteInstance() || source_site_instance_); + DCHECK(!RequiresInitiatorBasedSourceSiteInstance() || + source_site_instance_); } // Let the NTP override the navigation params and pretend that this is a @@ -4775,22 +4787,34 @@ return is_navigation_started_; } -bool NavigationRequest::RequiresSourceSiteInstance() const { +bool NavigationRequest::RequiresInitiatorBasedSourceSiteInstance() const { const bool is_data_or_about = common_params_->url.SchemeIs(url::kDataScheme) || common_params_->url.IsAboutBlank(); + const bool has_valid_initiator = common_params_->initiator_origin && common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque() .IsValid(); - return is_data_or_about && has_valid_initiator && !dest_site_instance_; + + // If renderer-initiated navigation of a main frame |has_valid_initiator| but + // has no |initiator_routing_id_|, then it means that the opener was + // suppressed (and therefore that a source SiteInstance is not needed). Note + // that |initiator_routing_id| is always MSG_ROUTING_NONE during + // browser-initiated navigations (including session restore or history + // navigations). + const bool was_opener_suppressed = + has_valid_initiator && frame_tree_node()->IsMainFrame() && + initiator_routing_id_.frame_routing_id == MSG_ROUTING_NONE && + !browser_initiated_; + + return is_data_or_about && has_valid_initiator && !was_opener_suppressed && + !dest_site_instance_; } void NavigationRequest::SetSourceSiteInstanceToInitiatorIfNeeded() { - if (source_site_instance_ || !RequiresSourceSiteInstance() || - !common_params_->initiator_origin.has_value()) { + if (source_site_instance_ || !RequiresInitiatorBasedSourceSiteInstance()) return; - } const auto tuple = common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque();
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index c0691276..1748599 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -1020,16 +1020,17 @@ } // Returns true if the contents of |common_params_| requires - // |source_site_instance_| to be set. This is used to ensure that data: - // URLs with valid initiator origins always have |source_site_instance_| set - // so that site isolation enforcements work properly. - bool RequiresSourceSiteInstance() const; + // |source_site_instance_| to be set. This is used to ensure that data: and + // about:blank URLs with valid initiator origins always have + // |source_site_instance_| set so that site isolation enforcements work + // properly. + bool RequiresInitiatorBasedSourceSiteInstance() const; // Sets |source_site_instance_| to a SiteInstance that is derived from // |common_params_->initiator_origin| and related to the |frame_tree_node_|'s // current SiteInstance. |source_site_instance_| is only set if it doesn't - // already have a value, |common_params_->initiator_origin| has a valid - // origin, and RequiresSourceSiteInstance() return true. + // already have a value and RequiresInitiatorBasedSourceSiteInstance() returns + // true. void SetSourceSiteInstanceToInitiatorIfNeeded(); // See RestartBackForwardCachedNavigation.
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index dd3c9f1..5acde63 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -1690,6 +1690,15 @@ } } + // Check if we should use |source_instance|, such as for about:blank and data: + // URLs. Preferring |source_instance| over a site-less |current_instance| is + // important in session restore scenarios which should commit in the + // SiteInstance based on FrameNavigationEntry's initiator_origin. + if (CanUseSourceSiteInstance(dest_url, source_instance, was_server_redirect, + is_failure)) { + return SiteInstanceDescriptor(source_instance); + } + // If we haven't used our SiteInstance yet, then we can use it for this // entry. We won't commit the SiteInstance to this site until the response // is received (in OnResponseStarted), unless the navigation entry was @@ -1748,13 +1757,6 @@ return SiteInstanceDescriptor(current_instance_impl); } - // Check if we should use |source_instance|, such as for about:blank and data: - // URLs. - if (CanUseSourceSiteInstance(dest_url, source_instance, was_server_redirect, - is_failure)) { - return SiteInstanceDescriptor(source_instance); - } - // Use the current SiteInstance for same site navigations. if (IsCurrentlySameSite(render_frame_host_.get(), dest_url)) return SiteInstanceDescriptor(render_frame_host_->GetSiteInstance());
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc index 1e7731b5..7593005 100644 --- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -5536,10 +5536,9 @@ // Test to ensure that the error page navigation does not change // BrowsingInstances when window.open is present. -// TODO(crbug.com/1110429): Disabled due to flakiness. IN_PROC_BROWSER_TEST_P( ProactivelySwapBrowsingInstancesCrossSiteSwapProcessTest, - DISABLED_ErrorPageNavigationWithWindowOpenDoesNotChangeBrowsingInstance) { + ErrorPageNavigationWithWindowOpenDoesNotChangeBrowsingInstance) { StartEmbeddedServer(); GURL url(embedded_test_server()->GetURL("/title1.html")); GURL error_url(embedded_test_server()->GetURL("/empty.html"));
diff --git a/content/browser/renderer_host/input/synthetic_input_browsertest.cc b/content/browser/renderer_host/input/synthetic_input_browsertest.cc index cb4a2aa..f2c3651 100644 --- a/content/browser/renderer_host/input/synthetic_input_browsertest.cc +++ b/content/browser/renderer_host/input/synthetic_input_browsertest.cc
@@ -158,15 +158,12 @@ "document.scrollingElement.scrollTop")); } -#if defined(OS_ANDROID) -// http://crbug.com/1103731. Flaky on Android bots. -#define MAYBE_SlowSmoothScrollWheel DISABLED_SlowSmoothScrollWheel -#else -#define MAYBE_SlowSmoothScrollWheel SlowSmoothScrollWheel -#endif // This test ensures that slow synthetic wheel scrolling does not lose precision // over time. -IN_PROC_BROWSER_TEST_F(SyntheticInputTest, MAYBE_SlowSmoothScrollWheel) { +// https://crbug.com/1103731. Flaky on Android bots. +// https://crbug.com/1086334. Flaky on all desktop bots, but maybe for a +// different reason. +IN_PROC_BROWSER_TEST_F(SyntheticInputTest, DISABLED_SlowSmoothScrollWheel) { LoadURL(R"HTML( data:text/html;charset=utf-8, <!DOCTYPE html>
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index cc7630ec..8c16f55 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -13615,8 +13615,10 @@ base::test::ScopedFeatureList feature_list_; }; -IN_PROC_BROWSER_TEST_P(SitePerProcessBrowserTestWithoutSadFrameTabReload, - ChildFrameCrashMetrics_ScrolledIntoViewAfterTabIsShown) { +// Flaky everywhere: https://crbug.com/1115096 +IN_PROC_BROWSER_TEST_P( + SitePerProcessBrowserTestWithoutSadFrameTabReload, + DISABLED_ChildFrameCrashMetrics_ScrolledIntoViewAfterTabIsShown) { // Start on a page that has a single iframe, which is positioned out of // view, and navigate that iframe cross-site. GURL main_url(
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 698180f..cf4071d1 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -5914,15 +5914,11 @@ // a popup menu in the correct position, even if the top-level page repositions // its out-of-process iframe. This verifies that screen positioning information // is propagating down the frame tree correctly. -#if defined(OS_ANDROID) // On Android the reported menu coordinates are relative to the OOPIF, and its // screen position is computed later, so this test isn't relevant. -#define MAYBE_NestedPopupMenuTest DISABLED_NestedPopupMenuTest -#else -#define MAYBE_NestedPopupMenuTest NestedPopupMenuTest -#endif +// Flaky on all other platforms: https://crbug.com/1074248 IN_PROC_BROWSER_TEST_F(SitePerProcessHitTestBrowserTest, - MAYBE_NestedPopupMenuTest) { + DISABLED_NestedPopupMenuTest) { GURL main_url(embedded_test_server()->GetURL( "/cross_site_iframe_factory.html?a(b(c))")); EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc index db270a1..c7aa618 100644 --- a/content/browser/storage_partition_impl_map.cc +++ b/content/browser/storage_partition_impl_map.cc
@@ -451,6 +451,14 @@ in_memory ? base::FilePath() : partition->GetPath().Append(kAppCacheDirname), browser_context_, browser_context_->GetSpecialStoragePolicy()); + } else if (!in_memory) { + // If AppCache is not enabled, clean up any on disk storage. This is the + // path that will execute once AppCache has been fully removed from Chrome. + base::ThreadPool::PostTask( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce( + [](const base::FilePath& dir) { base::DeletePathRecursively(dir); }, + partition->GetPath().Append(kAppCacheDirname))); } // Check first to avoid memory leak in unittests.
diff --git a/content/browser/storage_partition_impl_map_unittest.cc b/content/browser/storage_partition_impl_map_unittest.cc index f7db83b9..cbb4b2c 100644 --- a/content/browser/storage_partition_impl_map_unittest.cc +++ b/content/browser/storage_partition_impl_map_unittest.cc
@@ -9,11 +9,14 @@ #include "base/files/file_util.h" #include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/content_constants.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" namespace content { @@ -46,4 +49,48 @@ EXPECT_FALSE(base::PathExists(inactive_path)); } +TEST(StoragePartitionImplMapTest, AppCacheCleanup) { + const auto kOnDiskConfig = content::StoragePartitionConfig::Create( + "foo", /*partition_name=*/"", /*in_memory=*/false); + + base::test::ScopedFeatureList f; + f.InitAndDisableFeature(blink::features::kAppCache); + BrowserTaskEnvironment task_environment; + TestBrowserContext browser_context; + base::FilePath appcache_path; + + { + base::RunLoop run_loop; + // Creating the partition in the map also does the deletion, so + // create it once, so we can find out what path the partition + // with this name is. + StoragePartitionImplMap map(&browser_context); + + auto* partition = map.Get(kOnDiskConfig, true); + appcache_path = partition->GetPath().Append(kAppCacheDirname); + + base::ThreadPool::PostTask(FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + } + + // Create an AppCache directory that would have existed. + EXPECT_FALSE(base::PathExists(appcache_path)); + EXPECT_TRUE(base::CreateDirectory(appcache_path)); + + { + base::RunLoop run_loop; + StoragePartitionImplMap map(&browser_context); + auto* partition = map.Get(kOnDiskConfig, true); + + ASSERT_EQ(appcache_path, partition->GetPath().Append(kAppCacheDirname)); + + base::ThreadPool::PostTask(FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + + // Verify that creating this partition deletes any AppCache directory it may + // have had. + EXPECT_FALSE(base::PathExists(appcache_path)); + } +} + } // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index b56ff2c..7ad9729 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3412,7 +3412,10 @@ std::make_unique<NavigationController::LoadURLParams>( params.target_url); load_params->initiator_origin = opener->GetLastCommittedOrigin(); - load_params->source_site_instance = source_site_instance; + // Avoiding setting |load_params->source_site_instance| when + // |opener_suppressed| is true, because in that case we do not want to use + // the old SiteInstance and/or BrowsingInstance. See also the test here: + // NewPopupCOOP_SameOriginPolicyAndCrossOriginIframeSetsNoopener. load_params->referrer = params.referrer.To<Referrer>(); load_params->transition_type = ui::PAGE_TRANSITION_LINK; load_params->is_renderer_initiated = true;
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 8505c8c..3d954b3 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -529,11 +529,9 @@ visual_properties.new_size = gfx::Size(100, 100); visual_properties.compositor_viewport_pixel_rect = gfx::Rect(200, 200); visual_properties.visible_viewport_size = visual_properties.new_size; - visual_properties.auto_resize_enabled = main_widget()->auto_resize_mode(); - visual_properties.min_size_for_auto_resize = - main_widget()->min_size_for_auto_resize(); - visual_properties.max_size_for_auto_resize = - main_widget()->max_size_for_auto_resize(); + visual_properties.auto_resize_enabled = view()->AutoResizeMode(); + visual_properties.min_size_for_auto_resize = min_size_for_autoresize_; + visual_properties.max_size_for_auto_resize = max_size_for_autoresize_; visual_properties.local_surface_id_allocation = viz::LocalSurfaceIdAllocation( viz::LocalSurfaceId(1, 1, base::UnguessableToken::Create()), @@ -566,6 +564,17 @@ cc::LayerTreeHost* host = main_widget()->layer_tree_host(); EXPECT_EQ(compositor_dsf, host->device_scale_factor()); } + + void EnableAutoResize(const gfx::Size& min_size, const gfx::Size& max_size) { + min_size_for_autoresize_ = min_size; + max_size_for_autoresize_ = max_size; + blink::WebView* webview = view()->GetWebView(); + webview->EnableAutoResizeForTesting(min_size, max_size); + } + + private: + gfx::Size min_size_for_autoresize_; + gfx::Size max_size_for_autoresize_; }; // This test class forces UseZoomForDSF to be on for all platforms. @@ -3262,8 +3271,7 @@ } // namespace TEST_F(RenderViewImplEnableZoomForDSFTest, AutoResizeWithZoomForDSF) { - main_widget()->EnableAutoResizeForTesting(gfx::Size(5, 5), - gfx::Size(1000, 1000)); + EnableAutoResize(gfx::Size(5, 5), gfx::Size(1000, 1000)); LoadHTML(kAutoResizeTestPage); gfx::Size size_at_1x = main_widget()->size(); ASSERT_FALSE(size_at_1x.IsEmpty()); @@ -3275,8 +3283,7 @@ } TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithoutZoomForDSF) { - main_widget()->EnableAutoResizeForTesting(gfx::Size(5, 5), - gfx::Size(1000, 1000)); + EnableAutoResize(gfx::Size(5, 5), gfx::Size(1000, 1000)); LoadHTML(kAutoResizeTestPage); gfx::Size size_at_1x = main_widget()->size(); ASSERT_FALSE(size_at_1x.IsEmpty());
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index c468b81..c0f9e9b6 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1028,13 +1028,8 @@ return false; } -void RenderViewImpl::ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size, - const gfx::Size& max_size) { - GetWebView()->EnableAutoResizeMode(min_size, max_size); -} - -void RenderViewImpl::DisableAutoResizeForWidget() { - GetWebView()->DisableAutoResizeMode(); +bool RenderViewImpl::AutoResizeMode() { + return GetWebView()->AutoResizeMode(); } void RenderViewImpl::ScrollFocusedNodeIntoViewForWidget() {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 780c4bf..7467f97 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -346,9 +346,7 @@ void SetActiveForWidget(bool active) override; bool SupportsMultipleWindowsForWidget() override; bool ShouldAckSyntheticInputImmediately() override; - void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size, - const gfx::Size& max_size) override; - void DisableAutoResizeForWidget() override; + bool AutoResizeMode() override; void ScrollFocusedNodeIntoViewForWidget() override; void DidReceiveSetFocusEventForWidget() override; void DidCommitCompositorFrameForWidget() override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 47ceac9..21f68f96 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -472,15 +472,10 @@ web_view->CancelPagePopup(); } - SetAutoResizeMode(visual_properties.auto_resize_enabled, - visual_properties.min_size_for_auto_resize, - visual_properties.max_size_for_auto_resize, - visual_properties.screen_info.device_scale_factor); - browser_controls_params_ = visual_properties.browser_controls_params; } - if (!auto_resize_mode_) { + if (!AutoResizeMode()) { if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_) { is_fullscreen_granted_ = visual_properties.is_fullscreen_granted; if (is_fullscreen_granted_) @@ -493,7 +488,7 @@ gfx::Size old_visible_viewport_size = visible_viewport_size_; if (device_emulator_) { - DCHECK(!auto_resize_mode_); + DCHECK(!AutoResizeMode()); DCHECK(!synchronous_resize_mode_for_testing_); // TODO(danakj): Have RenderWidget grab emulated values from the emulator @@ -541,7 +536,7 @@ if (!ignore_resize_ipc) { gfx::Rect new_compositor_viewport_pixel_rect = visual_properties.compositor_viewport_pixel_rect; - if (auto_resize_mode_) { + if (AutoResizeMode()) { new_compositor_viewport_pixel_rect = gfx::Rect(gfx::ScaleToCeiledSize( size_, visual_properties.screen_info.device_scale_factor)); } @@ -570,9 +565,8 @@ // hierarchy via the VisualProperties waterfall. visible_viewport_size_ = visual_properties.visible_viewport_size; - if (!auto_resize_mode_) { - size_ = visual_properties.new_size; - ResizeWebWidget(); + if (!AutoResizeMode()) { + SetSize(visual_properties.new_size); } } } @@ -672,31 +666,6 @@ return 1; } -void RenderWidget::SetAutoResizeMode(bool auto_resize, - const gfx::Size& min_size_before_dsf, - const gfx::Size& max_size_before_dsf, - float device_scale_factor) { - bool was_changed = auto_resize_mode_ != auto_resize; - auto_resize_mode_ = auto_resize; - - min_size_for_auto_resize_ = min_size_before_dsf; - max_size_for_auto_resize_ = max_size_before_dsf; - - if (auto_resize) { - gfx::Size min_auto_size = min_size_for_auto_resize_; - gfx::Size max_auto_size = max_size_for_auto_resize_; - if (compositor_deps_->IsUseZoomForDSFEnabled()) { - min_auto_size = - gfx::ScaleToCeiledSize(min_auto_size, device_scale_factor); - max_auto_size = - gfx::ScaleToCeiledSize(max_auto_size, device_scale_factor); - } - delegate()->ApplyAutoResizeLimitsForWidget(min_auto_size, max_auto_size); - } else if (was_changed) { - delegate()->DisableAutoResizeForWidget(); - } -} - void RenderWidget::SetRootWindowSegments( const std::vector<gfx::Rect>& root_window_segments) { if (root_widget_window_segments_ != root_window_segments) { @@ -940,7 +909,7 @@ void RenderWidget::ResizeWebWidget() { // In auto resize mode, blink controls sizes and RenderWidget should not be // passing values back in. - DCHECK(!auto_resize_mode_); + DCHECK(!AutoResizeMode()); // The widget size given to blink is scaled by the (non-emulated, // see https://crbug.com/819903) device scale factor (if UseZoomForDSF is @@ -1000,7 +969,7 @@ DCHECK(delegate()); DCHECK(for_frame()); // Emulation happens on regular main frames which don't use auto-resize mode. - DCHECK(!auto_resize_mode_); + DCHECK(!AutoResizeMode()); UpdateSurfaceAndScreenInfo(local_surface_id_allocation_from_parent_, CompositorViewportRect(), screen_info); @@ -1023,8 +992,7 @@ screen_info_.device_scale_factor)); visible_viewport_size_ = visible_viewport_size; - size_ = widget_size; - ResizeWebWidget(); + SetSize(widget_size); } void RenderWidget::SetScreenMetricsEmulationParameters( @@ -1317,6 +1285,11 @@ } } +void RenderWidget::SetSize(const gfx::Size& new_size) { + size_ = new_size; + ResizeWebWidget(); +} + void RenderWidget::ImeSetCompositionForPepper( const blink::WebString& text, const std::vector<ui::ImeTextSpan>& ime_text_spans, @@ -1436,8 +1409,7 @@ compositor_viewport_pixel_rect, screen_info_); visible_viewport_size_ = new_window_rect.size(); - size_ = new_window_rect.size(); - ResizeWebWidget(); + SetSize(new_window_rect.size()); widget_screen_rect_ = new_window_rect; window_screen_rect_ = new_window_rect; @@ -1759,7 +1731,7 @@ gfx::Size viewport_pixel_size = gfx::ScaleToCeiledSize(size_, factor); UpdateSurfaceAndScreenInfo(local_surface_id_allocation_from_parent_, gfx::Rect(viewport_pixel_size), info); - if (!auto_resize_mode_) + if (!AutoResizeMode()) ResizeWebWidget(); // This picks up the new device scale factor in |info|. RenderFrameImpl* render_frame = @@ -1786,26 +1758,6 @@ SetWindowRectSynchronously(new_window_rect); } -void RenderWidget::EnableAutoResizeForTesting(const gfx::Size& min_size, - const gfx::Size& max_size) { - SetAutoResizeMode(true, min_size, max_size, screen_info_.device_scale_factor); -} - -void RenderWidget::DisableAutoResizeForTesting(const gfx::Size& new_size) { - if (!auto_resize_mode_) - return; - - SetAutoResizeMode(false, gfx::Size(), gfx::Size(), - screen_info_.device_scale_factor); - - // The |new_size| is empty when resetting auto resize in between tests. In - // this case the current size should just be preserved. - if (!new_size.IsEmpty()) { - size_ = new_size; - ResizeWebWidget(); - } -} - #if BUILDFLAG(ENABLE_PLUGINS) PepperPluginInstanceImpl* RenderWidget::GetFocusedPepperPluginInsideWidget() { blink::WebFrameWidget* frame_widget = GetFrameWidget(); @@ -1840,4 +1792,10 @@ return CompositorViewportRect(); } +bool RenderWidget::AutoResizeMode() { + if (!delegate_) + return false; + return delegate_->AutoResizeMode(); +} + } // namespace content
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index bf205cf..9093dbb2 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -272,6 +272,7 @@ blink::WebRect WindowRect() override; blink::WebRect ViewRect() override; void SetWindowRect(const blink::WebRect&) override; + void SetSize(const gfx::Size&) override; void ConvertViewportToWindow(blink::WebRect* rect) override; void ConvertViewportToWindow(blink::WebFloatRect* rect) override; void ConvertWindowToViewport(blink::WebFloatRect* rect) override; @@ -368,16 +369,6 @@ void DidNavigate(ukm::SourceId source_id, const GURL& url); - bool auto_resize_mode() const { return auto_resize_mode_; } - - const gfx::Size& min_size_for_auto_resize() const { - return min_size_for_auto_resize_; - } - - const gfx::Size& max_size_for_auto_resize() const { - return max_size_for_auto_resize_; - } - viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::PointF& point, gfx::PointF* local_point); @@ -387,9 +378,6 @@ void SetDeviceScaleFactorForTesting(float factor); void SetDeviceColorSpaceForTesting(const gfx::ColorSpace& color_space); void SetWindowRectSynchronouslyForTesting(const gfx::Rect& new_window_rect); - void EnableAutoResizeForTesting(const gfx::Size& min_size, - const gfx::Size& max_size); - void DisableAutoResizeForTesting(const gfx::Size& new_size); // Do a hit test for a given point in viewport coordinate. blink::WebHitTestResult GetHitTestResultAtPoint(const gfx::PointF& point); @@ -442,13 +430,6 @@ // visual viewport size, or the device scale factor change. void ResizeWebWidget(); - // Enable or disable auto-resize. This is part of - // OnUpdateVisualProperties though tests may call to it more directly. - void SetAutoResizeMode(bool auto_resize, - const gfx::Size& min_size_before_dsf, - const gfx::Size& max_size_before_dsf, - float device_scale_factor); - // Helper method to get the device_viewport_rect() from the compositor, which // is always in physical pixels. gfx::Rect CompositorViewportRect() const; @@ -539,6 +520,8 @@ PepperPluginInstanceImpl* GetFocusedPepperPluginInsideWidget(); #endif + bool AutoResizeMode(); + // Whether this widget is for a frame. This excludes widgets that are not for // a frame (eg popups, pepper), but includes both the main frame // (via delegate_) and subframes (via for_child_local_root_frame_). @@ -591,16 +574,6 @@ // The size of the visible viewport in pixels. gfx::Size visible_viewport_size_; - // Whether the WebWidget is in auto resize mode, which is used for example - // by extension popups. - bool auto_resize_mode_ = false; - - // The minimum size to use for auto-resize. - gfx::Size min_size_for_auto_resize_; - - // The maximum size to use for auto-resize. - gfx::Size max_size_for_auto_resize_; - // Indicates that we shouldn't bother generated paint events. bool is_hidden_;
diff --git a/content/renderer/render_widget_delegate.h b/content/renderer/render_widget_delegate.h index ee0951a..7258c0a5 100644 --- a/content/renderer/render_widget_delegate.h +++ b/content/renderer/render_widget_delegate.h
@@ -34,17 +34,13 @@ // VR. https://crbug.com/940063 virtual bool ShouldAckSyntheticInputImmediately() = 0; + // Returns the current state of auto resize. + virtual bool AutoResizeMode() = 0; + // ================================== // These methods called during handling of a SynchronizeVisualProperties // message to handle updating state on the delegate. // - // Called during handling a SynchronizeVisualProperties message, if auto - // resize is enabled, with the new auto size limits. - virtual void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size, - const gfx::Size& max_size) = 0; - // Called during handling a SynchronizeVisualProperties message, if auto - // resize was enabled but is being disabled. - virtual void DisableAutoResizeForWidget() = 0; // Called during handling a SynchronizeVisualProperties message, if the // message informed that the focused node should be scrolled into view. virtual void ScrollFocusedNodeIntoViewForWidget() = 0;
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index 31d1c92..a5e19de7 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -568,9 +568,6 @@ void SetActiveForWidget(bool active) override {} bool SupportsMultipleWindowsForWidget() override { return true; } bool ShouldAckSyntheticInputImmediately() override { return true; } - void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size, - const gfx::Size& max_size) override {} - void DisableAutoResizeForWidget() override {} void ScrollFocusedNodeIntoViewForWidget() override {} void DidReceiveSetFocusEventForWidget() override {} void DidCommitCompositorFrameForWidget() override {}
diff --git a/content/shell/renderer/web_test/test_runner.cc b/content/shell/renderer/web_test/test_runner.cc index 1f3c392..bceb3dd 100644 --- a/content/shell/renderer/web_test/test_runner.cc +++ b/content/shell/renderer/web_test/test_runner.cc
@@ -1232,11 +1232,11 @@ if (max_width <= 0 || max_height <= 0) return; - RenderWidget* widget = frame_->GetLocalRootRenderWidget(); + blink::WebView* web_view = GetWebFrame()->View(); - blink::WebSize min_size(min_width, min_height); - blink::WebSize max_size(max_width, max_height); - widget->EnableAutoResizeForTesting(min_size, max_size); + gfx::Size min_size(min_width, min_height); + gfx::Size max_size(max_width, max_height); + web_view->EnableAutoResizeForTesting(min_size, max_size); } void TestRunnerBindings::DisableAutoResizeMode(int new_width, int new_height) { @@ -1250,11 +1250,12 @@ RenderWidget* widget = frame_->GetLocalRootRenderWidget(); - blink::WebSize new_size(new_width, new_height); - widget->DisableAutoResizeForTesting(new_size); + gfx::Size new_size(new_width, new_height); + blink::WebView* web_view = GetWebFrame()->View(); + web_view->DisableAutoResizeForTesting(new_size); gfx::Rect window_rect(widget->WindowRect().x, widget->WindowRect().y, - new_size.width, new_size.height); + new_size.width(), new_size.height()); widget->SetWindowRectSynchronouslyForTesting(window_rect); } @@ -2258,6 +2259,7 @@ web_view->SetTabKeyCyclesThroughElements(true); web_view->GetSettings()->SetHighlightAds(false); + web_view->DisableAutoResizeForTesting(gfx::Size()); } void TestRunner::ResetWebWidget(WebWidgetTestProxy* web_widget_test_proxy) { @@ -2269,7 +2271,6 @@ // These things are only modified/valid for the main frame's widget. if (web_widget_test_proxy->delegate()) { web_widget->ResetZoomLevelForTesting(); - web_widget_test_proxy->DisableAutoResizeForTesting(gfx::Size()); web_widget_test_proxy->UseSynchronousResizeModeForTesting(false); web_widget->SetMainFrameOverlayColor(SK_ColorTRANSPARENT);
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index e9246526..04e365b4 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -146,7 +146,7 @@ # Win / AMD / Passthrough command decoder / D3D11 crbug.com/685232 [ win amd d3d11 passthrough ] conformance/textures/misc/copytexsubimage2d-subrects.html [ RetryOnFailure ] -crbug.com/772037 [ win7 debug amd d3d11 passthrough ] conformance/textures/misc/texture-sub-image-cube-maps.html [ RetryOnFailure ] +crbug.com/772037 [ win amd d3d11 passthrough ] conformance/textures/misc/texture-sub-image-cube-maps.html [ RetryOnFailure ] crbug.com/772037 [ win7 release amd d3d11 passthrough ] conformance/extensions/oes-texture-half-float.html [ RetryOnFailure ] # Vulkan / Passthrough command decoder
diff --git a/device/bluetooth/public/mojom/adapter.mojom b/device/bluetooth/public/mojom/adapter.mojom index c6e729cf..2e2e72c 100644 --- a/device/bluetooth/public/mojom/adapter.mojom +++ b/device/bluetooth/public/mojom/adapter.mojom
@@ -41,6 +41,10 @@ bool discovering; }; +// Represents a request to discover nearby devices. +// Note: Methods which are declared [Sync] are for use by +// //chrome/services/sharing/nearby; all other usage of their synchronous +// signatures is strongly discouraged. interface DiscoverySession { // Returns true if the session is active, false otherwise. If false, the // adapter might still be discovering as there might still be other active @@ -66,6 +70,9 @@ // Represents an open connection to a remote device. Releasing it will destroy // the underlying connection, but callers should prefer to let a call to // Disconnect() to finish first. +// Note: Methods which are declared [Sync] are for use by +// //chrome/services/sharing/nearby; all other usage of their synchronous +// signatures is strongly discouraged. interface Socket { // Use to gracefully close the underlying connection before destroying. The // reply callback can be used to synchronize a reconnection attempt; @@ -77,6 +84,9 @@ // Handles requests to either query Bluetooth adapter capabilities or state, or // find or connect to remote devices. Backed by //device/bluetooth. +// Note: Methods which are declared [Sync] are for use by +// //chrome/services/sharing/nearby; all other usage of their synchronous +// signatures is strongly discouraged. interface Adapter { // Creates a GATT connection to the device with |address| and returns a // Device if the connection was succesful. The GATT connection is tied to the @@ -142,4 +152,3 @@ // Called after the device hasn't been seen for 3 minutes. DeviceRemoved(DeviceInfo device); }; -
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index 5aa2dfb..75eb3aa 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -28,6 +28,7 @@ #include "extensions/common/error_utils.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permissions_data.h" +#include "extensions/common/script_constants.h" #include "extensions/common/user_script.h" using content::WebContents; @@ -193,8 +194,13 @@ } // match_about_blank: - if (script_value.match_about_blank) - script->set_match_about_blank(*script_value.match_about_blank); + if (script_value.match_about_blank) { + script->set_match_origin_as_fallback( + *script_value.match_about_blank + ? extensions::MatchOriginAsFallbackBehavior:: + kMatchForAboutSchemeAndClimbTree + : extensions::MatchOriginAsFallbackBehavior::kNever); + } // css: if (script_value.css) {
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc index ad6150a5..d881623 100644 --- a/extensions/browser/url_loader_factory_manager.cc +++ b/extensions/browser/url_loader_factory_manager.cc
@@ -29,6 +29,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" #include "extensions/common/manifest_handlers/content_scripts_handler.h" +#include "extensions/common/script_constants.h" #include "extensions/common/switches.h" #include "extensions/common/user_script.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -478,8 +479,19 @@ if (user_script.js_scripts().empty()) return false; + // TODO(devlin): Update GetEffectiveDocumentURL() to take a + // MatchOriginAsFallbackBehavior. + bool match_about_blank = false; + switch (user_script.match_origin_as_fallback()) { + case MatchOriginAsFallbackBehavior::kAlways: + case MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree: + match_about_blank = true; + break; + case MatchOriginAsFallbackBehavior::kNever: + break; // `false` is correct for |match_about_blank|. + } GURL effective_url = GetEffectiveDocumentURL( - navigating_frame, navigation_target, user_script.match_about_blank()); + navigating_frame, navigation_target, match_about_blank); bool is_subframe = navigating_frame->GetParent(); return user_script.MatchesDocument(effective_url, is_subframe); }
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index b3b6dfd7..16dba9f 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -293,6 +293,7 @@ "permissions/usb_device_permission.h", "permissions/usb_device_permission_data.cc", "permissions/usb_device_permission_data.h", + "script_constants.h", "stack_frame.cc", "stack_frame.h", "switches.cc",
diff --git a/extensions/common/manifest_handlers/content_scripts_handler.cc b/extensions/common/manifest_handlers/content_scripts_handler.cc index b2c2b70..db6fbd66 100644 --- a/extensions/common/manifest_handlers/content_scripts_handler.cc +++ b/extensions/common/manifest_handlers/content_scripts_handler.cc
@@ -24,6 +24,7 @@ #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/permissions_parser.h" #include "extensions/common/permissions/permissions_data.h" +#include "extensions/common/script_constants.h" #include "extensions/common/url_pattern.h" #include "extensions/common/url_pattern_set.h" #include "extensions/strings/grit/extensions_strings.h" @@ -114,19 +115,7 @@ result->set_match_all_frames(all_frames->GetBool()); } - // match about blank - const base::Value* match_about_blank = - content_script.FindKey(keys::kMatchAboutBlank); - if (match_about_blank != nullptr) { - if (!match_about_blank->is_bool()) { - *error = ErrorUtils::FormatErrorMessageUTF16( - errors::kInvalidMatchAboutBlank, - base::NumberToString(definition_index)); - return nullptr; - } - result->set_match_about_blank(match_about_blank->GetBool()); - } - + bool has_match_origin_as_fallback = false; // match origin as fallback if (base::FeatureList::IsEnabled( extensions_features::kContentScriptsMatchOriginAsFallback)) { @@ -139,7 +128,31 @@ base::NumberToString(definition_index)); return nullptr; } - result->set_match_origin_as_fallback(match_origin_as_fallback->GetBool()); + has_match_origin_as_fallback = true; + result->set_match_origin_as_fallback( + match_origin_as_fallback->GetBool() + ? MatchOriginAsFallbackBehavior::kAlways + : MatchOriginAsFallbackBehavior::kNever); + } + } + + // match about blank + // Note: match_about_blank is ignored if |match_origin_as_fallback| was + // specified. + if (!has_match_origin_as_fallback) { + const base::Value* match_about_blank = + content_script.FindKey(keys::kMatchAboutBlank); + if (match_about_blank) { + if (!match_about_blank->is_bool()) { + *error = ErrorUtils::FormatErrorMessageUTF16( + errors::kInvalidMatchAboutBlank, + base::NumberToString(definition_index)); + return nullptr; + } + result->set_match_origin_as_fallback( + match_about_blank->GetBool() + ? MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree + : MatchOriginAsFallbackBehavior::kNever); } }
diff --git a/extensions/common/script_constants.h b/extensions/common/script_constants.h new file mode 100644 index 0000000..60a1e62 --- /dev/null +++ b/extensions/common/script_constants.h
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_COMMON_SCRIPT_CONSTANTS_H_ +#define EXTENSIONS_COMMON_SCRIPT_CONSTANTS_H_ + +namespace extensions { + +// Whether to fall back to matching the origin for frames where the URL +// cannot be matched directly, such as those with about: or data: schemes. +enum class MatchOriginAsFallbackBehavior { + // Never fall back on the origin; this means scripts will never match on + // these frames. + kNever, + // Match the origin only for about:-scheme frames, and then climb the frame + // tree to find an appropriate ancestor to get a full URL (including path). + // This is for supporting the "match_about_blank" key. + // TODO(devlin): I wonder if we could simplify this to be "MatchForAbout", + // and not worry about climbing the frame tree. It would be a behavior + // change, but I wonder how many extensions it would impact in practice. + kMatchForAboutSchemeAndClimbTree, + // Match the origin as a fallback whenever applicable. This won't have a + // corresponding path. + kAlways, +}; + +// TODO(devlin): Move the other non-UserScript-specific constants like +// RunLocation and InjectionType from UserScript into here. + +} // namespace extensions + +#endif // EXTENSIONS_COMMON_SCRIPT_CONSTANTS_H_
diff --git a/extensions/common/user_script.cc b/extensions/common/user_script.cc index ac3b90ad..ee9008f 100644 --- a/extensions/common/user_script.cc +++ b/extensions/common/user_script.cc
@@ -97,8 +97,7 @@ user_script_id_(-1), emulate_greasemonkey_(false), match_all_frames_(false), - match_about_blank_(false), - match_origin_as_fallback_(false), + match_origin_as_fallback_(MatchOriginAsFallbackBehavior::kNever), incognito_enabled_(false) {} UserScript::~UserScript() { @@ -132,7 +131,6 @@ script->user_script_id_ = other.user_script_id_; script->emulate_greasemonkey_ = other.emulate_greasemonkey_; script->match_all_frames_ = other.match_all_frames_; - script->match_about_blank_ = other.match_about_blank_; script->match_origin_as_fallback_ = other.match_origin_as_fallback_; script->incognito_enabled_ = other.incognito_enabled_; @@ -199,8 +197,7 @@ pickle->WriteInt(user_script_id_); pickle->WriteBool(emulate_greasemonkey()); pickle->WriteBool(match_all_frames()); - pickle->WriteBool(match_about_blank()); - pickle->WriteBool(match_origin_as_fallback()); + pickle->WriteInt(static_cast<int>(match_origin_as_fallback())); pickle->WriteBool(is_incognito_enabled()); PickleHostID(pickle, host_id_); @@ -255,8 +252,10 @@ CHECK(iter->ReadInt(&user_script_id_)); CHECK(iter->ReadBool(&emulate_greasemonkey_)); CHECK(iter->ReadBool(&match_all_frames_)); - CHECK(iter->ReadBool(&match_about_blank_)); - CHECK(iter->ReadBool(&match_origin_as_fallback_)); + int match_origin_as_fallback_int = 0; + CHECK(iter->ReadInt(&match_origin_as_fallback_int)); + match_origin_as_fallback_ = + static_cast<MatchOriginAsFallbackBehavior>(match_origin_as_fallback_int); CHECK(iter->ReadBool(&incognito_enabled_)); UnpickleHostID(pickle, iter, &host_id_);
diff --git a/extensions/common/user_script.h b/extensions/common/user_script.h index e145bc6..2b35497 100644 --- a/extensions/common/user_script.h +++ b/extensions/common/user_script.h
@@ -12,6 +12,7 @@ #include "base/files/file_path.h" #include "base/strings/string_piece.h" #include "extensions/common/host_id.h" +#include "extensions/common/script_constants.h" #include "extensions/common/url_pattern.h" #include "extensions/common/url_pattern_set.h" #include "url/gurl.h" @@ -170,14 +171,12 @@ bool match_all_frames() const { return match_all_frames_; } void set_match_all_frames(bool val) { match_all_frames_ = val; } - // Whether to match about:blank and about:srcdoc. - bool match_about_blank() const { return match_about_blank_; } - void set_match_about_blank(bool val) { match_about_blank_ = val; } - - // Whether to match on the origin if an appropriate URL cannot be found for - // the frame. - bool match_origin_as_fallback() const { return match_origin_as_fallback_; } - void set_match_origin_as_fallback(bool val) { + // Whether to match the origin as a fallback if the URL cannot be used + // directly. + MatchOriginAsFallbackBehavior match_origin_as_fallback() const { + return match_origin_as_fallback_; + } + void set_match_origin_as_fallback(MatchOriginAsFallbackBehavior val) { match_origin_as_fallback_ = val; } @@ -239,8 +238,7 @@ // Returns true if the script should be applied to the given // |effective_document_url|. It is the caller's responsibility to calculate - // |effective_document_url| based on match_about_blank() and - // match_origin_as_fallback(). + // |effective_document_url| based on match_origin_as_fallback(). bool MatchesDocument(const GURL& effective_document_url, bool is_subframe) const; @@ -329,15 +327,11 @@ // Defaults to false. bool match_all_frames_; - // Whether the user script should run in about:blank and about:srcdoc as well. - // Defaults to false. - bool match_about_blank_; - // Whether the user script should run in frames whose initiator / precursor // origin matches a match pattern, if an appropriate URL cannot be found for // the frame for matching purposes, such as in the case of about:, data:, and // other schemes. - bool match_origin_as_fallback_; + MatchOriginAsFallbackBehavior match_origin_as_fallback_; // True if the script should be injected into an incognito tab. bool incognito_enabled_;
diff --git a/extensions/renderer/programmatic_script_injector.cc b/extensions/renderer/programmatic_script_injector.cc index 8b6f67d7..6de5d30b 100644 --- a/extensions/renderer/programmatic_script_injector.cc +++ b/extensions/renderer/programmatic_script_injector.cc
@@ -15,6 +15,7 @@ #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/api_permission.h" #include "extensions/common/permissions/permissions_data.h" +#include "extensions/common/script_constants.h" #include "extensions/renderer/injection_host.h" #include "extensions/renderer/renderer_extension_registry.h" #include "extensions/renderer/script_context.h" @@ -82,8 +83,10 @@ } GURL effective_document_url = ScriptContext::GetEffectiveDocumentURLForInjection( - frame, frame->GetDocument().Url(), params_->match_about_blank, - /*match_origin_as_fallback=*/false); + frame, frame->GetDocument().Url(), + params_->match_about_blank + ? MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree + : MatchOriginAsFallbackBehavior::kNever); if (params_->is_web_view) { if (frame->Parent()) { // This is a subframe inside <webview>, so allow it.
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc index d3acdf2..e4401b4 100644 --- a/extensions/renderer/script_context.cc +++ b/extensions/renderer/script_context.cc
@@ -43,6 +43,8 @@ kAllowDataFrames = 1 << 2, }; +// TODO(devlin): Modify this to take a +// UserScript::MatchOriginAsFallbackBehavior, and handle it appropriately. GURL GetEffectiveDocumentURL(blink::WebLocalFrame* frame, const GURL& document_url, int flags) { @@ -466,16 +468,21 @@ GURL ScriptContext::GetEffectiveDocumentURLForInjection( blink::WebLocalFrame* frame, const GURL& document_url, - bool match_about_blank, - bool match_origin_as_fallback) { + MatchOriginAsFallbackBehavior match_origin_as_fallback) { // We explicitly allow inaccessible parents here. Extensions should still be // able to inject into a sandboxed iframe if it has access to the embedding // origin. int flags = kAllowInaccessibleParents; - if (match_about_blank) - flags |= kAllowAboutFrames; - if (match_origin_as_fallback) - flags |= kAllowDataFrames; + switch (match_origin_as_fallback) { + case MatchOriginAsFallbackBehavior::kNever: + break; + case MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree: + flags |= kAllowAboutFrames; + break; + case MatchOriginAsFallbackBehavior::kAlways: + flags |= kAllowAboutFrames | kAllowDataFrames; + break; + } return GetEffectiveDocumentURL(frame, document_url, flags); }
diff --git a/extensions/renderer/script_context.h b/extensions/renderer/script_context.h index 472a645..a97bc32 100644 --- a/extensions/renderer/script_context.h +++ b/extensions/renderer/script_context.h
@@ -17,6 +17,7 @@ #include "base/unguessable_token.h" #include "extensions/common/features/feature.h" #include "extensions/common/permissions/api_permission_set.h" +#include "extensions/common/script_constants.h" #include "extensions/renderer/module_system.h" #include "extensions/renderer/safe_builtins.h" #include "extensions/renderer/script_injection_callback.h" @@ -225,17 +226,14 @@ // If |document_url| is an about: or data: URL, returns the URL of the first // frame without an about: or data: URL that matches the initiator origin. // This may not be the immediate parent. Returns |document_url| if it is not - // an about: or data: URL, if the corresponding |match_about_blank| or - // |match_origin_as_fallback| is false, or if a suitable parent cannot be - // found. + // an about: or data: URL, if |match_origin_as_fallback| is set to not match, + // or if a suitable parent cannot be found. // Considers parent contexts that cannot be accessed (as is the case for // sandboxed frames). - // TODO(devlin): Enum-ify match_about_* here. static GURL GetEffectiveDocumentURLForInjection( blink::WebLocalFrame* frame, const GURL& document_url, - bool match_about_blank, - bool match_origin_as_fallback); + MatchOriginAsFallbackBehavior match_origin_as_fallback); // Grants a set of content capabilities to this context. void set_content_capabilities(APIPermissionSet capabilities) {
diff --git a/extensions/renderer/script_context_browsertest.cc b/extensions/renderer/script_context_browsertest.cc index 1ff15549..b3a1a08e 100644 --- a/extensions/renderer/script_context_browsertest.cc +++ b/extensions/renderer/script_context_browsertest.cc
@@ -5,6 +5,7 @@ #include "chrome/test/base/chrome_render_view_test.h" #include "content/public/renderer/render_frame.h" #include "content/public/test/frame_load_waiter.h" +#include "extensions/common/script_constants.h" #include "extensions/renderer/script_context.h" #include "extensions/renderer/script_context_set.h" #include "third_party/blink/public/web/web_document.h" @@ -22,15 +23,12 @@ return ScriptContext::GetEffectiveDocumentURLForContext( frame, frame->GetDocument().Url(), /*match_about_blank=*/true); } - GURL GetEffectiveDocumentURLForInjection(WebLocalFrame* frame) { + GURL GetEffectiveDocumentURLForInjection( + WebLocalFrame* frame, + MatchOriginAsFallbackBehavior match_origin_as_fallback = + MatchOriginAsFallbackBehavior::kAlways) { return ScriptContext::GetEffectiveDocumentURLForInjection( - frame, frame->GetDocument().Url(), - /*match_about_blank=*/true, /*match_origin_as_fallback=*/true); - } - GURL GetEffectiveURLForInjectionWithoutMatchingData(WebLocalFrame* frame) { - return ScriptContext::GetEffectiveDocumentURLForInjection( - frame, frame->GetDocument().Url(), - /*match_about_blank=*/true, /*match_origin_as_fallback=*/false); + frame, frame->GetDocument().Url(), match_origin_as_fallback); } }; @@ -136,17 +134,25 @@ // injecting scripts. EXPECT_EQ(data_url, GetEffectiveDocumentURLForContext(frame4)); EXPECT_EQ(top_url, GetEffectiveDocumentURLForInjection(frame4)); - // Sanity-check: without matching data: URLs, the original URL should be + // Sanity-check: if we only match about: schemes, the original URL should be // returned. - EXPECT_EQ(data_url, GetEffectiveURLForInjectionWithoutMatchingData(frame4)); + EXPECT_EQ( + data_url, + GetEffectiveDocumentURLForInjection( + frame4, + MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree)); // top -> sandboxed data URL = same URL when classifying contexts, but // inherited when injecting scripts. EXPECT_EQ(data_url, GetEffectiveDocumentURLForContext(frame5)); EXPECT_EQ(top_url, GetEffectiveDocumentURLForInjection(frame5)); - // Sanity-check: without matching data: URLs, the original URL should be + // Sanity-check: if we only match about: schemes, the original URL should be // returned. - EXPECT_EQ(data_url, GetEffectiveURLForInjectionWithoutMatchingData(frame5)); + EXPECT_EQ( + data_url, + GetEffectiveDocumentURLForInjection( + frame5, + MatchOriginAsFallbackBehavior::kMatchForAboutSchemeAndClimbTree)); // top -> different origin = different origin EXPECT_EQ(different_url, GetEffectiveDocumentURLForContext(frame3));
diff --git a/extensions/renderer/user_script_injector.cc b/extensions/renderer/user_script_injector.cc index 691f6625..381ca41 100644 --- a/extensions/renderer/user_script_injector.cc +++ b/extensions/renderer/user_script_injector.cc
@@ -204,7 +204,7 @@ GURL effective_document_url = ScriptContext::GetEffectiveDocumentURLForInjection( web_frame, web_frame->GetDocument().Url(), - script_->match_about_blank(), script_->match_origin_as_fallback()); + script_->match_origin_as_fallback()); return injection_host->CanExecuteOnFrame( effective_document_url,
diff --git a/extensions/renderer/user_script_set.cc b/extensions/renderer/user_script_set.cc index 877982f5..2022c7a6 100644 --- a/extensions/renderer/user_script_set.cc +++ b/extensions/renderer/user_script_set.cc
@@ -217,8 +217,7 @@ GURL effective_document_url = ScriptContext::GetEffectiveDocumentURLForInjection( - web_frame, document_url, script->match_about_blank(), - script->match_origin_as_fallback()); + web_frame, document_url, script->match_origin_as_fallback()); bool is_subframe = web_frame->Parent(); if (!script->MatchesDocument(effective_document_url, is_subframe))
diff --git a/gpu/command_buffer/service/external_vk_image_dawn_representation.cc b/gpu/command_buffer/service/external_vk_image_dawn_representation.cc index 678d70b..246989e 100644 --- a/gpu/command_buffer/service/external_vk_image_dawn_representation.cc +++ b/gpu/command_buffer/service/external_vk_image_dawn_representation.cc
@@ -52,7 +52,6 @@ texture_descriptor.usage = usage; texture_descriptor.dimension = WGPUTextureDimension_2D; texture_descriptor.size = {size().width(), size().height(), 1}; - texture_descriptor.arrayLayerCount = 1; texture_descriptor.mipLevelCount = 1; texture_descriptor.sampleCount = 1;
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm b/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm index 8b1f3d6..78ebc2f 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm +++ b/gpu/command_buffer/service/shared_image_backing_factory_iosurface.mm
@@ -111,13 +111,12 @@ } WGPUTexture BeginAccess(WGPUTextureUsage usage) final { - WGPUTextureDescriptor texture_descriptor; + WGPUTextureDescriptor texture_descriptor = {}; texture_descriptor.nextInChain = nullptr; texture_descriptor.format = wgpu_format_; texture_descriptor.usage = usage; texture_descriptor.dimension = WGPUTextureDimension_2D; texture_descriptor.size = {size().width(), size().height(), 1}; - texture_descriptor.arrayLayerCount = 1; texture_descriptor.mipLevelCount = 1; texture_descriptor.sampleCount = 1;
diff --git a/gpu/command_buffer/service/shared_image_backing_gl_image.cc b/gpu/command_buffer/service/shared_image_backing_gl_image.cc index df341211..c34decc5 100644 --- a/gpu/command_buffer/service/shared_image_backing_gl_image.cc +++ b/gpu/command_buffer/service/shared_image_backing_gl_image.cc
@@ -431,12 +431,12 @@ std::unique_ptr<SharedImageRepresentationOverlay> SharedImageBackingGLImage::ProduceOverlay(SharedImageManager* manager, MemoryTypeTracker* tracker) { -#if defined(OS_MAC) +#if defined(OS_MAC) || defined(USE_OZONE) return std::make_unique<SharedImageRepresentationOverlayImpl>( manager, this, tracker, image_); -#else // defined(OS_MAC) +#else // !(defined(OS_MAC) || defined(USE_OZONE)) return SharedImageBacking::ProduceOverlay(manager, tracker); -#endif // !defined(OS_MAC) +#endif // defined(OS_MAC) || defined(USE_OZONE) } std::unique_ptr<SharedImageRepresentationDawn>
diff --git a/gpu/command_buffer/service/shared_image_representation_d3d.cc b/gpu/command_buffer/service/shared_image_representation_d3d.cc index 06b3ae1..4afcd6c1 100644 --- a/gpu/command_buffer/service/shared_image_representation_d3d.cc +++ b/gpu/command_buffer/service/shared_image_representation_d3d.cc
@@ -79,13 +79,12 @@ return nullptr; } - WGPUTextureDescriptor texture_descriptor; + WGPUTextureDescriptor texture_descriptor = {}; texture_descriptor.nextInChain = nullptr; texture_descriptor.format = wgpu_format; texture_descriptor.usage = usage; texture_descriptor.dimension = WGPUTextureDimension_2D; texture_descriptor.size = {size().width(), size().height(), 1}; - texture_descriptor.arrayLayerCount = 1; texture_descriptor.mipLevelCount = 1; texture_descriptor.sampleCount = 1;
diff --git a/gpu/command_buffer/service/shared_image_representation_dawn_ozone.cc b/gpu/command_buffer/service/shared_image_representation_dawn_ozone.cc index d134bf3..101b41e 100644 --- a/gpu/command_buffer/service/shared_image_representation_dawn_ozone.cc +++ b/gpu/command_buffer/service/shared_image_representation_dawn_ozone.cc
@@ -64,7 +64,6 @@ texture_descriptor.usage = usage; texture_descriptor.dimension = WGPUTextureDimension_2D; texture_descriptor.size = {pixmap_size.width(), pixmap_size.height(), 1}; - texture_descriptor.arrayLayerCount = 1; texture_descriptor.mipLevelCount = 1; texture_descriptor.sampleCount = 1;
diff --git a/gpu/command_buffer/tests/shared_image_gl_backing_produce_dawn_unittest.cc b/gpu/command_buffer/tests/shared_image_gl_backing_produce_dawn_unittest.cc index d3a4598c..6eb7757e 100644 --- a/gpu/command_buffer/tests/shared_image_gl_backing_produce_dawn_unittest.cc +++ b/gpu/command_buffer/tests/shared_image_gl_backing_produce_dawn_unittest.cc
@@ -20,24 +20,15 @@ namespace gpu { namespace { -class MockBufferMapReadCallback { +class MockBufferMapCallback { public: - MOCK_METHOD4(Call, - void(WGPUBufferMapAsyncStatus status, - const uint32_t* ptr, - uint64_t data_length, - void* userdata)); + MOCK_METHOD(void, Call, (WGPUBufferMapAsyncStatus status, void* userdata)); }; +std::unique_ptr<testing::StrictMock<MockBufferMapCallback>> + mock_buffer_map_callback; -std::unique_ptr<testing::StrictMock<MockBufferMapReadCallback>> - mock_buffer_map_read_callback; -void ToMockBufferMapReadCallback(WGPUBufferMapAsyncStatus status, - const void* ptr, - uint64_t data_length, - void* userdata) { - // Assume the data is uint32_t - mock_buffer_map_read_callback->Call(status, static_cast<const uint32_t*>(ptr), - data_length, userdata); +void ToMockBufferMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) { + mock_buffer_map_callback->Call(status, userdata); } } // namespace @@ -66,14 +57,14 @@ gpu::kNullSurfaceHandle, attributes, option.shared_memory_limits, nullptr, nullptr, base::ThreadTaskRunnerHandle::Get()); ASSERT_EQ(result, ContextResult::kSuccess); - mock_buffer_map_read_callback = - std::make_unique<testing::StrictMock<MockBufferMapReadCallback>>(); + mock_buffer_map_callback = + std::make_unique<testing::StrictMock<MockBufferMapCallback>>(); } void TearDown() override { WebGPUTest::TearDown(); gl_context_.reset(); - mock_buffer_map_read_callback = nullptr; + mock_buffer_map_callback = nullptr; } bool ShouldSkipTest() { @@ -164,9 +155,9 @@ wgpu::BufferCopyView copy_dst = {}; copy_dst.buffer = readback_buffer; - copy_dst.offset = 0; - copy_dst.bytesPerRow = 256; - copy_dst.rowsPerImage = 0; + copy_dst.layout.offset = 0; + copy_dst.layout.bytesPerRow = 256; + copy_dst.layout.rowsPerImage = 0; wgpu::Extent3D copy_size = {1, 1, 1}; @@ -181,15 +172,16 @@ reservation.generation); // Map the buffer and assert the pixel is the correct value. - readback_buffer.MapReadAsync(ToMockBufferMapReadCallback, this); - uint32_t buffer_contents = 0xFF00FF00; - EXPECT_CALL(*mock_buffer_map_read_callback, - Call(WGPUBufferMapAsyncStatus_Success, - testing::Pointee(testing::Eq(buffer_contents)), - sizeof(uint32_t), this)) + readback_buffer.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapCallback, + nullptr); + EXPECT_CALL(*mock_buffer_map_callback, + Call(WGPUBufferMapAsyncStatus_Success, nullptr)) .Times(1); WaitForCompletion(device); + + const void* data = readback_buffer.GetConstMappedRange(0, 4); + EXPECT_EQ(0xFF00FF00, *static_cast<const uint32_t*>(data)); } }
diff --git a/gpu/command_buffer/tests/webgpu_mailbox_unittest.cc b/gpu/command_buffer/tests/webgpu_mailbox_unittest.cc index 360ef29..6a51c11 100644 --- a/gpu/command_buffer/tests/webgpu_mailbox_unittest.cc +++ b/gpu/command_buffer/tests/webgpu_mailbox_unittest.cc
@@ -14,24 +14,15 @@ namespace gpu { namespace { -class MockBufferMapReadCallback { +class MockBufferMapCallback { public: - MOCK_METHOD4(Call, - void(WGPUBufferMapAsyncStatus status, - const uint32_t* ptr, - uint64_t data_length, - void* userdata)); + MOCK_METHOD(void, Call, (WGPUBufferMapAsyncStatus status, void* userdata)); }; +std::unique_ptr<testing::StrictMock<MockBufferMapCallback>> + mock_buffer_map_callback; -std::unique_ptr<testing::StrictMock<MockBufferMapReadCallback>> - mock_buffer_map_read_callback; -void ToMockBufferMapReadCallback(WGPUBufferMapAsyncStatus status, - const void* ptr, - uint64_t data_length, - void* userdata) { - // Assume the data is uint32_t - mock_buffer_map_read_callback->Call(status, static_cast<const uint32_t*>(ptr), - data_length, userdata); +void ToMockBufferMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) { + mock_buffer_map_callback->Call(status, userdata); } class MockUncapturedErrorCallback { @@ -55,14 +46,14 @@ void SetUp() override { WebGPUTest::SetUp(); Initialize(WebGPUTest::Options()); - mock_buffer_map_read_callback = - std::make_unique<testing::StrictMock<MockBufferMapReadCallback>>(); + mock_buffer_map_callback = + std::make_unique<testing::StrictMock<MockBufferMapCallback>>(); mock_device_error_callback = std::make_unique<testing::StrictMock<MockUncapturedErrorCallback>>(); } void TearDown() override { - mock_buffer_map_read_callback = nullptr; + mock_buffer_map_callback = nullptr; mock_device_error_callback = nullptr; WebGPUTest::TearDown(); } @@ -153,9 +144,9 @@ wgpu::BufferCopyView copy_dst = {}; copy_dst.buffer = readback_buffer; - copy_dst.offset = 0; - copy_dst.bytesPerRow = 256; - copy_dst.rowsPerImage = 0; + copy_dst.layout.offset = 0; + copy_dst.layout.bytesPerRow = 256; + copy_dst.layout.rowsPerImage = 0; wgpu::Extent3D copy_size = {1, 1, 1}; @@ -170,15 +161,16 @@ reservation.generation); // Map the buffer and assert the pixel is the correct value. - readback_buffer.MapReadAsync(ToMockBufferMapReadCallback, 0); - uint32_t buffer_contents = 0xFF00FF00; - EXPECT_CALL(*mock_buffer_map_read_callback, - Call(WGPUBufferMapAsyncStatus_Success, - testing::Pointee(testing::Eq(buffer_contents)), - sizeof(uint32_t), 0)) + readback_buffer.MapAsync(wgpu::MapMode::Read, 0, 4, ToMockBufferMapCallback, + nullptr); + EXPECT_CALL(*mock_buffer_map_callback, + Call(WGPUBufferMapAsyncStatus_Success, nullptr)) .Times(1); WaitForCompletion(device); + + const void* data = readback_buffer.GetConstMappedRange(0, 4); + EXPECT_EQ(0xFF00FF00, *static_cast<const uint32_t*>(data)); } }
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg index 2421052..c7277a3 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/commit-queue.cfg
@@ -1187,6 +1187,10 @@ includable_only: true } builders { + name: "chromium/try/mac-arm64-rel" + includable_only: true + } + builders { name: "chromium/try/mac-coverage-rel" experiment_percentage: 3 location_regexp: ".*"
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index d28efaa..115368b 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -26826,6 +26826,42 @@ } } builders { + name: "mac-arm64-rel" + swarming_host: "chromium-swarm.appspot.com" + swarming_tags: "vpython:native-python-wrapper" + dimensions: "builderless:1" + dimensions: "cpu:x86-64" + dimensions: "os:Mac-10.13" + dimensions: "pool:luci.chromium.try" + dimensions: "ssd:1" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/master" + cmd: "recipes" + } + properties: "{\"$build/goma\":{\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"tryserver.chromium.mac\",\"recipe\":\"chromium_trybot\"}" + execution_timeout_secs: 14400 + expiration_secs: 7200 + caches { + name: "win_toolchain" + path: "win_toolchain" + } + build_numbers: YES + service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" + task_template_canary_percentage { + value: 5 + } + resultdb { + enable: true + bq_exports { + project: "luci-resultdb" + dataset: "chromium" + table: "try_test_results" + test_results {} + } + } + } + builders { name: "mac-coverage-rel" swarming_host: "chromium-swarm.appspot.com" swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg index f815d0e..24b6ae9 100644 --- a/infra/config/generated/luci-milo.cfg +++ b/infra/config/generated/luci-milo.cfg
@@ -4636,6 +4636,9 @@ name: "buildbucket/luci.chromium.try/linux_vr" } builders { + name: "buildbucket/luci.chromium.try/mac-arm64-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac-rel" } builders { @@ -16180,6 +16183,9 @@ name: "buildbucket/luci.chromium.try/ios14-sdk-simulator" } builders { + name: "buildbucket/luci.chromium.try/mac-arm64-rel" + } + builders { name: "buildbucket/luci.chromium.try/mac-coverage-rel" } builders {
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star index c84a489..38406ed 100644 --- a/infra/config/subprojects/chromium/try.star +++ b/infra/config/subprojects/chromium/try.star
@@ -477,6 +477,12 @@ ) try_.chromium_mac_builder( + name = "mac-arm64-rel", + goma_jobs = goma.jobs.J150, + os = os.MAC_10_13, +) + +try_.chromium_mac_builder( name = "mac_chromium_compile_dbg_ng", goma_jobs = goma.jobs.J150, os = os.MAC_10_13,
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py index 959aa8a..9bb7ddc2 100644 --- a/ios/build/bots/scripts/test_runner.py +++ b/ios/build/bots/scripts/test_runner.py
@@ -382,13 +382,6 @@ # for XCtests and Gtests. self.xctest = xctest - # TODO(crbug.com/1110375): Remove this when WebRTC xctests run with - # xcodebuild_runner. - webrtc_xctest_names = [ - 'apprtcmobile_tests', 'sdk_unittests', 'sdk_framework_unittests' - ] - self.webrtc_xctest = self.xctest and self.app_name in webrtc_xctest_names - self.test_results = {} self.test_results['version'] = 3 self.test_results['path_delimiter'] = '.' @@ -530,10 +523,7 @@ """ result = gtest_utils.GTestResult(cmd) - if self.webrtc_xctest: - parser = xctest_utils.XCTestLogParser() - else: - parser = gtest_utils.GTestLogParser() + parser = gtest_utils.GTestLogParser() # TODO(crbug.com/812705): Implement test sharding for unit tests. # TODO(crbug.com/812712): Use thread pool for DeviceTestRunner as well. @@ -549,9 +539,6 @@ LOGGER.debug('Stdout flushed after test process.') returncode = proc.returncode - if self.webrtc_xctest and parser.SystemAlertPresent(): - raise SystemAlertPresentError() - LOGGER.debug('Processing test results.') for test in parser.FailedTests(include_flaky=True): # Test cases are named as <test group>.<test case>. If the test case @@ -564,9 +551,8 @@ result.passed_tests.extend(parser.PassedTests(include_flaky=True)) # Only GTest outputs compiled tests in a json file. - if not self.webrtc_xctest: - result.disabled_tests_from_compiled_tests_file.extend( - parser.DisabledTestsFromCompiledTestsFile()) + result.disabled_tests_from_compiled_tests_file.extend( + parser.DisabledTestsFromCompiledTestsFile()) LOGGER.info('%s returned %s\n', cmd[0], returncode) @@ -579,16 +565,10 @@ """Launches the test app.""" self.set_up() destination = 'id=%s' % self.udid - if self.webrtc_xctest: - test_app = test_apps.EgtestsApp( - self.app_path, - included_tests=self.test_cases, - env_vars=self.env_vars, - test_args=self.test_args) # When current |launch| method is invoked, this is running a unit test # target. For simulators, '--xctest' is passed to test runner scripts to # make it run XCTest based unit test. - elif self.xctest: + if self.xctest: test_app = test_apps.SimulatorXCTestUnitTestsApp( self.app_path, included_tests=self.test_cases,
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm index b378631e..b726e745 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -61,6 +61,14 @@ NSString* const kSiriShortcutSearchInChrome = @"SearchInChromeIntent"; NSString* const kSiriShortcutOpenInIncognito = @"OpenInChromeIncognitoIntent"; +std::vector<GURL> createGURLVectorFromIntentURLs(NSArray<NSURL*>* intentURLs) { + std::vector<GURL> URLs; + for (NSURL* URL in intentURLs) { + URLs.push_back(net::GURLWithNSURL(URL)); + } + return URLs; +} + } // namespace @interface UserActivityHandler () @@ -176,18 +184,23 @@ base::RecordAction(UserMetricsAction("IOSLaunchedByOpenInChromeIntent")); OpenInChromeIntent* intent = base::mac::ObjCCastStrict<OpenInChromeIntent>( userActivity.interaction.intent); - if (!intent.url) - return NO; - GURL webpageGURL(net::GURLWithNSURL(intent.url)); - if (!webpageGURL.is_valid()) + if (!intent.url || intent.url.count == 0) { return NO; + } + std::vector<GURL> URLs = createGURLVectorFromIntentURLs(intent.url); AppStartupParameters* startupParams = - [[AppStartupParameters alloc] initWithExternalURL:webpageGURL - completeURL:webpageGURL]; + [[AppStartupParameters alloc] initWithURLs:URLs]; + [connectionInformation setStartupParameters:startupParams]; - webpageURL = intent.url; + return [self continueUserActivityURLs:URLs + applicationIsActive:applicationIsActive + tabOpener:tabOpener + connectionInformation:connectionInformation + startupInformation:startupInformation + Incognito:NO]; + } else if ([userActivity.activityType isEqualToString:kSiriShortcutOpenInIncognito]) { base::RecordAction(UserMetricsAction("IOSLaunchedByOpenInIncognitoIntent")); @@ -199,13 +212,11 @@ return NO; } - std::vector<GURL> URLs; - for (NSURL* URL in intent.urls) { - URLs.push_back(net::GURLWithNSURL(URL)); - } + std::vector<GURL> URLs = createGURLVectorFromIntentURLs(intent.urls); AppStartupParameters* startupParams = [[AppStartupParameters alloc] initWithURLs:URLs]; + startupParams.launchInIncognito = YES; [connectionInformation setStartupParameters:startupParams]; return [self continueUserActivityURLs:URLs
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm index 9b3ab7a..74d6bbe5 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -515,8 +515,13 @@ NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:@"OpenInChromeIntent"]; OpenInChromeIntent* intent = [[OpenInChromeIntent alloc] init]; - NSURL* nsurl = [NSURL URLWithString:@"http://www.google.com"]; - intent.url = nsurl; + + NSURL* url1 = [[NSURL alloc] initWithString:@"http://www.google.com"]; + NSURL* url2 = [[NSURL alloc] initWithString:@"http://www.apple.com"]; + NSURL* url3 = [[NSURL alloc] initWithString:@"http://www.espn.com"]; + NSArray<NSURL*>* urls = [NSArray arrayWithObjects:url1, url2, url3, nil]; + + intent.url = urls; INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent response:nil]; userActivity.interaction = interaction; @@ -525,13 +530,21 @@ [OCMockObject niceMockForProtocol:@protocol(StartupInformation)]; id connectionInformationMock = [OCMockObject niceMockForProtocol:@protocol(ConnectionInformation)]; + [[connectionInformationMock expect] setStartupParameters:[OCMArg checkWithBlock:^BOOL(id value) { - EXPECT_TRUE([value isKindOfClass:[AppStartupParameters class]]); + EXPECT_TRUE([value isKindOfClass:[AppStartupParameters class]] || + value == nil); - AppStartupParameters* startupParameters = (AppStartupParameters*)value; - const GURL calledURL = startupParameters.externalURL; - return calledURL == net::GURLWithNSURL(nsurl); + if (value != nil) { + AppStartupParameters* startupParameters = + (AppStartupParameters*)value; + const GURL calledURL = startupParameters.externalURL; + EXPECT_TRUE((int)[intent.url count] == 3); + return [intent.url containsObject:(net::NSURLWithGURL(calledURL))]; + } else { + return YES; + } }]]; // The test will fail if a method of this object is called. @@ -617,15 +630,20 @@ // Test. EXPECT_OCMOCK_VERIFY(startupInformationMock); EXPECT_TRUE(result); + EXPECT_EQ(3U, tabOpener.URLs.size()); } // Tests that Chrome responds to open intents in the foreground. TEST_F(UserActivityHandlerTest, ContinueUserActivityIntentForeground) { - GURL gurl("http://www.google.com"); NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:@"OpenInChromeIntent"]; OpenInChromeIntent* intent = [[OpenInChromeIntent alloc] init]; - intent.url = net::NSURLWithGURL(gurl); + NSURL* url1 = [[NSURL alloc] initWithString:@"http://www.google.com"]; + NSURL* url2 = [[NSURL alloc] initWithString:@"http://www.apple.com"]; + NSURL* url3 = [[NSURL alloc] initWithString:@"http://www.espn.com"]; + NSArray<NSURL*>* urls = [NSArray arrayWithObjects:url1, url2, url3, nil]; + + intent.url = urls; INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent response:nil]; userActivity.interaction = interaction; @@ -636,19 +654,32 @@ id connectionInformationMock = [OCMockObject niceMockForProtocol:@protocol(ConnectionInformation)]; + [[connectionInformationMock expect] setStartupParameters:[OCMArg checkWithBlock:^BOOL(id value) { - EXPECT_TRUE([value isKindOfClass:[AppStartupParameters class]]); + EXPECT_TRUE([value isKindOfClass:[AppStartupParameters class]] || + value == nil); - AppStartupParameters* startupParameters = (AppStartupParameters*)value; - const GURL calledURL = startupParameters.externalURL; - return calledURL == net::GURLWithNSURL(intent.url); + if (value != nil) { + AppStartupParameters* startupParameters = + (AppStartupParameters*)value; + const GURL calledURL = startupParameters.externalURL; + EXPECT_TRUE((int)[intent.url count] == 3); + return [intent.url containsObject:(net::NSURLWithGURL(calledURL))]; + } else { + return YES; + } }]]; MockTabOpener* tabOpener = [[MockTabOpener alloc] init]; + std::vector<GURL> URLs; + for (NSURL* URL in urls) { + URLs.push_back(net::GURLWithNSURL(URL)); + } + AppStartupParameters* startupParams = - [[AppStartupParameters alloc] initWithExternalURL:gurl completeURL:gurl]; + [[AppStartupParameters alloc] initWithURLs:URLs]; [[[connectionInformationMock stub] andReturn:startupParams] startupParameters]; @@ -661,9 +692,9 @@ startupInformation:startupInformationMock]; // Test. - EXPECT_EQ(gurl, tabOpener.urlLoadParams.web_params.url); - EXPECT_TRUE(tabOpener.urlLoadParams.web_params.virtual_url.is_empty()); + EXPECT_OCMOCK_VERIFY(startupInformationMock); EXPECT_TRUE(result); + EXPECT_EQ(3U, tabOpener.URLs.size()); } // Tests that handleStartupParameters with a file url. "external URL" gets
diff --git a/ios/chrome/app/intents/Intents.intentdefinition b/ios/chrome/app/intents/Intents.intentdefinition index 653f181..2537829 100644 --- a/ios/chrome/app/intents/Intents.intentdefinition +++ b/ios/chrome/app/intents/Intents.intentdefinition
@@ -29,8 +29,6 @@ <true/> <key>INIntentInput</key> <string>url</string> - <key>INIntentKeyParameter</key> - <string>url</string> <key>INIntentLastParameterTag</key> <integer>6</integer> <key>INIntentManagedParameterCombinations</key> @@ -68,13 +66,15 @@ <key>INIntentParameterPromptDialogCustom</key> <true/> <key>INIntentParameterPromptDialogFormatString</key> - <string>Which URL?</string> + <string>What URL?</string> <key>INIntentParameterPromptDialogFormatStringID</key> <string>3PpdH5</string> <key>INIntentParameterPromptDialogType</key> <string>Primary</string> </dict> </array> + <key>INIntentParameterSupportsMultipleValues</key> + <true/> <key>INIntentParameterSupportsResolution</key> <true/> <key>INIntentParameterTag</key>
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index cb6d579..64ac300e 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -615,6 +615,10 @@ <message name="IDS_IOS_CONTENT_CONTEXT_OPEN" desc="The iOS menu item for opening a link. Shorter than the desktop version [Length: 25em] [iOS only]"> Open </message> + <message name="IDS_IOS_CONTENT_CONTEXT_OPEN_ALL_LINKS" desc="The iOS menu item for opening a list of links in new tabs. Shorter than the desktop version [iOS only]"> + Open all + </message> + <message name="IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW" desc="The iOS menu item for opening a link in a new window. [iOS only]"> Open in New Window </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_OPEN_ALL_LINKS.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_OPEN_ALL_LINKS.png.sha1 new file mode 100644 index 0000000..1662d76 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_CONTENT_CONTEXT_OPEN_ALL_LINKS.png.sha1
@@ -0,0 +1 @@ +bc00ee9d4343e90794c79a08fe91a81b2e7953ae \ No newline at end of file
diff --git a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm index 389f779..f98793a 100644 --- a/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm +++ b/ios/chrome/browser/app_launcher/app_launcher_tab_helper_unittest.mm
@@ -444,8 +444,8 @@ web_state_.SetBrowserState(enterprise_policy_helper_->GetBrowserState()); policy::PolicyMap policy_map; - auto value = std::make_unique<base::Value>(base::Value::Type::LIST); - value->Append("itms-apps://*"); + base::Value value(base::Value::Type::LIST); + value.Append("itms-apps://*"); policy_map.Set(policy::key::kURLBlocklist, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, std::move(value), nullptr);
diff --git a/ios/chrome/browser/policy/policy_app_interface.mm b/ios/chrome/browser/policy/policy_app_interface.mm index 0c6b100d..f809a72 100644 --- a/ios/chrome/browser/policy/policy_app_interface.mm +++ b/ios/chrome/browser/policy/policy_app_interface.mm
@@ -4,7 +4,10 @@ #import "ios/chrome/browser/policy/policy_app_interface.h" +#include <memory> + #include "base/json/json_string_value_serializer.h" +#include "base/optional.h" #include "base/strings/sys_string_conversions.h" #include "base/values.h" #include "components/policy/core/browser/browser_policy_connector.h" @@ -44,15 +47,18 @@ // Takes a JSON-encoded string representing a |base::Value|, and deserializes // into a |base::Value| pointer. If nullptr is given, returns a pointer to a // |base::Value| of type NONE. -std::unique_ptr<base::Value> DeserializeValue(NSString* json_value) { +base::Optional<base::Value> DeserializeValue(NSString* json_value) { if (!json_value) { - return std::make_unique<base::Value>(base::Value::Type::NONE); + return base::Value(base::Value::Type::NONE); } std::string json = base::SysNSStringToUTF8(json_value); JSONStringValueDeserializer deserializer(json); - return deserializer.Deserialize(/*error_code=*/nullptr, - /*error_message=*/nullptr); + std::unique_ptr<base::Value> value = + deserializer.Deserialize(/*error_code=*/nullptr, + /*error_message=*/nullptr); + return value ? base::make_optional<base::Value>(std::move(*value)) + : base::nullopt; } } @@ -80,7 +86,7 @@ } + (void)setPolicyValue:(NSString*)jsonValue forKey:(NSString*)policyKey { - std::unique_ptr<base::Value> value = DeserializeValue(jsonValue); + base::Optional<base::Value> value = DeserializeValue(jsonValue); policy::PolicyMap values; values.Set(base::SysNSStringToUTF8(policyKey), policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
diff --git a/ios/chrome/browser/ui/activity_services/activity_scenario.h b/ios/chrome/browser/ui/activity_services/activity_scenario.h index 67eb330..8a5055d8 100644 --- a/ios/chrome/browser/ui/activity_services/activity_scenario.h +++ b/ios/chrome/browser/ui/activity_services/activity_scenario.h
@@ -12,8 +12,9 @@ TabShareButton = 0, QRCodeImage = 1, HistoryEntry = 2, + ReadingListEntry = 3, // Highest enumerator. Recommended by Histogram metrics best practices. - kMaxValue = HistoryEntry + kMaxValue = ReadingListEntry }; #endif // IOS_CHROME_BROWSER_UI_ACTIVITY_SERVICES_ACTIVITY_SCENARIO_H_
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_histograms.mm b/ios/chrome/browser/ui/activity_services/activity_service_histograms.mm index b37a552..28ac899 100644 --- a/ios/chrome/browser/ui/activity_services/activity_service_histograms.mm +++ b/ios/chrome/browser/ui/activity_services/activity_service_histograms.mm
@@ -22,6 +22,8 @@ "Mobile.Share.QRCodeImage.Actions"; const char kShareHistoryEntryActionsHistogram[] = "Mobile.Share.HistoryEntry.Actions"; +const char kShareReadingListEntryActionsHistogram[] = + "Mobile.Share.ReadingListEntry.Actions"; // Enum representing an aggregation of the |ActivityType| enum values in a way // that is relevant for metric collection. Current values should not @@ -133,6 +135,9 @@ case ActivityScenario::HistoryEntry: histogramName = kShareHistoryEntryActionsHistogram; break; + case ActivityScenario::ReadingListEntry: + histogramName = kShareReadingListEntryActionsHistogram; + break; } base::UmaHistogramEnumeration(histogramName, actionType); }
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_discover_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_discover_item.mm index 04d5601..1b08936 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_discover_item.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_discover_item.mm
@@ -8,6 +8,11 @@ #error "This file requires ARC support." #endif +namespace { +// The minimum height for the Feed Cell. +const CGFloat kMinimumFeedCellHeight = 50; +} + #pragma mark - ContentSuggestionsDiscoverItem @interface ContentSuggestionsDiscoverItem () @@ -36,7 +41,8 @@ } - (CGFloat)cellHeightForWidth:(CGFloat)width { - return self.lastConfiguredCell ? [self.lastConfiguredCell feedHeight] : 100.0; + return self.lastConfiguredCell ? [self.lastConfiguredCell feedHeight] + : kMinimumFeedCellHeight; } @end @@ -56,7 +62,6 @@ if (_discoverFeed == discoverFeed) { return; } - [_discoverFeed.view removeFromSuperview]; _discoverFeed = discoverFeed; if (discoverFeed) { UIView* discoverView = discoverFeed.view; @@ -78,7 +83,7 @@ - (CGFloat)feedHeight { UICollectionView* feedView; if (!self.discoverFeed) { - return 0; + return kMinimumFeedCellHeight; } // TODO(crbug.com/1092900): Make this more robust. Will require // the provider to expose the feed as a UICollectionViewController. @@ -87,7 +92,9 @@ feedView = static_cast<UICollectionView*>(view); } } - return feedView.contentSize.height; + // In order for the Feed loading spinner to be displayed, the minimum feed + // height must be kMinimumFeedCellHeight. + return fmax(feedView.contentSize.height, kMinimumFeedCellHeight); } @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 949bb41c..0623e19 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -66,7 +66,10 @@ #include "ios/chrome/grit/ios_strings.h" #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/discover_feed/discover_feed_provider.h" -#include "ui/base/l10n/l10n_util_mac.h" +#import "ios/web/public/navigation/navigation_item.h" +#import "ios/web/public/navigation/navigation_manager.h" +#import "ios/web/public/web_state.h" +#import "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -211,8 +214,20 @@ self.metricsRecorder = [[ContentSuggestionsMetricsRecorder alloc] init]; self.metricsRecorder.delegate = self.contentSuggestionsMediator; + // Offset to maintain Discover feed scroll position. + CGFloat offset = 0; + if (IsDiscoverFeedEnabled() && contentSuggestionsEnabled) { + web::NavigationManager* navigationManager = + self.webState->GetNavigationManager(); + web::NavigationItem* item = navigationManager->GetVisibleItem(); + if (item) { + offset = item->GetPageDisplayState().scroll_state().content_offset().y; + } + } + self.suggestionsViewController = [[ContentSuggestionsViewController alloc] - initWithStyle:CollectionViewControllerStyleDefault]; + initWithStyle:CollectionViewControllerStyleDefault + offset:offset]; [self.suggestionsViewController setDataSource:self.contentSuggestionsMediator]; self.suggestionsViewController.suggestionCommandHandler = self.NTPMediator;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.h index fc07cf067..57bf1ed50 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.h
@@ -13,6 +13,14 @@ // is pinned to the top of the collection. @interface ContentSuggestionsLayout : MDCCollectionViewFlowLayout +// The cached scroll position of the NTP. +@property(nonatomic, assign) CGFloat offset; + +// Creates layout with |offset| as additional height. Allows the view's height +// to be increased enough to maintain the scroll position. Only needed if +// Discover feed is enabled. +- (instancetype)initWithOffset:(CGFloat)offset; + @end #endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_LAYOUT_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm index 1237ab8..12d43807 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm
@@ -16,6 +16,13 @@ @implementation ContentSuggestionsLayout +- (instancetype)initWithOffset:(CGFloat)offset { + if (self = [super init]) { + _offset = offset; + } + return self; +} + - (CGSize)collectionViewContentSize { CGFloat collectionViewHeight = self.collectionView.bounds.size.height; CGFloat headerHeight = [self firstHeaderHeight]; @@ -40,6 +47,11 @@ CGSize contentSize = [super collectionViewContentSize]; if (contentSize.height < minimumHeight) { contentSize.height = minimumHeight; + // Increases the minimum height to allow the page to scroll to the cached + // position. + if (self.offset > 0) { + contentSize.height += self.offset; + } } return contentSize; }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h index 97bf153..f0bc509a 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h
@@ -34,8 +34,10 @@ : CollectionViewController <ContentSuggestionsCollectionControlling, ContentSuggestionsConsumer> +// Inits view controller with |offset| to maintain scroll position if needed. +// Offset is only required if Discover feed is enabled. - (instancetype)initWithStyle:(CollectionViewControllerStyle)style - NS_DESIGNATED_INITIALIZER; + offset:(CGFloat)offset NS_DESIGNATED_INITIALIZER; - (instancetype)initWithLayout:(UICollectionViewLayout*)layout style:(CollectionViewControllerStyle)style
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 08fb184..0b89460 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -71,6 +71,12 @@ // The DiscoverFeedVC that might be displayed by this VC. @property(nonatomic, weak) UIViewController* discoverFeedVC; +// The FeedView CollectionView contained by discoverFeedVC. +@property(nonatomic, strong) UICollectionView* feedView; + +// Navigation offset applied to the layout height to maintain the scroll +// position, since the feed height is dynamic. +@property(nonatomic) CGFloat offset; @end @@ -88,8 +94,11 @@ #pragma mark - Lifecycle -- (instancetype)initWithStyle:(CollectionViewControllerStyle)style { - UICollectionViewLayout* layout = [[ContentSuggestionsLayout alloc] init]; +- (instancetype)initWithStyle:(CollectionViewControllerStyle)style + offset:(CGFloat)offset { + _offset = offset; + UICollectionViewLayout* layout = + [[ContentSuggestionsLayout alloc] initWithOffset:offset]; self = [super initWithLayout:layout style:style]; if (self) { _collectionUpdater = [[ContentSuggestionsCollectionUpdater alloc] init]; @@ -288,6 +297,13 @@ // Resize the collection as it might have been rotated while not being // presented (e.g. rotation on stack view). [self updateConstraints]; + // Remove forced height if it was already applied, since the scroll position + // was already maintained. + if (self.offset > 0) { + ContentSuggestionsLayout* layout = static_cast<ContentSuggestionsLayout*>( + self.collectionView.collectionViewLayout); + layout.offset = 0; + } } - (void)viewDidLayoutSubviews { @@ -396,15 +412,40 @@ if ([self.collectionUpdater isDiscoverItem:[self.collectionViewModel itemTypeForIndexPath:indexPath]]) { + // TODO(crbug.com/1114792): Remove DiscoverItem logic once we stop + // containing the DiscoverFeed inside a cell. ContentSuggestionsDiscoverItem* discoverFeedItem = static_cast<ContentSuggestionsDiscoverItem*>(item); - self.discoverFeedVC = discoverFeedItem.discoverFeed; - if (self.discoverFeedVC) { - [self addChildViewController:self.discoverFeedVC]; - UICollectionViewCell* cell = [super collectionView:collectionView - cellForItemAtIndexPath:indexPath]; - [self.discoverFeedVC didMoveToParentViewController:self]; - return cell; + UIViewController* newFeedViewController = discoverFeedItem.discoverFeed; + + if (newFeedViewController != self.discoverFeedVC) { + // If previous VC is not nil, remove it from the view hierarchy. + if (self.discoverFeedVC) { + [self.discoverFeedVC willMoveToParentViewController:nil]; + [self.discoverFeedVC.view removeFromSuperview]; + [self.discoverFeedVC removeFromParentViewController]; + } + + // If new VC is not nil, add it to the view hierarchy. + if (newFeedViewController) { + [self addChildViewController:newFeedViewController]; + UICollectionViewCell* cell = [super collectionView:collectionView + cellForItemAtIndexPath:indexPath]; + [newFeedViewController didMoveToParentViewController:self]; + + // Observe its CollectionView for contentSize changes. + for (UIView* view in newFeedViewController.view.subviews) { + if ([view isKindOfClass:[UICollectionView class]]) { + self.feedView = static_cast<UICollectionView*>(view); + } + } + [self.feedView addObserver:self + forKeyPath:@"contentSize" + options:0 + context:nil]; + self.discoverFeedVC = newFeedViewController; + return cell; + } } } @@ -729,6 +770,26 @@ return YES; } +#pragma mark - ContentSuggestionsConsumer + +- (void)setContentSuggestionsEnabled:(BOOL)enabled { + _contentSuggestionsEnabled = enabled; +} + +#pragma mark - NSKeyValueObserving + +// TODO(crbug.com/1114792): Remove once we stop containing the DiscoverFeed +// inside a cell. +- (void)observeValueForKeyPath:(NSString*)keyPath + ofObject:(id)object + change:(NSDictionary*)change + context:(void*)context { + if (object == self.feedView && [keyPath isEqualToString:@"contentSize"]) { + // Reload the CollectionView data to adjust to the new Feed height. + [self.collectionView reloadData]; + } +} + #pragma mark - Private - (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer { @@ -819,10 +880,4 @@ [self.discoverFeedMenuHandler openDiscoverFeedMenu:menuButton]; } -#pragma mark - ContentSuggestionsConsumer - -- (void)setContentSuggestionsEnabled:(BOOL)enabled { - _contentSuggestionsEnabled = enabled; -} - @end
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm index 3ccf22f7..8c5d3b2 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -373,6 +373,14 @@ return [self.delegate locationBarModel]; } +- (UIResponder<UITextInput>*)scribbleForwardingTarget { + return self.omniboxCoordinator.scribbleInput; +} + +- (void)locationBarRequestScribbleTargetFocus { + [self.omniboxCoordinator focusOmniboxForScribble]; +} + #pragma mark - LocationBarViewControllerDelegate - (void)locationBarSteadyViewTapped {
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h index 32f36611..16d06a1 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
@@ -30,6 +30,12 @@ // Notifies the delegate about a tap on the Copy entry in the editing menu. - (void)locationBarCopyTapped; +// Returns the target that location bar scribble events should be forwarded to. +- (UIResponder<UITextInput>*)scribbleForwardingTarget; + +// Request the scribble target to be focused. +- (void)locationBarRequestScribbleTargetFocus; + @end // The view controller displaying the location bar. Manages the two states of
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm index a403071..f54a3df 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -48,8 +48,18 @@ // off mode for the badge view. const double kFullscreenProgressBadgeViewThreshold = 0.85; +// Identifier for the omnibox embedded in this location bar as a scribble +// element. +const NSString* kScribbleOmniboxElementId = @"omnibox"; + } // namespace +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 +@interface LocationBarViewController (Scribble) < + UIIndirectScribbleInteractionDelegate> +@end +#endif // defined(__IPHONE14_0) + @interface LocationBarViewController () // The injected edit view. @property(nonatomic, strong) UIView* editView; @@ -192,6 +202,14 @@ action:@selector(showLongPressMenu:)]; [_locationBarSteadyView.locationButton addGestureRecognizer:recognizer]; +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + if (@available(iOS 14, *)) { + UIIndirectScribbleInteraction* scribbleInteraction = + [[UIIndirectScribbleInteraction alloc] initWithDelegate:self]; + [_locationBarSteadyView addInteraction:scribbleInteraction]; + } +#endif // #if defined(__IPHONE_14_0) + DCHECK(self.editView) << "The edit view must be set at this point"; [self.view addSubview:self.editView]; @@ -386,6 +404,53 @@ return targetOffset; } +#pragma mark - UIIndirectScribbleInteractionDelegate + +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + +- (void)indirectScribbleInteraction:(UIIndirectScribbleInteraction*)interaction + requestElementsInRect:(CGRect)rect + completion: + (void (^)(NSArray<UIScribbleElementIdentifier>* + elements))completion + API_AVAILABLE(ios(14.0)) { + completion(@[ kScribbleOmniboxElementId ]); +} + +- (BOOL)indirectScribbleInteraction:(UIIndirectScribbleInteraction*)interaction + isElementFocused: + (UIScribbleElementIdentifier)elementIdentifier + API_AVAILABLE(ios(14.0)) { + DCHECK(elementIdentifier == kScribbleOmniboxElementId); + return self.delegate.scribbleForwardingTarget.isFirstResponder; +} + +- (CGRect) + indirectScribbleInteraction:(UIIndirectScribbleInteraction*)interaction + frameForElement:(UIScribbleElementIdentifier)elementIdentifier + API_AVAILABLE(ios(14.0)) { + DCHECK(elementIdentifier == kScribbleOmniboxElementId); + + // Imitate the entire location bar being scribblable. + return self.view.bounds; +} + +- (void)indirectScribbleInteraction:(UIIndirectScribbleInteraction*)interaction + focusElementIfNeeded: + (UIScribbleElementIdentifier)elementIdentifier + referencePoint:(CGPoint)focusReferencePoint + completion: + (void (^)(UIResponder<UITextInput>* focusedInput)) + completion API_AVAILABLE(ios(14.0)) { + if (!self.delegate.scribbleForwardingTarget.isFirstResponder) { + [self.delegate locationBarRequestScribbleTargetFocus]; + } + + completion(self.delegate.scribbleForwardingTarget); +} + +#endif // defined(__IPHONE_14_0) + #pragma mark - private - (void)locationBarSteadyViewTapped {
diff --git a/ios/chrome/browser/ui/menu/BUILD.gn b/ios/chrome/browser/ui/menu/BUILD.gn index 2d86946..ab8d181 100644 --- a/ios/chrome/browser/ui/menu/BUILD.gn +++ b/ios/chrome/browser/ui/menu/BUILD.gn
@@ -13,6 +13,13 @@ configs += [ "//build/config/compiler:enable_arc" ] deps = [ "resources:copy_link_url", + "resources:delete", + "resources:edit", + "resources:open_in_incognito", + "resources:open_in_new_tab", + "resources:open_new_window", + "resources:remove", + "resources:share", "//base", "//ios/chrome/app/strings", "//ios/chrome/browser/ui/commands", @@ -32,6 +39,13 @@ deps = [ ":menu", "resources:copy_link_url", + "resources:delete", + "resources:edit", + "resources:open_in_incognito", + "resources:open_in_new_tab", + "resources:open_new_window", + "resources:remove", + "resources:share", "//base", "//base/test:test_support", "//ios/chrome/app/strings",
diff --git a/ios/chrome/browser/ui/menu/action_factory.h b/ios/chrome/browser/ui/menu/action_factory.h index 4a9d4b4..e39cbec9 100644 --- a/ios/chrome/browser/ui/menu/action_factory.h +++ b/ios/chrome/browser/ui/menu/action_factory.h
@@ -55,6 +55,11 @@ // needs to open a URL in a new tab. - (UIAction*)actionToOpenInNewTabWithBlock:(ProceduralBlock)block; +// Creates a UIAction instance whose title and icon are configured for opening +// multiple URLs in new tabs. When triggered, the action will invoke the |block| +// which needs to open URLs in new tabs. +- (UIAction*)actionToOpenAllTabsWithBlock:(ProceduralBlock)block; + // Creates a UIAction instance configured for opening the |URL| in a new // incognito tab and which will invoke the given |completion| block after // execution. @@ -81,6 +86,10 @@ // which will invoke the given edit |block| when executed. - (UIAction*)actionToEditWithBlock:(ProceduralBlock)block; +// Creates a UIAction instance configured for hiding which will invoke +// the given hiding |block| when executed. +- (UIAction*)actionToHideWithBlock:(ProceduralBlock)block; + @end #endif // IOS_CHROME_BROWSER_UI_MENU_ACTION_FACTORY_H_
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm index dfa2ef1..13bb8ee 100644 --- a/ios/chrome/browser/ui/menu/action_factory.mm +++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -71,7 +71,7 @@ - (UIAction*)actionToShareWithBlock:(ProceduralBlock)block { return [self actionWithTitle:l10n_util::GetNSString(IDS_IOS_SHARE_BUTTON_LABEL) - image:[UIImage systemImageNamed:@"square.and.arrow.up"] + image:[UIImage imageNamed:@"share"] type:MenuActionType::Share block:block]; } @@ -79,7 +79,7 @@ - (UIAction*)actionToDeleteWithBlock:(ProceduralBlock)block { UIAction* action = [self actionWithTitle:l10n_util::GetNSString(IDS_IOS_DELETE_ACTION_TITLE) - image:[UIImage systemImageNamed:@"trash"] + image:[UIImage imageNamed:@"delete"] type:MenuActionType::Delete block:block]; action.attributes = UIMenuElementAttributesDestructive; @@ -102,11 +102,19 @@ - (UIAction*)actionToOpenInNewTabWithBlock:(ProceduralBlock)block { return [self actionWithTitle:l10n_util::GetNSString( IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB) - image:[UIImage systemImageNamed:@"plus"] + image:[UIImage imageNamed:@"open_in_new_tab"] type:MenuActionType::OpenInNewTab block:block]; } +- (UIAction*)actionToOpenAllTabsWithBlock:(ProceduralBlock)block { + return [self actionWithTitle:l10n_util::GetNSString( + IDS_IOS_CONTENT_CONTEXT_OPEN_ALL_LINKS) + image:[UIImage systemImageNamed:@"plus"] + type:MenuActionType::OpenAllInNewTabs + block:block]; +} + - (UIAction*)actionToOpenInNewIncognitoTabWithURL:(const GURL)URL completion:(ProceduralBlock)completion { UrlLoadParams params = UrlLoadParams::InNewTab(URL); @@ -124,7 +132,7 @@ - (UIAction*)actionToOpenInNewIncognitoTabWithBlock:(ProceduralBlock)block { return [self actionWithTitle:l10n_util::GetNSString( IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE) - image:nil + image:[UIImage imageNamed:@"open_in_incognito"] type:MenuActionType::OpenInNewIncognitoTab block:block]; } @@ -137,7 +145,7 @@ NSUserActivity* activity = ActivityToLoadURL(activityOrigin, URL); return [self actionWithTitle:l10n_util::GetNSString( IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW) - image:[UIImage systemImageNamed:@"plus.square"] + image:[UIImage imageNamed:@"open_new_window"] type:MenuActionType::OpenInNewWindow block:^{ [windowOpener openNewWindowWithActivity:activity]; @@ -150,7 +158,7 @@ - (UIAction*)actionToRemoveWithBlock:(ProceduralBlock)block { UIAction* action = [self actionWithTitle:l10n_util::GetNSString(IDS_IOS_REMOVE_ACTION_TITLE) - image:[UIImage systemImageNamed:@"trash"] + image:[UIImage imageNamed:@"remove"] type:MenuActionType::Remove block:block]; action.attributes = UIMenuElementAttributesDestructive; @@ -159,9 +167,20 @@ - (UIAction*)actionToEditWithBlock:(ProceduralBlock)block { return [self actionWithTitle:l10n_util::GetNSString(IDS_IOS_EDIT_ACTION_TITLE) - image:nil + image:[UIImage imageNamed:@"edit"] type:MenuActionType::Edit block:block]; } +- (UIAction*)actionToHideWithBlock:(ProceduralBlock)block { + UIAction* action = + [self actionWithTitle:l10n_util::GetNSString( + IDS_IOS_RECENT_TABS_HIDE_MENU_OPTION) + image:nil + type:MenuActionType::Hide + block:block]; + action.attributes = UIMenuElementAttributesDestructive; + return action; +} + @end
diff --git a/ios/chrome/browser/ui/menu/action_factory_unittest.mm b/ios/chrome/browser/ui/menu/action_factory_unittest.mm index 56ca448..de02bf6a 100644 --- a/ios/chrome/browser/ui/menu/action_factory_unittest.mm +++ b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
@@ -116,7 +116,7 @@ [[ActionFactory alloc] initWithBrowser:test_browser_.get() scenario:kTestMenuScenario]; - UIImage* expectedImage = [UIImage systemImageNamed:@"square.and.arrow.up"]; + UIImage* expectedImage = [UIImage imageNamed:@"share"]; NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_SHARE_BUTTON_LABEL); @@ -135,7 +135,7 @@ [[ActionFactory alloc] initWithBrowser:test_browser_.get() scenario:kTestMenuScenario]; - UIImage* expectedImage = [UIImage systemImageNamed:@"trash"]; + UIImage* expectedImage = [UIImage imageNamed:@"delete"]; NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_DELETE_ACTION_TITLE); @@ -157,7 +157,7 @@ GURL testURL = GURL("https://example.com"); - UIImage* expectedImage = [UIImage systemImageNamed:@"plus"]; + UIImage* expectedImage = [UIImage imageNamed:@"open_in_new_tab"]; NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB); @@ -182,18 +182,19 @@ GURL testURL = GURL("https://example.com"); + UIImage* expectedImage = [UIImage imageNamed:@"open_in_incognito"]; NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_OPEN_IN_INCOGNITO_ACTION_TITLE); UIAction* actionWithURL = [factory actionToOpenInNewIncognitoTabWithURL:testURL completion:nil]; EXPECT_TRUE([expectedTitle isEqualToString:actionWithURL.title]); - EXPECT_FALSE(!!actionWithURL.image); + EXPECT_EQ(expectedImage, actionWithURL.image); UIAction* actionWithBlock = [factory actionToOpenInNewIncognitoTabWithBlock:nil]; EXPECT_TRUE([expectedTitle isEqualToString:actionWithBlock.title]); - EXPECT_FALSE(!!actionWithBlock.image); + EXPECT_EQ(expectedImage, actionWithBlock.image); } } @@ -206,7 +207,7 @@ GURL testURL = GURL("https://example.com"); - UIImage* expectedImage = [UIImage systemImageNamed:@"plus.square"]; + UIImage* expectedImage = [UIImage imageNamed:@"open_new_window"]; NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPENINNEWWINDOW); @@ -220,6 +221,25 @@ } } +// Tests that the remove action has the right title and image. +TEST_F(ActionFactoryTest, RemoveAction) { + if (@available(iOS 13.0, *)) { + ActionFactory* factory = + [[ActionFactory alloc] initWithBrowser:test_browser_.get() + scenario:kTestMenuScenario]; + + UIImage* expectedImage = [UIImage imageNamed:@"remove"]; + NSString* expectedTitle = + l10n_util::GetNSString(IDS_IOS_REMOVE_ACTION_TITLE); + + UIAction* action = [factory actionToRemoveWithBlock:^{ + }]; + + EXPECT_TRUE([expectedTitle isEqualToString:action.title]); + EXPECT_EQ(expectedImage, action.image); + } +} + // Tests that the edit action has the right title and image. TEST_F(ActionFactoryTest, EditAction) { if (@available(iOS 13.0, *)) { @@ -227,12 +247,50 @@ [[ActionFactory alloc] initWithBrowser:test_browser_.get() scenario:kTestMenuScenario]; + UIImage* expectedImage = [UIImage imageNamed:@"edit"]; NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_EDIT_ACTION_TITLE); UIAction* action = [factory actionToEditWithBlock:^{ }]; EXPECT_TRUE([expectedTitle isEqualToString:action.title]); + EXPECT_EQ(expectedImage, action.image); + } +} + +// Tests that the Open All Tabs action has the right title and image. +TEST_F(ActionFactoryTest, openAllTabsAction) { + if (@available(iOS 13.0, *)) { + ActionFactory* factory = + [[ActionFactory alloc] initWithBrowser:test_browser_.get() + scenario:kTestMenuScenario]; + + UIImage* expectedImage = [UIImage systemImageNamed:@"plus"]; + NSString* expectedTitle = + l10n_util::GetNSString(IDS_IOS_CONTENT_CONTEXT_OPEN_ALL_LINKS); + + UIAction* action = [factory actionToOpenAllTabsWithBlock:^{ + }]; + + EXPECT_TRUE([expectedTitle isEqualToString:action.title]); + EXPECT_EQ(expectedImage, action.image); + } +} + +// Tests that the hide action has the right title and image. +TEST_F(ActionFactoryTest, hideAction) { + if (@available(iOS 13.0, *)) { + ActionFactory* factory = + [[ActionFactory alloc] initWithBrowser:test_browser_.get() + scenario:kTestMenuScenario]; + + NSString* expectedTitle = + l10n_util::GetNSString(IDS_IOS_RECENT_TABS_HIDE_MENU_OPTION); + + UIAction* action = [factory actionToHideWithBlock:^{ + }]; + + EXPECT_TRUE([expectedTitle isEqualToString:action.title]); EXPECT_EQ(nil, action.image); } }
diff --git a/ios/chrome/browser/ui/menu/menu_action_type.h b/ios/chrome/browser/ui/menu/menu_action_type.h index b97e8c2..9a19fa2 100644 --- a/ios/chrome/browser/ui/menu/menu_action_type.h +++ b/ios/chrome/browser/ui/menu/menu_action_type.h
@@ -17,7 +17,9 @@ Remove = 5, Edit = 6, Share = 7, - kMaxValue = Share + OpenAllInNewTabs = 8, + Hide = 9, + kMaxValue = Hide }; #endif // IOS_CHROME_BROWSER_UI_MENU_MENU_ACTION_TYPE_H_
diff --git a/ios/chrome/browser/ui/menu/menu_histograms.h b/ios/chrome/browser/ui/menu/menu_histograms.h index 2650b514..b7c1ef5 100644 --- a/ios/chrome/browser/ui/menu/menu_histograms.h +++ b/ios/chrome/browser/ui/menu/menu_histograms.h
@@ -14,7 +14,8 @@ kReadingListEntry = 2, kRecentTabsEntry = 3, kContentSuggestionsEntry = 4, - kMaxValue = kContentSuggestionsEntry + kRecentTabsHeader = 5, + kMaxValue = kRecentTabsHeader }; // Records a menu shown histogram metric for the |scenario|.
diff --git a/ios/chrome/browser/ui/menu/menu_histograms.mm b/ios/chrome/browser/ui/menu/menu_histograms.mm index 1e991cd3..47a5d289 100644 --- a/ios/chrome/browser/ui/menu/menu_histograms.mm +++ b/ios/chrome/browser/ui/menu/menu_histograms.mm
@@ -23,6 +23,8 @@ "Mobile.ContextMenu.ReadingListEntry.Actions"; const char RecentTabsEntryActionsHistogram[] = "Mobile.ContextMenu.RecentTabsEntry.Actions"; +const char RecentTabsHeaderActionsHistogram[] = + "Mobile.ContextMenu.RecentTabsHeader.Actions"; const char ContentSuggestionsEntryActionsHistogram[] = "Mobile.ContextMenu.ContentSuggestionsEntry.Actions"; } // namespace @@ -41,6 +43,8 @@ return ReadingListEntryActionsHistogram; case MenuScenario::kRecentTabsEntry: return RecentTabsEntryActionsHistogram; + case MenuScenario::kRecentTabsHeader: + return RecentTabsHeaderActionsHistogram; case MenuScenario::kContentSuggestionsEntry: return ContentSuggestionsEntryActionsHistogram; }
diff --git a/ios/chrome/browser/ui/menu/resources/BUILD.gn b/ios/chrome/browser/ui/menu/resources/BUILD.gn index fc0ae5e..f490f62 100644 --- a/ios/chrome/browser/ui/menu/resources/BUILD.gn +++ b/ios/chrome/browser/ui/menu/resources/BUILD.gn
@@ -11,3 +11,59 @@ "copy_link_url.imageset/copy_link_url@3x.png", ] } + +imageset("delete") { + sources = [ + "delete.imageset/Contents.json", + "delete.imageset/delete@2x.png", + "delete.imageset/delete@3x.png", + ] +} + +imageset("edit") { + sources = [ + "edit.imageset/Contents.json", + "edit.imageset/edit@2x.png", + "edit.imageset/edit@3x.png", + ] +} + +imageset("open_in_incognito") { + sources = [ + "open_in_incognito.imageset/Contents.json", + "open_in_incognito.imageset/open_in_incognito@2x.png", + "open_in_incognito.imageset/open_in_incognito@3x.png", + ] +} + +imageset("open_in_new_tab") { + sources = [ + "open_in_new_tab.imageset/Contents.json", + "open_in_new_tab.imageset/open_in_new_tab@2x.png", + "open_in_new_tab.imageset/open_in_new_tab@3x.png", + ] +} + +imageset("open_new_window") { + sources = [ + "open_new_window.imageset/Contents.json", + "open_new_window.imageset/open_new_window@2x.png", + "open_new_window.imageset/open_new_window@3x.png", + ] +} + +imageset("remove") { + sources = [ + "remove.imageset/Contents.json", + "remove.imageset/remove@2x.png", + "remove.imageset/remove@3x.png", + ] +} + +imageset("share") { + sources = [ + "share.imageset/Contents.json", + "share.imageset/share@2x.png", + "share.imageset/share@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/menu/resources/delete.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/delete.imageset/Contents.json new file mode 100644 index 0000000..358e495 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/delete.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "delete@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "delete@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/delete.imageset/delete@2x.png b/ios/chrome/browser/ui/menu/resources/delete.imageset/delete@2x.png new file mode 100644 index 0000000..ed846e76 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/delete.imageset/delete@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/delete.imageset/delete@3x.png b/ios/chrome/browser/ui/menu/resources/delete.imageset/delete@3x.png new file mode 100644 index 0000000..2eacd069 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/delete.imageset/delete@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/edit.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/edit.imageset/Contents.json new file mode 100644 index 0000000..fbf2220d --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/edit.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "edit@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "edit@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/edit.imageset/edit@2x.png b/ios/chrome/browser/ui/menu/resources/edit.imageset/edit@2x.png new file mode 100644 index 0000000..d7a86fb --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/edit.imageset/edit@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/edit.imageset/edit@3x.png b/ios/chrome/browser/ui/menu/resources/edit.imageset/edit@3x.png new file mode 100644 index 0000000..b6e63e2 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/edit.imageset/edit@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/Contents.json new file mode 100644 index 0000000..18b6fc2 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "open_in_incognito@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "open_in_incognito@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/open_in_incognito@2x.png b/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/open_in_incognito@2x.png new file mode 100644 index 0000000..e02a3d1 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/open_in_incognito@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/open_in_incognito@3x.png b/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/open_in_incognito@3x.png new file mode 100644 index 0000000..7e6db40 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_in_incognito.imageset/open_in_incognito@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/Contents.json new file mode 100644 index 0000000..51cbfcf --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "open_in_new_tab@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "open_in_new_tab@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/open_in_new_tab@2x.png b/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/open_in_new_tab@2x.png new file mode 100644 index 0000000..41c8b83 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/open_in_new_tab@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/open_in_new_tab@3x.png b/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/open_in_new_tab@3x.png new file mode 100644 index 0000000..5636c7d --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_in_new_tab.imageset/open_in_new_tab@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/Contents.json new file mode 100644 index 0000000..9fc7b3f2 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "open_new_window@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "open_new_window@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/open_new_window@2x.png b/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/open_new_window@2x.png new file mode 100644 index 0000000..358f5c87 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/open_new_window@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/open_new_window@3x.png b/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/open_new_window@3x.png new file mode 100644 index 0000000..9899f7e --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/open_new_window.imageset/open_new_window@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/remove.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/remove.imageset/Contents.json new file mode 100644 index 0000000..2fd94f42 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/remove.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "remove@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "remove@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/remove.imageset/remove@2x.png b/ios/chrome/browser/ui/menu/resources/remove.imageset/remove@2x.png new file mode 100644 index 0000000..20e64b9 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/remove.imageset/remove@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/remove.imageset/remove@3x.png b/ios/chrome/browser/ui/menu/resources/remove.imageset/remove@3x.png new file mode 100644 index 0000000..8f563b91 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/remove.imageset/remove@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/share.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/share.imageset/Contents.json new file mode 100644 index 0000000..ba02f71 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/share.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "share@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "share@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/menu/resources/share.imageset/share@2x.png b/ios/chrome/browser/ui/menu/resources/share.imageset/share@2x.png new file mode 100644 index 0000000..8a97a5b4 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/share.imageset/share@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/share.imageset/share@3x.png b/ios/chrome/browser/ui/menu/resources/share.imageset/share@3x.png new file mode 100644 index 0000000..7aa4150 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/share.imageset/share@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_container_view.h b/ios/chrome/browser/ui/omnibox/omnibox_container_view.h index ef0d041..09ab904 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_container_view.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_container_view.h
@@ -37,6 +37,9 @@ // Sets the alpha level of the leading image view. - (void)setLeadingImageAlpha:(CGFloat)alpha; +// Sets the scale of the leading image view. +- (void)setLeadingImageScale:(CGFloat)scaleValue; + // Asks the container view to attch any layout guides to its views. - (void)attachLayoutGuides;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm b/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm index 73df915..047f8813 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm
@@ -117,6 +117,10 @@ self.leadingImageView.alpha = alpha; } +- (void)setLeadingImageScale:(CGFloat)scaleValue { + self.leadingImageView.transform = + CGAffineTransformMakeScale(scaleValue, scaleValue); +} #pragma mark - private - (void)setupLeadingImageViewWithTint:(UIColor*)iconTint {
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h index bb7f386..2b779cbe 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h
@@ -35,6 +35,7 @@ - (void)start; // Stop this coordinator. - (void)stop; + // Indicates if the omnibox is the first responder. - (BOOL)isOmniboxFirstResponder; // Inserts text to the omnibox without triggering autocomplete. @@ -45,6 +46,12 @@ - (void)updateOmniboxState; // Use this method to make the omnibox first responder. - (void)focusOmnibox; + +// Prepare the omnibox for scribbling. +- (void)focusOmniboxForScribble; +// Target input for scribble targeting the omnibox. +- (UIResponder<UITextInput>*)scribbleInput; + // Use this method to resign |textField| as the first responder. - (void)endEditing; // Creates a child popup coordinator. The popup coordinator is linked to the
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm index a8f4591..e015f55 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm
@@ -189,6 +189,17 @@ return self.viewController; } +#pragma mark Scribble + +- (void)focusOmniboxForScribble { + [self.textField becomeFirstResponder]; + [self.viewController prepareOmniboxForScribble]; +} + +- (UIResponder<UITextInput>*)scribbleInput { + return self.viewController.textField; +} + #pragma mark - OmniboxViewControllerDelegate - (void)omniboxViewControllerTextInputModeDidChange:
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h index aa55cdd..940af56 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h
@@ -57,6 +57,12 @@ - (instancetype)initWithIncognito:(BOOL)isIncognito; - (void)setTextChangeDelegate:(OmniboxTextChangeDelegate*)textChangeDelegate; + +// Hides extra chrome, i.e. attributed text, and clears. +- (void)prepareOmniboxForScribble; +// Restores the chrome post-scribble. +- (void)cleanupOmniboxAfterScribble; + @end #endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm index 6f6e05e..0bfb48d 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
@@ -364,7 +364,19 @@ #pragma mark - EditViewAnimatee - (void)setLeadingIconFaded:(BOOL)faded { - [self.view setLeadingImageAlpha:faded ? 0 : 1]; + CATransition* transition = [CATransition animation]; + transition.duration = 0.3; + transition.timingFunction = [CAMediaTimingFunction + functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + transition.type = kCATransitionFade; + [self.view.layer addAnimation:transition forKey:nil]; + if (faded) { + [self.view setLeadingImageAlpha:0]; + [self.view setLeadingImageScale:0]; + } else { + [self.view setLeadingImageAlpha:1]; + [self.view setLeadingImageScale:1]; + } } - (void)setClearButtonFaded:(BOOL)faded {
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm index ff6e9a5..6aed82d 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm
@@ -494,7 +494,7 @@ policy::PolicyMap map; map.Set("test-policy", policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_PLATFORM, - std::make_unique<base::Value>("hello"), nullptr); + base::Value("hello"), nullptr); enterprise_policy_helper->GetPolicyProvider()->UpdateChromePolicy(map); CreateMediatorWithBrowserPolicyConnector(
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index c02514b..7b469f9 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -41,6 +41,7 @@ "//ios/chrome/browser/metrics:metrics_internal", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/tabs", + "//ios/chrome/browser/ui/activity_services", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", @@ -48,6 +49,7 @@ "//ios/chrome/browser/ui/menu", "//ios/chrome/browser/ui/reading_list/context_menu", "//ios/chrome/browser/ui/reading_list/resources:distillation_fail_new", + "//ios/chrome/browser/ui/sharing", "//ios/chrome/browser/ui/side_swipe", "//ios/chrome/browser/ui/table_view", "//ios/chrome/browser/ui/table_view:feature_flags",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm index 321ff7c6a..fce4af5e 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_coordinator.mm
@@ -19,6 +19,7 @@ #import "ios/chrome/browser/metrics/new_tab_page_uma.h" #include "ios/chrome/browser/reading_list/offline_url_utils.h" #include "ios/chrome/browser/reading_list/reading_list_model_factory.h" +#import "ios/chrome/browser/ui/activity_services/activity_params.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/menu/action_factory.h" @@ -33,6 +34,7 @@ #import "ios/chrome/browser/ui/reading_list/reading_list_mediator.h" #import "ios/chrome/browser/ui/reading_list/reading_list_menu_provider.h" #import "ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.h" +#import "ios/chrome/browser/ui/sharing/sharing_coordinator.h" #import "ios/chrome/browser/ui/table_view/feature_flags.h" #import "ios/chrome/browser/ui/table_view/table_view_animator.h" #import "ios/chrome/browser/ui/table_view/table_view_navigation_controller.h" @@ -74,14 +76,12 @@ @property(nonatomic, strong) ReadingListContextMenuCoordinator* contextMenuCoordinator; +// Coordinator in charge of handling sharing use cases. +@property(nonatomic, strong) SharingCoordinator* sharingCoordinator; + @end @implementation ReadingListCoordinator -@synthesize started = _started; -@synthesize mediator = _mediator; -@synthesize navigationController = _navigationController; -@synthesize tableViewController = _tableViewController; -@synthesize contextMenuCoordinator = _contextMenuCoordinator; #pragma mark - Accessors @@ -187,6 +187,10 @@ completion:nil]; self.tableViewController = nil; self.navigationController = nil; + + [self.sharingCoordinator stop]; + self.sharingCoordinator = nil; + [super stop]; self.started = NO; } @@ -420,7 +424,9 @@ #pragma mark - ReadingListMenuProvider - (UIContextMenuConfiguration*)contextMenuConfigurationForItem: - (id<ReadingListListItem>)item API_AVAILABLE(ios(13.0)) { + (id<ReadingListListItem>)item + withView:(UIView*)view + API_AVAILABLE(ios(13.0)) { __weak id<ReadingListListItemAccessibilityDelegate> accessibilityDelegate = self.tableViewController; __weak __typeof(self) weakSelf = self; @@ -470,6 +476,12 @@ [menuElements addObject:[actionFactory actionToCopyURL:item.entryURL]]; + [menuElements addObject:[actionFactory actionToShareWithBlock:^{ + [weakSelf shareURL:item.entryURL + title:item.title + fromView:view]; + }]]; + [menuElements addObject:[actionFactory actionToDeleteWithBlock:^{ [accessibilityDelegate deleteItem:item]; }]]; @@ -483,4 +495,23 @@ actionProvider:actionProvider]; } +#pragma mark - Private + +// Triggers the URL sharing flow for the given |URL| and |title|, with the +// origin |view| representing the UI component for that URL. +- (void)shareURL:(const GURL&)URL + title:(NSString*)title + fromView:(UIView*)view { + ActivityParams* params = + [[ActivityParams alloc] initWithURL:URL + title:title + scenario:ActivityScenario::ReadingListEntry]; + self.sharingCoordinator = [[SharingCoordinator alloc] + initWithBaseViewController:self.tableViewController + browser:self.browser + params:params + originView:view]; + [self.sharingCoordinator start]; +} + @end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_menu_provider.h b/ios/chrome/browser/ui/reading_list/reading_list_menu_provider.h index 2e24311..d9c3016e 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_menu_provider.h +++ b/ios/chrome/browser/ui/reading_list/reading_list_menu_provider.h
@@ -10,9 +10,12 @@ // Protocol for instances that will provide menus to ReadingList components. @protocol ReadingListMenuProvider -// Creates a context menu configuration instance for the given |item|. +// Creates a context menu configuration instance for the given |item| and it's +// corresponding |view|. - (UIContextMenuConfiguration*)contextMenuConfigurationForItem: - (id<ReadingListListItem>)item API_AVAILABLE(ios(13.0)); + (id<ReadingListListItem>)item + withView:(UIView*)view + API_AVAILABLE(ios(13.0)); @end
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm index da91a67..2e4092a 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -318,7 +318,9 @@ return [self.menuProvider contextMenuConfigurationForItem:[self.tableViewModel - itemAtIndexPath:indexPath]]; + itemAtIndexPath:indexPath] + withView:[self.tableView + cellForRowAtIndexPath:indexPath]]; } #pragma mark - TableViewURLDragDataSource
diff --git a/ios/chrome/browser/ui/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/recent_tabs/BUILD.gn index 852dc8b..e1525a07 100644 --- a/ios/chrome/browser/ui/recent_tabs/BUILD.gn +++ b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
@@ -35,6 +35,7 @@ "//ios/chrome/browser/ui/table_view", "//ios/chrome/browser/ui/table_view:feature_flags", "//ios/chrome/browser/ui/util", + "//ios/chrome/browser/ui/util:multiwindow_util", "//ios/chrome/browser/url_loading", "//ios/chrome/browser/web_state_list", "//ui/base",
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm index e4bf98e..90d51bf 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm
@@ -5,7 +5,8 @@ #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" #include "base/ios/block_types.h" -#include "base/mac/foundation_util.h" +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" @@ -19,12 +20,17 @@ #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_presentation_delegate.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_transitioning_delegate.h" +#include "ios/chrome/browser/ui/recent_tabs/synced_sessions.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h" #import "ios/chrome/browser/ui/table_view/feature_flags.h" #import "ios/chrome/browser/ui/table_view/table_view_navigation_controller.h" #import "ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h" +#import "ios/chrome/browser/ui/util/multi_window_support.h" #import "ios/chrome/browser/url_loading/url_loading_browser_agent.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" +#include "ios/chrome/grit/ios_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -41,6 +47,9 @@ TableViewNavigationController* recentTabsNavigationController; @property(nonatomic, strong) RecentTabsTransitioningDelegate* recentTabsTransitioningDelegate; +@property(nonatomic, strong) + RecentTabsTableViewController* recentTabsTableViewController; + @end @implementation RecentTabsCoordinator @@ -51,18 +60,18 @@ - (void)start { // Initialize and configure RecentTabsTableViewController. - RecentTabsTableViewController* recentTabsTableViewController = + self.recentTabsTableViewController = [[RecentTabsTableViewController alloc] init]; - recentTabsTableViewController.browser = self.browser; - recentTabsTableViewController.loadStrategy = self.loadStrategy; + self.recentTabsTableViewController.browser = self.browser; + self.recentTabsTableViewController.loadStrategy = self.loadStrategy; CommandDispatcher* dispatcher = self.browser->GetCommandDispatcher(); id<ApplicationCommands> handler = HandlerForProtocol(dispatcher, ApplicationCommands); - recentTabsTableViewController.handler = handler; - recentTabsTableViewController.presentationDelegate = self; + self.recentTabsTableViewController.handler = handler; + self.recentTabsTableViewController.presentationDelegate = self; if (@available(iOS 13.0, *)) { - recentTabsTableViewController.menuProvider = self; + self.recentTabsTableViewController.menuProvider = self; } // Adds the "Done" button and hooks it up to |stop|. @@ -72,7 +81,7 @@ action:@selector(dismissButtonTapped)]; [dismissButton setAccessibilityIdentifier:kTableViewNavigationDismissButtonId]; - recentTabsTableViewController.navigationItem.rightBarButtonItem = + self.recentTabsTableViewController.navigationItem.rightBarButtonItem = dismissButton; // Initialize and configure RecentTabsMediator. Make sure to use the @@ -84,18 +93,18 @@ self.browser->GetBrowserState()->GetOriginalChromeBrowserState(); // Set the consumer first before calling [self.mediator initObservers] and // then [self.mediator configureConsumer]. - self.mediator.consumer = recentTabsTableViewController; + self.mediator.consumer = self.recentTabsTableViewController; // TODO(crbug.com/845636) : Currently, the image data source must be set // before the mediator starts updating its consumer. Fix this so that order of // calls does not matter. - recentTabsTableViewController.imageDataSource = self.mediator; - recentTabsTableViewController.delegate = self.mediator; + self.recentTabsTableViewController.imageDataSource = self.mediator; + self.recentTabsTableViewController.delegate = self.mediator; [self.mediator initObservers]; [self.mediator configureConsumer]; // Present RecentTabsNavigationController. self.recentTabsNavigationController = [[TableViewNavigationController alloc] - initWithTable:recentTabsTableViewController]; + initWithTable:self.recentTabsTableViewController]; self.recentTabsNavigationController.toolbarHidden = YES; BOOL useCustomPresentation = YES; @@ -104,7 +113,7 @@ [self.recentTabsNavigationController setModalPresentationStyle:UIModalPresentationFormSheet]; self.recentTabsNavigationController.presentationController.delegate = - recentTabsTableViewController; + self.recentTabsTableViewController; useCustomPresentation = NO; } } @@ -118,7 +127,7 @@ setModalPresentationStyle:UIModalPresentationCustom]; } - recentTabsTableViewController.preventUpdates = NO; + self.recentTabsTableViewController.preventUpdates = NO; [self.baseViewController presentViewController:self.recentTabsNavigationController @@ -127,12 +136,7 @@ } - (void)stop { - // TODO(crbug.com/805135): Create RecentTabsLocalCommands?. Remove - // "base/mac/foundation_util.h" import then. - RecentTabsTableViewController* recentTabsTableViewController = - base::mac::ObjCCastStrict<RecentTabsTableViewController>( - self.recentTabsNavigationController.tableViewController); - [recentTabsTableViewController dismissModals]; + [self.recentTabsTableViewController dismissModals]; [self.recentTabsNavigationController dismissViewControllerAnimated:YES completion:self.completion]; @@ -146,8 +150,37 @@ [self stop]; } +#pragma mark - Private + +// Opens all tabs from the given |sectionIdentifier|. +- (void)openAllTabsFromSessionSectionIdentitifer:(NSInteger)sectionIdentifier { + synced_sessions::DistantSession const* session = + [self.recentTabsTableViewController + sessionForSectionIdentifier:sectionIdentifier]; + [self openAllTabsFromSession:session]; +} + #pragma mark - RecentTabsPresentationDelegate +- (void)openAllTabsFromSession:(const synced_sessions::DistantSession*)session { + base::RecordAction(base::UserMetricsAction( + "MobileRecentTabManagerOpenAllTabsFromOtherDevice")); + base::UmaHistogramCounts100( + "Mobile.RecentTabsManager.TotalTabsFromOtherDevicesOpenAll", + session->tabs.size()); + + for (auto const& tab : session->tabs) { + UrlLoadParams params = UrlLoadParams::InNewTab(tab->virtual_url); + params.SetInBackground(YES); + params.web_params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK; + params.load_strategy = self.loadStrategy; + params.in_incognito = self.browser->GetBrowserState()->IsOffTheRecord(); + UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params); + } + + [self showActiveRegularTabFromRecentTabs]; +} + - (void)dismissRecentTabs { self.completion = nil; [self stop]; @@ -178,26 +211,51 @@ (TableViewURLItem*)item API_AVAILABLE(ios(13.0)) { __weak __typeof(self) weakSelf = self; - UIContextMenuActionProvider actionProvider = - ^(NSArray<UIMenuElement*>* suggestedActions) { - if (!weakSelf) { - // Return an empty menu. - return [UIMenu menuWithTitle:@"" children:@[]]; - } + UIContextMenuActionProvider actionProvider = ^( + NSArray<UIMenuElement*>* suggestedActions) { + if (!weakSelf) { + // Return an empty menu. + return [UIMenu menuWithTitle:@"" children:@[]]; + } - RecentTabsCoordinator* strongSelf = weakSelf; + RecentTabsCoordinator* strongSelf = weakSelf; - // Record that this context menu was shown to the user. - RecordMenuShown(MenuScenario::kRecentTabsEntry); + // Record that this context menu was shown to the user. + RecordMenuShown(MenuScenario::kRecentTabsEntry); - ActionFactory* actionFactory = [[ActionFactory alloc] - initWithBrowser:strongSelf.browser - scenario:MenuScenario::kRecentTabsEntry]; + ActionFactory* actionFactory = + [[ActionFactory alloc] initWithBrowser:strongSelf.browser + scenario:MenuScenario::kRecentTabsEntry]; - UIAction* copyAction = [actionFactory actionToCopyURL:item.URL]; + NSMutableArray<UIMenuElement*>* menuElements = + [[NSMutableArray alloc] init]; - return [UIMenu menuWithTitle:@"" children:@[ copyAction ]]; - }; + [menuElements addObject:[actionFactory actionToOpenInNewTabWithURL:item.URL + completion:^{ + [strongSelf stop]; + }]]; + + [menuElements + addObject:[actionFactory actionToOpenInNewIncognitoTabWithURL:item.URL + completion:^{ + [strongSelf stop]; + }]]; + + if (IsMultipleScenesSupported()) { + [menuElements + addObject: + [actionFactory + actionToOpenInNewWindowWithURL:item.URL + activityOrigin:WindowActivityRecentTabsOrigin + completion:^{ + [strongSelf stop]; + }]]; + } + + [menuElements addObject:[actionFactory actionToCopyURL:item.URL]]; + + return [UIMenu menuWithTitle:@"" children:menuElements]; + }; return [UIContextMenuConfiguration configurationWithIdentifier:nil @@ -208,17 +266,51 @@ - (UIContextMenuConfiguration*) contextMenuConfigurationForHeaderWithSectionIdentifier: (NSInteger)sectionIdentifier API_AVAILABLE(ios(13.0)) { - return [UIContextMenuConfiguration - configurationWithIdentifier:nil - previewProvider:nil - actionProvider:^(NSArray<UIMenuElement*>* suggestedActions) { - // Record that this context menu was shown to the user. - RecordMenuShown(MenuScenario::kRecentTabsEntry); + __weak __typeof(self) weakSelf = self; - // TODO(crbug.com/1093302): Implement this. + UIContextMenuActionProvider actionProvider = + ^(NSArray<UIMenuElement*>* suggestedActions) { + if (!weakSelf || ![weakSelf.recentTabsTableViewController + isSessionSectionIdentifier:sectionIdentifier]) { + // Return an empty menu. + return [UIMenu menuWithTitle:@"" children:@[]]; + } - return [UIMenu menuWithTitle:@"" children:@[]]; - }]; + // Record that this context menu was shown to the user. + RecordMenuShown(MenuScenario::kRecentTabsHeader); + + ActionFactory* actionFactory = [[ActionFactory alloc] + initWithBrowser:weakSelf.browser + scenario:MenuScenario::kRecentTabsHeader]; + + NSMutableArray<UIMenuElement*>* menuElements = + [[NSMutableArray alloc] init]; + + synced_sessions::DistantSession const* session = + [weakSelf.recentTabsTableViewController + sessionForSectionIdentifier:sectionIdentifier]; + + if (!session->tabs.empty()) { + [menuElements + addObject:[actionFactory actionToOpenAllTabsWithBlock:^{ + [weakSelf + openAllTabsFromSessionSectionIdentitifer:sectionIdentifier]; + }]]; + } + + [menuElements + addObject:[actionFactory actionToHideWithBlock:^{ + [weakSelf.recentTabsTableViewController + removeSessionAtSessionSectionIdentifier:sectionIdentifier]; + }]]; + + return [UIMenu menuWithTitle:@"" children:menuElements]; + }; + + return + [UIContextMenuConfiguration configurationWithIdentifier:nil + previewProvider:nil + actionProvider:actionProvider]; } @end
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_presentation_delegate.h b/ios/chrome/browser/ui/recent_tabs/recent_tabs_presentation_delegate.h index e480641..2bbab18d 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_presentation_delegate.h +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_presentation_delegate.h
@@ -7,6 +7,10 @@ #import <UIKit/UIKit.h> +namespace synced_sessions { +class DistantSession; +} + // Presentation commands that depend on the context from which they are // presented. @protocol RecentTabsPresentationDelegate @@ -19,6 +23,10 @@ // Tells the receiver to show the history UI. Receiver may also dismiss recent // tabs. - (void)showHistoryFromRecentTabs; + +// Tells the receiver to open all tabs from the given |session|. +- (void)openAllTabsFromSession:(const synced_sessions::DistantSession*)session; + @end #endif // IOS_CHROME_BROWSER_UI_RECENT_TABS_RECENT_TABS_PRESENTATION_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h index 202c1c63..c90665b16 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.h
@@ -12,6 +12,10 @@ class Browser; enum class UrlLoadStrategy; +namespace synced_sessions { +class DistantSession; +} + @protocol ApplicationCommands; @protocol RecentTabsMenuProvider; @protocol RecentTabsTableViewControllerDelegate; @@ -51,6 +55,16 @@ - (instancetype)init NS_DESIGNATED_INITIALIZER; - (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE; +// Returns YES if |sectionIdentifier| is a Sessions sectionIdentifier. +- (BOOL)isSessionSectionIdentifier:(NSInteger)sectionIdentifier; + +// Returns Sessions corresponding to the given |sectionIdentifier|. +- (synced_sessions::DistantSession const*)sessionForSectionIdentifier: + (NSInteger)sectionIdentifer; + +// Hides Sessions corresponding to the given |sectionIdentifier|. +- (void)removeSessionAtSessionSectionIdentifier:(NSInteger)sectionIdentifier; + @end #endif // IOS_CHROME_BROWSER_UI_RECENT_TABS_RECENT_TABS_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index efddfb3..182567b67 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -645,13 +645,51 @@ return sessionSectionIndexes; } -// Returns YES if |sectionIdentifier| is a Sessions sectionIdentifier. +#pragma mark - Public + - (BOOL)isSessionSectionIdentifier:(NSInteger)sectionIdentifier { NSArray* sessionSectionIdentifiers = [self allSessionSectionIdentifiers]; NSNumber* sectionIdentifierObject = @(sectionIdentifier); return [sessionSectionIdentifiers containsObject:sectionIdentifierObject]; } +- (synced_sessions::DistantSession const*)sessionForSectionIdentifier: + (NSInteger)sectionIdentifer { + NSInteger section = + [self.tableViewModel sectionForSectionIdentifier:sectionIdentifer]; + DCHECK([self isSessionSectionIdentifier:sectionIdentifer]); + return _syncedSessions->GetSession(section - kNumberOfSectionsBeforeSessions); +} + +- (void)removeSessionAtSessionSectionIdentifier:(NSInteger)sectionIdentifier { + DCHECK([self isSessionSectionIdentifier:sectionIdentifier]); + synced_sessions::DistantSession const* session = + [self sessionForSectionIdentifier:sectionIdentifier]; + std::string sessionTagCopy = session->tag; + + NSInteger section = + [self.tableViewModel sectionForSectionIdentifier:sectionIdentifier]; + + __weak __typeof(self) weakSelf = self; + void (^tableUpdates)(void) = ^{ + [weakSelf.tableViewModel removeSectionWithIdentifier:sectionIdentifier]; + _syncedSessions->EraseSession(section - kNumberOfSectionsBeforeSessions); + [weakSelf.tableView deleteSections:[NSIndexSet indexSetWithIndex:section] + withRowAnimation:UITableViewRowAnimationLeft]; + }; + + [self.tableView performBatchUpdates:tableUpdates + completion:^(BOOL) { + if (!weakSelf) + return; + sync_sessions::OpenTabsUIDelegate* openTabs = + SessionSyncServiceFactory::GetForBrowserState( + weakSelf.browserState) + ->GetOpenTabsUIDelegate(); + openTabs->DeleteForeignSession(sessionTagCopy); + }]; +} + #pragma mark - Consumer Protocol - (void)refreshUserState:(SessionsSyncUserState)newSessionState { @@ -1015,13 +1053,6 @@ [self indexOfSessionForTabAtIndexPath:indexPath]); } -- (synced_sessions::DistantSession const*)sessionForSection:(NSInteger)section { - NSInteger sectionIdentifer = - [self.tableViewModel sectionIdentifierForSection:section]; - DCHECK([self isSessionSectionIdentifier:sectionIdentifer]); - return _syncedSessions->GetSession(section - kNumberOfSectionsBeforeSessions); -} - - (synced_sessions::DistantTab const*)distantTabAtIndexPath: (NSIndexPath*)indexPath { DCHECK_EQ([self.tableViewModel itemTypeForIndexPath:indexPath], @@ -1294,48 +1325,9 @@ } - (void)openTabsFromSessionSectionIdentifier:(NSInteger)sectionIdentifier { - base::RecordAction(base::UserMetricsAction( - "MobileRecentTabManagerOpenAllTabsFromOtherDevice")); - NSInteger section = - [self.tableViewModel sectionForSectionIdentifier:sectionIdentifier]; synced_sessions::DistantSession const* session = - [self sessionForSection:section]; - for (auto const& tab : session->tabs) { - UrlLoadParams params = UrlLoadParams::InNewTab(tab->virtual_url); - params.SetInBackground(YES); - params.web_params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK; - params.load_strategy = self.loadStrategy; - params.in_incognito = self.isIncognito; - UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params); - } - UMA_HISTOGRAM_COUNTS_100( - "Mobile.RecentTabsManager.TotalTabsFromOtherDevicesOpenAll", - session->tabs.size()); - [self.presentationDelegate showActiveRegularTabFromRecentTabs]; -} - -- (void)removeSessionAtSessionSectionIdentifier:(NSInteger)sectionIdentifier { - DCHECK([self isSessionSectionIdentifier:sectionIdentifier]); - NSInteger section = - [self.tableViewModel sectionForSectionIdentifier:sectionIdentifier]; - synced_sessions::DistantSession const* session = - [self sessionForSection:section]; - std::string sessionTagCopy = session->tag; - sync_sessions::OpenTabsUIDelegate* openTabs = - SessionSyncServiceFactory::GetForBrowserState(self.browserState) - ->GetOpenTabsUIDelegate(); - - void (^tableUpdates)(void) = ^{ - [self.tableViewModel removeSectionWithIdentifier:sectionIdentifier]; - _syncedSessions->EraseSession(section - kNumberOfSectionsBeforeSessions); - [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:section] - withRowAnimation:UITableViewRowAnimationLeft]; - }; - - [self.tableView performBatchUpdates:tableUpdates - completion:^(BOOL) { - openTabs->DeleteForeignSession(sessionTagCopy); - }]; + [self sessionForSectionIdentifier:sectionIdentifier]; + [self.presentationDelegate openAllTabsFromSession:session]; } #pragma mark - SigninPromoViewConsumer
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index c640384..0451e10 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -436,4 +436,8 @@ self.incognitoTabsMediator.browser = browser; } +- (void)openAllTabsFromSession:(const synced_sessions::DistantSession*)session { + // TODO(crbug.com/1093302) : Implement this. +} + @end
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h index de3f185..ecf3841 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h +++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
@@ -153,40 +153,38 @@ // Returns YES if |identity| is valid and if the service has it in its list of // identitites. - virtual bool IsValidIdentity(ChromeIdentity* identity) const; + virtual bool IsValidIdentity(ChromeIdentity* identity); virtual bool IsValidIdentityTemporary(ChromeIdentity* identity) const; // Returns the chrome identity having the email equal to |email| or |nil| if // no matching identity is found. - virtual ChromeIdentity* GetIdentityWithEmail(const std::string& email) const; + virtual ChromeIdentity* GetIdentityWithEmail(const std::string& email); virtual ChromeIdentity* GetIdentityWithEmailTemporary( const std::string& email) const; // Returns the chrome identity having the gaia ID equal to |gaia_id| or |nil| // if no matching identity is found. - virtual ChromeIdentity* GetIdentityWithGaiaID( - const std::string& gaia_id) const; + virtual ChromeIdentity* GetIdentityWithGaiaID(const std::string& gaia_id); virtual ChromeIdentity* GetIdentityWithGaiaIDTemporary( const std::string& gaia_id) const; // Returns the canonicalized emails for all identities. - virtual std::vector<std::string> GetCanonicalizeEmailsForAllIdentities() - const; + virtual std::vector<std::string> GetCanonicalizeEmailsForAllIdentities(); virtual std::vector<std::string> GetCanonicalizeEmailsForAllIdentitiesTemporary() const; // Returns true if there is at least one identity. - virtual bool HasIdentities() const; + virtual bool HasIdentities(); virtual bool HasIdentitiesTemporary() const; // Returns all ChromeIdentity objects in an array. - virtual NSArray* GetAllIdentities() const; + virtual NSArray* GetAllIdentities(); virtual NSArray* GetAllIdentitiesTemporary() const; // Returns all ChromeIdentity objects sorted by the ordering used in the // account manager, which is typically based on the keychain ordering of // accounts. - virtual NSArray* GetAllIdentitiesSortedForDisplay() const; + virtual NSArray* GetAllIdentitiesSortedForDisplay(); virtual NSArray* GetAllIdentitiesSortedForDisplayTemporary() const; // Forgets the given identity on the device. This method logs the user out.
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm index cdcb2b8..09254cd 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm +++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
@@ -61,7 +61,7 @@ return nil; } -bool ChromeIdentityService::IsValidIdentity(ChromeIdentity* identity) const { +bool ChromeIdentityService::IsValidIdentity(ChromeIdentity* identity) { return IsValidIdentityTemporary(identity); } @@ -71,7 +71,7 @@ } ChromeIdentity* ChromeIdentityService::GetIdentityWithEmail( - const std::string& email) const { + const std::string& email) { return GetIdentityWithEmailTemporary(email); } @@ -81,7 +81,7 @@ } ChromeIdentity* ChromeIdentityService::GetIdentityWithGaiaID( - const std::string& gaia_id) const { + const std::string& gaia_id) { return GetIdentityWithGaiaIDTemporary(gaia_id); } @@ -91,7 +91,7 @@ } std::vector<std::string> -ChromeIdentityService::GetCanonicalizeEmailsForAllIdentities() const { +ChromeIdentityService::GetCanonicalizeEmailsForAllIdentities() { return GetCanonicalizeEmailsForAllIdentitiesTemporary(); } @@ -100,7 +100,7 @@ return std::vector<std::string>(); } -bool ChromeIdentityService::HasIdentities() const { +bool ChromeIdentityService::HasIdentities() { return HasIdentitiesTemporary(); } @@ -108,7 +108,7 @@ return false; } -NSArray* ChromeIdentityService::GetAllIdentities() const { +NSArray* ChromeIdentityService::GetAllIdentities() { return GetAllIdentitiesTemporary(); } @@ -116,7 +116,7 @@ return nil; } -NSArray* ChromeIdentityService::GetAllIdentitiesSortedForDisplay() const { +NSArray* ChromeIdentityService::GetAllIdentitiesSortedForDisplay() { return GetAllIdentitiesSortedForDisplayTemporary(); }
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h index 2db18b2..01b169b 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h
@@ -39,12 +39,11 @@ ChromeBrowserState* browser_state, id<ChromeIdentityInteractionManagerDelegate> delegate) const; - bool IsValidIdentity(ChromeIdentity* identity) const override; - ChromeIdentity* GetIdentityWithGaiaID( - const std::string& gaia_id) const override; - bool HasIdentities() const override; - NSArray* GetAllIdentities() const override; - NSArray* GetAllIdentitiesSortedForDisplay() const override; + bool IsValidIdentity(ChromeIdentity* identity) override; + ChromeIdentity* GetIdentityWithGaiaID(const std::string& gaia_id) override; + bool HasIdentities() override; + NSArray* GetAllIdentities() override; + NSArray* GetAllIdentitiesSortedForDisplay() override; void ForgetIdentity(ChromeIdentity* identity, ForgetIdentityCallback callback) override;
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm index 767ceca5..ced7a12 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm
@@ -174,13 +174,12 @@ return manager; } -bool FakeChromeIdentityService::IsValidIdentity( - ChromeIdentity* identity) const { +bool FakeChromeIdentityService::IsValidIdentity(ChromeIdentity* identity) { return [identities_ indexOfObject:identity] != NSNotFound; } ChromeIdentity* FakeChromeIdentityService::GetIdentityWithGaiaID( - const std::string& gaia_id) const { + const std::string& gaia_id) { NSString* gaiaID = base::SysUTF8ToNSString(gaia_id); NSUInteger index = [identities_ indexOfObjectPassingTest:^BOOL(ChromeIdentity* obj, @@ -193,15 +192,15 @@ return [identities_ objectAtIndex:index]; } -bool FakeChromeIdentityService::HasIdentities() const { +bool FakeChromeIdentityService::HasIdentities() { return [identities_ count] > 0; } -NSArray* FakeChromeIdentityService::GetAllIdentities() const { +NSArray* FakeChromeIdentityService::GetAllIdentities() { return identities_; } -NSArray* FakeChromeIdentityService::GetAllIdentitiesSortedForDisplay() const { +NSArray* FakeChromeIdentityService::GetAllIdentitiesSortedForDisplay() { return identities_; }
diff --git a/ios/showcase/content_suggestions/sc_content_suggestions_coordinator.mm b/ios/showcase/content_suggestions/sc_content_suggestions_coordinator.mm index b0aeceb..cc9be79 100644 --- a/ios/showcase/content_suggestions/sc_content_suggestions_coordinator.mm +++ b/ios/showcase/content_suggestions/sc_content_suggestions_coordinator.mm
@@ -39,7 +39,8 @@ _dataSource = [[SCContentSuggestionsDataSource alloc] init]; _suggestionViewController = [[ContentSuggestionsViewController alloc] - initWithStyle:CollectionViewControllerStyleDefault]; + initWithStyle:CollectionViewControllerStyleDefault + offset:0]; [_suggestionViewController setDataSource:_dataSource]; _suggestionViewController.suggestionCommandHandler =
diff --git a/ios/testing/earl_grey/base_earl_grey_test_case.mm b/ios/testing/earl_grey/base_earl_grey_test_case.mm index 12df528..3d6cc29 100644 --- a/ios/testing/earl_grey/base_earl_grey_test_case.mm +++ b/ios/testing/earl_grey/base_earl_grey_test_case.mm
@@ -152,6 +152,15 @@ [self tapAlertButtonWithText:@"Not Now" error:&error]; GREYAssertNil( error, @"Error closing Carrier Settings Update alert.\n%@", error); + } else if ([alertText containsString:@"would like to find and connect to " + @"devices on your local network."]) { + DLOG(WARNING) << "Denying iOS system alert of connecting to local " + "network devices!"; + NSError* error = nil; + [self tapAlertButtonWithText:@"OK" error:&error]; + GREYAssertNil(error, + @"Error closing connecting to local network devices.\n%@", + error); } else { XCTFail("An unsupported system alert is present on device. Failing " "this test. Alert label: %@",
diff --git a/ios/web_view/internal/passwords/web_view_password_feature_manager.h b/ios/web_view/internal/passwords/web_view_password_feature_manager.h index 1a68f973..795fab1 100644 --- a/ios/web_view/internal/passwords/web_view_password_feature_manager.h +++ b/ios/web_view/internal/passwords/web_view_password_feature_manager.h
@@ -41,6 +41,9 @@ password_manager::metrics_util::PasswordAccountStorageUsageLevel ComputePasswordAccountStorageUsageLevel() const override; + void IncrementMoveToAccountRefusedCount() override; + int GetMoveToAccountRefusedCount() const override; + private: PrefService* const pref_service_; const syncer::SyncService* const sync_service_;
diff --git a/ios/web_view/internal/passwords/web_view_password_feature_manager.mm b/ios/web_view/internal/passwords/web_view_password_feature_manager.mm index e19121cb..2333846 100644 --- a/ios/web_view/internal/passwords/web_view_password_feature_manager.mm +++ b/ios/web_view/internal/passwords/web_view_password_feature_manager.mm
@@ -71,4 +71,13 @@ kUsingAccountStorage; } +void WebViewPasswordFeatureManager::IncrementMoveToAccountRefusedCount() { + NOTREACHED(); +} + +int WebViewPasswordFeatureManager::GetMoveToAccountRefusedCount() const { + NOTREACHED(); + return 0; +} + } // namespace ios_web_view
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index d4de568..6f85849 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -584,7 +584,7 @@ "UsePooledSharedImageVideoProvider", base::FEATURE_ENABLED_BY_DEFAULT}; // Used to enable/disable zero copy video path on webview for MCVD. -const base::Feature kWebViewZeroCopyVideo{"EnableZeroCopyVideoOnWebview", +const base::Feature kWebViewZeroCopyVideo{"WebViewZeroCopyVideo", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_ANDROID)
diff --git a/media/gpu/test/video_encoder/video_encoder_client.cc b/media/gpu/test/video_encoder/video_encoder_client.cc index de3f9bb..4def591 100644 --- a/media/gpu/test/video_encoder/video_encoder_client.cc +++ b/media/gpu/test/video_encoder/video_encoder_client.cc
@@ -44,8 +44,10 @@ VideoEncoderClientConfig::VideoEncoderClientConfig( const Video* video, - VideoCodecProfile output_profile) + VideoCodecProfile output_profile, + uint32_t bitrate) : output_profile(output_profile), + bitrate(bitrate), framerate(video->FrameRate()), num_frames_to_encode(video->NumFrames()) {}
diff --git a/media/gpu/test/video_encoder/video_encoder_client.h b/media/gpu/test/video_encoder/video_encoder_client.h index e5482ce6..319e3ad 100644 --- a/media/gpu/test/video_encoder/video_encoder_client.h +++ b/media/gpu/test/video_encoder/video_encoder_client.h
@@ -34,8 +34,10 @@ // Video encoder client configuration. // TODO(dstaessens): Add extra parameters (e.g. h264 output level) struct VideoEncoderClientConfig { + static constexpr uint32_t kDefaultBitrate = 200000; VideoEncoderClientConfig(const Video* video, - VideoCodecProfile output_profile); + VideoCodecProfile output_profile, + uint32_t bitrate = kDefaultBitrate); VideoEncoderClientConfig(const VideoEncoderClientConfig&); // The output output profile to be used. @@ -44,7 +46,7 @@ // without waiting for the result of the previous encodes requests. size_t max_outstanding_encode_requests = 1; // The desired bitrate in bits/second. - uint32_t bitrate = 200000; + uint32_t bitrate = kDefaultBitrate; // The desired framerate in frames/second. uint32_t framerate = 30.0; // The number of frames to be encoded. This can be more than the number of
diff --git a/media/gpu/test/video_encoder/video_encoder_test_environment.cc b/media/gpu/test/video_encoder/video_encoder_test_environment.cc index f9c53d2..6f7283f1 100644 --- a/media/gpu/test/video_encoder/video_encoder_test_environment.cc +++ b/media/gpu/test/video_encoder/video_encoder_test_environment.cc
@@ -46,6 +46,39 @@ // decode any vp8 stream in BitstreamValidator. kFFmpegDecodeOpaqueVP8, }; + +uint32_t GetDefaultTargetBitrate(const gfx::Size& resolution, + const uint32_t framerate) { + constexpr uint32_t Mbps = 1000 * 1000; + // The half of video bitrates recommended by YouTube for 16:9 SDR 30fps video. + // (https://support.google.com/youtube/answer/1722171). Dividing them by 2 is + // to tune for video call apps, which are most frequent use scenarios of video + // encoders. + // The bitrates don't scale linearly so we use the following lookup table as a + // base for computing a reasonable bitrate for the specified resolution and + // framerate. + constexpr struct { + gfx::Size resolution; + uint32_t bitrate; + } kDefaultTargetBitrates[] = { + {gfx::Size(640, 360), 0.5 * Mbps}, {gfx::Size(854, 480), 1.25 * Mbps}, + {gfx::Size(1280, 720), 2.5 * Mbps}, {gfx::Size(1920, 1080), 4 * Mbps}, + {gfx::Size(2560, 1440), 8 * Mbps}, {gfx::Size(3840, 2160), 18 * Mbps}, + }; + + const auto* it = std::find_if( + std::cbegin(kDefaultTargetBitrates), std::cend(kDefaultTargetBitrates), + [resolution](const auto& target_bitrate) { + return resolution.GetArea() <= target_bitrate.resolution.GetArea(); + }); + LOG_ASSERT(it != std::cend(kDefaultTargetBitrates)) + << "Target bitrate for the resolution is not found, resolution=" + << resolution.ToString(); + const double resolution_ratio = + (resolution.GetArea() / static_cast<double>(it->resolution.GetArea())); + const double framerate_ratio = framerate > 30 ? 1.5 : 1.0; + return it->bitrate * resolution_ratio * framerate_ratio; +} } // namespace // static @@ -94,10 +127,12 @@ return nullptr; } + const uint32_t bitrate = + GetDefaultTargetBitrate(video->Resolution(), video->FrameRate()); VideoCodecProfile profile = it->profile; return new VideoEncoderTestEnvironment( std::move(video), enable_bitstream_validator, output_folder, profile, - save_output_bitstream, frame_output_config); + bitrate, save_output_bitstream, frame_output_config); } VideoEncoderTestEnvironment::VideoEncoderTestEnvironment( @@ -105,6 +140,7 @@ bool enable_bitstream_validator, const base::FilePath& output_folder, VideoCodecProfile profile, + uint32_t bitrate, bool save_output_bitstream, const FrameOutputConfig& frame_output_config) : VideoTestEnvironment(kEnabledFeaturesForVideoEncoderTest, @@ -113,6 +149,7 @@ enable_bitstream_validator_(enable_bitstream_validator), output_folder_(output_folder), profile_(profile), + bitrate_(bitrate), save_output_bitstream_(save_output_bitstream), frame_output_config_(frame_output_config), gpu_memory_buffer_factory_( @@ -136,6 +173,10 @@ return profile_; } +uint32_t VideoEncoderTestEnvironment::Bitrate() const { + return bitrate_; +} + bool VideoEncoderTestEnvironment::SaveOutputBitstream() const { return save_output_bitstream_; }
diff --git a/media/gpu/test/video_encoder/video_encoder_test_environment.h b/media/gpu/test/video_encoder/video_encoder_test_environment.h index ee17be6..11168aa 100644 --- a/media/gpu/test/video_encoder/video_encoder_test_environment.h +++ b/media/gpu/test/video_encoder/video_encoder_test_environment.h
@@ -45,6 +45,8 @@ const base::FilePath& OutputFolder() const; // Get the output codec profile. VideoCodecProfile Profile() const; + // Get the target bitrate (bits/second). + uint32_t Bitrate() const; // Whether the encoded bitstream is saved to disk. bool SaveOutputBitstream() const; base::Optional<base::FilePath> OutputBitstreamFilePath() const; @@ -62,6 +64,7 @@ bool enable_bitstream_validator, const base::FilePath& output_folder, VideoCodecProfile profile, + uint32_t bitrate, bool save_output_bitstream, const FrameOutputConfig& frame_output_config); @@ -73,6 +76,8 @@ const base::FilePath output_folder_; // VideoCodecProfile to be produced by VideoEncoder. const VideoCodecProfile profile_; + // Targeted bitrate (bits/second) of the stream produced by VideoEncoder. + const uint32_t bitrate_; // Whether the bitstream produced by VideoEncoder is saved to disk. const bool save_output_bitstream_; // The configuration about saving decoded images of bitstream encoded by
diff --git a/media/gpu/video_encode_accelerator_tests.cc b/media/gpu/video_encode_accelerator_tests.cc index 6278ec6..480f09020 100644 --- a/media/gpu/video_encode_accelerator_tests.cc +++ b/media/gpu/video_encode_accelerator_tests.cc
@@ -223,7 +223,8 @@ // Encode video from start to end. Wait for the kFlushDone event at the end of // the stream, that notifies us all frames have been encoded. TEST_F(VideoEncoderTest, FlushAtEndOfStream) { - VideoEncoderClientConfig config(g_env->Video(), g_env->Profile()); + VideoEncoderClientConfig config(g_env->Video(), g_env->Profile(), + g_env->Bitrate()); auto encoder = CreateVideoEncoder(g_env->Video(), config); encoder->Encode(); @@ -239,7 +240,8 @@ // resolution. The test only verifies initialization and doesn't do any // encoding. TEST_F(VideoEncoderTest, Initialize) { - VideoEncoderClientConfig config(g_env->Video(), g_env->Profile()); + VideoEncoderClientConfig config(g_env->Video(), g_env->Profile(), + g_env->Bitrate()); auto encoder = CreateVideoEncoder(g_env->Video(), config); EXPECT_EQ(encoder->GetEventCount(VideoEncoder::kInitialized), 1u); @@ -250,7 +252,8 @@ // of scope at the end of the test. The test will pass if no asserts or crashes // are triggered upon destroying. TEST_F(VideoEncoderTest, DestroyBeforeInitialize) { - VideoEncoderClientConfig config(g_env->Video(), g_env->Profile()); + VideoEncoderClientConfig config(g_env->Video(), g_env->Profile(), + g_env->Bitrate()); auto video_encoder = VideoEncoder::Create(config, g_env->GetGpuMemoryBufferFactory()); @@ -277,7 +280,8 @@ // The minimal number of concurrent encoders we expect to be supported. constexpr size_t kMinSupportedConcurrentEncoders = 3; - VideoEncoderClientConfig config(g_env->Video(), g_env->Profile()); + VideoEncoderClientConfig config(g_env->Video(), g_env->Profile(), + g_env->Bitrate()); std::vector<std::unique_ptr<VideoEncoder>> encoders( kMinSupportedConcurrentEncoders); for (size_t i = 0; i < kMinSupportedConcurrentEncoders; ++i) @@ -296,7 +300,8 @@ } TEST_F(VideoEncoderTest, BitrateCheck) { - VideoEncoderClientConfig config(g_env->Video(), g_env->Profile()); + VideoEncoderClientConfig config(g_env->Video(), g_env->Profile(), + g_env->Bitrate()); config.num_frames_to_encode = kNumFramesToEncodeForBitrateCheck; auto encoder = CreateVideoEncoder(g_env->Video(), config); @@ -311,7 +316,8 @@ } TEST_F(VideoEncoderTest, DynamicBitrateChange) { - VideoEncoderClientConfig config(g_env->Video(), g_env->Profile()); + VideoEncoderClientConfig config(g_env->Video(), g_env->Profile(), + g_env->Bitrate()); config.num_frames_to_encode = kNumFramesToEncodeForBitrateCheck * 2; auto encoder = CreateVideoEncoder(g_env->Video(), config); @@ -339,7 +345,8 @@ } TEST_F(VideoEncoderTest, DynamicFramerateChange) { - VideoEncoderClientConfig config(g_env->Video(), g_env->Profile()); + VideoEncoderClientConfig config(g_env->Video(), g_env->Profile(), + g_env->Bitrate()); config.num_frames_to_encode = kNumFramesToEncodeForBitrateCheck * 2; auto encoder = CreateVideoEncoder(g_env->Video(), config); @@ -371,7 +378,8 @@ auto nv12_video = g_env->Video()->ConvertToNV12(); ASSERT_TRUE(nv12_video); - VideoEncoderClientConfig config(nv12_video.get(), g_env->Profile()); + VideoEncoderClientConfig config(nv12_video.get(), g_env->Profile(), + g_env->Bitrate()); config.input_storage_type = VideoEncodeAccelerator::Config::StorageType::kDmabuf;
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl index 0bb970e..fb9c72e 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
@@ -130,15 +130,53 @@ #if BUILDFLAG(MOJO_TRACE_ENABLED) // Write this structure into |value|. The members are represented as a - // dictionary |member name|: |member value|. + // dictionary |member name|: |member value|. This method does not deal with + // the dictionary name. The caller is responsible for not calling + // |AsValueInto| when |value| expects array items (see Array/Dictionary + // methods of |base::trace_event::TracedValue|). // // |value| The TracedValue to be written into. - // |parameter_name| Name of the variable holding this structure, - // used as the name of the dictionary representing this structure. - // If nullptr, then the dictionary representing this structure has no name - // (used in arrays of structures). - void ToTracedValue(base::trace_event::TracedValue* value, - const char* parameter_name = nullptr); + // + // Example uses: + // + // // |my_var1, my_var2| are variables with defined |AsValueInto| method. + // auto value = std::make_unique<base::trace_event::TracedValue>(); + // value->BeginDictionary("my_var1"); + // my_var1.AsValueInto(value.get()); + // value->EndDictionary(); + // value->BeginDictionary("my_var2"); + // my_var2.AsValueInto(value.get()); + // value->EndDictionary(); + // + // // |my_var| is a variable with defined |AsValueInto| method. + // auto value = std::make_unique<base::trace_event::TracedValue>(); + // my_var.AsValueInto(value.get()); + // TRACE_EVENT1("test", "test", "my_var", std::move(value)); + // + // Calling |AsValueInto| on two objects without opening and closing a + // dictionary for each object is theoretically possible, but strongly + // discouraged due to potential name collisions: + // + // struct A { + // int foo; + // }; + // struct B { + // int bar; + // }; + // struct C { + // int foo; + // int bar; + // }; + // auto value1 = std::make_unique<base::trace_event::TracedValue>(); + // auto value2 = std::make_unique<base::trace_event::TracedValue>(); + // A a; + // B b; + // C c; + // // value1 and value2 will be filled with the same information: + // a.AsValueInto(value1); + // b.AsValueInto(value1); + // c.AsValueInto(value2); + void AsValueInto(base::trace_event::TracedValue* value) const; #endif // BUILDFLAG(MOJO_TRACE_ENABLED) private:
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl index fe9aeada..9639f14 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_class_definition.tmpl
@@ -33,13 +33,7 @@ {%- endif %} #if BUILDFLAG(MOJO_TRACE_ENABLED) -void {{struct.name}}::ToTracedValue(base::trace_event::TracedValue* value, - const char* parameter_name) { - if (parameter_name) { - value->BeginDictionary(parameter_name); - } else { - value->BeginDictionary(); - } +void {{struct.name}}::AsValueInto(base::trace_event::TracedValue* value) const { {%- for field in struct.fields %} {%- for line in field.kind|write_input_param_for_tracing( parameter_name=field.name, @@ -48,7 +42,6 @@ {{line}} {%- endfor -%} {%- endfor %} - value->EndDictionary(); } #endif // BUILDFLAG(MOJO_TRACE_ENABLED)
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index 7ae44f63..850956c 100644 --- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -7,6 +7,8 @@ import mojom.generate.generator as generator import mojom.generate.module as mojom import mojom.generate.pack as pack +from abc import ABCMeta +from abc import abstractmethod from mojom.generate.template_expander import UseJinja, UseJinjaForImportedTemplate @@ -668,52 +670,231 @@ GetCppPodType(constant.kind), constant.name, self._ConstantValue(constant)) - def _WriteInputParamForTracing(self, kind, parameter_name, cpp_parameter_name, - value): - """Generates lines of C++ to log parameter |parameter_name| into TracedValue - |value|. + class _OutputContext(object): + __metaclass__ = ABCMeta + """Represents the context in which |self.value| should be used. + + This is a base class for _ArrayItem, _DictionaryItemWithLiteralKey, and + _DictionaryItemWithCopiedKey. The distinction between _ArrayItem and + _DictionaryItemWithLiteralKey/_DictionaryItemWithCopiedKey is that + _ArrayItem has no name. The distinction between + _DictionaryItemWithLiteralKey and _DictionaryItemWithCopiedKey is whether + the name is expected to be long lived or can be temporary. + """ + + def __init__(self, value): + self.value = value + + @abstractmethod + def AddSingleValue(self, trace_type, parameter_value): + pass + + @abstractmethod + def BeginContainer(self, container_type): + pass + + def EndContainer(self, container_type): + """Return a line of C++ code to close a container on self.value. + + Args: + container_type: {string} Either 'Dictionary' or 'Array'. + + Returns: + A single line of C++ which closes a container on self.value. + """ + return '%s->End%s();' % (self.value, container_type) + + def AsValueInto(self, cpp_expression): + """Return a line of C++ code to trace a variable to self.value. + Most probably the user of this method wants to yield + |self.BeginContainer('Dictionary')| immediately before and + |self.EndContainer('Dictionary')| immediately after a call to + |AsValueInto| (see documentation of |cpp_expression::AsValueInto|). + + Args: + cpp_expression: {string} The C++ expression on which |->AsValueInto| + will be called. + + Returns: + A single line of C++ which calls |AsValueInto| on |cpp_expression| + with self.value as the parameter. + """ + return '%s->AsValueInto(%s);' % (cpp_expression, self.value) + + def TraceContainer(self, container_type, iterator_name, container_name, + loop_body): + """Generate the C++ for-loop to trace the container |container_name|. + + Args: + container_type: {string} Either 'Array' or 'Dictionary'. + iterator_name: {string} The iterator variable name to be used. + container_name: {string} The name of the variable holding the container. + loop_body: {iterable} Lines of C++ code that trace individual elements. + + Yields: + Lines of C++ for-loop to trace the container. + """ + yield self.BeginContainer(container_type) + yield 'for (const auto& %s : %s) {' % (iterator_name, container_name) + for line in loop_body: + yield ' ' + line + yield '}' + yield self.EndContainer(container_type) + + class _ArrayItem(_OutputContext): + """Represents a |TracedValue| which expects to receive an array item (of no + name). This means that |AddSingleValue| will return a call on self.value + which is an Append and |BeginContainer| will start a container with no + name. + + Attributes: + value: {string} The name of the C++ variable of type + |base::trace_event::TracedValue*| this object represents. + """ + + def __init__(self, value): + super(Generator._ArrayItem, self).__init__(value) + + def AddSingleValue(self, trace_type, parameter_value): + """Return a line of C++ code that will append a single value to + |self.value|. + + Args: + trace_type: {string} The type of the appended value. Can be one of: + 'Integer', 'Double', 'Boolean', 'String'. + parameter_value: {string} The C++ expression to be passed as the + appended value. + + Returns: + A single line of C++ which appends |parameter_value| to self.value. + """ + return '%s->Append%s(%s);' % (self.value, trace_type, parameter_value) + + def BeginContainer(self, container_type): + """Return a line of C++ code to open a container on self.value. + + Args: + container_type: {string} Either 'Dictionary' or 'Array'. + + Returns: + A single line of C++ which starts a container on self.value. + """ + return '%s->Begin%s();' % (self.value, container_type) + + class _DictionaryItemWithLiteralKey(_OutputContext): + """Represents a |TracedValue| which expects to receive a dictionary item + (with a long lived name). This means that |AddSingleValue| will return a + call on self.value which is a Set and |BeginContainer| will start a + container with self.name used in a string literal. + + |base::trace_event::TracedValue| has two sets of methods -- ones with copied + name and ones with long lived name. This class corresponds to using the long + lived name. + + _DictionaryItemWithLiteralKey generates calls on + |base::trace_event::TracedValue| which do not copy the name (assume that + the used name is long lived. Thus self.name is used inside a "quoted" long + lived string. + + Attributes: + value: {string} The name of the C++ variable of type + |base::trace_event::TracedValue*| this object represents. + name: {string} The name of the mojo variable that is currently being + traced. Used inside double-quotes in method calls. + """ + + def __init__(self, name, value): + super(Generator._DictionaryItemWithLiteralKey, self).__init__(value) + self.name = name + + def AddSingleValue(self, trace_type, parameter_value): + """Return a line of C++ code that will set a single value to |self.value|. + Uses |self.name| inside a "quoted" string. + + Args: + trace_type: {string} The type of the set value. Can be one of: + 'Integer', 'Double', 'Boolean', 'String', 'Value'. + parameter_value: {string} The C++ expression to be passed as the + set value. + + Returns: + A single line of C++ that sets |parameter_value| of name |"self.name"| + on self.value. + """ + return '%s->Set%s("%s", %s);' % (self.value, trace_type, self.name, + parameter_value) + + def BeginContainer(self, container_type): + return '%s->Begin%s("%s");' % (self.value, container_type, self.name) + + class _DictionaryItemWithCopiedKey(_OutputContext): + """Represents a |TracedValue| which expects to receive a dictionary item + (with a name which is a temporary string). This means that + |AddSingleValue| will return a call on self.value which is an + SetXWithCopiedName and |BeginContainer| will start a container with + self.name used as a temporary string. + + |base::trace_event::TracedValue| has two sets of methods -- ones with copied + name and ones with long lived name. This class corresponds to using the + copied name. + + _DictionaryItemWithCopiedKey generates calls on + |base::trace_event::TracedValue| which do copy the name (assume that + self.name is a C++ expression evaluating to a temporary string). + + Attributes: + value: {string} The name of the C++ variable of type + |base::trace_event::TracedValue*| this object represents. + name: {string} The name of the mojo variable that is currently being + traced. Used directly (not in double quotes) in method calls. + """ + + def __init__(self, name, value): + super(Generator._DictionaryItemWithCopiedKey, self).__init__(value) + self.name = name + + def AddSingleValue(self, trace_type, parameter_value): + """Return a line of C++ code that will set a single value to |self.value|. + Uses |self.name| directly as a parameter that is expected to be copied + (can be a temporary string). + + Args: + trace_type: {string} The type of the set value. Can be one of: + 'Integer', 'Double', 'Boolean', 'String', 'Value'. + parameter_value: {string} The C++ expression to be passed as the + set value. + + Returns: + A single line of C++ that sets |parameter_value| of name |self.name| + on self.value (with copied name). + """ + return '%s->Set%sWithCopiedName(%s, %s);' % (self.value, trace_type, + self.name, parameter_value) + + def BeginContainer(self, container_type): + return '%s->Begin%sWithCopiedName(%s);' % (self.value, container_type, + self.name) + + def _WriteInputParamForTracingImpl(self, kind, cpp_parameter_name, + output_context): + """Generates lines of C++ to log a parameter into TracedValue + |output_context.value|. Use |output_context.name| if |output_context| is of + inhereted type from Generator._OutputContext. Args: kind: {Kind} The kind of the parameter (corresponds to its C++ type). - parameter_name: {string} The name of the mojom parameter to be logged. - Internal use: If |parameter_name| is an empty string this method uses - TracedValue::AppendT instead of TracedValue::SetT (thus populates - array values). cpp_parameter_name: {string} The actual C++ variable name corresponding to - the mojom parameter |parameter_name|. - value: {string} The C++ TracedValue* variable name to be logged into. + the mojom parameter |parameter_name|. Can be a valid C++ expression + (e.g., dereferenced variable |"(*var)"|). + output_context: {Generator._OutputContext} Represents the TracedValue* + variable to be written into. Possibly also holds the mojo parameter name + corresponding to |cpp_parameter_name|. Yields: - {string} C++ lines of code that trace |parameter_name| into |value|. + {string} C++ lines of code that trace a |cpp_parameter_name| into + |output_context.value|. """ - def _AddSingleValue(trace_type, parameter_value): - """Choose the appropriate way to add a piece of information to - TracedValue |value|. If there is no |parameter_name| use the array methods - TracedValue::AppendT. - - Args: - trace_type: {string} Which method to use. Can have the following values: - 'Integer', 'Double', 'Boolean', 'String'. Corresponds to the T in - TracedValue::SetT or TracedValue::AppendT. If |parameter_name| there - are additional possible values: 'IntegerWithCopiedName', - 'DoubleWithCopiedName', 'BooleanWithCopiedName', - 'StringWithCopiedName'. - parameter_value: {string} This will be used verbatim as the second - parameter of TracedValue::SetT, resp. TracedValue::AppendT. To pass a - string literal use '"my string literal"'. - - Args from the surrounding method: - parameter_name: {string} |if parameter_name| use SetT, otherwise use - AppendT. - value: {string} The TracedValue variable to be traced in. - """ - if parameter_name: - return '%s->Set%s("%s", %s);' % (value, trace_type, parameter_name, - parameter_value) - else: - return '%s->Append%s(%s);' % (value, trace_type, parameter_value) - def _WrapIfNullable(inner_lines): """Check if kind is nullable if so yield code to check whether it has value. @@ -727,14 +908,14 @@ Args from the surrounding method: kind cpp_parameter_name - _AddSingleValue + output_context.AddSingleValue """ if mojom.IsNullableKind(kind): yield 'if (%s.has_value()) {' % cpp_parameter_name for line in inner_lines(cpp_parameter_name + '.value()'): yield ' ' + line yield '} else {' - yield ' ' + _AddSingleValue('String', '"base::nullopt"') + yield ' ' + output_context.AddSingleValue('String', '"base::nullopt"') yield '}' else: # |yield from| is introduced in Python3.3. @@ -744,26 +925,27 @@ # TODO(crbug.com/1103623): Support more involved types. if mojom.IsEnumKind(kind): if self._IsTypemappedKind(kind) or IsNativeOnlyKind(kind): - yield _AddSingleValue('Integer', - 'static_cast<int>(%s)' % cpp_parameter_name) + yield output_context.AddSingleValue( + 'Integer', 'static_cast<int>(%s)' % cpp_parameter_name) else: - yield _AddSingleValue( + yield output_context.AddSingleValue( 'String', 'base::trace_event::ValueToString(%s)' % cpp_parameter_name) return if mojom.IsStringKind(kind): if self.for_blink: # WTF::String is nullable on its own. - yield _AddSingleValue('String', '%s.Utf8()' % cpp_parameter_name) + yield output_context.AddSingleValue('String', + '%s.Utf8()' % cpp_parameter_name) return # The type might be base::Optional<std::string> or std::string. for line in _WrapIfNullable(lambda cpp_parameter_name: [ - _AddSingleValue('String', cpp_parameter_name) + output_context.AddSingleValue('String', cpp_parameter_name) ]): yield line return if kind == mojom.BOOL: - yield _AddSingleValue('Boolean', cpp_parameter_name) + yield output_context.AddSingleValue('Boolean', cpp_parameter_name) return # TODO(crbug.com/1103623): Make TracedValue support int64_t, then move to # mojom.IsIntegralKind. @@ -771,66 +953,39 @@ mojom.INT8, mojom.UINT8, mojom.INT16, mojom.UINT16, mojom.INT32 ]: # Parameter is representable as 32bit int. - yield _AddSingleValue('Integer', cpp_parameter_name) + yield output_context.AddSingleValue('Integer', cpp_parameter_name) return if kind in [mojom.UINT32, mojom.INT64, mojom.UINT64]: - yield _AddSingleValue('String', - 'base::NumberToString(%s)' % cpp_parameter_name) + yield output_context.AddSingleValue( + 'String', 'base::NumberToString(%s)' % cpp_parameter_name) return if mojom.IsFloatKind(kind) or mojom.IsDoubleKind(kind): - yield _AddSingleValue('Double', cpp_parameter_name) + yield output_context.AddSingleValue('Double', cpp_parameter_name) return if (mojom.IsStructKind(kind) and not self._IsTypemappedKind(kind) and not IsNativeOnlyKind(kind)): yield 'if (%s.is_null()) {' % cpp_parameter_name - yield ' ' + _AddSingleValue('String', '"nullptr"') + yield ' ' + output_context.AddSingleValue('String', '"nullptr"') yield '} else {' - if parameter_name: - yield ' %s->ToTracedValue(%s, "%s");' % (cpp_parameter_name, value, - parameter_name) - else: - yield ' %s->ToTracedValue(%s);' % (cpp_parameter_name, value) + yield ' ' + output_context.BeginContainer('Dictionary') + yield ' ' + output_context.AsValueInto(cpp_parameter_name) + yield ' ' + output_context.EndContainer('Dictionary') yield '}' return - def _TraceArray(iterator_name, container_name, loop_body): - """Generate the C++ for-loop to trace the container |container_name|. - - Args: - iterator_name: {string} The iterator variable name to be used. - container_name: {string} The name of the variable holding the container. - loop_body: {iterable} Lines of C++ code that traces individual elements. - - Args from the surrounding method: - parameter_name - value - """ - if parameter_name: - yield '%s->BeginArray("%s");' % (value, parameter_name) - else: - yield '%s->BeginArray();' % value - yield 'for (const auto& %s : %s) {' % (iterator_name, container_name) - # TODO(crbug.com/1103623): Remove the following hack once all types are - # supported. - yield ' // Get rid of -Wunused-variable for unsupported types.' - yield ' std::ignore = %s;' % iterator_name - for line in loop_body: - yield ' ' + line - yield '}' - yield '%s->EndArray();' % value - if mojom.IsArrayKind(kind): iterator_name = 'item' - loop_body = self._WriteInputParamForTracing( + loop_body = self._WriteInputParamForTracingImpl( kind=kind.kind, - parameter_name='', cpp_parameter_name=iterator_name, - value=value) - # Array might be a nullable kind. - for line in _WrapIfNullable(lambda cpp_parameter_name: _TraceArray( + output_context=Generator._ArrayItem(output_context.value)) + loop_generator = lambda cpp_parameter_name: output_context.TraceContainer( + container_type='Array', iterator_name=iterator_name, container_name=cpp_parameter_name, - loop_body=loop_body)): + loop_body=loop_body) + # Array might be a nullable kind. + for line in _WrapIfNullable(loop_generator): yield line return @@ -838,7 +993,56 @@ return 'base::trace_event::ValueToString(%s, "<value of type %s>")' % ( cpp_parameter_name, self._GetCppWrapperParamType(kind)) - yield _AddSingleValue('String', _TraceEventToString()) + if mojom.IsMapKind(kind): + iterator_name = 'item' + if self.for_blink: + # WTF::HashMap<,> + key_access = '.key' + value_access = '.value' + else: + # base::flat_map<,> + key_access = '.first' + value_access = '.second' + loop_body = self._WriteInputParamForTracingImpl( + kind=kind.value_kind, + cpp_parameter_name=iterator_name + value_access, + output_context=Generator._DictionaryItemWithCopiedKey( + value=output_context.value, + name=_TraceEventToString(cpp_parameter_name=iterator_name + + key_access, + kind=kind.key_kind))) + loop_generator = lambda cpp_parameter_name: output_context.TraceContainer( + container_type="Dictionary", + iterator_name=iterator_name, + container_name=cpp_parameter_name, + loop_body=loop_body) + # Dictionary might be a nullable kind. + for line in _WrapIfNullable(loop_generator): + yield line + return + yield output_context.AddSingleValue('String', _TraceEventToString()) + + def _WriteInputParamForTracing(self, kind, parameter_name, cpp_parameter_name, + value): + """Generates lines of C++ to log parameter |parameter_name| into TracedValue + |value|. + + Args: + kind: {Kind} The kind of the parameter (corresponds to its C++ type). + cpp_parameter_name: {string} The actual C++ variable name corresponding to + the mojom parameter |parameter_name|. Can be a valid C++ expression + (e.g., dereferenced variable |"(*var)"|). + value: {string} The C++ |TracedValue*| variable name to be logged into. + + Yields: + {string} C++ lines of code that trace |parameter_name| into |value|. + """ + for line in self._WriteInputParamForTracingImpl( + kind=kind, + cpp_parameter_name=cpp_parameter_name, + output_context=Generator._DictionaryItemWithLiteralKey( + name=parameter_name, value=value)): + yield line def _GetCppWrapperType(self, kind,
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index cc976c8..c7d9061 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1035,9 +1035,6 @@ if (config()->HasClientRequestedIndependentOption( quic::kQLVE, quic::Perspective::IS_CLIENT)) { connection()->EnableLegacyVersionEncapsulation(session_key_.host()); - // Legacy Version Encapsulation needs CHLO padding to be disabled. - // TODO(dschinazi) remove this line once we deprecate quic_dont_pad_chlo. - crypto_config_->GetConfig()->set_disable_chlo_padding(true); } quic::QuicSpdyClientSessionBase::Initialize(); SetHpackEncoderDebugVisitor(std::make_unique<HpackEncoderDebugVisitor>());
diff --git a/net/quic/quic_connectivity_monitor.cc b/net/quic/quic_connectivity_monitor.cc index 044e233f..733faa7 100644 --- a/net/quic/quic_connectivity_monitor.cc +++ b/net/quic/quic_connectivity_monitor.cc
@@ -35,9 +35,7 @@ return; } - UMA_HISTOGRAM_COUNTS_100( - "Net.QuicConnectivityMonitor.NumActiveQuicSessionsAtNetworkChange", - active_sessions_.size()); + base::ClampedNumeric<int> num_degrading_sessions = GetNumDegradingSessions(); if (num_sessions_active_during_current_speculative_connectivity_failure_) { UMA_HISTOGRAM_COUNTS_100( @@ -47,6 +45,20 @@ } UMA_HISTOGRAM_COUNTS_100( + "Net.QuicConnectivityMonitor.NumActiveQuicSessionsAtNetworkChange", + active_sessions_.size()); + + int percentage = 0; + if (num_sessions_active_during_current_speculative_connectivity_failure_ && + num_sessions_active_during_current_speculative_connectivity_failure_ + .value() > 0) { + percentage = base::saturated_cast<int>( + num_all_degraded_sessions_ * 100.0 / + num_sessions_active_during_current_speculative_connectivity_failure_ + .value()); + } + + UMA_HISTOGRAM_COUNTS_100( "Net.QuicConnectivityMonitor.NumAllSessionsDegradedAtNetworkChange", num_all_degraded_sessions_); @@ -55,14 +67,6 @@ base::UmaHistogramCustomCounts(raw_histogram_name1, num_all_degraded_sessions_, 1, 100, 50); - int percentage = 0; - if (num_sessions_active_during_current_speculative_connectivity_failure_) { - percentage = - num_all_degraded_sessions_ * 100 / - num_sessions_active_during_current_speculative_connectivity_failure_ - .value(); - } - const std::string percentage_histogram_name1 = "Net.QuicConnectivityMonitor.PercentageAllDegradedSessions." + notification; @@ -70,16 +74,18 @@ base::UmaHistogramPercentage(percentage_histogram_name1, percentage); // Skip degrading session collection if there are less than two sessions. - if (active_sessions_.size() < 2) + if (active_sessions_.size() < 2u) return; - size_t num_degrading_sessions = GetNumDegradingSessions(); const std::string raw_histogram_name = "Net.QuicConnectivityMonitor.NumActiveDegradingSessions." + notification; base::UmaHistogramCustomCounts(raw_histogram_name, num_degrading_sessions, 1, 100, 50); - percentage = num_degrading_sessions * 100 / active_sessions_.size(); + + percentage = base::saturated_cast<double>(num_degrading_sessions * 100.0 / + active_sessions_.size()); + const std::string percentage_histogram_name = "Net.QuicConnectivityMonitor.PercentageActiveDegradingSessions." + notification; @@ -109,6 +115,11 @@ degrading_sessions_.insert(session); num_all_degraded_sessions_++; + // If the degrading session used to be on the previous default network, it is + // possible that the session is no longer tracked in |active_sessions_| due + // to the recent default network change. + active_sessions_.insert(session); + if (!num_sessions_active_during_current_speculative_connectivity_failure_) { num_sessions_active_during_current_speculative_connectivity_failure_ = active_sessions_.size(); @@ -127,6 +138,12 @@ return; degrading_sessions_.erase(session); + + // If the resumed session used to be on the previous default network, it is + // possible that the session is no longer tracked in |active_sessions_| due + // to the recent default network change. + active_sessions_.insert(session); + num_all_degraded_sessions_ = 0u; num_sessions_active_during_current_speculative_connectivity_failure_ = base::nullopt; @@ -139,6 +156,11 @@ if (network != default_network_) return; + // If the session used to be on the previous default network, it is + // possible that the session is no longer tracked in |active_sessions_| due + // to the recent default network change. + active_sessions_.insert(session); + ++write_error_map_[error_code]; bool is_session_degraded =
diff --git a/net/quic/quic_connectivity_monitor.h b/net/quic/quic_connectivity_monitor.h index e1fa650..5e26d8d 100644 --- a/net/quic/quic_connectivity_monitor.h +++ b/net/quic/quic_connectivity_monitor.h
@@ -5,6 +5,7 @@ #ifndef NET_QUIC_QUIC_CONNECTIVITY_MONITOR_H_ #define NET_QUIC_QUIC_CONNECTIVITY_MONITOR_H_ +#include "base/numerics/clamped_math.h" #include "net/base/network_change_notifier.h" #include "net/quic/quic_chromium_client_session.h" #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" @@ -104,11 +105,13 @@ // - starts by the earliest detection of path degradation or a connectivity // related packet write error, // - ends immediately by the detection of path recovery or a network change. - base::Optional<size_t> + // Use clamped math to cap number of sessions at INT_MAX. + base::Optional<base::ClampedNumeric<int>> num_sessions_active_during_current_speculative_connectivity_failure_; // Total number of sessions that has been degraded before any recovery, // including no longer active sessions. - size_t num_all_degraded_sessions_{0u}; + // Use clamped math to cap number of sessions at INT_MAX. + base::ClampedNumeric<int> num_all_degraded_sessions_{0}; // Map from the write error code to the corresponding number of reports. WriteErrorMap write_error_map_;
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index e01c45c..0dfb1f1 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -237,9 +237,6 @@ // If true, use predictable grease settings identifiers and values. QUIC_FLAG(bool, FLAGS_quic_enable_http3_grease_randomness, true) -// If true, disable QUIC version h3-25. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_draft_25, true) - // If true, disable QUIC version h3-27. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_disable_version_draft_27, false) @@ -301,16 +298,6 @@ FLAGS_quic_reloadable_flag_quic_support_handshake_done_in_t050, true) -// When true, QUIC_CRYPTO versions of QUIC will not send the max ACK delay -// unless it is configured to a non-default value. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_dont_send_max_ack_delay_if_default, - true) - -// When true, do not pad the QUIC_CRYPTO CHLO message itself. Note that the -// packet containing the CHLO will still be padded. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_dont_pad_chlo, true) - // When true, QuicDispatcher supports decapsulation of Legacy Version // Encapsulation packets. QUIC_FLAG(
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 6318e43..dbb18c5 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -97,9 +97,6 @@ return quic_version.UsesTls() ? HttpResponseInfo::CONNECTION_INFO_QUIC_T050 : HttpResponseInfo::CONNECTION_INFO_QUIC_Q050; - case quic::QUIC_VERSION_IETF_DRAFT_25: - DCHECK(quic_version.UsesTls()); - return HttpResponseInfo::CONNECTION_INFO_QUIC_DRAFT_25; case quic::QUIC_VERSION_IETF_DRAFT_27: DCHECK(quic_version.UsesTls()); return HttpResponseInfo::CONNECTION_INFO_QUIC_DRAFT_27;
diff --git a/pdf/document_loader_impl_unittest.cc b/pdf/document_loader_impl_unittest.cc index 44dd41c0..6748217 100644 --- a/pdf/document_loader_impl_unittest.cc +++ b/pdf/document_loader_impl_unittest.cc
@@ -36,6 +36,8 @@ class LoaderData { public: LoaderData() = default; + LoaderData(const LoaderData&) = delete; + LoaderData& operator=(const LoaderData&) = delete; ~LoaderData() { // We should call callbacks to prevent memory leaks. // The callbacks don't do anything, because the objects that created the @@ -135,14 +137,13 @@ int status_code_ = 0; bool closed_ = true; gfx::Range open_byte_range_ = gfx::Range::InvalidRange(); - - DISALLOW_COPY_AND_ASSIGN(LoaderData); }; explicit TestURLLoader(LoaderData* data) : data_(data) { data_->set_closed(false); } - + TestURLLoader(const TestURLLoader&) = delete; + TestURLLoader& operator=(const TestURLLoader&) = delete; ~TestURLLoader() override { Close(); } int GetContentLength() const override { return data_->content_length(); } @@ -192,13 +193,13 @@ private: LoaderData* data_; - - DISALLOW_COPY_AND_ASSIGN(TestURLLoader); }; class TestClient : public DocumentLoader::Client { public: TestClient() { full_page_loader_data()->set_content_type("application/pdf"); } + TestClient(const TestClient&) = delete; + TestClient& operator=(const TestClient&) = delete; ~TestClient() override = default; // DocumentLoader::Client overrides: @@ -248,21 +249,18 @@ private: TestURLLoader::LoaderData full_page_loader_data_; TestURLLoader::LoaderData partial_loader_data_; - - DISALLOW_COPY_AND_ASSIGN(TestClient); }; class MockClient : public TestClient { public: MockClient() = default; + MockClient(const MockClient&) = delete; + MockClient& operator=(const MockClient&) = delete; MOCK_METHOD(void, OnPendingRequestComplete, (), (override)); MOCK_METHOD(void, OnNewDataReceived, (), (override)); MOCK_METHOD(void, OnDocumentComplete, (), (override)); MOCK_METHOD(void, OnDocumentCanceled, (), (override)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockClient); }; } // namespace
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h index cafddb3..11d14e2 100644 --- a/pdf/out_of_process_instance.h +++ b/pdf/out_of_process_instance.h
@@ -16,7 +16,6 @@ #include "base/callback.h" #include "base/containers/queue.h" -#include "base/macros.h" #include "pdf/paint_manager.h" #include "pdf/pdf_view_plugin_base.h" #include "pdf/preview_mode_client.h" @@ -54,6 +53,8 @@ public PreviewModeClient::Client { public: explicit OutOfProcessInstance(PP_Instance instance); + OutOfProcessInstance(const OutOfProcessInstance&) = delete; + OutOfProcessInstance& operator=(const OutOfProcessInstance&) = delete; ~OutOfProcessInstance() override; // pp::Instance implementation. @@ -503,8 +504,6 @@ ACCESSIBILITY_STATE_PENDING, // Enabled but waiting for doc to load. ACCESSIBILITY_STATE_LOADED } accessibility_state_ = ACCESSIBILITY_STATE_OFF; - - DISALLOW_COPY_AND_ASSIGN(OutOfProcessInstance); }; } // namespace chrome_pdf
diff --git a/pdf/pdfium/findtext_unittest.cc b/pdf/pdfium/findtext_unittest.cc index 8b2e987..818a6f6 100644 --- a/pdf/pdfium/findtext_unittest.cc +++ b/pdf/pdfium/findtext_unittest.cc
@@ -19,6 +19,8 @@ class FindTextTestClient : public TestClient { public: FindTextTestClient() = default; + FindTextTestClient(const FindTextTestClient&) = delete; + FindTextTestClient& operator=(const FindTextTestClient&) = delete; ~FindTextTestClient() override = default; // PDFEngine::Client: @@ -48,9 +50,6 @@ } return results; } - - private: - DISALLOW_COPY_AND_ASSIGN(FindTextTestClient); }; } // namespace
diff --git a/pdf/pdfium/pdfium_api_string_buffer_adapter.h b/pdf/pdfium/pdfium_api_string_buffer_adapter.h index fd806c78..320488b8 100644 --- a/pdf/pdfium/pdfium_api_string_buffer_adapter.h +++ b/pdf/pdfium/pdfium_api_string_buffer_adapter.h
@@ -10,7 +10,6 @@ #include <string> #include "base/callback.h" -#include "base/macros.h" #include "base/numerics/safe_math.h" #include "base/optional.h" #include "base/strings/string16.h" @@ -34,6 +33,9 @@ PDFiumAPIStringBufferAdapter(StringType* str, size_t expected_size, bool check_expected_size); + PDFiumAPIStringBufferAdapter(const PDFiumAPIStringBufferAdapter&) = delete; + PDFiumAPIStringBufferAdapter& operator=(const PDFiumAPIStringBufferAdapter&) = + delete; ~PDFiumAPIStringBufferAdapter(); // Returns a pointer to |str_|'s buffer. The buffer's size is large enough to @@ -57,8 +59,6 @@ const size_t expected_size_; const bool check_expected_size_; bool is_closed_; - - DISALLOW_COPY_AND_ASSIGN(PDFiumAPIStringBufferAdapter); }; // Helper to deal with the fact that many PDFium APIs write the null-terminator
diff --git a/pdf/pdfium/pdfium_document.h b/pdf/pdfium/pdfium_document.h index db3fb37..0df76d8b 100644 --- a/pdf/pdfium/pdfium_document.h +++ b/pdf/pdfium/pdfium_document.h
@@ -8,7 +8,6 @@ #include <memory> #include <string> -#include "base/macros.h" #include "third_party/pdfium/public/cpp/fpdf_scopers.h" #include "third_party/pdfium/public/fpdf_dataavail.h" #include "third_party/pdfium/public/fpdfview.h" @@ -20,6 +19,8 @@ class PDFiumDocument { public: explicit PDFiumDocument(DocumentLoader* doc_loader); + PDFiumDocument(const PDFiumDocument&) = delete; + PDFiumDocument& operator=(const PDFiumDocument&) = delete; ~PDFiumDocument(); FPDF_FILEACCESS& file_access() { return *file_access_; } @@ -65,8 +66,6 @@ // Current form availability status. int form_status_ = PDF_FORM_NOTAVAIL; - - DISALLOW_COPY_AND_ASSIGN(PDFiumDocument); }; } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index 04bf55dd..2993db8 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -13,7 +13,6 @@ #include <string> #include <vector> -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/time.h" @@ -223,6 +222,8 @@ public: MouseDownState(const PDFiumPage::Area& area, const PDFiumPage::LinkTarget& target); + MouseDownState(const MouseDownState&) = delete; + MouseDownState& operator=(const MouseDownState&) = delete; ~MouseDownState(); void Set(const PDFiumPage::Area& area, @@ -234,8 +235,6 @@ private: PDFiumPage::Area area_; PDFiumPage::LinkTarget target_; - - DISALLOW_COPY_AND_ASSIGN(MouseDownState); }; friend class FormFillerTest;
diff --git a/pdf/pdfium/pdfium_engine_exports.h b/pdf/pdfium/pdfium_engine_exports.h index e734390..6f5f075 100644 --- a/pdf/pdfium/pdfium_engine_exports.h +++ b/pdf/pdfium/pdfium_engine_exports.h
@@ -16,6 +16,8 @@ class PDFiumEngineExports : public PDFEngineExports { public: PDFiumEngineExports(); + PDFiumEngineExports(const PDFiumEngineExports&) = delete; + PDFiumEngineExports& operator=(const PDFiumEngineExports&) = delete; ~PDFiumEngineExports() override; // PDFEngineExports: @@ -59,9 +61,6 @@ int page_number, double* width, double* height) override; - - private: - DISALLOW_COPY_AND_ASSIGN(PDFiumEngineExports); }; } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_engine_exports_unittest.cc b/pdf/pdfium/pdfium_engine_exports_unittest.cc index 6cb86713..012b2ca 100644 --- a/pdf/pdfium/pdfium_engine_exports_unittest.cc +++ b/pdf/pdfium/pdfium_engine_exports_unittest.cc
@@ -29,6 +29,8 @@ class PDFiumEngineExportsTest : public testing::Test { public: PDFiumEngineExportsTest() = default; + PDFiumEngineExportsTest(const PDFiumEngineExportsTest&) = delete; + PDFiumEngineExportsTest& operator=(const PDFiumEngineExportsTest&) = delete; ~PDFiumEngineExportsTest() override = default; protected: @@ -49,8 +51,6 @@ private: std::unique_ptr<base::ThreadTaskRunnerHandle> handle_; base::FilePath pdf_data_dir_; - - DISALLOW_COPY_AND_ASSIGN(PDFiumEngineExportsTest); }; } // namespace
diff --git a/pdf/pdfium/pdfium_form_filler.h b/pdf/pdfium/pdfium_form_filler.h index 7f2355e..e362db8 100644 --- a/pdf/pdfium/pdfium_form_filler.h +++ b/pdf/pdfium/pdfium_form_filler.h
@@ -8,7 +8,6 @@ #include <map> #include <memory> -#include "base/macros.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "third_party/pdfium/public/fpdf_formfill.h"
diff --git a/pdf/pdfium/pdfium_page.h b/pdf/pdfium/pdfium_page.h index c228866a..06d0810 100644 --- a/pdf/pdfium/pdfium_page.h +++ b/pdf/pdfium/pdfium_page.h
@@ -31,6 +31,8 @@ class PDFiumPage { public: PDFiumPage(PDFiumEngine* engine, int i); + PDFiumPage(const PDFiumPage&) = delete; + PDFiumPage& operator=(const PDFiumPage&) = delete; PDFiumPage(PDFiumPage&& that); ~PDFiumPage(); @@ -387,8 +389,6 @@ // objects. std::set<int> page_object_text_run_breaks_; bool available_; - - DISALLOW_COPY_AND_ASSIGN(PDFiumPage); }; // Converts page orientations to the PDFium equivalents, as defined by
diff --git a/pdf/pdfium/pdfium_page_unittest.cc b/pdf/pdfium/pdfium_page_unittest.cc index 3cec1b6..a7e188f2 100644 --- a/pdf/pdfium/pdfium_page_unittest.cc +++ b/pdf/pdfium/pdfium_page_unittest.cc
@@ -86,6 +86,8 @@ class PDFiumPageLinkTest : public PDFiumTestBase { public: PDFiumPageLinkTest() = default; + PDFiumPageLinkTest(const PDFiumPageLinkTest&) = delete; + PDFiumPageLinkTest& operator=(const PDFiumPageLinkTest&) = delete; ~PDFiumPageLinkTest() override = default; const std::vector<PDFiumPage::Link>& GetLinks(PDFiumEngine* engine, @@ -95,8 +97,6 @@ page->CalculateLinks(); return page->links_; } - - DISALLOW_COPY_AND_ASSIGN(PDFiumPageLinkTest); }; TEST_F(PDFiumPageLinkTest, TestLinkGeneration) {
diff --git a/pdf/pdfium/pdfium_print.h b/pdf/pdfium/pdfium_print.h index 764a125..b2d6ad2 100644 --- a/pdf/pdfium/pdfium_print.h +++ b/pdf/pdfium/pdfium_print.h
@@ -7,7 +7,6 @@ #include <vector> -#include "base/macros.h" #include "build/build_config.h" #include "third_party/pdfium/public/cpp/fpdf_scopers.h" #include "third_party/pdfium/public/fpdfview.h" @@ -28,6 +27,8 @@ class PDFiumPrint { public: explicit PDFiumPrint(PDFiumEngine* engine); + PDFiumPrint(const PDFiumPrint&) = delete; + PDFiumPrint& operator=(const PDFiumPrint&) = delete; ~PDFiumPrint(); #if defined(OS_CHROMEOS) @@ -86,8 +87,6 @@ const PP_PrintSettings_Dev& print_settings); PDFiumEngine* const engine_; - - DISALLOW_COPY_AND_ASSIGN(PDFiumPrint); }; } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_unsupported_features.h b/pdf/pdfium/pdfium_unsupported_features.h index 35f5e1d2..9823802f 100644 --- a/pdf/pdfium/pdfium_unsupported_features.h +++ b/pdf/pdfium/pdfium_unsupported_features.h
@@ -5,8 +5,6 @@ #ifndef PDF_PDFIUM_PDFIUM_UNSUPPORTED_FEATURES_H_ #define PDF_PDFIUM_PDFIUM_UNSUPPORTED_FEATURES_H_ -#include "base/macros.h" - namespace chrome_pdf { class PDFiumEngine; @@ -18,12 +16,12 @@ class ScopedUnsupportedFeature { public: explicit ScopedUnsupportedFeature(PDFiumEngine* engine); + ScopedUnsupportedFeature(const ScopedUnsupportedFeature&) = delete; + ScopedUnsupportedFeature& operator=(const ScopedUnsupportedFeature&) = delete; ~ScopedUnsupportedFeature(); private: PDFiumEngine* const old_engine_; - - DISALLOW_COPY_AND_ASSIGN(ScopedUnsupportedFeature); }; } // namespace chrome_pdf
diff --git a/remoting/protocol/webrtc_dummy_video_encoder.cc b/remoting/protocol/webrtc_dummy_video_encoder.cc index 29c8a961..58da05e 100644 --- a/remoting/protocol/webrtc_dummy_video_encoder.cc +++ b/remoting/protocol/webrtc_dummy_video_encoder.cc
@@ -273,7 +273,6 @@ WebrtcDummyVideoEncoderFactory::QueryVideoEncoder( const webrtc::SdpVideoFormat& format) const { CodecInfo codec_info; - codec_info.is_hardware_accelerated = true; // Set internal source to true to directly provide encoded frames to webrtc. codec_info.has_internal_source = true; return codec_info;
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index 782b059..899c2dea 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -5654,7 +5654,15 @@ } }; -TEST_F(NetworkContextMockHostTest, CustomProxyUsesSpecifiedProxyList) { +#if defined(OS_LINUX) +// Flaky crashes on Linux: https://crbug.com/1115201 +#define MAYBE_CustomProxyUsesSpecifiedProxyList \ + DISABLED_CustomProxyUsesSpecifiedProxyList +#else +#define MAYBE_CustomProxyUsesSpecifiedProxyList \ + CustomProxyUsesSpecifiedProxyList +#endif +TEST_F(NetworkContextMockHostTest, MAYBE_CustomProxyUsesSpecifiedProxyList) { net::EmbeddedTestServer proxy_test_server; net::test_server::RegisterDefaultHandlers(&proxy_test_server); ASSERT_TRUE(proxy_test_server.Start());
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc index 94013f4e..1902cca8 100644 --- a/storage/browser/blob/blob_registry_impl.cc +++ b/storage/browser/blob/blob_registry_impl.cc
@@ -372,8 +372,10 @@ for (const auto& entry : elements_) { auto& element = entry.element; if (element->is_bytes()) { - transport_strategy_->AddBytesElement(element->get_bytes().get(), - entry.bytes_provider); + if (element->get_bytes()->length > 0) { + transport_strategy_->AddBytesElement(element->get_bytes().get(), + entry.bytes_provider); + } } else if (element->is_file()) { const auto& f = element->get_file(); builder_->AppendFile(
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc index e418597..a3207ff 100644 --- a/storage/browser/blob/blob_registry_impl_unittest.cc +++ b/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -294,6 +294,37 @@ EXPECT_EQ(0u, BlobsUnderConstruction()); } +TEST_F(BlobRegistryImplTest, Register_EmptyBytesBlob) { + const std::string kId = "id"; + const std::string kContentType = "content/type"; + const std::string kContentDisposition = "disposition"; + + std::vector<blink::mojom::DataElementPtr> elements; + elements.push_back( + blink::mojom::DataElement::NewBytes(blink::mojom::DataElementBytes::New( + 0, base::nullopt, CreateBytesProvider("")))); + + mojo::Remote<blink::mojom::Blob> blob; + EXPECT_TRUE(registry_->Register(blob.BindNewPipeAndPassReceiver(), kId, + kContentType, kContentDisposition, + std::move(elements))); + + EXPECT_TRUE(bad_messages_.empty()); + + EXPECT_EQ(kId, UUIDFromBlob(blob.get())); + EXPECT_TRUE(context_->registry().HasEntry(kId)); + std::unique_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId); + EXPECT_EQ(kContentType, handle->content_type()); + EXPECT_EQ(kContentDisposition, handle->content_disposition()); + EXPECT_EQ(0u, handle->size()); + + WaitForBlobCompletion(handle.get()); + + EXPECT_FALSE(handle->IsBroken()); + EXPECT_EQ(BlobStatus::DONE, handle->GetBlobStatus()); + EXPECT_EQ(0u, BlobsUnderConstruction()); +} + TEST_F(BlobRegistryImplTest, Register_ReferencedBlobClosedPipe) { const std::string kId = "id";
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index cdacdd2..354098c 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -1819,6 +1819,12 @@ "test_id_prefix": "ninja://chrome/browser/password_check/android:password_check_junit_tests/" }, { + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests", @@ -20169,6 +20175,12 @@ "test_id_prefix": "ninja://chrome/browser/password_check/android:password_check_junit_tests/" }, { + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests", @@ -28686,6 +28698,13 @@ }, { "isolate_profile_data": true, + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { + "isolate_profile_data": true, "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests",
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json index 84bf803..2a377433 100644 --- a/testing/buildbot/chromium.ci.json +++ b/testing/buildbot/chromium.ci.json
@@ -13388,6 +13388,12 @@ "test_id_prefix": "ninja://chrome/browser/password_check/android:password_check_junit_tests/" }, { + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests", @@ -95782,6 +95788,12 @@ "test_id_prefix": "ninja://chrome/browser/password_check/android:password_check_junit_tests/" }, { + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests", @@ -162670,6 +162682,12 @@ "test_id_prefix": "ninja://chrome/browser/password_check/android:password_check_junit_tests/" }, { + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests", @@ -169480,6 +169498,13 @@ }, { "isolate_profile_data": true, + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { + "isolate_profile_data": true, "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests", @@ -180007,6 +180032,13 @@ }, { "isolate_profile_data": true, + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { + "isolate_profile_data": true, "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests",
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 6765693..bf6ef43 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -8078,6 +8078,12 @@ "test_id_prefix": "ninja://chrome/browser/password_check/android:password_check_junit_tests/" }, { + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 5606e3a..767346b 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -9835,6 +9835,13 @@ }, { "isolate_profile_data": true, + "name": "password_manager_junit_tests", + "swarming": {}, + "test": "password_manager_junit_tests", + "test_id_prefix": "ninja://chrome/browser/password_manager/android:password_manager_junit_tests/" + }, + { + "isolate_profile_data": true, "name": "services_junit_tests", "swarming": {}, "test": "services_junit_tests",
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter index ba932d4..44c7a42 100644 --- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter +++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter
@@ -4,7 +4,24 @@ -ActiveDirectoryJoinTest.* -ActiveDirectoryLoginAutocompleteTest.* -ActiveDirectoryLoginTest.* +-All/DiscoverScreenTest.* +-All/EphemeralUserOobeTest.* +-All/GestureNavigationScreenTest.* +-All/MergeSessionTest.* +-All/MergeSessionTimeoutTest.* -All/OobeGuestButtonPolicy.* +-All/OobeInteractiveUITest.* +-All/OobeLocalizationTest.* +-All/OobeZeroTouchInteractiveUITest.* +-All/ParameterizedArcTermsOfServiceScreenTest.* +-All/PublicSessionOobeTest.* +-All/PublicSessionWithTermsOfServiceOobeTest.* +-All/SAMLPasswordAttributesTest.* +-All/SyncConsentPolicyDisabledTest.* +-All/SyncConsentTestWithParams.* +-All/WebviewLoginWithIframeTest.* +-All/WizardControllerDeviceStateExplicitRequirementTest.* +-All/WizardControllerUpdateAfterCompletedOobeTest.* -AppDownloadingScreenTest.* -ArcTermsOfServiceScreenTest.* -AssistantOptInFlowTest.* @@ -13,8 +30,8 @@ -AutoEnrollmentWithStatistics.* -BlockingLoginTest.* -ChallengeResponseAuthKeysLoaderBrowserTest.* --DebugOverlayTest.* -DebugOverlayOnLoginTest.* +-DebugOverlayTest.* -DemoSessionActiveDirectoryDeviceTest.* -DemoSessionConsumerDeviceTest.* -DemoSessionDemoDeviceModeTest.* @@ -29,7 +46,6 @@ -DeviceDisablingBeforeLoginHostCreated.* -DeviceDisablingTest.* -DeviceIDTest.* --DiscoverScreenTest.* -DockedMagnifierVirtualKeyboardTest.* -EnableDebuggingDevTest.* -EnableDebuggingNonDevTest.* @@ -60,10 +76,11 @@ -LoginCursorTest.* -LoginOfflineTest.* -LoginPolicyTestBase.* --MarketingOptInScreenTest.* +-MarketingOptInDefaultContries/MarketingOptInScreenTest.* +-MarketingOptInDoubleOptInCountriesContries/MarketingOptInScreenTest.* +-MarketingOptInExtendedContries/MarketingOptInScreenTest.* -MarketingOptInScreenTestDisabled.* --MergeSessionTest.* --MergeSessionTimeoutTest.* +-NetworkErrorScreenTest.* -OAuth2Test.* -OobeBaseTest.* -OobeCompletedUnownedTest.* @@ -72,13 +89,10 @@ -OobeConfigurationTest.* -OobeConfigurationTestNoHID.* -OobeDisplayChooserTest.* --OobeInteractiveUITest.* --OobeLocalizationTest.* -OobeSpokenFeedbackTest.* -OobeTest.* -OobeZeroTouchInteractiveUITest.* -PackagedLicenseScreenTest.* --ParameterizedArcTermsOfServiceScreenTest.* -PolicyProvidedCertsOnUserSessionInitTest.* -PresetPolicyDeviceDisablingTest.* -PrimaryUserPoliciesProxiedTest.* @@ -96,17 +110,14 @@ -RestoreOnStartupTestChromeOS.* -SAMLDeviceAttestationTest.* -SAMLEnrollmentTest.* --SAMLPasswordAttributesTest.* -SAMLPolicyTest.* -SamlTest.* -SecurityTokenSamlTest.* -SiteIsolationFlagHandlingTest.* -StartupBrowserWindowLaunchSuppressedTest.* --SyncConsentPolicyDisabledTest.* -SyncConsentRecorderTest.* -SyncConsentSplitSettingsSyncTest.* -SyncConsentTest.* --SyncConsentTestWithParams.* -SyncConsentTimezoneOverride.* -SystemWebDialogOobeTest.* -TermsOfServiceScreenTest.* @@ -118,7 +129,6 @@ -WebviewClientCertsLoginTestBase.* -WebviewClientCertsTokenLoadingLoginTest.* -WebviewLoginTest.* --WebviewLoginWithIframeTest.* -WebviewProxyAuthLoginTest.* -WelcomeScreenBrowserTest.* -WelcomeScreenSystemDevModeBrowserTest.* @@ -127,7 +137,6 @@ -WizardControllerCellularFirstTest.* -WizardControllerDemoSetupDeviceDisabledTest.* -WizardControllerDemoSetupTest.* --WizardControllerDeviceStateExplicitRequirementTest.* -WizardControllerDeviceStateTest.* -WizardControllerDeviceStateWithInitialEnrollmentTest.* -WizardControllerEnableAdbSideloadingTest.* @@ -139,4 +148,3 @@ -WizardControllerProxyAuthOnSigninTest.* -WizardControllerScreenPriorityOOBETest.* -WizardControllerTest.* --WizardControllerUpdateAfterCompletedOobeTest.*
diff --git a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter index 75e51ddcc..bf0a76a 100644 --- a/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter +++ b/testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter
@@ -4,7 +4,24 @@ ActiveDirectoryJoinTest.* ActiveDirectoryLoginAutocompleteTest.* ActiveDirectoryLoginTest.* +All/DiscoverScreenTest.* +All/EphemeralUserOobeTest.* +All/GestureNavigationScreenTest.* +All/MergeSessionTest.* +All/MergeSessionTimeoutTest.* All/OobeGuestButtonPolicy.* +All/OobeInteractiveUITest.* +All/OobeLocalizationTest.* +All/OobeZeroTouchInteractiveUITest.* +All/ParameterizedArcTermsOfServiceScreenTest.* +All/PublicSessionOobeTest.* +All/PublicSessionWithTermsOfServiceOobeTest.* +All/SAMLPasswordAttributesTest.* +All/SyncConsentPolicyDisabledTest.* +All/SyncConsentTestWithParams.* +All/WebviewLoginWithIframeTest.* +All/WizardControllerDeviceStateExplicitRequirementTest.* +All/WizardControllerUpdateAfterCompletedOobeTest.* AppDownloadingScreenTest.* ArcTermsOfServiceScreenTest.* AssistantOptInFlowTest.* @@ -13,8 +30,8 @@ AutoEnrollmentWithStatistics.* BlockingLoginTest.* ChallengeResponseAuthKeysLoaderBrowserTest.* -DebugOverlayTest.* DebugOverlayOnLoginTest.* +DebugOverlayTest.* DemoSessionActiveDirectoryDeviceTest.* DemoSessionConsumerDeviceTest.* DemoSessionDemoDeviceModeTest.* @@ -29,7 +46,6 @@ DeviceDisablingBeforeLoginHostCreated.* DeviceDisablingTest.* DeviceIDTest.* -DiscoverScreenTest.* DockedMagnifierVirtualKeyboardTest.* EnableDebuggingDevTest.* EnableDebuggingNonDevTest.* @@ -60,10 +76,11 @@ LoginCursorTest.* LoginOfflineTest.* LoginPolicyTestBase.* -MarketingOptInScreenTest.* +MarketingOptInDefaultContries/MarketingOptInScreenTest.* +MarketingOptInDoubleOptInCountriesContries/MarketingOptInScreenTest.* +MarketingOptInExtendedContries/MarketingOptInScreenTest.* MarketingOptInScreenTestDisabled.* -MergeSessionTest.* -MergeSessionTimeoutTest.* +NetworkErrorScreenTest.* OAuth2Test.* OobeBaseTest.* OobeCompletedUnownedTest.* @@ -72,13 +89,10 @@ OobeConfigurationTest.* OobeConfigurationTestNoHID.* OobeDisplayChooserTest.* -OobeInteractiveUITest.* -OobeLocalizationTest.* OobeSpokenFeedbackTest.* OobeTest.* OobeZeroTouchInteractiveUITest.* PackagedLicenseScreenTest.* -ParameterizedArcTermsOfServiceScreenTest.* PolicyProvidedCertsOnUserSessionInitTest.* PresetPolicyDeviceDisablingTest.* PrimaryUserPoliciesProxiedTest.* @@ -96,17 +110,14 @@ RestoreOnStartupTestChromeOS.* SAMLDeviceAttestationTest.* SAMLEnrollmentTest.* -SAMLPasswordAttributesTest.* SAMLPolicyTest.* SamlTest.* SecurityTokenSamlTest.* SiteIsolationFlagHandlingTest.* StartupBrowserWindowLaunchSuppressedTest.* -SyncConsentPolicyDisabledTest.* SyncConsentRecorderTest.* SyncConsentSplitSettingsSyncTest.* SyncConsentTest.* -SyncConsentTestWithParams.* SyncConsentTimezoneOverride.* SystemWebDialogOobeTest.* TermsOfServiceScreenTest.* @@ -118,7 +129,6 @@ WebviewClientCertsLoginTestBase.* WebviewClientCertsTokenLoadingLoginTest.* WebviewLoginTest.* -WebviewLoginWithIframeTest.* WebviewProxyAuthLoginTest.* WelcomeScreenBrowserTest.* WelcomeScreenSystemDevModeBrowserTest.* @@ -127,7 +137,6 @@ WizardControllerCellularFirstTest.* WizardControllerDemoSetupDeviceDisabledTest.* WizardControllerDemoSetupTest.* -WizardControllerDeviceStateExplicitRequirementTest.* WizardControllerDeviceStateTest.* WizardControllerDeviceStateWithInitialEnrollmentTest.* WizardControllerEnableAdbSideloadingTest.* @@ -139,4 +148,3 @@ WizardControllerProxyAuthOnSigninTest.* WizardControllerScreenPriorityOOBETest.* WizardControllerTest.* -WizardControllerUpdateAfterCompletedOobeTest.*
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index a111b5c..7246387 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1358,6 +1358,10 @@ "label": "//chrome/browser/password_check/android:password_check_junit_tests", "type": "junit_test", }, + "password_manager_junit_tests": { + "label": "//chrome/browser/password_manager/android:password_manager_junit_tests", + "type": "junit_test", + }, "pdf_fuzzers": { "label": "//pdf/pdfium/fuzzers:pdf_fuzzers", "type": "additional_compile_target",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index 1d385d3..1e38b7c 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py
@@ -139,6 +139,7 @@ 'net_junit_tests', 'net_junit_tests', 'password_check_junit_tests', + 'password_manager_junit_tests', 'services_junit_tests', 'shipped_binaries', 'system_webview_apk',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 7cbdf4d..38a2170 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -803,6 +803,7 @@ 'net_junit_tests': {}, 'paint_preview_junit_tests': {}, 'password_check_junit_tests': {}, + 'password_manager_junit_tests': {}, 'services_junit_tests': {}, 'touch_to_fill_junit_tests': {}, 'ui_junit_tests': {},
diff --git a/third_party/abseil-cpp/OWNERS b/third_party/abseil-cpp/OWNERS index 6865063..af171cf 100644 --- a/third_party/abseil-cpp/OWNERS +++ b/third_party/abseil-cpp/OWNERS
@@ -1,6 +1,5 @@ danilchap@chromium.org kwiberg@chromium.org mbonadei@chromium.org -phoglund@chromium.org # COMPONENT: Internals>Core
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index bf71f1c..e59d2bc 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -581,7 +581,8 @@ // The AppCache feature is a kill-switch for the entire AppCache feature, // both backend and API. If disabled, then it will turn off the backend and -// api, regardless of the presence of valid origin trial tokens. +// api, regardless of the presence of valid origin trial tokens. Disabling +// AppCache will also delete any AppCache data from the profile directory. const base::Feature kAppCache{"AppCache", base::FEATURE_ENABLED_BY_DEFAULT}; // If AppCacheRequireOriginTrial is enabled, then the AppCache backend in the // browser will require origin trial tokens in order to load or store manifests
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index 71ff0d0..e27aa92e 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -1927,8 +1927,6 @@ kBackgroundFetchRegistrationAbort = 2552, kBackgroundFetchRegistrationMatch = 2553, kBackgroundFetchRegistrationMatchAll = 2554, - kV8AtomicsNotify = 2555, - kV8AtomicsWake = 2556, kFormDisabledAttributePresent = 2557, kFormDisabledAttributePresentAndSubmit = 2558, kCSSValueAppearanceCheckboxRendered = 2559,
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index f3c18b7..9e8f2404a 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -323,13 +323,15 @@ // Auto-Resize ----------------------------------------------------------- - // In auto-resize mode, the view is automatically adjusted to fit the html - // content within the given bounds. - virtual void EnableAutoResizeMode(const WebSize& min_size, - const WebSize& max_size) = 0; + // Return the state of the auto resize mode. + virtual bool AutoResizeMode() = 0; - // Turn off auto-resize. - virtual void DisableAutoResizeMode() = 0; + // Enable auto resize. + virtual void EnableAutoResizeForTesting(const gfx::Size& min_size, + const gfx::Size& max_size) = 0; + + // Disable auto resize. + virtual void DisableAutoResizeForTesting(const gfx::Size& new_size) = 0; // Data exchange ------------------------------------------------------- @@ -352,7 +354,6 @@ // Cancel emulation started via |enableDeviceEmulation| call. virtual void DisableDeviceEmulation() = 0; - // Context menu -------------------------------------------------------- virtual void PerformCustomContextMenuAction(unsigned action) = 0;
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h index 9eb25ffd..e1f5b474 100644 --- a/third_party/blink/public/web/web_widget_client.h +++ b/third_party/blink/public/web/web_widget_client.h
@@ -127,6 +127,9 @@ // content view area, i.e. doesn't include any window decorations. virtual WebRect ViewRect() { return WebRect(); } + // Set the size of the widget. + virtual void SetSize(const gfx::Size&) {} + // Requests to lock the mouse cursor for the |requester_frame| in the // widget. If true is returned, the success result will be asynchronously // returned via a single call to WebWidget::didAcquirePointerLock() or
diff --git a/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc b/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc index 2db4ebb..73980312 100644 --- a/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc +++ b/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc
@@ -65,11 +65,9 @@ template <typename CallbackInfo> static void LocationAttributeGet(const CallbackInfo& info) { - v8::Isolate* isolate = info.GetIsolate(); v8::Local<v8::Object> holder = info.Holder(); - DOMWindow* window = V8Window::ToImpl(holder); - window->ReportCoopAccess(isolate, "location"); + window->ReportCoopAccess("location"); Location* location = window->location(); DCHECK(location); @@ -77,6 +75,7 @@ if (DOMDataStore::SetReturnValue(info.GetReturnValue(), location)) return; + v8::Isolate* isolate = info.GetIsolate(); v8::Local<v8::Value> wrapper; // Note that this check is gated on whether or not |window| is remote, not @@ -141,9 +140,8 @@ template <typename CallbackInfo> static void OpenerAttributeSet(v8::Local<v8::Value> value, const CallbackInfo& info) { - v8::Isolate* isolate = info.GetIsolate(); DOMWindow* impl = V8Window::ToImpl(info.Holder()); - impl->ReportCoopAccess(isolate, "opener"); + impl->ReportCoopAccess("opener"); if (!impl->GetFrame()) return; @@ -157,6 +155,7 @@ To<LocalFrame>(impl->GetFrame())->Loader().SetOpener(nullptr); } + v8::Isolate* isolate = info.GetIsolate(); // Delete the accessor from the inner object. if (info.Holder() ->Delete(isolate->GetCurrentContext(), @@ -210,7 +209,7 @@ // https://html.spec.whatwg.org/C/#document-tree-child-browsing-context-name-property-set Frame* child = frame->Tree().ScopedChild(name); if (child) { - window->ReportCoopAccess(info.GetIsolate(), "named"); + window->ReportCoopAccess("named"); UseCounter::Count(CurrentExecutionContext(info.GetIsolate()), WebFeature::kNamedAccessOnWindow_ChildBrowsingContext); @@ -271,7 +270,7 @@ if (!has_named_item && !has_id_item) return; - window->ReportCoopAccess(info.GetIsolate(), "named"); + window->ReportCoopAccess("named"); if (!has_named_item && has_id_item && !doc->ContainsMultipleElementsWithId(name)) {
diff --git a/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc b/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc index 2d907ef0..7be29b2 100644 --- a/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc +++ b/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
@@ -161,13 +161,6 @@ case v8::Isolate::kWasmSimdOpcodes: blink_feature = WebFeature::kV8WasmSimdOpcodes; break; - case v8::Isolate::kAtomicsNotify: - blink_feature = WebFeature::kV8AtomicsNotify; - break; - case v8::Isolate::kAtomicsWake: - blink_feature = WebFeature::kV8AtomicsWake; - deprecated = true; - break; case v8::Isolate::kCollator: blink_feature = WebFeature::kCollator; break;
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index fcb6f7f..7dcbbba 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -418,7 +418,6 @@ "//third_party/blink/renderer/modules/payments/address_init.idl", "//third_party/blink/renderer/modules/payments/android_pay_method_data.idl", "//third_party/blink/renderer/modules/payments/basic_card_request.idl", - "//third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl", "//third_party/blink/renderer/modules/payments/can_make_payment_event.idl", "//third_party/blink/renderer/modules/payments/can_make_payment_event_init.idl", "//third_party/blink/renderer/modules/payments/can_make_payment_response.idl",
diff --git a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl index d470c3b..8cfbc5e 100644 --- a/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/attributes.cc.tmpl
@@ -70,7 +70,7 @@ {% endif %}{# not attribute.is_static #} {% if interface_name == "Window" and attribute.has_cross_origin_getter %} - impl->ReportCoopAccess(info.GetIsolate(), "{{attribute.name}}"); + impl->ReportCoopAccess("{{attribute.name}}"); {% endif %} {% if attribute.cached_attribute_validation_method %}
diff --git a/third_party/blink/renderer/bindings/templates/methods.cc.tmpl b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl index 6823bfa..f9bf0bc 100644 --- a/third_party/blink/renderer/bindings/templates/methods.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/methods.cc.tmpl
@@ -55,7 +55,7 @@ {% endif %}{# not method.is_static #} {% if interface_name == "Window" and method.is_cross_origin %} - impl->ReportCoopAccess(info.GetIsolate(), "{{method.name}}"); + impl->ReportCoopAccess("{{method.name}}"); {% endif %} {# Security checks #}
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer_item.h b/third_party/blink/renderer/core/clipboard/data_transfer_item.h index f055fb3..5b8eb4a 100644 --- a/third_party/blink/renderer/core/clipboard/data_transfer_item.h +++ b/third_party/blink/renderer/core/clipboard/data_transfer_item.h
@@ -55,6 +55,8 @@ public: explicit DataTransferItem(DataTransfer*, DataObjectItem*); + DataTransferItem(const DataTransferItem&) = delete; + DataTransferItem& operator=(const DataTransferItem&) = delete; String kind() const; String type() const; @@ -75,7 +77,6 @@ Member<DataTransfer> data_transfer_; Member<DataObjectItem> item_; - DISALLOW_COPY_AND_ASSIGN(DataTransferItem); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h b/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h index b1f37d5..15fbc94 100644 --- a/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h +++ b/third_party/blink/renderer/core/clipboard/dragged_isolated_file_system.h
@@ -17,6 +17,10 @@ class CORE_EXPORT DraggedIsolatedFileSystem { public: DraggedIsolatedFileSystem() = default; + DraggedIsolatedFileSystem(const DraggedIsolatedFileSystem&) = delete; + DraggedIsolatedFileSystem& operator=(const DraggedIsolatedFileSystem&) = + delete; + virtual ~DraggedIsolatedFileSystem() = default; using FileSystemIdPreparationCallback = void (*)(DataObject*); @@ -27,7 +31,6 @@ private: static FileSystemIdPreparationCallback prepare_callback_; - DISALLOW_COPY_AND_ASSIGN(DraggedIsolatedFileSystem); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.h b/third_party/blink/renderer/core/clipboard/system_clipboard.h index 04a769dd..b0e4f95 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.h +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -32,6 +32,9 @@ enum SmartReplaceOption { kCanSmartReplace, kCannotSmartReplace }; explicit SystemClipboard(LocalFrame* frame); + SystemClipboard(const SystemClipboard&) = delete; + SystemClipboard& operator=(const SystemClipboard&) = delete; + uint64_t SequenceNumber(); bool IsSelectionMode() const; void SetSelectionMode(bool); @@ -87,7 +90,6 @@ // Whether the selection buffer is available on the underlying platform. bool is_selection_buffer_available_ = false; - DISALLOW_COPY_AND_ASSIGN(SystemClipboard); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 91703eb..fc73acd 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -2525,11 +2525,11 @@ } } -void WebViewImpl::EnableAutoResizeMode(const WebSize& min_size, - const WebSize& max_size) { +void WebViewImpl::EnableAutoResizeMode(const gfx::Size& min_size, + const gfx::Size& max_size) { should_auto_resize_ = true; - min_auto_size_ = min_size; - max_auto_size_ = max_size; + min_auto_size_ = IntSize(min_size); + max_auto_size_ = IntSize(max_size); ConfigureAutoResizeMode(); } @@ -2538,6 +2538,37 @@ ConfigureAutoResizeMode(); } +bool WebViewImpl::AutoResizeMode() { + return should_auto_resize_; +} + +void WebViewImpl::EnableAutoResizeForTesting(const gfx::Size& min_window_size, + const gfx::Size& max_window_size) { + float scale_factor = 1.f; + if (Platform::Current()->IsUseZoomForDSFEnabled()) { + scale_factor = MainFrameImpl() + ->FrameWidgetImpl() + ->Client() + ->GetScreenInfo() + .device_scale_factor; + } + EnableAutoResizeMode(gfx::ScaleToCeiledSize(min_window_size, scale_factor), + gfx::ScaleToCeiledSize(max_window_size, scale_factor)); +} + +void WebViewImpl::DisableAutoResizeForTesting( + const gfx::Size& new_window_size) { + if (!should_auto_resize_) + return; + DisableAutoResizeMode(); + + // The |new_size| is empty when resetting auto resize in between tests. In + // this case the current size should just be preserved. + if (!new_window_size.IsEmpty()) { + MainFrameImpl()->FrameWidgetImpl()->Client()->SetSize(new_window_size); + } +} + void WebViewImpl::SetDefaultPageScaleLimits(float min_scale, float max_scale) { GetPage()->SetDefaultPageScaleLimits(min_scale, max_scale); }
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 53b6ea2..497c4a0 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -188,9 +188,10 @@ float ZoomFactorForDeviceScaleFactor() override { return zoom_factor_for_device_scale_factor_; } - void EnableAutoResizeMode(const WebSize& min_size, - const WebSize& max_size) override; - void DisableAutoResizeMode() override; + bool AutoResizeMode() override; + void EnableAutoResizeForTesting(const gfx::Size& min_window_size, + const gfx::Size& max_window_size) override; + void DisableAutoResizeForTesting(const gfx::Size& new_window_size) override; WebHitTestResult HitTestResultAt(const gfx::PointF&); WebHitTestResult HitTestResultForTap(const gfx::Point&, const WebSize&) override; @@ -242,6 +243,9 @@ void SetZoomFactorOverride(float); void SetCompositorDeviceScaleFactorOverride(float); TransformationMatrix GetDeviceEmulationTransform() const; + void EnableAutoResizeMode(const gfx::Size& min_viewport_size, + const gfx::Size& max_viewport_size); + void DisableAutoResizeMode(); SkColor BackgroundColor() const; Color BaseBackgroundColor() const;
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index e784829..500fd32 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -246,8 +246,8 @@ .Utf8(); } - void TestAutoResize(const WebSize& min_auto_resize, - const WebSize& max_auto_resize, + void TestAutoResize(const gfx::Size& min_auto_resize, + const gfx::Size& max_auto_resize, const std::string& page_width, const std::string& page_height, int expected_width, @@ -862,8 +862,8 @@ } void WebViewTest::TestAutoResize( - const WebSize& min_auto_resize, - const WebSize& max_auto_resize, + const gfx::Size& min_auto_resize, + const gfx::Size& max_auto_resize, const std::string& page_width, const std::string& page_height, int expected_width, @@ -908,8 +908,8 @@ } TEST_F(WebViewTest, AutoResizeMinimumSize) { - WebSize min_auto_resize(91, 56); - WebSize max_auto_resize(403, 302); + gfx::Size min_auto_resize(91, 56); + gfx::Size max_auto_resize(403, 302); std::string page_width = "91px"; std::string page_height = "56px"; int expected_width = 91; @@ -920,8 +920,8 @@ } TEST_F(WebViewTest, AutoResizeHeightOverflowAndFixedWidth) { - WebSize min_auto_resize(90, 95); - WebSize max_auto_resize(90, 100); + gfx::Size min_auto_resize(90, 95); + gfx::Size max_auto_resize(90, 100); std::string page_width = "60px"; std::string page_height = "200px"; int expected_width = 90; @@ -932,8 +932,8 @@ } TEST_F(WebViewTest, AutoResizeFixedHeightAndWidthOverflow) { - WebSize min_auto_resize(90, 100); - WebSize max_auto_resize(200, 100); + gfx::Size min_auto_resize(90, 100); + gfx::Size max_auto_resize(200, 100); std::string page_width = "300px"; std::string page_height = "80px"; int expected_width = 200; @@ -946,8 +946,8 @@ // Next three tests disabled for https://bugs.webkit.org/show_bug.cgi?id=92318 . // It seems we can run three AutoResize tests, then the next one breaks. TEST_F(WebViewTest, AutoResizeInBetweenSizes) { - WebSize min_auto_resize(90, 95); - WebSize max_auto_resize(200, 300); + gfx::Size min_auto_resize(90, 95); + gfx::Size max_auto_resize(200, 300); std::string page_width = "100px"; std::string page_height = "200px"; int expected_width = 100; @@ -958,8 +958,8 @@ } TEST_F(WebViewTest, AutoResizeOverflowSizes) { - WebSize min_auto_resize(90, 95); - WebSize max_auto_resize(200, 300); + gfx::Size min_auto_resize(90, 95); + gfx::Size max_auto_resize(200, 300); std::string page_width = "300px"; std::string page_height = "400px"; int expected_width = 200; @@ -970,8 +970,8 @@ } TEST_F(WebViewTest, AutoResizeMaxSize) { - WebSize min_auto_resize(90, 95); - WebSize max_auto_resize(200, 300); + gfx::Size min_auto_resize(90, 95); + gfx::Size max_auto_resize(200, 300); std::string page_width = "200px"; std::string page_height = "300px"; int expected_width = 200; @@ -4478,7 +4478,7 @@ std::string url = RegisterMockedHttpURLLoad("subtree-layout.html"); WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->EnableAutoResizeMode(WebSize(200, 200), WebSize(200, 200)); + web_view->EnableAutoResizeMode(gfx::Size(200, 200), gfx::Size(200, 200)); LoadFrame(web_view->MainFrameImpl(), url); LocalFrameView* frame_view =
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc index 342d07cb..0955eeb5 100644 --- a/third_party/blink/renderer/core/frame/deprecation.cc +++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -502,11 +502,6 @@ "native UI", kM75, "5825971391299584")}; - case WebFeature::kV8AtomicsWake: - return {"V8AtomicsWake", kM76, - ReplacedWillBeRemoved("Atomics.wake", "Atomics.notify", kM76, - "6228189936353280")}; - case WebFeature::kXRSupportsSession: return {"XRSupportsSession", kM80, ReplacedBy(
diff --git a/third_party/blink/renderer/core/frame/dom_window.cc b/third_party/blink/renderer/core/frame/dom_window.cc index 8adebbc..b891805 100644 --- a/third_party/blink/renderer/core/frame/dom_window.cc +++ b/third_party/blink/renderer/core/frame/dom_window.cc
@@ -166,7 +166,7 @@ } DOMWindow* DOMWindow::AnonymousIndexedGetter(uint32_t index) { - ReportCoopAccess(window_proxy_manager_->GetIsolate(), "indexed"); + ReportCoopAccess("indexed"); if (!GetFrame()) return nullptr; @@ -450,11 +450,11 @@ // Check if the accessing context would be able to access this window if COOP // was enforced. If this isn't a report is sent. -void DOMWindow::ReportCoopAccess(v8::Isolate* isolate, - const char* property_name) { +void DOMWindow::ReportCoopAccess(const char* property_name) { if (coop_access_monitor_.IsEmpty()) // Fast early return. Very likely true. return; + v8::Isolate* isolate = window_proxy_manager_->GetIsolate(); LocalDOMWindow* accessing_window = IncumbentDOMWindow(isolate); LocalFrame* accessing_frame = accessing_window->GetFrame();
diff --git a/third_party/blink/renderer/core/frame/dom_window.h b/third_party/blink/renderer/core/frame/dom_window.h index dcf07d1..eb902c56 100644 --- a/third_party/blink/renderer/core/frame/dom_window.h +++ b/third_party/blink/renderer/core/frame/dom_window.h
@@ -147,7 +147,7 @@ // // This function must be called when accessing any attributes and methods // marked as "CrossOrigin" in the window.idl. - void ReportCoopAccess(v8::Isolate* isolate, const char* property_name); + void ReportCoopAccess(const char* property_name); protected: explicit DOMWindow(Frame&);
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc index fb8eb96..500c6098 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -875,7 +875,7 @@ EXPECT_EQ(IntSize(0, 0), IntSize(WebView()->MainFrameWidget()->Size())); EXPECT_EQ(IntSize(0, 0), GetFrame()->GetPage()->GetVisualViewport().Size()); - WebView()->EnableAutoResizeMode(WebSize(10, 10), WebSize(1000, 1000)); + WebView()->EnableAutoResizeMode(gfx::Size(10, 10), gfx::Size(1000, 1000)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); @@ -2386,7 +2386,7 @@ TEST_P(VisualViewportTest, AutoResizeNoHeightUsesMinimumHeight) { InitializeWithDesktopSettings(); WebView()->ResizeWithBrowserControls(WebSize(0, 0), 0, 0, false); - WebView()->EnableAutoResizeMode(WebSize(25, 25), WebSize(100, 100)); + WebView()->EnableAutoResizeMode(gfx::Size(25, 25), gfx::Size(100, 100)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString(WebView()->MainFrameImpl(), "<!DOCTYPE html>"
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc index e1428ed..d0ef01c 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -598,6 +598,11 @@ // https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode SetDisplayMode(visual_properties.display_mode); + SetAutoResizeMode(visual_properties.auto_resize_enabled, + visual_properties.min_size_for_auto_resize, + visual_properties.max_size_for_auto_resize, + visual_properties.screen_info.device_scale_factor); + bool capture_sequence_number_changed = visual_properties.capture_sequence_number != last_capture_sequence_number_;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h index e1ff0ea..f0d5c4e 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -393,6 +393,13 @@ virtual void SetZoomLevel(double zoom_level); + // Enable or disable auto-resize. This is part of + // UpdateVisualProperties though tests may call to it more directly. + virtual void SetAutoResizeMode(bool auto_resize, + const gfx::Size& min_size_before_dsf, + const gfx::Size& max_size_before_dsf, + float device_scale_factor) = 0; + // This method returns the focused frame belonging to this WebWidget, that // is, a focused frame with the same local root as the one corresponding // to this widget. It will return nullptr if no frame is focused or, the
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 ad8a6da..3c4ad18e 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
@@ -1076,6 +1076,13 @@ gfx::Rect(rect_in_root_frame)); } +void WebFrameWidgetImpl::SetAutoResizeMode(bool auto_resize, + const gfx::Size& min_size_before_dsf, + const gfx::Size& max_size_before_dsf, + float device_scale_factor) { + // Auto resize mode only exists on the top level widget. +} + HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos( const FloatPoint& pos_in_root_frame) { FloatPoint doc_point =
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index 3b408b6..e619d3fdf 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -129,6 +129,10 @@ void DidCreateLocalRootView() override; HitTestResult CoreHitTestResultAt(const gfx::PointF&) override; void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override; + void SetAutoResizeMode(bool auto_resize, + const gfx::Size& min_size_before_dsf, + const gfx::Size& max_size_before_dsf, + float device_scale_factor) override; // FrameWidget overrides: void SetRootLayer(scoped_refptr<cc::Layer>) override;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc index 90385a49..8d769ba 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/frame/web_view_frame_widget.h" +#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/exported/web_view_impl.h" #include "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" @@ -290,4 +291,19 @@ WebFrameWidgetBase::SetZoomLevel(zoom_level); } +void WebViewFrameWidget::SetAutoResizeMode(bool auto_resize, + const gfx::Size& min_window_size, + const gfx::Size& max_window_size, + float device_scale_factor) { + if (auto_resize) { + if (!Platform::Current()->IsUseZoomForDSFEnabled()) + device_scale_factor = 1.f; + web_view_->EnableAutoResizeMode( + gfx::ScaleToCeiledSize(min_window_size, device_scale_factor), + gfx::ScaleToCeiledSize(max_window_size, device_scale_factor)); + } else if (web_view_->AutoResizeMode()) { + web_view_->DisableAutoResizeMode(); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h index 94a3662..a24bb45 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -89,6 +89,10 @@ HitTestResult CoreHitTestResultAt(const gfx::PointF&) override; void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override; void SetZoomLevel(double zoom_level) override; + void SetAutoResizeMode(bool auto_resize, + const gfx::Size& min_size_before_dsf, + const gfx::Size& max_size_before_dsf, + float device_scale_factor) override; // FrameWidget overrides: void SetRootLayer(scoped_refptr<cc::Layer>) override;
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 55d23faf..2b903cc 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -2615,6 +2615,7 @@ ReplaceLayoutResult(std::move(result), index); return; } + DCHECK_EQ(index, layout_results_.size()); const auto& fragment = To<NGPhysicalBoxFragment>(result->PhysicalFragment()); layout_results_.push_back(std::move(result)); #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc index 6d0860c..2dffb5e 100644 --- a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc +++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -485,9 +485,10 @@ DCHECK(performance); double input_timestamp = - had_recent_input ? performance->MonotonicTimeToDOMHighResTimeStamp( - most_recent_input_timestamp_) - : 0.0; + most_recent_input_timestamp_initialized_ + ? performance->MonotonicTimeToDOMHighResTimeStamp( + most_recent_input_timestamp_) + : 0.0; LayoutShift* entry = LayoutShift::Create(performance->now(), score_delta, had_recent_input, input_timestamp, CreateAttributionList());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc index cc6c3115..2fa2e4265 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -544,7 +544,19 @@ // (colum balancing). Keep them in this list, and add them to the fragment // builder when we have the final column fragments. Or clear the list and // retry otherwise. - NGContainerFragmentBuilder::ChildrenVector new_columns; + struct ResultWithOffset { + scoped_refptr<const NGLayoutResult> result; + LogicalOffset offset; + + ResultWithOffset(scoped_refptr<const NGLayoutResult> result, + LogicalOffset offset) + : result(result), offset(offset) {} + + const NGPhysicalBoxFragment& Fragment() const { + return To<NGPhysicalBoxFragment>(result->PhysicalFragment()); + } + }; + Vector<ResultWithOffset, 16> new_columns; scoped_refptr<const NGLayoutResult> result; @@ -584,7 +596,7 @@ // Add the new column fragment to the list, but don't commit anything to // the fragment builder until we know whether these are the final columns. LogicalOffset logical_offset(column_inline_offset, column_block_offset); - new_columns.emplace_back(logical_offset, &result->PhysicalFragment()); + new_columns.emplace_back(result, logical_offset); LayoutUnit space_shortage = result->MinimalSpaceShortage(); if (space_shortage > LayoutUnit()) { @@ -600,8 +612,6 @@ if (result->ColumnSpanner()) break; - Node().AddColumnResult(result, column_break_token.get()); - column_break_token = To<NGBlockBreakToken>(column.BreakToken()); // If we're participating in an outer fragmentation context, we'll only @@ -693,28 +703,16 @@ column_size.block_size = new_column_block_size; } while (true); - bool is_empty = false; - - // If there was no content inside to process, we don't want the resulting - // empty column fragment. - if (new_columns.size() == 1u) { - const NGPhysicalBoxFragment& column = - *To<NGPhysicalBoxFragment>(new_columns[0].fragment.get()); - - if (column.Children().size() == 0) { - // No content. Keep the trailing margin from any previous column spanner. - is_empty = true; - - // TODO(mstensho): It's wrong to keep the empty fragment, just so that - // out-of-flow descendants get propagated correctly. Find some other way - // of propagating them. - if (!column.HasOutOfFlowPositionedDescendants()) - return result; - } - } - intrinsic_block_size_ = column_block_offset + column_size.block_size; + // If we just have one empty fragmentainer, we need to keep the trailing + // margin from any previous column spanner, and also make sure that we don't + // incorrectly consider this to be a class A breakpoint. A fragmentainer may + // end up empty if there's no in-flow content at all inside the multicol + // container, or if the multicol container starts with a spanner. + bool is_empty = + new_columns.size() == 1 && new_columns[0].Fragment().Children().empty(); + if (!is_empty) { has_processed_first_child_ = true; container_builder_.SetPreviousBreakAfter(EBreakBetween::kAuto); @@ -725,9 +723,12 @@ } // Commit all column fragments to the fragment builder. - for (auto column : new_columns) { - container_builder_.AddChild(To<NGPhysicalBoxFragment>(*column.fragment), - column.offset); + const NGBlockBreakToken* incoming_column_token = next_column_token; + for (auto result_with_offset : new_columns) { + const NGPhysicalBoxFragment& fragment = result_with_offset.Fragment(); + container_builder_.AddChild(fragment, result_with_offset.offset); + Node().AddColumnResult(result_with_offset.result, incoming_column_token); + incoming_column_token = To<NGBlockBreakToken>(fragment.BreakToken()); } return result;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc index 461e2bc..abc909a 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -78,10 +78,15 @@ const auto* fragment = iterator.NextChild(); ASSERT_TRUE(fragment); EXPECT_EQ(PhysicalSize(210, 100), fragment->Size()); + EXPECT_EQ(1UL, fragment->Children().size()); EXPECT_FALSE(iterator.NextChild()); - // There should be nothing inside the multicol container. - ASSERT_FALSE(FragmentChildIterator(fragment).NextChild()); + // A multicol container will always create at least one fragmentainer. + fragment = FragmentChildIterator(fragment).NextChild(); + ASSERT_TRUE(fragment); + EXPECT_EQ(PhysicalSize(100, 100), fragment->Size()); + EXPECT_EQ(0UL, fragment->Children().size()); + EXPECT_FALSE(iterator.NextChild()); } @@ -362,6 +367,7 @@ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. offset:unplaced size:1000x0 offset:0,0 size:320x0 + offset:0,0 size:100x1 )DUMP"; EXPECT_EQ(expectation, dump); } @@ -3045,6 +3051,7 @@ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. offset:unplaced size:1000x0 offset:0,0 size:320x0 + offset:0,0 size:100x1 )DUMP"; EXPECT_EQ(expectation, dump); } @@ -3145,7 +3152,7 @@ </style> <div id="container"> <div id="parent"> - <div style="columns:2;"> + <div style="columns:2; column-gap:0;"> <div style="column-span:all;"> <br> </div> @@ -3160,6 +3167,7 @@ offset:0,0 size:320x20 offset:0,0 size:100x20 offset:0,0 size:100x20 + offset:0,0 size:50x1 offset:0,0 size:100x20 offset:0,0 size:0x20 )DUMP"; @@ -3977,6 +3985,7 @@ offset:0,0 size:100x50 offset:0,0 size:5x20 offset:0,20 size:100x30 + offset:1,1 size:44x29 offset:110,0 size:100x50 offset:0,0 size:100x50 offset:220,0 size:100x50 @@ -4310,6 +4319,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:45x1 offset:0,0 size:22x100 offset:110,0 size:100x100 offset:0,0 size:100x35 @@ -4597,6 +4607,7 @@ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. offset:unplaced size:1000x86 offset:0,0 size:322x86 + offset:1,1 size:100x1 offset:1,1 size:320x44 offset:1,45 size:100x40 offset:0,0 size:100x20 @@ -4671,6 +4682,7 @@ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. offset:unplaced size:1000x46 offset:0,0 size:322x46 + offset:1,1 size:100x1 offset:1,1 size:320x44 )DUMP"; EXPECT_EQ(expectation, dump); @@ -4821,6 +4833,7 @@ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. offset:unplaced size:1000x130 offset:0,0 size:320x130 + offset:0,0 size:100x1 offset:10,10 size:33x10 offset:0,30 size:100x20 offset:0,0 size:100x20 @@ -4857,6 +4870,7 @@ String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. offset:unplaced size:1000x130 offset:0,0 size:320x130 + offset:220,0 size:100x1 offset:277,10 size:33x10 offset:220,30 size:100x20 offset:0,0 size:100x20 @@ -4962,7 +4976,7 @@ </style> <div id="container"> <div id="parent"> - <div style="columns:2;"> + <div style="columns:2; column-gap:0;"> <div style="column-span:all; margin-top:10px; margin-bottom:20px; width:33px; height:100px;"></div> <div style="column-span:all; width:44px; height:10px;"></div> </div> @@ -4975,6 +4989,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,10 size:33x90 offset:110,0 size:100x100 offset:0,0 size:100x40 @@ -5182,7 +5197,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5200,6 +5215,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x40 offset:110,0 size:100x100 offset:0,0 size:100x40 @@ -5214,7 +5230,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5232,6 +5248,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x40 offset:110,0 size:100x100 offset:0,0 size:100x40 @@ -5247,7 +5264,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5268,6 +5285,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x40 offset:0,0 size:33x10 offset:0,10 size:44x10 @@ -5285,7 +5303,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5306,6 +5324,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x40 offset:110,0 size:100x100 offset:0,0 size:100x40 @@ -5323,7 +5342,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5341,6 +5360,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x40 offset:110,0 size:100x100 offset:0,0 size:100x50 @@ -5356,7 +5376,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5374,6 +5394,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x60 offset:110,0 size:100x100 offset:0,0 size:100x60 @@ -5390,7 +5411,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5408,6 +5429,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x60 offset:110,0 size:100x100 offset:0,0 size:100x60 @@ -5424,7 +5446,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5443,6 +5465,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:55x40 offset:110,0 size:100x100 offset:0,0 size:100x100 @@ -5460,7 +5483,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:100px; column-fill:auto; column-gap:10px; width:320px; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } .content { break-inside:avoid; height:20px; } </style> <div id="container"> @@ -5483,6 +5506,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:11x100 offset:0,0 size:22x20 offset:0,20 size:33x20 @@ -5510,7 +5534,7 @@ orphans: 3; widows: 3; } - .inner { columns:2; } + .inner { columns:2; column-gap:0; } </style> <div id="container"> <div class="outer"> @@ -5532,6 +5556,7 @@ offset:0,0 size:320x100 offset:0,0 size:100x100 offset:0,0 size:100x100 + offset:0,0 size:50x1 offset:0,0 size:11x100 offset:0,0 size:0x20 offset:0,20 size:0x20 @@ -5595,7 +5620,7 @@ SetBodyInnerHTML(R"HTML( <style> .outer { columns:3; height:50px; column-fill:auto; width:320px; } - .middle { columns:3; height:140px; column-fill:auto; } + .middle { columns:2; height:140px; column-fill:auto; } .inner { column-span:all; columns:2; height:80px; column-fill:auto; } .outer, .middle, .inner { column-gap:10px; } .content { break-inside:avoid; height:20px; } @@ -5622,6 +5647,7 @@ offset:0,0 size:320x50 offset:0,0 size:100x50 offset:0,0 size:100x50 + offset:0,0 size:45x1 offset:0,0 size:100x50 offset:0,0 size:45x50 offset:0,0 size:131x20
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc index 0ddd926..15ce9116 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -448,11 +448,14 @@ const MinMaxSizesInput& input) const { MinMaxSizesResult result; - // TODO(crbug.com/1011842): Need to consider content-size here. bool apply_size_containment = Node().ShouldApplySizeContainment(); - - // Size containment does not consider the legend for sizing. - if (!apply_size_containment) { + if (apply_size_containment) { + // Size containment does not consider the legend for sizing. + base::Optional<MinMaxSizesResult> result_without_children = + CalculateMinMaxSizesIgnoringChildren(Node(), BorderScrollbarPadding()); + if (result_without_children) + return *result_without_children; + } else { if (NGBlockNode legend = Node().GetRenderedLegend()) { result = ComputeMinAndMaxContentContribution(Style(), legend, input); result.sizes += ComputeMinMaxMargins(Style(), legend).InlineSum();
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc index f82fb308..7363804 100644 --- a/third_party/blink/renderer/core/layout/scrollbars_test.cc +++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -2060,7 +2060,7 @@ // Enable auto size mode where the frame is resized such that the content // doesn't need scrollbars (up to a maximum). - WebView().EnableAutoResizeMode(WebSize(100, 100), WebSize(100, 200)); + WebView().EnableAutoResizeMode(gfx::Size(100, 100), gfx::Size(100, 200)); // Note, the frame autosizer doesn't work correctly with subpixel sizes so // even though the container is a fraction larger than the frame, we don't @@ -2098,7 +2098,7 @@ TEST_F(ScrollbarsTest, AutosizeAlmostRemovableScrollbar) { // This test requires that scrollbars take up space. ENABLE_OVERLAY_SCROLLBARS(false); - WebView().EnableAutoResizeMode(WebSize(25, 25), WebSize(800, 600)); + WebView().EnableAutoResizeMode(gfx::Size(25, 25), gfx::Size(800, 600)); SimRequest resource("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html");
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index 388338d..262c245e 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -905,6 +905,12 @@ paint_info.context, GetDisplayItemClient(), paint_info.phase)) return; + if (physical_box_fragment.IsFieldsetContainer()) { + NGFieldsetPainter(box_fragment_) + .PaintMask(paint_info, paint_offset, BorderEdges()); + return; + } + // TODO(eae): Switch to LayoutNG version of BackgroundImageGeometry. BackgroundImageGeometry geometry(*static_cast<const LayoutBoxModelObject*>( box_fragment_.GetLayoutObject()));
diff --git a/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc index 7a5b6be..e259c99 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.cc
@@ -20,38 +20,15 @@ namespace blink { -void NGFieldsetPainter::PaintBoxDecorationBackground( - const PaintInfo& paint_info, - const PhysicalOffset& paint_offset) { +FieldsetPaintInfo NGFieldsetPainter::CreateFieldsetPaintInfo() const { const NGLink* legend = nullptr; if (!fieldset_.Children().empty()) { const auto& first_child = fieldset_.Children().front(); if (first_child->IsRenderedLegend()) legend = &first_child; } - - // Paint the fieldset (background, other decorations, and) border, with the - // cutout hole for the legend. - PaintFieldsetDecorationBackground(legend, paint_info, paint_offset); -} - -void NGFieldsetPainter::PaintFieldsetDecorationBackground( - const NGLink* legend, - const PaintInfo& paint_info, - const PhysicalOffset& paint_offset) { - PhysicalSize fieldset_size(fieldset_.Size()); - PhysicalRect paint_rect(paint_offset, fieldset_size); + const PhysicalSize fieldset_size(fieldset_.Size()); const auto& fragment = fieldset_; - BoxDecorationData box_decoration_data(paint_info, fragment); - // TODO(crbug.com/786475): Fieldset should not scroll. - DCHECK(!box_decoration_data.IsPaintingScrollingBackground()); - if (!box_decoration_data.ShouldPaint()) - return; - - if (DrawingRecorder::UseCachedDrawingIfPossible( - paint_info.context, *fieldset_.GetLayoutObject(), paint_info.phase)) - return; - LayoutRectOutsets fieldset_borders = fragment.Borders().ToLayoutRectOutsets(); const ComputedStyle& style = fieldset_.Style(); PhysicalRect legend_border_box; @@ -85,8 +62,29 @@ legend_border_box.offset = legend_logical_offset.ConvertToPhysical( writing_direction, fieldset_size, legend_border_box.size); } - FieldsetPaintInfo fieldset_paint_info(style, fieldset_size, fieldset_borders, - legend_border_box); + return FieldsetPaintInfo(style, fieldset_size, fieldset_borders, + legend_border_box); +} + +// Paint the fieldset (background, other decorations, and) border, with the +// cutout hole for the legend. +void NGFieldsetPainter::PaintBoxDecorationBackground( + const PaintInfo& paint_info, + const PhysicalOffset& paint_offset) { + PhysicalSize fieldset_size(fieldset_.Size()); + PhysicalRect paint_rect(paint_offset, fieldset_size); + BoxDecorationData box_decoration_data(paint_info, fieldset_); + // TODO(crbug.com/786475): Fieldset should not scroll. + DCHECK(!box_decoration_data.IsPaintingScrollingBackground()); + if (!box_decoration_data.ShouldPaint()) + return; + + if (DrawingRecorder::UseCachedDrawingIfPossible( + paint_info.context, *fieldset_.GetLayoutObject(), paint_info.phase)) + return; + + const ComputedStyle& style = fieldset_.Style(); + FieldsetPaintInfo fieldset_paint_info = CreateFieldsetPaintInfo(); PhysicalRect contracted_rect(paint_rect); contracted_rect.Contract(fieldset_paint_info.border_outsets); @@ -128,4 +126,22 @@ } } +void NGFieldsetPainter::PaintMask(const PaintInfo& paint_info, + const PhysicalOffset& paint_offset, + const NGBorderEdges& border_edges) { + // TODO(eae): Switch to LayoutNG version of BackgroundImageGeometry. + const LayoutObject& layout_object = *fieldset_.GetLayoutObject(); + BackgroundImageGeometry geometry( + static_cast<const LayoutBoxModelObject&>(layout_object)); + + NGBoxFragmentPainter ng_box_painter(fieldset_); + DrawingRecorder recorder(paint_info.context, layout_object, paint_info.phase, + ng_box_painter.VisualRect(paint_offset)); + PhysicalRect paint_rect(paint_offset, fieldset_.Size()); + paint_rect.Contract(CreateFieldsetPaintInfo().border_outsets); + ng_box_painter.PaintMaskImages(paint_info, paint_rect, layout_object, + geometry, border_edges.line_left, + border_edges.line_right); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.h b/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.h index 5a5f601..20d5f80 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.h +++ b/third_party/blink/renderer/core/paint/ng/ng_fieldset_painter.h
@@ -10,7 +10,8 @@ namespace blink { class NGPhysicalBoxFragment; -struct NGLink; +struct FieldsetPaintInfo; +struct NGBorderEdges; struct PaintInfo; struct PhysicalOffset; @@ -22,11 +23,10 @@ : fieldset_(fieldset) {} void PaintBoxDecorationBackground(const PaintInfo&, const PhysicalOffset&); + void PaintMask(const PaintInfo&, const PhysicalOffset&, const NGBorderEdges&); private: - void PaintFieldsetDecorationBackground(const NGLink* legend, - const PaintInfo&, - const PhysicalOffset&); + FieldsetPaintInfo CreateFieldsetPaintInfo() const; const NGPhysicalBoxFragment& fieldset_; };
diff --git a/third_party/blink/renderer/core/script/document_modulator_impl_test.cc b/third_party/blink/renderer/core/script/document_modulator_impl_test.cc index 415a10b..b96db13 100644 --- a/third_party/blink/renderer/core/script/document_modulator_impl_test.cc +++ b/third_party/blink/renderer/core/script/document_modulator_impl_test.cc
@@ -13,10 +13,12 @@ namespace blink { class DocumentModulatorImplTest : public PageTestBase { - DISALLOW_COPY_AND_ASSIGN(DocumentModulatorImplTest); public: DocumentModulatorImplTest() = default; + DocumentModulatorImplTest(const DocumentModulatorImplTest&) = delete; + DocumentModulatorImplTest& operator=(const DocumentModulatorImplTest&) = + delete; void SetUp() override; protected:
diff --git a/third_party/blink/renderer/core/script/html_parser_script_runner.h b/third_party/blink/renderer/core/script/html_parser_script_runner.h index 331dc34..390b3de 100644 --- a/third_party/blink/renderer/core/script/html_parser_script_runner.h +++ b/third_party/blink/renderer/core/script/html_parser_script_runner.h
@@ -26,7 +26,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_HTML_PARSER_SCRIPT_RUNNER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_HTML_PARSER_SCRIPT_RUNNER_H_ -#include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h" #include "third_party/blink/renderer/core/script/pending_script.h" @@ -67,6 +66,8 @@ HTMLParserScriptRunner(HTMLParserReentryPermit*, Document*, HTMLParserScriptRunnerHost*); + HTMLParserScriptRunner(const HTMLParserScriptRunner&) = delete; + HTMLParserScriptRunner& operator=(const HTMLParserScriptRunner&) = delete; ~HTMLParserScriptRunner() override; // Invoked when the parser is detached. @@ -161,8 +162,6 @@ // when |force_deferred_scripts_| is not empty in order to let the force // deferred scripts execute before any async scripts. bool suspended_async_script_execution_ = false; - - DISALLOW_COPY_AND_ASSIGN(HTMLParserScriptRunner); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h b/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h index 02738ad..7109814 100644 --- a/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h +++ b/third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h
@@ -26,7 +26,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_IGNORE_DESTRUCTIVE_WRITE_COUNT_INCREMENTER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_IGNORE_DESTRUCTIVE_WRITE_COUNT_INCREMENTER_H_ -#include "base/macros.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -36,6 +35,10 @@ STACK_ALLOCATED(); public: + IgnoreDestructiveWriteCountIncrementer( + const IgnoreDestructiveWriteCountIncrementer&) = delete; + IgnoreDestructiveWriteCountIncrementer& operator=( + const IgnoreDestructiveWriteCountIncrementer&) = delete; explicit IgnoreDestructiveWriteCountIncrementer(Document* document) : count_(document ? &document->ignore_destructive_write_count_ : nullptr) { @@ -52,7 +55,6 @@ private: unsigned* count_; - DISALLOW_COPY_AND_ASSIGN(IgnoreDestructiveWriteCountIncrementer); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/script/module_map.h b/third_party/blink/renderer/core/script/module_map.h index e6271075..da36d05 100644 --- a/third_party/blink/renderer/core/script/module_map.h +++ b/third_party/blink/renderer/core/script/module_map.h
@@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_MAP_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_MODULE_MAP_H_ -#include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -31,6 +30,8 @@ class Entry; public: + ModuleMap(const ModuleMap&) = delete; + ModuleMap& operator=(const ModuleMap&) = delete; explicit ModuleMap(Modulator*); void Trace(Visitor*) const; @@ -59,7 +60,6 @@ Member<Modulator> modulator_; Member<ModuleScriptLoaderRegistry> loader_registry_; - DISALLOW_COPY_AND_ASSIGN(ModuleMap); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/script/pending_import_map.h b/third_party/blink/renderer/core/script/pending_import_map.h index 219d0d6..96e10c8e 100644 --- a/third_party/blink/renderer/core/script/pending_import_map.h +++ b/third_party/blink/renderer/core/script/pending_import_map.h
@@ -45,6 +45,8 @@ ImportMap*, ScriptValue error_to_rethrow, const ExecutionContext& original_context); + PendingImportMap(const PendingImportMap&) = delete; + PendingImportMap& operator=(const PendingImportMap&) = delete; void RegisterImportMap() const; @@ -65,8 +67,6 @@ // This is only used to check whether the script element is moved between // context and thus doesn't retain a strong reference. WeakMember<const ExecutionContext> original_execution_context_; - - DISALLOW_COPY_AND_ASSIGN(PendingImportMap); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/script/pending_script.h b/third_party/blink/renderer/core/script/pending_script.h index 791ea7f..206c9d97 100644 --- a/third_party/blink/renderer/core/script/pending_script.h +++ b/third_party/blink/renderer/core/script/pending_script.h
@@ -26,7 +26,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_SCRIPT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_PENDING_SCRIPT_H_ -#include "base/macros.h" #include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h" #include "third_party/blink/public/platform/scheduler/web_scoped_virtual_time_pauser.h" #include "third_party/blink/renderer/core/core_export.h" @@ -65,6 +64,8 @@ class CORE_EXPORT PendingScript : public GarbageCollected<PendingScript>, public NameClient { public: + PendingScript(const PendingScript&) = delete; + PendingScript& operator=(const PendingScript&) = delete; virtual ~PendingScript(); TextPosition StartingPosition() const { return starting_position_; } @@ -171,8 +172,6 @@ WeakMember<ExecutionContext> original_execution_context_; const bool created_during_document_write_; - - DISALLOW_COPY_AND_ASSIGN(PendingScript); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/script/script_runner.h b/third_party/blink/renderer/core/script/script_runner.h index ad67795..02204d0 100644 --- a/third_party/blink/renderer/core/script/script_runner.h +++ b/third_party/blink/renderer/core/script/script_runner.h
@@ -27,7 +27,6 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_RUNNER_H_ #include "base/location.h" -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h" @@ -48,6 +47,8 @@ public NameClient { public: explicit ScriptRunner(Document*); + ScriptRunner(const ScriptRunner&) = delete; + ScriptRunner& operator=(const ScriptRunner&) = delete; void QueueScriptForExecution(PendingScript*); bool HasPendingScripts() const { @@ -122,8 +123,6 @@ // design doc: // https://docs.google.com/document/u/1/d/1G-IUrT4enARZlsIrFQ4d4cRVe9MRTJASfWwolV09JZE/edit. bool delay_async_script_milestone_reached_ = false; - - DISALLOW_COPY_AND_ASSIGN(ScriptRunner); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/script/xml_parser_script_runner.h b/third_party/blink/renderer/core/script/xml_parser_script_runner.h index 969d735c..82716dd 100644 --- a/third_party/blink/renderer/core/script/xml_parser_script_runner.h +++ b/third_party/blink/renderer/core/script/xml_parser_script_runner.h
@@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_XML_PARSER_SCRIPT_RUNNER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_XML_PARSER_SCRIPT_RUNNER_H_ -#include "base/macros.h" #include "third_party/blink/renderer/core/script/pending_script.h" #include "third_party/blink/renderer/platform/wtf/text/text_position.h" @@ -23,6 +22,8 @@ public PendingScriptClient { public: explicit XMLParserScriptRunner(XMLParserScriptRunnerHost*); + XMLParserScriptRunner(const XMLParserScriptRunner&) = delete; + XMLParserScriptRunner& operator=(const XMLParserScriptRunner&) = delete; ~XMLParserScriptRunner() override; bool HasParserBlockingScript() const { return parser_blocking_script_; } @@ -45,7 +46,6 @@ // TODO(crbug/717643): Implement // https://html.spec.whatwg.org/C/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing - DISALLOW_COPY_AND_ASSIGN(XMLParserScriptRunner); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/BUILD.gn b/third_party/blink/renderer/modules/payments/BUILD.gn index 32ba3124..ed4b9f2 100644 --- a/third_party/blink/renderer/modules/payments/BUILD.gn +++ b/third_party/blink/renderer/modules/payments/BUILD.gn
@@ -51,8 +51,6 @@ "payment_state_resolver.h", "payments_validators.cc", "payments_validators.h", - "secure_payment_confirmation_helper.cc", - "secure_payment_confirmation_helper.h", "update_payment_details_function.cc", "update_payment_details_function.h", ]
diff --git a/third_party/blink/renderer/modules/payments/idls.gni b/third_party/blink/renderer/modules/payments/idls.gni index 407fbe4..ea997922 100644 --- a/third_party/blink/renderer/modules/payments/idls.gni +++ b/third_party/blink/renderer/modules/payments/idls.gni
@@ -21,7 +21,6 @@ "address_init.idl", "android_pay_method_data.idl", "basic_card_request.idl", - "secure_payment_confirmation_request.idl", "can_make_payment_event_init.idl", "can_make_payment_response.idl", "image_object.idl",
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc index 2ccd3bae..a0e2ac8 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.cc +++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -51,7 +51,6 @@ #include "third_party/blink/renderer/modules/payments/payment_request_update_event.h" #include "third_party/blink/renderer/modules/payments/payment_response.h" #include "third_party/blink/renderer/modules/payments/payments_validators.h" -#include "third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.h" #include "third_party/blink/renderer/modules/payments/update_payment_details_function.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" @@ -412,14 +411,14 @@ output->api_version = android_pay->apiVersion(); } -void StringifyAndParseMethodSpecificData(ExecutionContext& execution_context, +void StringifyAndParseMethodSpecificData(v8::Isolate* isolate, const String& supported_method, const ScriptValue& input, PaymentMethodDataPtr& output, ExceptionState& exception_state) { PaymentsValidators::ValidateAndStringifyObject( - execution_context.GetIsolate(), "Payment method data", input, - output->stringified_data, exception_state); + isolate, "Payment method data", input, output->stringified_data, + exception_state); if (exception_state.HadException()) return; @@ -428,21 +427,15 @@ // data asynchronously. Do not throw exceptions here. if (supported_method == kGooglePayMethod || supported_method == kAndroidPayMethod) { - SetAndroidPayMethodData(execution_context.GetIsolate(), input, output, - exception_state); + SetAndroidPayMethodData(isolate, input, output, exception_state); if (exception_state.HadException()) exception_state.ClearException(); } - // Parse method data to avoid parsing JSON in the browser. if (supported_method == "basic-card") { + // Parses basic-card data to avoid parsing JSON in the browser. BasicCardHelper::ParseBasiccardData(input, output->supported_networks, exception_state); - } else if (supported_method == "secure-payment-confirmation" && - RuntimeEnabledFeatures::SecurePaymentConfirmationEnabled( - &execution_context)) { - SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData( - input, exception_state); } } @@ -487,8 +480,8 @@ if (modifier->hasData() && !modifier->data().IsEmpty()) { StringifyAndParseMethodSpecificData( - execution_context, modifier->supportedMethod(), modifier->data(), - output.back()->method_data, exception_state); + execution_context.GetIsolate(), modifier->supportedMethod(), + modifier->data(), output.back()->method_data, exception_state); } else { output.back()->method_data->stringified_data = ""; } @@ -684,8 +677,9 @@ if (payment_method_data->hasData() && !payment_method_data->data().IsEmpty()) { StringifyAndParseMethodSpecificData( - execution_context, payment_method_data->supportedMethod(), - payment_method_data->data(), output.back(), exception_state); + execution_context.GetIsolate(), + payment_method_data->supportedMethod(), payment_method_data->data(), + output.back(), exception_state); if (exception_state.HadException()) continue; @@ -1205,9 +1199,8 @@ mojom::blink::ConsoleMessageSource::kJavaScript, mojom::blink::ConsoleMessageLevel::kError, "Payment method \"" + data->supported_method + - "\" cannot be used with \"requestShipping\", " - "\"requestPayerName\", " - "\"requestPayerEmail\", or \"requestPayerPhone\".")); + "\" cannot be used with \"requestShipping\", \"requestPayerName\", " + "\"requestPayerEmail\", or \"requestPayerPhone\".")); } }
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc deleted file mode 100644 index 68e2bcd..0000000 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.cc +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.h" - -#include <stdint.h> - -#include "base/logging.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.h" -#include "third_party/blink/renderer/platform/bindings/exception_state.h" - -namespace blink { -namespace { - -// Arbitrarily chosen limit of 1 hour. -constexpr uint32_t kMaxTimeoutInMilliseconds = 1000 * 60 * 60; - -} // namespace - -// static -void SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData( - const ScriptValue& input, - ExceptionState& exception_state) { - DCHECK(!input.IsEmpty()); - SecurePaymentConfirmationRequest* request = - NativeValueTraits<SecurePaymentConfirmationRequest>::NativeValue( - input.GetIsolate(), input.V8Value(), exception_state); - if (exception_state.HadException()) - return; - - if (request->instrumentId().IsEmpty()) { - exception_state.ThrowRangeError( - "The \"secure-payment-confirmation\" method requires a non-empty " - "\"instrumentId\" field."); - return; - } - - if (request->hasTimeout() && request->timeout() > kMaxTimeoutInMilliseconds) { - exception_state.ThrowRangeError( - "The \"secure-payment-confirmation\" method requires at most 1 hour " - "\"timeout\" field."); - return; - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.h b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.h deleted file mode 100644 index 760b76a..0000000 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_SECURE_PAYMENT_CONFIRMATION_HELPER_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_SECURE_PAYMENT_CONFIRMATION_HELPER_H_ - -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -class ScriptValue; -class ExceptionState; - -class SecurePaymentConfirmationHelper { - STATIC_ONLY(SecurePaymentConfirmationHelper); - - public: - // Parse 'secure-payment-confirmation' data in |input| or throw an exception. - static void ParseSecurePaymentConfirmationData(const ScriptValue& input, - ExceptionState&); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_SECURE_PAYMENT_CONFIRMATION_HELPER_H_
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl deleted file mode 100644 index cb94e7a..0000000 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl +++ /dev/null
@@ -1,20 +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. - -// https://github.com/rsolomakhin/secure-payment-confirmation#authenticating-a-payment - -enum SecurePaymentConfirmationAction { - "authenticate", -}; - -dictionary SecurePaymentConfirmationRequest { - SecurePaymentConfirmationAction action; - required DOMString instrumentId; - // Opaque data about the current transaction provided by the issuer. As the - // issuer is the RP of the credential, |networkData| provides protection - // against replay attacks. - required BufferSource networkData; - unsigned long timeout; - required USVString fallbackUrl; -};
diff --git a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc index 2327bf6..31752e5 100644 --- a/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.cc
@@ -588,6 +588,10 @@ if (!decoder_) return false; + // TODO(crbug.com/1114916): Disable grid image support in libavif until the + // libavif grid image code has been audited. + decoder_->disableGridImages = AVIF_TRUE; + // TODO(dalecurtis): This may create a second copy of the media data in // memory, which is not great. libavif should provide a read() based API: // https://github.com/AOMediaCodec/libavif/issues/11
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 8a5eaf76..cc7d4c8d 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -218,7 +218,7 @@ }, { name: "AzimuthAltitude", - status: "experimental", + status: "stable", }, { name: "BackForwardCache", @@ -1678,12 +1678,6 @@ name: "ScrollUnification", }, { - name: "SecurePaymentConfirmation", - origin_trial_feature_name: "SecurePaymentConfirmation", - origin_trial_os: ["mac"], - status: "experimental", - }, - { name: "SendBeaconThrowForBlobWithNonSimpleType", status: "stable", },
diff --git a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc index 9b722440..e3e8850 100644 --- a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc +++ b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.cc
@@ -246,9 +246,9 @@ needs_unbuffered_input_for_debugger_(false), allow_raf_aligned_input_(allow_raf_aligned_input), main_task_runner_(main_task_runner), - main_thread_scheduler_(main_thread_scheduler), - use_raf_fallback_timer_(true) { - raf_fallback_timer_.SetTaskRunner(main_task_runner); + main_thread_scheduler_(main_thread_scheduler) { + raf_fallback_timer_ = std::make_unique<base::OneShotTimer>(); + raf_fallback_timer_->SetTaskRunner(main_task_runner); event_predictor_ = std::make_unique<InputEventPrediction>( base::FeatureList::IsEnabled(blink::features::kResamplingInputEvents)); @@ -508,8 +508,13 @@ DispatchRafAlignedInput(base::TimeTicks::Now()); } +void MainThreadEventQueue::ClearRafFallbackTimerForTesting() { + raf_fallback_timer_.reset(); +} + void MainThreadEventQueue::DispatchRafAlignedInput(base::TimeTicks frame_time) { - raf_fallback_timer_.Stop(); + if (raf_fallback_timer_) + raf_fallback_timer_->Stop(); size_t queue_size_at_start; // Record the queue size so that we only process @@ -676,8 +681,8 @@ void MainThreadEventQueue::SetNeedsMainFrame() { if (main_task_runner_->BelongsToCurrentThread()) { - if (use_raf_fallback_timer_) { - raf_fallback_timer_.Start( + if (raf_fallback_timer_) { + raf_fallback_timer_->Start( FROM_HERE, kMaxRafDelay, base::BindOnce(&MainThreadEventQueue::RafFallbackTimerFired, this)); } @@ -696,6 +701,7 @@ void MainThreadEventQueue::ClearClient() { DCHECK(main_task_runner_->BelongsToCurrentThread()); client_ = nullptr; + raf_fallback_timer_.reset(); } void MainThreadEventQueue::SetNeedsLowLatency(bool low_latency) {
diff --git a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h index 3949bfe..359f6ea 100644 --- a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h +++ b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue.h
@@ -141,9 +141,7 @@ const std::unique_ptr<MainThreadEventQueueTask>& item) const; void RafFallbackTimerFired(); - void set_use_raf_fallback_timer(bool use_timer) { - use_raf_fallback_timer_ = use_timer; - } + void ClearRafFallbackTimerForTesting(); friend class QueuedWebInputEvent; friend class MainThreadEventQueueTest; @@ -175,8 +173,10 @@ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; scheduler::WebThreadScheduler* main_thread_scheduler_; - base::OneShotTimer raf_fallback_timer_; - bool use_raf_fallback_timer_; + + // A safe guard timer to ensure input is always processed. A BeginMainFrame + // signal might not always occur if our visibility changed. + std::unique_ptr<base::OneShotTimer> raf_fallback_timer_; std::unique_ptr<InputEventPrediction> event_predictor_;
diff --git a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc index 3a8f1c01..cc62383 100644 --- a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc +++ b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
@@ -185,7 +185,7 @@ void SetUp() override { queue_ = new MainThreadEventQueue(this, main_task_runner_, &thread_scheduler_, true); - queue_->set_use_raf_fallback_timer(false); + queue_->ClearRafFallbackTimerForTesting(); } void HandleEvent(WebInputEvent& event,
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 7670b0b3..007c43c 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -265,6 +265,7 @@ 'gfx::Rect', 'gfx::RectF', 'gfx::RRectF', + 'gfx::ScaleToCeiledSize', 'gfx::ScaleVector2d', 'gfx::Size', 'gfx::SizeF',
diff --git a/third_party/blink/tools/blinkpy/w3c/export_notifier.py b/third_party/blink/tools/blinkpy/w3c/export_notifier.py index 32612d24..21b6717 100644 --- a/third_party/blink/tools/blinkpy/w3c/export_notifier.py +++ b/third_party/blink/tools/blinkpy/w3c/export_notifier.py
@@ -18,6 +18,9 @@ from blinkpy.w3c.wpt_github import GitHubError _log = logging.getLogger(__name__) +RELEVANT_TASKCLUSTER_CHECKS = [ + 'wpt-chrome-dev-stability', 'wpt-firefox-nightly-stability', 'lint' +] class ExportNotifier(object): @@ -28,7 +31,7 @@ self.dry_run = dry_run def main(self): - """Surfaces stability check failures to Gerrit through comments.""" + """Surfaces relevant Taskcluster check failures to Gerrit through comments.""" gerrit_dict = {} try: @@ -47,13 +50,13 @@ _log.info('Found %d failing PRs.', len(prs)) for pr in prs: - statuses = self.get_taskcluster_statuses(pr.number) - if not statuses: + check_runs = self.get_check_runs(pr.number) + if not check_runs: continue - taskcluster_status = self.get_failure_taskcluster_status( - statuses, pr.number) - if not taskcluster_status: + checks_results = self.get_relevant_failed_taskcluster_checks( + check_runs, pr.number) + if not checks_results: continue gerrit_id = self.wpt_github.extract_metadata( @@ -64,30 +67,30 @@ gerrit_sha = self.wpt_github.extract_metadata( WPT_REVISION_FOOTER, pr.body) - gerrit_dict[gerrit_id] = PRStatusInfo( - taskcluster_status['target_url'], pr.number, gerrit_sha) + gerrit_dict[gerrit_id] = PRStatusInfo(checks_results, pr.number, + gerrit_sha) self.process_failing_prs(gerrit_dict) return False - def get_taskcluster_statuses(self, number): - """Retrieves Taskcluster status through PR number. + def get_check_runs(self, number): + """Retrieves check runs through a PR number. Returns: - A JSON object representing all Taskcluster statuses for this PR. + A JSON array representing the check runs for the HEAD of this PR. """ try: branch = self.wpt_github.get_pr_branch(number) - statuses = self.wpt_github.get_branch_statuses(branch) + check_runs = self.wpt_github.get_branch_check_runs(branch) except GitHubError as e: _log.error(str(e)) return None - return statuses + return check_runs def process_failing_prs(self, gerrit_dict): - """Processes and comments on CLs with failed TackCluster status.""" - _log.info('Processing %d CLs with failed Taskcluster status.', + """Processes and comments on CLs with failed Tackcluster checks.""" + _log.info('Processing %d CLs with failed Taskcluster checks.', len(gerrit_dict)) for change_id, pr_status_info in gerrit_dict.items(): try: @@ -107,7 +110,7 @@ if self.dry_run: _log.info('[dry_run] Would have commented on CL %s\n', change_id) - _log.debug('Comments are:\n %s\n', cl_comment) + _log.debug('Comments are:\n%s\n', cl_comment) else: _log.info('Commenting on CL %s\n', change_id) cl.post_comment(cl_comment) @@ -132,65 +135,42 @@ return False - def get_failure_taskcluster_status(self, taskcluster_status, pr_number): - """Parses Taskcluster status from Taskcluster statuses description field. + def get_relevant_failed_taskcluster_checks(self, check_runs, pr_number): + """Filters relevant failed Taskcluster checks from check_runs. Args: - taskcluster_status: array; is of following format: - [ - { - "url": "https://b", - "avatar_url": "https://a", - "id": 1, - "node_id": "A", - "state": "failure", - "description": "TaskGroup: failure", - "target_url": "https://tools.taskcluster.net/task-group-inspector/#/abc", - "context": "Community-TC (pull_request)", - "created_at": "2019-08-05T22:52:08Z", - "updated_at": "2019-08-05T22:52:08Z" - } - ] - e.g. https://api.github.com/repos/web-platform-tests/wpt/commits/chromium-export-cl-1407433/status + check_runs: A JSON array; e.g. "check_runs" in + https://developer.github.com/v3/checks/runs/#response-3 pr_number: The PR number. Returns: - Taskcluster status dictionary if it has a failure status; None otherwise. + A dictionary where keys are names of the Taskcluster checks and values + are URLs to the Taskcluster checks' results. """ - status = None - for status_dict in taskcluster_status: - if status_dict['context'] == 'Community-TC (pull_request)': - status = status_dict - break + checks_results = {} + for check in check_runs: + if (check['conclusion'] == 'failure') and ( + check['name'] in RELEVANT_TASKCLUSTER_CHECKS): + result_url = '{}pull/{}/checks?check_run_id={}'.format( + WPT_GH_URL, pr_number, check['id']) + checks_results[check['name']] = result_url - if status and status['state'] == 'failure': - return status - - if status is None: - return None - - _log.debug('Taskcluster status for PR %s is %s', pr_number, status) - return None + return checks_results class PRStatusInfo(object): - LINK_TAG = 'Taskcluster Link: ' CL_SHA_TAG = 'Gerrit CL SHA: ' PATCHSET_TAG = 'Patchset Number: ' - def __init__(self, link, pr_number, gerrit_sha=None): - self._link = link - self.pr_number = pr_number + def __init__(self, checks_results, pr_number, gerrit_sha=None): + self._checks_results = checks_results + self._pr_number = pr_number if gerrit_sha: self._gerrit_sha = gerrit_sha else: self._gerrit_sha = 'Latest' @property - def link(self): - return self._link - - @property def gerrit_sha(self): return self._gerrit_sha @@ -202,20 +182,30 @@ return None - def to_gerrit_comment(self, patchset=None): - status_line = ( - 'The exported PR, {pr_url}, has failed Taskcluster check(s) ' - 'on GitHub, which could indicate cross-browser failures on the ' - 'exported changes. Please contact ecosystem-infra@chromium.org for ' - 'more information.').format( - pr_url='%spull/%d' % (WPT_GH_URL, self.pr_number) - ) - link_line = ('\n\n{}{}').format(PRStatusInfo.LINK_TAG, self.link) - sha_line = ('\n{}{}').format(PRStatusInfo.CL_SHA_TAG, self.gerrit_sha) + def _checks_results_as_comment(self): + comment = '' + for check, url in self._checks_results.items(): + comment += '\n%s (%s)' % (check, url) - comment = status_line + link_line + sha_line + return comment + + def to_gerrit_comment(self, patchset=None): + comment = ( + 'The exported PR, {}, has failed the following check(s) ' + 'on GitHub:\n{}\n\nThese failures will block the export. ' + 'They may represent new or existing problems; please take ' + 'a look at the output and see if it can be fixed. ' + 'Unresolved failures will be looked at by the Ecosystem-Infra ' + 'sheriff after this CL has been landed in Chromium; if you ' + 'need earlier help please contact ecosystem-infra@chromium.org.\n\n' + 'Any suggestions to improve this service are welcome; ' + 'crbug.com/1027618.').format( + '%spull/%d' % (WPT_GH_URL, self._pr_number), + self._checks_results_as_comment()) + + comment += ('\n\n{}{}').format(PRStatusInfo.CL_SHA_TAG, + self._gerrit_sha) if patchset is not None: comment += ('\n{}{}').format(PRStatusInfo.PATCHSET_TAG, patchset) - comment += '\n\nAny suggestions to improve this service are welcome; crbug.com/1027618.' return comment
diff --git a/third_party/blink/tools/blinkpy/w3c/export_notifier_unittest.py b/third_party/blink/tools/blinkpy/w3c/export_notifier_unittest.py index db218b6..185d9c1 100644 --- a/third_party/blink/tools/blinkpy/w3c/export_notifier_unittest.py +++ b/third_party/blink/tools/blinkpy/w3c/export_notifier_unittest.py
@@ -20,11 +20,11 @@ def test_get_gerrit_sha_from_comment_success(self): gerrit_comment = self.generate_notifier_comment( - 123, 'bar', 'num', None) + 123, 'checks', 'SHA', None) actual = PRStatusInfo.get_gerrit_sha_from_comment(gerrit_comment) - self.assertEqual(actual, 'num') + self.assertEqual(actual, 'SHA') def test_get_gerrit_sha_from_comment_fail(self): gerrit_comment = 'ABC' @@ -34,71 +34,82 @@ self.assertIsNone(actual) def test_to_gerrit_comment(self): - pr_status_info = PRStatusInfo('bar', 123, 'num') - expected = self.generate_notifier_comment(123, 'bar', 'num', None) + checks_results = {'key1': 'val1', 'key2': 'val2'} + result_comment = '\nkey2 (val2)\nkey1 (val1)' + pr_status_info = PRStatusInfo(checks_results, 123, 'SHA') + expected = self.generate_notifier_comment(123, result_comment, 'SHA', + None) actual = pr_status_info.to_gerrit_comment() self.assertEqual(expected, actual) def test_to_gerrit_comment_latest(self): - pr_status_info = PRStatusInfo('bar', 123, None) - expected = self.generate_notifier_comment(123, 'bar', 'Latest', None) + checks_results = {'key1': 'val1', 'key2': 'val2'} + result_comment = '\nkey2 (val2)\nkey1 (val1)' + pr_status_info = PRStatusInfo(checks_results, 123, None) + expected = self.generate_notifier_comment(123, result_comment, + 'Latest', None) actual = pr_status_info.to_gerrit_comment() self.assertEqual(expected, actual) def test_to_gerrit_comment_with_patchset(self): - pr_status_info = PRStatusInfo('bar', 123, 'num') - expected = self.generate_notifier_comment(123, 'bar', 'num', 3) + checks_results = {'key1': 'val1', 'key2': 'val2'} + result_comment = '\nkey2 (val2)\nkey1 (val1)' + pr_status_info = PRStatusInfo(checks_results, 123, 'SHA') + expected = self.generate_notifier_comment(123, result_comment, 'SHA', + 3) actual = pr_status_info.to_gerrit_comment(3) self.assertEqual(expected, actual) - def test_get_failure_taskcluster_status_success(self): - taskcluster_status = [{ - "state": "failure", - "context": "Community-TC (pull_request)", - }, { - "state": "success", - "context": "random", - }] + def test_get_relevant_failed_taskcluster_checks_success(self): + check_runs = [ + { + "id": "1", + "conclusion": "failure", + "name": "wpt-chrome-dev-stability" + }, + { + "id": "2", + "conclusion": "failure", + "name": "wpt-firefox-nightly-stability" + }, + ] + expected = { + 'wpt-chrome-dev-stability': + 'https://github.com/web-platform-tests/wpt/pull/123/checks?check_run_id=1', + 'wpt-firefox-nightly-stability': + 'https://github.com/web-platform-tests/wpt/pull/123/checks?check_run_id=2' + } self.assertEqual( - self.notifier.get_failure_taskcluster_status( - taskcluster_status, 123), { - "state": "failure", - "context": "Community-TC (pull_request)", - }) + self.notifier.get_relevant_failed_taskcluster_checks( + check_runs, 123), expected) - def test_get_failure_taskcluster_status_fail(self): - taskcluster_status = [ + def test_get_relevant_failed_taskcluster_checks_empty(self): + check_runs = [ { - "state": "success", - "context": "Community-TC (pull_request)", + "id": "1", + "conclusion": "success", + "name": "wpt-chrome-dev-stability" + }, + { + "id": "2", + "conclusion": "failure", + "name": "infra" }, ] self.assertEqual( - self.notifier.get_failure_taskcluster_status( - taskcluster_status, 123), None) - - def test_get_failure_taskcluster_pending_status(self): - taskcluster_status = [ - { - "state": "pending", - "context": "Community-TC (pull_request)", - }, - ] - - self.assertEqual( - self.notifier.get_failure_taskcluster_status( - taskcluster_status, 123), None) + self.notifier.get_relevant_failed_taskcluster_checks( + check_runs, 123), {}) def test_has_latest_taskcluster_status_commented_false(self): - pr_status_info = PRStatusInfo('bar', 123, 'num') + pr_status_info = PRStatusInfo('bar', 123, 'SHA') messages = [{ "date": "2019-08-20 17:42:05.000000000", "message": "Uploaded patch set 1.\nInitial upload", @@ -111,7 +122,7 @@ self.assertFalse(actual) def test_has_latest_taskcluster_status_commented_true(self): - pr_status_info = PRStatusInfo('bar', 123, 'num') + pr_status_info = PRStatusInfo({'a': 'b'}, 123, 'SHA') messages = [ { "date": "2019-08-20 17:42:05.000000000", @@ -119,11 +130,10 @@ "_revision_number": 1 }, { - "date": - "2019-08-21 17:41:05.000000000", - "message": self.generate_notifier_comment(123, 'bar', 'num', 3), - "_revision_number": - 2 + "date": "2019-08-21 17:41:05.000000000", + "message": + self.generate_notifier_comment(123, 'result', 'SHA', 3), + "_revision_number": 2 }, ] @@ -132,28 +142,31 @@ self.assertTrue(actual) - self.assertTrue(actual) + def test_get_check_runs_success(self): + self.notifier.wpt_github = MockWPTGitHub(pull_requests=[]) + self.notifier.wpt_github.check_runs = [ + { + "id": "123", + "conclusion": "failure", + "name": "wpt-chrome-dev-stability" + }, + { + "id": "456", + "conclusion": "success", + "name": "firefox" + }, + ] + actual = self.notifier.get_check_runs(123) - def test_get_taskcluster_statuses_success(self): - self.notifier.wpt_github = MockWPTGitHub(pull_requests=[ - PullRequest( - title='title1', - number=1234, - body='description\nWPT-Export-Revision: 1', - state='open', - labels=[]), - ]) - status = [{"description": "foo"}] - self.notifier.wpt_github.status = status - actual = self.notifier.get_taskcluster_statuses(123) - - self.assertEqual(actual, status) + self.assertEqual(len(actual), 2) self.assertEqual(self.notifier.wpt_github.calls, [ 'get_pr_branch', - 'get_branch_statuses', + 'get_branch_check_runs', ]) def test_process_failing_prs_success(self): + checks_results = {'key1': 'val1', 'key2': 'val2'} + result_comment = '\nkey2 (val2)\nkey1 (val1)' self.notifier.dry_run = False self.notifier.gerrit = MockGerritAPI() self.notifier.gerrit.cl = MockGerritCL( @@ -175,14 +188,15 @@ }, ], 'revisions': { - 'num': { + 'SHA': { '_number': 1 } } }, api=self.notifier.gerrit) - gerrit_dict = {'abc': PRStatusInfo('bar', 123, 'num')} - expected = self.generate_notifier_comment(123, 'bar', 'num', 1) + gerrit_dict = {'abc': PRStatusInfo(checks_results, 123, 'SHA')} + expected = self.generate_notifier_comment(123, result_comment, 'SHA', + 1) self.notifier.process_failing_prs(gerrit_dict) @@ -208,19 +222,19 @@ { "date": "2019-08-21 17:41:05.000000000", - "message": self.generate_notifier_comment(123, 'bar', 'num', 3), + "message": self.generate_notifier_comment(123, 'bar', 'SHA', 3), "_revision_number": 2 }, ], 'revisions': { - 'num': { + 'SHA': { '_number': 1 } } }, api=self.notifier.gerrit) - gerrit_dict = {'abc': PRStatusInfo('bar', 123, 'num')} + gerrit_dict = {'abc': PRStatusInfo('bar', 123, 'SHA')} self.notifier.process_failing_prs(gerrit_dict) @@ -249,14 +263,17 @@ }, ], 'revisions': { - 'num': { + 'SHA': { '_number': 1 } } }, api=self.notifier.gerrit) - expected = self.generate_notifier_comment(123, 'bar', 'Latest') - gerrit_dict = {'abc': PRStatusInfo('bar', 123, None)} + checks_results = {'key1': 'val1', 'key2': 'val2'} + result_comment = '\nkey2 (val2)\nkey1 (val1)' + expected = self.generate_notifier_comment(123, result_comment, + 'Latest') + gerrit_dict = {'abc': PRStatusInfo(checks_results, 123, None)} self.notifier.process_failing_prs(gerrit_dict) @@ -269,14 +286,14 @@ def test_process_failing_prs_raise_gerrit_error(self): self.notifier.dry_run = False self.notifier.gerrit = MockGerritAPI(raise_error=True) - gerrit_dict = {'abc': PRStatusInfo('bar', 'num')} + gerrit_dict = {'abc': PRStatusInfo('bar', 'SHA')} self.notifier.process_failing_prs(gerrit_dict) self.assertEqual(self.notifier.gerrit.cls_queried, ['abc']) self.assertEqual(self.notifier.gerrit.request_posted, []) self.assertLog([ - 'INFO: Processing 1 CLs with failed Taskcluster status.\n', + 'INFO: Processing 1 CLs with failed Taskcluster checks.\n', 'ERROR: Could not process Gerrit CL abc: Error from query_cl\n' ]) @@ -290,13 +307,21 @@ state='open', labels=['']) ] - status = [{ - "state": "failure", - "context": "Community-TC (pull_request)", - "node_id": "foo", - "target_url": "bar" - }] - self.notifier.wpt_github.status = status + self.notifier.wpt_github.check_runs = [ + { + "id": "123", + "conclusion": "failure", + "name": "wpt-chrome-dev-stability" + }, + { + "id": "456", + "conclusion": "success", + "name": "firefox" + }, + ] + checks_results_comment = ('\nwpt-chrome-dev-stability (' + 'https://github.com/web-platform-tests/wpt' + '/pull/1234/checks?check_run_id=123)') self.notifier.dry_run = False self.notifier.gerrit = MockGerritAPI() @@ -325,7 +350,8 @@ } }, api=self.notifier.gerrit) - expected = self.generate_notifier_comment(1234, 'bar', 'hash', 2) + expected = self.generate_notifier_comment(1234, checks_results_comment, + 'hash', 2) exit_code = self.notifier.main() @@ -333,7 +359,7 @@ self.assertEqual(self.notifier.wpt_github.calls, [ 'recent_failing_chromium_exports', 'get_pr_branch', - 'get_branch_statuses', + 'get_branch_check_runs', ]) self.assertEqual(self.notifier.gerrit.cls_queried, ['decafbad']) self.assertEqual(self.notifier.gerrit.request_posted, @@ -341,30 +367,39 @@ 'message': expected })]) - def generate_notifier_comment(self, pr_number, link, sha, patchset=None): + def generate_notifier_comment(self, + pr_number, + checks_results_comment, + sha, + patchset=None): if patchset: comment = ( 'The exported PR, https://github.com/web-platform-tests/wpt/pull/{}, ' - 'has failed Taskcluster check(s) on GitHub, which could indicate ' - 'cross-browser failures on the exported changes. Please contact ' - 'ecosystem-infra@chromium.org for more information.\n\n' - 'Taskcluster Link: {}\n' + 'has failed the following check(s) on GitHub:\n{}' + '\n\nThese failures will block the export. ' + 'They may represent new or existing problems; please take ' + 'a look at the output and see if it can be fixed. ' + 'Unresolved failures will be looked at by the Ecosystem-Infra ' + 'sheriff after this CL has been landed in Chromium; if you ' + 'need earlier help please contact ecosystem-infra@chromium.org.\n\n' + 'Any suggestions to improve this service are welcome; ' + 'crbug.com/1027618.\n\n' 'Gerrit CL SHA: {}\n' - 'Patchset Number: {}' - '\n\nAny suggestions to improve this service are welcome; ' - 'crbug.com/1027618.').format( - pr_number, link, sha, patchset - ) + 'Patchset Number: {}').format(pr_number, + checks_results_comment, sha, + patchset) else: comment = ( 'The exported PR, https://github.com/web-platform-tests/wpt/pull/{}, ' - 'has failed Taskcluster check(s) on GitHub, which could indicate ' - 'cross-browser failures on the exported changes. Please contact ' - 'ecosystem-infra@chromium.org for more information.\n\n' - 'Taskcluster Link: {}\n' - 'Gerrit CL SHA: {}' - '\n\nAny suggestions to improve this service are welcome; ' - 'crbug.com/1027618.').format( - pr_number, link, sha - ) + 'has failed the following check(s) on GitHub:\n{}' + '\n\nThese failures will block the export. ' + 'They may represent new or existing problems; please take ' + 'a look at the output and see if it can be fixed. ' + 'Unresolved failures will be looked at by the Ecosystem-Infra ' + 'sheriff after this CL has been landed in Chromium; if you ' + 'need earlier help please contact ecosystem-infra@chromium.org.\n\n' + 'Any suggestions to improve this service are welcome; ' + 'crbug.com/1027618.\n\n' + 'Gerrit CL SHA: {}').format(pr_number, checks_results_comment, + sha) return comment
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_github.py b/third_party/blink/tools/blinkpy/w3c/wpt_github.py index 091971c..7e5674b5 100644 --- a/third_party/blink/tools/blinkpy/w3c/wpt_github.py +++ b/third_party/blink/tools/blinkpy/w3c/wpt_github.py
@@ -48,13 +48,14 @@ assert self.has_credentials() return base64.b64encode('{}:{}'.format(self.user, self.token)) - def request(self, path, method, body=None): + def request(self, path, method, body=None, accept_header=None): """Sends a request to GitHub API and deserializes the response. Args: path: API endpoint without base URL (starting with '/'). method: HTTP method to be used for this request. body: Optional payload in the request body (default=None). + accept_header: Custom media type in the Accept header (default=None). Returns: A JSONResponse instance. @@ -64,7 +65,10 @@ if body: body = json.dumps(body) - headers = {'Accept': 'application/vnd.github.v3+json'} + if accept_header: + headers = {'Accept': accept_header} + else: + headers = {'Accept': 'application/vnd.github.v3+json'} if self.has_credentials(): headers['Authorization'] = 'Basic {}'.format(self.auth_token()) @@ -307,24 +311,6 @@ _log.info('Fetched %d PRs from GitHub.', len(all_prs)) return all_prs - def get_branch_statuses(self, branch_name): - """Gets the status of a PR. - - API doc: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref - - Returns: - The list of check statuses of the PR. - """ - path = '/repos/{}/{}/commits/{}/status'.format( - WPT_GH_ORG, WPT_GH_REPO_NAME, branch_name) - response = self.request(path, method='GET') - - if response.status_code != 200: - raise GitHubError(200, response.status_code, - 'get the statuses of PR %d' % branch_name) - - return response.data['statuses'] - def get_pr_branch(self, pr_number): """Gets the remote branch name of a PR. @@ -343,6 +329,33 @@ return response.data['head']['ref'] + def get_branch_check_runs(self, remote_branch_name): + """Returns the check runs of a remote branch. + + API doc: https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-git-reference + + Returns: + The list of check runs from the HEAD of the branch. + """ + path = '/repos/%s/%s/commits/%s/check-runs?page=1&per_page=%d' % ( + WPT_GH_ORG, WPT_GH_REPO_NAME, remote_branch_name, MAX_PER_PAGE) + accept_header = 'application/vnd.github.antiope-preview+json' + + check_runs = [] + while path is not None: + response = self.request(path, + method='GET', + accept_header=accept_header) + if response.status_code != 200: + raise GitHubError( + 200, response.status_code, + 'get branch check runs %s' % remote_branch_name) + + check_runs += response.data['check_runs'] + path = self.extract_link_next(response.getheader('Link')) + + return check_runs + def is_pr_merged(self, pr_number): """Checks if a PR has been merged.
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py b/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py index afe7893..dee3b5b 100644 --- a/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py +++ b/third_party/blink/tools/blinkpy/w3c/wpt_github_mock.py
@@ -35,7 +35,7 @@ self.create_pr_index = 0 self.create_pr_fail_index = create_pr_fail_index self.merged_index = merged_index - self.status = '' + self.check_runs = [] def all_pull_requests(self, limit=30): self.calls.append('all_pull_requests') @@ -90,9 +90,9 @@ self.calls.append('get_pr_branch') return 'fake_branch_PR_%d' % number - def get_branch_statuses(self, branch_name): - self.calls.append('get_branch_statuses') - return self.status + def get_branch_check_runs(self, remote_branch_name): + self.calls.append('get_branch_check_runs') + return self.check_runs def pr_for_chromium_commit(self, commit): self.calls.append('pr_for_chromium_commit')
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py b/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py index ed73364..d4fef809 100644 --- a/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py +++ b/third_party/blink/tools/blinkpy/w3c/wpt_github_unittest.py
@@ -80,8 +80,10 @@ len(self.wpt_github.recent_failing_chromium_exports()), 1) def test_recent_failing_chromium_exports_all_pages(self): - self.wpt_github = WPTGitHub( - MockHost(), user='rutabaga', token='decafbad', pr_history_window=1) + self.wpt_github = WPTGitHub(MockHost(), + user='rutabaga', + token='decafbad', + pr_history_window=1) self.wpt_github.host.web.responses = [ { 'status_code': @@ -271,20 +273,56 @@ with self.assertRaises(GitHubError): self.wpt_github.create_pr('branch', 'title', 'body') - def test_get_branch_statuses(self): + def test_branch_check_runs_single_page(self): + self.wpt_github = WPTGitHub(MockHost(), + user='rutabaga', + token='decafbad', + pr_history_window=1) self.wpt_github.host.web.responses = [ { 'status_code': 200, - 'body': json.dumps({ - 'statuses': [{ - 'description': 'abc' - }] - }) + 'headers': { + 'Link': '' + }, + 'body': json.dumps({'check_runs': [{ + 'conclusion': 'success' + }]}) }, ] self.assertEqual( - self.wpt_github.get_branch_statuses('1234')[0]['description'], - 'abc') + self.wpt_github.get_branch_check_runs('1')[0]['conclusion'], + 'success') + + def test_branch_check_runs_all_pages(self): + self.wpt_github = WPTGitHub(MockHost(), + user='rutabaga', + token='decafbad', + pr_history_window=1) + self.wpt_github.host.web.responses = [ + { + 'status_code': 200, + 'headers': { + 'Link': + '<https://api.github.com/resources?page=2>; rel="next"' + }, + 'body': json.dumps({'check_runs': [{ + 'conclusion': 'success' + }]}) + }, + { + 'status_code': 200, + 'headers': { + 'Link': '' + }, + 'body': json.dumps({'check_runs': [{ + 'conclusion': 'failure' + }]}) + }, + ] + + check_runs = self.wpt_github.get_branch_check_runs('1') + self.assertEqual(check_runs[0]['conclusion'], 'success') + self.assertEqual(check_runs[1]['conclusion'], 'failure') def test_get_pr_branch(self): self.wpt_github.host.web.responses = [ @@ -376,8 +414,14 @@ def test_pr_for_chromium_commit_prefers_change_id(self): self.wpt_github.all_pull_requests = lambda: [ - PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee\nCr-Commit-Position: refs/heads/master@{#10}', 'open', []), - PullRequest('PR2', 2, 'body\nChange-Id: I00decade\nCr-Commit-Position: refs/heads/master@{#33}', 'open', []), + PullRequest( + 'PR1', 1, + 'body\nChange-Id: I00c0ffee\nCr-Commit-Position: refs/heads/master@{#10}', + 'open', []), + PullRequest( + 'PR2', 2, + 'body\nChange-Id: I00decade\nCr-Commit-Position: refs/heads/master@{#33}', + 'open', []), ] chromium_commit = MockChromiumCommit( MockHost(), @@ -388,7 +432,9 @@ def test_pr_for_chromium_commit_multiple_change_ids(self): self.wpt_github.all_pull_requests = lambda: [ - PullRequest('PR1', 1, 'body\nChange-Id: I00c0ffee\nChange-Id: I00decade', 'open', []), + PullRequest('PR1', 1, + 'body\nChange-Id: I00c0ffee\nChange-Id: I00decade', + 'open', []), ] chromium_commit = MockChromiumCommit(
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 99a39e6..eb366e35 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1096,13 +1096,8 @@ crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/composited-with-overflow-in-next-column.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/doubly-nested-with-top-padding-crossing-row-boundaries.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/change-second-row-height.html [ Failure ] -crbug.com/1105758 virtual/layout_ng_block_frag/fast/multicol/dynamic/insert-spanner-before-content.html [ Crash ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/insert-spanner-into-stf-constrained-width.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/insert-spanner-into-stf-unconstrained-width.html [ Failure ] -crbug.com/1105758 virtual/layout_ng_block_frag/fast/multicol/dynamic/insert-spanner-pseudo-after-then-content.html [ Crash ] -crbug.com/1105758 virtual/layout_ng_block_frag/fast/multicol/dynamic/insert-spanner-pseudo-before-after-in-content.html [ Crash ] -crbug.com/1105758 virtual/layout_ng_block_frag/fast/multicol/dynamic/insert-spanner-pseudo-before-following-content.html [ Crash ] -crbug.com/1105758 virtual/layout_ng_block_frag/fast/multicol/dynamic/insert-spanner-pseudo-before.html [ Crash ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/relpos-becomes-static-has-abspos.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/remove-column-content-next-to-abspos-between-spanners.html [ Failure ] crbug.com/591099 virtual/layout_ng_block_frag/fast/multicol/dynamic/static-becomes-relpos-has-abspos.html [ Crash Failure ] @@ -1278,15 +1273,6 @@ virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/cascade/* [ Skip ] virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/text/* [ Skip ] -# Fieldset in NG -# - -# Size containment -crbug.com/875235 external/wpt/css/css-sizing/contain-intrinsic-size/contain-intrinsic-size-014.html [ Failure ] -# Mask paiting area -crbug.com/875235 paint/masks/fieldset-mask.html [ Failure ] - - # ====== LayoutNG-only failures until here ====== # ====== MathMLCore-only tests from here ====== @@ -2669,6 +2655,36 @@ crbug.com/1105958 external/wpt/payment-request/payment-is-showing.https.html [ Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/table-cell-001.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/table-cell-001.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/table-cell-001.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/table-progression-vrl-004.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/table-progression-vrl-004.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/table-progression-vrl-004.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/line-box-direction-vlr-016.xht [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/line-box-direction-vlr-016.xht [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/line-box-direction-vlr-016.xht [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/line-box-direction-vrl-015.xht [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/line-box-direction-vrl-015.xht [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/line-box-direction-vrl-015.xht [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/table-progression-vlr-003.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/table-progression-vlr-003.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/table-progression-vlr-003.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/block-flow-direction-vrl-017.xht [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/block-flow-direction-vrl-017.xht [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/block-flow-direction-vrl-017.xht [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/table-progression-vlr-004.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/table-progression-vlr-004.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/table-progression-vlr-004.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/table-cell-002.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/table-cell-002.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/table-cell-002.html [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/block-flow-direction-vlr-018.xht [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/block-flow-direction-vlr-018.xht [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/block-flow-direction-vlr-018.xht [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/css/css-writing-modes/table-progression-vrl-003.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-writing-modes/table-progression-vrl-003.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-writing-modes/table-progression-vrl-003.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-8.html [ Failure ] crbug.com/626703 [ Mac ] external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-8.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-8.html [ Failure ] @@ -6757,3 +6773,5 @@ # Sheriff 2020-08-11 crbug.com/1095540 virtual/threaded-prefer-compositing/fast/scrolling/resize-corner-tracking-touch.html [ Pass Failure ] + +crbug.com/1113521 [ Mac ] fast/events/mouse-cursor-image-set.html [ Pass Crash ]
diff --git a/third_party/blink/web_tests/W3CImportExpectations b/third_party/blink/web_tests/W3CImportExpectations index 3fa4e02..3d5f8a0 100644 --- a/third_party/blink/web_tests/W3CImportExpectations +++ b/third_party/blink/web_tests/W3CImportExpectations
@@ -287,30 +287,6 @@ external/wpt/css/css-writing-modes/writing-mode-parsing-sideways-lr-001.html [ Skip ] external/wpt/css/css-writing-modes/writing-mode-parsing-sideways-rl-001.html [ Skip ] -# CSS Writing Modes Level 3: Following tests require applying writing-mode to table-cell, which we do not support today. crbug.com/409155 -external/wpt/css/css-writing-modes/block-flow-direction-vlr-018.xht [ Skip ] -external/wpt/css/css-writing-modes/block-flow-direction-vrl-017.xht [ Skip ] -external/wpt/css/css-writing-modes/line-box-direction-vlr-016.xht [ Skip ] -external/wpt/css/css-writing-modes/line-box-direction-vrl-015.xht [ Skip ] -external/wpt/css/css-writing-modes/table-cell-001.html [ Skip ] -external/wpt/css/css-writing-modes/table-cell-002.html [ Skip ] - -# CSS Writing Modes Level 3: Following tests require bottom-to-top or mixed ordering of table cells, which we do not support today. crbug.com/409155 -external/wpt/css/css-writing-modes/table-column-order-002.xht [ Skip ] -external/wpt/css/css-writing-modes/table-column-order-003.xht [ Skip ] -external/wpt/css/css-writing-modes/table-column-order-004.xht [ Skip ] -external/wpt/css/css-writing-modes/table-column-order-005.xht [ Skip ] -external/wpt/css/css-writing-modes/table-progression-001-ref.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-002-ref.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vlr-001.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vlr-002.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vlr-003.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vlr-004.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vrl-001.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vrl-002.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vrl-003.html [ Skip ] -external/wpt/css/css-writing-modes/table-progression-vrl-004.html [ Skip ] - # CSS Writing Modes Level 3: Following tests require new definition of ch unit, which we do not support today. crbug.com/409155 external/wpt/css/css-writing-modes/ch-units-vrl-001.html [ Skip ] external/wpt/css/css-writing-modes/ch-units-vrl-002.html [ Skip ]
diff --git a/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-undefined-expected.html b/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-undefined-expected.html deleted file mode 100644 index a2ea5ade..0000000 --- a/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-undefined-expected.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<style> -.box { - width: 100px; - height: 100px; - background-color: #0f0; - transform: translateY(0px); -} -</style> - -<div id="first" class="box"></div> -<div id="second" class="box"></div> -<div id="third" class="box" style="transform: translateY(150px)"></div>
diff --git a/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-undefined.html b/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-undefined.html deleted file mode 100644 index 4070b104..0000000 --- a/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-undefined.html +++ /dev/null
@@ -1,66 +0,0 @@ -<!DOCTYPE html> -<style> -.box { - width: 100px; - height: 100px; - background-color: #0f0; -} -</style> - -<div id="first" class="box"></div> -<div id="second" class="box"></div> -<div id="third" class="box"></div> - -<script type="text/worklet"> -registerAnimator("first_animator", class { - animate(currentTime, effect) { - // Unset effect.localTime is equivalent to 'null' - } -}); - -registerAnimator("second_animator", class { - animate(currentTime, effect) { - // explicitly set the localtime to null. - effect.localTime = null; - } -}); - -registerAnimator("third_animator", class { - animate(currentTime, effect) { - // Here to ensure we actually are producing frames. - effect.localTime = 500; - } -}); -</script> - -<script src="resources/animation-worklet-tests.js"></script> - -<script> - -if (window.testRunner) - testRunner.waitUntilDone(); - -runInAnimationWorklet( - document.querySelector('script[type*=worklet]').textContent -).then(_ => { - for (let testcase of ['first', 'second', 'third']) { - const animation = new WorkletAnimation(`${testcase}_animator`, - new KeyframeEffect(document.getElementById(testcase), - [ - { transform: 'translateY(200px)' }, - { transform: 'translateY(100px)' } - ], { - duration: 1000, - } - ) - ); - animation.play(); - } - - if (window.testRunner) { - waitTwoAnimationFrames(_ => { - testRunner.notifyDone(); - }); - } -}); -</script>
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 d413b05..1a25e41 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
@@ -120557,6 +120557,19 @@ {} ] ], + "block-flow-direction-vlr-018.xht": [ + "7f8bb9f4ebdad2cd0b940522ecc25eb6219f5570", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], "block-flow-direction-vlr-020.xht": [ "89fe29d53c31c0d7cdbc1f1ba6559b027caeced0", [ @@ -120687,6 +120700,19 @@ {} ] ], + "block-flow-direction-vrl-017.xht": [ + "b51f4eaf2258af6ed8b5e6fd8f2a9aae91661bbe", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], "block-flow-direction-vrl-019.xht": [ "2144962990767bb4e2ff7f32f168dafa355f722b", [ @@ -122858,6 +122884,19 @@ {} ] ], + "line-box-direction-vlr-016.xht": [ + "39be7a9283049b58bf059591c444235db1428620", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], "line-box-direction-vlr-018.xht": [ "24c7ed33a83750e7f47c0b67fb771f676d7b70a8", [ @@ -122962,6 +123001,19 @@ {} ] ], + "line-box-direction-vrl-015.xht": [ + "4e2791accf005962039f689a8e7b543bf7d4fa10", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], "line-box-direction-vrl-017.xht": [ "2f1ef84d3045381d2908fc47aed67f81733306e7", [ @@ -125679,6 +125731,188 @@ {} ] ], + "table-cell-001.html": [ + "29344abbab5e0a1e0b521d97f0b3470984b4e4aa", + [ + null, + [ + [ + "/css/css-writing-modes/reference/table-cell-001-ref.html", + "==" + ] + ], + {} + ] + ], + "table-cell-002.html": [ + "320926f39455b8ecfd50c43462b3ba6dd019d207", + [ + null, + [ + [ + "/css/css-writing-modes/reference/table-cell-002-ref.html", + "==" + ] + ], + {} + ] + ], + "table-column-order-002.xht": [ + "9fd26e3caddea5b582ef70951e38244c04541b68", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], + "table-column-order-003.xht": [ + "c26de3887dfe6f42b7a5ed8a84712aec64f97ff2", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], + "table-column-order-004.xht": [ + "9ee1bab1a8032faafedc788c79e5e50dc28221db", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], + "table-column-order-005.xht": [ + "635714a2af07f880e5fe7a57d3cfb1e725bfb99d", + [ + null, + [ + [ + "/css/css-writing-modes/block-flow-direction-001-ref.xht", + "==" + ] + ], + {} + ] + ], + "table-progression-vlr-001.html": [ + "6b9d3c1f443cdde8f2aa8650bb40782554ff7657", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-001-ref.html", + "==" + ] + ], + {} + ] + ], + "table-progression-vlr-002.html": [ + "a3668178a93b5237f3ab08ffaa5c551fbb9c1fdf", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-002-ref.html", + "==" + ] + ], + {} + ] + ], + "table-progression-vlr-003.html": [ + "def5c3c36d952d89f0ad4ecdaf6d4876a7634d24", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-001-ref.html", + "==" + ] + ], + {} + ] + ], + "table-progression-vlr-004.html": [ + "dd444e35ac8ae9e03ffa772bbc721a7a3f2388c8", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-002-ref.html", + "==" + ] + ], + {} + ] + ], + "table-progression-vrl-001.html": [ + "c5c309005852e47070b39883ce2baaf79db6dfb9", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-001-ref.html", + "==" + ] + ], + {} + ] + ], + "table-progression-vrl-002.html": [ + "99fe8153e591f0ab1de09699868b0e09cb734614", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-002-ref.html", + "==" + ] + ], + {} + ] + ], + "table-progression-vrl-003.html": [ + "3116f30a17ff31fc0f0ec92dc8c7cbaa26e94e5d", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-001-ref.html", + "==" + ] + ], + {} + ] + ], + "table-progression-vrl-004.html": [ + "bcafef13c9d94876a1d201f344386866a812a68c", + [ + null, + [ + [ + "/css/css-writing-modes/table-progression-002-ref.html", + "==" + ] + ], + {} + ] + ], "tcy-white-space-processing-001.html": [ "fd81fe91fa7f872a102e720aa94635f897683878", [ @@ -193370,6 +193604,14 @@ [] ] }, + "table-progression-001-ref.html": [ + "41aa1295ad34ab5e41a2186030b574752750ad01", + [] + ], + "table-progression-002-ref.html": [ + "37445460b878e7fe24290f6e80d7cac6a9cb31b4", + [] + ], "test-plan": { "img": { "figure-over_and_under-fail.svg": [ @@ -198143,7 +198385,7 @@ [] ], "testharness-api.md": [ - "72263dbd4ead3d0dc2340bcdc83064f9ea8dffa5", + "38997a2dcc945c3c569b1348313ba92dff5fec85", [] ], "testharness-tutorial.md": [ @@ -207246,8 +207488,16 @@ "d7da078904c86fb7656af6001c27c5871698b619", [] ], + "property-indexed-getter.https.html.headers": [ + "64f4d5fedffd208b7174c7d8e0bce4e99ce1ac0f", + [] + ], + "property-named-getter.https.html.headers": [ + "64f4d5fedffd208b7174c7d8e0bce4e99ce1ac0f", + [] + ], "property.https-expected.txt": [ - "ba655328c973a9fd51197c2b50f2616f3d038103", + "9276b03e5919a4230a2ee14c42fab0abec9d6d18", [] ] }, @@ -218340,7 +218590,7 @@ [] ], "performance-timeline.idl": [ - "d3783858578c881b352e571deeb8cc4c9f0e6454", + "36107ddeea296df350a2f4da33fcc396d203eaae", [] ], "periodic-background-sync.idl": [ @@ -229657,6 +229907,10 @@ "f495a0c554537f1161981e19c12c597ba41ef2b2", [] ], + "com.apple.SafariTechnologyPreview.plist": [ + "122080972c9f63410062ee8d33d0ed0286af8f11", + [] + ], "fyi_hook.yml": [ "f02f3cd8224e0b3eb4f478318f0437f5a475f4e5", [] @@ -229686,7 +229940,7 @@ [] ], "install_safari.yml": [ - "d0660d152bbdfc89f308bfc048cd2221e9ea7524", + "6c1b562d411a2aeecc30d3fbc1aed6362f3526e5", [] ], "pip_install.yml": [ @@ -337169,7 +337423,7 @@ "reporting": { "access-reporting": { "openee-accessed_openee-coop-ro.https.html": [ - "1472afa63c1d61d54cb68b3f3d192778fd7381de", + "24943b03f39106596bef73612d7b286f02531ec2", [ null, { @@ -337178,7 +337432,7 @@ ] ], "openee-accessed_openee-coop.https.html": [ - "64dd07b5701a640244330435f88172a1c2c60984", + "07ba21a0c742bab4606dd27a6d0fd5b492a7b449", [ null, { @@ -337205,7 +337459,7 @@ ] ], "opener-accessed_openee-coop-ro.https.html": [ - "3e5180af6260a691e08ee649c87e68a6579e3c59", + "b8f9f22e7cbf4ca80fd152258b539b106b77dbb1", [ null, { @@ -337214,7 +337468,7 @@ ] ], "opener-accessed_openee-coop.https.html": [ - "e39dcfcec6a8bd9a5011944873d76d6689f80b34", + "ffce48de49627c02807316309b541f748e943d6c", [ null, { @@ -337240,8 +337494,26 @@ } ] ], + "property-indexed-getter.https.html": [ + "d2309e5fbd14c4dc987f8fde6ec02c41ca774819", + [ + null, + { + "timeout": "long" + } + ] + ], + "property-named-getter.https.html": [ + "2ab9093fcb58f1346854c443de41e3f8f2a00243", + [ + null, + { + "timeout": "long" + } + ] + ], "property.https.html": [ - "625fc94117768b792a27c148f609ccccef61507b", + "6a22cb2076cbfcf042926ef7249d98139651de53", [ null, { @@ -356247,6 +356519,15 @@ {} ] ], + "input-timestamp.html": [ + "02dde1ad5d740fb62c82994c05518cec4017dbaa", + [ + null, + { + "testdriver": true + } + ] + ], "local-shift-without-viewport-shift.html": [ "37729f1c13c298b5a2d95c46b7a4f199d8943022", [
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-after-duration-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/references/not-translated-box-ref.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-after-duration-ref.html rename to third_party/blink/web_tests/external/wpt/animation-worklet/references/not-translated-box-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/references/translated-box-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/references/translated-box-ref.html index c73f5a1..f1dde2e1 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/references/translated-box-ref.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/references/translated-box-ref.html
@@ -5,6 +5,7 @@ height: 100px; transform: translateY(100px); background-color: green; + will-change: transform; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-cancel-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-cancel-ref.html deleted file mode 100644 index d4492737..0000000 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-cancel-ref.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!DOCTYPE html> -<title>Reference for Canceling a playing WorkletAnimation should remove the effect</title> -<style> -#box { - width: 100px; - height: 100px; - background-color: blue; -} -</style> - -<div id="box"></div>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-cancel.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-cancel.https.html index 3a28c75..3b664ec 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-cancel.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-cancel.https.html
@@ -2,7 +2,7 @@ <title>Canceling a playing WorkletAnimation should remove the effect</title> <link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> <meta name="assert" content="Canceling a playing animation should remove the effect"> -<link rel="match" href="worklet-animation-cancel-ref.html"> +<link rel="match" href="references/not-translated-box-ref.html"> <script src="/web-animations/testcommon.js"></script> <script src="/common/reftest-wait.js"></script> @@ -12,7 +12,7 @@ #box { width: 100px; height: 100px; - background-color: blue; + background-color: green; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread-ref.html deleted file mode 100644 index aad07d5..0000000 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread-ref.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!DOCTYPE html> -<title>Reference for Animation Worklet should have access to effect timing from within the worklet thread</title> -<style> -#box { - width: 100px; - height: 100px; - background-color: green; - transform: translateY(100px); -} -</style> - -<div id="box"></div>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread.https.html index 54d1c8b..4ba68d7 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-get-timing-on-worklet-thread.https.html
@@ -2,7 +2,7 @@ <title>Animation Worklet should have access to effect timing from within the worklet thread</title> <link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> <meta name="assert" content="Animation Worklet should have access to effect timing from within the worklet thread"> -<link rel="match" href="worklet-animation-get-timing-on-worklet-thread-ref.html"> +<link rel="match" href="references/translated-box-ref.html"> <script src="/web-animations/testcommon.js"></script> <script src="/common/reftest-wait.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-after-duration.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-after-duration.https.html index adc90f1d..21293bc 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-after-duration.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-after-duration.https.html
@@ -2,7 +2,7 @@ <title>Animation Worklet local time set after duration</title> <link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> <meta name="assert" content="If an effect doesn't have fill-mode specified, setting its local time beyond its duration makes the animation inactive."> -<link rel="match" href="worklet-animation-local-time-after-duration-ref.html"> +<link rel="match" href="references/not-translated-box-ref.html"> <script src="/web-animations/testcommon.js"></script> <script src="/common/reftest-wait.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-before-start-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-before-start-ref.html deleted file mode 100644 index cda4ca4..0000000 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-before-start-ref.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<title>Reference for Animation Worklet local time set before start</title> -<style> -#box { - width: 100px; - height: 100px; - background-color: green; - will-change: transform; - transform: translateY(200px); -} -</style> - -<div id="box"></div>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-before-start.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-before-start.https.html index addb16e..a959b73c 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-before-start.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-before-start.https.html
@@ -2,7 +2,7 @@ <title>Animation Worklet local time set before start</title> <link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> <meta name="assert" content="The local time should be trimmed by the duration, e.g. this is equivalent to effect.localTime = 0"> -<link rel="match" href="worklet-animation-local-time-before-start-ref.html"> +<link rel="match" href="references/translated-box-ref.html"> <script src="/web-animations/testcommon.js"></script> <script src="/common/reftest-wait.js"></script> @@ -23,7 +23,7 @@ const box = document.getElementById('box'); const effect = new KeyframeEffect(box, [ - { transform: 'translateY(200px)' }, + { transform: 'translateY(100px)' }, { transform: 'translateY(0px)' } ], { duration: 1000,
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-1.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-1.https.html new file mode 100644 index 0000000..7db0a97 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-1.https.html
@@ -0,0 +1,163 @@ +<!DOCTYPE html> +<title>Setting localTime to null means effect does not apply</title> +<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="common.js"></script> + +<style> +.box { + width: 100px; + height: 100px; + background-color: green; + display: inline-block; +} +</style> + +<div> +<div class="box" id="target1"></div> +<div class="box" id="target2"></div> +<div class="box" id="target3"></div> +<div class="box" id="target4"></div> +</div> + + +<script> +promise_test(async t => { + await runInAnimationWorklet(` + registerAnimator("blank_animator", class { + animate(currentTime, effect) { + // Unset effect.localTime is equivalent to 'null' + } + }); + `); + const target = document.getElementById('target1'); + + const animation = new WorkletAnimation('blank_animator', + new KeyframeEffect(target, + [ + { transform: 'translateY(100px)' }, + { transform: 'translateY(200px)' } + ], { + duration: 1000, + } + ) + ); + animation.play(); + await waitForAsyncAnimationFrames(1); + assert_equals(getComputedStyle(target).transform, "matrix(1, 0, 0, 1, 0, 0)"); +}, "A worklet which never sets localTime has no effect."); + +promise_test(async t => { + await runInAnimationWorklet(` + registerAnimator("null_animator", class { + animate(currentTime, effect) { + effect.localTime = null; + } + }); + `); + const target = document.getElementById('target2'); + + const animation = new WorkletAnimation('null_animator', + new KeyframeEffect(target, + [ + { transform: 'translateY(100px)' }, + { transform: 'translateY(200px)' } + ], { + duration: 1000, + } + ) + ); + animation.play(); + await waitForAsyncAnimationFrames(1); + assert_equals(getComputedStyle(target).transform, "matrix(1, 0, 0, 1, 0, 0)"); +}, "A worklet which sets localTime to null has no effect."); + +promise_test(async t => { + await runInAnimationWorklet(` + registerAnimator("drop_animator", class { + animate(currentTime, effect) { + if (currentTime < 500) + effect.localTime = 500; + else if (currentTime < 1000) + effect.localTime = 0; + else + effect.localTime = null; + } + }); + `); + const target = document.getElementById('target3'); + + const animation = new WorkletAnimation('drop_animator', + new KeyframeEffect(target, + [ + { transform: 'translateY(100px)' }, + { transform: 'translateY(200px)' } + ], { + duration: 1000, + } + ) + ); + animation.play(); + await waitForAsyncAnimationFrames(5); + assert_equals(getComputedStyle(target).transform, "matrix(1, 0, 0, 1, 0, 150)", + "The animation has an effect at first"); + + await waitForAnimationFrameWithCondition(() => animation.currentTime > 500); + await waitForAsyncAnimationFrames(1); + assert_equals(getComputedStyle(target).transform, "matrix(1, 0, 0, 1, 0, 100)", + "The effect correctly changes"); + + await waitForAnimationFrameWithCondition(() => animation.currentTime > 1000); + await waitForAsyncAnimationFrames(1); + assert_equals(getComputedStyle(target).transform, "matrix(1, 0, 0, 1, 0, 0)", + "The effect stops on nulling of localTime"); + +}, "A worklet which changes localTime to from a number to null has no effect on transform."); + +promise_test(async t => { + await runInAnimationWorklet(` + registerAnimator("drop2_animator", class { + animate(currentTime, effect) { + if (currentTime < 500) + effect.localTime = 500; + else if (currentTime < 1000) + effect.localTime = 0; + else + effect.localTime = null; + } + }); + `); + const target = document.getElementById('target4'); + + const animation = new WorkletAnimation('drop2_animator', + new KeyframeEffect(target, + [ + { backgroundColor: 'red' }, + { backgroundColor: 'blue' } + ], { + duration: 1000, + } + ) + ); + animation.play(); + await waitForAsyncAnimationFrames(5); + assert_equals(getComputedStyle(target).backgroundColor, "rgb(128, 0, 128)", + "The animation has an effect at first"); + + await waitForAnimationFrameWithCondition(() => animation.currentTime > 500); + await waitForAsyncAnimationFrames(1); + assert_equals(getComputedStyle(target).backgroundColor, "rgb(255, 0, 0)", + "The effect correctly changes"); + + await waitForAnimationFrameWithCondition(() => animation.currentTime > 1000); + await waitForAsyncAnimationFrames(1); + assert_equals(getComputedStyle(target).backgroundColor, "rgb(0, 128, 0)", + "The effect stops on nulling of localTime"); + +}, "A worklet which changes localTime to from a number to null has no effect on backgroundColor."); + + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-2-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-2-ref.html new file mode 100644 index 0000000..3b7a2b9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-2-ref.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Setting localTime to null means effect does not apply (reftest)</title> +<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> + +<style> +.box { + width: 100px; + height: 100px; + background-color: green; + display: inline-block; +} + +#control { + background-color: red; + transform: translateY(100px); +} +</style> + +<div> +<div class="box" id="target1"></div> +<div class="box" id="target2"></div> +<div class="box" id="target3"></div> +<div class="box" id="target4"></div> +<div class="box" id="control"></div> +</div> + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-2.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-2.https.html new file mode 100644 index 0000000..5a83e96 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-local-time-null-2.https.html
@@ -0,0 +1,108 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>Setting localTime to null means effect does not apply (reftest)</title> +<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> +<link rel="match" href="worklet-animation-local-time-null-2-ref.html"> + +<script src="/common/reftest-wait.js"></script> +<script src="/web-animations/testcommon.js"></script> +<script src="common.js"></script> + +<style> +.box { + width: 100px; + height: 100px; + background-color: green; + display: inline-block; +} +</style> + +<div> +<div class="box" id="target1"></div> +<div class="box" id="target2"></div> +<div class="box" id="target3"></div> +<div class="box" id="target4"></div> +<div class="box" id="control"></div> +</div> + + +<script> +runInAnimationWorklet(` + registerAnimator("blank_animator", class { + animate(currentTime, effect) { + // Unset effect.localTime is equivalent to 'null' + } + }); + + registerAnimator("null_animator", class { + animate(currentTime, effect) { + effect.localTime = null; + } + }); + + registerAnimator("drop_animator", class { + animate(currentTime, effect) { + if (currentTime < 500) + effect.localTime = 500; + else if (currentTime < 1000) + effect.localTime = 0; + else + effect.localTime = null; + } + }); + + registerAnimator("add_animator", class { + animate(currentTime, effect) { + if (currentTime < 1000) + effect.localTime = 500; + else + effect.localTime = 0; + } + }); +`).then(() => { + + const start_animation = (animator, targetId, keyframes) => { + const animation = new WorkletAnimation(animator, + new KeyframeEffect( + document.getElementById(targetId), + keyframes, + {duration: 1000} + ) + ); + animation.play(); + return animation; + }; + + start_animation('blank_animator','target1', [ + { transform: 'translateY(100px)' }, + { transform: 'translateY(200px)' } + ]); + + start_animation('null_animator','target2', [ + { transform: 'translateY(100px)' }, + { transform: 'translateY(200px)' } + ]); + + start_animation('drop_animator','target3', [ + { transform: 'translateY(100px)' }, + { transform: 'translateY(200px)' } + ]); + + start_animation('drop_animator','target4', [ + { backgroundColor: 'red' }, + { backgroundColor: 'blue' } + ]); + + // check that animation worklets are running to stop accidental pass + const control_anim = start_animation('add_animator','control', [ + { backgroundColor: 'red', transform: 'translateY(100px)' }, + { backgroundColor: 'blue', transform: 'translateY(200px)' } + ]); + + waitForAnimationFrameWithCondition(() => control_anim.currentTime > 1000) + .then(() => waitForAsyncAnimationFrames(1)) + .then(takeScreenshot); +}); + + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-keyframes-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-keyframes-ref.html deleted file mode 100644 index 26bf33f..0000000 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-keyframes-ref.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!DOCTYPE html> -<title>Reference for Worklet Animation sets keyframes</title> -<style> -#box { - width: 100px; - height: 100px; - transform: translateX(100px); - background-color: green; -} -</style> - -<div id="box"></div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-keyframes.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-keyframes.https.html index 01740849..d3d0289 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-keyframes.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-keyframes.https.html
@@ -2,7 +2,7 @@ <title>Worklet Animation sets keyframes</title> <link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> <meta name="assert" content="Can update the keyframes for an effect while the animation is running"> -<link rel="match" href="worklet-animation-set-keyframes-ref.html"> +<link rel="match" href="references/translated-box-ref.html"> <script src="/web-animations/testcommon.js"></script> <script src="/common/reftest-wait.js"></script> @@ -21,13 +21,13 @@ <script> registerConstantLocalTimeAnimator(500).then(()=>{ const keyframes_before = [ - { transform: 'translateY(0)' }, - { transform: 'translateY(200px)' } - ]; - const keyframes_after = [ { transform: 'translateX(0)' }, { transform: 'translateX(200px)' } ]; + const keyframes_after = [ + { transform: 'translateY(0)' }, + { transform: 'translateY(200px)' } + ]; const box = document.getElementById('box'); const effect = new KeyframeEffect(box, keyframes_before, {duration: 1000});
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-timing-ref.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-timing-ref.html deleted file mode 100644 index 8c354a8..0000000 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-timing-ref.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!DOCTYPE html> -<title>Reference for Worklet Animation sets timing</title> -<style> -#box { - width: 100px; - height: 100px; - transform: translateX(50px); - background-color: green; -} -</style> - -<div id="box"></div> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-timing.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-timing.https.html index ac3f05f4..6c5cd513 100644 --- a/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-timing.https.html +++ b/third_party/blink/web_tests/external/wpt/animation-worklet/worklet-animation-set-timing.https.html
@@ -2,7 +2,7 @@ <title>Worklet Animation sets timing</title> <link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/"> <meta name="assert" content="Can update the timing for an effect while the animation is running"> -<link rel="match" href="worklet-animation-set-timing-ref.html"> +<link rel="match" href="references/translated-box-ref.html"> <script src="/web-animations/testcommon.js"></script> <script src="/common/reftest-wait.js"></script> @@ -21,8 +21,8 @@ <script> registerConstantLocalTimeAnimator(500).then(()=>{ const keyframes = [ - { transform: 'translateX(0)' }, - { transform: 'translateX(200px)' } + { transform: 'translateY(0)' }, + { transform: 'translateY(400px)' } ]; const options_before = { duration: 1000
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-018.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-018.xht new file mode 100644 index 0000000..7f8bb9f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/block-flow-direction-vlr-018.xht
@@ -0,0 +1,95 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: table-cell and 'vertical-lr' - block flow direction of block-level boxes</title> + + <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that a table-cell with its 'writing-mode' set to 'vertical-lr' establishes a block formating context with a left-to-right block flow direction." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + div#table-cell + { + display: table-cell; + height: 9em; + writing-mode: vertical-lr; + } + + div#table-cell > div + { + background-color: blue; + border-bottom: blue solid 1em; + border-top: blue solid 1em; + } + + div.left-border + { + border-left: blue solid 1em; + } + + div#right-border + { + border-right: blue solid 1em; + } + ]]></style> + </head> + + <body> + + <div id="table-cell"> + +<!-- The 1st left-most line of "P" --> <div class="left-border">AAAAAAA</div> + +<!-- The 2nd left-most line of "P" --> <div>B C </div> + +<!-- The 3rd left-most line of "P" --> <div>D E </div> + +<!-- The 4th left-most line of "P" --> <div>FFFF </div> + + + +<!-- The left-most line of "A" --> <div class="left-border">GGGGGGG</div> + +<!-- The 2nd left-most line of "A" --> <div>H J </div> + +<!-- The 3rd left-most line of "A" --> <div>K L </div> + +<!-- The 4th left-most line of "A" --> <div>MMMMMMM</div> + + + +<!-- The 1st left-most line of left-most "S" --> <div class="left-border">NNNN Q</div> + +<!-- The 2nd left-most line of left-most "S" --> <div>R S T</div> + +<!-- The 3rd left-most line of left-most "S" --> <div>U V W</div> + +<!-- The 4th left-most line of left-most "S" --> <div>X YYYY</div> + + + +<!-- The left-most line of right-most "S" --> <div class="left-border">aaaa b</div> + +<!-- The 2nd left-most line of right-most "S" --> <div>c d e</div> + +<!-- The 3rd left-most line of right-most "S" --> <div>f g h</div> + +<!-- The 4th left-most line of right-most "S" --> <div id="right-border">j kkkk</div> + + </div> + + </body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-017.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-017.xht new file mode 100644 index 0000000..b51f4ea --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/block-flow-direction-vrl-017.xht
@@ -0,0 +1,95 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: table-cell and 'vertical-rl' - block flow direction of block-level boxes</title> + + <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that a table-cell with its 'writing-mode' set to 'vertical-rl' establishes a block formating context with a right-to-left block flow direction." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + div#table-cell + { + display: table-cell; + height: 9em; + writing-mode: vertical-rl; + } + + div#table-cell > div + { + background-color: blue; + border-bottom: blue solid 1em; + border-top: blue solid 1em; + } + + div.right-border + { + border-right: blue solid 1em; + } + + div#left-border + { + border-left: blue solid 1em; + } + ]]></style> + </head> + + <body> + + <div id="table-cell"> + +<!-- The right-most line of right-most "S" --> <div class="right-border">A BBBB</div> + +<!-- The 2nd right-most line of right-most "S" --> <div>C D E</div> + +<!-- The 3rd right-most line of right-most "S" --> <div>F G H</div> + +<!-- The 4th right-most line of right-most "S" --> <div>JJJJ K</div> + + + +<!-- The right-most line of left-most "S" --> <div class="right-border">L MMMM</div> + +<!-- The 2nd right-most line of left-most "S" --> <div>Q R S</div> + +<!-- The 3rd right-most line of left-most "S" --> <div>T U V</div> + +<!-- The 4th right-most line of left-most "S" --> <div>WWWW X</div> + + + +<!-- The right-most line of "A" --> <div class="right-border">YYYYYYY</div> + +<!-- The 2nd right-most line of "A" --> <div>Z a </div> + +<!-- The 3rd right-most line of "A" --> <div>b c </div> + +<!-- The 4th right-most line of "A" --> <div>ddddddd</div> + + + +<!-- The right-most line of "P" --> <div class="right-border">eeee </div> + +<!-- The 2nd right-most line of "P" --> <div>f g </div> + +<!-- The 3rd right-most line of "P" --> <div>h j </div> + +<!-- The 4th right-most line of "P" --> <div id="left-border">kkkkkkk</div> + + </div> + + </body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/line-box-direction-vlr-016.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/line-box-direction-vlr-016.xht new file mode 100644 index 0000000..39be7a92 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/line-box-direction-vlr-016.xht
@@ -0,0 +1,40 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: table-cell and 'vertical-lr' - ordering direction of line boxes</title> + + <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that the lines boxes of a table-cell with its 'writing-mode' set to 'vertical-lr' are ordered from left to right." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + div + { + background-color: blue; + border: blue solid 1em; + display: table-cell; + height: 7em; /* Each line box has an inline-size of 7em */ + writing-mode: vertical-lr; + } + ]]></style> + </head> + + <body> + + <div>AAAAAAA B C D E FFFF GGGGGGG H J K L MMMMMMM NNNN Q R S T U V W X YYYY aaaa b c d e f g h j kkkk</div> + + </body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/line-box-direction-vrl-015.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/line-box-direction-vrl-015.xht new file mode 100644 index 0000000..4e2791ac --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/line-box-direction-vrl-015.xht
@@ -0,0 +1,40 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: table-cell and 'vertical-rl' - ordering direction of line boxes</title> + + <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the writing-mode property" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that the lines boxes of a table-cell with its 'writing-mode' set to 'vertical-rl' are ordered from right to left." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + div + { + background-color: blue; + border: blue solid 1em; + display: table-cell; + height: 7em; /* Each line box has an inline-size of 7em */ + writing-mode: vertical-rl; + } + ]]></style> + </head> + + <body> + + <div>A BBBB C D E F G H JJJJ K L MMMM Q R S T U V WWWW X YYYYYYY Z a b c ddddddd eeee f g h j kkkkkkk</div> + + </body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-cell-001.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-cell-001.html new file mode 100644 index 0000000..29344abb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-cell-001.html
@@ -0,0 +1,43 @@ +<!doctype html> +<html lang="en"> +<meta charset="utf-8"> +<title>CSS Writing Mode test: orthogonal table cell</title> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"> +<meta assert="The writing mode property applies to table cells: two adjacent cells can have orthogonal writing modes, and the enclosing table must be laid out correctly."> +<meta flags="ahem"> +<link rel="match" href="reference/table-cell-001-ref.html"> +<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/"> + +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +table, td { + padding: 0; + border-spacing: 0; + font: 20px/20px ahem; +} +td { background: green; } +#t2 { writing-mode: vertical-rl; } + +#red { + font: 20px/20px ahem; + position: absolute; + z-index: -1; + background: red; + height: 4em; + width: 5em; +} + + +</style> + +<p>There should be a <strong>green rectangle</strong> and <strong>no red</strong>. + +<div id=red></div> + +<table><tbody><tr><td id=t1> </td><td id=t2> </td></tr></tbody></table> +<!-- +* Each table cell should be 4em in its inline dimention: horizontal for the first, vertical for the second. +* The first table cell should be 4em tall, to match the height of the second one. +* The second table cell should be 1em in its block dimention, which is horizontal. +* Juxtaposing the two that give 4em x 5em. +-->
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-cell-002.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-cell-002.html new file mode 100644 index 0000000..320926f3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-cell-002.html
@@ -0,0 +1,33 @@ +<!doctype html> +<html lang="en"> +<meta charset="utf-8"> +<title>CSS Writing Mode test: orthogonal table cell</title> +<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#block-flow"> +<meta assert="The writing mode property applies to table cells: max-heights constrains on a vertical table cell (in a horizontal table) + ought to have the same effect on the cell as max-width would on horizontal ones. + Lines of longer than the max which have break opportunities are expected to wrap."> +<meta flags="ahem"> +<link rel="match" href="reference/table-cell-002-ref.html"> +<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/"> + +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> +<style> +table, td { + padding: 0; + border-spacing: 0; +} +td { + max-height: 100px; + font: 50px / 50px ahem; + color: green; + writing-mode: vertical-rl; + background: red; +} +</style> + +<p>There should be a <strong>green square</strong> and <strong>no red</strong>. + +<table><tbody><tr><td>xx xx</td></tr></tbody></table> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-002.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-002.xht new file mode 100644 index 0000000..9fd26e3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-002.xht
@@ -0,0 +1,70 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-rl</title> + + <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> + <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 --> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that a table with 'writing-mode' set to 'vertical-rl' and with 'direction' set to 'rtl' will have its column displayed from bottom (1st column) to top (last column). This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + table + { + background-color: blue; + border-spacing: 0em; + border: blue solid 1em; + height: 7em; + direction: rtl; + writing-mode: vertical-rl; + } + + td + { + padding-bottom: 0em; + padding-left: 1em; + padding-right: 0em; + padding-top: 0em; + } + + td.left-most-cell + { + padding-left: 0em; + } + ]]></style> + </head> + + <body> + + <table> + + <!-- The right-most "S" --> + <tr><td><!-- bottommost column -->111 2 3 4 </td><td>5 6 7 88</td><td><!-- topmost column --> 9 0 1 22</td></tr> + + <!-- The left-most "S" --> + <tr><td><!-- bottommost column -->333 4 5 6 </td><td>7 8 9 00</td><td><!-- topmost column --> 1 2 3 44</td></tr> + + <!-- The "A" --> + <tr><td><!-- bottommost column -->555 666</td><td>77 8 9 00</td><td><!-- topmost column -->11 2 3 44</td></tr> + + <!-- The "P" --> + <tr><td class="left-most-cell"><!-- bottommost column --> 555</td><td class="left-most-cell">66 7 8 99</td><td class="left-most-cell"><!-- topmost column -->00 1 2 33</td></tr> + + </table> + + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-003.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-003.xht new file mode 100644 index 0000000..c26de38 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-003.xht
@@ -0,0 +1,70 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-lr</title> + + <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> + <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 --> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that a table with 'writing-mode' set to 'vertical-lr' and with 'direction' set to 'rtl' will have its column displayed from bottom (1st column) to top (last column). This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + table + { + background-color: blue; + border-spacing: 0em; + border: blue solid 1em; + height: 7em; + direction: rtl; + writing-mode: vertical-lr; + } + + td + { + padding-bottom: 0em; + padding-left: 1em; + padding-right: 0em; + padding-top: 0em; + } + + td.left-most-cell + { + padding-left: 0em; + } + ]]></style> + </head> + + <body> + + <table> + + <!-- The "P" --> + <tr><td class="left-most-cell"><!-- bottommost column -->111 </td><td class="left-most-cell">22 3 4 55</td><td class="left-most-cell"><!-- topmost column -->66 7 8 99</td></tr> + + <!-- The "A" --> + <tr><td><!-- bottommost column -->000 111</td><td>22 3 4 55</td><td><!-- topmost column -->66 7 8 99</td></tr> + + <!-- The left-most "S" --> + <tr><td><!-- bottommost column -->0 1 2 333</td><td>44 5 6 7 </td><td><!-- topmost column -->88 9 0 1</td></tr> + + <!-- The right-most "S" --> + <tr><td><!-- bottommost column -->2 3 4 555</td><td>66 7 8 9 </td><td><!-- topmost column -->00 1 2 3</td></tr> + + </table> + + </body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-004.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-004.xht new file mode 100644 index 0000000..9ee1bab1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-004.xht
@@ -0,0 +1,70 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-rl</title> + + <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> + <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 --> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that colspanned cells in a table with 'direction' set to 'rtl' are handled according to a bottom-to-top column direction. This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + table + { + background-color: blue; + border-spacing: 0em; + border: blue solid 1em; + height: 7em; + direction: rtl; + writing-mode: vertical-rl; + } + + td + { + padding-bottom: 0em; + padding-left: 1em; + padding-right: 0em; + padding-top: 0em; + } + + td.left-most-cell + { + padding-left: 0em; + } + ]]></style> + </head> + + <body> + + <table> + + <!-- The right-most "S" --> + <tr><td><!-- bottommost column -->111 2 3 4 </td><td>5 6 7 88</td><td><!-- topmost column --> 9 0 1 22</td></tr> + + <!-- The left-most "S" --> + <tr><td colspan="2"><!-- bottommost column -->3333 4 5 6 7 8 99</td><td><!-- topmost column --> 1 2 3 44</td></tr> + + <!-- The "A" --> + <tr><td><!-- bottommost column -->555 666</td><td colspan="2"><!-- topmost column -->7777 8 9 0 1 2222</td></tr> + + <!-- The "P" --> + <tr><td class="left-most-cell"><!-- bottommost column --> 333</td><td class="left-most-cell">44 5 6 77</td><td class="left-most-cell"><!-- topmost column -->88 9 0 11</td></tr> + + </table> + + </body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-005.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-005.xht new file mode 100644 index 0000000..635714a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-column-order-005.xht
@@ -0,0 +1,70 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + + <title>CSS Writing Modes Test: 'direction: rtl' - table columns order and vertical-lr</title> + + <link rel="author" title="Hajime Shiozawa" href="mailto:hajime.shiozawa@gmail.com" /> + <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2015-12-21 --> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the direction property" /> + <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes" /> + <link rel="match" href="block-flow-direction-001-ref.xht" /> + + <meta content="ahem" name="flags" /> + <meta content="This test checks that colspanned cells in a table with 'direction' set to 'rtl' are handled according to a bottom-to-top column direction. This test relies on right-to-left directionality applying to characters that are strongly sensitive to directionality. In this test, we use digits [0-9] and non-breaking spaces which are all strongly sensitive to bidi directionality." name="assert" /> + + <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + <style type="text/css"><![CDATA[ + body + { + color: yellow; + font: 20px/1 Ahem; + } + + table + { + background-color: blue; + border-spacing: 0em; + border: blue solid 1em; + height: 7em; + direction: rtl; + writing-mode: vertical-lr; + } + + td + { + padding-bottom: 0em; + padding-left: 1em; + padding-right: 0em; + padding-top: 0em; + } + + td.left-most-cell + { + padding-left: 0em; + } + ]]></style> + </head> + + <body> + + <table> + + <!-- The "P" --> + <tr><td class="left-most-cell"><!-- bottommost column -->111 </td><td class="left-most-cell">22 3 4 55</td><td class="left-most-cell"><!-- topmost column -->66 7 8 99</td></tr> + + <!-- The "A" --> + <tr><td colspan="2"><!-- bottommost column -->00000 1 2 33333</td><td><!-- topmost column -->44 5 6 77</td></tr> + + <!-- The left-most "S" --> + <tr><td><!-- bottommost column -->8 9 0 111</td><td colspan="2"><!-- topmost column -->2222 3 4 5 6 7 8</td></tr> + + <!-- The right-most "S" --> + <tr><td><!-- bottommost column -->9 0 1 222</td><td>33 4 5 6 </td><td><!-- topmost column -->77 8 9 0</td></tr> + + </table> + + </body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-001-ref.html new file mode 100644 index 0000000..41aa129 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-001-ref.html
@@ -0,0 +1,93 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Reference</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2016-01-15 --> + +<style> + table { + border-spacing: 0; + margin: 1em; + } + td { + width: 1em; + height: 1em; + border: solid gray; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } + .purp { background: purple } + .pink { background: fuchsia } + .yllw { background: yellow } + .orng { background: orange } + caption { background: green; } +</style> + +<p>Test passes if the following three tables look identical. + +<table> + <caption></caption> + <tr> + <td rowspan=2> + <td class="orng"> + <td colspan=3> + <td class="navy"> + <tr> + <td rowspan=3> + <td class="yllw"> + <td class="pink"> + <td rowspan=2> + <td class="blue"> + <tr> + <td class="aqua"> + <td rowspan=2 colspan=2> + <td rowspan=2> + <tr> + <td class="teal"> + <td class="purp"> +</table> + +<table> + <tr> + <td rowspan=2> + <td class="orng"> + <td colspan=3> + <td class="navy"> + <tr> + <td rowspan=3> + <td class="yllw"> + <td class="pink"> + <td rowspan=2> + <td class="blue"> + <tr> + <td class="aqua"> + <td rowspan=2 colspan=2> + <td rowspan=2> + <tr> + <td class="teal"> + <td class="purp"> +</table> + +<table> + <tr> + <td rowspan=2> + <td class="orng"> + <td colspan=3> + <td class="navy"> + <tr> + <td rowspan=3> + <td class="yllw"> + <td class="pink"> + <td rowspan=2> + <td class="blue"> + <tr> + <td class="aqua"> + <td rowspan=2 colspan=2> + <td rowspan=2> + <tr> + <td class="teal"> + <td class="purp"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-002-ref.html new file mode 100644 index 0000000..37445460 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-002-ref.html
@@ -0,0 +1,68 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Reference</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2016-01-15 --> + +<style> + table { + border-spacing: 0; + border: solid gray; + margin: 1em; + float: left; + } + td { + width: 1em; + height: 1em; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } +</style> + +<p>Test passes if the following patterned boxes all look identical. + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table> + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table> + + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table> + + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table> + + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-001.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-001.html new file mode 100644 index 0000000..6b9d3c1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-001.html
@@ -0,0 +1,135 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-lr Table Row/Rowgroup/Cell Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 --> +<link rel="match" href="table-progression-001-ref.html"> +<meta name="assert" content="This test checks that vertical-lr tables order rows/rowgroups left to right and cells top-to-bottom (LTR) or bottom-to-top (RTL) per 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table rows and row groups."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property"> + +<style> + .test { + writing-mode: vertical-lr; + } + [dir=rtl] { + direction: rtl; + } + + table { + border-spacing: 0; + margin: 1em; + } + td { + width: 1em; + height: 1em; + border: solid gray; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } + .purp { background: purple } + .pink { background: fuchsia } + .yllw { background: yellow } + .orng { background: orange } + + + /* These rules must have no effect. */ + .test thead, + .test tfoot, + .test tbody, + .test tr, + .test td { + writing-mode: horizontal-tb; /* For UAs not supporting vertical-rl */ + writing-mode: vertical-rl; + direction: rtl; + } + .test[dir=rtl] thead, + .test[dir=rtl] tfoot, + .test[dir=rtl] tbody, + .test[dir=rtl] tr, + .test[dir=rtl] td { + direction: ltr; + } +</style> + +<p>Test passes if the following three tables look identical. + +<table class="test"> + <thead> + <tr> + <td colspan=2> + <td class="aqua"> + <td class="teal"> + <tfoot> + <tr> + <td class="navy"> + <td class="blue"> + <td colspan=2> + <tbody> + <tr> + <td class="orng"> + <td colspan=3> + <tbody> + <tr> + <td rowspan=3> + <td class="yllw"> + <td rowspan=2 colspan=2> + <tr> + <td class="pink"> + <tr> + <td colspan=2> + <td class="purp"> +</table> + +<table dir=rtl class="test"> + <thead> + <tr> + <td class="teal"> + <td class="aqua"> + <td colspan=2> + <tfoot> + <tr> + <td colspan=2> + <td class="blue"> + <td class="navy"> + <tbody> + <tr> + <td colspan=3> + <td class="orng"> + <tbody> + <tr> + <td rowspan=2 colspan=2> + <td class="yllw"> + <td rowspan=3> + <tr> + <td class="pink"> + <tr> + <td class="purp"> + <td colspan=2> +</table> + + +<table class="reference"> + <tr> + <td rowspan=2> + <td class="orng"> + <td colspan=3> + <td class="navy"> + + <tr> + <td rowspan=3> + <td class="yllw"> + <td class="pink"> + <td rowspan=2> + <td class="blue"> + <tr> + <td class="aqua"> + <td rowspan=2 colspan=2> + <td rowspan=2> + <tr> + <td class="teal"> + <td class="purp"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-002.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-002.html new file mode 100644 index 0000000..a3668178 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-002.html
@@ -0,0 +1,87 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-lr Table Column/Colgroup Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 --> +<link rel="match" href="table-progression-002-ref.html"> +<meta name="assert" content="This test checks that vertical-lr tables order columns top-to-bottom (LTR) or bottom-to-top (RTL) per the table's 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table columns and column groups."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction"z> + +<style> + .test { + writing-mode: vertical-lr; + } + [dir=rtl] { + direction: rtl; + } + + + table { + border-spacing: 0; + border: solid gray; + margin: 1em; + float: left; + } + td { + width: 1em; + height: 1em; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } + + /* These declarations must have no effect. */ + .test col, + .test colgroup { + writing-mode: horizontal-tb; + writing-mode: vertical-rl; + direction: rtl; + } + .test[dir=rtl] col, + .test[dir=rtl] colgroup { + direction: ltr; + } +</style> + +<p>Test passes if the following patterned boxes all look identical. + +<table class="test"> + <col span=2 class="navy"> + <col class="blue"> + <col span=2 class="aqua"> + <tr><td><td><td><td><td> +</table> +<table class="test"> + <colgroup span=2 class="navy"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="aqua"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table dir=rtl class="test"> + <col span=2 class="aqua"> + <col class="blue"> + <col span=2 class="navy"> + <tr><td><td><td><td><td> +</table> +<table dir=rtl class="test"> + <colgroup span=2 class="aqua"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="navy"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-003.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-003.html new file mode 100644 index 0000000..def5c3c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-003.html
@@ -0,0 +1,116 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-lr upright orientation Table Row/Rowgroup/Cell Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-19 --> +<link rel="match" href="table-progression-001-ref.html"> +<meta name="assert" content="This test checks that vertical-lr tables, whether LTR or RTL, order rows/rowgroups left to right and cells top-to-bottom when text-orientation is upright."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property"> + +<style> + .test { + writing-mode: vertical-lr; + text-orientation: upright; + } + [dir=rtl] { + direction: rtl; + } + + table { + border-spacing: 0; + margin: 1em; + } + td { + width: 1em; + height: 1em; + border: solid gray; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } + .purp { background: purple } + .pink { background: fuchsia } + .yllw { background: yellow } + .orng { background: orange } +</style> + +<p>Test passes if the following three tables look identical. + +<table class="test"> + <thead> + <tr> + <td colspan=2> + <td class="aqua"> + <td class="teal"> + <tfoot> + <tr> + <td class="navy"> + <td class="blue"> + <td colspan=2> + <tbody> + <tr> + <td class="orng"> + <td colspan=3> + <tbody> + <tr> + <td rowspan=3> + <td class="yllw"> + <td rowspan=2 colspan=2> + <tr> + <td class="pink"> + <tr> + <td colspan=2> + <td class="purp"> +</table> + +<table class="test" dir=rtl> + <thead> + <tr> + <td colspan=2> + <td class="aqua"> + <td class="teal"> + <tfoot> + <tr> + <td class="navy"> + <td class="blue"> + <td colspan=2> + <tbody> + <tr> + <td class="orng"> + <td colspan=3> + <tbody> + <tr> + <td rowspan=3> + <td class="yllw"> + <td rowspan=2 colspan=2> + <tr> + <td class="pink"> + <tr> + <td colspan=2> + <td class="purp"> +</table> + +<table class="reference"> + <tr> + <td rowspan=2> + <td class="orng"> + <td colspan="3"> + <td class="navy"> + <tr> + <td rowspan="3"> + <td class="yllw"> + <td class="pink"> + <td rowspan="2"> + <td class="blue"> + <tr> + <td class="aqua"> + <td rowspan=2 colspan=2> + <td rowspan=2> + <tr> + <td class="teal"> + <td class="purp"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-004.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-004.html new file mode 100644 index 0000000..dd444e3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vlr-004.html
@@ -0,0 +1,76 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-lr upright orientation Table Column/Colgroup Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="match" href="table-progression-002-ref.html"> +<meta name="assert" content="This test checks that vertical-lr tables, whether LTR or RTL, order columns top-to-bottom when text-orientation is upright."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction"z> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property"> + +<style> + .test { + writing-mode: vertical-lr; + text-orientation: upright; + } + [dir=rtl] { + direction: rtl; + } + + + table { + border-spacing: 0; + border: solid gray; + margin: 1em; + float: left; + } + td { + width: 1em; + height: 1em; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } +</style> + +<p>Test passes if the following patterned boxes all look identical. + +<table class="test"> + <col span=2 class="navy"> + <col class="blue"> + <col span=2 class="aqua"> + <tr><td><td><td><td><td> +</table> +<table class="test"> + <colgroup span=2 class="navy"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="aqua"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table dir=rtl class="test"> + <col span=2 class="navy"> + <col class="blue"> + <col span=2 class="aqua"> + <tr><td><td><td><td><td> +</table> +<table dir=rtl class="test"> + <colgroup span=2 class="navy"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="aqua"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-001.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-001.html new file mode 100644 index 0000000..c5c30900 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-001.html
@@ -0,0 +1,132 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-rl Table Row/Rowgroup/Cell Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 --> +<link rel="match" href="table-progression-001-ref.html"> +<meta name="assert" content="This test checks that vertical-rl tables order rows/rowgroups right to left and cells top-to-bottom (LTR) or bottom-to-top (RTL) per 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table rows and row groups."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property"> + +<style> + .test { + writing-mode: vertical-rl; + } + [dir=rtl] { + direction: rtl; + } + + table { + border-spacing: 0; + margin: 1em; + } + td { + width: 1em; + height: 1em; + border: solid gray; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } + .purp { background: purple } + .pink { background: fuchsia } + .yllw { background: yellow } + .orng { background: orange } + + /* These rules must have no effect. */ + .test thead, + .test tfoot, + .test tbody, + .test tr, + .test td { + writing-mode: horizontal-tb; /* For UAs not supporting vertical-rl */ + writing-mode: vertical-lr; + direction: rtl; + } + .test[dir=rtl] thead, + .test[dir=rtl] tfoot, + .test[dir=rtl] tbody, + .test[dir=rtl] tr, + .test[dir=rtl] td { + direction: ltr; + } +</style> + +<p>Test passes if the following three tables look identical. + +<table class="test"> + <thead> + <tr> + <td class="navy"> + <td class="blue"> + <td colspan=2> + <tfoot> + <tr> + <td colspan=2> + <td class="aqua"> + <td class="teal"> + <tbody> + <tr> + <td rowspan=3> + <td colspan=2> + <td class="purp"> + <tr> + <td class="pink"> + <td rowspan=2 colspan=2> + <tr> + <td class="yllw"> + <tbody> + <tr> + <td class="orng"> + <td colspan=3> +</table> + +<table dir=rtl class="test"> + <thead> + <tr> + <td colspan=2> + <td class="blue"> + <td class="navy"> + <tfoot> + <tr> + <td class="teal"> + <td class="aqua"> + <td colspan=2> + <tbody> + <tr> + <td class="purp"> + <td colspan=2> + <td rowspan=3> + <tr> + <td rowspan=2 colspan=2> + <td class="pink"> + <tr> + <td class="yllw"> + <tbody> + <tr> + <td colspan=3> + <td class="orng"> +</table> + +<table class="reference"> + <tr> + <td rowspan=2> + <td class="orng"> + <td colspan="3"> + <td class="navy"> + <tr> + <td rowspan="3"> + <td class="yllw"> + <td class="pink"> + <td rowspan="2"> + <td class="blue"> + <tr> + <td class="aqua"> + <td rowspan=2 colspan=2> + <td rowspan=2> + <tr> + <td class="teal"> + <td class="purp"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-002.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-002.html new file mode 100644 index 0000000..99fe815 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-002.html
@@ -0,0 +1,86 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-rl Table Column/Colgroup Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-15 --> +<link rel="match" href="table-progression-002-ref.html"> +<meta name="assert" content="This test checks that vertical-rl tables order columns top-to-bottom (LTR) or bottom-to-top (RTL) per the table's 'direction'. This test also checks that 'writing-mode' and 'direction' do not apply to table columns and column groups."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property"> + +<style> + .test { + writing-mode: vertical-rl; + } + [dir=rtl] { + direction: rtl; + } + + table { + border-spacing: 0; + border: solid gray; + margin: 1em; + float: left; + } + td { + width: 1em; + height: 1em; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } + + /* These declarations must have no effect. */ + .test col, + .test colgroup { + writing-mode: horizontal-tb; + writing-mode: vertical-lr; + direction: rtl; + } + .test[dir=rtl] col, + .test[dir=rtl] colgroup { + direction: ltr; + } +</style> + +<p>Test passes if the following patterned boxes all look identical. + +<table class="test"> + <col span=2 class="navy"> + <col class="blue"> + <col span=2 class="aqua"> + <tr><td><td><td><td><td> +</table> +<table class="test"> + <colgroup span=2 class="navy"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="aqua"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table dir=rtl class="test"> + <col span=2 class="aqua"> + <col class="blue"> + <col span=2 class="navy"> + <tr><td><td><td><td><td> +</table> +<table dir=rtl class="test"> + <colgroup span=2 class="aqua"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="navy"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-003.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-003.html new file mode 100644 index 0000000..3116f30 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-003.html
@@ -0,0 +1,116 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-rl upright orientation Table Row/Rowgroup/Cell Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/"> <!-- 2016-01-19 --> +<link rel="match" href="table-progression-001-ref.html"> +<meta name="assert" content="This test checks that vertical-rl tables, whether LTR or RTL, order rows/rowgroups right to left and cells top-to-bottom when text-orientation is upright."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property"> + +<style> + .test { + writing-mode: vertical-rl; + text-orientation: upright; + } + [dir=rtl] { + direction: rtl; + } + + table { + border-spacing: 0; + margin: 1em; + } + td { + width: 1em; + height: 1em; + border: solid gray; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } + .purp { background: purple } + .pink { background: fuchsia } + .yllw { background: yellow } + .orng { background: orange } +</style> + +<p>Test passes if the following three tables look identical. + +<table class="test"> + <thead> + <tr> + <td class="navy"> + <td class="blue"> + <td colspan=2> + <tfoot> + <tr> + <td colspan=2> + <td class="aqua"> + <td class="teal"> + <tbody> + <tr> + <td rowspan=3> + <td colspan=2> + <td class="purp"> + <tr> + <td class="pink"> + <td rowspan=2 colspan=2> + <tr> + <td class="yllw"> + <tbody> + <tr> + <td class="orng"> + <td colspan=3> +</table> + +<table class="test" dir=rtl> + <thead> + <tr> + <td class="navy"> + <td class="blue"> + <td colspan=2> + <tfoot> + <tr> + <td colspan=2> + <td class="aqua"> + <td class="teal"> + <tbody> + <tr> + <td rowspan=3> + <td colspan=2> + <td class="purp"> + <tr> + <td class="pink"> + <td rowspan=2 colspan=2> + <tr> + <td class="yllw"> + <tbody> + <tr> + <td class="orng"> + <td colspan=3> +</table> + +<table class="reference"> + <tr> + <td rowspan=2> + <td class="orng"> + <td colspan="3"> + <td class="navy"> + <tr> + <td rowspan="3"> + <td class="yllw"> + <td class="pink"> + <td rowspan="2"> + <td class="blue"> + <tr> + <td class="aqua"> + <td rowspan=2 colspan=2> + <td rowspan=2> + <tr> + <td class="teal"> + <td class="purp"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-004.html b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-004.html new file mode 100644 index 0000000..bcafef13 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/table-progression-vrl-004.html
@@ -0,0 +1,75 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Test: vertical-rl upright orientation Table Column/Colgroup Ordering</title> +<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"> +<link rel="match" href="table-progression-002-ref.html"> +<meta name="assert" content="This test checks that vertical-rl tables, whether LTR or RTL, order columns top-to-bottom when text-orientation is upright."> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#block-flow" title="3.1 Block Flow Direction: the 'writing-mode' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#direction" title="2.1 Specifying Directionality: the 'direction' property"> +<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#text-orientation" title="5.1 Orienting Text: the 'text-orientation' property"> + +<style> + .test { + writing-mode: vertical-rl; + text-orientation: upright; + } + [dir=rtl] { + direction: rtl; + } + + table { + border-spacing: 0; + border: solid gray; + margin: 1em; + float: left; + } + td { + width: 1em; + height: 1em; + } + + .navy { background: navy} + .blue { background: blue } + .aqua { background: aqua } + .teal { background: teal } +</style> + +<p>Test passes if the following patterned boxes all look identical. + +<table class="test"> + <col span=2 class="navy"> + <col class="blue"> + <col span=2 class="aqua"> + <tr><td><td><td><td><td> +</table> +<table class="test"> + <colgroup span=2 class="navy"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="aqua"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table dir=rtl class="test"> + <col span=2 class="navy"> + <col class="blue"> + <col span=2 class="aqua"> + <tr><td><td><td><td><td> +</table> +<table dir=rtl class="test"> + <colgroup span=2 class="navy"></colgroup> + <colgroup> + <col class="blue"> + <col span=2 class="aqua"> + </colgroup> + <tr><td><td><td><td><td> +</table> + +<table class="reference"> + <tr><td class="navy"> + <tr><td class="navy"> + <tr><td class="blue"> + <tr><td class="aqua"> + <tr><td class="aqua"> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/docs/writing-tests/testharness-api.md b/third_party/blink/web_tests/external/wpt/docs/writing-tests/testharness-api.md index 72263db..38997a2 100644 --- a/third_party/blink/web_tests/external/wpt/docs/writing-tests/testharness-api.md +++ b/third_party/blink/web_tests/external/wpt/docs/writing-tests/testharness-api.md
@@ -515,7 +515,7 @@ Both setup functions recognize the following properties: `explicit_done` - Wait for an explicit call to done() before declaring all -tests complete (see below; implicitly true for single page tests) +tests complete (see below; always true for single page tests) `output_document` - The document to which results should be logged. By default this is the current document but could be an ancestor document in some cases
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/performance-timeline.idl b/third_party/blink/web_tests/external/wpt/interfaces/performance-timeline.idl index d3783858..36107ddee 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/performance-timeline.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/performance-timeline.idl
@@ -20,7 +20,8 @@ }; callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries, - PerformanceObserver observer); + PerformanceObserver observer, + optional boolean hasDroppedEntry = false); [Exposed=(Window,Worker)] interface PerformanceObserver { constructor(PerformanceObserverCallback callback);
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/input-timestamp.html b/third_party/blink/web_tests/external/wpt/layout-instability/input-timestamp.html new file mode 100644 index 0000000..02dde1a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/layout-instability/input-timestamp.html
@@ -0,0 +1,71 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Layout Instability: observe timestamp after user input</title> + +<body> + <style> + #myDiv { + position: relative; + width: 300px; + height: 100px; + } + + /* Disable the button's focus ring, which otherwise expands its visual rect by + * 1px on all sides, triggering a layout shift event. + */ + #button { + outline: none; + } + </style> + <div id='myDiv'></div> + <button id='button'>Generate a 'click' event</button> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/resources/testdriver.js></script> + <script src=/resources/testdriver-vendor.js></script> + <script src=resources/util.js></script> + <script src=/event-timing/resources/event-timing-test-utils.js></script> + <script> + let timeAfterClick; + + promise_test(async t => { + assert_implements(window.LayoutShift, 'Layout Instability is not supported.'); + // Wait for the initial render to complete. + await waitForAnimationFrames(2); + + const startTime = performance.now(); + return new Promise(resolve => { + const observer = new PerformanceObserver( + t.step_func(entryList => { + const endTime = performance.now(); + assert_equals(entryList.getEntries().length, 1); + const entry = entryList.getEntries()[0]; + assert_equals(entry.entryType, "layout-shift"); + assert_equals(entry.name, ""); + assert_greater_than_equal(entry.startTime, startTime); + assert_less_than_equal(entry.startTime, endTime); + assert_equals(entry.duration, 0.0); + // The layout shift value should be: + // 300 * (100 + 60) * (60 / maxDimension) / viewport size. + assert_equals(entry.value, computeExpectedScore(300 * (100 + 60), 60)); + // We should see that there was a click input entry. + assert_equals(entry.hadRecentInput, false); + assert_greater_than_equal(timeAfterClick, entry.lastInputTime); + resolve(); + }) + ); + observer.observe({ entryTypes: ['layout-shift'] }); + // User input event + clickAndBlockMain('button').then(() => { + // 500ms delay + step_timeout(function() { + timeAfterClick = performance.now(); + // Modify the position of the div. + document.getElementById('myDiv').style = "top: 60px"; + }, 500); + }); + }); + }, 'Layout shift right after user input is observable via PerformanceObserver.'); + </script> + +</body>
diff --git a/third_party/blink/web_tests/external/wpt/payment-request/secure-payment-confirmation.https.html b/third_party/blink/web_tests/external/wpt/payment-request/secure-payment-confirmation.https.html deleted file mode 100644 index 655a3f6..0000000 --- a/third_party/blink/web_tests/external/wpt/payment-request/secure-payment-confirmation.https.html +++ /dev/null
@@ -1,225 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Test for 'secure-payment-confirmation' payment method</title> -<link rel="help" href="https://github.com/rsolomakhin/secure-payment-confirmation"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -'use strict'; - -const details = {total: - {label: 'Total', amount: {value: '0.01', currency: 'USD'}}}; - -test(() => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - // All valid parameters. - action: 'authenticate', - instrumentId: 'x', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); -}, 'Valid payment method data does not throw exceptions.'); - -test(() => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - // Omitted action field. - instrumentId: 'x', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); -}, 'The action field is optional.'); - -test(() => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - // Omitted timeout field. - fallbackUrl: 'https://fallback.example/url' - }, - }], details); -}, 'The timeout field is optional.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - // Invalid action parameter. - action: 'authorize', - instrumentId: 'x', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'Invalid action parameter throws an exception.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - // Omitted instrumentId field. - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'The instrumentId field is required.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - // Omitted instrumentId field. - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'The networkData field is required.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - // Omitted fallbackUrl field. - }, - }], details); - }); -}, 'The fallbackUrl field is required.'); - -test(() => { - assert_throws_js(RangeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - // Empty instrumentId field. - instrumentId: '', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'Empty instrumentId field throws exception.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - // Null networkData field. - networkData: null, - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'Null networkData field throws exception.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - // Empty networkData field. - networkData: [], - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'Empty networkData field throws exception.'); - -test(() => { - assert_throws_js(RangeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - // Timeout longer than 1 hour. - timeout: 1000 * 60 * 60 + 1, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'Timeout longer than 1 hour throws exception.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - // Large instrumentId value. - instrumentId: 'x'.repeat(1024 * 1024), - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'Large instrumentId value throws exception.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - // Large networkData value. - networkData: Uint8Array.from('x'.repeat(1024 * 1024), c => c.charCodeAt(0)), - timeout: 60000, - fallbackUrl: 'https://fallback.example/url' - }, - }], details); - }); -}, 'Large networkData value throws exception.'); - -test(() => { - assert_throws_js(TypeError, () => { - new PaymentRequest([{ - supportedMethods: 'secure-payment-confirmation', - data: { - action: 'authenticate', - instrumentId: 'x', - networkData: Uint8Array.from('x', c => c.charCodeAt(0)), - timeout: 60000, - // Large fallbackUrl value. - fallbackUrl: 'https://fallback.example/ur' + 'l'.repeat(1024 * 1024) - }, - }], details); - }); -}, 'Large fallbackUrl value throws exception.'); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_compat-mouse-events-when-removing-nodes.html b/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_compat-mouse-events-when-removing-nodes.html index 88d03b7..6d13b0de 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_compat-mouse-events-when-removing-nodes.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/compat/pointerevent_compat-mouse-events-when-removing-nodes.html
@@ -5,12 +5,17 @@ <script src="/resources/testdriver-vendor.js"></script> <script src="/resources/testdriver-actions.js"></script> <script type="text/javascript" src="../pointerevent_support.js"></script> - +<!-- There are significant differences in how browsers fire pointer events and +compat mouse events when elements are removed from the dom. +There is a discussion about the order of pointer events and mouse compat events +for this scenario in the pointer event working group (See link below)--> +<link rel="help" href="https://github.com/w3c/pointerevents/issues/285"> <style> div.box { margin: 5px; padding: 20px; float: left; + background-color:green; } #grey { width: 50px; @@ -22,12 +27,14 @@ <div id="grey" class="box" style="background-color:grey"> </div> +<button id="done">Done</button> <div id="console"></div> <script> var receivedEvents = []; +var done_clicked = false; var eventList = ["mousedown", "mouseup", "mousemove", "pointerdown", "pointerup", "pointermove"]; @@ -62,6 +69,9 @@ }); } +var done_button = document.getElementById("done"); +done_button.addEventListener("click",()=>done_clicked=true); + function performActions() { var rect = document.getElementById("green").getBoundingClientRect(); var x1 = Math.ceil(rect.left + 5); @@ -73,13 +83,13 @@ .pointerDown() .pointerUp() .send() - .then( () => resolveWhen( () => receivedEvents.length == 6 ) ); + .then(()=> test_driver.click(done_button)); } function testScenario(targetEvent, expectedEvents, description) { promise_test(async () => { - removeNodeEvent = targetEvent; receivedEvents = []; + removeNodeEvent = targetEvent; createGreenBoxAndAddListeners(); await performActions();
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/azure/com.apple.SafariTechnologyPreview.plist b/third_party/blink/web_tests/external/wpt/tools/ci/azure/com.apple.SafariTechnologyPreview.plist new file mode 100644 index 0000000..1220809 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/tools/ci/azure/com.apple.SafariTechnologyPreview.plist
@@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>AllowRemoteAutomation</key> + <true/> +</dict> +</plist>
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/azure/install_safari.yml b/third_party/blink/web_tests/external/wpt/tools/ci/azure/install_safari.yml index d0660d1..6c1b562 100644 --- a/third_party/blink/web_tests/external/wpt/tools/ci/azure/install_safari.yml +++ b/third_party/blink/web_tests/external/wpt/tools/ci/azure/install_safari.yml
@@ -9,7 +9,10 @@ - ${{ if eq(parameters.channel, 'preview') }}: - script: | HOMEBREW_NO_AUTO_UPDATE=1 brew cask install tools/ci/azure/safari-technology-preview.rb - sudo "/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver" --enable + # Workaround for `sudo safardriver --enable` not working on Catalina: + # https://github.com/web-platform-tests/wpt/issues/21751 + mkdir -p ~/Library/WebDriver/ + cp tools/ci/azure/com.apple.SafariTechnologyPreview.plist ~/Library/WebDriver/ defaults write com.apple.SafariTechnologyPreview WebKitJavaScriptCanOpenWindowsAutomatically 1 defaults write com.apple.SafariTechnologyPreview ExperimentalServerTimingEnabled 1 displayName: 'Install Safari Technology Preview'
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/mac-system-ui-weight-expected.png index d49cd03..e064490 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/mac-system-ui-weight-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/mac-system-ui-weight-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/mac-system-ui-weight-expected.png index 416d476..0ef2b32b 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/mac-system-ui-weight-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/mac-system-ui-weight-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/mac-system-ui-weight-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/mac-system-ui-weight-expected.png index 87e7aaee..e782c16 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/mac-system-ui-weight-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/mac-system-ui-weight-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 66ebfbf1..15d27fb 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5147,6 +5147,8 @@ method refresh interface PointerEvent : MouseEvent attribute @@toStringTag + getter altitudeAngle + getter azimuthAngle getter height getter isPrimary getter pointerId
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium index 3b74616b..fee72d6 100644 --- a/third_party/harfbuzz-ng/README.chromium +++ b/third_party/harfbuzz-ng/README.chromium
@@ -1,10 +1,10 @@ Name: harfbuzz-ng Short Name: harfbuzz-ng URL: http://harfbuzz.org -Version: 2.7.0-42 +Version: 2.7.0-69 CPEPrefix: cpe:/a:harfbuzz_project:harfbuzz:2.6.4 -Date: 20200804 -Revision: cdb7d2b9bc0d5928ae4f6ba16fe905f603583688 +Date: 20200811 +Revision: d03eecb4d63e1cdac77a08d081179c28440b2d18 Security Critical: yes License: MIT License File: src/COPYING
diff --git a/tools/android/dependency_analysis/js/package.json b/tools/android/dependency_analysis/js/package.json index 97cbeb2..5ae301a 100644 --- a/tools/android/dependency_analysis/js/package.json +++ b/tools/android/dependency_analysis/js/package.json
@@ -11,7 +11,8 @@ "dependencies": { "@trevoreyre/autocomplete-vue": "^2.2.0", "d3": "^5.16.0", - "vue": "^2.6.11" + "vue": "^2.6.11", + "vue-material": "^1.0.0-beta-14" }, "devDependencies": { "copy-webpack-plugin": "^6.0.3",
diff --git a/tools/android/dependency_analysis/js/src/class_view.html b/tools/android/dependency_analysis/js/src/class_view.html index ed9c20e..db52db48e 100644 --- a/tools/android/dependency_analysis/js/src/class_view.html +++ b/tools/android/dependency_analysis/js/src/class_view.html
@@ -3,6 +3,8 @@ <head> <link rel="icon" type="image/png" href="https://fonts.gstatic.com/s/i/googlematerialicons/account_tree/v6/gm_blue-48dp/1x/gm_account_tree_gm_blue_48dp.png"> + <link rel="stylesheet" + href="//fonts.googleapis.com/css?family=Roboto:400,500,700,400italic|Material+Icons"> </head> <body> <div id="class-graph-page"></div>
diff --git a/tools/android/dependency_analysis/js/src/class_view.js b/tools/android/dependency_analysis/js/src/class_view.js index 4e5de7b..a998c016 100644 --- a/tools/android/dependency_analysis/js/src/class_view.js +++ b/tools/android/dependency_analysis/js/src/class_view.js
@@ -2,13 +2,39 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import Vue from 'vue'; import ClassGraphPage from './vue_components/class_graph_page.vue'; import {loadGraph} from './load_graph.js'; -import * as d3 from 'd3'; + +import Vue from 'vue'; +import { + MdButton, + MdCheckbox, + MdDivider, + MdField, + MdIcon, + MdList, + // MdMenu is a dependency of MdField's MdSelect, see + // https://github.com/vuematerial/vue-material/issues/1974 + MdMenu, + MdRadio, + MdSubheader, +} from 'vue-material/dist/components'; + +import 'vue-material/dist/vue-material.min.css'; +import 'vue-material/dist/theme/default.css'; document.addEventListener('DOMContentLoaded', () => { loadGraph().then(data => { + Vue.use(MdButton); + Vue.use(MdCheckbox); + Vue.use(MdDivider); + Vue.use(MdField); + Vue.use(MdIcon); + Vue.use(MdList); + Vue.use(MdMenu); + Vue.use(MdRadio); + Vue.use(MdSubheader); + new Vue({ el: '#class-graph-page', render: createElement => createElement( @@ -21,6 +47,6 @@ ), }); }).catch(e => { - document.write("Error loading graph."); + document.write('Error loading graph.'); }); });
diff --git a/tools/android/dependency_analysis/js/src/graph_view.js b/tools/android/dependency_analysis/js/src/graph_view.js index 2506174..0ab4eb0 100644 --- a/tools/android/dependency_analysis/js/src/graph_view.js +++ b/tools/android/dependency_analysis/js/src/graph_view.js
@@ -350,9 +350,10 @@ .classed('graph-labels', true) .attr('pointer-events', 'none'); - // TODO(yjlong): SVG should be resizable & these values updated. - const width = +svg.attr('width'); - const height = +svg.attr('height'); + // Using .style() instead of .attr() gets px-based measurements of + // percentage-based widths and heights. + const width = parseInt(svg.style('width'), 10); + const height = parseInt(svg.style('height'), 10); const centeringStrengthY = 0.1; const centeringStrengthX = centeringStrengthY * (height / width);
diff --git a/tools/android/dependency_analysis/js/src/package_view.html b/tools/android/dependency_analysis/js/src/package_view.html index 6c28e6b..3f77ad80 100644 --- a/tools/android/dependency_analysis/js/src/package_view.html +++ b/tools/android/dependency_analysis/js/src/package_view.html
@@ -3,6 +3,8 @@ <head> <link rel="icon" type="image/png" href="https://fonts.gstatic.com/s/i/googlematerialicons/account_tree/v6/gm_blue-48dp/1x/gm_account_tree_gm_blue_48dp.png"> + <link rel="stylesheet" + href="//fonts.googleapis.com/css?family=Roboto:400,500,700,400italic|Material+Icons"> </head> <body> <div id="package-graph-page"></div>
diff --git a/tools/android/dependency_analysis/js/src/package_view.js b/tools/android/dependency_analysis/js/src/package_view.js index f8929da..a775697 100644 --- a/tools/android/dependency_analysis/js/src/package_view.js +++ b/tools/android/dependency_analysis/js/src/package_view.js
@@ -2,13 +2,39 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import Vue from 'vue'; import PackageGraphPage from './vue_components/package_graph_page.vue'; import {loadGraph} from './load_graph.js'; -import * as d3 from 'd3'; + +import Vue from 'vue'; +import { + MdButton, + MdCheckbox, + MdDivider, + MdField, + MdIcon, + MdList, + // MdMenu is a dependency of MdField's MdSelect, see + // https://github.com/vuematerial/vue-material/issues/1974 + MdMenu, + MdRadio, + MdSubheader, +} from 'vue-material/dist/components'; + +import 'vue-material/dist/vue-material.min.css'; +import 'vue-material/dist/theme/default.css'; document.addEventListener('DOMContentLoaded', () => { loadGraph().then(data => { + Vue.use(MdButton); + Vue.use(MdCheckbox); + Vue.use(MdDivider); + Vue.use(MdField); + Vue.use(MdIcon); + Vue.use(MdList); + Vue.use(MdMenu); + Vue.use(MdRadio); + Vue.use(MdSubheader); + new Vue({ el: '#package-graph-page', render: createElement => createElement( @@ -21,6 +47,6 @@ ), }); }).catch(e => { - document.write("Error loading graph."); + document.write('Error loading graph.'); }); });
diff --git a/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue b/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue index 02d15b9..b6dff36 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/class_graph_hull_settings.vue
@@ -9,15 +9,15 @@ v-for="hullDisplay in HullDisplay" :key="hullDisplay" @change="displayOptionChanged"> - <input + <MdRadio :id="hullDisplay" v-model="internalSelectedHullDisplay" + class="md-primary hull-settings-option" type="radio" name="hullDisplayRadioButtons" :value="hullDisplay"> - <label :for="hullDisplay"> {{ hullDisplay }} - </label> + </MdRadio> </div> </div> </template> @@ -58,4 +58,8 @@ flex-direction: column; margin-bottom: 10px; } + +.hull-settings-option { + margin: 0; +} </style>
diff --git a/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue b/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue index 42023e5..9dc9e73c 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/class_graph_page.vue
@@ -4,31 +4,12 @@ <template> <div id="page-container"> - <div id="page-controls"> - <GraphFilterInput - :node-ids="pageModel.getNodeIds()" - :nodes-already-in-filter=" - displaySettingsData.nodeFilterData.filterList" - :shorten-name="filterShortenName" - @[CUSTOM_EVENTS.FILTER_SUBMITTED]="filterAddOrCheckNode"/> - <GraphFilterItems - :node-filter-data="displaySettingsData.nodeFilterData" - :shorten-name="filterShortenName" - @[CUSTOM_EVENTS.FILTER_REMOVE]="filterRemoveNode" - @[CUSTOM_EVENTS.FILTER_CHECK_ALL]="filterCheckAll" - @[CUSTOM_EVENTS.FILTER_UNCHECK_ALL]="filterUncheckAll"/> - <NumericInput - description="Change inbound (blue) depth:" - input-id="inbound-input" - :input-value.sync="displaySettingsData.inboundDepth" - :min-value="0"/> - <NumericInput - description="Change outbound (yellow) depth:" - input-id="outbound-input" - :input-value.sync="displaySettingsData.outboundDepth" - :min-value="0"/> - </div> - <div id="graph-and-node-details-container"> + <div id="title-and-graph-container"> + <div + id="title" + class="md-headline"> + Clank Dependency Viewer - Class Graph + </div> <GraphVisualization :graph-update-triggers="[ getNodeGroup, @@ -39,25 +20,61 @@ :get-node-group="getNodeGroup" @[CUSTOM_EVENTS.NODE_CLICKED]="graphNodeClicked" @[CUSTOM_EVENTS.NODE_DOUBLE_CLICKED]="graphNodeDoubleClicked"/> - <div id="node-details-container"> - <GraphDisplayPanel - :display-settings-data="displaySettingsData" - :display-settings-preset.sync=" - displaySettingsData.displaySettingsPreset"> - <GraphDisplaySettings - :display-settings-data="displaySettingsData" - @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> - <ClassGraphHullSettings - :selected-hull-display.sync="displaySettingsData.hullDisplay" - @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> - </GraphDisplayPanel> - <GraphSelectedNodeDetails - :selected-node-details-data="pageModel.selectedNodeDetailsData" - @[CUSTOM_EVENTS.DETAILS_CHECK_NODE]="filterAddOrCheckNode" - @[CUSTOM_EVENTS.DETAILS_UNCHECK_NODE]="filterUncheckNode"/> - <ClassDetailsPanel - :selected-class="pageModel.selectedNodeDetailsData.selectedNode"/> + </div> + <div + id="page-sidebar" + class="md-elevation-3"> + <MdSubheader class="sidebar-subheader"> + Node Filter + </MdSubheader> + <GraphFilterItems + id="graph-filter-items" + :node-filter-data="displaySettingsData.nodeFilterData" + :shorten-name="filterShortenName" + @[CUSTOM_EVENTS.FILTER_REMOVE]="filterRemoveNode" + @[CUSTOM_EVENTS.FILTER_CHECK_ALL]="filterCheckAll" + @[CUSTOM_EVENTS.FILTER_UNCHECK_ALL]="filterUncheckAll"/> + <GraphFilterInput + :node-ids="pageModel.getNodeIds()" + :nodes-already-in-filter=" + displaySettingsData.nodeFilterData.filterList" + :shorten-name="filterShortenName" + @[CUSTOM_EVENTS.FILTER_SUBMITTED]="filterAddOrCheckNode"/> + <MdSubheader class="sidebar-subheader"> + Display Options + </MdSubheader> + <div id="inbound-outbound-depth-inputs"> + <NumericInput + description="Inbound Depth" + input-id="inbound-input" + :input-value.sync="displaySettingsData.inboundDepth" + :min-value="0"/> + <NumericInput + description="Outbound Depth" + input-id="outbound-input" + :input-value.sync="displaySettingsData.outboundDepth" + :min-value="0"/> </div> + <GraphDisplayPanel + :display-settings-data="displaySettingsData" + :display-settings-preset.sync=" + displaySettingsData.displaySettingsPreset"> + <GraphDisplaySettings + :display-settings-data="displaySettingsData" + @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> + <ClassGraphHullSettings + :selected-hull-display.sync="displaySettingsData.hullDisplay" + @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> + </GraphDisplayPanel> + <MdSubheader class="sidebar-subheader"> + Node Details + </MdSubheader> + <GraphSelectedNodeDetails + :selected-node-details-data="pageModel.selectedNodeDetailsData" + @[CUSTOM_EVENTS.DETAILS_CHECK_NODE]="filterAddOrCheckNode" + @[CUSTOM_EVENTS.DETAILS_UNCHECK_NODE]="filterUncheckNode"/> + <ClassDetailsPanel + :selected-class="pageModel.selectedNodeDetailsData.selectedNode"/> </div> </div> </template> @@ -247,9 +264,43 @@ </style> <style scoped> +#title { + padding: 10px; +} + #page-container { display: flex; + flex-direction: row; + height: 100vh; + width: 100vw; +} + +#title-and-graph-container { + display: flex; flex-direction: column; + flex-grow: 1; +} + +#page-sidebar { + display: flex; + flex-direction: column; + flex-grow: 0; + overflow-y: scroll; + padding: 0 20px; + width: 30vw; +} + +.sidebar-subheader { + padding: 0; +} + +#graph-filter-items { + margin-bottom: 10px; +} + +#inbound-outbound-depth-inputs { + display: flex; + flex-direction: row; } #page-controls { @@ -257,9 +308,4 @@ flex-direction: row; height: 15vh; } - -#graph-and-node-details-container { - display: flex; - flex-direction: row; -} </style>
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_display_panel.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_display_panel.vue index 3a0e9b1..0e395a2 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/graph_display_panel.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_display_panel.vue
@@ -5,21 +5,31 @@ <template> <div id="display-panel"> <div id="preset-container"> - <select - v-model="internalDisplaySettingsPreset" - @change="applySelectedPreset"> - <option - v-for="presetName in DisplaySettingsPreset" - :key="presetName" - :value="presetName"> - {{ presetName }} - </option> - </select> - <button @click="settingsExpanded = !settingsExpanded"> - {{ settingsExpanded ? 'Collapse' : 'Expand' }} Advanced Settings - </button> + <MdField id="preset-select-container"> + <label for="preset-select">Display Preset</label> + <MdSelect + id="preset-select" + v-model="internalDisplaySettingsPreset" + @md-selected="applySelectedPreset"> + <MdOption + v-for="presetName in DisplaySettingsPreset" + :key="presetName" + :value="presetName"> + {{ presetName }} + </MdOption> + </MdSelect> + </MdField> + <MdButton + class="md-primary md-raised md-dense" + @click="settingsExpanded = !settingsExpanded"> + {{ settingsExpanded ? 'Hide' : 'Show' }} Advanced + </MdButton> </div> - <slot v-if="settingsExpanded"/> + <div + v-if="settingsExpanded" + id="advanced-panel"> + <slot/> + </div> </div> </template> @@ -63,8 +73,19 @@ <style scoped> #preset-container { + align-items: baseline; display: flex; flex-direction: row; + justify-content: space-between; +} + +#preset-select-container { + margin-bottom: 0; + width: 60%; +} + +#advanced-panel { + margin: 0 20px; } #display-panel {
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue index 4be37dba..4f524701 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_display_settings.vue
@@ -4,34 +4,36 @@ <template> <div id="display-settings"> - <div> - <input - id="curve-edges" - v-model="displaySettingsData.curveEdges" - type="checkbox" - @change="displayOptionChanged"> - <label for="curve-edges">Curve graph edges</label> - </div> - <div> - <input - id="color-on-hover" - v-model="displaySettingsData.colorOnlyOnHover" - type="checkbox" - @change="displayOptionChanged"> - <label for="color-on-hover">Color graph edges only on node hover</label> - </div> - <label for="graph-edge-color">Graph edge color scheme:</label> - <select - id="graph-edge-color" - v-model="displaySettingsData.graphEdgeColor" + <MdField class="display-settings-option"> + <label for="graph-edge-color">Graph edge color scheme:</label> + <MdSelect + id="graph-edge-color" + v-model="displaySettingsData.graphEdgeColor" + @md-selected="displayOptionChanged"> + <MdOption + v-for="edgeColor in GraphEdgeColor" + :key="edgeColor" + :value="edgeColor"> + {{ edgeColor }} + </MdOption> + </MdSelect> + </MdField> + <MdCheckbox + id="curve-edges" + v-model="displaySettingsData.curveEdges" + class="md-primary display-settings-option" + type="checkbox" @change="displayOptionChanged"> - <option - v-for="edgeColor in GraphEdgeColor" - :key="edgeColor" - :value="edgeColor"> - {{ edgeColor }} - </option> - </select> + Curve graph edges + </MdCheckbox> + <MdCheckbox + id="color-on-hover" + v-model="displaySettingsData.colorOnlyOnHover" + class="md-primary display-settings-option" + type="checkbox" + @change="displayOptionChanged"> + Color graph edges only on node hover + </MdCheckbox> </div> </template> @@ -63,4 +65,8 @@ flex-direction: column; margin-bottom: 10px; } + +.display-settings-option { + margin: 5px 0; +} </style>
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_filter_input.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_filter_input.vue index 101a72db..a3c8345 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/graph_filter_input.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_filter_input.vue
@@ -4,7 +4,11 @@ <template> <div class="user-input-group"> - <label for="filter-input">Add node to filter (exact name):</label> + <label + class="md-subheading" + for="filter-input"> + Add Node + </label> <Autocomplete id="filter-input" ref="autocomplete" @@ -76,16 +80,23 @@ <style> #filter-input { - width: 500px; + width: 100%; } .autocomplete-result-list { background: #fff; box-sizing: content-box; list-style: none; - max-height: 600px; + margin: 0; + max-height: 40vh; overflow-y: auto; padding: 0; + /* !important since Autocomplete hard-codes z-index into its HTML template */ + z-index: 10 !important; +} + +.autocomplete-result { + word-wrap: break-word; } .autocomplete-result:hover,
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_filter_items.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_filter_items.vue index a0294f2..b139646 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/graph_filter_items.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_filter_items.vue
@@ -5,28 +5,36 @@ <template> <div id="filter-items-container"> <div id="controls"> - <button @click="checkAll"> + <MdButton + class="md-primary md-raised md-dense" + @click="checkAll"> Check All - </button> - <button @click="uncheckAll"> + </MdButton> + <MdButton + class="md-primary md-raised md-dense" + @click="uncheckAll"> Uncheck All - </button> + </MdButton> </div> - <ul id="filter-list"> - <li + <MdList + id="filter-list" + class="md-scrollbar"> + <MdListItem v-for="node in filterList" :key="node.name"> - <div class="filter-list-item"> - <div @click="removeFromFilter(node.name)"> - x - </div> - <input - v-model="node.checked" - type="checkbox"> - <div>{{ shortenName(node.name) }}</div> + <MdButton + class="numeric-input-button md-icon-button md-dense" + @click="removeFromFilter(node.name)"> + <MdIcon>clear</MdIcon> + </MdButton> + <MdCheckbox + v-model="node.checked" + class="md-primary"/> + <div class="filter-items-text md-list-item-text"> + {{ shortenName(node.name) }} </div> - </li> - </ul> + </MdListItem> + </MdList> </div> </template> @@ -58,6 +66,13 @@ export default GraphFilterItems; </script> +<style> +#filter-list .md-list-item-content { + min-height: 0; + padding: 0; +} +</style> + <style scoped> ul { list-style-type: none; @@ -70,20 +85,21 @@ min-width: 100px; } +.filter-items-text{ + display: inline-block; + margin-left: 15px; + white-space: normal; + width: 100%; + word-wrap: break-word; +} + #filter-list { - margin: 0; - overflow-x: hidden; + max-height: 30vh; overflow-y: scroll; - padding: 0; } #controls { display: flex; flex-direction: row; } - -.filter-list-item { - display: flex; - flex-direction: row; -} </style>
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_selected_node_details.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_selected_node_details.vue index 9841914..bcb6b8b5 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/graph_selected_node_details.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_selected_node_details.vue
@@ -5,28 +5,39 @@ <template> <div class="selected-node-details"> <template v-if="selectedNode !== null"> - <ul> - <li>Name: {{ selectedNode.id }}</li> - <li>Display Name: {{ selectedNode.displayName }}</li> - <li - v-for="(value, key) in selectedNode.visualizationState" - :key="key"> - {{ key }}: {{ value }} - </li> - </ul> - <button + <MdList class="md-double-line"> + <MdListItem> + <div class="md-list-item-text"> + <span class="selected-node-details-text"> + {{ selectedNode.id }} + </span> + <span>Name</span> + </div> + </MdListItem> + <MdListItem> + <div class="md-list-item-text"> + <span class="selected-node-details-text"> + {{ selectedNode.displayName }} + </span> + <span>Display Name</span> + </div> + </MdListItem> + </MdList> + <MdButton v-if="selectedNode.visualizationState.selectedByFilter" + class="md-primary md-raised md-dense" @click="uncheckNodeInFilter"> Uncheck in filter - </button> - <button + </MdButton> + <MdButton v-else + class="md-primary md-raised md-dense" @click="checkNodeInFilter"> Add/check in filter - </button> + </MdButton> </template> <div v-else> - Click a node for more details. + (Click a node for more details.) </div> </div> </template> @@ -59,6 +70,12 @@ .selected-node-details { display: flex; flex-direction: column; - min-width: 400px; +} + +.selected-node-details-text{ + display: inline-block; + white-space: normal; + width: 100%; + word-wrap: break-word; } </style>
diff --git a/tools/android/dependency_analysis/js/src/vue_components/graph_visualization.vue b/tools/android/dependency_analysis/js/src/vue_components/graph_visualization.vue index d99ad7b0..52a485b 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/graph_visualization.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/graph_visualization.vue
@@ -5,8 +5,8 @@ <template> <svg id="graph-svg" - width="960" - height="600"/> + width="100%" + height="100%"/> </template> <script> @@ -72,9 +72,12 @@ </script> <style> +svg text { + font-family: Roboto; +} + .graph-hull-labels text { dominant-baseline: baseline; - font-family: sans-serif; font-size: 10px; font-weight: bold; text-anchor: middle; @@ -89,7 +92,6 @@ } .graph-labels text { - font-family: sans-serif; font-size: 12px; }
diff --git a/tools/android/dependency_analysis/js/src/vue_components/numeric_input.vue b/tools/android/dependency_analysis/js/src/vue_components/numeric_input.vue index 3845af9..b53309f 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/numeric_input.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/numeric_input.vue
@@ -4,20 +4,26 @@ <template> <div class="numeric-input-container"> - <label :for="inputId">{{ description }}</label> - <div class="input-and-button-container"> - <input + <MdField + class="input-field"> + <label :for="inputId">{{ description }}</label> + <MdInput :id="inputId" v-model="internalInputValue" - type="number"> - <div class="button-group"> - <button @click="internalInputValue++"> - + - </button> - <button @click="internalInputValue--"> - - - </button> - </div> + class="numeric-input-value" + type="number"/> + </MdField> + <div class="button-group"> + <MdButton + class="numeric-input-button md-icon-button md-dense" + @click="internalInputValue++"> + <MdIcon>expand_less</MdIcon> + </MdButton> + <MdButton + class="numeric-input-button md-icon-button md-dense" + @click="internalInputValue--"> + <MdIcon>expand_more</MdIcon> + </MdButton> </div> </div> </template> @@ -58,24 +64,27 @@ <style scoped> .numeric-input-container { display: flex; - flex-direction: column; - max-width: 150px; -} - -.input-and-button-container { - display: flex; flex-direction: row; } .button-group { + align-items: center; display: flex; flex-direction: column; } -input { +.numeric-input-button { + margin: 0; +} + +.numeric-input-value { width: 100%; } +.input-field { + width: 50%; +} + input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none;
diff --git a/tools/android/dependency_analysis/js/src/vue_components/package_details_panel.vue b/tools/android/dependency_analysis/js/src/vue_components/package_details_panel.vue index 4a6d113..456a9fe 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/package_details_panel.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/package_details_panel.vue
@@ -58,8 +58,9 @@ <style scoped> .package-details-panel { - max-height: 300px; - overflow: hidden; + max-height: 400px; + min-height: 200px; overflow-y: scroll; + overflow-x: hidden; } </style>
diff --git a/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue b/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue index 020904abc..048c049 100644 --- a/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue +++ b/tools/android/dependency_analysis/js/src/vue_components/package_graph_page.vue
@@ -4,31 +4,12 @@ <template> <div id="page-container"> - <div id="page-controls"> - <GraphFilterInput - :node-ids="pageModel.getNodeIds()" - :nodes-already-in-filter=" - displaySettingsData.nodeFilterData.filterList" - :shorten-name="filterShortenName" - @[CUSTOM_EVENTS.FILTER_SUBMITTED]="filterAddOrCheckNode"/> - <GraphFilterItems - :node-filter-data="displaySettingsData.nodeFilterData" - :shorten-name="filterShortenName" - @[CUSTOM_EVENTS.FILTER_REMOVE]="filterRemoveNode" - @[CUSTOM_EVENTS.FILTER_CHECK_ALL]="filterCheckAll" - @[CUSTOM_EVENTS.FILTER_UNCHECK_ALL]="filterUncheckAll"/> - <NumericInput - description="Change inbound (blue) depth:" - input-id="inbound-input" - :input-value.sync="displaySettingsData.inboundDepth" - :min-value="0"/> - <NumericInput - description="Change outbound (yellow) depth:" - input-id="outbound-input" - :input-value.sync="displaySettingsData.outboundDepth" - :min-value="0"/> - </div> - <div id="graph-and-node-details-container"> + <div id="title-and-graph-container"> + <div + id="title" + class="md-headline"> + Clank Dependency Viewer - Package Graph + </div> <GraphVisualization :graph-update-triggers="[ displaySettingsData, @@ -37,22 +18,58 @@ :display-settings-data="displaySettingsData" @[CUSTOM_EVENTS.NODE_CLICKED]="graphNodeClicked" @[CUSTOM_EVENTS.NODE_DOUBLE_CLICKED]="graphNodeDoubleClicked"/> - <div id="node-details-container"> - <GraphDisplayPanel - :display-settings-data="displaySettingsData" - :display-settings-preset.sync=" - displaySettingsData.displaySettingsPreset"> - <GraphDisplaySettings - :display-settings-data="displaySettingsData" - @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> - </GraphDisplayPanel> - <GraphSelectedNodeDetails - :selected-node-details-data="pageModel.selectedNodeDetailsData" - @[CUSTOM_EVENTS.DETAILS_CHECK_NODE]="filterAddOrCheckNode" - @[CUSTOM_EVENTS.DETAILS_UNCHECK_NODE]="filterUncheckNode"/> - <PackageDetailsPanel - :selected-package="pageModel.selectedNodeDetailsData.selectedNode"/> + </div> + <div + id="page-sidebar" + class="md-elevation-3"> + <MdSubheader class="sidebar-subheader"> + Node Filter + </MdSubheader> + <GraphFilterItems + id="graph-filter-items" + :node-filter-data="displaySettingsData.nodeFilterData" + :shorten-name="filterShortenName" + @[CUSTOM_EVENTS.FILTER_REMOVE]="filterRemoveNode" + @[CUSTOM_EVENTS.FILTER_CHECK_ALL]="filterCheckAll" + @[CUSTOM_EVENTS.FILTER_UNCHECK_ALL]="filterUncheckAll"/> + <GraphFilterInput + :node-ids="pageModel.getNodeIds()" + :nodes-already-in-filter=" + displaySettingsData.nodeFilterData.filterList" + :shorten-name="filterShortenName" + @[CUSTOM_EVENTS.FILTER_SUBMITTED]="filterAddOrCheckNode"/> + <MdSubheader class="sidebar-subheader"> + Display Options + </MdSubheader> + <div id="inbound-outbound-depth-inputs"> + <NumericInput + description="Inbound Depth" + input-id="inbound-input" + :input-value.sync="displaySettingsData.inboundDepth" + :min-value="0"/> + <NumericInput + description="Outbound Depth" + input-id="outbound-input" + :input-value.sync="displaySettingsData.outboundDepth" + :min-value="0"/> </div> + <GraphDisplayPanel + :display-settings-data="displaySettingsData" + :display-settings-preset.sync=" + displaySettingsData.displaySettingsPreset"> + <GraphDisplaySettings + :display-settings-data="displaySettingsData" + @[CUSTOM_EVENTS.DISPLAY_OPTION_CHANGED]="displayOptionChanged"/> + </GraphDisplayPanel> + <MdSubheader class="sidebar-subheader"> + Node Details + </MdSubheader> + <GraphSelectedNodeDetails + :selected-node-details-data="pageModel.selectedNodeDetailsData" + @[CUSTOM_EVENTS.DETAILS_CHECK_NODE]="filterAddOrCheckNode" + @[CUSTOM_EVENTS.DETAILS_UNCHECK_NODE]="filterUncheckNode"/> + <PackageDetailsPanel + :selected-package="pageModel.selectedNodeDetailsData.selectedNode"/> </div> </div> </template> @@ -221,9 +238,43 @@ </style> <style scoped> +#title { + padding: 10px; +} + #page-container { display: flex; + flex-direction: row; + height: 100vh; + width: 100vw; +} + +#title-and-graph-container { + display: flex; flex-direction: column; + flex-grow: 1; +} + +#page-sidebar { + display: flex; + flex-direction: column; + flex-grow: 0; + overflow-y: scroll; + padding: 0 20px; + width: 30vw; +} + +.sidebar-subheader { + padding: 0; +} + +#graph-filter-items { + margin-bottom: 10px; +} + +#inbound-outbound-depth-inputs { + display: flex; + flex-direction: row; } #page-controls { @@ -231,14 +282,4 @@ flex-direction: row; height: 15vh; } - -#graph-and-node-details-container { - display: flex; - flex-direction: row; -} - -#node-details-container { - display: flex; - flex-direction: column; -} </style>
diff --git a/tools/android/dependency_analysis/js/webpack.config.js b/tools/android/dependency_analysis/js/webpack.config.js index 20c9517..803ac5c 100644 --- a/tools/android/dependency_analysis/js/webpack.config.js +++ b/tools/android/dependency_analysis/js/webpack.config.js
@@ -59,7 +59,6 @@ }, { test: /\.css$/, - include: path.resolve(__dirname, 'src'), use: ['vue-style-loader', 'style-loader', 'css-loader'], }, ],
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index bff6a945..e761565 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -179,8 +179,8 @@ 'ToTWinCFI': 'clang_tot_win_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on_x86', 'ToTWinCFI64': 'clang_tot_win_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on', 'ToTWinThinLTO64': 'clang_tot_win_official_full_symbols_thin_lto_static', - 'ToTiOS': 'ios_clang_tot', - 'ToTiOSDevice': 'ios_clang_device_tot', + 'ToTiOS': 'ios_clang_tot_xctest', + 'ToTiOSDevice': 'ios_clang_device_tot_xctest', 'UBSanVptr Linux': 'ubsan_vptr_release_bot', }, @@ -278,13 +278,13 @@ 'ios13-sdk-simulator': 'ios_simulator_debug_static_rbe_bot_xctest', 'ios14-beta-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios14-sdk-simulator': 'ios_simulator_debug_static_rbe_bot_xctest', - 'ios-asan': 'ios_simulator_release_static_asan_bot', + 'ios-asan': 'ios_simulator_release_static_asan_bot_xctest', 'ios-simulator': 'ios_error', - 'ios-simulator-code-coverage': 'clang_code_coverage_ios', + 'ios-simulator-code-coverage': 'clang_code_coverage_ios_xctest', 'ios-simulator-cr-recipe': 'ios_simulator_debug_static_bot_xctest', - 'ios-simulator-cronet': 'ios_cronet', - 'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_multi_window', - 'ios-webkit-tot': 'ios_simulator_debug_static_rbe_bot', + 'ios-simulator-cronet': 'ios_cronet_xctest', + 'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_multi_window_xctest', + 'ios-webkit-tot': 'ios_simulator_debug_static_rbe_bot_xctest', 'linux-annotator-rel': 'release_bot', 'linux-blink-animation-use-time-delta': 'debug_bot_enable_blink_animation_use_time_delta', 'linux-blink-heap-concurrent-marking-tsan-rel': 'release_trybot_tsan', @@ -491,9 +491,9 @@ 'Mac Builder': 'gpu_tests_release_bot_minimal_symbols_no_nacl', 'Mac Builder (dbg)': 'gpu_tests_debug_bot', 'ios-device': 'ios_device_release_rbe_compile_only', - 'ios-simulator': 'ios_simulator_debug_static_rbe_bot', - 'ios-simulator-full-configs': 'ios_simulator_debug_static_bot', - 'ios-simulator-noncq': 'ios_simulator_debug_static_rbe_bot', + 'ios-simulator': 'ios_simulator_debug_static_rbe_bot_xctest', + 'ios-simulator-full-configs': 'ios_simulator_debug_static_bot_xctest', + 'ios-simulator-noncq': 'ios_simulator_debug_static_rbe_bot_xctest', 'mac-arm64-rel': 'mac_arm64_release_bot', }, @@ -949,12 +949,12 @@ 'ios13-sdk-simulator': 'ios_simulator_debug_static_rbe_bot_xctest', 'ios14-beta-simulator': 'ios_simulator_debug_static_rbe_bot_xctest', 'ios14-sdk-simulator': 'ios_simulator_debug_static_rbe_bot_xctest', - 'ios-simulator': 'ios_simulator_debug_static_rbe_bot', - 'ios-simulator-full-configs': 'ios_simulator_debug_static_bot', - 'ios-simulator-cronet': 'ios_cronet', - 'ios-simulator-code-coverage': 'clang_code_coverage_ios_partial_instrumentation', + 'ios-simulator': 'ios_simulator_debug_static_rbe_bot_xctest', + 'ios-simulator-full-configs': 'ios_simulator_debug_static_bot_xctest', + 'ios-simulator-cronet': 'ios_cronet_xctest', + 'ios-simulator-code-coverage': 'clang_code_coverage_ios_partial_instrumentation_xctest', 'ios-simulator-cr-recipe': 'ios_simulator_debug_static_bot_xctest', - 'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_multi_window', + 'ios-simulator-multi-window': 'ios_simulator_debug_static_bot_multi_window_xctest', 'mac-osxbeta-rel': 'gpu_tests_release_trybot_deterministic_mac', 'mac_chromium_10.10': 'gpu_tests_release_trybot_deterministic_mac', 'mac_chromium_10.12_rel_ng': 'gpu_tests_release_trybot_deterministic_mac', @@ -970,6 +970,7 @@ 'mac_upload_clang': 'release_bot', 'mac-coverage-rel': 'gpu_tests_release_trybot_deterministic_mac_code_coverage', 'mac-rel': 'gpu_tests_release_trybot_deterministic_mac', + 'mac-arm64-rel': 'mac_arm64_release_trybot', }, 'tryserver.chromium.perf': { @@ -1586,12 +1587,12 @@ 'release_bot', 'clang', 'use_clang_coverage', 'no_symbols', ], - 'clang_code_coverage_ios': [ - 'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_use_goma_rbe', + 'clang_code_coverage_ios_xctest': [ + 'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_use_goma_rbe', 'xctest', ], - 'clang_code_coverage_ios_partial_instrumentation': [ - 'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_use_goma_rbe', 'partial_code_coverage_instrumentation', + 'clang_code_coverage_ios_partial_instrumentation_xctest': [ + 'use_clang_coverage', 'debug_static_bot', 'x64', 'ios', 'ios_use_goma_rbe', 'partial_code_coverage_instrumentation', 'xctest', ], 'clang_tot_asan_lsan_static_release': [ @@ -1970,17 +1971,17 @@ # build files. 'ios_error': [ 'error'], - 'ios_clang_tot': [ - 'clang_tot', 'ios_simulator', 'ios_disable_code_signing', 'release', 'static', + 'ios_clang_tot_xctest': [ + 'clang_tot', 'ios_simulator', 'ios_disable_code_signing', 'release', 'static', 'xctest', ], - 'ios_clang_device_tot': [ - 'clang_tot', 'ios_device', 'release', 'ios_chromium_cert' + 'ios_clang_device_tot_xctest': [ + 'clang_tot', 'ios_device', 'release', 'ios_chromium_cert', 'xctest', ], - 'ios_cronet': [ + 'ios_cronet_xctest': [ 'additional_target_cpus_x86', 'cronet_ios', 'debug_static_bot', - 'ios_deployment_target_10_0', 'ios_simulator' + 'ios_deployment_target_10_0', 'ios_simulator', 'xctest', ], 'ios_device_release_compile_only': [ @@ -1996,28 +1997,20 @@ 'ios_device', 'ios_disable_code_signing', 'ios_use_goma_rbe', 'release_bot', 'xctest', ], - 'ios_simulator_debug_static_bot': [ - 'debug_static_bot', 'ios_simulator', - ], - 'ios_simulator_debug_static_bot_xctest': [ 'debug_static_bot', 'ios_simulator', 'xctest', ], - 'ios_simulator_debug_static_bot_multi_window': [ - 'debug_static_bot', 'ios_enable_multi_window', 'ios_simulator', - ], - - 'ios_simulator_debug_static_rbe_bot': [ - 'debug_static_bot', 'ios_simulator', 'ios_use_goma_rbe' + 'ios_simulator_debug_static_bot_multi_window_xctest': [ + 'debug_static_bot', 'ios_enable_multi_window', 'ios_simulator', 'xctest', ], 'ios_simulator_debug_static_rbe_bot_xctest': [ 'debug_static_bot', 'ios_simulator', 'ios_use_goma_rbe', 'xctest', ], - 'ios_simulator_release_static_asan_bot': [ - 'ios_simulator', 'release_bot', 'asan' + 'ios_simulator_release_static_asan_bot_xctest': [ + 'ios_simulator', 'release_bot', 'asan', 'xctest', ], 'libfuzzer_asan_debug_bot': [ @@ -2099,6 +2092,10 @@ 'release_bot', 'arm64', ], + 'mac_arm64_release_trybot': [ + 'release_trybot', 'arm64', + ], + 'msan_no_origins_release_bot': [ 'msan_no_origins', 'release_bot',
diff --git a/tools/metrics/BUILD.gn b/tools/metrics/BUILD.gn index c4dacb6..dac2416 100644 --- a/tools/metrics/BUILD.gn +++ b/tools/metrics/BUILD.gn
@@ -94,6 +94,7 @@ "//tools/metrics/histograms/expand_owners.py", "//tools/metrics/histograms/expand_owners_unittest.py", "//tools/metrics/histograms/extract_histograms.py", + "//tools/metrics/histograms/extract_histograms_test.py", "//tools/metrics/histograms/generate_expired_histograms_array.py", "//tools/metrics/histograms/generate_expired_histograms_array_unittest.py", "//tools/metrics/histograms/histogram_ownership.py",
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 2359223f..553e2e19b 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2401,6 +2401,7 @@ label="prefer_related_applications is only supported on Chrome Beta & Stable on Android"/> <int value="38" label="Manifest URL was changed during fetch"/> + <int value="39" label="Manifest display_override value not supported"/> </enum> <enum name="AppBannersInstallEvent"> @@ -37172,6 +37173,7 @@ <int value="0" label="Tab Share Button"/> <int value="1" label="QR Code Image"/> <int value="2" label="History Entry"/> + <int value="3" label="Reading List Entry"/> </enum> <enum name="IOSContentSizeCategory"> @@ -37286,6 +37288,8 @@ <int value="5" label="Remove"/> <int value="6" label="Edit"/> <int value="7" label="Share"/> + <int value="8" label="Open all in New Tabs"/> + <int value="9" label="Hide"/> </enum> <enum name="IOSMenuScenario"> @@ -37294,6 +37298,7 @@ <int value="2" label="ReadingList Entry"/> <int value="3" label="RecentTabs Entry"/> <int value="4" label="ContentSuggestions Entry"/> + <int value="5" label="RecentTabs Header"/> </enum> <enum name="IOSNTPImpression"> @@ -70249,6 +70254,13 @@ <int value="3" label="False to True"/> </enum> +<enum name="TrustedWebActivityQualityEnforcementViolationType"> + <int value="0" label="Error 404"/> + <int value="1" label="Error 5xx"/> + <int value="2" label="Page unavailable offline"/> + <int value="3" label="Digital assetlinks verification failure"/> +</enum> + <enum name="TunnelRedirectHistogramValue"> <obsolete> Removed in Chrome 76.
diff --git a/tools/metrics/histograms/extract_histograms_test.py b/tools/metrics/histograms/extract_histograms_test.py index e457669..72cd5135 100644 --- a/tools/metrics/histograms/extract_histograms_test.py +++ b/tools/metrics/histograms/extract_histograms_test.py
@@ -634,13 +634,11 @@ """) # Check that error is logged when empty string variant name is used # in token that is not the last token. - with self.assertLogs(level='ERROR') as log: - histograms_dict, _ = extract_histograms._ExtractHistogramsFromXmlTree( - histogram_with_duplicate_variant, {}) - histograms_dict, have_errors = extract_histograms._UpdateHistogramsWithTokens( - histograms_dict) - self.assertTrue(have_errors) - self.assertIn('Duplicate histogram name', log.output[0]) + histograms_dict, _ = extract_histograms._ExtractHistogramsFromXmlTree( + histogram_with_duplicate_variant, {}) + _, have_errors = extract_histograms._UpdateHistogramsWithTokens( + histograms_dict) + self.assertTrue(have_errors) if __name__ == "__main__":
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 6cae367..4e3551c3 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -1512,7 +1512,7 @@ </histogram> <histogram name="Ads.Media.LoadType" enum="MediaLoadType" - expires_after="2020-11-22"> + expires_after="2021-02-07"> <owner>johnidel@chromium.org</owner> <owner>jkarlin@chromium.org</owner> <summary> @@ -6686,7 +6686,7 @@ </histogram> <histogram name="Apps.AppList.DriveQuickAccessProvider.CacheEmpty" - enum="BooleanEmpty" expires_after="2020-12-06"> + enum="BooleanEmpty" expires_after="2021-02-07"> <owner>tby@chromium.org</owner> <owner>wrong@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -6698,7 +6698,7 @@ </histogram> <histogram name="Apps.AppList.DriveQuickAccessProvider.DriveFSMounted" - enum="Boolean" expires_after="2020-12-06"> + enum="Boolean" expires_after="2021-02-07"> <owner>tby@chromium.org</owner> <owner>wrong@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -6709,7 +6709,7 @@ </histogram> <histogram name="Apps.AppList.DriveQuickAccessProvider.FileError" - enum="DriveFileError" expires_after="2020-12-06"> + enum="DriveFileError" expires_after="2021-02-07"> <owner>tby@chromium.org</owner> <owner>wrong@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -6809,7 +6809,7 @@ </histogram> <histogram name="Apps.AppList.OsSettingsProvider.QueryTime" units="ms" - expires_after="2020-12-01"> + expires_after="2021-02-07"> <owner>jiameng@chromium.org</owner> <owner>tby@chromium.org</owner> <summary> @@ -6962,7 +6962,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateFileProvider.Latency" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -6973,7 +6973,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateFileProvider.NotifierCreationSuccess" - enum="BooleanSuccess" expires_after="2020-12-06"> + enum="BooleanSuccess" expires_after="2021-02-07"> <owner>tby@chromium.org</owner> <owner>edimitriadis@chromium.org</owner> <summary> @@ -6983,7 +6983,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateResults.LaunchedItemType" - enum="ZeroStateResultType" expires_after="2020-12-06"> + enum="ZeroStateResultType" expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -6993,7 +6993,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateResults.ReceivedScore.DriveQuickAccess" - units="score" expires_after="2020-12-06"> + units="score" expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -7005,7 +7005,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateResults.ReceivedScore.OmniboxSearch" - units="score" expires_after="2020-12-06"> + units="score" expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -7029,7 +7029,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateResultsList.Clicked" - enum="BooleanClicked" expires_after="2020-12-06"> + enum="BooleanClicked" expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -7041,7 +7041,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateResultsList.ContainsDriveFiles" - enum="Boolean" expires_after="2020-12-06"> + enum="Boolean" expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -7052,7 +7052,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateResultsList.FileImpressions" - enum="AppListSearchResult" expires_after="2020-12-06"> + enum="AppListSearchResult" expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -7078,7 +7078,7 @@ </histogram> <histogram name="Apps.AppList.ZeroStateResultsList.LaunchedItemPositionV2" - units="position" expires_after="2020-12-06"> + units="position" expires_after="2021-02-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>jiameng@chromium.org</owner> @@ -7184,7 +7184,7 @@ </histogram> <histogram name="Apps.AppListAppLaunchedV2" enum="AppListLaunchedFrom" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <!-- Name completed by histogram_suffixes name="AppListState" --> <owner>mmourgos@chromium.org</owner> @@ -7683,7 +7683,7 @@ </histogram> <histogram name="Apps.AppListSuggestedChipOpenType" enum="AppListSearchResult" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <!-- Name completed by histogram_suffixes name="TabletOrClamshellMode" --> <owner>newcomer@chromium.org</owner> @@ -8412,13 +8412,13 @@ </summary> </histogram> -<histogram name="Arc.AndroidBootTime" units="ms" expires_after="2020-12-06"> +<histogram name="Arc.AndroidBootTime" units="ms" expires_after="2021-02-07"> <owner>elijahtaylor@google.com</owner> <owner>shihuis@google.com</owner> <summary>The time elapsed for booting up the ARC instance.</summary> </histogram> -<histogram name="Arc.AppCount" units="units" expires_after="2020-12-06"> +<histogram name="Arc.AppCount" units="units" expires_after="2021-02-07"> <owner>elijahtaylor@google.com</owner> <owner>shihuis@google.com</owner> <summary> @@ -8698,7 +8698,7 @@ </histogram> <histogram name="Arc.EngagementTime.ArcTotal" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>maajid@google.com</owner> <owner>shaochuan@google.com</owner> <owner>shihuis@google.com</owner> @@ -8735,7 +8735,7 @@ </histogram> <histogram name="Arc.EngagementTime.Total" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>maajid@google.com</owner> <owner>shaochuan@google.com</owner> <owner>shihuis@google.com</owner> @@ -8852,7 +8852,7 @@ </summary> </histogram> -<histogram name="Arc.ImeCount" units="units" expires_after="2020-12-06"> +<histogram name="Arc.ImeCount" units="units" expires_after="2021-02-07"> <owner>yhanada@chromium.org</owner> <owner>tetsui@chromium.org</owner> <summary> @@ -8948,7 +8948,7 @@ </histogram> <histogram name="Arc.OOMKills.Score" units="badness score" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>elijahtaylor@google.com</owner> <owner>shihuis@google.com</owner> <summary> @@ -9202,7 +9202,7 @@ </histogram> <histogram name="Arc.Reauthorization.Result" enum="ArcProvisioningResult" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <!-- Name completed by histogram_suffixes name="ArcUserTypes" --> <owner>khmel@google.com</owner> @@ -9408,7 +9408,7 @@ </histogram> <histogram name="Arc.UserInteraction" enum="ArcUserInteraction" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>jhorwich@chromium.org</owner> <owner>elijahtaylor@chromium.org</owner> <owner>shihuis@google.com</owner> @@ -9741,7 +9741,7 @@ </histogram> <histogram name="Ash.Desks.DesksSwitch" enum="DesksSwitchSource" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <owner>tclaiborne@chromium.org</owner> <summary> @@ -9777,7 +9777,7 @@ </histogram> <histogram name="Ash.Desks.NewDesk2" enum="DesksCreationRemovalSource" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <owner>tclaiborne@chromium.org</owner> <summary> @@ -9788,7 +9788,7 @@ </histogram> <histogram name="Ash.Desks.NumberOfWindowsOnDesk_1" units="units" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <owner>tclaiborne@chromium.org</owner> <summary> @@ -9798,7 +9798,7 @@ </histogram> <histogram name="Ash.Desks.NumberOfWindowsOnDesk_2" units="units" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <owner>tclaiborne@chromium.org</owner> <summary> @@ -9808,7 +9808,7 @@ </histogram> <histogram name="Ash.Desks.NumberOfWindowsOnDesk_3" units="units" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <owner>tclaiborne@chromium.org</owner> <summary> @@ -9818,7 +9818,7 @@ </histogram> <histogram name="Ash.Desks.NumberOfWindowsOnDesk_4" units="units" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <owner>tclaiborne@chromium.org</owner> <summary> @@ -10327,7 +10327,7 @@ </histogram> <histogram name="Ash.NightLight.ScheduleType" enum="AshNightLightScheduleType" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <summary> The selected Night Light schedule type. Emitted when the user changes the @@ -10336,7 +10336,7 @@ </histogram> <histogram name="Ash.NightLight.Temperature" - enum="AshNightLightTemperatureRanges" expires_after="2020-12-06"> + enum="AshNightLightTemperatureRanges" expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <summary> The ranges in which the selected values of the Night Light color temperature @@ -10589,7 +10589,7 @@ </histogram> <histogram name="Ash.Shelf.NumberOfPinnedItems" units="Icons" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>anasalazar@google.com</owner> <owner>mmourgos@google.com</owner> <summary> @@ -11126,7 +11126,7 @@ </histogram> <histogram name="Ash.TouchView.TouchViewActive" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>girard@chromium.org</owner> <summary> The length of time that TouchView is active, for each activation. @@ -11678,7 +11678,7 @@ </histogram> <histogram name="Assistant.ButtonClickCount" enum="AssistantButtonId" - expires_after="2020-10-25"> + expires_after="2021-02-07"> <owner>xiaohuic@chromium.org</owner> <owner>meilinw@chromium.org</owner> <summary> @@ -11723,7 +11723,7 @@ </histogram> <histogram name="Assistant.EntryPoint" enum="AssistantEntryPoint" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>xiaohuic@chromium.org</owner> <owner>meilinw@chromium.org</owner> <summary> @@ -12234,7 +12234,7 @@ </histogram> <histogram name="Assistant.QueryResponseType" enum="AssistantQueryResponseType" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>xiaohuic@chromium.org</owner> <owner>meilinw@chromium.org</owner> <summary>The Assistant query response type.</summary> @@ -17493,7 +17493,7 @@ <histogram name="BackForwardCache.AllSites.HistoryNavigationOutcome.BrowsingInstanceNotSwappedReason" enum="BackForwardCacheBrowsingInstanceNotSwappedReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> <summary> @@ -17531,7 +17531,7 @@ <histogram name="BackForwardCache.AllSites.HistoryNavigationOutcome.NotRestoredReason" - enum="BackForwardCacheNotRestoredReason" expires_after="2020-12-06"> + enum="BackForwardCacheNotRestoredReason" expires_after="2021-02-07"> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> <summary> @@ -17547,7 +17547,7 @@ <histogram name="BackForwardCache.EvictedAfterDocumentRestoredReason" enum="BackForwardCacheEvictedAfterDocumentRestoredReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> <summary> @@ -17587,7 +17587,7 @@ </histogram> <histogram name="BackForwardCache.HistoryNavigationOutcome.BlocklistedFeature" - enum="WebSchedulerTrackedFeature" expires_after="2020-12-06"> + enum="WebSchedulerTrackedFeature" expires_after="2021-02-07"> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> <summary> @@ -17605,7 +17605,7 @@ <histogram name="BackForwardCache.HistoryNavigationOutcome.BrowsingInstanceNotSwappedReason" enum="BackForwardCacheBrowsingInstanceNotSwappedReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> <summary> @@ -17622,7 +17622,7 @@ <histogram name="BackForwardCache.HistoryNavigationOutcome.DisabledForRenderFrameHostReason" enum="BackForwardCacheDisabledForRenderFrameHostReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>carlscab@chromium.org</owner> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> @@ -17644,7 +17644,7 @@ </histogram> <histogram name="BackForwardCache.HistoryNavigationOutcome.NotRestoredReason" - enum="BackForwardCacheNotRestoredReason" expires_after="2020-12-06"> + enum="BackForwardCacheNotRestoredReason" expires_after="2021-02-07"> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> <summary> @@ -19605,7 +19605,7 @@ </histogram> <histogram name="Blink.DecodedImageType" enum="DecodedImageType" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>urvang@chromium.org</owner> <summary>Image codec inferred during decode.</summary> </histogram> @@ -20058,7 +20058,7 @@ </histogram> <histogram base="true" name="Blink.ImageDecoders.InitiallyFullyDecodedByteSize" - units="bytes" expires_after="2020-12-06"> + units="bytes" expires_after="2021-02-07"> <owner>mbarowsky@chromium.org</owner> <owner>andrescj@chromium.org</owner> <summary> @@ -20089,7 +20089,7 @@ </histogram> <histogram name="Blink.ImageDecoders.Jpeg.ColorSpace" enum="JpegColorSpace" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>andrescj@chromium.org</owner> <owner>mcasas@chromium.org</owner> <summary> @@ -23196,7 +23196,7 @@ </histogram> <histogram name="BlueZ.ResultOfPairing" enum="BlueZResultOfPairing" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>mcchou@chromium.org</owner> <summary> This is specific to Chrome OS. Records the outcomes of pairing with remote @@ -23594,7 +23594,7 @@ </histogram> <histogram name="BrotliFilter.CompressionPercent" units="%" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>eustas@chromium.org</owner> <summary>Compressed/Decompressed size ratio.</summary> </histogram> @@ -23939,7 +23939,7 @@ </histogram> <histogram name="Browser.Tabs.SelectionToVisibilityRequestTime" - units="microseconds" expires_after="2020-12-06"> + units="microseconds" expires_after="2021-02-07"> <owner>sadrul@chromium.org</owner> <owner>sky@chromium.org</owner> <summary> @@ -24133,7 +24133,7 @@ </histogram> <histogram name="BrowserRenderProcessHost.FramePrioritiesSeen" - enum="FramePrioritiesSeen" expires_after="2020-12-06"> + enum="FramePrioritiesSeen" expires_after="2021-02-07"> <owner>ericrobinson@chromium.org</owner> <owner>csharrison@chromium.org</owner> <summary> @@ -24464,7 +24464,7 @@ </histogram> <histogram name="BrowserSwitcher.LaunchTime" units="ms" - expires_after="2020-11-15"> + expires_after="2021-02-07"> <owner>nicolaso@chromium.org</owner> <owner>pastarmovj@chromium.org</owner> <summary> @@ -25554,7 +25554,7 @@ </histogram> <histogram name="ChildProcess.Crashed.UtilityProcessHash" - enum="UtilityProcessNameHash" expires_after="2020-12-06"> + enum="UtilityProcessNameHash" expires_after="2021-02-07"> <owner>wfh@chromium.org</owner> <owner>chrome-stability-core@google.com</owner> <summary> @@ -26340,7 +26340,7 @@ </histogram> <histogram name="ChromeOS.Apps.IntentPickerAction" - enum="ArcIntentHandlerAction" expires_after="2020-12-06"> + enum="ArcIntentHandlerAction" expires_after="2021-02-07"> <owner>elijahtaylor@google.com</owner> <owner>dominickn@chromium.org</owner> <owner>shihuis@google.com</owner> @@ -26749,7 +26749,7 @@ </histogram> <histogram name="ChromeOS.MemoryPressureLevel" enum="MemoryPressureLevel" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>xdai@chromium.org</owner> <summary> The memory pressure level in Chrome OS, which is recorded periodically (once @@ -26848,7 +26848,7 @@ </histogram> <histogram name="ChromeOS.SAML.Provider" enum="ChromeOSSamlProvider" - expires_after="2020-12-02"> + expires_after="2021-02-07"> <owner>mslus@chromium.org</owner> <owner>mohammedabdon@chromium.org</owner> <summary>Records SAML provider when SAML login flow is used.</summary> @@ -27216,7 +27216,7 @@ </histogram> <histogram name="ChromeOS.SystemTray.FeaturePodCountOnOpen" units="count" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>tengs@chromium.org</owner> <owner>amehfooz@chromium.org</owner> <summary> @@ -27347,7 +27347,7 @@ </histogram> <histogram base="true" name="ChromeOS.USB.DeviceAttached" - enum="ChromeOSUsbEventTiming" expires_after="2020-12-06"> + enum="ChromeOSUsbEventTiming" expires_after="2021-02-07"> <owner>allenwebb@chromium.org</owner> <owner>jorgelo@chromium.org</owner> <owner>mnissler@chromium.org</owner> @@ -28441,7 +28441,7 @@ </histogram> <histogram name="Compositing.DirectRenderer.GL.DrawFrameUs" - units="microseconds" expires_after="2020-12-06"> + units="microseconds" expires_after="2021-02-07"> <owner>weiliangc@chromium.org</owner> <summary> Time spent drawing of composited layers by GLRenderer, in microseconds. This @@ -28456,7 +28456,7 @@ </histogram> <histogram name="Compositing.DirectRenderer.PartialSwap.ExtraDamage" units="%" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>vasilyt@chromium.org</owner> <owner>backer@chromium.org</owner> <summary> @@ -28471,7 +28471,7 @@ </histogram> <histogram name="Compositing.DirectRenderer.PartialSwap.FrameBufferDamage" - units="%" expires_after="2020-10-04"> + units="%" expires_after="2021-02-07"> <owner>vasilyt@chromium.org</owner> <owner>backer@chromium.org</owner> <summary> @@ -30663,7 +30663,7 @@ </histogram> <histogram name="ContentSettings.Popups.StrongBlockerActions" - enum="StrongPopupBlockerAction" expires_after="2020-12-06"> + enum="StrongPopupBlockerAction" expires_after="2021-02-07"> <owner>csharrison@chromium.org</owner> <summary> Counts of various events related to the strong popup blocker (aka abusive @@ -32206,7 +32206,7 @@ </histogram> <histogram name="Cookie.CommitProblem" enum="CookieCommitProblem" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>morlovich@chromium.org</owner> <summary> Recorded when a problem occurs trying to commit changes to the cookie store @@ -32461,7 +32461,7 @@ </histogram> <histogram name="Cookie.LoadProblem" enum="CookieLoadProblem" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>morlovich@chromium.org</owner> <summary> Recorded when a problem is recorded when loading the persistent cookie @@ -32943,7 +32943,7 @@ </summary> </histogram> -<histogram name="Cookie.Type" enum="CookieType" expires_after="2020-12-06"> +<histogram name="Cookie.Type" enum="CookieType" expires_after="2021-02-07"> <owner>mkwst@chromium.org</owner> <summary>For each cookie added to the store, record it's type(s).</summary> </histogram> @@ -33053,7 +33053,7 @@ </histogram> <histogram name="Cras.HfpBatteryIndicatorSupported" - enum="CrasHfpBatteryIndicator" expires_after="2020-12-01"> + enum="CrasHfpBatteryIndicator" expires_after="2021-02-07"> <owner>enshuo@chromium.org</owner> <owner>chromeos-audio@google.com</owner> <summary> @@ -33538,7 +33538,7 @@ </histogram> <histogram name="Cras.OutputDeviceHeadphoneRuntime" units="seconds" - expires_after="2020-12-01"> + expires_after="2021-02-07"> <owner>yuhsuan@chromium.org</owner> <owner>chromeos-audio@google.com</owner> <summary> @@ -36084,7 +36084,7 @@ </histogram> <histogram name="Cryptohome.HomedirEncryptionType" enum="HomedirEncryptionType" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>dspaid@chromium.org</owner> <summary> The encryption type used for a user's cryptohome directory. This is logged @@ -36248,7 +36248,7 @@ </histogram> <histogram name="Cryptohome.TimeSessionUnlock" units="ms" - expires_after="2020-12-01"> + expires_after="2021-02-07"> <owner>kerrnel@chromium.org</owner> <owner>mnissler@chromium.org</owner> <summary> @@ -36401,7 +36401,7 @@ </histogram> <histogram name="Cryptohome.TpmResults" enum="CryptohomeTpmResults" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>afakhry@chromium.org</owner> <summary> The errors resulting from interacting with the Trusted Platform Module (TPM) @@ -46038,7 +46038,7 @@ </histogram> <histogram name="Download.IOSDownloadFileUI" enum="DownloadFileUI" - expires_after="2020-11-29"> + expires_after="2021-02-07"> <owner>ewannpv@chromium.org</owner> <owner>eugenebut@chromium.org</owner> <summary> @@ -47813,7 +47813,7 @@ </histogram> <histogram name="DrmUtil.CreateDisplaySnapshot.EdidBlobIsEmpty" enum="Boolean" - expires_after="2020-10-11"> + expires_after="2021-02-07"> <owner>andrescj@chromium.org</owner> <owner>mcasas@chromium.org</owner> <owner>chromeos-gfx@google.com</owner> @@ -48557,7 +48557,7 @@ </histogram> <histogram name="Enterprise.ActiveDirectoryJoin" - enum="ActiveDirectoryDomainJoinType" expires_after="2020-10-30"> + enum="ActiveDirectoryDomainJoinType" expires_after="2021-02-07"> <owner>fsandrade@chromium.org</owner> <owner>tomdobro@chromium.org</owner> <summary> @@ -49581,7 +49581,7 @@ <histogram name="Enterprise.MachineLevelUserCloudPolicyEnrollment.UnenrollSuccess" - enum="BooleanSuccess" expires_after="2020-10-01"> + enum="BooleanSuccess" expires_after="2021-02-07"> <owner>domfc@chromium.org</owner> <owner>zmin@chromium.org</owner> <summary> @@ -53394,7 +53394,7 @@ </histogram> <histogram name="Event.Latency.ScrollUpdate.Touch.TimeToHandled2" - units="microseconds" expires_after="2020-12-06"> + units="microseconds" expires_after="2021-02-07"> <owner>tdresser@chromium.org</owner> <summary> Time between initial creation of a touch event and the generated @@ -63765,7 +63765,7 @@ </histogram> <histogram name="GCM.RegistrationRequest.NetErrorCode" enum="NetErrorCodes" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>peter@chromium.org</owner> <owner>platform-capabilities@chromium.org</owner> <summary> @@ -66221,7 +66221,7 @@ </histogram> <histogram name="GPU.IOSurface.CreateTime" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>ccameron@chromium.org</owner> <summary> The time that it took for a call to IOSurfaceCreate to complete. @@ -66371,7 +66371,7 @@ </histogram> <histogram name="GPU.OopRaster.GlyphCacheMiss" - enum="OopRasterGlyphCacheMissType" expires_after="2020-12-06"> + enum="OopRasterGlyphCacheMissType" expires_after="2021-02-07"> <owner>khushalsagar@chromium.org</owner> <summary> During OutOfProcess(Oop) raster, the renderer generates and sends the @@ -67272,7 +67272,7 @@ </histogram> <histogram name="Graphics.Smoothness.FrameSequenceLength" units="count" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>sadrul@chromium.org</owner> <owner>graphics-dev@chromium.org</owner> <summary> @@ -69407,7 +69407,7 @@ </histogram> <histogram name="HttpCache.Pattern" enum="HttpCachePattern" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>morlovich@chromium.org</owner> <owner>jkarlin@chromium.org</owner> <summary>For each http cache transaction, the recorded pattern.</summary> @@ -73554,7 +73554,7 @@ </histogram> <histogram name="IOS.PageLoadCount.Counts" - enum="IOSPageLoadCountNavigationType" expires_after="2020-12-06"> + enum="IOSPageLoadCountNavigationType" expires_after="2021-02-07"> <owner>danyao@chromium.org</owner> <summary>The number of navigation started events by navigation type.</summary> </histogram> @@ -74477,7 +74477,7 @@ </histogram> <histogram name="Keyboard.ShortcutViewer.StartupTime" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>jamescook@chromium.org</owner> <owner>msw@chromium.org</owner> <owner>wutao@chromium.org</owner> @@ -75532,7 +75532,7 @@ </histogram> <histogram name="LoadingPredictor.PreconnectCount" units="origins" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>alexilin@chromium.org</owner> <summary> The number of origins that were preconnected for a page load. It includes @@ -75542,7 +75542,7 @@ </histogram> <histogram name="LoadingPredictor.PreconnectHitsPercentage" units="%" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>alexilin@chromium.org</owner> <summary> The percentage of origins that were preconnected and requested by a page @@ -75553,7 +75553,7 @@ </histogram> <histogram base="true" name="LoadingPredictor.PreconnectLearningCount" - units="origins" expires_after="2020-12-06"> + units="origins" expires_after="2021-02-07"> <owner>alexilin@chromium.org</owner> <owner>tbansal@chromium.org</owner> <summary> @@ -75563,7 +75563,7 @@ </histogram> <histogram base="true" name="LoadingPredictor.PreconnectLearningPrecision" - units="%" expires_after="2020-12-06"> + units="%" expires_after="2021-02-07"> <owner>alexilin@chromium.org</owner> <owner>tbansal@chromium.org</owner> <summary> @@ -75598,7 +75598,7 @@ </histogram> <histogram name="LoadingPredictor.PreresolveCount" units="hosts" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>alexilin@chromium.org</owner> <summary> The number of hosts that were preresolved for a page load. It includes only @@ -76121,7 +76121,7 @@ </histogram> <histogram name="Login.FailureReason" enum="LoginFailureReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>achuith@chromium.org</owner> <summary>Chrome OS login failure reason.</summary> </histogram> @@ -76161,7 +76161,7 @@ </histogram> <histogram name="Login.OfflineFailure.IsKnownUser" enum="LoginIsKnownUser" - expires_after="2020-11-01"> + expires_after="2021-02-07"> <owner>glevin@chromium.org</owner> <summary> On offline login failure, records whether it is for an existing user. @@ -76329,7 +76329,7 @@ </histogram> <histogram name="Login.UserType" enum="LoginUserType" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>cmasone@chromium.org</owner> <summary> Chrome OS histogram that keeps track of the way a user logs in and whether @@ -89863,7 +89863,7 @@ </histogram> <histogram name="MPArch.ChildProcessLaunchSubsequent" units="units" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>ppi@chromium.org</owner> <summary> The time it takes to spawn child sub processes not counting the first one. @@ -113272,7 +113272,7 @@ </histogram> <histogram name="NQE.EffectiveConnectionType.OnECTComputation" - enum="NQEEffectiveConnectionType" expires_after="2020-12-06"> + enum="NQEEffectiveConnectionType" expires_after="2021-02-07"> <owner>tbansal@chromium.org</owner> <owner>src/net/nqe/OWNERS</owner> <summary> @@ -113656,7 +113656,7 @@ </histogram> <histogram name="NQE.RTT.ObservationSource" enum="NQEObservationSource" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>tbansal@chromium.org</owner> <owner>bengr@chromium.org</owner> <summary> @@ -117042,7 +117042,7 @@ </summary> </histogram> -<histogram name="Omnibox.PasteAndGo" units="count" expires_after="2020-12-06"> +<histogram name="Omnibox.PasteAndGo" units="count" expires_after="2021-02-07"> <owner>mpearson@chromium.org</owner> <owner>jdonnelly@chromium.org</owner> <summary> @@ -118051,7 +118051,7 @@ </histogram> <histogram name="OOBE.ErrorScreensTime.Update" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>raleksandrov@google.com</owner> <owner>cros-oac@google.com</owner> <summary>Time spent on error screens during update.</summary> @@ -118261,7 +118261,7 @@ </histogram> <histogram name="OOBE.StepCompletionTimeByExitReason" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>raleksandrov@google.com</owner> <owner>cros-oac@google.com</owner> <summary>Time spent on specific OOBE screen grouped by exit reason.</summary> @@ -118280,7 +118280,7 @@ </histogram> <histogram name="OOBE.SyncConsentScreen.ReviewFollowingSetup" - enum="BooleanChecked" expires_after="2020-12-06"> + enum="BooleanChecked" expires_after="2021-02-07"> <owner>raleksandrov@google.com</owner> <owner>cros-oac@google.com</owner> <summary> @@ -128642,7 +128642,7 @@ </histogram> <histogram name="PasswordProtection.ModalWarningDialogAction" - enum="PasswordProtectionWarningAction" expires_after="2020-11-29"> + enum="PasswordProtectionWarningAction" expires_after="2021-02-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -129349,7 +129349,7 @@ </summary> </histogram> -<histogram name="PDF.HasAttachment" enum="Boolean" expires_after="2020-12-06"> +<histogram name="PDF.HasAttachment" enum="Boolean" expires_after="2021-02-07"> <owner>hnakashima@chromium.org</owner> <owner>thestig@chromium.org</owner> <summary> @@ -135283,7 +135283,7 @@ </histogram> <histogram name="Power.BatteryRemainingAtStartOfSessionOnAC" units="%" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>tbroch@chromium.org</owner> <summary> Chrome OS remaining battery charge as percent of the maximum battery charge, @@ -135801,7 +135801,7 @@ </summary> </histogram> -<histogram name="Power.IdleTimeOnBattery" units="ms" expires_after="2020-12-06"> +<histogram name="Power.IdleTimeOnBattery" units="ms" expires_after="2021-02-07"> <owner>tbroch@chromium.org</owner> <owner>jiameng@chromium.org</owner> <summary> @@ -135811,7 +135811,7 @@ </histogram> <histogram name="Power.KernelResumeTimeOnAC" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>tbroch@chromium.org</owner> <summary> The time that the kernel took to resume the Chrome OS device from @@ -135856,7 +135856,7 @@ </histogram> <histogram name="Power.LengthOfSession" units="seconds" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>tbroch@chromium.org</owner> <summary> The length of time, in seconds, that a user spent in a single session. @@ -136097,7 +136097,7 @@ </histogram> <histogram name="Power.PowerSupplyType" enum="PowerSupplyType" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>bleung@chromium.org</owner> <owner>tbroch@chromium.org</owner> <summary> @@ -136353,7 +136353,7 @@ </histogram> <histogram name="PowerML.SmartDimModel.Result" - enum="PowerMLSmartDimModelResult" expires_after="2020-12-06"> + enum="PowerMLSmartDimModelResult" expires_after="2021-02-07"> <owner>jiameng@chromium.org</owner> <summary> This is the status code returned by the model when calculating a user @@ -141081,7 +141081,7 @@ </histogram> <histogram name="ProtoDB.InitStatus" enum="LevelDBStatus" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>nyquist@chromium.org</owner> <owner>ssid@chromium.org</owner> <summary>The LevelDB Status from a ProtoDatabase Init call.</summary> @@ -141141,7 +141141,7 @@ </histogram> <histogram name="ProximityAuth.BleWeaveConnectionResult" - enum="ProximityAuth_BleWeaveConnectionResult" expires_after="2020-12-06"> + enum="ProximityAuth_BleWeaveConnectionResult" expires_after="2021-02-07"> <owner>hansberry@chromium.org</owner> <summary> Provides a breakdown of how often each BLE weave connection result occurs. @@ -141150,7 +141150,7 @@ <histogram name="ProximityAuth.BluetoothGattConnectionResult" enum="ProximityAuth_BluetoothGattConnectionResult" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>hansberry@chromium.org</owner> <summary> Provides a breakdown of how many times each possible Bluetooth GATT @@ -141335,7 +141335,7 @@ </histogram> <histogram name="PushMessaging.DeliveryStatus" enum="PushEventStatus" - expires_after="2020-10-25"> + expires_after="2021-02-07"> <owner>peter@chromium.org</owner> <summary> When a Service Worker receives a push message, this records whether the @@ -148457,7 +148457,7 @@ </histogram> <histogram name="SafeBrowsing.RT.Backoff.State" enum="BooleanEnabled" - expires_after="2020-12-05"> + expires_after="2021-02-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -151321,7 +151321,7 @@ </histogram> <histogram name="SBClientDownload.CheckDownloadStats" - enum="SBClientDownloadCheckDownloadStats" expires_after="2020-12-06"> + enum="SBClientDownloadCheckDownloadStats" expires_after="2021-02-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <owner>mattm@chromium.org</owner> @@ -151454,7 +151454,7 @@ </histogram> <histogram name="SBClientDownload.DownloadExtensions" - enum="SBClientDownloadExtensions" expires_after="2020-12-06"> + enum="SBClientDownloadExtensions" expires_after="2021-02-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <owner>mattm@chromium.org</owner> @@ -174430,7 +174430,7 @@ </histogram> <histogram name="Sync.DataTypeRunFailures2" enum="SyncModelTypes" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>jkrcal@chromium.org</owner> <owner>mastiz@chromium.org</owner> <summary> @@ -174456,7 +174456,7 @@ </histogram> <histogram name="Sync.DataTypeStartFailures2" enum="SyncModelTypes" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>jkrcal@chromium.org</owner> <owner>mastiz@chromium.org</owner> <summary> @@ -175428,7 +175428,7 @@ </histogram> <histogram base="true" name="Sync.ModelTypeCount4" units="entries" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>jkrcal@chromium.org</owner> <owner>mastiz@chromium.org</owner> <summary> @@ -175471,7 +175471,7 @@ </histogram> <histogram base="true" name="Sync.ModelTypeEntityChange3" - enum="SyncEntityChange" expires_after="2020-12-06"> + enum="SyncEntityChange" expires_after="2021-02-07"> <owner>jkrcal@chromium.org</owner> <summary> Recorded once for every sync entity change (whenever it is commited to the @@ -175695,7 +175695,7 @@ </histogram> <histogram name="Sync.NonReflectionUpdateFreshnessPossiblySkewed2" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>mastiz@chromium.org</owner> <owner>melandory@chromium.org</owner> <summary> @@ -181954,7 +181954,7 @@ </histogram> <histogram name="Tracing.Background.ScenarioState" - enum="BackgroundTracingState" expires_after="2020-12-06"> + enum="BackgroundTracingState" expires_after="2021-02-07"> <owner>oysteine@chromium.org</owner> <summary> Records state of the Background Tracing system, from when scenarios are @@ -182305,7 +182305,7 @@ </histogram> <histogram name="Translate.HrefHint.Status" enum="HrefTranslateStatus" - expires_after="2020-12-01"> + expires_after="2021-02-07"> <owner>megjablon@google.com</owner> <owner>chrome-language@google.com</owner> <summary> @@ -182925,6 +182925,17 @@ </summary> </histogram> +<histogram name="TrustedWebActivity.QualityEnforcementViolation" + enum="TrustedWebActivityQualityEnforcementViolationType" + expires_after="2020-12-31"> + <owner>eirage@chromium.org</owner> + <owner>peconn@chromium.org</owner> + <summary> + When Trusted Web Activity launches or navigates to a site that violate the + quality criteria, records the violation type. + </summary> +</histogram> + <histogram name="TrustedWebActivity.ShareTargetRequest" enum="WebShareTargetMethod" expires_after="M88"> <owner>peconn@chromium.org</owner> @@ -183112,7 +183123,7 @@ </histogram> <histogram name="UKM.Entries.Dropped" enum="UkmDataDroppedReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> @@ -183122,7 +183133,7 @@ </histogram> <histogram name="UKM.Entries.Dropped.ByEntryHash" enum="UkmEventNameHash" - expires_after="2020-10-04"> + expires_after="2021-02-07"> <owner>jwd@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> @@ -183156,7 +183167,7 @@ </histogram> <histogram name="UKM.Entries.SerializedCount2" units="entries" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary>Number of serialized UKM entries when storing a UKM log.</summary> @@ -183186,7 +183197,7 @@ </summary> </histogram> -<histogram name="UKM.LogSize.OnSuccess" units="KB" expires_after="2020-12-06"> +<histogram name="UKM.LogSize.OnSuccess" units="KB" expires_after="2021-02-07"> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> @@ -183257,7 +183268,7 @@ </histogram> <histogram name="UKM.Sources.Dropped" enum="UkmDataDroppedReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> @@ -183267,7 +183278,7 @@ </histogram> <histogram name="UKM.Sources.KeptSourcesCount" units="sources" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> @@ -183304,7 +183315,7 @@ </histogram> <histogram name="UKM.Sources.UnsentSourcesCount" units="sources" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> @@ -183352,7 +183363,7 @@ </histogram> <histogram name="UKM.UnsentLogs.NumDropped" units="units" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>rkaplow@chromium.org</owner> <owner>ukm-team@google.com</owner> <summary> @@ -184848,7 +184859,7 @@ </histogram> <histogram name="V8.CompileLazyMicroSeconds" units="microseconds" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>hablich@chromium.org</owner> <summary> Aggregated time spent compiling functions lazily during a single script @@ -185580,7 +185591,7 @@ </histogram> <histogram name="V8.LiftoffBailoutReasons" enum="LiftoffBailoutReason" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>ecmziegler@chromium.org</owner> <owner>adamk@chromium.org</owner> <owner>clemensb@chromium.org</owner> @@ -188476,7 +188487,7 @@ </histogram> <histogram name="WebApk.Install.InstallEvent" enum="WebApkInstallEvent" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>hartmanng@chromium.org</owner> <owner> src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS @@ -188777,7 +188788,7 @@ </histogram> <histogram name="WebApk.Startup.Cold.ShellLaunchToSplashscreenVisible" - units="ms" expires_after="2020-10-18"> + units="ms" expires_after="2021-02-07"> <owner>mheikal@chromium.org</owner> <owner>yfriedman@chromium.org</owner> <summary> @@ -189990,7 +190001,7 @@ </histogram> <histogram name="WebCore.FindInPage.TaskDuration" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>rakina@chromium.org</owner> <owner>altimin@chromium.org</owner> <summary> @@ -190313,7 +190324,7 @@ </histogram> <histogram name="WebCore.IndexedDB.LevelDB.OpenTime" units="ms" - expires_after="2020-10-25"> + expires_after="2021-02-07"> <owner>cmumford@chromium.org</owner> <summary> The time that it takes to open IndexedDB's LevelDB backing store. @@ -191457,7 +191468,7 @@ </histogram> <histogram name="WebCore.WebSocket.SendType" enum="WebSocketSendType" - expires_after="2020-09-27"> + expires_after="2021-02-07"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> <summary> @@ -191482,7 +191493,7 @@ </histogram> <histogram name="WebFont.BlankTextShownTime" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>kenjibaheux@chromium.org</owner> <owner>ksakamoto@chromium.org</owner> <summary> @@ -192224,7 +192235,7 @@ </histogram> <histogram name="WebRTC.Audio.ApmCaptureInputLevelAverageRms" - units="dBFS (negated)" expires_after="2020-12-06"> + units="dBFS (negated)" expires_after="2021-02-07"> <owner>hlundin@chromium.org</owner> <summary> This histogram reports the average RMS of the signal coming in to WebRTC's @@ -192236,7 +192247,7 @@ </histogram> <histogram name="WebRTC.Audio.ApmCaptureInputLevelPeakRms" - units="dBFS (negated)" expires_after="2020-12-06"> + units="dBFS (negated)" expires_after="2021-02-07"> <owner>hlundin@chromium.org</owner> <summary> This histogram reports the peak RMS of the signal coming in to WebRTC's @@ -192248,7 +192259,7 @@ </histogram> <histogram name="WebRTC.Audio.ApmCaptureOutputLevelAverageRms" - units="dBFS (negated)" expires_after="2020-12-06"> + units="dBFS (negated)" expires_after="2021-02-07"> <owner>peah@chromium.org</owner> <summary> This histogram reports the average RMS of the signal in the output of @@ -192363,7 +192374,7 @@ </histogram> <histogram name="WebRTC.Audio.AverageExcessBufferDelayMs" units="ms" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>hlundin@chromium.org</owner> <summary> Measures the average waiting time in the buffer for each packet. The waiting @@ -192981,14 +192992,14 @@ </histogram> <histogram name="WebRTC.BWE.InitiallyLostPackets" units="packets" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>holmer@chromium.org</owner> <summary> The number of video packets lost durig the first 2 seconds in a WebRTC call. </summary> </histogram> -<histogram name="WebRTC.BWE.InitialRtt" units="ms" expires_after="2020-12-06"> +<histogram name="WebRTC.BWE.InitialRtt" units="ms" expires_after="2021-02-07"> <owner>holmer@chromium.org</owner> <summary> The round-trip time as measured 2 seconds into a WebRTC call. @@ -193141,7 +193152,7 @@ </histogram> <histogram name="WebRTC.Call.EstimatedSendBitrateInKbps" units="kbps" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>holmer@chromium.org</owner> <summary> Average estimated send bitrate during a call, counted from first packet sent @@ -193970,7 +193981,7 @@ </histogram> <histogram name="WebRTC.UserMediaRequest.Result2" - enum="MediaStreamRequestResult2" expires_after="2020-12-06"> + enum="MediaStreamRequestResult2" expires_after="2021-02-07"> <owner>grunell@chromium.org</owner> <summary> Counters for UserMediaRequests results such as failure reasons. The standard @@ -194069,7 +194080,7 @@ </histogram> <histogram name="WebRTC.Video.BitrateSentInKbps" units="kbps" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>asapersson@chromium.org</owner> <summary> The number of sent bits per second for a sent video stream. Recorded when a @@ -194092,7 +194103,7 @@ </histogram> <histogram name="WebRTC.Video.CpuLimitedResolutionInPercent" units="%" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>asapersson@chromium.org</owner> <summary> Percentage of frames that are limited in resolution due to CPU for a sent @@ -194586,7 +194597,7 @@ </histogram> <histogram name="WebRTC.Video.PliPacketsSentPerMinute" units="packets/minute" - expires_after="2020-10-11"> + expires_after="2021-02-07"> <owner>asapersson@chromium.org</owner> <summary> The number of sent RTCP PLI packets per minute for a received video stream. @@ -194606,7 +194617,7 @@ </histogram> <histogram name="WebRTC.Video.QualityLimitedResolutionInPercent" units="%" - expires_after="2020-11-01"> + expires_after="2021-02-07"> <owner>asapersson@chromium.org</owner> <summary> Percentage of sent frames that are downscaled in resolution due to quality @@ -194669,7 +194680,7 @@ </histogram> <histogram name="WebRTC.Video.RenderFramesPerSecond" units="fps" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>asapersson@chromium.org</owner> <summary> The number of sent frames to the renderer per second for a received video @@ -195311,7 +195322,7 @@ </histogram> <histogram name="WebRTC.Video.SentPacketsLostInPercent" units="%" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>asapersson@chromium.org</owner> <summary> Percentage of sent packets lost for a sent video stream. Recorded when a @@ -195807,7 +195818,7 @@ </histogram> <histogram name="WebUI.CreatedForUrl" enum="WebUIUrlHashes" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>dbeam@chromium.org</owner> <summary>URLs for which Chrome creates WebUIControllers.</summary> </histogram> @@ -196874,7 +196885,7 @@ </histogram> <histogram name="WrenchMenu.MenuAction" enum="WrenchMenuAction" - expires_after="2020-12-06"> + expires_after="2021-02-07"> <owner>ainslie@chromium.org</owner> <owner>edwardjung@chromium.org</owner> <summary>Number of times that each menu item is clicked.</summary> @@ -211334,10 +211345,6 @@ label="Only counting memory used by GL command buffers."/> <suffix name="Discardable" label="Only counting memory used by Discardable manager."/> - <suffix name="Discardable.FreelistSize" - label="Freelist size used by ClientDiscardableMemoryManager."/> - <suffix name="Discardable.VirtualSize" - label="Virtual memory used by ClientDiscardableMemoryManager."/> <suffix name="ExtensionFunctions" label="Only counting memory used by ExtensionFunctions."/> <suffix name="Extensions.ValueStore" @@ -211457,6 +211464,10 @@ </histogram_suffixes> <histogram_suffixes name="ProcessMemoryAllocatorSmall2" separator="."> + <suffix name="Discardable.FreelistSize" + label="Freelist size used by ClientDiscardableMemoryManager."/> + <suffix name="Discardable.VirtualSize" + label="Virtual memory used by ClientDiscardableMemoryManager."/> <suffix name="DownloadService" label="Only counting memory used by Download service."/> <suffix name="FontCaches" label="Only counting memory used by font caches."/>
diff --git a/tools/metrics/histograms/merge_xml_test.py b/tools/metrics/histograms/merge_xml_test.py index 3dd0fb6..6ca5c8f 100644 --- a/tools/metrics/histograms/merge_xml_test.py +++ b/tools/metrics/histograms/merge_xml_test.py
@@ -84,8 +84,8 @@ """Checks that the UkmEventNameHash enum is populated correctly. If ukm.xml is provided, populate a list of ints to the UkmEventNameHash enum - where where each value is a xml event name hash truncated to 31 bits and - each label is the corresponding event name. + where each value is a truncated hash of the event name and each label is the + corresponding event name, with obsolete label when applicable. """ merged = merge_xml.PrettyPrintMergedFiles(histogram_paths.ALL_TEST_XMLS) expected_merged_xml = """ @@ -109,9 +109,11 @@ This gets populated by the GetEnumsNodes function in merge_xml.py when producing the merged XML file. </summary> - <int value="324605288" label="AbusiveExperienceHeuristic.WindowOpen"/> - <int value="1621538456" label="AbusiveExperienceHeuristic.TabUnder"/> - <int value="1913876024" label="Autofill.SelectedMaskedServerCard (Obsolete)"/> + <int value="151676257" label="AbusiveExperienceHeuristic.TestEvent1"/> + <int value="898353372" + label="AbusiveExperienceHeuristic.TestEvent2 (Obsolete)"/> + <int value="1052089961" label="Autofill.TestEvent3"/> + <int value="1758741469" label="FullyObsolete.TestEvent4 (Obsolete)"/> </enum> </enums>
diff --git a/tools/metrics/histograms/populate_enums.py b/tools/metrics/histograms/populate_enums.py index 8be71a2..1fbc60c 100644 --- a/tools/metrics/histograms/populate_enums.py +++ b/tools/metrics/histograms/populate_enums.py
@@ -22,18 +22,32 @@ """Returns a simple struct containing the event details. Args: - event: An event. + event: An event description as defined in ukm.xml. Returns: - A struct containing the event name, name hash, and whether the event is - obsolete. + A struct containing the event name, truncated hash, and whether the event is + considered obsolete. """ name = event.getAttribute('name') # The value is UKM event name hash truncated to 31 bits. This is recorded in - # https://cs.chromium.org/chromium/src/components/ukm/ukm_recorder_impl.cc?rcl=728ad079d8e52ada4e321fb4f53713e4f0588072&l=114 + # https://cs.chromium.org/chromium/src/components/ukm/ukm_recorder_impl.cc?q=LogEventHashasUmaHistogram hash = codegen.HashName(name) & 0x7fffffff - is_obsolete = event.getElementsByTagName('obsolete') - return EventDetails(name=name, hash=hash, is_obsolete=is_obsolete) + + def _HasDirectObsoleteTag(node): + return any( + isinstance(child, xml.dom.minidom.Element) + and child.tagName == 'obsolete' for child in node.childNodes) + + # The UKM event is considered obsolete if the event itself is marked as + # obsolete with a tag or all of its metrics are marked as obsolete. + is_event_obsolete = _HasDirectObsoleteTag(event) + are_all_metrics_obsolete = all( + _HasDirectObsoleteTag(metric) + for metric in event.getElementsByTagName('metric')) + + return EventDetails(name=name, + hash=hash, + is_obsolete=is_event_obsolete or are_all_metrics_obsolete) def PopulateEnumWithUkmEvents(doc, enum, ukm_events):
diff --git a/tools/metrics/histograms/test_data/ukm.xml b/tools/metrics/histograms/test_data/ukm.xml index e5b9dc6..fd17a10 100644 --- a/tools/metrics/histograms/test_data/ukm.xml +++ b/tools/metrics/histograms/test_data/ukm.xml
@@ -1,44 +1,66 @@ <ukm-configuration> -<event name="AbusiveExperienceHeuristic.TabUnder"> - <owner>csharrison@chromium.org</owner> - <metric name="DidTabUnder"> +<event name="AbusiveExperienceHeuristic.TestEvent1"> + <owner>owner1@chromium.org</owner> + <metric name="Metric"> <summary> - True if the page attempted a tab-under navigation. + A summary of AbusiveExperienceHeuristic.TestEvent1 </summary> </metric> </event> -<event name="AbusiveExperienceHeuristic.WindowOpen"> - <owner>yaoxia@chromium.org</owner> - <summary> - Recorded whenever window.open() is called when AdTagging is enabled. - </summary> - <metric name="FromAdScript"> - <summary> - True if the page called window.open() with an ad script in the stack. - </summary> - </metric> - <metric name="FromAdSubframe"> - <summary> - True if the page called window.open() from an ad subframe. - </summary> - </metric> -</event> - -<event name="Autofill.SelectedMaskedServerCard"> +<event name="AbusiveExperienceHeuristic.TestEvent2"> + <owner>owner3@chromium.org</owner> <obsolete> Deprecated 2/2019 </obsolete> - <owner>jiahuiguo@google.com</owner> - <metric name="MillisecondsSinceFormParsed"> + <metric name="Metric"> <summary> - Obsolete. - - Time since form parse. + A summary of the metric. </summary> </metric> </event> +<event name="Autofill.TestEvent3"> + <owner>owner3@chromium.org</owner> + <summary> + A summary of Autofill.TestEvent3. + </summary> + <metric name="MetricVersion1"> + <summary> + MetricVersion1 summary. + </summary> + <obsolete> + Deprecated and replaced by MetricVersion2. + </obsolete> + </metric> + <metric name="MetricVersion2"> + <summary> + MetricVersion2 summary. + </summary> + </metric> +</event> + +<event name="FullyObsolete.TestEvent4"> + <owner>owner4@chromium.org</owner> + <summary> + All metrics of this event are marked as obsolete. + </summary> + <metric name="MetricVersion1"> + <summary> + MetricVersion1 summary. + </summary> + <obsolete> + Deprecated and replaced by MetricVersion2. + </obsolete> + </metric> + <metric name="MetricVersion2"> + <summary> + MetricVersion2 summary. + </summary> + <obsolete/> + </metric> +</event> + </ukm-configuration>
diff --git a/tools/metrics/metrics_python_tests.py b/tools/metrics/metrics_python_tests.py index 38fd9ab..a51946ec 100755 --- a/tools/metrics/metrics_python_tests.py +++ b/tools/metrics/metrics_python_tests.py
@@ -11,29 +11,32 @@ TYP_DIR = os.path.join(SRC_DIR, 'third_party', 'catapult', 'third_party', 'typ') if not TYP_DIR in sys.path: - sys.path.insert(0, TYP_DIR) + sys.path.insert(0, TYP_DIR) import typ def resolve(*paths): - return [os.path.join(THIS_DIR, *(p.split('/'))) for p in paths] + return [os.path.join(THIS_DIR, *(p.split('/'))) for p in paths] -sys.exit(typ.main(tests=resolve( - 'actions/extract_actions_test.py', - 'histograms/generate_expired_histograms_array_unittest.py', - 'histograms/pretty_print_test.py', - 'rappor/rappor_model_test.py', - 'ukm/codegen_test.py', - 'ukm/gen_builders_test.py', - 'ukm/ukm_model_test.py', - 'ukm/xml_validations_test.py', - '../json_comment_eater/json_comment_eater_test.py', - '../json_to_struct/element_generator_test.py', - '../json_to_struct/struct_generator_test.py', - '../variations/fieldtrial_to_struct_unittest.py', - '../variations/fieldtrial_util_unittest.py', - '../variations/split_variations_cmd_unittest.py', - '../../components/variations/service/' - 'generate_ui_string_overrider_unittest.py', - ))) + +sys.exit( + typ.main(tests=resolve( + 'actions/extract_actions_test.py', + 'histograms/extract_histograms_test.py', + 'histograms/generate_expired_histograms_array_unittest.py', + 'histograms/pretty_print_test.py', + 'rappor/rappor_model_test.py', + 'ukm/codegen_test.py', + 'ukm/gen_builders_test.py', + 'ukm/ukm_model_test.py', + 'ukm/xml_validations_test.py', + '../json_comment_eater/json_comment_eater_test.py', + '../json_to_struct/element_generator_test.py', + '../json_to_struct/struct_generator_test.py', + '../variations/fieldtrial_to_struct_unittest.py', + '../variations/fieldtrial_util_unittest.py', + '../variations/split_variations_cmd_unittest.py', + '../../components/variations/service/' + 'generate_ui_string_overrider_unittest.py', + )))
diff --git a/tools/perf/contrib/download_mobile/OWNERS b/tools/perf/contrib/download_mobile/OWNERS new file mode 100644 index 0000000..a07b0b4 --- /dev/null +++ b/tools/perf/contrib/download_mobile/OWNERS
@@ -0,0 +1,3 @@ +skyostil@chromium.org +eseckler@chromium.org +khokhlov@google.com
diff --git a/tools/perf/contrib/download_mobile/__init__.py b/tools/perf/contrib/download_mobile/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tools/perf/contrib/download_mobile/__init__.py
diff --git a/tools/perf/contrib/download_mobile/download_mobile.py b/tools/perf/contrib/download_mobile/download_mobile.py new file mode 100644 index 0000000..1f48e05 --- /dev/null +++ b/tools/perf/contrib/download_mobile/download_mobile.py
@@ -0,0 +1,64 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import time + +from core import perf_benchmark +from core import platforms + +from telemetry import benchmark +from telemetry import page as page_module +from telemetry import story +from telemetry.web_perf import timeline_based_measurement + + +class _Download4M(page_module.Page): + def RunPageInteractions(self, action_runner): + action_runner.ClickElement(text='4M') + time.sleep(100) + + +class _Download10x400K(page_module.Page): + def RunPageInteractions(self, action_runner): + for _ in range(10): + action_runner.ClickElement(text='400K') + time.sleep(10) + + +@benchmark.Info(emails=['chrometto-team@google.com']) +class DownloadMobile(perf_benchmark.PerfBenchmark): + """A benchmark to measure the power effect of downloading one big vs + several small files. + + Note that it always uses the live storage.googleapis.com site, even if the + --use-live-sites option is not set. + """ + + SUPPORTED_PLATFORM_TAGS = [platforms.ANDROID] + + def CreateStorySet(self, options): + ps = story.StorySet() + page_url = 'file://' + os.path.join(os.path.dirname(__file__), 'page.html') + ps.AddStory(_Download4M(page_url, ps, name='download_4M')) + ps.AddStory(_Download10x400K(page_url, ps, name='download_10x400K')) + return ps + + def CreateCoreTimelineBasedMeasurementOptions(self): + options = timeline_based_measurement.Options() + options.config.enable_experimental_system_tracing = True + options.config.system_trace_config.EnablePower() + options.SetTimelineBasedMetrics(['tbmv3:power_rails_metric']) + return options + + def SetExtraBrowserOptions(self, options): + # Note that this overwrites the --proxy-bypass-list argument + # set in chrome_startup_args.py. + options.AppendExtraBrowserArgs([ + '--proxy-bypass-list=<-loopback>;storage.googleapis.com', + ]) + + @classmethod + def Name(cls): + return 'download.mobile'
diff --git a/tools/perf/contrib/download_mobile/page.html b/tools/perf/contrib/download_mobile/page.html new file mode 100644 index 0000000..c42ba18 --- /dev/null +++ b/tools/perf/contrib/download_mobile/page.html
@@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> + <body> + <button + type="submit" + onclick="window.open('https://storage.googleapis.com/chromium-telemetry/download.mobile/4M.jpg?' + Math.random())" + >4M</button> + <button + type="submit" + onclick="window.open('https://storage.googleapis.com/chromium-telemetry/download.mobile/400K.jpg?' + Math.random())" + >400K</button> + </body> +</html>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index bf182823c..c7b280c 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -2,15 +2,15 @@ "trace_processor_shell": { "win": { "hash": "9632b44419444a74efa0e5241589bf4235e4853b", - "remote_path": "perfetto_binaries/trace_processor_shell/win/01e0ccdc9b8b4697a343b8ef49f53fd489d79a41/trace_processor_shell.exe" + "remote_path": "perfetto_binaries/trace_processor_shell/win/21e5b4554a5fc356b475064da679f83b27e1bbed/trace_processor_shell.exe" }, "mac": { - "hash": "dea286533132e8fa15bf99e552c736559a9144ff", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/01e0ccdc9b8b4697a343b8ef49f53fd489d79a41/trace_processor_shell" + "hash": "a18e8850873ecb7443534a60c74277d2d06bd1e6", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/0376edf14e5896af79fc71552f9579cbbd12f381/trace_processor_shell" }, "linux": { "hash": "283e0325abb12d3cea2c5a23acbdc39cfc6dd13f", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/01e0ccdc9b8b4697a343b8ef49f53fd489d79a41/trace_processor_shell" + "remote_path": "perfetto_binaries/trace_processor_shell/linux/21e5b4554a5fc356b475064da679f83b27e1bbed/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/accessibility/ax_node_position.cc b/ui/accessibility/ax_node_position.cc index ef23c50..a61526d1 100644 --- a/ui/accessibility/ax_node_position.cc +++ b/ui/accessibility/ax_node_position.cc
@@ -261,6 +261,19 @@ return text_length; } +bool AXNodePosition::IsEmbeddedObjectInParent() const { + switch (g_ax_embedded_object_behavior) { + case AXEmbeddedObjectBehavior::kSuppressCharacter: + return false; + case AXEmbeddedObjectBehavior::kExposeCharacter: + // We don't need to expose an "embedded object character" for textual + // nodes and nodes that are invisible to platform APIs. Textual nodes are + // represented by their actual text. + return !IsNullPosition() && !GetAnchor()->IsText() && + GetAnchor()->IsChildOfLeaf(); + } +} + bool AXNodePosition::IsInLineBreakingObject() const { if (IsNullPosition()) return false;
diff --git a/ui/accessibility/ax_node_position.h b/ui/accessibility/ax_node_position.h index 838bdd9..025b2125 100644 --- a/ui/accessibility/ax_node_position.h +++ b/ui/accessibility/ax_node_position.h
@@ -56,6 +56,7 @@ AXNode::AXID GetAnchorID(AXNode* node) const override; AXTreeID GetTreeID(AXNode* node) const override; + bool IsEmbeddedObjectInParent() const override; bool IsInLineBreakingObject() const override; ax::mojom::Role GetRole() const override; AXNodeTextStyles GetTextStyles() const override;
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h index 8e48079..c76e3fb8 100644 --- a/ui/accessibility/ax_position.h +++ b/ui/accessibility/ax_position.h
@@ -3360,7 +3360,7 @@ // Returns whether or not this anchor is represented in their parent with a // single embedded object character. - virtual bool IsEmbeddedObjectInParent() const { return false; } + virtual bool IsEmbeddedObjectInParent() const = 0; // Determines if the anchor containing this position produces a hard line // break in the text representation, e.g. a block level element or a <br>.
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 741cd354..4dbcc4d2 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -34,6 +34,10 @@ "gpu/wayland_buffer_manager_gpu.h", "gpu/wayland_canvas_surface.cc", "gpu/wayland_canvas_surface.h", + "gpu/wayland_overlay_candidates.cc", + "gpu/wayland_overlay_candidates.h", + "gpu/wayland_overlay_manager.cc", + "gpu/wayland_overlay_manager.h", "gpu/wayland_surface_factory.cc", "gpu/wayland_surface_factory.h", "gpu/wayland_surface_gpu.h", @@ -173,7 +177,7 @@ "//ui/ozone/common", "//ui/ozone/public/mojom/wayland:wayland_mojom", "//ui/platform_window", - "//ui/platform_window/platform_window_handler", + "//ui/platform_window/handlers", ] if (is_linux && !is_chromeos) { @@ -313,6 +317,7 @@ testonly = true sources = [ + "gpu/wayland_overlay_manager_unittest.cc", "host/wayland_connection_unittest.cc", "host/wayland_data_device_unittest.cc", "host/wayland_data_drag_controller_unittest.cc", @@ -347,7 +352,7 @@ "//ui/gfx/linux:test_support", "//ui/ozone:platform", "//ui/ozone:test_support", - "//ui/platform_window/platform_window_handler", + "//ui/platform_window/handlers", ] import("//ui/base/ui_features.gni")
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc index d450530..8ee69e5b 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc +++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -247,6 +247,8 @@ } buffer_manager_->CommitOverlays(widget_, std::move(overlay_configs)); + submitted_frame->unacked_submissions = submitted_frame->planes.size(); + submitted_frame->unacked_presentations = submitted_frame->planes.size(); submitted_frame->planes.clear(); submitted_frames_.push_back(std::move(submitted_frame)); } @@ -274,12 +276,13 @@ // submitted_frames_ may temporarily have more than one buffer in it if // buffers are released out of order by the Wayland server. DCHECK(!submitted_frames_.empty()); + if (--submitted_frames_.front()->unacked_submissions) + return; auto submitted_frame = std::move(submitted_frames_.front()); submitted_frames_.erase(submitted_frames_.begin()); submitted_frame->overlays.clear(); - DCHECK_EQ(submitted_frame->buffer_id, buffer_id); std::move(submitted_frame->completion_callback) .Run(gfx::SwapCompletionResult(swap_result)); @@ -296,10 +299,35 @@ void GbmSurfacelessWayland::OnPresentation( uint32_t buffer_id, const gfx::PresentationFeedback& feedback) { - DCHECK(!pending_presentation_frames_.empty()); + // Items in |submitted_frames_| will not be moved to + // |pending_presentation_frames_| until |unacked_submissions| decrements to 0. + // Example: + // A SwapBuffers that submitted 2 buffers (buffer_1 and buffer_2) will push + // a submitted_frame expecting 2 submission feedbacks and 2 presentation + // feedbacks. + // If IPCs comes in the order of: + // buffer_1:submission > buffer_2:submission > buffer_1:presentation > + // buffer_2:presentation + // We are fine without below logic. However, this can happen: + // buffer_1:submission > buffer_1:presentation > buffer_2:submission > + // buffer_2:presentation + // In this case, we have to find the item in |submitted_frames_| and + // decrement |unacked_presentations| there. + // TODO(fangzhoug): This solution is sub-optimal and confusing. It increases + // the number of IPCs from browser to gpu. The barrier logic should be in the + // browser process. + if (pending_presentation_frames_.empty()) { + auto it = submitted_frames_.begin(); + for (; !(*it)->unacked_presentations; ++it) + ; + --(*it)->unacked_presentations; + return; + } auto* frame = pending_presentation_frames_.front().get(); - DCHECK_EQ(frame->buffer_id, buffer_id); + if (--frame->unacked_presentations) + return; + std::move(frame->presentation_callback).Run(feedback); pending_presentation_frames_.erase(pending_presentation_frames_.begin()); }
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h index cfc5377..13dbd84 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h +++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -101,6 +101,12 @@ bool schedule_planes_succeeded = false; std::vector<PlaneData> planes; + + // TODO(fangzhoug): This is a temporary solution to barrier swap/present + // acks of a frame that contains multiple buffer commits. Next step is to + // barrier in browser process to avoid extra IPC hops. + size_t unacked_submissions; + size_t unacked_presentations; }; void MaybeSubmitFrames();
diff --git a/ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.cc b/ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.cc new file mode 100644 index 0000000..1163133 --- /dev/null +++ b/ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.cc
@@ -0,0 +1,24 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.h" + +#include "ui/ozone/platform/wayland/gpu/wayland_overlay_manager.h" +#include "ui/ozone/public/overlay_surface_candidate.h" + +namespace ui { + +WaylandOverlayCandidates::WaylandOverlayCandidates( + WaylandOverlayManager* manager, + gfx::AcceleratedWidget widget) + : overlay_manager_(manager), widget_(widget) {} + +WaylandOverlayCandidates::~WaylandOverlayCandidates() = default; + +void WaylandOverlayCandidates::CheckOverlaySupport( + std::vector<OverlaySurfaceCandidate>* candidates) { + overlay_manager_->CheckOverlaySupport(candidates, widget_); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.h b/ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.h new file mode 100644 index 0000000..37a66b63 --- /dev/null +++ b/ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.h
@@ -0,0 +1,39 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_OVERLAY_CANDIDATES_H_ +#define UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_OVERLAY_CANDIDATES_H_ + +#include <vector> + +#include "base/macros.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/ozone/public/overlay_candidates_ozone.h" + +namespace ui { +class WaylandOverlayManager; +class OverlaySurfaceCandidate; + +// OverlayCandidatesOzone implementation that delegates overlay decision to +// WaylandOverlayManager. +class WaylandOverlayCandidates : public OverlayCandidatesOzone { + public: + WaylandOverlayCandidates(WaylandOverlayManager* manager, + gfx::AcceleratedWidget widget); + WaylandOverlayCandidates(const WaylandOverlayCandidates&) = delete; + WaylandOverlayCandidates& operator=(const WaylandOverlayCandidates&) = delete; + ~WaylandOverlayCandidates() override; + + // OverlayCandidatesOzone: + void CheckOverlaySupport( + std::vector<OverlaySurfaceCandidate>* candidates) override; + + private: + WaylandOverlayManager* const overlay_manager_; // Not owned. + const gfx::AcceleratedWidget widget_; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_OVERLAY_CANDIDATES_H_
diff --git a/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc b/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc new file mode 100644 index 0000000..089ca8b --- /dev/null +++ b/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.cc
@@ -0,0 +1,56 @@ +// 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 "ui/ozone/platform/wayland/gpu/wayland_overlay_manager.h" + +#include "ui/gfx/geometry/rect_conversions.h" +#include "ui/ozone/platform/wayland/gpu/wayland_overlay_candidates.h" +#include "ui/ozone/public/overlay_surface_candidate.h" + +namespace ui { + +WaylandOverlayManager::WaylandOverlayManager() = default; +WaylandOverlayManager::~WaylandOverlayManager() = default; + +std::unique_ptr<OverlayCandidatesOzone> +WaylandOverlayManager::CreateOverlayCandidates(gfx::AcceleratedWidget widget) { + return std::make_unique<WaylandOverlayCandidates>(this, widget); +} + +void WaylandOverlayManager::CheckOverlaySupport( + std::vector<OverlaySurfaceCandidate>* candidates, + gfx::AcceleratedWidget widget) { + for (auto& candidate : *candidates) { + bool can_handle = CanHandleCandidate(candidate, widget); + + // CanHandleCandidate() should never return false if the candidate is + // the primary plane. + DCHECK(can_handle || candidate.plane_z_order != 0); + + candidate.overlay_handled = can_handle; + } +} + +bool WaylandOverlayManager::CanHandleCandidate( + const OverlaySurfaceCandidate& candidate, + gfx::AcceleratedWidget widget) const { + if (candidate.buffer_size.IsEmpty()) + return false; + + if (candidate.transform == gfx::OVERLAY_TRANSFORM_INVALID) + return false; + + // Reject candidates that don't fall on a pixel boundary. + if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f)) + return false; + + if (candidate.is_clipped && !candidate.clip_rect.Contains( + gfx::ToNearestRect(candidate.display_rect))) { + return false; + } + + return true; +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.h b/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.h new file mode 100644 index 0000000..5de78b30 --- /dev/null +++ b/ui/ozone/platform/wayland/gpu/wayland_overlay_manager.h
@@ -0,0 +1,44 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_OVERLAY_MANAGER_H_ +#define UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_OVERLAY_MANAGER_H_ + +#include "base/macros.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/ozone/public/overlay_candidates_ozone.h" +#include "ui/ozone/public/overlay_manager_ozone.h" + +namespace ui { +class OverlaySurfaceCandidate; + +// Ozone Wayland extension of the OverlayManagerOzone interface. It verifies the +// minimum validity of overlay candidates. Candidates' buffers are forwarded to +// Wayland server as Wayland subsurfaces. Actual HW overlay promotion happens +// later in Wayland Server. +class WaylandOverlayManager : public OverlayManagerOzone { + public: + WaylandOverlayManager(); + WaylandOverlayManager(const WaylandOverlayManager&) = delete; + WaylandOverlayManager& operator=(const WaylandOverlayManager&) = delete; + ~WaylandOverlayManager() override; + + // OverlayManagerOzone: + std::unique_ptr<OverlayCandidatesOzone> CreateOverlayCandidates( + gfx::AcceleratedWidget w) override; + + // Checks if overlay candidates can be displayed as overlays. Modifies + // |candidates| to indicate if they can. + void CheckOverlaySupport(std::vector<OverlaySurfaceCandidate>* candidates, + gfx::AcceleratedWidget widget); + + protected: + // Perform basic validation to see if |candidate| is a valid request. + bool CanHandleCandidate(const OverlaySurfaceCandidate& candidate, + gfx::AcceleratedWidget widget) const; +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_GPU_WAYLAND_OVERLAY_MANAGER_H_
diff --git a/ui/ozone/platform/wayland/gpu/wayland_overlay_manager_unittest.cc b/ui/ozone/platform/wayland/gpu/wayland_overlay_manager_unittest.cc new file mode 100644 index 0000000..18c605d --- /dev/null +++ b/ui/ozone/platform/wayland/gpu/wayland_overlay_manager_unittest.cc
@@ -0,0 +1,77 @@ +// 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 "ui/ozone/platform/wayland/gpu/wayland_overlay_manager.h" + +#include "base/bind.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/ozone/public/overlay_surface_candidate.h" + +namespace ui { +namespace { + +constexpr gfx::AcceleratedWidget kPrimaryWidget = 1; + +OverlaySurfaceCandidate CreateCandidate(const gfx::Rect& rect, + int plane_z_order) { + ui::OverlaySurfaceCandidate candidate; + candidate.transform = gfx::OVERLAY_TRANSFORM_NONE; + candidate.format = gfx::BufferFormat::YUV_420_BIPLANAR; + candidate.plane_z_order = plane_z_order; + candidate.buffer_size = rect.size(); + candidate.display_rect = gfx::RectF(rect); + candidate.crop_rect = gfx::RectF(rect); + return candidate; +} + +} // namespace + +TEST(WaylandOverlayManagerTest, MultipleOverlayCandidates) { + WaylandOverlayManager manager; + + std::vector<OverlaySurfaceCandidate> candidates = { + CreateCandidate(gfx::Rect(10, 10, 20, 20), -2), + CreateCandidate(gfx::Rect(30, 30, 10, 10), -1), + CreateCandidate(gfx::Rect(0, 0, 100, 100), 0), + CreateCandidate(gfx::Rect(40, 40, 20, 20), 1), + CreateCandidate(gfx::Rect(60, 60, 20, 20), 2)}; + + // Submit a set of candidates that could potentially be displayed in an + // overlay. All candidates should be marked as handled. + manager.CheckOverlaySupport(&candidates, kPrimaryWidget); + EXPECT_TRUE(candidates[0].overlay_handled); + EXPECT_TRUE(candidates[1].overlay_handled); + EXPECT_TRUE(candidates[2].overlay_handled); + EXPECT_TRUE(candidates[3].overlay_handled); + EXPECT_TRUE(candidates[4].overlay_handled); +} + +TEST(WaylandOverlayManagerTest, NonIntegerDisplayRect) { + WaylandOverlayManager manager; + + // Candidates for output surface and single-on-top quad. + std::vector<OverlaySurfaceCandidate> candidates = { + CreateCandidate(gfx::Rect(0, 0, 100, 100), 0), + CreateCandidate(gfx::Rect(10, 10, 20, 20), 1)}; + + // Submit a set of candidates that could potentially be displayed in an + // overlay. + manager.CheckOverlaySupport(&candidates, kPrimaryWidget); + EXPECT_TRUE(candidates[0].overlay_handled); + EXPECT_TRUE(candidates[1].overlay_handled); + + candidates[0].overlay_handled = false; + candidates[1].overlay_handled = false; + + // Modify the display_rect for the second candidate so it's non-integer. We + // will never try to promote this to an overlay. This verifies we don't try to + // convert the non-integer RectF into a Rect which DCHECKs. + candidates[1].display_rect = gfx::RectF(9.4, 10.43, 20.11, 20.99); + manager.CheckOverlaySupport(&candidates, kPrimaryWidget); + EXPECT_TRUE(candidates[0].overlay_handled); + EXPECT_FALSE(candidates[1].overlay_handled); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index a0331bb..defa1c9 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -35,8 +35,8 @@ #include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h" #include "ui/ozone/platform/wayland/test/wayland_test.h" #include "ui/ozone/public/platform_clipboard.h" -#include "ui/platform_window/platform_window_handler/wm_drag_handler.h" -#include "ui/platform_window/platform_window_handler/wm_drop_handler.h" +#include "ui/platform_window/handlers/wm_drag_handler.h" +#include "ui/platform_window/handlers/wm_drop_handler.h" #include "ui/platform_window/platform_window_init_properties.h" #include "url/gurl.h"
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc index 8590429..1f24f36 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -18,7 +18,7 @@ #include "ui/ozone/platform/wayland/host/wayland_data_drag_controller.h" #include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/host/wayland_window_drag_controller.h" -#include "ui/platform_window/platform_window_handler/wm_drop_handler.h" +#include "ui/platform_window/handlers/wm_drop_handler.h" namespace ui {
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h index 0eb0a83..980044f 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -8,9 +8,9 @@ #include "build/lacros_buildflags.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" -#include "ui/platform_window/platform_window_handler/wm_drag_handler.h" -#include "ui/platform_window/platform_window_handler/wm_move_loop_handler.h" -#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/platform_window/handlers/wm_drag_handler.h" +#include "ui/platform_window/handlers/wm_move_loop_handler.h" +#include "ui/platform_window/handlers/wm_move_resize_handler.h" namespace ui {
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc index 1a150c21..d6aa7c9 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -31,8 +31,8 @@ #include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h" #include "ui/ozone/platform/wayland/test/wayland_test.h" #include "ui/ozone/test/mock_platform_window_delegate.h" +#include "ui/platform_window/handlers/wm_move_loop_handler.h" #include "ui/platform_window/platform_window_delegate.h" -#include "ui/platform_window/platform_window_handler/wm_move_loop_handler.h" using testing::_; using testing::Mock;
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc index 91ed358d..745e2f8 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -30,7 +30,7 @@ #include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h" #include "ui/ozone/platform/wayland/test/wayland_test.h" #include "ui/ozone/test/mock_platform_window_delegate.h" -#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/platform_window/handlers/wm_move_resize_handler.h" #include "ui/platform_window/platform_window_init_properties.h" using ::testing::_;
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc index 67d59d4..1e78bc51 100644 --- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc +++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -21,10 +21,10 @@ #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" #include "ui/gfx/linux/client_native_pixmap_dmabuf.h" #include "ui/gfx/native_widget_types.h" -#include "ui/ozone/common/stub_overlay_manager.h" #include "ui/ozone/platform/wayland/common/wayland_util.h" #include "ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h" #include "ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h" +#include "ui/ozone/platform/wayland/gpu/wayland_overlay_manager.h" #include "ui/ozone/platform/wayland/gpu/wayland_surface_factory.h" #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_connector.h" #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h" @@ -79,6 +79,11 @@ .ignore_screen_bounds_for_menus = true, }; +constexpr OzonePlatform::InitializedHostProperties + kWaylandInitializedHostProperties = { + /*supports_overlays=*/false, +}; + class OzonePlatformWayland : public OzonePlatform { public: OzonePlatformWayland() { CHECK(features::IsUsingOzonePlatform()); } @@ -181,7 +186,6 @@ buffer_manager_connector_ = std::make_unique<WaylandBufferManagerConnector>( connection_->buffer_manager_host()); cursor_factory_ = std::make_unique<BitmapCursorFactoryOzone>(); - overlay_manager_ = std::make_unique<StubOverlayManager>(); input_controller_ = CreateStubInputController(); gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost()); @@ -199,6 +203,7 @@ buffer_manager_ = std::make_unique<WaylandBufferManagerGpu>(); surface_factory_ = std::make_unique<WaylandSurfaceFactory>( connection_.get(), buffer_manager_.get()); + overlay_manager_ = std::make_unique<WaylandOverlayManager>(); #if defined(WAYLAND_GBM) const base::FilePath drm_node_path = path_finder_.GetDrmRenderNodePath(); if (drm_node_path.empty()) { @@ -221,6 +226,10 @@ return kWaylandPlatformProperties; } + const InitializedHostProperties& GetInitializedHostProperties() override { + return kWaylandInitializedHostProperties; + } + void AddInterfaces(mojo::BinderMap* binders) override { binders->Add<ozone::mojom::WaylandBufferManagerGpu>( base::BindRepeating( @@ -243,7 +252,6 @@ std::unique_ptr<WaylandConnection> connection_; std::unique_ptr<WaylandSurfaceFactory> surface_factory_; std::unique_ptr<CursorFactory> cursor_factory_; - std::unique_ptr<StubOverlayManager> overlay_manager_; std::unique_ptr<InputController> input_controller_; std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_; std::unique_ptr<WaylandInputMethodContextFactory> @@ -252,6 +260,7 @@ // Objects, which solely live in the GPU process. std::unique_ptr<WaylandBufferManagerGpu> buffer_manager_; + std::unique_ptr<WaylandOverlayManager> overlay_manager_; // Provides supported buffer formats for native gpu memory buffers // framework.
diff --git a/ui/ozone/platform/x11/BUILD.gn b/ui/ozone/platform/x11/BUILD.gn index 3845ba0..4484522 100644 --- a/ui/ozone/platform/x11/BUILD.gn +++ b/ui/ozone/platform/x11/BUILD.gn
@@ -58,7 +58,7 @@ "//ui/ozone:ozone_base", "//ui/ozone/common", "//ui/platform_window", - "//ui/platform_window/platform_window_handler", + "//ui/platform_window/handlers", "//ui/platform_window/x11", ]
diff --git a/ui/platform_window/platform_window_handler/BUILD.gn b/ui/platform_window/handlers/BUILD.gn similarity index 93% rename from ui/platform_window/platform_window_handler/BUILD.gn rename to ui/platform_window/handlers/BUILD.gn index 85d99aa..d026dded 100644 --- a/ui/platform_window/platform_window_handler/BUILD.gn +++ b/ui/platform_window/handlers/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -component("platform_window_handler") { +component("handlers") { output_name = "platform_window_handler_libs" sources = [
diff --git a/ui/platform_window/platform_window_handler/DEPS b/ui/platform_window/handlers/DEPS similarity index 100% rename from ui/platform_window/platform_window_handler/DEPS rename to ui/platform_window/handlers/DEPS
diff --git a/ui/platform_window/platform_window_handler/wm_drag_handler.cc b/ui/platform_window/handlers/wm_drag_handler.cc similarity index 91% rename from ui/platform_window/platform_window_handler/wm_drag_handler.cc rename to ui/platform_window/handlers/wm_drag_handler.cc index 5dafa35..7d1b208 100644 --- a/ui/platform_window/platform_window_handler/wm_drag_handler.cc +++ b/ui/platform_window/handlers/wm_drag_handler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/platform_window/platform_window_handler/wm_drag_handler.h" +#include "ui/platform_window/handlers/wm_drag_handler.h" #include "ui/base/class_property.h" #include "ui/platform_window/platform_window.h"
diff --git a/ui/platform_window/platform_window_handler/wm_drag_handler.h b/ui/platform_window/handlers/wm_drag_handler.h similarity index 88% rename from ui/platform_window/platform_window_handler/wm_drag_handler.h rename to ui/platform_window/handlers/wm_drag_handler.h index c30acac..ff667a02 100644 --- a/ui/platform_window/platform_window_handler/wm_drag_handler.h +++ b/ui/platform_window/handlers/wm_drag_handler.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_ -#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_ +#ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_DRAG_HANDLER_H_ +#define UI_PLATFORM_WINDOW_HANDLERS_WM_DRAG_HANDLER_H_ #include "base/bind.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/native_widget_types.h" -#include "ui/platform_window/platform_window_handler/wm_platform_export.h" +#include "ui/platform_window/handlers/wm_platform_export.h" namespace ui { class PlatformWindow; @@ -64,4 +64,4 @@ } // namespace ui -#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_ +#endif // UI_PLATFORM_WINDOW_HANDLERS_WM_DRAG_HANDLER_H_
diff --git a/ui/platform_window/platform_window_handler/wm_drop_handler.cc b/ui/platform_window/handlers/wm_drop_handler.cc similarity index 90% rename from ui/platform_window/platform_window_handler/wm_drop_handler.cc rename to ui/platform_window/handlers/wm_drop_handler.cc index 64ff6bd..5a981c8 100644 --- a/ui/platform_window/platform_window_handler/wm_drop_handler.cc +++ b/ui/platform_window/handlers/wm_drop_handler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/platform_window/platform_window_handler/wm_drop_handler.h" +#include "ui/platform_window/handlers/wm_drop_handler.h" #include "ui/base/class_property.h" #include "ui/platform_window/platform_window.h"
diff --git a/ui/platform_window/platform_window_handler/wm_drop_handler.h b/ui/platform_window/handlers/wm_drop_handler.h similarity index 88% rename from ui/platform_window/platform_window_handler/wm_drop_handler.h rename to ui/platform_window/handlers/wm_drop_handler.h index 98b0583e..9a00a68 100644 --- a/ui/platform_window/platform_window_handler/wm_drop_handler.h +++ b/ui/platform_window/handlers/wm_drop_handler.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DROP_HANDLER_H_ -#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DROP_HANDLER_H_ +#ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_DROP_HANDLER_H_ +#define UI_PLATFORM_WINDOW_HANDLERS_WM_DROP_HANDLER_H_ #include <memory> #include "ui/gfx/native_widget_types.h" -#include "ui/platform_window/platform_window_handler/wm_platform_export.h" +#include "ui/platform_window/handlers/wm_platform_export.h" namespace gfx { class PointF; @@ -61,4 +61,4 @@ } // namespace ui -#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DROP_HANDLER_H_ +#endif // UI_PLATFORM_WINDOW_HANDLERS_WM_DROP_HANDLER_H_
diff --git a/ui/platform_window/platform_window_handler/wm_move_loop_handler.cc b/ui/platform_window/handlers/wm_move_loop_handler.cc similarity index 90% rename from ui/platform_window/platform_window_handler/wm_move_loop_handler.cc rename to ui/platform_window/handlers/wm_move_loop_handler.cc index 94192b3e..07ec6477 100644 --- a/ui/platform_window/platform_window_handler/wm_move_loop_handler.cc +++ b/ui/platform_window/handlers/wm_move_loop_handler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/platform_window/platform_window_handler/wm_move_loop_handler.h" +#include "ui/platform_window/handlers/wm_move_loop_handler.h" #include "ui/base/class_property.h" #include "ui/platform_window/platform_window.h"
diff --git a/ui/platform_window/platform_window_handler/wm_move_loop_handler.h b/ui/platform_window/handlers/wm_move_loop_handler.h similarity index 75% rename from ui/platform_window/platform_window_handler/wm_move_loop_handler.h rename to ui/platform_window/handlers/wm_move_loop_handler.h index 98b1fc40..49b2d2f 100644 --- a/ui/platform_window/platform_window_handler/wm_move_loop_handler.h +++ b/ui/platform_window/handlers/wm_move_loop_handler.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_LOOP_HANDLER_H_ -#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_LOOP_HANDLER_H_ +#ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_LOOP_HANDLER_H_ +#define UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_LOOP_HANDLER_H_ -#include "ui/platform_window/platform_window_handler/wm_platform_export.h" +#include "ui/platform_window/handlers/wm_platform_export.h" namespace gfx { class Vector2d; @@ -36,4 +36,4 @@ } // namespace ui -#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_LOOP_HANDLER_H_ +#endif // UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_LOOP_HANDLER_H_
diff --git a/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc b/ui/platform_window/handlers/wm_move_resize_handler.cc similarity index 91% rename from ui/platform_window/platform_window_handler/wm_move_resize_handler.cc rename to ui/platform_window/handlers/wm_move_resize_handler.cc index a79ad70a..5faa080 100644 --- a/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc +++ b/ui/platform_window/handlers/wm_move_resize_handler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/platform_window/handlers/wm_move_resize_handler.h" #include "ui/base/class_property.h" #include "ui/platform_window/platform_window.h"
diff --git a/ui/platform_window/platform_window_handler/wm_move_resize_handler.h b/ui/platform_window/handlers/wm_move_resize_handler.h similarity index 88% rename from ui/platform_window/platform_window_handler/wm_move_resize_handler.h rename to ui/platform_window/handlers/wm_move_resize_handler.h index ac30160..dd40e58 100644 --- a/ui/platform_window/platform_window_handler/wm_move_resize_handler.h +++ b/ui/platform_window/handlers/wm_move_resize_handler.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_ -#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_ +#ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_RESIZE_HANDLER_H_ +#define UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_RESIZE_HANDLER_H_ -#include "ui/platform_window/platform_window_handler/wm_platform_export.h" +#include "ui/platform_window/handlers/wm_platform_export.h" namespace gfx { class Point; @@ -60,4 +60,4 @@ } // namespace ui -#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_ +#endif // UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_RESIZE_HANDLER_H_
diff --git a/ui/platform_window/platform_window_handler/wm_platform_export.h b/ui/platform_window/handlers/wm_platform_export.h similarity index 78% rename from ui/platform_window/platform_window_handler/wm_platform_export.h rename to ui/platform_window/handlers/wm_platform_export.h index 37165fb7..26b560d 100644 --- a/ui/platform_window/platform_window_handler/wm_platform_export.h +++ b/ui/platform_window/handlers/wm_platform_export.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_ -#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_ +#ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_PLATFORM_EXPORT_H_ +#define UI_PLATFORM_WINDOW_HANDLERS_WM_PLATFORM_EXPORT_H_ // Defines WM_PLATFORM_EXPORT so that functionality implemented by the // wm_platform module can be exported to consumers. @@ -29,4 +29,4 @@ #define WM_PLATFORM_EXPORT #endif -#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_ +#endif // UI_PLATFORM_WINDOW_HANDLERS_WM_PLATFORM_EXPORT_H_
diff --git a/ui/platform_window/x11/BUILD.gn b/ui/platform_window/x11/BUILD.gn index 7ec3088..1fdb8c6 100644 --- a/ui/platform_window/x11/BUILD.gn +++ b/ui/platform_window/x11/BUILD.gn
@@ -25,7 +25,7 @@ "//ui/platform_window", "//ui/platform_window/common", "//ui/platform_window/extensions", - "//ui/platform_window/platform_window_handler", + "//ui/platform_window/handlers", ] defines = [ "X11_WINDOW_IMPLEMENTATION" ]
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc index 6723d41..a1d56f5 100644 --- a/ui/platform_window/x11/x11_window.cc +++ b/ui/platform_window/x11/x11_window.cc
@@ -28,7 +28,7 @@ #include "ui/platform_window/common/platform_window_defaults.h" #include "ui/platform_window/extensions/workspace_extension_delegate.h" #include "ui/platform_window/extensions/x11_extension_delegate.h" -#include "ui/platform_window/platform_window_handler/wm_drop_handler.h" +#include "ui/platform_window/handlers/wm_drop_handler.h" #include "ui/platform_window/x11/x11_topmost_window_finder.h" #include "ui/platform_window/x11/x11_window_manager.h"
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h index 581befa..a479792 100644 --- a/ui/platform_window/x11/x11_window.h +++ b/ui/platform_window/x11/x11_window.h
@@ -14,10 +14,10 @@ #include "ui/gfx/x/event.h" #include "ui/platform_window/extensions/workspace_extension.h" #include "ui/platform_window/extensions/x11_extension.h" +#include "ui/platform_window/handlers/wm_drag_handler.h" +#include "ui/platform_window/handlers/wm_move_loop_handler.h" +#include "ui/platform_window/handlers/wm_move_resize_handler.h" #include "ui/platform_window/platform_window.h" -#include "ui/platform_window/platform_window_handler/wm_drag_handler.h" -#include "ui/platform_window/platform_window_handler/wm_move_loop_handler.h" -#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" #include "ui/platform_window/platform_window_init_properties.h" #include "ui/platform_window/x11/x11_window_export.h"
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 0ee43ea..c647a24 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -724,7 +724,7 @@ "//ui/aura", "//ui/events", "//ui/platform_window", - "//ui/platform_window/platform_window_handler", + "//ui/platform_window/handlers", "//ui/touch_selection", "//ui/wm", "//ui/wm/public", @@ -1164,7 +1164,7 @@ "//ui/gl:test_support", "//ui/native_theme", "//ui/native_theme:test_support", - "//ui/platform_window/platform_window_handler", + "//ui/platform_window/handlers", "//ui/resources", "//ui/resources:ui_test_pak", "//ui/strings", @@ -1380,7 +1380,7 @@ deps += [ "//ui/events/platform", "//ui/platform_window", - "//ui/platform_window/platform_window_handler", + "//ui/platform_window/handlers", ] }
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h index ad8c8568..413f86b 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
@@ -15,8 +15,8 @@ #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/native_widget_types.h" -#include "ui/platform_window/platform_window_handler/wm_drag_handler.h" -#include "ui/platform_window/platform_window_handler/wm_drop_handler.h" +#include "ui/platform_window/handlers/wm_drag_handler.h" +#include "ui/platform_window/handlers/wm_drop_handler.h" #include "ui/views/views_export.h" namespace aura {
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc index a23b5cb..522d3c5 100644 --- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc +++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
@@ -14,9 +14,9 @@ #include "ui/aura/window_tree_host.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h" #include "ui/base/dragdrop/os_exchange_data.h" +#include "ui/platform_window/handlers/wm_drag_handler.h" +#include "ui/platform_window/handlers/wm_drop_handler.h" #include "ui/platform_window/platform_window.h" -#include "ui/platform_window/platform_window_handler/wm_drag_handler.h" -#include "ui/platform_window/platform_window_handler/wm_drop_handler.h" #include "ui/views/test/views_test_base.h" #include "ui/views/views_delegate.h" #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc index 21f52d8..d8ee9bd 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
@@ -19,7 +19,7 @@ #include "ui/display/screen.h" #include "ui/events/event.h" #include "ui/platform_window/extensions/x11_extension.h" -#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/platform_window/handlers/wm_move_resize_handler.h" #include "ui/platform_window/platform_window_init_properties.h" #include "ui/views/linux_ui/linux_ui.h" #include "ui/views/views_delegate.h"
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc index b07ab9d..1fc52c6 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux_interactive_uitest.cc
@@ -7,8 +7,8 @@ #include "ui/aura/client/aura_constants.h" #include "ui/aura/window_tree_host_platform.h" #include "ui/base/hit_test.h" +#include "ui/platform_window/handlers/wm_move_resize_handler.h" #include "ui/platform_window/platform_window.h" -#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" #include "ui/views/widget/desktop_aura/window_event_filter_linux.h"
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc index f9a4343..c5737541 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -21,8 +21,8 @@ #include "ui/display/screen.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/platform_window/extensions/workspace_extension.h" +#include "ui/platform_window/handlers/wm_move_loop_handler.h" #include "ui/platform_window/platform_window.h" -#include "ui/platform_window/platform_window_handler/wm_move_loop_handler.h" #include "ui/platform_window/platform_window_init_properties.h" #include "ui/views/corewm/tooltip_aura.h" #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h"
diff --git a/ui/views/widget/desktop_aura/window_event_filter_linux.cc b/ui/views/widget/desktop_aura/window_event_filter_linux.cc index 915fa77..90557d2 100644 --- a/ui/views/widget/desktop_aura/window_event_filter_linux.cc +++ b/ui/views/widget/desktop_aura/window_event_filter_linux.cc
@@ -14,7 +14,7 @@ #include "ui/display/screen.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" -#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/platform_window/handlers/wm_move_resize_handler.h" #include "ui/views/linux_ui/linux_ui.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h" #include "ui/views/widget/native_widget_aura.h"
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html index 4f4c0b0..a3fb220 100644 --- a/ui/webui/resources/cr_elements/shared_vars_css.html +++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -155,16 +155,6 @@ --cr-section-indent-padding: calc( var(--cr-section-padding) + var(--cr-section-indent-width)); - /* TODO(crbug.com/973674): Do not use this mixin. Use the class cr-row - * from shared_style_css.html instead. */ - --cr-section: { - align-items: center; - border-top: var(--cr-separator-line); - display: flex; - min-height: var(--cr-section-min-height); - padding: 0 var(--cr-section-padding); - } - --cr-section-vertical-margin: 21px; --cr-centered-card-max-width: 680px;
diff --git a/ui/wm/core/shadow_controller.cc b/ui/wm/core/shadow_controller.cc index 395257e3..6b6712ca 100644 --- a/ui/wm/core/shadow_controller.cc +++ b/ui/wm/core/shadow_controller.cc
@@ -264,7 +264,7 @@ if (shadow) { shadow->SetElevation(GetShadowElevationForActiveState(window)); shadow->layer()->SetVisible(should_show); - } else if (should_show && !shadow) { + } else if (should_show) { CreateShadowForWindow(window); } }
diff --git a/weblayer/browser/android/javatests/skew/mb_config.pyl b/weblayer/browser/android/javatests/skew/mb_config.pyl index 726ef6f..8e4311f 100644 --- a/weblayer/browser/android/javatests/skew/mb_config.pyl +++ b/weblayer/browser/android/javatests/skew/mb_config.pyl
@@ -65,9 +65,10 @@ 'release': { 'gn_args': 'is_debug=false', }, - + # TODO(rmhasan): Add back GOMA support when you can start the goma proxy + # in a recipe. 'release_bot': { - 'mixins': ['release', 'static', 'goma'], + 'mixins': ['release', 'static'], }, 'static': {